2 * $Logfile: /Freespace2/code/Graphics/GrSoft.cpp $
7 * Code for our software renderer using standard Win32 functions. (Dibsections, etc)
10 * Revision 1.7 2002/06/05 08:05:29 relnev
11 * stub/warning removal.
13 * reworked the sound code.
15 * Revision 1.6 2002/05/28 21:36:10 relnev
16 * some more timer junk.
18 * tried to fix software mode.
20 * Revision 1.5 2002/05/28 17:26:57 theoddone33
21 * Fill in some timer and palette setting stubs. Still no display
23 * Revision 1.4 2002/05/28 17:03:29 theoddone33
24 * fs2 gets to the main game loop now
26 * Revision 1.3 2002/05/28 04:56:51 theoddone33
27 * runs a little bit now
29 * Revision 1.2 2002/05/28 04:07:28 theoddone33
30 * New graphics stubbing arrangement
32 * Revision 1.1.1.1 2002/05/03 03:28:09 root
36 * 12 7/14/99 9:42a Dave
37 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
40 * 11 7/09/99 9:51a Dave
41 * Added thick polyline code.
43 * 10 6/29/99 10:35a Dave
44 * Interface polygon bitmaps! Whee!
46 * 9 2/03/99 11:44a Dave
47 * Fixed d3d transparent textures.
49 * 8 1/24/99 11:37p Dave
50 * First full rev of beam weapons. Very customizable. Removed some bogus
51 * Int3()'s in low level net code.
53 * 7 12/18/98 1:13a Dave
54 * Rough 1024x768 support for Direct3D. Proper detection and usage through
57 * 6 12/06/98 2:36p Dave
58 * Drastically improved nebula fogging.
60 * 5 11/30/98 5:31p Dave
61 * Fixed up Fred support for software mode.
63 * 4 11/30/98 1:07p Dave
64 * 16 bit conversion, first run.
66 * 3 11/11/98 5:37p Dave
67 * Checkin for multiplayer testing.
69 * 2 10/07/98 10:53a Dave
72 * 1 10/07/98 10:49a Dave
74 * 84 5/20/98 9:46p John
75 * added code so the places in code that change half the palette don't
76 * have to clear the screen.
78 * 83 5/18/98 11:17a John
79 * Fixed some bugs with software window and output window.
81 * 82 5/17/98 5:03p John
82 * Fixed some bugs that make the taskbar interfere with the DEBUG-only
85 * 81 5/15/98 2:44p John
86 * Made windowed mode not touch the window if no handle to window found.
88 * 80 5/14/98 5:42p John
89 * Revamped the whole window position/mouse code for the graphics windows.
91 * 79 5/07/98 6:58p Hoffoss
92 * Made changes to mouse code to fix a number of problems.
94 * 78 5/06/98 5:30p John
95 * Removed unused cfilearchiver. Removed/replaced some unused/little used
96 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
97 * DirectX header files and libs that fixed the Direct3D alpha blending
100 * 77 4/23/98 8:24a John
101 * Changed the way palette effect works so that:
102 * 1. If gr_flash isn't called this frame, screen shows no flash.
103 * 2. With hardware, only 3d portion of screen gets flashed.
105 * 76 4/21/98 5:22p John
106 * Fixed all the &^#@$ cursor bugs with popups. For Glide, had problem
107 * with mouse restoring assuming back buffer was same buffer last frame,
108 * for software, problems with half drawn new frames, then mouse got
109 * restored on top of that with old data.
111 * 75 4/14/98 12:15p John
112 * Made 16-bpp movies work.
114 * 74 4/11/98 12:48p John
115 * Made software fade out actually clear screen to black.
117 * 73 4/01/98 9:21p John
118 * Made NDEBUG, optimized build with no warnings or errors.
120 * 72 3/25/98 8:07p John
121 * Restructured software rendering into two modules; One for windowed
122 * debug mode and one for DirectX fullscreen.
124 * 71 3/24/98 3:58p John
125 * Put in (hopefully) final gamma setting code.
127 * 70 3/17/98 5:55p John
128 * Added code to dump Glide frames. Moved Allender's "hack" code out of
129 * Freespace.cpp into the proper place, graphics lib.
131 * 69 3/14/98 5:46p John
133 * 68 3/14/98 5:43p John
134 * Saved area under mouse cursor. Made save_Screen restore it so no mouse
135 * is on those screens.
137 * 67 3/12/98 8:50a John
138 * took out "allocating zbuffer" mprintf
140 * 66 3/10/98 4:18p John
141 * Cleaned up graphics lib. Took out most unused gr functions. Made D3D
142 * & Glide have popups and print screen. Took out all >8bpp software
143 * support. Made Fred zbuffer. Made zbuffer allocate dynamically to
144 * support Fred. Made zbuffering key off of functions rather than one
147 * 65 3/06/98 4:09p John
148 * Changed the way we do bitmap RLE'ing... this speds up HUD bitmaps by
151 * 64 3/05/98 4:28p John
152 * Made mouse cursor hide while setting palette.
154 * 63 3/02/98 5:42p John
155 * Removed WinAVI stuff from Freespace. Made all HUD gauges wriggle from
156 * afterburner. Made gr_set_clip work good with negative x &y. Made
157 * model_caching be on by default. Made each cached model have it's own
158 * bitmap id. Made asteroids not rotate when model_caching is on.
160 * 62 2/24/98 3:50p John
161 * Made Alt+Tabbing work with Glide. Made Int3's restore Glide screen on
164 * 61 2/24/98 1:59p John
165 * Made gr_aabitmap_ex clip properly
167 * 60 2/05/98 9:21p John
168 * Some new Direct3D code. Added code to monitor a ton of stuff in the
171 * 59 1/19/98 6:15p John
172 * Fixed all my Optimized Build compiler warnings
174 * 58 1/15/98 4:07p John
175 * added grx_set_palette_internal which doesn't clear the screen and flip
176 * before setting the palette.
178 * 57 1/15/98 4:02p John
179 * Fixed stupid bug on my part where I called graphics rendering functions
180 * from another thread!!! Duh! Fixed it by setting a variable and then
181 * resetting the palette at the next flip.
183 * 56 1/08/98 5:06p John
184 * Replaced Int3 with a mprintf
186 * 55 1/08/98 3:10p John
187 * Undid my palette changes for interplay rev
189 * 54 1/08/98 3:03p John
191 * 53 1/05/98 11:52a Jasen
192 * JAS: Made graphics code work if os_get_window returns NULL when trying
195 * 52 12/30/97 6:47p John
196 * Made fade time correct
198 * 51 12/30/97 6:46p John
199 * Added first rev of palette fade in out functions
201 * 50 12/21/97 4:33p John
202 * Made debug console functions a class that registers itself
203 * automatically, so you don't need to add the function to
204 * debugfunctions.cpp.
206 * 49 12/05/97 4:26p John
207 * made palette set code be like it was before.
209 * 48 12/04/97 8:05p John
210 * added test code to brighten palette
212 * 47 12/03/97 2:16p John
213 * Took out blur code and fake_vram buffer.
215 * 46 12/02/97 4:00p John
216 * Added first rev of thruster glow, along with variable levels of
217 * translucency, which retquired some restructing of palman.
219 * 45 11/30/97 12:18p John
220 * added more 24 & 32-bpp primitives
222 * 44 11/29/97 2:06p John
223 * added mode 16-bpp support
225 * 43 11/21/97 11:32a John
226 * Added nebulas. Fixed some warpout bugs.
228 * 42 11/20/97 9:51a John
229 * added code to force screen to 16-bit even if rendering 8.
231 * 41 11/17/97 10:33a John
232 * updated force_windowed code.
234 * 40 11/14/97 3:54p John
235 * Added triple buffering.
237 * 39 11/14/97 3:08p Johnson
238 * fixed bug with fred.
240 * 38 11/14/97 12:30p John
241 * Fixed some DirectX bugs. Moved the 8-16 xlat tables into Graphics
242 * libs. Made 16-bpp DirectX modes know what bitmap format they're in.
244 * 37 11/06/97 4:12p John
245 * Took out debug code that returned NULL for DD.
247 * 36 11/05/97 12:35p John
248 * added correct gr_bitmap_ex that does clipping
251 * 35 10/31/97 9:43a John
252 * fixed red background color bug.
254 * 34 10/19/97 1:53p John
255 * hacked in a fix to a zbuffer error caused by inaccuracies.
257 * 33 10/19/97 12:55p John
258 * new code to lock / unlock surfaces for smooth directx integration.
260 * 32 10/15/97 4:48p John
261 * added 16-bpp aascaler
263 * 31 10/14/97 4:50p John
266 * 30 10/14/97 8:08a John
267 * added a bunch more 16 bit support
269 * 29 10/09/97 5:23p John
270 * Added support for more 16-bpp functions
272 * 28 10/03/97 9:10a John
273 * added better antialiased line drawer
275 * 27 9/23/97 11:50a Lawrance
276 * jas: added xparency to rle'd bitblts
278 * 26 9/23/97 10:45a John
279 * made so you can tell bitblt code to rle a bitmap by passing flag to
282 * 25 9/20/97 10:48a John
283 * added motion blur code.
285 * 24 9/09/97 10:39a Sandeep
286 * fixed warning level 4
288 * 23 9/07/97 2:34p John
289 * fixed bug with fullscreen toggling not working when in > 8bpp mode.
291 * 22 9/03/97 4:32p John
292 * changed bmpman to only accept ani and pcx's. made passing .pcx or .ani
293 * to bm_load functions not needed. Made bmpman keep track of palettes
294 * for bitmaps not mapped into game palettes.
296 * 21 8/26/97 11:30a John
297 * removed call to restoredisplymode when going from fullscreen to
298 * windowed, which hopefully fixes the screwey taskbar problem.
300 * 20 8/04/97 4:47p John
303 * 19 7/17/97 9:31a John
304 * made all directX header files name start with a v
306 * 18 7/10/97 2:06p John
307 * added code to specify alphablending type for bitmaps.
309 * 17 6/20/97 1:50p John
310 * added rle code to bmpman. made gr8_aabitmap use it.
312 * 16 6/17/97 12:03p John
313 * Moved color/alphacolor functions into their own module. Made all color
314 * functions be part of the low-level graphics drivers, not just the
317 * 15 6/13/97 5:35p John
318 * added some antialiased bitmaps and lines
320 * 14 6/12/97 2:50a Lawrance
321 * bm_unlock() now passed bitmap number, not pointer
323 * 13 6/11/97 5:49p John
324 * Changed palette code to only recalculate alphacolors when needed, not
325 * when palette changes.
327 * 12 6/11/97 1:12p John
328 * Started fixing all the text colors in the game.
330 * 11 6/06/97 5:03p John
331 * fixed bug withalpha colors failing after gr_init
333 * 10 6/06/97 4:41p John
334 * Fixed alpha colors to be smoothly integrated into gr_set_color_fast
337 * 9 5/29/97 3:09p John
338 * Took out debug menu.
339 * Made software scaler draw larger bitmaps.
340 * Optimized Direct3D some.
342 * 8 5/16/97 9:11a John
343 * fixed bug that made Ctrl+Break in fullscreen hang
345 * 7 5/14/97 4:40p John
348 * 6 5/14/97 4:38p John
349 * Fixed print_screen bug.
351 * 5 5/14/97 2:09p John
352 * made fullscreen use 254 palette entries. Used
353 * CreateCompatibleDC(NULL) Instead of GetDC(HWND_DESKTOP) because the
354 * GetDC method fails when you change screen depth dynamically under NT.
356 * 4 5/14/97 10:53a John
357 * fixed some discrepencies between d3d and software palette setting.
359 * 3 5/14/97 8:53a John
360 * Fixed a palette bug when switching into/outof d3d mode.
362 * 2 5/13/97 12:39p John
363 * Got fullscreen mode working.
365 * 1 5/12/97 12:14p John
373 #include <windowsx.h>
380 #include "floating.h"
383 #include "grinternal.h"
385 // Headers for 2d functions
393 #include "gradient.h"
394 #include "pcxutils.h"
404 // This structure is the same as LOGPALETTE except that LOGPALETTE
405 // requires you to malloc out space for the palette, which just isn't
406 // worth the trouble.
409 SDL_Surface *soft_surface;
416 PALETTEENTRY palPalEntry[256];
419 // This structure is the same as BITMAPINFO except that BITMAPINFO
420 // requires you to malloc out space for the palette, which just isn't
421 // worth the trouble. I also went ahead and threw a handy union to
422 // easily reference the hicolor masks in 15/16 bpp modes.
424 BITMAPINFOHEADER Header;
426 RGBQUAD aColors[256];
427 ushort PalIndex[256];
428 uint hicolor_masks[3];
432 EZ_BITMAPINFO DibInfo;
433 HBITMAP hDibSection = NULL;
434 HBITMAP hOldBitmap = NULL;
436 void *lpDibBits=NULL;
438 HPALETTE hOldPalette=NULL, hPalette = NULL;
441 int Gr_soft_inited = 0;
443 static volatile int Grsoft_activated = 1; // If set, that means application got focus, so reset palette
445 void gr_buffer_release()
450 SelectPalette( hDibDC, hOldPalette, FALSE );
451 if (!DeleteObject(hPalette)) {
452 mprintf(( "JOHN: Couldn't delete palette object\n" ));
458 SelectObject(hDibDC, hOldBitmap );
464 DeleteObject(hDibSection);
471 void gr_buffer_create( int w, int h, int bpp )
474 Int3(); // w must be multiple 4
481 memset( &DibInfo, 0, sizeof(EZ_BITMAPINFO));
482 DibInfo.Header.biSize = sizeof(BITMAPINFOHEADER);
483 DibInfo.Header.biWidth = w;
484 DibInfo.Header.biHeight = h;
485 DibInfo.Header.biPlanes = 1;
486 DibInfo.Header.biClrUsed = 0;
494 Gr_red.mask = 0xff0000;
499 Gr_green.mask = 0xff00;
507 DibInfo.Header.biCompression = BI_RGB;
508 DibInfo.Header.biBitCount = 8;
509 for (int i=0; i<256; i++ ) {
510 DibInfo.Colors.aColors[i].rgbRed = 0;
511 DibInfo.Colors.aColors[i].rgbGreen = 0;
512 DibInfo.Colors.aColors[i].rgbBlue = 0;
513 DibInfo.Colors.aColors[i].rgbReserved = 0;
522 Gr_red.mask = 0x7C00;
527 Gr_green.mask = 0x3E0;
535 DibInfo.Header.biCompression = BI_BITFIELDS;
536 DibInfo.Header.biBitCount = 16;
537 DibInfo.Colors.hicolor_masks[0] = Gr_red.mask;
538 DibInfo.Colors.hicolor_masks[1] = Gr_green.mask;
539 DibInfo.Colors.hicolor_masks[2] = Gr_blue.mask;
549 Gr_red.mask = 0xF800;
554 Gr_green.mask = 0x7E0;
562 DibInfo.Header.biCompression = BI_BITFIELDS;
563 DibInfo.Header.biBitCount = 16;
564 DibInfo.Colors.hicolor_masks[0] = Gr_red.mask;
565 DibInfo.Colors.hicolor_masks[1] = Gr_green.mask;
566 DibInfo.Colors.hicolor_masks[2] = Gr_blue.mask;
575 Gr_red.mask = 0xff0000;
580 Gr_green.mask = 0xff00;
588 DibInfo.Header.biCompression = BI_RGB;
589 DibInfo.Header.biBitCount = unsigned short(bpp);
594 Int3(); // Illegal bpp
600 hDibDC = CreateCompatibleDC(NULL);
601 hDibSection = CreateDIBSection(hDibDC,(BITMAPINFO *)&DibInfo,DIB_RGB_COLORS,&lpDibBits,NULL,NULL);
602 hOldBitmap = (HBITMAP)SelectObject(hDibDC, hDibSection );
604 if ( hDibSection == NULL ) {
605 Int3(); // couldn't allocate dib section
611 // This makes a best-fit palette from the 256 target colors and
612 // the system colors which should look better than only using the
613 // colors in the range 10-246, but it will totally reorder the palette.
614 // All colors get changed in target_palette.
618 HPALETTE gr_create_palette_0(ubyte * target_palette)
620 EZ_LOGPALETTE LogicalPalette;
622 HPALETTE hpal,hpalOld;
623 PALETTEENTRY pe[256];
624 int NumSysColors, NumColors;
627 // Create a 1-1 mapping of the system palette
628 LogicalPalette.palVersion = 0x300;
629 LogicalPalette.palNumEntries = 256;
631 // Pack in all the colors
632 for (i=0;i<256; i++) {
633 LogicalPalette.palPalEntry[i].peRed = target_palette[i*3+0];
634 LogicalPalette.palPalEntry[i].peGreen = target_palette[i*3+1];
635 LogicalPalette.palPalEntry[i].peBlue = target_palette[i*3+2];
636 LogicalPalette.palPalEntry[i].peFlags = 0; //PC_EXPLICIT;
639 hpal = CreatePalette( (LOGPALETTE *)&LogicalPalette );
641 ScreenDC = CreateCompatibleDC(NULL);
643 if ( !(GetDeviceCaps(ScreenDC,RASTERCAPS) & RC_PALETTE) ) {
648 NumSysColors = GetDeviceCaps( ScreenDC, NUMCOLORS );
649 NumColors = GetDeviceCaps( ScreenDC, SIZEPALETTE );
651 // Reset all the Palette Manager tables
652 SetSystemPaletteUse( ScreenDC, SYSPAL_NOSTATIC );
653 SetSystemPaletteUse( ScreenDC, SYSPAL_STATIC );
655 // Enter our palette's values into the free slots
656 hpalOld=SelectPalette( ScreenDC, hpal, FALSE );
657 RealizePalette( ScreenDC );
658 SelectPalette( ScreenDC, hpalOld, FALSE );
660 GetSystemPaletteEntries(ScreenDC,0,NumColors,pe);
662 for (i=0; i<NumSysColors/2; i++ ) {
665 for (; i<NumColors - NumSysColors/2; i++ ) {
666 pe[i].peFlags = PC_NOCOLLAPSE;
668 for (; i<NumColors; i++ ) {
671 ResizePalette( hpal, NumColors);
672 SetPaletteEntries( hpal, 0, NumColors, pe );
674 for (i=0; i<256; i++ ) {
675 target_palette[i*3+0] = pe[i].peRed;
676 target_palette[i*3+1] = pe[i].peGreen;
677 target_palette[i*3+2] = pe[i].peBlue;
685 HPALETTE gr_create_palette_256( ubyte * target_palette )
687 EZ_LOGPALETTE LogicalPalette;
690 // Pack in all the colors
691 for (i=0;i<256; i++) {
692 LogicalPalette.palPalEntry[i].peRed = target_palette[i*3+0];
693 LogicalPalette.palPalEntry[i].peGreen = target_palette[i*3+1];
694 LogicalPalette.palPalEntry[i].peBlue = target_palette[i*3+2];
695 LogicalPalette.palPalEntry[i].peFlags = 0; //PC_RESERVED; //PC_EXPLICIT;
698 // Create a 1-1 mapping of the system palette
699 LogicalPalette.palVersion = 0x300;
700 LogicalPalette.palNumEntries = 256;
702 return CreatePalette( (LOGPALETTE *)&LogicalPalette );
705 // This makes an indentity logical palette that saves entries 10-246
706 // and leaves them in place. Colors 0-9 and 246-255 get changed in
707 // target_palette. trash_flag tells us whether to trash the system palette
709 HPALETTE gr_create_palette_236( ubyte * target_palette )
711 EZ_LOGPALETTE LogicalPalette;
713 int NumSysColors, NumColors, UserLowest, UserHighest;
716 // Pack in all the colors
717 for (i=0;i<256; i++) {
718 LogicalPalette.palPalEntry[i].peRed = target_palette[i*3+0];
719 LogicalPalette.palPalEntry[i].peGreen = target_palette[i*3+1];
720 LogicalPalette.palPalEntry[i].peBlue = target_palette[i*3+2];
721 LogicalPalette.palPalEntry[i].peFlags = 0; //PC_EXPLICIT;
724 // Create a 1-1 mapping of the system palette
725 LogicalPalette.palVersion = 0x300;
726 LogicalPalette.palNumEntries = 256;
728 ScreenDC = CreateCompatibleDC(NULL);
730 // Reset all the Palette Manager tables
731 SetSystemPaletteUse( ScreenDC, SYSPAL_NOSTATIC );
732 SetSystemPaletteUse( ScreenDC, SYSPAL_STATIC );
734 if ( !(GetDeviceCaps(ScreenDC,RASTERCAPS) & RC_PALETTE) ) {
736 return CreatePalette( (LOGPALETTE *)&LogicalPalette );
739 NumSysColors = GetDeviceCaps( ScreenDC, NUMCOLORS );
740 NumColors = GetDeviceCaps( ScreenDC, SIZEPALETTE );
742 Assert( NumColors <= 256 );
744 UserLowest = NumSysColors/2; // 10 normally
745 UserHighest = NumColors - NumSysColors/2 - 1; // 245 normally
747 Assert( (UserHighest - UserLowest + 1) >= 236 );
749 GetSystemPaletteEntries(ScreenDC,0,NumSysColors/2,LogicalPalette.palPalEntry);
750 GetSystemPaletteEntries(ScreenDC,UserHighest+1,NumSysColors/2,LogicalPalette.palPalEntry+1+UserHighest);
754 for (i=0; i<256; i++ ) {
756 if ( (i >= UserLowest) && (i<=UserHighest) ) {
757 LogicalPalette.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
759 LogicalPalette.palPalEntry[i].peFlags = 0;
761 target_palette[i*3+0] = LogicalPalette.palPalEntry[i].peRed;
762 target_palette[i*3+1] = LogicalPalette.palPalEntry[i].peGreen;
763 target_palette[i*3+2] = LogicalPalette.palPalEntry[i].peBlue;
766 return CreatePalette( (LOGPALETTE *)&LogicalPalette );
769 HPALETTE gr_create_palette_254( ubyte * target_palette )
771 EZ_LOGPALETTE LogicalPalette;
773 int NumSysColors, NumColors, UserLowest, UserHighest;
776 // Pack in all the colors
777 for (i=0;i<256; i++) {
778 LogicalPalette.palPalEntry[i].peRed = target_palette[i*3+0];
779 LogicalPalette.palPalEntry[i].peGreen = target_palette[i*3+1];
780 LogicalPalette.palPalEntry[i].peBlue = target_palette[i*3+2];
781 LogicalPalette.palPalEntry[i].peFlags = 0; //PC_EXPLICIT;
784 // Create a 1-1 mapping of the system palette
785 LogicalPalette.palVersion = 0x300;
786 LogicalPalette.palNumEntries = 256;
788 ScreenDC = CreateCompatibleDC(NULL);
790 // Reset all the Palette Manager tables
791 SetSystemPaletteUse( ScreenDC, SYSPAL_NOSTATIC );
792 SetSystemPaletteUse( ScreenDC, SYSPAL_STATIC );
794 if ( !(GetDeviceCaps(ScreenDC,RASTERCAPS) & RC_PALETTE) ) {
796 return CreatePalette( (LOGPALETTE *)&LogicalPalette );
799 SetSystemPaletteUse( ScreenDC, SYSPAL_NOSTATIC );
801 NumColors = GetDeviceCaps( ScreenDC, SIZEPALETTE );
803 Assert( NumColors <= 256 );
805 UserLowest = NumSysColors/2; // 10 normally
806 UserHighest = NumColors - NumSysColors/2 - 1; // 245 normally
808 Assert( (UserHighest - UserLowest + 1) >= 236 );
810 GetSystemPaletteEntries(ScreenDC,0,NumSysColors/2,LogicalPalette.palPalEntry);
811 GetSystemPaletteEntries(ScreenDC,UserHighest+1,NumSysColors/2,LogicalPalette.palPalEntry+1+UserHighest);
815 for (i=0; i<256; i++ ) {
817 if ( (i >= UserLowest) && (i<=UserHighest) ) {
818 LogicalPalette.palPalEntry[i].peFlags = PC_NOCOLLAPSE;
820 LogicalPalette.palPalEntry[i].peFlags = 0;
822 target_palette[i*3+0] = LogicalPalette.palPalEntry[i].peRed;
823 target_palette[i*3+1] = LogicalPalette.palPalEntry[i].peGreen;
824 target_palette[i*3+2] = LogicalPalette.palPalEntry[i].peBlue;
827 return CreatePalette( (LOGPALETTE *)&LogicalPalette );
831 void grx_set_palette_internal( ubyte * new_pal )
834 SDL_Color colors[256];
838 SelectPalette( hDibDC, hOldPalette, FALSE );
839 if (!DeleteObject(hPalette)) {
840 mprintf(( "JOHN: Couldn't delete palette object\n" ));
847 // Make sure color 0 is black
848 if ( (new_pal[0]!=0) || (new_pal[1]!=0) || (new_pal[2]!=0) ) {
849 // color 0 isn't black!! switch it!
851 int black_index = -1;
853 for (i=1; i<256; i++ ) {
854 if ( (new_pal[i*3+0]==0) && (new_pal[i*3+1]==0) && (new_pal[i*3+2]==0) ) {
859 if ( black_index > -1 ) {
860 // swap black and color 0, so color 0 is black
862 tmp[0] = new_pal[black_index*3+0];
863 tmp[1] = new_pal[black_index*3+1];
864 tmp[2] = new_pal[black_index*3+2];
866 new_pal[black_index*3+0] = new_pal[0];
867 new_pal[black_index*3+1] = new_pal[1];
868 new_pal[black_index*3+2] = new_pal[2];
874 // no black in palette, force color 0 to be black.
883 if ( gr_screen.bits_per_pixel==8 ) {
885 // Name n_preserved One-one Speed Windowed?
886 // -------------------------------------------------------------------
887 // gr_create_palette_256 256 0-255 Slow Yes
888 // gr_create_palette_254 254 1-254 Fast No
889 // gr_create_palette_236 236 10-245 Fast Yes
890 // gr_create_palette_0 0 none Fast Yes
895 if ( n_preserved <= 0 ) {
896 hPalette = gr_create_palette_0(new_pal); // No colors mapped one-to-one, but probably has close to all 256 colors in it somewhere.
897 } else if ( n_preserved <= 236 ) {
898 hPalette = gr_create_palette_236(new_pal); // All colors except low 10 and high 10 mapped one-to-one
899 } else if ( n_preserved <= 254 ) {
900 hPalette = gr_create_palette_254(new_pal); // All colors except 0 and 255 mapped one-to-one, but changes system colors. Not pretty in a window.
904 for (int i = 0; i < 256; i++)
906 colors[i].r = new_pal[i*3+0];
907 colors[i].g = new_pal[i*3+1];
908 colors[i].b = new_pal[i*3+2];
910 SDL_SetColors (soft_surface, colors, 0, 256);
913 hPalette = gr_create_palette_256(new_pal); // All 256 mapped one-to-one, but BLT's are slow.
917 for (i=0; i<256; i++ ) {
918 DibInfo.Colors.aColors[i].rgbRed = new_pal[i*3+0];
919 DibInfo.Colors.aColors[i].rgbGreen = new_pal[i*3+1];
920 DibInfo.Colors.aColors[i].rgbBlue = new_pal[i*3+2];
921 DibInfo.Colors.aColors[i].rgbReserved = 0;
924 hOldPalette = SelectPalette( hDibDC, hPalette, FALSE );
925 SetDIBColorTable( hDibDC, 0, 256, DibInfo.Colors.aColors );
935 void grx_set_palette( ubyte * new_pal, int is_alphacolor )
944 grx_set_palette_internal(new_pal);
954 grx_set_palette_internal(new_pal);
959 void grx_print_screen(char * filename)
962 ubyte **row_data = (ubyte **)malloc( gr_screen.max_h * sizeof(ubyte *) );
964 mprintf(( "couldn't allocate enough memory to dump screen\n" ));
970 for (i=0; i<gr_screen.max_h; i++ ) {
971 row_data[i] = GR_SCREEN_PTR(ubyte,0,i);
974 pcx_write_bitmap( filename, gr_screen.max_w, gr_screen.max_h, row_data, Gr_current_palette );
987 void gr_soft_unlock()
992 void grx_set_palette_internal( ubyte * new_pal );
994 int Grx_mouse_saved = 0;
995 int Grx_mouse_saved_x1 = 0;
996 int Grx_mouse_saved_y1 = 0;
997 int Grx_mouse_saved_x2 = 0;
998 int Grx_mouse_saved_y2 = 0;
999 int Grx_mouse_saved_w = 0;
1000 int Grx_mouse_saved_h = 0;
1001 #define MAX_SAVE_SIZE (32*32)
1002 ubyte Grx_mouse_saved_data[MAX_SAVE_SIZE];
1004 // Clamps X between R1 and R2
1005 #define CLAMP(x,r1,r2) do { if ( (x) < (r1) ) (x) = (r1); else if ((x) > (r2)) (x) = (r2); } while(0)
1007 void grx_save_mouse_area(int x, int y, int w, int h )
1009 Grx_mouse_saved_x1 = x;
1010 Grx_mouse_saved_y1 = y;
1011 Grx_mouse_saved_x2 = x+w-1;
1012 Grx_mouse_saved_y2 = y+h-1;
1014 CLAMP(Grx_mouse_saved_x1, gr_screen.clip_left, gr_screen.clip_right );
1015 CLAMP(Grx_mouse_saved_x2, gr_screen.clip_left, gr_screen.clip_right );
1016 CLAMP(Grx_mouse_saved_y1, gr_screen.clip_top, gr_screen.clip_bottom );
1017 CLAMP(Grx_mouse_saved_y2, gr_screen.clip_top, gr_screen.clip_bottom );
1019 Grx_mouse_saved_w = Grx_mouse_saved_x2 - Grx_mouse_saved_x1 + 1;
1020 Grx_mouse_saved_h = Grx_mouse_saved_y2 - Grx_mouse_saved_y1 + 1;
1022 if ( Grx_mouse_saved_w < 1 ) return;
1023 if ( Grx_mouse_saved_h < 1 ) return;
1025 // Make sure we're not saving too much!
1026 Assert( (Grx_mouse_saved_w*Grx_mouse_saved_h) <= MAX_SAVE_SIZE );
1028 Grx_mouse_saved = 1;
1034 dptr = Grx_mouse_saved_data;
1036 for (int i=0; i<Grx_mouse_saved_h; i++ ) {
1037 sptr = GR_SCREEN_PTR(ubyte,Grx_mouse_saved_x1,Grx_mouse_saved_y1+i);
1039 for(int j=0; j<Grx_mouse_saved_w; j++ ) {
1048 void grx_restore_mouse_area()
1050 if ( !Grx_mouse_saved ) {
1058 sptr = Grx_mouse_saved_data;
1060 for (int i=0; i<Grx_mouse_saved_h; i++ ) {
1061 dptr = GR_SCREEN_PTR(ubyte,Grx_mouse_saved_x1,Grx_mouse_saved_y1+i);
1063 for(int j=0; j<Grx_mouse_saved_w; j++ ) {
1072 void gr_soft_activate(int active)
1081 static int Palette_flashed = 0;
1082 static int Palette_flashed_last_frame = 0;
1084 void grx_change_palette( ubyte *pal );
1088 if ( (!Palette_flashed) && (Palette_flashed_last_frame) ) {
1090 grx_change_palette( gr_palette );
1093 Palette_flashed_last_frame = Palette_flashed;
1094 Palette_flashed = 0;
1096 // If program reactivated, flip set new palette.
1097 // We do the cnt temporary variable because Grsoft_activated
1098 // can be set during interrupts.
1100 int cnt = Grsoft_activated;
1102 Grsoft_activated -= cnt;
1105 memcpy( new_pal, gr_palette, 768 );
1106 grx_set_palette_internal( new_pal ); // Call internal one so it doesn't clear screen and call flip
1113 // for (i=0; i<gr_screen.max_h; i++ ) {
1114 // memset( gr_screen.row_data[i], i & 255, abs(gr_screen.rowsize) );
1120 Grx_mouse_saved = 0; // assume not saved
1122 mouse_eval_deltas();
1123 if ( mouse_is_visible() ) {
1125 mouse_get_pos( &mx, &my );
1126 grx_save_mouse_area(mx,my,32,32);
1127 if ( Gr_cursor == -1 ) {
1128 gr_set_color(255,255,255);
1129 gr_line( mx, my, mx+7, my + 7 );
1130 gr_line( mx, my, mx+5, my );
1131 gr_line( mx, my, mx, my+5 );
1133 gr_set_bitmap(Gr_cursor);
1134 gr_bitmap( mx, my );
1141 int x = gr_screen.offset_x;
1142 int y = gr_screen.offset_y;
1143 int w = gr_screen.clip_width;
1144 int h = gr_screen.clip_height;
1146 t1 = timer_get_fixed_seconds();
1148 SDL_UpdateRect (soft_surface, x, y, w, h);
1150 t2 = timer_get_fixed_seconds();
1152 t = (w*h*gr_screen.bytes_per_pixel)/1024;
1154 HWND hwnd = (HWND)os_get_window();
1157 int x = gr_screen.offset_x;
1158 int y = gr_screen.offset_y;
1159 int w = gr_screen.clip_width;
1160 int h = gr_screen.clip_height;
1162 HPALETTE hOldPalette = NULL;
1163 HDC hdc = GetDC(hwnd);
1166 t1 = timer_get_fixed_seconds();
1169 hOldPalette=SelectPalette(hdc,hPalette, FALSE );
1170 uint nColors = RealizePalette( hdc );
1172 //if (nColors) mprintf(( "Actually set %d palette colors.\n", nColors ));
1176 BitBlt(hdc,0,h/2,w,h/2,hDibDC,x,y+h/2,SRCCOPY);
1178 BitBlt(hdc,0,0,w,h,hDibDC,x,y,SRCCOPY);
1182 SelectPalette(hdc,hOldPalette, FALSE );
1184 ReleaseDC( hwnd, hdc );
1186 t2 = timer_get_fixed_seconds();
1188 t = (w*h*gr_screen.bytes_per_pixel)/1024;
1189 //mprintf(( "%d MB/s\n", fixmuldiv(t,65,d) ));
1195 if ( Grx_mouse_saved ) {
1196 grx_restore_mouse_area();
1201 // switch onscreen, offscreen
1202 // Set msg to 0 if calling outside of the window handler.
1203 void grx_flip_window(uint _hdc, int x, int y, int w, int h )
1208 HDC hdc = (HDC)_hdc;
1209 HPALETTE hOldPalette = NULL;
1213 hOldPalette=SelectPalette(hdc,hPalette, FALSE );
1214 RealizePalette( hdc );
1217 min_w = gr_screen.clip_width;
1218 if ( w < min_w ) min_w = w;
1220 min_h = gr_screen.clip_height;
1221 if ( h < min_h ) min_h = h;
1223 BitBlt(hdc,x,y,min_w,min_h,hDibDC,gr_screen.offset_x,gr_screen.offset_y,SRCCOPY);
1225 //StretchBlt( hdc, 0, 0, w, h, hDibDC, 0, 0, 640, 480, SRCCOPY );
1228 SelectPalette(hdc,hOldPalette, FALSE );
1234 // sets the clipping region & offset
1235 void grx_set_clip(int x,int y,int w,int h)
1237 gr_screen.offset_x = x;
1238 gr_screen.offset_y = y;
1240 gr_screen.clip_left = 0;
1241 gr_screen.clip_right = w-1;
1243 gr_screen.clip_top = 0;
1244 gr_screen.clip_bottom = h-1;
1246 // check for sanity of parameters
1247 if ( gr_screen.clip_left+x < 0 ) {
1248 gr_screen.clip_left = -x;
1249 } else if ( gr_screen.clip_left+x > gr_screen.max_w-1 ) {
1250 gr_screen.clip_left = gr_screen.max_w-1-x;
1252 if ( gr_screen.clip_right+x < 0 ) {
1253 gr_screen.clip_right = -x;
1254 } else if ( gr_screen.clip_right+x >= gr_screen.max_w-1 ) {
1255 gr_screen.clip_right = gr_screen.max_w-1-x;
1258 if ( gr_screen.clip_top+y < 0 ) {
1259 gr_screen.clip_top = -y;
1260 } else if ( gr_screen.clip_top+y > gr_screen.max_h-1 ) {
1261 gr_screen.clip_top = gr_screen.max_h-1-y;
1264 if ( gr_screen.clip_bottom+y < 0 ) {
1265 gr_screen.clip_bottom = -y;
1266 } else if ( gr_screen.clip_bottom+y > gr_screen.max_h-1 ) {
1267 gr_screen.clip_bottom = gr_screen.max_h-1-y;
1270 gr_screen.clip_width = gr_screen.clip_right - gr_screen.clip_left + 1;
1271 gr_screen.clip_height = gr_screen.clip_bottom - gr_screen.clip_top + 1;
1274 // resets the clipping region to entire screen
1276 // should call this before gr_surface_flip() if you clipped some portion of the screen but still
1277 // want a full-screen display
1278 void grx_reset_clip()
1280 gr_screen.offset_x = 0;
1281 gr_screen.offset_y = 0;
1282 gr_screen.clip_left = 0;
1283 gr_screen.clip_top = 0;
1284 gr_screen.clip_right = gr_screen.max_w - 1;
1285 gr_screen.clip_bottom = gr_screen.max_h - 1;
1286 gr_screen.clip_width = gr_screen.max_w;
1287 gr_screen.clip_height = gr_screen.max_h;
1291 // Sets the current bitmap
1292 void grx_set_bitmap( int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy )
1294 gr_screen.current_alpha = alpha;
1295 gr_screen.current_alphablend_mode = alphablend_mode;
1296 gr_screen.current_bitblt_mode = bitblt_mode;
1297 gr_screen.current_bitmap = bitmap_num;
1298 gr_screen.current_bitmap_sx = sx;
1299 gr_screen.current_bitmap_sy = sy;
1303 // clears entire clipping region to black.
1311 w = gr_screen.clip_right-gr_screen.clip_left+1;
1312 for (i=gr_screen.clip_top; i<=gr_screen.clip_bottom; i++) {
1313 pDestBits = GR_SCREEN_PTR(ubyte,gr_screen.clip_left,i);
1314 memset( pDestBits, 0, w );
1322 void grx_start_frame()
1326 void grx_stop_frame()
1330 void gr_soft_fog_set(int fog_mode, int r, int g, int b, float near, float far)
1334 void gr_soft_get_pixel(int x, int y, int *r, int *g, int *b)
1338 void grx_fade_in(int instantaneous);
1339 void grx_fade_out(int instantaneous);
1340 void grx_flash(int r, int g, int b);
1342 static ubyte *Gr_saved_screen = NULL;
1343 static uint Gr_saved_screen_palette_checksum = 0;
1344 static ubyte Gr_saved_screen_palette[768];
1346 int gr8_save_screen()
1351 if (gr_screen.bits_per_pixel != 8) {
1352 mprintf(( "Save Screen only works in 8 bpp!\n" ));
1356 if ( Gr_saved_screen ) {
1357 mprintf(( "Screen alread saved!\n" ));
1361 Gr_saved_screen = (ubyte *)malloc( gr_screen.max_w*gr_screen.max_h );
1362 if (!Gr_saved_screen) {
1363 mprintf(( "Couldn't get memory for saved screen!\n" ));
1367 Gr_saved_screen_palette_checksum = gr_palette_checksum;
1368 memcpy( Gr_saved_screen_palette, gr_palette, 768 );
1372 for (i=0; i<gr_screen.max_h; i++ ) {
1373 ubyte *dptr = GR_SCREEN_PTR(ubyte,0,i);
1374 memcpy( &Gr_saved_screen[gr_screen.max_w*i], dptr, gr_screen.max_w );
1383 void gr8_restore_screen(int id)
1388 if ( !Gr_saved_screen ) {
1393 if ( Gr_saved_screen_palette_checksum != gr_palette_checksum ) {
1394 // Palette changed! Remap the bitmap!
1396 for (i=0; i<256; i++ ) {
1397 xlat[i] = (ubyte)palette_find( Gr_saved_screen_palette[i*3+0], Gr_saved_screen_palette[i*3+1], Gr_saved_screen_palette[i*3+2] );
1400 for (i=0; i<gr_screen.max_h*gr_screen.max_w; i++ ) {
1401 Gr_saved_screen[i] = xlat[Gr_saved_screen[i]];
1404 memcpy( Gr_saved_screen_palette, gr_palette, 768 );
1405 Gr_saved_screen_palette_checksum = gr_palette_checksum;
1410 for (i=0; i<gr_screen.max_h; i++ ) {
1411 ubyte *dptr = GR_SCREEN_PTR(ubyte,0,i);
1412 memcpy( dptr, &Gr_saved_screen[gr_screen.max_w*i], gr_screen.max_w );
1419 void gr8_free_screen(int id)
1421 if ( Gr_saved_screen ) {
1422 free( Gr_saved_screen );
1423 Gr_saved_screen = NULL;
1427 static int Gr8_dump_frames = 0;
1428 static ubyte *Gr8_dump_buffer = NULL;
1429 static int Gr8_dump_frame_number = 0;
1430 static int Gr8_dump_frame_count = 0;
1431 static int Gr8_dump_frame_count_max = 0;
1432 static int Gr8_dump_frame_size = 0;
1435 void gr8_dump_frame_start(int first_frame, int frames_between_dumps)
1437 if ( Gr8_dump_frames ) {
1438 Int3(); // We're already dumping frames. See John.
1441 Gr8_dump_frames = 1;
1442 Gr8_dump_frame_number = first_frame;
1443 Gr8_dump_frame_count = 0;
1444 Gr8_dump_frame_count_max = frames_between_dumps;
1445 Gr8_dump_frame_size = 640 * 480;
1447 if ( !Gr8_dump_buffer ) {
1448 int size = Gr8_dump_frame_count_max * Gr8_dump_frame_size;
1449 Gr8_dump_buffer = (ubyte *)malloc(size);
1450 if ( !Gr8_dump_buffer ) {
1451 Error(LOCATION, "Unable to malloc %d bytes for dump buffer", size );
1456 // A hacked function to dump the frame buffer contents
1457 void gr8_dump_screen_hack( void * dst )
1462 for (i = 0; i < 480; i++) {
1463 memcpy( (ubyte *)dst+(i*640), GR_SCREEN_PTR(ubyte,0,i), 640 );
1468 void gr8_flush_frame_dump()
1471 char filename[MAX_PATH_LEN], *movie_path = "";
1474 for (i = 0; i < Gr8_dump_frame_count; i++) {
1477 for ( j = 0; j < 480; j++ )
1478 buffer[j] = Gr8_dump_buffer+(i*Gr8_dump_frame_size)+(j*640);
1480 sprintf(filename, NOX("%sfrm%04d"), movie_path, Gr8_dump_frame_number );
1481 pcx_write_bitmap(filename, 640, 480, buffer, gr_palette);
1482 Gr8_dump_frame_number++;
1486 void gr8_dump_frame()
1488 // A hacked function to dump the frame buffer contents
1489 gr8_dump_screen_hack( Gr8_dump_buffer+(Gr8_dump_frame_count*Gr8_dump_frame_size) );
1491 Gr8_dump_frame_count++;
1493 if ( Gr8_dump_frame_count == Gr8_dump_frame_count_max ) {
1494 gr8_flush_frame_dump();
1495 Gr8_dump_frame_count = 0;
1499 void grx_get_region(int front, int w, int h, ubyte *data)
1503 // resolution checking
1504 int gr_soft_supports_res_ingame(int res)
1509 int gr_soft_supports_res_interface(int res)
1514 void gr8_dump_frame_stop()
1516 if ( !Gr8_dump_frames ) {
1517 Int3(); // We're not dumping frames. See John.
1521 // dump any remaining frames
1522 gr8_flush_frame_dump();
1524 Gr8_dump_frames = 0;
1525 if ( Gr8_dump_buffer ) {
1526 free(Gr8_dump_buffer);
1527 Gr8_dump_buffer = NULL;
1531 void gr_soft_set_cull(int cull)
1536 void gr_soft_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
1539 gr_set_bitmap(bmap1);
1542 gr_set_bitmap(bmap2);
1548 void gr_soft_filter_set(int filter)
1553 int gr_soft_tcache_set(int bitmap_id, int bitmap_type, float *u_ratio, float *v_ratio, int fail_on_full = 0, int sx = -1, int sy = -1, int force = 0 )
1559 void gr_soft_set_clear_color(int r, int g, int b)
1563 extern uint Gr_signature;
1565 //extern void gr_set_palette_internal(char *name, ubyte *pal);
1567 void gr8_set_gamma(float gamma)
1570 Gr_gamma_int = int(Gr_gamma*100);
1572 // Create the Gamma lookup table
1574 for (i=0; i<256; i++ ) {
1575 int v = fl2i(pow(i2fl(i)/255.0f, 1.0f/Gr_gamma)*255.0f);
1578 } else if ( v < 0 ) {
1581 Gr_gamma_lookup[i] = v;
1584 // ubyte new_pal[768];
1585 // if ( gr_screen.bits_per_pixel!=8 ) return;
1587 // for (i=0; i<768; i++ ) {
1588 // new_pal[i] = ubyte(Gr_gamma_lookup[gr_palette[i]]);
1590 // grx_change_palette( new_pal );
1592 gr_screen.signature = Gr_signature++;
1600 // software mode only supports 640x480
1601 Assert(gr_screen.res == GR_640);
1602 if(gr_screen.res != GR_640){
1603 gr_screen.res = GR_640;
1604 gr_screen.max_w = 640;
1605 gr_screen.max_h = 480;
1608 // Prepare the window to go full screen
1610 if (SDL_InitSubSystem (SDL_INIT_VIDEO) < 0)
1612 fprintf (stderr, "Couldn't initialize SDL: %s", SDL_GetError());
1618 soft_surface = SDL_SetVideoMode (640,480,8,0);
1619 if (soft_surface == NULL) {
1620 fprintf (stderr, "Couldn't set 640x480x8 mode: %s", SDL_GetError());
1624 HWND hwnd = (HWND)os_get_window();
1627 DWORD style, exstyle;
1631 style = WS_CAPTION | WS_SYSMENU;
1633 // Create Game Window
1634 client_rect.left = client_rect.top = 0;
1635 client_rect.right = gr_screen.max_w;
1636 client_rect.bottom = gr_screen.max_h;
1637 AdjustWindowRect(&client_rect,style,FALSE);
1640 SystemParametersInfo( SPI_GETWORKAREA, 0, &work_rect, 0 );
1641 int x = work_rect.left + (( work_rect.right - work_rect.left )-(client_rect.right - client_rect.left))/2;
1642 int y = work_rect.top;
1643 if ( x < work_rect.left ) {
1648 int WinW = client_rect.right - client_rect.left;
1649 int WinH = client_rect.bottom - client_rect.top;
1651 ShowWindow(hwnd, SW_SHOWNORMAL );
1652 SetWindowLong( hwnd, GWL_STYLE, style );
1653 SetWindowLong( hwnd, GWL_EXSTYLE, exstyle );
1654 SetWindowPos( hwnd, HWND_NOTOPMOST, WinX, WinY, WinW, WinH, SWP_SHOWWINDOW );
1655 SetActiveWindow(hwnd);
1656 SetForegroundWindow(hwnd);
1660 Palette_flashed = 0;
1661 Palette_flashed_last_frame = 0;
1663 gr_screen.bits_per_pixel = 8;
1664 gr_screen.bytes_per_pixel = 1;
1666 gr_buffer_create( gr_screen.max_w, gr_screen.max_h, gr_screen.bits_per_pixel );
1669 gr_screen.offscreen_buffer_base = gr_screen.offscreen_buffer = soft_surface->pixels;
1670 gr_screen.rowsize = soft_surface->pitch;
1672 gr_screen.offscreen_buffer_base = lpDibBits;
1674 gr_screen.rowsize = DibInfo.Header.biWidth*((gr_screen.bits_per_pixel+7)/8);
1675 Assert( DibInfo.Header.biWidth == gr_screen.max_w );
1677 if (DibInfo.Header.biHeight > 0) {
1679 gr_screen.offscreen_buffer = (void *)((uint)gr_screen.offscreen_buffer_base + (gr_screen.max_h - 1) * gr_screen.rowsize);
1680 gr_screen.rowsize *= -1;
1683 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
1687 grx_init_alphacolors();
1689 gr_screen.gf_flip = grx_flip;
1690 gr_screen.gf_flip_window = grx_flip_window;
1691 gr_screen.gf_set_clip = grx_set_clip;
1692 gr_screen.gf_reset_clip = grx_reset_clip;
1693 gr_screen.gf_set_font = grx_set_font;
1694 gr_screen.gf_set_color = grx_set_color;
1695 gr_screen.gf_set_bitmap = grx_set_bitmap;
1696 gr_screen.gf_create_shader = grx_create_shader;
1697 gr_screen.gf_set_shader = grx_set_shader;
1698 gr_screen.gf_clear = grx_clear;
1699 // gr_screen.gf_bitmap = grx_bitmap;
1700 // ]gr_screen.gf_bitmap_ex = grx_bitmap_ex;
1702 gr_screen.gf_aabitmap = grx_aabitmap;
1703 gr_screen.gf_aabitmap_ex = grx_aabitmap_ex;
1705 gr_screen.gf_rect = grx_rect;
1706 gr_screen.gf_shade = gr8_shade;
1707 gr_screen.gf_string = gr8_string;
1708 gr_screen.gf_circle = gr8_circle;
1710 gr_screen.gf_line = gr8_line;
1711 gr_screen.gf_aaline = gr8_aaline;
1712 gr_screen.gf_pixel = gr8_pixel;
1713 gr_screen.gf_scaler = gr8_scaler;
1714 gr_screen.gf_aascaler = gr8_aascaler;
1715 gr_screen.gf_tmapper = grx_tmapper;
1717 gr_screen.gf_gradient = gr8_gradient;
1719 gr_screen.gf_set_palette = grx_set_palette;
1720 gr_screen.gf_get_color = grx_get_color;
1721 gr_screen.gf_init_color = grx_init_color;
1722 gr_screen.gf_init_alphacolor = grx_init_alphacolor;
1723 gr_screen.gf_set_color_fast = grx_set_color_fast;
1724 gr_screen.gf_print_screen = grx_print_screen;
1725 gr_screen.gf_start_frame = grx_start_frame;
1726 gr_screen.gf_stop_frame = grx_stop_frame;
1728 gr_screen.gf_fade_in = grx_fade_in;
1729 gr_screen.gf_fade_out = grx_fade_out;
1730 gr_screen.gf_flash = grx_flash;
1733 // Retrieves the zbuffer mode.
1734 gr_screen.gf_zbuffer_get = gr8_zbuffer_get;
1735 gr_screen.gf_zbuffer_set = gr8_zbuffer_set;
1736 gr_screen.gf_zbuffer_clear = gr8_zbuffer_clear;
1738 gr_screen.gf_save_screen = gr8_save_screen;
1739 gr_screen.gf_restore_screen = gr8_restore_screen;
1740 gr_screen.gf_free_screen = gr8_free_screen;
1742 // Screen dumping stuff
1743 gr_screen.gf_dump_frame_start = gr8_dump_frame_start;
1744 gr_screen.gf_dump_frame_stop = gr8_dump_frame_stop;
1745 gr_screen.gf_dump_frame = gr8_dump_frame;
1748 gr_screen.gf_set_gamma = gr8_set_gamma;
1750 // Lock/unlock stuff
1751 gr_screen.gf_lock = gr_soft_lock;
1752 gr_screen.gf_unlock = gr_soft_unlock;
1755 gr_screen.gf_get_region = grx_get_region;
1758 gr_screen.gf_fog_set = gr_soft_fog_set;
1761 gr_screen.gf_get_pixel = gr_soft_get_pixel;
1764 gr_screen.gf_set_cull = gr_soft_set_cull;
1767 gr_screen.gf_cross_fade = gr_soft_cross_fade;
1770 gr_screen.gf_filter_set = gr_soft_filter_set;
1773 gr_screen.gf_tcache_set = gr_soft_tcache_set;
1776 gr_screen.gf_set_clear_color = gr_soft_set_clear_color;
1783 void gr_soft_force_windowed()
1787 void gr_soft_cleanup()
1789 if (Gr_soft_inited) {
1790 gr_buffer_release();
1795 void grx_change_palette( ubyte * new_pal )
1799 SDL_Color colors[256];
1800 for (i=0; i<256; i++)
1802 colors[i].r = new_pal[i*3+0];
1803 colors[i].g = new_pal[i*3+1];
1804 colors[i].b = new_pal[i*3+2];
1806 SDL_SetColors (soft_surface, colors, 0, 256);
1810 SelectPalette( hDibDC, hOldPalette, FALSE );
1811 if (!DeleteObject(hPalette))
1816 hPalette = gr_create_palette_256(new_pal); // All 256 mapped one-to-one, but BLT's are slow.
1820 for (i=0; i<256; i++ ) {
1821 DibInfo.Colors.aColors[i].rgbRed = new_pal[i*3+0];
1822 DibInfo.Colors.aColors[i].rgbGreen = new_pal[i*3+1];
1823 DibInfo.Colors.aColors[i].rgbBlue = new_pal[i*3+2];
1824 DibInfo.Colors.aColors[i].rgbReserved = 0;
1827 hOldPalette = SelectPalette( hDibDC, hPalette, FALSE );
1828 SetDIBColorTable( hDibDC, 0, 256, DibInfo.Colors.aColors );
1833 void grx_flash( int r, int g, int b )
1838 if ( (r==0) && (g==0) && (b==0) ) {
1844 for (i=0; i<256; i++ ) {
1845 t = gr_palette[i*3+0] + r;
1846 if ( t < 0 ) t = 0; else if (t>255) t = 255;
1847 new_pal[i*3+0] = (ubyte)t;
1849 t = gr_palette[i*3+1] + g;
1850 if ( t < 0 ) t = 0; else if (t>255) t = 255;
1851 new_pal[i*3+1] = (ubyte)t;
1853 t = gr_palette[i*3+2] + b;
1854 if ( t < 0 ) t = 0; else if (t>255) t = 255;
1855 new_pal[i*3+2] = (ubyte)t;
1858 grx_change_palette( new_pal );
1861 #ifndef HARDWARE_ONLY
1862 static int gr_palette_faded_out = 0;
1865 #define FADE_TIME (F1_0/4) // How long to fade out
1867 void grx_fade_out(int instantaneous)
1869 #ifndef HARDWARE_ONLY
1873 if (!gr_palette_faded_out) {
1875 if ( !instantaneous ) {
1878 fix start_time, stop_time, t1;
1880 start_time = timer_get_fixed_seconds();
1884 for (i=0; i<768; i++ ) {
1885 int c = (gr_palette[i]*(FADE_TIME-t1))/FADE_TIME;
1891 new_pal[i] = (ubyte)c;
1893 grx_change_palette( new_pal );
1897 t1 = timer_get_fixed_seconds() - start_time;
1899 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
1901 stop_time = timer_get_fixed_seconds();
1903 mprintf(( "Took %d frames (and %.1f secs) to fade out\n", count, f2fl(stop_time-start_time) ));
1906 gr_palette_faded_out = 1;
1912 memset( new_pal, 0, 768 );
1913 grx_change_palette( new_pal );
1920 void grx_fade_in(int instantaneous)
1922 #ifndef HARDWARE_ONLY
1926 if (gr_palette_faded_out) {
1928 if ( !instantaneous ) {
1930 fix start_time, stop_time, t1;
1932 start_time = timer_get_fixed_seconds();
1936 for (i=0; i<768; i++ ) {
1937 int c = (gr_palette[i]*t1)/FADE_TIME;
1943 new_pal[i] = (ubyte)c;
1945 grx_change_palette( new_pal );
1949 t1 = timer_get_fixed_seconds() - start_time;
1951 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
1953 stop_time = timer_get_fixed_seconds();
1955 mprintf(( "Took %d frames (and %.1f secs) to fade in\n", count, f2fl(stop_time-start_time) ));
1957 gr_palette_faded_out = 0;
1960 memcpy( new_pal, gr_palette, 768 );
1961 grx_change_palette( new_pal );