Round 3: Some minor cross-platform compatibility changes (FreeBSD), still may not...
[theoddone33/hhexen.git] / svgalib / i_svgalib.c
1 //**************************************************************************
2 //**
3 //** $Id$
4 //**
5 //**************************************************************************
6
7
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <sys/time.h>
11
12 #include <vga.h>           // SVGALib includes
13 #include <vgakeyboard.h>
14 #include <vgamouse.h>
15
16 #include <unistd.h>    /* jim - usleep () */
17
18 #include <unistd.h>    /* jim - usleep () */
19
20 #include "h2def.h"
21 #include "r_local.h"
22 #include "p_local.h"    // for P_AproxDistance
23 #include "sounds.h"
24 #include "i_sound.h"
25 #include "soundst.h"
26 #include "st_start.h"
27
28 static enum {F_nomouse, F_mouse} mflag = F_nomouse;
29
30 // Macros
31
32 #define SEQ_ADDR 0x3C4
33 #define SEQ_DATA 0x3C5
34 #define REG_MAPMASK 0x02
35
36 #define MASK_PLANE0 0x01
37 #define MASK_PLANE1 0x02
38 #define MASK_PLANE2 0x04
39 #define MASK_PLANE3 0x08
40
41 #define P0OFFSET 38400*0
42 #define P1OFFSET 38400*1
43 #define P2OFFSET 38400*2
44 #define P3OFFSET 38400*3
45
46 #define VID_INT 0x10
47 #define VB_SYNC
48 #define BITPLANE(p)
49
50 #define KEY_LSHIFT      0xfe
51
52 #define KEY_INS         (0x80+0x52)
53 #define KEY_DEL         (0x80+0x53)
54 #define KEY_PGUP        (0x80+0x49)
55 #define KEY_PGDN        (0x80+0x51)
56 #define KEY_HOME        (0x80+0x47)
57 #define KEY_END         (0x80+0x4f)
58
59 // Public Data
60
61 int DisplayTicker = 0;
62
63
64 void I_ReadMouse (void);
65
66 extern  int usemouse;
67
68
69 //==================================================
70
71 #define VBLCOUNTER              34000           // hardware tics to a frame
72
73 #define MOUSEB1 1
74 #define MOUSEB2 2
75 #define MOUSEB3 4
76
77 boolean mousepresent;
78
79 //===============================
80
81 extern int ticcount;
82
83 extern boolean novideo; // if true, stay in text mode for debugging
84
85 #define KBDQUESIZE 32
86 byte keyboardque[KBDQUESIZE];
87 int kbdtail, kbdhead;
88
89
90 #define SC_RSHIFT       0x36
91 #define SC_LSHIFT       0x2a
92
93 byte        scantokey[128] =
94                                         {
95 //  0           1       2       3       4       5       6       7
96 //  8           9       A       B       C       D       E       F
97         0  ,    27,     '1',    '2',    '3',    '4',    '5',    '6',
98         '7',    '8',    '9',    '0',    '-',    '=',    KEY_BACKSPACE, 9, // 0
99         'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
100         'o',    'p',    '[',    ']',    13 ,    KEY_RCTRL,'a',  's',      // 1
101         'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
102         39 ,    '`',    KEY_LSHIFT,92,  'z',    'x',    'c',    'v',      // 2
103         'b',    'n',    'm',    ',',    '.',    '/',    KEY_RSHIFT,'*',
104         KEY_RALT,' ',   0  ,    KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5,   // 3
105         KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10,0  ,    0  , KEY_HOME,
106         KEY_UPARROW,KEY_PGUP,'-',KEY_LEFTARROW,'5',KEY_RIGHTARROW,'+',KEY_END, //4
107         KEY_DOWNARROW,KEY_PGDN,KEY_INS,KEY_DEL,0,0,             0,              KEY_F11,
108         KEY_F12,0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 5
109         0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
110         0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,        // 6
111         0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0,
112         0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0  ,    0         // 7
113                                         };
114
115 //==========================================================================
116
117
118 /*
119 ============================================================================
120
121                                                                 USER INPUT
122
123 ============================================================================
124 */
125
126 //--------------------------------------------------------------------------
127 //
128 // PROC I_WaitVBL
129 //
130 //--------------------------------------------------------------------------
131
132 void I_WaitVBL(int vbls)
133 {
134         if( novideo )
135         {
136                 return;
137         }
138         while( vbls-- )
139         {
140         usleep( 16667 );
141         }
142 }
143
144 //--------------------------------------------------------------------------
145 //
146 // PROC I_SetPalette
147 //
148 // Palette source must use 8 bit RGB elements.
149 //
150 //--------------------------------------------------------------------------
151 void I_SetPalette(byte *palette)
152 {
153    register int* buf = NULL;
154    register short count = 256 / 2;
155    register int* p;
156    register unsigned char* gtable = gammatable[usegamma];
157
158    if(novideo)
159         {
160                 return;
161         }
162         I_WaitVBL(1);
163    
164    //Code lynched from Collin Phipps' lsdoom
165    p = buf = Z_Malloc(256 * 3 * sizeof(int),PU_STATIC,NULL);
166    do {  
167        //One RGB Triple
168       p[0]=gtable[palette[0]] >> 2;
169       p[1]=gtable[palette[1]] >> 2;
170       p[2]=gtable[palette[2]] >> 2;
171       //And another
172       p[3]=gtable[palette[3]] >> 2;
173       p[4]=gtable[palette[4]] >> 2;
174       p[5]=gtable[palette[5]] >> 2;
175       
176       p+=6; palette+=6;
177    } while (--count);
178    if(vga_oktowrite())
179      vga_setpalvec(0,256,buf);
180    
181    Z_Free(buf);
182 }
183 /*
184 ============================================================================
185
186                                                         GRAPHICS MODE
187
188 ============================================================================
189 */
190
191 //byte *pcscreen;
192 byte  *destscreen, *destview;
193
194 /*
195 ==============
196 =
197 = I_Update
198 =
199 ==============
200 */
201
202 int UpdateState;
203 extern int screenblocks;
204
205 void I_Update (void)
206 {
207         int i;
208         byte *dest;
209         int tics;
210         static int lasttic;
211
212 //
213 // blit screen to video
214 //
215         if(DisplayTicker) //Displays little dots in corner
216         {
217            if(screenblocks > 9 || UpdateState&(I_FULLSCRN|I_MESSAGES))
218              {  
219              dest = (byte *)screen;
220              }
221            else
222            {
223               dest = (byte*)graph_mem;
224            }
225                 tics = ticcount-lasttic;
226                 lasttic = ticcount;
227                 if(tics > 20) tics = 20;
228                 for(i = 0; i < tics; i++)
229                 {
230                    *dest = 0xff;
231                    dest += 2; 
232                 }
233                 for(i = tics; i < 20; i++)
234                 {
235                    *dest = 0x00;
236                    dest += 2;
237                 }
238         }
239
240         //memset(pcscreen, 255, SCREENHEIGHT*SCREENWIDTH);
241
242         if(UpdateState == I_NOUPDATE)
243         {
244                 return;
245         }
246         if(UpdateState&I_FULLSCRN)
247         {
248            memcpy(graph_mem, screen, SCREENWIDTH*SCREENHEIGHT);
249            UpdateState = I_NOUPDATE; // clear out all draw types
250
251         }
252         if(UpdateState&I_FULLVIEW)
253         {
254                 if(UpdateState&I_MESSAGES && screenblocks > 7)
255                 {
256                    for(i = 0; i < (viewwindowy+viewheight)*SCREENWIDTH; 
257                        i += SCREENWIDTH)
258                         {       
259                            memcpy(graph_mem+i, screen+i, SCREENWIDTH);
260                         } 
261                    
262                         UpdateState &= ~(I_FULLVIEW|I_MESSAGES);
263                 }
264                 else
265                 {
266                    for(i = viewwindowy*SCREENWIDTH+viewwindowx; i <
267                                 (viewwindowy+viewheight)*SCREENWIDTH; i += SCREENWIDTH)
268                         {
269                                 memcpy(graph_mem+i, screen+i, viewwidth);
270                         }
271                    UpdateState &= ~I_FULLVIEW;
272                 }
273         }
274         if(UpdateState&I_STATBAR)
275         {
276                 memcpy(graph_mem+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
277                         screen+SCREENWIDTH*(SCREENHEIGHT-SBARHEIGHT),
278                         SCREENWIDTH*SBARHEIGHT);
279                 UpdateState &= ~I_STATBAR;
280         }
281         if(UpdateState&I_MESSAGES)
282         {
283                 memcpy(graph_mem, screen, SCREENWIDTH*28);
284                 UpdateState &= ~I_MESSAGES;
285         }
286 }
287
288 //-----------------------------------------------------------------------------
289 //
290 // PROC I_KeyboardHandler()
291 //
292 //-----------------------------------------------------------------------------
293
294 static void I_KeyboardHandler(int scancode, int press)
295 {
296    event_t ev;
297    
298    ev.type = (press == KEY_EVENTPRESS) ? ev_keydown : ev_keyup;
299    switch (scancode) {
300     case SCANCODE_CURSORBLOCKUP:
301     case SCANCODE_CURSORUP: ev.data1 = KEY_UPARROW; break;
302     case SCANCODE_CURSORBLOCKDOWN:
303     case SCANCODE_CURSORDOWN: ev.data1 = KEY_DOWNARROW; break;
304     case SCANCODE_CURSORBLOCKLEFT:
305     case SCANCODE_CURSORLEFT: ev.data1 = KEY_LEFTARROW; break;
306     case SCANCODE_CURSORBLOCKRIGHT:
307     case SCANCODE_CURSORRIGHT: ev.data1 = KEY_RIGHTARROW; break;
308     case SCANCODE_ESCAPE: ev.data1 = KEY_ESCAPE; break;
309     case SCANCODE_ENTER:
310     case SCANCODE_KEYPADENTER: ev.data1 = KEY_ENTER; break;
311     case SCANCODE_F1: ev.data1 = KEY_F1; break;
312     case SCANCODE_F2: ev.data1 = KEY_F2; break;
313     case SCANCODE_F3: ev.data1 = KEY_F3; break;
314     case SCANCODE_F4: ev.data1 = KEY_F4; break;
315     case SCANCODE_F5: ev.data1 = KEY_F5; break;
316     case SCANCODE_F6: ev.data1 = KEY_F6; break;
317     case SCANCODE_F7: ev.data1 = KEY_F7; break;
318     case SCANCODE_F8: ev.data1 = KEY_F8; break;
319     case SCANCODE_F9: ev.data1 = KEY_F9; break;
320     case SCANCODE_F10: ev.data1 = KEY_F10; break;
321     case SCANCODE_F11: ev.data1 = KEY_F11; break;
322     case SCANCODE_F12: ev.data1 = KEY_F12; break;
323     case SCANCODE_INSERT: ev.data1 = KEY_INS; break;
324     case SCANCODE_REMOVE: ev.data1 = KEY_DEL; break;
325     case SCANCODE_PAGEUP: ev.data1 = KEY_PGUP; break;
326     case SCANCODE_PAGEDOWN: ev.data1 = KEY_PGDN; break;
327     case SCANCODE_HOME: ev.data1 = KEY_HOME; break;
328     case SCANCODE_END: ev.data1 = KEY_END; break;
329     case SCANCODE_BACKSPACE: ev.data1 = KEY_BACKSPACE; break;
330     case SCANCODE_BREAK:
331     case SCANCODE_BREAK_ALTERNATIVE: ev.data1 = KEY_PAUSE; break;
332     case SCANCODE_EQUAL: ev.data1 = KEY_EQUALS; break;
333     case SCANCODE_MINUS:
334     case SCANCODE_KEYPADMINUS: ev.data1 = KEY_MINUS; break;
335     case SCANCODE_LEFTSHIFT:
336     case SCANCODE_RIGHTSHIFT: ev.data1 = KEY_RSHIFT; break;
337     case SCANCODE_LEFTCONTROL:
338     case SCANCODE_RIGHTCONTROL: ev.data1 = KEY_RCTRL; break;
339     case SCANCODE_LEFTALT:
340     case SCANCODE_RIGHTALT: ev.data1 = KEY_RALT; break;
341     default: ev.data1 = scantokey[scancode]; break;
342    }
343    H2_PostEvent(&ev);
344 }
345
346 //-----------------------------------------------------------------------------
347 //
348 // PROC I_MouseEventHandler()
349 //
350 //-----------------------------------------------------------------------------
351
352 static void I_MouseEventHandler(int button, int dx, int dy, int dz,
353                               int rdx, int rdy, int rdz)
354 {
355    event_t ev;
356    
357    ev.type = ev_mouse;
358    ev.data1 = ((button & MOUSE_LEFTBUTTON) ? 1 : 0) |
359               ((button & MOUSE_MIDDLEBUTTON) ? 2 : 0) |
360               ((button & MOUSE_LEFTBUTTON) ? 4 : 0);
361    ev.data2 = dx << 2; ev.data3 = -(dy<<2);
362    
363    H2_PostEvent(&ev);
364 }
365
366 //--------------------------------------------------------------------------
367 //
368 // PROC I_ShutdownGraphics
369 //
370 //--------------------------------------------------------------------------
371
372 void I_ShutdownGraphics(void)
373 {
374    if(mflag != F_nomouse) vga_setmousesupport(0);
375    keyboard_close();
376    vga_setmode(TEXT);
377    system("stty sane");
378 }
379
380 //--------------------------------------------------------------------------
381 //
382 // PROC I_InitGraphics
383 //
384 //--------------------------------------------------------------------------
385
386 void I_InitGraphics(void)
387 {
388    ST_Message("I_InitGraphics: ");
389    vga_init();
390    
391    atexit(I_ShutdownGraphics);
392    
393    keyboard_init();
394    keyboard_seteventhandler(I_KeyboardHandler);
395    
396    if(!M_CheckParm("-nomouse")) {
397       vga_setmousesupport(1);
398       mflag = F_mouse;
399    }
400    
401    if(!vga_hasmode(G320x200x256))
402       I_Error("SVGALib reports no mode 13h");
403    putc('\n',stderr); 
404    
405    if(vga_setmode(G320x200x256))
406      I_Error("Can't set video mode 13h");
407    
408    I_SetPalette( W_CacheLumpName("PLAYPAL", PU_CACHE) );
409
410    if(mflag == F_mouse) mouse_seteventhandler(I_MouseEventHandler);
411 }
412
413
414 //--------------------------------------------------------------------------
415 //
416 // PROC I_ReadScreen
417 //
418 // Reads the screen currently displayed into a linear buffer.
419 //
420 //--------------------------------------------------------------------------
421
422 /*
423 void I_ReadScreen(byte *scr)
424 {
425         memcpy(scr, screen, SCREENWIDTH*SCREENHEIGHT);
426 }
427 */
428
429 //===========================================================================
430
431 void   I_StartTic (void)
432 {
433    if(mflag != F_nomouse) mouse_update();
434    keyboard_update();
435 }
436
437
438 /*
439 void   I_ReadKeys (void)
440 {
441         int             k;
442
443
444         while (1)
445         {
446            while (kbdtail < kbdhead)
447            {
448                    k = keyboardque[kbdtail&(KBDQUESIZE-1)];
449                    kbdtail++;
450                    printf ("0x%x\n",k);
451                    if (k == 1)
452                            I_Quit ();
453            }
454         }
455 }
456 */
457
458
459 /*
460 ============================================================================
461
462                                                 KEYBOARD
463
464 ============================================================================
465 */
466
467 int lastpress;
468
469 /*
470 ================
471 =
472 = I_KeyboardISR
473 =
474 ================
475 */
476
477 void I_KeyboardISR(void)
478 {
479 // Get the scan code
480
481         keyboardque[kbdhead&(KBDQUESIZE-1)] = lastpress = 0;  //TODO
482         kbdhead++;
483 }
484
485
486
487 /*
488 ===============
489 =
490 = I_StartupKeyboard
491 =
492 ===============
493 */
494
495 void I_StartupKeyboard (void)
496 {
497     //TODO
498 }
499
500
501 void I_ShutdownKeyboard (void)
502 {
503     //TODO
504 }
505
506
507
508 /*
509 ============================================================================
510
511                                                         MOUSE
512
513 ============================================================================
514 */
515
516
517 int I_ResetMouse (void)
518 {
519     // Return 0xffff if mouse reset ok.
520     return 0;
521 }
522
523
524
525 /*
526 ================
527 =
528 = StartupMouse
529 =
530 ================
531 */
532
533 void I_StartupCyberMan(void);
534
535 void I_StartupMouse (void)
536 {
537    //
538    // General mouse detection
539    //
540         mousepresent = 0;
541         if ( M_CheckParm ("-nomouse") || !usemouse )
542                 return;
543
544         if (I_ResetMouse () != 0xffff)
545         {
546                 ST_Message("Mouse: not present\n");
547                 return;
548         }
549         ST_Message("Mouse: detected\n");
550
551         mousepresent = 1;
552
553         I_StartupCyberMan();
554 }
555
556
557 /*
558 ================
559 =
560 = ShutdownMouse
561 =
562 ================
563 */
564
565 void I_ShutdownMouse (void)
566 {
567         if (!mousepresent)
568           return;
569
570         I_ResetMouse ();
571 }
572
573
574 /*
575 ================
576 =
577 = I_ReadMouse
578 =
579 ================
580 */
581
582 void I_ReadMouse (void)
583 {
584 #if 0
585         event_t ev;
586
587 //
588 // mouse events
589 //
590         if (!mousepresent)
591                 return;
592
593         ev.type = ev_mouse;
594
595         memset (&dpmiregs,0,sizeof(dpmiregs));
596         dpmiregs.eax = 3;                               // read buttons / position
597         DPMIInt (0x33);
598         ev.data1 = dpmiregs.ebx;
599
600         dpmiregs.eax = 11;                              // read counters
601         DPMIInt (0x33);
602         ev.data2 = (short)dpmiregs.ecx;
603         ev.data3 = -(short)dpmiregs.edx;
604
605         H2_PostEvent (&ev);
606 #endif
607 }
608
609
610 //==========================================================================
611 //
612 //
613 // I_StartupReadKeys
614 //
615 //
616 //==========================================================================
617
618 void I_StartupReadKeys(void)
619 {
620         int k;
621
622    while (kbdtail < kbdhead)
623    {
624            k = keyboardque[kbdtail&(KBDQUESIZE-1)];
625            kbdtail++;
626            if (k == 1)
627                    I_Quit ();
628    }
629 }
630
631
632 //EOF