1 /****************************************************************************
2 * Small Precludes OpenGL demo
3 *
4 * By Jason Nunn <jsno8192@yahoo.com.au>
5 * (C) Copyright 2000-2003
6 * Darwin, NT, Australia
7 * http://jsno.arafuraconnect.com.au
8 *
9 * =====================================================================
10 * misc stuff
11 *
12 ****************************************************************************/
13 #include "defs.h"
14 #include "protos.p"
15 
16 typedef struct _tex_ll_t
17 {
18   GLuint           id;
19   struct _tex_ll_t *next;
20 } tex_ll_t;
21 
22 PUBLIC int       window_size_x = SCREEN_SIZE_X,
23                  window_size_y = SCREEN_SIZE_Y;
24 
25 PUBLIC void      (*draw_h_hook)(void);
26 PUBLIC void      (*calc_hook)(void);
27 
28 PUBLIC GLfloat   black_pixel[1][3],
29                  white_pixel[8][3],
30                  blue_pixel[8][3],
31                  yellow_pixel[1][3] = {{0.9375, 0.9375, 0.0}},
32                  green_pixel[MAX_SCORE_TABLE][3],
33                  red_pixel[MAX_SCORE_TABLE][3],
34                  intro_haze[2][3] = {{0.0, 0.9, 0.0}, {0.0, 0.35, 0.0}},
35                  purple_pixel[1][3] = {{0.7, 0.1, 8.0}};
36 
37 PUBLIC GLfloat       bm_colour[4] = {1.0, 1.0, 1.0, 1.0},
38                      bm_colour2[4] = {1.0, 1.0, 1.0, 0.6};
39 
40 PUBLIC unsigned int  update_speed = UPDATE_SPEED;
41 
42 PUBLIC char          *console_message[MAX_MESSAGES];
43 PUBLIC float         console_message_alpha_fade;
44 
45 PRIVATE GLdouble     time_start;
46 PRIVATE tex_ll_t     *tex_ll;
47 PRIVATE int          fps_f;
48 PRIVATE Display      *x_display;
49 PRIVATE unsigned int xkb_delay, xkb_rate;
50 
51 /****************************************************************************
52 *
53 ****************************************************************************/
ramp_colour(GLfloat r1,float g1,float b1,GLfloat r2,float g2,float b2,GLfloat * p,int run)54 PUBLIC void ramp_colour(
55   GLfloat r1, float g1, float b1,
56   GLfloat r2, float g2, float b2,
57   GLfloat *p, int run)
58 {
59   int     i, m1, m2;
60   GLfloat rs, gs, bs;
61 
62   p[R] = r1;
63   p[G] = g1;
64   p[B] = b1;
65   i = run - 1;
66   rs = (r2 - r1) / (GLfloat)i;
67   gs = (g2 - g1) / (GLfloat)i;
68   bs = (b2 - b1) / (GLfloat)i;
69 
70   m1 = 3;
71   m2 = 0;
72   for(i = 1; i < run; i++)
73   {
74     p[m1 + R] = p[m2 + R] + rs;
75     p[m1 + G] = p[m2 + G] + gs;
76     p[m1 + B] = p[m2 + B] + bs;
77     m1 += 3;
78     m2 += 3;
79   }
80 }
81 
82 /****************************************************************************
83 *
84 ****************************************************************************/
get_clock(void)85 PUBLIC GLdouble get_clock(void)
86 {
87   struct timeval t;
88 
89   gettimeofday(&t,NULL);
90   return ((GLdouble)t.tv_sec + (0.000001 * (GLdouble)t.tv_usec));
91 }
92 
sync_time_lapse(void)93 PUBLIC void sync_time_lapse(void)
94 {
95   time_start = get_clock();
96 }
97 
get_time_lapse(void)98 PUBLIC GLdouble get_time_lapse(void)
99 {
100   return (get_clock() - time_start) * 32;
101 }
102 
103 /****************************************************************************
104 *
105 ****************************************************************************/
blit_line(int x1,int y1,int x2,int y2)106 PUBLIC void blit_line(int x1, int y1, int x2, int y2)
107 {
108   glDisable(GL_TEXTURE_2D);
109 
110   glBegin(GL_LINES);
111     glVertex2i(x1, y1);
112     glVertex2i(x2, y2);
113   glEnd();
114 
115   glEnable(GL_TEXTURE_2D);
116 }
117 
118 /****************************************************************************
119 *
120 ****************************************************************************/
blit_rect(int x,int y,int size_x,int size_y)121 PUBLIC void blit_rect(int x, int y, int size_x, int size_y)
122 {
123   size_x += x;
124   size_y += y;
125 
126   glDisable(GL_TEXTURE_2D);
127 
128   glBegin(GL_POLYGON);
129     glVertex2i(x, y);
130     glVertex2i(x, size_y);
131     glVertex2i(size_x, size_y);
132     glVertex2i(size_x, y);
133   glEnd();
134 
135   glEnable(GL_TEXTURE_2D);
136 }
137 
138 /****************************************************************************
139 *
140 ****************************************************************************/
blit_rect_hollow(int x,int y,int size_x,int size_y)141 PUBLIC void blit_rect_hollow(int x, int y, int size_x, int size_y)
142 {
143   size_x += x;
144   size_y += y;
145 
146   glDisable(GL_TEXTURE_2D);
147 
148   glBegin(GL_LINE_STRIP);
149     glVertex2i(x, y);
150     glVertex2i(x, size_y);
151     glVertex2i(size_x, size_y);
152     glVertex2i(size_x, y);
153     glVertex2i(x, y);
154   glEnd();
155 
156   glEnable(GL_TEXTURE_2D);
157 }
158 
159 /****************************************************************************
160 *
161 ****************************************************************************/
blit_bm(bm_t * bm,int x,int y)162 PUBLIC void blit_bm(bm_t *bm, int x, int y)
163 {
164   int                  x1, y1;
165   static const GLfloat tc[4][2] =
166     {{0.0, 0.0}, {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}};
167 
168   x1 = x + bm->size_x;
169   y1 = y + bm->size_y;
170 
171   if(x1 < 0 || y1 < 0)
172     return;
173   if(x >= SCREEN_SIZE_X || y >= SCREEN_SIZE_Y)
174     return;
175 
176   glBindTexture(GL_TEXTURE_2D, bm->id);
177   glBegin(GL_POLYGON);
178     glTexCoord2fv(tc[0]);
179     glVertex2i(x, y);
180 
181     glTexCoord2fv(tc[1]);
182     glVertex2i(x, y1);
183 
184     glTexCoord2fv(tc[2]);
185     glVertex2i(x1, y1);
186 
187     glTexCoord2fv(tc[3]);
188     glVertex2i(x1, y);
189   glEnd();
190 }
191 
192 /****************************************************************************
193 *
194 ****************************************************************************/
print_str_len(char * str,int l,int x,int y)195 PUBLIC void print_str_len(char *str, int l, int x, int y)
196 {
197   int i;
198 
199   for(i = 0; i < l; i++)
200   {
201     if(str[i] < 32)
202       continue;
203 
204     blit_bm(&(font_bm[(int)(str[i] - ' ')]), x, y);
205     x += 8;
206   }
207 }
208 
print_str(char * str,int x,int y)209 PUBLIC void print_str(char *str, int x, int y)
210 {
211   print_str_len(str, strlen(str), x, y);
212 }
213 
print_str_hazey(char * str,int x,int y,GLfloat * c1,GLfloat * c2)214 PUBLIC void print_str_hazey(char *str, int x, int y, GLfloat *c1, GLfloat *c2)
215 {
216   glColor3fv(c2);
217   print_str_len(str, strlen(str), x - 1, y);
218   print_str_len(str, strlen(str), x + 1, y);
219   print_str_len(str, strlen(str), x, y - 1);
220   print_str_len(str, strlen(str), x, y + 1);
221 
222   glColor3fv(c1);
223   print_str_len(str, strlen(str), x, y);
224 }
225 
226 /****************************************************************************
227 *
228 ****************************************************************************/
display_message(char * s,int y)229 PUBLIC void display_message(char *s, int y)
230 {
231   int  l;
232   char *s1;
233 
234   for(;;)
235   {
236     if(*s == '\0')
237       return;
238 
239     s1 = strchr(s, '\n');
240     if(s1 == NULL)
241       return;
242 
243     l = (int)(s1 - s);
244     if(l)
245       print_str_len(s, l, SCREEN_HSIZE_X - ((l << 3) >> 1), y);
246     y += 16;
247     s = s1 + 1;
248   }
249 }
250 
251 /****************************************************************************
252 * tex management
253 ****************************************************************************/
append_tex(GLuint id)254 PUBLIC void append_tex(GLuint id)
255 {
256   tex_ll_t *t;
257 
258   t = tex_ll;
259   tex_ll = (tex_ll_t *)alloc_mem(sizeof(tex_ll_t));
260   tex_ll->id = id;
261   tex_ll->next = t;
262 }
263 
delete_tex(GLuint id)264 PUBLIC void delete_tex(GLuint id)
265 {
266   tex_ll_t *p, *t;
267 
268   p = tex_ll;
269   for(;;)
270   {
271     if(p == NULL)
272       break;
273 
274     if(p->id == id)
275     {
276       glDeleteTextures(1, &(p->id));
277 
278       p->id = p->next->id;
279       t = p->next;
280       p->next = p->next->next;
281       free(t);
282     }
283 
284     p = p->next;
285   }
286 }
287 
free_textures(void)288 PUBLIC void free_textures(void)
289 {
290   tex_ll_t *p;
291 
292   printf("Freeing Textures.\n");
293 
294   p = tex_ll;
295   for(;;)
296   {
297     if(p == NULL)
298       break;
299 
300     glDeleteTextures(1, &(p->id));
301 
302     p = p->next;
303   }
304 }
305 
306 /****************************************************************************
307 *
308 ****************************************************************************/
convert_2_tex(GLubyte * buf,bm_t * bm,int aligned_f)309 PUBLIC void convert_2_tex(GLubyte *buf, bm_t *bm, int aligned_f)
310 {
311   glGenTextures(1, &(bm->id));
312   if(!bm->id)
313   {
314     fprintf(stderr, "convert_2_tex()::glGenTextures(): Error.\n");
315     end_game(-1);
316   }
317   glBindTexture(GL_TEXTURE_2D, bm->id);
318 
319 /* Set texture parameters */
320   if(aligned_f)
321   {
322     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
323     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
324   }
325   else
326   {
327     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
328     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
329   }
330 
331   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
332   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
333   glTexEnvi(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
334 
335   if(aligned_f)
336     glTexImage2D(GL_TEXTURE_2D, 0, 4, bm->size_x, bm->size_y,
337       0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
338   else
339     gluBuild2DMipmaps(GL_TEXTURE_2D, 4, bm->size_x, bm->size_y,
340       GL_RGBA, GL_UNSIGNED_BYTE, buf);
341 
342   append_tex(bm->id);
343 }
344 
345 /****************************************************************************
346 *
347 ****************************************************************************/
console_message_add(char * str)348 PUBLIC void console_message_add(char *str)
349 {
350   int x;
351 
352   if(console_message[0] != NULL)
353     free(console_message[0]);
354 
355   for(x = 0; x < (MAX_MESSAGES - 1); x++)
356     console_message[x] = console_message[x + 1];
357 
358   console_message[MAX_MESSAGES - 1] = (char *)alloc_mem(strlen(str) + 1);
359   strcpy(console_message[MAX_MESSAGES - 1], str);
360   console_message_alpha_fade = 0.8;
361 }
362 
console_message_display(void)363 PUBLIC void console_message_display(void)
364 {
365   int x;
366 
367   if(console_message_alpha_fade < 0.0)
368     return;
369 
370   glColor4f(0.0, 1.0, 0.0, console_message_alpha_fade);
371 
372   for(x = 0; x < MAX_MESSAGES; x++)
373   {
374     if(console_message[x] == NULL)
375       continue;
376 
377     print_str(
378       console_message[x],
379       SCREEN_SIZE_X - (strlen(console_message[x]) << 3),
380       (SCREEN_SIZE_Y - 80) + (x << 4));
381   }
382 }
383 
console_message_free(void)384 PUBLIC void console_message_free(void)
385 {
386   int x;
387 
388   for(x = 0; x < MAX_MESSAGES; x++)
389     if(console_message[x] != NULL)
390     {
391       free(console_message[x]);
392       console_message[x] = NULL;
393     }
394 }
395 
396 /****************************************************************************
397 *
398 ****************************************************************************/
on_exit_h()399 PRIVATE void on_exit_h()
400 {
401   free_textures();
402 
403   printf("See ya\n");
404 }
405 
406 /*
407  * have to have this as XkbSetAutoRepeatRate() doesn't work after exit
408  * called
409  */
end_game(int code)410 PUBLIC void end_game(int code)
411 {
412   if(x_display != NULL)
413   {
414     printf("Resetting X keyboard.\n");
415     XkbSetAutoRepeatRate(x_display, XkbUseCoreKbd, xkb_delay, xkb_rate);
416   }
417 
418   exit(code);
419 }
420 
421 /****************************************************************************
422 *
423 ****************************************************************************/
mouse_aspect(int v,int w,int r)424 PRIVATE inline int mouse_aspect(int v, int w, int r)
425 {
426   return v * r / w;
427 }
428 
keyboard_h(unsigned char key,int x,int y)429 PRIVATE void keyboard_h(unsigned char key, int x, int y)
430 {
431   switch(key)
432   {
433     case 27:
434       end_game(0);
435 
436     case KEY_FPS:
437         fps_f ^= 1;
438       break;
439 
440     case KEY_REDUCED:
441         reduced_f ^= 1;
442       break;
443 
444     default:
445     {
446       tkevent k;
447 
448       k.type    = KEYBOARD_EVENT;
449       k.val     = key;
450       k.mouse_x = mouse_aspect(x, window_size_x, 320);
451       k.mouse_y = mouse_aspect(y, window_size_y, 200);
452       put_kb_event(&k);
453       break;
454     }
455   }
456 }
457 
special_h(int key,int x,int y)458 PRIVATE void special_h(int key, int x, int y)
459 {
460   tkevent k;
461 
462   k.type    = SPECIAL_EVENT;
463   k.val     = (unsigned int)key;
464   k.mouse_x = mouse_aspect(x, window_size_x, 320);
465   k.mouse_y = mouse_aspect(y, window_size_y, 200);
466   put_kb_event(&k);
467 }
468 
mouse_h(int button,int state,int x,int y)469 PRIVATE void mouse_h(int button, int state, int x, int y)
470 {
471   tkevent k;
472 
473   if(!state)
474     return;
475 
476   k.type    = MOUSE_EVENT;
477   k.val     = button;
478   k.mouse_x = mouse_aspect(x, window_size_x, 320);
479   k.mouse_y = mouse_aspect(y, window_size_y, 200);
480   put_kb_event(&k);
481 }
482 
483 /****************************************************************************
484 *
485 ****************************************************************************/
timer_h(int value)486 PRIVATE void timer_h(int value)
487 {
488   glutPostRedisplay();
489   glutTimerFunc(update_speed, timer_h, 1);
490 }
491 
492 /****************************************************************************
493 *
494 ****************************************************************************/
resize_h(int w,int h)495 PRIVATE void resize_h(int w, int h)
496 {
497   window_size_x = w;
498   window_size_y = h;
499 
500 /*Prevent a divide by zero*/
501   if(h == 0)
502     h = 1;
503 
504 /*Set Viewport to window dimensions*/
505   glViewport(0, 0, w, h);
506 
507   glMatrixMode(GL_PROJECTION);
508   glLoadIdentity();
509 
510 /*clipping volume*/
511   glOrtho(0.0, SCREEN_SIZE_X, SCREEN_SIZE_Y, 0.0, 1.0, -1.0);
512 
513   glMatrixMode(GL_MODELVIEW);
514   glLoadIdentity();
515 }
516 
517 /****************************************************************************
518 *
519 ****************************************************************************/
main_draw_h(void)520 PRIVATE void main_draw_h(void)
521 {
522   static int    frame_count;
523   static double old_clock;
524   double        x;
525   static char   str[40],
526                 *mess = "You fucking cheat !\n";
527 
528   if(fps_f)
529   {
530     if((frame_count % 50) == 0)
531     {
532       x = get_clock();
533       sprintf(str, "%.2f fps", 50 / (x - old_clock));
534       old_clock = x;
535     }
536     frame_count++;
537   }
538 
539   glClear(GL_COLOR_BUFFER_BIT);
540 
541   glEnable(GL_BLEND);
542   glEnable(GL_TEXTURE_2D);
543 
544     if(draw_h_hook != NULL)
545       draw_h_hook();
546 
547   if(fps_f)
548   {
549     glColor4f(1.0, 1.0, 1.0, 0.5);
550     print_str(str, 0, 184);
551   }
552 
553   if(god_mode)
554   {
555     glColor4fv(bm_colour);
556     display_message(mess, 50);
557     display_message(mess, 120);
558   }
559 
560   glDisable(GL_TEXTURE_2D);
561   glDisable(GL_BLEND);
562 
563   glutSwapBuffers();
564 
565  /*
566   * do calc
567   */
568   if(calc_hook != NULL)
569     calc_hook();
570   sync_time_lapse();
571 }
572 
573 /****************************************************************************
574 *
575 ****************************************************************************/
opengl_init(int argc,char * argv[],int mode)576 PUBLIC void opengl_init(int argc, char *argv[], int mode)
577 {
578   int x, fs_f = 0;
579 
580   atexit(on_exit_h);
581   glutInit(&argc, argv);
582   glutInitDisplayMode(mode);
583 
584   window_size_x = 640;
585   window_size_y = 480;
586 
587   for(x = 1; x < argc; x++)
588   {
589     if(argv[x][0] == '-')
590     {
591       switch(argv[x][1])
592       {
593         case '3':
594           window_size_x = 320;
595           window_size_y = 200;
596           printf("320x200 mode.\n");
597           break;
598 
599         case '6':
600           window_size_x = 640;
601           window_size_y = 480;
602           printf("640x480 mode.\n");
603           break;
604 
605         case '1':
606           window_size_x = 1024;
607           window_size_y = 768;
608           printf("1024x768 mode.\n");
609           break;
610 
611         case 'f':
612           window_size_x = 320;
613           window_size_y = 200;
614           fs_f = 1;
615           printf("Full screen mode.\n");
616           break;
617       }
618     }
619   }
620 
621   glutInitWindowSize(window_size_x, window_size_y);
622   glutCreateWindow("Nighthawk " VERSION);
623 
624   glutKeyboardFunc(keyboard_h);
625   glutSpecialFunc(special_h);
626   glutMouseFunc(mouse_h);
627 
628   glutTimerFunc(update_speed, timer_h, 1);
629   glutReshapeFunc(resize_h);
630   glutDisplayFunc(main_draw_h);
631 
632   if(fs_f)
633     glutFullScreen();
634 
635   glutSetCursor(GLUT_CURSOR_CROSSHAIR);
636 
637   glShadeModel(GL_SMOOTH);
638   glFrontFace(GL_CCW);
639   glDepthFunc(GL_LEQUAL);
640   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
641   glDisable(GL_LIGHTING);
642 
643   glClearColor(0.0, 0.0, 0.0, 1.0);
644 
645   x_display = glXGetCurrentDisplay();
646   if(x_display != NULL)
647   {
648     XkbGetAutoRepeatRate(x_display, XkbUseCoreKbd, &xkb_delay, &xkb_rate);
649     XkbSetAutoRepeatRate(x_display, XkbUseCoreKbd, 200, 33);
650   }
651 }
652