]> icculus.org git repositories - btb/d2x.git/blob - main/old/winferno.c
This commit was manufactured by cvs2svn to create branch
[btb/d2x.git] / main / old / winferno.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: winferno.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
17 #pragma on (unreferenced)
18
19 #include "desw.h"
20 #include <mmsystem.h>
21
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 #include "gr.h"
26 #include "gamepal.h"
27 #include "palette.h"
28 #include "key.h"
29 #include "mono.h"
30 #include "timer.h"
31 #include "3d.h"
32 #include "bm.h"
33 #include "inferno.h"
34 #include "error.h"
35 #include "game.h"
36 #include "mem.h"
37 #include "screens.h"
38 #include "texmap.h"
39 #include "texmerge.h"
40 #include "menu.h"
41 #include "polyobj.h"
42 #include "pcx.h"
43 #include "args.h"
44 #include "player.h"
45 #include "text.h"
46 #include "gamefont.h"
47 #include "kconfig.h"
48 #include "newmenu.h"
49 #include "desc_id.h"
50 #include "config.h"
51 #include "cfile.h"
52 #include "mission.h"
53 #include "network.h"
54 #include "newdemo.h"
55 #include "digi.h"
56 #include "songs.h"
57 #include "ipx.h"
58 #include "modem.h"
59 #include "joy.h"
60 #include "movie.h"
61
62 #ifdef _3DFX
63 #include "3dfx_des.h"
64 #endif
65
66
67
68 //      Globals --------------------------------------------------------------------
69 extern int Network_allow_socket_changes;
70 extern char gr_palette[3*256];
71 extern int grd_fades_disabled;
72 extern int MenuHiresAvailable;
73 extern int piggy_low_memory;
74
75 int Function_mode=FMODE_MENU;           //game or editor?
76 int Screen_mode=-1;                                     //game screen or editor screen?
77 int descent_critical_error = 0;
78 unsigned descent_critical_deverror = 0;
79 unsigned descent_critical_errcode = 0;
80
81 /// CHANGE THIS.  PUT THIS WHERE IT SHOULD ME.
82
83 int WVIDEO_running=1;           //debugger can set to 1 if running
84
85
86 //      Version ID Info. -----------------------------------------------------------
87
88 #include "vers_id.h"
89
90 //Current version number
91
92 ubyte Version_major = 1;                //FULL VERSION
93 ubyte Version_minor = 2;
94
95 int registered_copy=0;
96 char name_copy[DESC_ID_LEN];
97
98 static const char desc_id_checksum_str[] = DESC_ID_CHKSUM_TAG "0000";   //4-byte checksum
99 char desc_id_exit_num = 0;
100 time_t t_current_time, t_saved_time;
101
102 byte CybermouseActive = 0;
103
104 static  char    title_pal[768];
105
106
107 //      THIS IS A HACK UNTIL WE HAVE MOVIES
108 int MovieHires = 1;
109 char CDROM_dir[30] = "";
110 int Hogfile_on_CD = 0;
111
112
113 // Function Prototypes --------------------------------------------------------
114 int init_cdrom();
115 int InitGraphics(void);
116 void DisplayDescentTitle(void);
117 void TestSounds();
118 void check_joystick_calibration();
119
120 void check_id_checksum_and_date();
121
122 HANDLE clipboard_renderformat(int cf);
123 HPALETTE SetPalette(HDC hdc, HPALETTE hPal);
124 void DestroyPalette(HPALETTE hPal);
125
126 #define HOGNAME "descent2.hog"
127
128 extern int CD_audio_desktop_dev;
129 extern DWORD CD_audio_desktop_vol;
130
131
132 //      Functions ------------------------------------------------------------------
133
134 void InitCD(char *arg)
135 {
136         int i;
137
138         logentry("Initializing CD-ROM...\n");
139
140         if (!init_cdrom()) {            //look for Cd, etc.
141                 #ifdef RELEASE
142                         Error("Sorry, the Descent II CD must be present to run.");
143                 #endif
144         }
145         else {          //check to make sure not running off CD
146 //              if (toupper(arg[0]) == toupper(CDROM_dir[0]))
147 //                      Error("You cannot run Descent II directly from your CD-ROM drive.\n"
148 //                                      "       To run Descent II, CD to the directory you installed to, then type D2.\n"
149 //                                      "       To install Descent II, type %c:\\INSTALL.",toupper(CDROM_dir[0]));
150         }
151
152 //      Let's save the current volume of CD-audio-out
153 //      Find CD-AUDIO device if there is one.
154         for (i = 0; i < auxGetNumDevs(); i++)
155         {
156                 AUXCAPS caps;
157                 auxGetDevCaps(i, &caps, sizeof(caps));
158                 if (caps.wTechnology == AUXCAPS_CDAUDIO) {
159                         CD_audio_desktop_dev = i;
160                         mprintf((0, "CD audio operating on AUX %d.\n", CD_audio_desktop_dev));
161                         break;
162                 }
163         }
164                                         
165         if (CD_audio_desktop_dev != -1) {
166         //       get the volume! 
167                 auxGetVolume(CD_audio_desktop_dev, &CD_audio_desktop_vol);
168                 mprintf((1, "CD vol: 0x%x\n", CD_audio_desktop_vol));
169         }
170 }
171
172
173 void InitVideo()
174 {
175         int flag;
176
177         logentry("Initializing Video System...\n");
178
179         if (FindArg("-hw_3dacc")) flag = 1;
180         else flag = 0;
181
182         if (!gfxInit(flag)) 
183                 Error("Unable to initialize GFX system.");
184
185 //@@   #ifdef _3DFX
186 //@@   _3dfx_available = _3dfx_Init();
187 //@@   #endif
188 }
189
190 void InitIO()
191 {
192         logentry("Initializing IO System...\n");
193
194         key_init();
195
196         if (!win95_controls_init()) 
197                 logentry("\tUnable to detect an auxillary control.\n");
198         mouse_set_window (_hAppWnd);
199         mouse_set_mode(0);                              // Non-centering mode
200 }
201
202
203 void InitData()
204 {
205         logentry("Initializing Data...\n");
206
207         ReadConfigFile();
208
209         if (! cfile_init(HOGNAME)) {            //didn't find HOG.  Check on CD
210                 #ifdef RELEASE
211                         Error("Could not find required file <%s>",HOGNAME);
212                 #endif
213         }
214
215         load_text();
216
217 //print out the banner title
218 #ifndef RELEASE
219         cprintf("\nDESCENT II %s v%d.%d",VERSION_TYPE,Version_major,Version_minor);
220         #ifdef VERSION_NAME
221         cprintf("  %s", VERSION_NAME);
222         #endif
223         cprintf("  %s %s\n", __DATE__,__TIME__);
224         cprintf("%s\n%s\n",TXT_COPYRIGHT,TXT_TRADEMARK);        
225         cprintf("\n\n");
226 #endif
227
228         check_id_checksum_and_date();
229 }
230
231
232 void InitSound()
233 {
234         logentry("Initializing Sound System...\n");
235
236         if (digi_init()) {
237                 logentry("Unable to initialize sound system.\n");
238         }
239 }
240
241
242 void InitNetwork()
243 {
244         int socket=0, showaddress=0;
245         int ipx_error;
246         int t;
247
248         logentry("Initializing Networking system...\n");
249
250         if ((t=FindArg("-socket")))
251                 socket = atoi( Args[t+1] );
252                 
253         if ( FindArg("-showaddress") ) showaddress=1;
254                 
255         if ((ipx_error=ipx_init(IPX_DEFAULT_SOCKET+socket,showaddress))==0)     {
256                 mprintf((0, "IPX protocol on channel %x.\n", IPX_DEFAULT_SOCKET+socket ));
257                 Network_active = 1;
258         } 
259         else {
260                 switch( ipx_error )     {
261                         case 3:         mprintf((1, "%s\n", TXT_NO_NETWORK)); break;
262                         case -2: mprintf((1, "%s 0x%x.\n", TXT_SOCKET_ERROR, IPX_DEFAULT_SOCKET+socket)); break;
263                         case -4: mprintf((1, "%s\n", TXT_MEMORY_IPX )); break;
264                         default:
265                                 mprintf((1, "\t%s %d\n", TXT_ERROR_IPX, ipx_error ));
266                 }
267                         
268                 logentry("%s\n",TXT_NETWORK_DISABLED);
269                 Network_active = 0;             // Assume no network
270         }
271                 
272         mprintf((0, "Here?"));
273
274         ipx_read_user_file( "descent.usr" );
275         ipx_read_network_file( "descent.net" );
276 }
277
278
279 void InitDescent()
280 {
281         Lighting_on = 1;                                                        //      Turn on lighting for now.
282
283 //      Set Display Mode
284         
285         if (!dd_VR_offscreen_buffer)    
286                 set_display_mode(0);                                    
287
288 //      Create and Set Initial Palette.
289         logentry("Initializing palette system...\n" );
290         gr_use_palette_table(DEFAULT_PALETTE);
291         gr_palette_load(gr_palette);
292
293         logentry( "Initializing font system...\n" );
294         gamefont_init();
295
296         if (FindArg("-lowresmovies")) 
297                 MovieHires = 0;
298
299         MenuHires = MenuHiresAvailable = 1;
300
301 //      Set up movies and title
302         logentry("Initializing movie libraries...\n" );
303         init_movies();          //init movie libraries
304
305         if (!init_subtitles("intro.tex")) 
306                 mprintf((1, "Unable to open subtitles.\n"));
307         PlayMovie("intro.mve",MOVIE_ABORT_ON);
308         HideCursorW();
309
310         close_subtitles();
311         songs_play_song( SONG_TITLE, 1);
312
313         FontHires = MenuHires;
314
315         //LoadCursorWin(MOUSE_WAIT_CURSOR);
316
317         DEFINE_SCREEN("DESCENTB.PCX");
318         DisplayDescentTitle();  
319
320 //      SendMessage(_hAppWnd, WM_SETREDRAW, FALSE, 0);
321
322 //      Doing some 3d initialization
323         logentry( "Doing bm_init...\n" );
324         bm_init();
325
326         DDGRRESTORE
327
328         logentry( "Initializing 3d system...\n" );
329         g3_init();
330
331         logentry( "Initializing texture caching system...\n" );
332         texmerge_init( 10 );            // 10 cache bitmaps
333
334         logentry("Final initialization...\n" );
335
336         memcpy(gr_palette,title_pal,sizeof(gr_palette));
337
338         set_screen_mode(SCREEN_MENU);
339
340         init_game();
341
342         set_detail_level_parameters(Detail_level);
343         
344 //      SendMessage(_hAppWnd, WM_SETREDRAW, TRUE, 0);
345         //LoadCursorWin(MOUSE_DEFAULT_CURSOR);
346 }
347
348
349 void InitPilot()
350 {
351 //      Title Page gone, now start main program
352 //      Players[Player_num].callsign[0] = '\0';
353
354         do_register_player(title_pal);
355
356         gr_palette_fade_out( title_pal, 32, 0 );
357
358         //check for special stamped version
359         if (registered_copy) {
360                 char time_str[32];      
361                 char time_str2[32];
362                 
363                 _ctime(&t_saved_time, time_str);
364                 _ctime(&t_current_time, time_str2);
365
366                 nm_messagebox("EVALUATION COPY",1,"Continue",
367                         "This special evaluation copy\n"
368                         "of DESCENT II has been issued to:\n\n"
369                         "%s\n"
370                         "\nEXPIRES %s\nYOUR TIME: %s\nNOT FOR DISTRIBUTION",
371                         name_copy, time_str,time_str2);
372
373                 gr_palette_fade_out( gr_palette, 32, 0 );
374         }
375
376         Game_mode = GM_GAME_OVER;
377 }
378
379
380 //      Winferno Internal Routines
381
382 void DisplayDescentTitle(void)
383 {
384 //      Create Descent Title Window and Load Title bitmap, and display it.
385         int                     pcx_error;
386         int                     width, height;
387
388         logentry("Displaying title...\n");
389
390 //      Display Title Bitmap, using title palette.
391         pcx_error = pcx_get_dimensions("DESCENTB.PCX", &width, &height);        
392         if (pcx_error != PCX_ERROR_NONE)        {
393                 gr_close();
394                 Error( "Couldn't load pcx file 'DESCENTB.PCX', PCX load error: %s\n", pcx_errormsg(pcx_error));
395         }
396
397 //      pcx_canvas = dd_gr_create_canvas(width, height );
398
399         gr_palette_clear();
400
401         dd_gr_set_current_canvas(NULL);
402         DDGRLOCK(dd_grd_curcanv)
403         {
404                 pcx_error=pcx_read_bitmap( "DESCENTB.PCX", &grd_curcanv->cv_bitmap, 
405                                 grd_curcanv->cv_bitmap.bm_type, 
406                                 title_pal );
407         }
408         DDGRUNLOCK(dd_grd_curcanv)
409
410         if (pcx_error == PCX_ERROR_NONE)        {
411         //      Blt to screen, then restore display
412                 DDGRRESTORE;
413                 gr_palette_fade_in( title_pal, 32, 0 );
414         } else {
415                 gr_close();
416                 Error( "Couldn't load pcx file 'DESCENT.PCX', PCX load error: %s\n", pcx_errormsg(pcx_error));
417         }
418 }
419
420
421 do_register_player(ubyte *title_pal)
422 {
423         Players[Player_num].callsign[0] = '\0';
424
425         if (!Auto_demo)         {
426
427                 key_flush();
428
429                 memcpy(gr_palette,title_pal,sizeof(gr_palette));
430                 remap_fonts_and_menus(1);
431                 RegisterPlayer();               //get player's name
432         }
433 }
434
435
436 //@@void check_joystick_calibration()   
437 //@@{
438 //@@    int x1, y1, x2, y2, c;
439 //@@    fix t1;
440 //@@
441 //@@    if ( (Config_control_type!=CONTROL_JOYSTICK) &&
442 //@@              (Config_control_type!=CONTROL_FLIGHTSTICK_PRO) &&
443 //@@              (Config_control_type!=CONTROL_THRUSTMASTER_FCS) &&
444 //@@              (Config_control_type!=CONTROL_GRAVIS_GAMEPAD)
445 //@@            ) return;
446 //@@
447 //@@    joy_get_pos( &x1, &y1 );
448 //@@
449 //@@    t1 = timer_get_fixed_seconds();
450 //@@    while( timer_get_fixed_seconds() < t1 + F1_0/100 )
451 //@@            ;
452 //@@
453 //@@    joy_get_pos( &x2, &y2 );
454 //@@
455 //@@    // If joystick hasn't moved...
456 //@@    if ( (abs(x2-x1)<30) &&  (abs(y2-y1)<30) )      {
457 //@@            if ( (abs(x1)>30) || (abs(x2)>30) ||  (abs(y1)>30) || (abs(y2)>30) )    {
458 //@@                    c = nm_messagebox( NULL, 2, TXT_CALIBRATE, TXT_SKIP, TXT_JOYSTICK_NOT_CEN );
459 //@@                    if ( c==0 )     {
460 //@@                            joydefs_calibrate();
461 //@@                    }
462 //@@            }
463 //@@    }
464 //@@
465 //@@}
466
467
468 int find_descent_cd()
469 {
470         char path[4];
471         char oldpath[MAX_PATH];
472         char volume[256];
473         int i;
474         int cdrom_drive=-1;
475
476         path[1] = ':';
477         path[2] = '\\';
478         path[3] = 0;
479
480         GetCurrentDirectory(MAX_PATH, oldpath);
481
482         for (i = 0; i < 26; i++) 
483         {
484                 path[0] = 'A'+i;
485                 if (GetDriveType(path) == DRIVE_CDROM) {
486                         cdrom_drive = -3;
487                         GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0);
488                         mprintf((0, "CD volume: %s\n", volume));
489                         if (!strcmpi(volume, "DESCENT_II") || !strcmpi(volume, "DESCENT.II")) {
490                                 if (!chdir(path)) 
491                                         if (!chdir("\\d2data")) {
492                                                 cdrom_drive = i;
493                                                 break;
494                                         }
495                         }
496                 }
497         }
498
499         SetCurrentDirectory(oldpath);
500         return cdrom_drive;
501 }
502
503
504 int init_cdrom()
505 {
506         int i;
507
508         //scan for CD, etc.
509
510         i = find_descent_cd();
511
512         if (i < 0) {                    //no CD
513
514                 #ifndef RELEASE
515                 if ((i=FindArg("-cdproxy")) != 0) {
516                         strcpy(CDROM_dir,"d:\\d2data\\");       //set directory
517                         CDROM_dir[0] = Args[i+1][0];
518                         return 1;
519                 }
520                 #endif
521
522                 return 0;
523         }
524         else {
525                 strcpy(CDROM_dir,"d:\\d2data\\");       //set directory
526                 CDROM_dir[0] = 'A'+i;                                   //set correct drive leter
527                 mprintf((0, "Descent 2 CD-ROM: %s\n", CDROM_dir));
528                 return 1;
529         }
530 }
531
532
533 //      ----------------------------------------------------------------------------
534
535 void
536 check_id_checksum_and_date()
537 {
538         const char name[sizeof(DESC_ID_TAG)-1+DESC_ID_LEN] = DESC_ID_TAG;
539         char time_str[] = DESC_DEAD_TIME_TAG "00000000";        //second part gets overwritten
540         int i, found;
541         unsigned long *checksum, test_checksum;
542         time_t current_time, saved_time;
543
544         saved_time = (time_t)strtol(time_str + strlen(DESC_DEAD_TIME_TAG), NULL, 16);
545         
546         t_saved_time = saved_time;
547
548         if (saved_time == (time_t)0)
549                 return;
550
551         mprintf((1, "TIME STAMPED: %d\n", saved_time));
552
553         strcpy(name_copy,name+strlen(DESC_ID_TAG));
554         registered_copy = 1;
555
556         t_current_time = current_time = time(NULL);
557
558         mprintf((1, "CURTIME: %d\n", current_time));
559
560         if (current_time >= saved_time)
561                 desc_id_exit_num = 1;
562
563         test_checksum = 0;
564         for (i = 0; i < strlen(name_copy); i++) {
565                 found = 0;        
566                 test_checksum += name_copy[i];
567                 if (((test_checksum / 2) * 2) != test_checksum)
568                         found = 1;
569                 test_checksum = test_checksum >> 1;
570                 if (found)
571                         test_checksum |= 0x80000000;
572         }
573         checksum = (unsigned long *)(desc_id_checksum_str + strlen(DESC_ID_CHKSUM_TAG));
574         if (test_checksum != *checksum)
575                 desc_id_exit_num = 2;
576
577         cprintf ("%s %s\n", TXT_REGISTRATION, name_copy);
578 }
579
580
581 //      ----------------------------------------------------------------------------
582 //      Nifty clipboard functions for placing a screen shot
583 //      ----------------------------------------------------------------------------
584
585 extern HANDLE win95_dib_from_bitmap(HBITMAP hbm);
586
587 void win95_save_pcx_shot()
588 {
589         char message[100];
590         static int savenum = 0;
591         fix t1;
592
593         dd_grs_canvas *screen_canv = dd_grd_screencanv;
594         dd_grs_canvas *temp_canv_1, *save_canv;         //*temp_canv_2, 
595         grs_font *save_font;
596         ubyte pal[768];
597         
598         char savename[FILENAME_LEN];    //NO STEREO savename2[FILENAME_LEN];
599         
600         int w,h,aw,x,y;
601
602         stop_time();
603
604         mprintf((0, "Screen shot!\n"));
605
606 /* Start */
607         save_canv = dd_grd_curcanv;
608         temp_canv_1 = dd_gr_create_canvas(screen_canv->canvas.cv_bitmap.bm_w,
609                                                                                                          screen_canv->canvas.cv_bitmap.bm_h);
610                 
611         dd_gr_blt_notrans(screen_canv, 0, 0, 0, 0, temp_canv_1, 0, 0, 0, 0);
612
613 /* Saved screen shot */
614         dd_gr_set_current_canvas(save_canv);
615
616         if ( savenum > 99 ) savenum = 0;
617         sprintf(savename,"screen%02d.pcx",savenum++);
618         sprintf( message, "%s '%s'", TXT_DUMPING_SCREEN, savename );
619
620         dd_gr_set_current_canvas(NULL);
621
622         DDGRLOCK(dd_grd_curcanv);
623         {
624                 save_font = grd_curcanv->cv_font;
625                 gr_set_curfont(GAME_FONT);
626                 gr_set_fontcolor(gr_find_closest_color_current(0,31,0),-1);
627                 gr_get_string_size(message,&w,&h,&aw);
628
629                 x = (grd_curcanv->cv_w-w)/2;
630                 y = (grd_curcanv->cv_h-h)/2;
631
632                 gr_setcolor(gr_find_closest_color_current(0,0,0));
633                 gr_rect(x-2,y-2,x+w+2,y+h+2);
634                 gr_printf(x,y,message);
635                 gr_set_curfont(save_font);
636         }
637         DDGRUNLOCK(dd_grd_curcanv);
638
639         if (GRMODEINFO(modex)) dd_gr_flip();
640
641         t1 = timer_get_fixed_seconds() + F1_0;
642
643         gr_palette_read(pal);           //get actual palette from the hardware
644
645         DDGRLOCK(temp_canv_1);
646                 pcx_write_bitmap(savename,&temp_canv_1->canvas.cv_bitmap,pal);
647         DDGRUNLOCK(temp_canv_1);
648
649         while ( timer_get_fixed_seconds() < t1 );               // Wait so that messag stays up at least 1 second.
650
651         dd_gr_set_current_canvas(screen_canv);
652
653         dd_gr_blt_notrans(temp_canv_1, 0,0,0,0, dd_grd_curcanv, 0,0,0,0);
654
655         if (GRMODEINFO(modex)) dd_gr_flip();
656
657         dd_gr_free_canvas(temp_canv_1);
658
659         dd_gr_set_current_canvas(save_canv);
660
661         key_flush();
662         start_time();
663 }
664
665
666 HANDLE hClipData = NULL;
667
668 BOOL clipboard_screenshot()
669 {
670         if (OpenClipboard(_hAppWnd)) {
671                 EmptyClipboard();
672                 SetClipboardData (CF_DIB     ,clipboard_renderformat(CF_DIB)); 
673                 SetClipboardData (CF_BITMAP  ,clipboard_renderformat(CF_BITMAP)); 
674                 SetClipboardData (CF_PALETTE ,clipboard_renderformat(CF_PALETTE)); 
675                 CloseClipboard (); 
676                 return TRUE;
677         }
678         else return FALSE;
679 }
680
681  
682 HANDLE clipboard_renderformat(int cf)
683 {
684         HANDLE hMem = NULL;
685         HBITMAP hbm;
686
687         switch(cf)
688         {
689                 case CF_BITMAP:
690                 {
691                 // Create screen shot BBM
692                         mprintf((1, "Creating DDB for clipboard.\n"));
693                         hMem = win95_screen_shot();
694                         if (!hMem) mprintf((1, "Unable to create clipboard object: CF_BITMAP\n"));
695                         break;
696                 }
697                 
698                 case CF_DIB:
699                 {
700                 // Create DIB and all memory associated with it.
701                         mprintf((1, "Creating DIB for clipboard.\n"));
702                         hbm = win95_screen_shot();
703                         hMem = win95_dib_from_bitmap(hbm);
704                         if (!hMem) mprintf((1, "Unable to create clipboard object: CF_DIB\n"));
705                         DeleteObject(hbm);
706                         break;
707                 }
708                 
709                 case CF_PALETTE:
710                 {
711                 //       Get current palette! (create a GDI palette from grpal)
712                         PALETTE lpal;
713                         char grpal[768];
714                         int i;
715  
716                         mprintf((1, "Creating Palette for clipboard.\n"));
717                         gr_palette_read(grpal);
718                         lpal.version = 0x300;
719                         lpal.num_entries = 256;
720                         for (i = 0; i < 256; i++) 
721                         {
722                                 lpal.entries[i].peRed = grpal[i*3] << 2;
723                                 lpal.entries[i].peGreen = grpal[i*3+1] << 2;
724                                 lpal.entries[i].peBlue = grpal[i*3+2] << 2;
725                                 lpal.entries[i].peFlags = 0;
726                         }                               
727
728                         hMem = CreatePalette((LOGPALETTE*)&lpal);
729                         if (!hMem) mprintf((1, "Unable to create clipboard object: CF_PALETTE\n"));
730                         break;
731                 }
732         }
733                 
734         return hMem;
735 }
736