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