use new d_realloc function, so mem manager doesn't die
[btb/d2x.git] / arch / ogl / gr.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/ogl/gr.c,v $
3  * $Revision: 1.4 $
4  * $Author: bradleyb $
5  * $Date: 2001-11-08 10:19:52 $
6  *
7  * // OGL video functions. - Added 9/15/99 Matthew Mueller
8  *
9  * $Log: not supported by cvs2svn $
10  * Revision 1.3  2001/11/04 09:00:25  bradleyb
11  * Enable d1x-style hud_message
12  *
13  * Revision 1.2  2001/10/31 07:35:47  bradleyb
14  * Sync with d1x
15  *
16  * Revision 1.1  2001/10/25 08:25:34  bradleyb
17  * Finished moving stuff to arch/blah.  I know, it's ugly, but It'll be easier to sync with d1x.
18  *
19  * Revision 1.7  2001/10/25 02:23:48  bradleyb
20  * formatting fix
21  *
22  * Revision 1.6  2001/10/18 23:59:23  bradleyb
23  * Changed __ENV_LINUX__ to __linux__
24  *
25  * Revision 1.5  2001/10/12 00:18:40  bradleyb
26  * Switched from Cygwin to mingw32 on MS boxes.  Vastly improved compilability.
27  *
28  * Revision 1.4  2001/01/29 13:47:52  bradleyb
29  * Fixed build, some minor cleanups.
30  *
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <conf.h>
35 #endif
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #ifdef __WINDOWS__
41 #include <windows.h>
42 #endif
43
44 //#include <GL/gl.h>
45 #include <unistd.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <errno.h>
50
51 #include "hudmsg.h"
52 #include "game.h"
53 #include "text.h"
54 #include "gr.h"
55 #include "gamefont.h"
56 #include "grdef.h"
57 #include "palette.h"
58 #include "u_mem.h"
59 #include "error.h"
60
61 #include "inferno.h"
62 #include "screens.h"
63
64 #include "strutil.h"
65 #include "mono.h"
66 #include "args.h"
67 #include "key.h"
68
69 #define DECLARE_VARS
70 #include "ogl_init.h"
71 #include <GL/glu.h>
72
73 int ogl_voodoohack=0;
74
75 int gr_installed = 0;
76
77
78 void gr_palette_clear(); // Function prototype for gr_init;
79 int gl_initialized=0;
80 int gl_reticle=1;
81
82 int ogl_fullscreen=0;
83
84 int gr_check_fullscreen(void){
85         return ogl_fullscreen;
86 }
87
88 void gr_do_fullscreen(int f){
89         if (ogl_voodoohack)
90                 ogl_fullscreen=1;//force fullscreen mode on voodoos.
91         else
92                 ogl_fullscreen=f;
93         if (gl_initialized){
94                 ogl_do_fullscreen_internal();
95         }
96 }
97
98 int gr_toggle_fullscreen(void){
99         gr_do_fullscreen(!ogl_fullscreen);
100         //      grd_curscreen->sc_mode=0;//hack to get it to reset screen mode
101         return ogl_fullscreen;
102 }
103
104 int arch_toggle_fullscreen_menu(void){
105         unsigned char *buf=NULL;
106
107         if (ogl_readpixels_ok){
108                 MALLOC(buf,unsigned char,grd_curscreen->sc_w*grd_curscreen->sc_h*3);
109                 glReadBuffer(GL_FRONT);
110                 glReadPixels(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h,GL_RGB,GL_UNSIGNED_BYTE,buf);
111         }
112
113         gr_do_fullscreen(!ogl_fullscreen);
114
115         if (ogl_readpixels_ok){
116 //              glWritePixels(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h,GL_RGB,GL_UNSIGNED_BYTE,buf);
117                 glRasterPos2f(0,0);
118                 glDrawPixels(grd_curscreen->sc_w,grd_curscreen->sc_h,GL_RGB,GL_UNSIGNED_BYTE,buf);
119                 free(buf);
120         }
121         //      grd_curscreen->sc_mode=0;//hack to get it to reset screen mode
122
123         return ogl_fullscreen;
124 }
125
126 void ogl_init_state(void){
127         /* select clearing (background) color   */
128         glClearColor(0.0, 0.0, 0.0, 0.0);
129         glShadeModel(GL_SMOOTH);
130
131         /* initialize viewing values */
132         glMatrixMode(GL_PROJECTION);
133         glLoadIdentity();
134         glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
135         glScalef(1.0, -1.0, 1.0);
136         glTranslatef(0.0, -1.0, 0.0);
137         gr_palette_step_up(0,0,0);//in case its left over from in game
138 }
139
140 int last_screen_mode=-1;
141
142 void ogl_set_screen_mode(void){
143         if (last_screen_mode==Screen_mode)
144                 return;
145         OGL_VIEWPORT(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h);
146 //      OGL_VIEWPORT(grd_curcanv->cv_bitmap.bm_x,grd_curcanv->cv_bitmap.bm_y,grd_curcanv->cv_bitmap.bm_w,grd_curcanv->cv_bitmap.bm_h);
147         if (Screen_mode==SCREEN_GAME){
148                 glDrawBuffer(GL_BACK);
149         }else{
150                 glClearColor(0.0, 0.0, 0.0, 0.0);
151                 glDrawBuffer(GL_FRONT);
152                 glClear(GL_COLOR_BUFFER_BIT);
153                 glMatrixMode(GL_PROJECTION);
154                 glLoadIdentity();//clear matrix
155                 glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
156                 glMatrixMode(GL_MODELVIEW);
157                 glLoadIdentity();//clear matrix
158                 glEnable(GL_BLEND);
159                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
160         }
161         last_screen_mode=Screen_mode;
162 }
163
164 void gr_update()
165 {
166         if (gl_initialized){
167
168                 if(Screen_mode != SCREEN_GAME){
169                         glFlush();
170                 }
171         }
172 }
173
174 const char *gl_vendor,*gl_renderer,*gl_version,*gl_extensions;
175
176 void ogl_get_verinfo(void){
177         int t;
178         gl_vendor=glGetString(GL_VENDOR);
179         gl_renderer=glGetString(GL_RENDERER);
180         gl_version=glGetString(GL_VERSION);
181         gl_extensions=glGetString(GL_EXTENSIONS);
182
183         printf("gl vendor:%s renderer:%s version:%s extensions:%s\n",gl_vendor,gl_renderer,gl_version,gl_extensions);
184
185         ogl_intensity4_ok=1;ogl_luminance4_alpha4_ok=1;ogl_rgba2_ok=1;ogl_gettexlevelparam_ok=1;
186
187 #ifdef __WINDOWS__
188         dglMultiTexCoord2fARB = (glMultiTexCoord2fARB_fp)wglGetProcAddress("glMultiTexCoord2fARB");
189         dglActiveTextureARB = (glActiveTextureARB_fp)wglGetProcAddress("glActiveTextureARB");
190         dglMultiTexCoord2fSGIS = (glMultiTexCoord2fSGIS_fp)wglGetProcAddress("glMultiTexCoord2fSGIS");
191         dglSelectTextureSGIS = (glSelectTextureSGIS_fp)wglGetProcAddress("glSelectTextureSGIS");
192 #endif
193
194         //multitexturing doesn't work yet.
195 #ifdef GL_ARB_multitexture
196         ogl_arb_multitexture_ok=0;//(strstr(gl_extensions,"GL_ARB_multitexture")!=0 && glActiveTextureARB!=0 && 0);
197         mprintf((0,"c:%p d:%p e:%p\n",strstr(gl_extensions,"GL_ARB_multitexture"),glActiveTextureARB,glBegin));
198 #endif
199 #ifdef GL_SGIS_multitexture
200         ogl_sgis_multitexture_ok=0;//(strstr(gl_extensions,"GL_SGIS_multitexture")!=0 && glSelectTextureSGIS!=0 && 0);
201         mprintf((0,"a:%p b:%p\n",strstr(gl_extensions,"GL_SGIS_multitexture"),glSelectTextureSGIS));
202 #endif
203
204         //add driver specific hacks here.  whee.
205         if ((stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.0\n")==0 || stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.2\n")==0) && stricmp(gl_version,"1.2 Mesa 3.0")==0){
206                 ogl_intensity4_ok=0;//ignores alpha, always black background instead of transparent.
207                 ogl_readpixels_ok=0;//either just returns all black, or kills the X server entirely
208                 ogl_gettexlevelparam_ok=0;//returns random data..
209         }
210         if (stricmp(gl_vendor,"Matrox Graphics Inc.")==0){
211                 //displays garbage. reported by
212                 //  redomen@crcwnet.com (render="Matrox G400" version="1.1.3 5.52.015")
213                 //  orulz (Matrox G200)
214                 ogl_intensity4_ok=0;
215         }
216
217         //allow overriding of stuff.
218 #ifdef GL_ARB_multitexture
219         if ((t=FindArg("-gl_arb_multitexture_ok"))){
220                 ogl_arb_multitexture_ok=atoi(Args[t+1]);
221         }
222 #endif
223 #ifdef GL_SGIS_multitexture
224         if ((t=FindArg("-gl_sgis_multitexture_ok"))){
225                 ogl_sgis_multitexture_ok=atoi(Args[t+1]);
226         }
227 #endif
228         if ((t=FindArg("-gl_intensity4_ok"))){
229                 ogl_intensity4_ok=atoi(Args[t+1]);
230         }
231         if ((t=FindArg("-gl_luminance4_alpha4_ok"))){
232                 ogl_luminance4_alpha4_ok=atoi(Args[t+1]);
233         }
234         if ((t=FindArg("-gl_rgba2_ok"))){
235                 ogl_rgba2_ok=atoi(Args[t+1]);
236         }
237         if ((t=FindArg("-gl_readpixels_ok"))){
238                 ogl_readpixels_ok=atoi(Args[t+1]);
239         }
240         if ((t=FindArg("-gl_gettexlevelparam_ok"))){
241                 ogl_gettexlevelparam_ok=atoi(Args[t+1]);
242         }
243
244         printf("gl_arb_multitexture:%i gl_sgis_multitexture:%i\n",ogl_arb_multitexture_ok,ogl_sgis_multitexture_ok);
245         printf("gl_intensity4:%i gl_luminance4_alpha4:%i gl_rgba2:%i gl_readpixels:%i gl_gettexlevelparam:%i\n",ogl_intensity4_ok,ogl_luminance4_alpha4_ok,ogl_rgba2_ok,ogl_readpixels_ok,ogl_gettexlevelparam_ok);
246 }
247
248 int gr_set_mode(u_int32_t mode)
249 {
250         unsigned int w,h;
251         char *gr_bm_data;
252
253 #ifdef NOGRAPH
254 return 0;
255 #endif
256 //      mode=0;
257         if (mode<=0)
258                 return 0;
259
260         w=SM_W(mode);
261         h=SM_H(mode);
262
263         //if (screen != NULL) gr_palette_clear();
264
265 //      ogl_init_state();
266         
267         gr_bm_data=grd_curscreen->sc_canvas.cv_bitmap.bm_data;//since we use realloc, we want to keep this pointer around.
268         memset( grd_curscreen, 0, sizeof(grs_screen));
269         grd_curscreen->sc_mode = mode;
270         grd_curscreen->sc_w = w;
271         grd_curscreen->sc_h = h;
272         grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
273         grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
274         grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
275         grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
276         grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
277         //grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = screen->pitch;
278         grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = w;
279         grd_curscreen->sc_canvas.cv_bitmap.bm_type = BM_OGL;
280         //grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)screen->pixels;
281 //      mprintf((0,"ogl/gr.c: reallocing %p to %i\n",grd_curscreen->sc_canvas.cv_bitmap.bm_data,w*h));
282         grd_curscreen->sc_canvas.cv_bitmap.bm_data = d_realloc(gr_bm_data,w*h);
283         gr_set_current_canvas(NULL);
284         //gr_enable_default_palette_loading();
285         
286         ogl_init_window(w,h);//platform specific code
287
288         ogl_get_verinfo();
289
290         OGL_VIEWPORT(0,0,w,h);
291
292         ogl_set_screen_mode();
293
294 //      gamefont_choose_game_font(w,h);
295         
296         return 0;
297 }
298
299 #define GLstrcmptestr(a,b) if (stricmp(a,#b)==0 || stricmp(a,"GL_" #b)==0)return GL_ ## b;
300 int ogl_atotexfilti(char *a,int min){
301         GLstrcmptestr(a,NEAREST);
302         GLstrcmptestr(a,LINEAR);
303         if (min){//mipmaps are valid only for the min filter
304                 GLstrcmptestr(a,NEAREST_MIPMAP_NEAREST);
305                 GLstrcmptestr(a,NEAREST_MIPMAP_LINEAR);
306                 GLstrcmptestr(a,LINEAR_MIPMAP_NEAREST);
307                 GLstrcmptestr(a,LINEAR_MIPMAP_LINEAR);
308         }
309         Error("unknown/invalid texture filter %s\n",a);
310 //      return GL_NEAREST;
311 }
312 int ogl_testneedmipmaps(int i){
313         switch (i){
314                 case GL_NEAREST:
315                 case GL_LINEAR:
316                         return 0;
317                 case GL_NEAREST_MIPMAP_NEAREST:
318                 case GL_NEAREST_MIPMAP_LINEAR:
319                 case GL_LINEAR_MIPMAP_NEAREST:
320                 case GL_LINEAR_MIPMAP_LINEAR:
321                         return 1;
322         }
323         Error("unknown texture filter %x\n",i);
324 //      return -1;
325 }
326 #ifdef OGL_RUNTIME_LOAD
327 #if defined(__WINDOWS__) || defined(__MINGW32__)
328 char *OglLibPath="opengl32.dll";
329 #endif
330 #ifdef __linux__
331 char *OglLibPath="libGL.so";
332 #endif
333
334 int ogl_rt_loaded=0;
335 int ogl_init_load_library(void)
336 {
337         int retcode=0;
338         if (!ogl_rt_loaded){
339                 int t;
340                 if ((t=FindArg("-gl_library")))
341                         OglLibPath=Args[t+1];
342
343                 retcode = OpenGL_LoadLibrary(true);
344                 if(retcode)
345                 {
346                         mprintf((0,"Opengl loaded ok\n"));
347         
348                         if(!glEnd)
349                         {
350                                 Error("Opengl: Functions not imported\n");
351                         }
352                 }else{
353                         Error("Opengl: error loading %s\n",OglLibPath);
354                 }
355                 ogl_rt_loaded=1;
356         }
357         return retcode;
358 }
359 #endif
360
361 int gr_init()
362 {
363  int mode = SM(640,480);
364  int retcode,t,glt=0;
365         // Only do this function once!
366         if (gr_installed==1)
367                 return -1;
368
369
370 #ifdef OGL_RUNTIME_LOAD
371         ogl_init_load_library();
372 #endif
373
374 #ifdef GR_SUPPORTS_FULLSCREEN_TOGGLE
375         if (FindArg("-gl_voodoo")){
376                 ogl_voodoohack=1;
377                 gr_toggle_fullscreen();
378         }
379         if (FindArg("-fullscreen"))
380                 gr_toggle_fullscreen();
381 #endif
382         if ((glt=FindArg("-gl_alttexmerge")))
383                 ogl_alttexmerge=1;
384         if ((t=FindArg("-gl_stdtexmerge")))
385                 if (t>=glt)//allow overriding of earlier args
386                         ogl_alttexmerge=0;
387                         
388         if ((glt=FindArg("-gl_16bittextures")))
389                 ogl_rgba_format=GL_RGB5_A1;
390
391         if ((glt=FindArg("-gl_mipmap"))){
392                 GL_texmagfilt=GL_LINEAR;
393                 GL_texminfilt=GL_LINEAR_MIPMAP_NEAREST;
394         }
395         if ((t=FindArg("-gl_simple"))){
396                 if (t>=glt){//allow overriding of earlier args
397                         glt=t;
398                         GL_texmagfilt=GL_NEAREST;
399                         GL_texminfilt=GL_NEAREST;
400                 }
401         }
402         if ((t=FindArg("-gl_texmagfilt")) || (t=FindArg("-gl_texmagfilter"))){
403                 if (t>=glt)//allow overriding of earlier args
404                         GL_texmagfilt=ogl_atotexfilti(Args[t+1],0);
405         }
406         if ((t=FindArg("-gl_texminfilt")) || (t=FindArg("-gl_texminfilter"))){
407                 if (t>=glt)//allow overriding of earlier args
408                         GL_texminfilt=ogl_atotexfilti(Args[t+1],1);
409         }
410         GL_needmipmaps=ogl_testneedmipmaps(GL_texminfilt);
411         mprintf((0,"gr_init: texmagfilt:%x texminfilt:%x needmipmaps=%i\n",GL_texmagfilt,GL_texminfilt,GL_needmipmaps));
412         
413         if ((t=FindArg("-gl_vidmem"))){
414                 ogl_mem_target=atoi(Args[t+1])*1024*1024;
415         }
416         if ((t=FindArg("-gl_reticle"))){
417                 gl_reticle=atoi(Args[t+1]);
418         }
419         //printf("ogl_mem_target=%i\n",ogl_mem_target);
420         
421         ogl_init();//platform specific initialization
422
423         ogl_init_texture_list_internal();
424                 
425         MALLOC( grd_curscreen,grs_screen,1 );
426         memset( grd_curscreen, 0, sizeof(grs_screen));
427         grd_curscreen->sc_canvas.cv_bitmap.bm_data = NULL;
428
429         // Set the mode.
430         if ((retcode=gr_set_mode(mode)))
431         {
432                 return retcode;
433         }
434         grd_curscreen->sc_canvas.cv_color = 0;
435         grd_curscreen->sc_canvas.cv_drawmode = 0;
436         grd_curscreen->sc_canvas.cv_font = NULL;
437         grd_curscreen->sc_canvas.cv_font_fg_color = 0;
438         grd_curscreen->sc_canvas.cv_font_bg_color = 0;
439         gr_set_current_canvas( &grd_curscreen->sc_canvas );
440
441         gr_installed = 1;
442         
443         atexit(gr_close);
444
445         return 0;
446 }
447
448 void gr_close()
449 {
450 //      mprintf((0,"ogl init: %s %s %s - %s\n",glGetString(GL_VENDOR),glGetString(GL_RENDERER),glGetString(GL_VERSION),glGetString,(GL_EXTENSIONS)));
451
452         ogl_close();//platform specific code
453         if (grd_curscreen){
454                 if (grd_curscreen->sc_canvas.cv_bitmap.bm_data)
455                         d_free(grd_curscreen->sc_canvas.cv_bitmap.bm_data);
456                 d_free(grd_curscreen);
457         }
458 #ifdef OGL_RUNTIME_LOAD
459         if (ogl_rt_loaded)
460                 OpenGL_LoadLibrary(false);
461 #endif
462 }
463 extern int r_upixelc;
464 void ogl_upixelc(int x, int y, int c){
465         r_upixelc++;
466 //      printf("gr_upixelc(%i,%i,%i)%i\n",x,y,c,Function_mode==FMODE_GAME);
467 //      if(Function_mode != FMODE_GAME){
468 //              grd_curcanv->cv_bitmap.bm_data[y*grd_curscreen->sc_canvas.cv_bitmap.bm_w+x]=c;
469 //      }else{
470                 OGL_DISABLE(TEXTURE_2D);
471                 glPointSize(1.0);
472                 glBegin(GL_POINTS);
473 //              glBegin(GL_LINES);
474 //      ogl_pal=gr_current_pal;
475                 glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
476 //      ogl_pal=gr_palette;
477                 glVertex2f((x+grd_curcanv->cv_bitmap.bm_x)/(float)last_width,1.0-(y+grd_curcanv->cv_bitmap.bm_y)/(float)last_height);
478 //              glVertex2f(x/((float)last_width+1),1.0-y/((float)last_height+1));
479                 glEnd();
480 //      }
481 }
482 void ogl_urect(int left,int top,int right,int bot){
483         GLfloat xo,yo,xf,yf;
484         int c=COLOR;
485         
486         xo=(left+grd_curcanv->cv_bitmap.bm_x)/(float)last_width;
487         xf=(right+grd_curcanv->cv_bitmap.bm_x)/(float)last_width;
488         yo=1.0-(top+grd_curcanv->cv_bitmap.bm_y)/(float)last_height;
489         yf=1.0-(bot+grd_curcanv->cv_bitmap.bm_y)/(float)last_height;
490         
491         OGL_DISABLE(TEXTURE_2D);
492         glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
493         glBegin(GL_QUADS);
494         glVertex2f(xo,yo);
495         glVertex2f(xo,yf);
496         glVertex2f(xf,yf);
497         glVertex2f(xf,yo);
498         glEnd();
499 }
500 void ogl_ulinec(int left,int top,int right,int bot,int c){
501         GLfloat xo,yo,xf,yf;
502         
503         xo=(left+grd_curcanv->cv_bitmap.bm_x)/(float)last_width;
504         xf=(right+grd_curcanv->cv_bitmap.bm_x)/(float)last_width;
505         yo=1.0-(top+grd_curcanv->cv_bitmap.bm_y)/(float)last_height;
506         yf=1.0-(bot+grd_curcanv->cv_bitmap.bm_y)/(float)last_height;
507         
508         OGL_DISABLE(TEXTURE_2D);
509         glColor3f(CPAL2Tr(c),CPAL2Tg(c),CPAL2Tb(c));
510         glBegin(GL_LINES);
511         glVertex2f(xo,yo);
512         glVertex2f(xf,yf);
513         glEnd();
514 }
515         
516
517 GLfloat last_r=0, last_g=0, last_b=0;
518 int do_pal_step=0;
519 void ogl_do_palfx(void){
520 //      GLfloat r,g,b,a;
521         OGL_DISABLE(TEXTURE_2D);
522         if (gr_palette_faded_out){
523 /*              glEnable(GL_BLEND);
524                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);*/
525                 glColor3f(0,0,0);
526 //              r=g=b=0.0;a=1.0;
527         }else{
528                 if (do_pal_step){
529                         //glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
530                         glEnable(GL_BLEND);
531                         glBlendFunc(GL_ONE,GL_ONE);
532                         glColor3f(last_r,last_g,last_b);
533 //                      r=f2fl(last_r);g=f2fl(last_g);b=f2fl(last_b);a=0.5;
534                 }else
535                         return;
536         }
537         
538         
539         glBegin(GL_QUADS);
540         glVertex2f(0,0);
541         glVertex2f(0,1);
542         glVertex2f(1,1);
543         glVertex2f(1,0);
544         glEnd();
545         
546         glEnable(GL_BLEND);     
547         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
548 }
549
550 void gr_palette_clear()
551 {
552         gr_palette_faded_out=1;
553 }
554
555
556 void gr_palette_step_up( int r, int g, int b )
557 {
558         if (gr_palette_faded_out) return;
559
560 //      if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
561
562 /*      last_r = r/63.0;
563         last_g = g/63.0;
564         last_b = b/63.0;
565         do_pal_step=(r || g || b);*/
566         
567         last_r = (r+gr_palette_gamma)/63.0;
568         last_g = (g+gr_palette_gamma)/63.0;
569         last_b = (b+gr_palette_gamma)/63.0;
570
571         do_pal_step=(r || g || b || gr_palette_gamma);
572         
573 }
574
575 //added on 980913 by adb to fix palette problems
576 // need a min without side effects...
577 #undef min
578 static inline int min(int x, int y) { return x < y ? x : y; }
579 //end changes by adb
580
581 void gr_palette_load( ubyte *pal )      
582 {
583  int i;//, j;
584
585  for (i=0; i<768; i++ ) {
586      gr_current_pal[i] = pal[i];
587      if (gr_current_pal[i] > 63) gr_current_pal[i] = 63;
588  }
589  //palette = screen->format->palette;
590
591  gr_palette_faded_out=0;
592
593  init_computed_colors();
594 }
595
596
597
598 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys)
599 {
600         gr_palette_faded_out=1;
601         return 0;
602 }
603
604
605
606 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
607 {
608         gr_palette_faded_out=0;
609         return 0;
610 }
611
612
613
614 void gr_palette_read(ubyte * pal)
615 {
616         int i;
617         for (i=0; i<768; i++ ) {
618                 pal[i]=gr_current_pal[i];
619                 if (pal[i] > 63) pal[i] = 63;
620         }
621 }
622
623 //writes out an uncompressed RGB .tga file
624 //if we got really spiffy, we could optionally link in libpng or something, and use that.
625 void write_bmp(char *savename,int w,int h,unsigned char *buf){
626         int f;
627 #if defined(__WINDOWS__) || defined(__MINGW32__)
628         f=open(savename,O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR);
629 #else
630         f=open(savename,O_CREAT|O_EXCL|O_WRONLY,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
631 #endif
632         if (f>=0){
633                 GLubyte    targaMagic[12] = { 0, //no identification field
634                          0,//no colormap
635                          2,//RGB image (well, BGR, actually)
636                          0, 0, 0, 0, 0, 0, 0, 0, 0 };//no colormap or image origin stuff.
637                 GLubyte blah;
638                 int r;
639                 GLubyte *s;
640                 int x,y;
641                 
642                 //write .TGA header.
643                 write (f,targaMagic,sizeof(targaMagic));
644                 blah=w%256;write (f,&blah,1);//w, low
645                 blah=w/256;write (f,&blah,1);//w, high
646                 blah=h%256;write (f,&blah,1);//h, low
647                 blah=h/256;write (f,&blah,1);//h, high
648                 blah=24;write (f,&blah,1);//24 bpp
649                 blah=0;write (f,&blah,1);//no attribute bits, origin is lowerleft, no interleave
650                 
651                 s=buf;
652                 for (y=0;y<h;y++){//TGAs use BGR ordering of data.
653                         for (x=0;x<w;x++){
654                                 blah=s[0];
655                                 s[0]=s[2];
656                                 s[2]=blah;
657                                 s+=3;                           
658                         }
659                 }
660                 x=0;y=w*h*3;
661                 while (x<y){
662                         r=write(f,buf+x,y);
663                         if (r<=0){
664                                 mprintf((0,"screenshot error, couldn't write to %s (err %i)\n",savename,errno));
665                                 break;
666                         }
667                         x+=r;y-=r;
668                 }
669                 close(f);
670         }else{
671                 mprintf((0,"screenshot error, couldn't open %s (err %i)\n",savename,errno));
672         }
673 }
674 void save_screen_shot(int automap_flag)
675 {
676 //      fix t1;
677         char message[100];
678         static int savenum=0;
679         char savename[13];
680         unsigned char *buf;
681         
682         if (!ogl_readpixels_ok){
683                 if (!automap_flag)
684                         hud_message(MSGC_GAME_FEEDBACK,"glReadPixels not supported on your configuration");
685                 return;
686         }
687
688         stop_time();
689
690 //added/changed on 10/31/98 by Victor Rachels to fix overwrite each new game
691         if ( savenum == 9999 ) savenum = 0;
692         sprintf(savename,"scrn%04d.tga",savenum++);
693
694         while(!access(savename,0))
695         {
696                 if ( savenum == 9999 ) savenum = 0;
697                 sprintf(savename,"scrn%04d.tga",savenum++);
698         }
699         sprintf( message, "%s '%s'", TXT_DUMPING_SCREEN, savename );
700 //end this section addition/change - Victor Rachels
701
702         if (automap_flag) {
703 //      save_font = grd_curcanv->cv_font;
704 //      gr_set_curfont(GAME_FONT);
705 //      gr_set_fontcolor(gr_find_closest_color_current(0,31,0),-1);
706 //      gr_get_string_size(message,&w,&h,&aw);
707 //              modex_print_message(32, 2, message);
708         } else {
709                 hud_message(MSGC_GAME_FEEDBACK,message);
710         }
711         
712         buf = d_malloc(grd_curscreen->sc_w*grd_curscreen->sc_h*3);
713         glReadBuffer(GL_FRONT);
714         glReadPixels(0,0,grd_curscreen->sc_w,grd_curscreen->sc_h,GL_RGB,GL_UNSIGNED_BYTE,buf);
715         write_bmp(savename,grd_curscreen->sc_w,grd_curscreen->sc_h,buf);
716         d_free(buf);
717
718         key_flush();
719         start_time();
720 }