1 /** ADAMEm: Coleco ADAM emulator ********************************************/
2 /**                                                                        **/
3 /**                                 MSDOS.c                                **/
4 /**                                                                        **/
5 /** This file contains generic MS-DOS specific routines. It does not       **/
6 /** include the sound emulation code                                       **/
7 /**                                                                        **/
8 /** Copyright (C) Marcel de Kogel 1996,1997,1998,1999                      **/
9 /**     You are not allowed to distribute this software commercially       **/
10 /**     Please, notify me, if you make any changes to this file            **/
11 /****************************************************************************/
12 
13 #include "Coleco.h"
14 #include "MSDOS.h"
15 #include "Bitmap.h"
16 #include "INT.h"
17 #include "Asm.h"
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <sys/time.h>
24 #include <sys/farptr.h>
25 #include <go32.h>
26 #include <dpmi.h>
27 #include <pc.h>
28 #include <dos.h>
29 #include <crt0.h>
30 #include <math.h>
31 #include <conio.h>
32 
33 /* Title for -help output */
34 char Title[]="ADAMEm MS-DOS 1.0";
35 
36 #define NUM_STACKS      8         /* Number of IRQ stacks                   */
37 #define STACK_SIZE      16384     /* Stack size                             */
38 
39 /* DJGPP startup flags */
40 int _crt0_startup_flags = _CRT0_FLAG_NONMOVE_SBRK | _CRT0_FLAG_LOCK_MEMORY;
41 
42 /* Key mapping */
43 static int KEY_LEFT,KEY_RIGHT,KEY_UP,KEY_DOWN,
44            KEY_BUTTONA,KEY_BUTTONB,KEY_BUTTONC,KEY_BUTTOND;
45 
46 /* Current VGA palette */
47 static byte VGA_Palette[17*3];
48 
49 static byte PalBuf[16];           /* Palette buffer                         */
50 static int default_mouse_sens=200;/* Default mouse sensitivity              */
51 static int keyboardmode;          /* 0=joystick, 1=keyboard                 */
52 static word MouseJoyState[2];     /* Current mouse status                   */
53 static word JoystickJoyState[2];  /* Current joystick status                */
54 static int nOldVideoMode;         /* Videomode when ADAMem was started      */
55 static unsigned font2screen[16*16*16];
56                                   /* Used by screen refresh driver          */
57 #ifdef DEBUG
58 static int dumpram=0;
59 #endif
60 static int makeshot=0;            /* 1 if screen shot should be taken       */
61 static int makesnap=0;            /* 1 if snapshot should be written        */
62 static int OldTimer=0;            /* Last value of timer                    */
63 static int NewTimer=0;            /* New value of timer                     */
64 static int calloptions=0;         /* If 1, OptionsDialogue() is called      */
65 static int in_options_dialogue=0; /* If 1, chain to old keyboard IRQ handler*/
66 static int SwitchVideoMode=0;     /* If 1, switch video mode in Keyboard()  */
67 
68 word cs_alias;                    /* Our data selector                      */
69 word DosSelector;                 /* Selector of DOS memory                 */
70 byte DisplayBuf[WIDTH*HEIGHT];    /* Screen buffer                          */
71 char szBitmapFile[256];           /* Next screen shot file                  */
72 char szSnapshotFile[256];         /* Next snapshot file                     */
73 char szJoystickFileName[256];     /* File holding joystick information      */
74 char *szKeys="CBCDC8D0381D2A2C";  /* Key scancodes                          */
75 int  mouse_sens=200;              /* Mouse sensitivity                      */
76 int  keypadmode=0;                /* 1 if keypad should be reversed         */
77 int  joystick=1;                  /* Joystick support                       */
78 int  calibrate=0;                 /* Set to 1 to force joystick calibration */
79 int  swapbuttons=0;               /* 1=joystick, 2=keyboard, 4=mouse        */
80 int  expansionmode=0;             /* Expansion module emulated              */
81 int  useoverscan=1;               /* Overscan colour support                */
82 int  videomode=0;                 /* 0=320x200   1=256x192                  */
83 int  syncemu=1;                   /* 0 - Don't sync emulation               */
84                                   /* 1 - Sync emulation to PC timer         */
85 int Text80;                       /* 1 if in Text80 mode                    */
86 int Text80Colour;                 /* Text80 foreground colour               */
87 int AutoText80;                   /* 1 if auto-switch to Text80 mode on     */
88 
89 /****************************************************************************/
90 /** VGA routines                                                           **/
91 /****************************************************************************/
VGA_SetPalette(int n,unsigned char * pal)92 static void VGA_SetPalette (int n,unsigned char *pal)
93 {
94  int i;
95  __disable ();
96  while ((inportb(0x3DA)&0x08)!=0);/* Wait until vertical retrace is off     */
97  while ((inportb(0x3DA)&0x08)==0);/* Now wait until it is on                */
98  outportb (0x3C8,0);              /* Start updating palette                 */
99  for (i=0;i<n*3;++i)
100   outportb(0x3C9,pal[i]/4);
101  __enable ();
102 }
103 
VGA_Reset(void)104 static void VGA_Reset (void)      /* Reset old video mode                   */
105 {
106  __dpmi_regs r;
107  r.x.ax=(short)nOldVideoMode;
108  __dpmi_int (0x10, &r);
109 }
110 
VGA_SetTweakMode(int mode)111 static void VGA_SetTweakMode (int mode)
112 {
113  static const byte crtc_regs_1[25]=
114  {
115   0x63,
116   0x4F,0x3F,0x40,0x92,
117   0x44,0x10,0xAF,0x1F,
118   0x00,0x41,0x00,0x00,
119   0x00,0x00,0x00,0x00,
120   0x8C,0x8E,0x7F,0x20,
121   0x40,0x86,0xA9,0xA3
122  };
123  static const byte crtc_regs_2[25]=
124  {
125   0xE3,
126   0x4F,0x3F,0x40,0x92,
127   0x44,0x10,0x0D,0x3E,
128   0x00,0x41,0x00,0x00,
129   0x00,0x00,0x00,0x00,
130   0xEA,0xAC,0xDF,0x20,
131   0x40,0xE7,0x06,0xA3
132  };
133  static const char *crtc_regs;
134  int i;
135  crtc_regs=(mode)? crtc_regs_2 : crtc_regs_1;
136  __disable ();
137  while (inportb(0x3DA)&8);
138  while ((inportb(0x3DA)&8)==0);
139  outportw (0x3C4,0x100);          /* sequencer reset                        */
140  outportb (0x3C2,*crtc_regs++);   /* misc. output reg                       */
141  outportw (0x3C4,0x300);          /* clear sequencer reset                  */
142  outportw (0x3D4,((crtc_regs[0x11]&0x7F)<<8)+0x11); /* deprotect regs 0-7   */
143  for (i=0;i<24;++i)
144   outportw (0x3D4,(crtc_regs[i]<<8)+i);
145  __enable ();
146 }
147 
VGA_SetBkColour(unsigned char colour)148 static void VGA_SetBkColour (unsigned char colour)
149 {
150  static int currbkcol=-1;
151  if (currbkcol==colour)
152   return;
153  currbkcol=colour;
154  VGA_Palette[0]=VGA_Palette[3]=Coleco_Palette[colour*3+0];
155  VGA_Palette[1]=VGA_Palette[4]=Coleco_Palette[colour*3+1];
156  VGA_Palette[2]=VGA_Palette[5]=Coleco_Palette[colour*3+2];
157  __disable ();
158  while (inportb(0x3DA)&8);
159  while ((inportb(0x3DA)&8)==0);
160  if (useoverscan || Text80)
161  {
162   outportb (0x3C8,0);
163   outportb (0x3C9,VGA_Palette[0]/4);
164   outportb (0x3C9,VGA_Palette[1]/4);
165   outportb (0x3C9,VGA_Palette[2]/4);
166  }
167  if (!Text80)
168  {
169   outportb (0x3C8,1);
170   outportb (0x3C9,VGA_Palette[3]/4);
171   outportb (0x3C9,VGA_Palette[4]/4);
172   outportb (0x3C9,VGA_Palette[5]/4);
173  }
174  __enable ();
175 }
176 
VGA_Init(void)177 static int VGA_Init (void)        /* Get old mode and set mode 13h          */
178 {
179  __dpmi_regs r;
180  r.x.ax=0x0F00;
181  __dpmi_int (0x10,&r);
182  nOldVideoMode=(int)(r.h.al & 0x7F);
183  r.x.ax=0x0013;
184  __dpmi_int (0x10,&r);
185  if (videomode)
186   VGA_SetTweakMode (videomode-1);
187  VGA_SetPalette (17,VGA_Palette);
188  return 1;
189 }
190 
PutImage(void)191 static void PutImage (void)
192 {
193  if (Text80)
194  {
195   int i,b1,b2;
196   _farsetsel (DosSelector);
197   b1=Text80Colour;
198   b2=Text80Colour<<4;
199   for (i=0;i<80*24;++i)
200   {
201    byte c;
202    c=DisplayBuf[i];
203    _farnspokeb (0xB8000+i*2,c&127);
204    _farnspokeb (0xB8001+i*2,(c&128)? b2:b1);
205   }
206  }
207  else
208   PutImage_Asm ();
209 }
210 
InitText80(void)211 void InitText80 (void)
212 {
213  __dpmi_regs r;
214  r.x.ax=3;                           /* Set 80x25 text mode                 */
215  __dpmi_int (0x10, &r);
216  r.h.ah=1;                           /* Turn off cursor                     */
217  r.x.cx=0x0F00;
218  __dpmi_int (0x10, &r);
219  VGA_SetPalette (16,VGA_Palette+3);  /* Set palette                         */
220  Text80=1;
221  RefreshScreen(1);                   /* Force a screen refresh              */
222 }
223 
ResetText80(void)224 void ResetText80 (void)
225 {
226  VGA_Init ();
227  Text80=0;
228  RefreshScreen(1);
229 }
230 
231 /****************************************************************************/
232 /** Keyboard routines                                                      **/
233 /****************************************************************************/
234 static __volatile__ int PausePressed=0;
235 static __volatile__ byte keybstatus[256];
236 static _go32_dpmi_seginfo keybirq;
237 
238 static byte keyboard_buffer[16];
239 static int keyboard_buffer_count=0;
LocalAddToKeyboardBuffer(byte ch)240 static void LocalAddToKeyboardBuffer (byte ch)
241 {
242  keyboard_buffer[keyboard_buffer_count]=ch;
243  keyboard_buffer_count=(keyboard_buffer_count+1)&15;
244  keyboard_buffer[keyboard_buffer_count]=0;
245 }
LocalGetKeyboardChar(void)246 static int LocalGetKeyboardChar (void)
247 {
248  int retval;
249  keyboard_buffer_count=(keyboard_buffer_count-1)&15;
250  retval=keyboard_buffer[keyboard_buffer_count];
251  keyboard_buffer[keyboard_buffer_count]=0;
252  return retval;
253 }
254 
255 static const byte scan2ascii[256] =
256 {
257  0,27,'1','2','3','4','5','6','7','8','9','0','-','=',8,
258  9,'q','w','e','r','t','y','u','i','o','p','[',']',13,
259  0,'a','s','d','f','g','h','j','k','l',';',39,'`',
260  0,92,'z','x','c','v','b','n','m',',','.','/',0,
261  '*',0,' ',0,129,130,131,132,133,134,144,145,0,0,
262  0,0,171,160,168,'-',163,128,161,'+',170,162,169,148,151,
263  0,0,0,0,0,0,0,0,0,0,0,0,
264  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
265  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
266  /* extended keys */
267  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
268  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
269  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
270  0,0,0,0,0,'/',0,0,0,0,0,0,0,0,0,0,
271  0,0,0,0,0,0,0,146,160,150,0,163,0,161,0,147,
272  162,149,148,151,0,0,0,0,0,0,0,0,0,0,0,0,
273  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
274  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
275 };
276 static const byte scan2ascii_shift[256] =
277 {
278  0,27,'!','@','#','$','%','^','&','*','(',')','_','+',184,
279  185,'Q','W','E','R','T','Y','U','I','O','P','{','}',13,
280  0,'A','S','D','F','G','H','J','K','L',':',34,'~',
281  0,'|','Z','X','C','V','B','N','M','<','>','?',0,
282  '*',0,' ',0,137,138,139,140,141,142,152,153,0,0,
283  0,0,0,0,0,'-',0,0,0,'+',0,0,0,156,159,
284  0,0,0,0,0,0,0,0,0,0,0,0,
285  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
286  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
287  /* extended keys */
288  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
289  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
290  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291  0,0,0,0,0,'/',0,0,0,0,0,0,0,0,0,0,
292  0,0,0,0,0,0,0,154,0,158,0,0,0,0,0,155,
293  0,157,156,159,0,0,0,0,0,0,0,0,0,0,0,0,
294  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
295  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
296 };
297 static const byte scan2ascii_ctrl[256] =
298 {
299  0,27,0,255,0,0,0,30,0,0,0,0,31,0,127,
300  0,17,23,5,18,20,25,21,9,15,16,27,29,13,
301  0,1,19,4,6,7,8,10,11,12,0,0,0,
302  0,28,26,24,3,22,2,14,13,0,0,0,0,
303  0,0,32,0,0,0,0,0,0,0,0,0,0,0,
304  0,0,0,164,0,0,167,0,165,0,0,166,0,0,0,
305  0,0,0,0,0,0,0,0,0,0,0,0,
306  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
307  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
308  /* extended keys */
309  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
310  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
311  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
312  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
313  0,0,0,0,0,0,0,0,164,0,0,167,0,165,0,0,
314  166,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
315  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
316  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
317 };
AltPressed(void)318 static inline int AltPressed (void)
319 {
320  return keybstatus[VK_Alt]||keybstatus[VK_Alt+128];
321 }
CtrlPressed(void)322 static inline int CtrlPressed (void)
323 {
324  return keybstatus[VK_Ctrl]||keybstatus[VK_Ctrl+128];
325 }
keyb_interrupt(void)326 static int keyb_interrupt (void)
327 {
328  unsigned code;
329  static int extkey;
330  static int CapsLock=0;
331  code=inportb (0x60);             /* get scancode                           */
332  if (code<0xE0)                   /* ignore codes >0xE0                     */
333  {
334   if (code & 0x80)                /* key is released                        */
335   {
336    code&=0x7F;
337    if (extkey)
338     keybstatus[code+128]=0;
339    else
340     keybstatus[code]=0;
341   }
342   else                            /* key is pressed                         */
343   {
344    if (extkey)
345    {
346     if (!keybstatus[code+128])
347     {
348      keybstatus[code+128]=1;
349      if (in_options_dialogue)     /* jump to old interrupt handler          */
350       return 1;
351      PausePressed=0;
352      switch (code)
353      {
354       case VK_Insert:
355        if (!keyboardmode || AltPressed())
356         joystick=1;
357        break;
358       case VK_Home:
359        if (!keyboardmode || AltPressed())
360         joystick=2;
361        break;
362       case VK_PageUp:
363        if (!keyboardmode || AltPressed())
364         joystick=3;
365        break;
366       case VK_Del:
367        if (!keyboardmode || AltPressed())
368         swapbuttons^=1;
369        break;
370       case VK_End:
371        if (!keyboardmode || AltPressed())
372         swapbuttons^=2;
373        break;
374       case VK_PageDown:
375        if (!keyboardmode || AltPressed())
376         swapbuttons^=4;
377        break;
378      }
379     }
380    }
381    else
382    {
383     if (!keybstatus[code])
384     {
385      keybstatus[code]=1;
386      if (in_options_dialogue)
387       return 1;
388      if (CtrlPressed() &&
389          (code==VK_F11 || code==VK_F12))
390      {
391       if (code==VK_F11)
392        PausePressed=2;
393       else
394        PausePressed=1;
395      }
396      else
397       PausePressed=0;
398      switch (code)
399      {
400       case VK_CapsLock:
401        CapsLock^=1;
402        break;
403       case VK_F1:
404        if (!keyboardmode || AltPressed())
405         ToggleSoundChannel (0);
406        break;
407       case VK_F2:
408        if (!keyboardmode || AltPressed())
409         ToggleSoundChannel (1);
410        break;
411       case VK_F3:
412        if (!keyboardmode || AltPressed())
413         ToggleSoundChannel (2);
414        break;
415       case VK_F4:
416        if (!keyboardmode || AltPressed())
417         ToggleSoundChannel (3);
418        break;
419       case VK_F5:
420        if (!keyboardmode || AltPressed())
421         ToggleSound ();
422        break;
423       case VK_F11:
424        if (!PausePressed && !AltPressed())
425         DecreaseSoundVolume ();
426        break;
427       case VK_F12:
428        if (!PausePressed && !AltPressed())
429         IncreaseSoundVolume ();
430        break;
431       case VK_F10:
432        Z80_Running=0;
433        break;
434       case VK_F7:
435 #ifdef DEBUG
436        if (CtrlPressed())
437        {
438         Z80_Trace=!Z80_Trace;
439         break;
440        }
441 #endif
442        if (!keyboardmode || AltPressed())
443         makesnap=1;
444        break;
445       case VK_F8:
446 #ifdef DEBUG
447        if (CtrlPressed())
448         dumpram=1;
449        else
450 #endif
451        if (!keyboardmode || AltPressed())
452         makeshot=1;
453        break;
454       case VK_F9:
455        if (EmuMode)
456        {
457         if (AltPressed())
458          SwitchVideoMode=1;
459         else
460          if (CtrlPressed())
461           calloptions=1;
462          else
463           keyboardmode=(keyboardmode)? 0:1;
464        }
465        break;
466      }
467     }
468    }
469    if (keyboardmode && !AltPressed())  /* Modify keyboard buffer            */
470    {
471     /* Check for HOME+Cursor key and Cursor key combinations */
472     if (code==VK_NumPad5 && !extkey)
473     {
474      if (keybstatus[VK_Left] ||
475          keybstatus[VK_Left+128]) { code=175; goto put_char_in_buf; }
476      if (keybstatus[VK_Right] ||
477          keybstatus[VK_Right+128]) { code=173; goto put_char_in_buf; }
478      if (keybstatus[VK_Up] ||
479          keybstatus[VK_Up+128]) { code=172; goto put_char_in_buf; }
480      if (keybstatus[VK_Down] ||
481          keybstatus[VK_Down+128]) { code=170; goto put_char_in_buf; }
482     }
483     if (keybstatus[VK_NumPad5])
484     {
485      if (code==VK_Left) { code=175; goto put_char_in_buf; }
486      if (code==VK_Right) { code=173; goto put_char_in_buf; }
487      if (code==VK_Up) { code=172; goto put_char_in_buf; }
488      if (code==VK_Down) { code=170; goto put_char_in_buf; }
489     }
490     if (code==VK_Up)
491     {
492      if (keybstatus[VK_Right] ||
493          keybstatus[VK_Right+128]) { code=168; goto put_char_in_buf; }
494      if (keybstatus[VK_Left] ||
495          keybstatus[VK_Left+128]) { code=171; goto put_char_in_buf; }
496     }
497     if (code==VK_Right)
498     {
499      if (keybstatus[VK_Up] ||
500          keybstatus[VK_Up+128]) { code=168; goto put_char_in_buf; }
501      if (keybstatus[VK_Down] ||
502          keybstatus[VK_Down+128]) { code=169; goto put_char_in_buf; }
503     }
504     if (code==VK_Down)
505     {
506      if (keybstatus[VK_Right] ||
507          keybstatus[VK_Right+128]) { code=169; goto put_char_in_buf; }
508      if (keybstatus[VK_Left] ||
509          keybstatus[VK_Left+128]) { code=170; goto put_char_in_buf; }
510     }
511     if (code==VK_Left)
512     {
513      if (keybstatus[VK_Up] ||
514          keybstatus[VK_Up+128]) { code=171; goto put_char_in_buf; }
515      if (keybstatus[VK_Down] ||
516          keybstatus[VK_Down+128]) { code=170; goto put_char_in_buf; }
517     }
518     if (extkey) code+=128;
519     if (keybstatus[VK_Ctrl] || keybstatus[VK_Ctrl+128])
520      code=scan2ascii_ctrl[code];
521     else if (keybstatus[VK_RightShift] || keybstatus[VK_LeftShift])
522      code=scan2ascii_shift[code];
523     else
524      code=scan2ascii[code];
525 put_char_in_buf:
526     if (CapsLock)
527     {
528      if (code>='a' && code<='z') code+='A'-'a';
529      else if (code>='A' && code<='Z') code+='a'-'A';
530     }
531     if (code) LocalAddToKeyboardBuffer (code);
532    }
533   }
534   extkey=0;
535  }
536  else
537   if (code==0xE0)
538    extkey=1;
539  if (in_options_dialogue)
540   return 1;
541  code=inportb (0x61);             /* acknowledge interrupt                  */
542  outportb (0x61,code | 0x80);
543  outportb (0x61,code);
544  outportb (0x20,0x20);
545  return 0;                        /* Do not chain to old handler            */
546 }
547 
Keyb_Init(void)548 static int Keyb_Init (void)       /* get old handler and install our own    */
549 {
550  keybirq.pm_offset=(int)keyb_interrupt;
551  keybirq.pm_selector=_go32_my_cs();
552  SetInt (9,&keybirq);
553  return 1;
554 }
555 
Keyb_Reset(void)556 static void Keyb_Reset (void)     /* install the old handler                */
557 {
558  ResetInt (9,&keybirq);
559 }
560 
561 /****************************************************************************/
562 /** Mouse routines                                                         **/
563 /****************************************************************************/
564 static _go32_dpmi_seginfo mouse_seginfo;
565 static _go32_dpmi_registers mouse_regs;
566 static int mouse_buttons=0;       /* mouse buttons pressed                  */
567 static int mouse_xpos=500;        /* horizontal position (0 - 1000)         */
568 static int mouse_ypos=500;        /* vertical position (0 - 1000)           */
569 static int mouse_x=0;             /* horizontal position (-500 - 500)       */
570 static int mouse_y=0;             /* vertical position (-500 - 500)         */
571 static int got_mouse=0;           /* 1 if mouse was properly initialised    */
572 
Mouse_SetJoyState()573 static void Mouse_SetJoyState ()
574 {
575  if (mouse_buttons&1)
576   MouseJoyState[0]&=0xBFFF;
577  if (mouse_buttons&2)
578   MouseJoyState[0]&=0xFFBF;
579  if (mouse_buttons&4)
580   MouseJoyState[1]&=0xBFFF;
581  if (mouse_buttons&8)
582   MouseJoyState[1]&=0xFFBF;
583  SpinnerPosition[0]=(default_mouse_sens*mouse_x*(abs(mouse_x)+mouse_sens))/
584                     (mouse_sens*mouse_sens);
585  SpinnerPosition[1]=(default_mouse_sens*mouse_y*(abs(mouse_y)+mouse_sens))/
586                     (mouse_sens*mouse_sens);
587 }
588 
Mouse_Callback(_go32_dpmi_registers * r)589 static void Mouse_Callback (_go32_dpmi_registers *r)
590 {
591  mouse_buttons=r->x.bx&7;
592  mouse_xpos=r->x.cx;
593  mouse_ypos=r->x.dx;
594 }
595 
Mouse_Check(void)596 static void Mouse_Check (void)
597 {
598  __dpmi_regs r;
599  int tmp;
600  if (!got_mouse)
601   return;
602  mouse_x=mouse_xpos-500;
603  mouse_y=mouse_ypos-500;
604  tmp=mouse_buttons;
605  if (mouse_x || mouse_y)
606  {
607   r.x.ax=0x04;
608   r.x.cx=500;
609   r.x.dx=500;
610   __dpmi_int (0x33,&r);
611   mouse_xpos=mouse_ypos=500;
612  }
613  switch (expansionmode)
614  {
615   case 4:                         /* emulate driving module                 */
616    if (mouse_buttons&7)
617     MouseJoyState[0]&=0xFEFF;
618    mouse_x/=4;
619    mouse_y=0;
620    mouse_buttons=0;
621    break;
622   case 5:                         /* emulate SA speed roller on both ports  */
623    mouse_x=(-mouse_x)/4;
624    mouse_y=-mouse_x;
625    mouse_buttons=0;
626    break;
627   case 6:                         /* emulate SA speed roller on port 1      */
628    mouse_x=(-mouse_x)/4;
629    mouse_y=0;
630    mouse_buttons=0;
631    break;
632   case 7:                         /* emulate SA speed roller on port 2      */
633    mouse_y=mouse_x/4;
634    mouse_x=0;
635    mouse_buttons=0;
636    break;
637  }
638  if (swapbuttons&4)
639   mouse_buttons=(mouse_buttons&(~3))|
640                 ((mouse_buttons&1)<<1)|
641                 ((mouse_buttons&2)>>1);
642  Mouse_SetJoyState ();
643  mouse_buttons=tmp;
644 }
645 
Mouse_Detect(void)646 static int Mouse_Detect (void)
647 {
648  __dpmi_regs r;
649  r.x.ax=0;
650  __dpmi_int (0x33,&r);
651  if (r.x.ax==0)
652   return 0;
653  got_mouse=1;
654  return 1;
655 }
656 
Mouse_Init(void)657 static void Mouse_Init (void)
658 {
659  __dpmi_regs r;
660  if (!got_mouse)
661   return;
662  r.x.ax=0x07;                     /* set horizontal range                   */
663  r.x.cx=0;
664  r.x.dx=1000;
665  __dpmi_int (0x33,&r);
666  r.x.ax=0x08;                     /* set vertical range                     */
667  r.x.cx=0;
668  r.x.dx=1000;
669  __dpmi_int (0x33,&r);
670  r.x.ax=0x04;                     /* set position                           */
671  r.x.cx=500;
672  r.x.dx=500;
673  __dpmi_int (0x33,&r);
674  r.x.ax=0x0F;                     /* set sensitivity                        */
675  r.x.cx=3;
676  r.x.dx=3;
677  __dpmi_int (0x33,&r);
678  mouse_seginfo.pm_selector=_my_cs();
679  mouse_seginfo.pm_offset=(unsigned)Mouse_Callback;
680  _go32_dpmi_allocate_real_mode_callback_retf (&mouse_seginfo,&mouse_regs);
681  r.x.ax=0x0C;
682  r.x.cx=0x1F;
683  r.x.dx=mouse_seginfo.rm_offset;
684  r.x.es=mouse_seginfo.rm_segment;
685  __dpmi_int (0x33,&r);
686  return;
687 }
688 
Mouse_Exit(void)689 static void Mouse_Exit (void)
690 {
691  __dpmi_regs r;
692  if (!got_mouse)
693   return;
694  r.x.ax=0x0C;
695  r.x.cx=0;
696  r.x.dx=0;
697  r.x.es=0;
698  __dpmi_int (0x33,&r);
699  r.x.ax=0;
700  __dpmi_int (0x33,&r);
701  _go32_dpmi_free_real_mode_callback (&mouse_seginfo);
702 }
703 
704 /****************************************************************************/
705 /** Joystick routines                                                      **/
706 /****************************************************************************/
707 typedef struct joyposstruct
708 {
709  int x,y;
710 } joypos;
711 
712 static int gotjoy=0;              /* 1 if joystick was properly initialised */
713 
714 static joypos joycentre;          /* joystick centre position               */
715 static joypos joymin;             /* left-upper corner position             */
716 static joypos joymax;             /* right-lower corner position            */
717 static joypos joy_lowmargin;      /* start of 'dead' region                 */
718 static joypos joy_highmargin;     /* end of 'dead' region                   */
719 
_JoyGetPos(joypos * jp)720 static int _JoyGetPos (joypos *jp)
721 {
722  unsigned tmp;
723  tmp=JoyGetPos ();
724  jp->x=(unsigned) (tmp&0xFFFF);
725  if (jp->x>=10000)
726   return 0;
727  jp->y=(unsigned) (tmp>>16);
728  if (jp->y>=10000)
729   return 0;
730  return 1;
731 }
732 
Joy_Init(void)733 static int Joy_Init (void)
734 {
735  joypos jp;
736  if (!_JoyGetPos (&jp))
737   return 0;
738  joycentre.x=jp.x;
739  joycentre.y=jp.y;
740  gotjoy=1;
741  return 1;
742 }
743 
CalibrateJoystick(void)744 static void CalibrateJoystick (void)
745 {
746  FILE *joyfile=NULL;
747  if (!calibrate)
748   joyfile=fopen(szJoystickFileName,"rb");
749  if (!joyfile)
750  {
751   fprintf (stderr,"Move joystick to top left and press any key\n");
752   getch ();
753   _JoyGetPos (&joymin);
754   fprintf (stderr,"Move joystick to bottom right and press any key\n");
755   getch ();
756   _JoyGetPos (&joymax);
757   joyfile=fopen(szJoystickFileName,"wb");
758   if (joyfile)
759   {
760    fwrite (&joymin,sizeof(joymin),1,joyfile);
761    fwrite (&joymax,sizeof(joymax),1,joyfile);
762    fclose (joyfile);
763   }
764  }
765  else
766  {
767   fread (&joymin,sizeof(joymin),1,joyfile);
768   fread (&joymax,sizeof(joymax),1,joyfile);
769   fclose (joyfile);
770  }
771  joy_lowmargin.x=joycentre.x-(joycentre.x-joymin.x)/8;
772  joy_lowmargin.y=joycentre.y-(joycentre.y-joymin.y)/8;
773  joy_highmargin.x=joycentre.x+(joymax.x-joycentre.x)/8;
774  joy_highmargin.y=joycentre.y+(joymax.y-joycentre.y)/8;
775  /* prevent a divide by zero in JoySortOutAnalogue() */
776  if (joy_lowmargin.x-joymin.x==0)
777   joy_lowmargin.x++;
778  if (joymax.x-joy_highmargin.x==0)
779   joy_highmargin.x--;
780  if (joy_lowmargin.y-joymin.y==0)
781   joy_lowmargin.y++;
782  if (joymax.y-joy_highmargin.y==0)
783   joy_highmargin.y--;
784 }
785 
786 #define JOY_RANGE       128
JoySortOutAnalogue(joypos * jp)787 static void JoySortOutAnalogue (joypos *jp)
788 {
789  if (jp->x < joymin.x)
790   jp->x=-JOY_RANGE;
791  else
792   if (jp->x > joymax.x)
793    jp->x=JOY_RANGE;
794   else
795    if ((jp->x > joy_lowmargin.x) && (jp->x < joy_highmargin.x))
796     jp->x=0;
797    else
798     if (jp->x < joy_lowmargin.x)
799      jp->x=-JOY_RANGE+(jp->x-joymin.x)*JOY_RANGE/(joy_lowmargin.x-joymin.x);
800     else
801      jp->x=JOY_RANGE-(joymax.x-jp->x)*JOY_RANGE/(joymax.x-joy_highmargin.x);
802 
803  if (jp->y < joymin.y)
804   jp->y=-JOY_RANGE;
805  else
806   if (jp->y > joymax.y)
807    jp->y=JOY_RANGE;
808   else
809    if ((jp->y > joy_lowmargin.y) && (jp->y < joy_highmargin.y))
810     jp->y=0;
811    else
812     if (jp->y < joy_lowmargin.y)
813      jp->y=-JOY_RANGE+(jp->y-joymin.y)*JOY_RANGE/(joy_lowmargin.y-joymin.y);
814     else
815      jp->y=JOY_RANGE-(joymax.y-jp->y)*JOY_RANGE/(joymax.y-joy_highmargin.y);
816 }
817 
Joy_Check(void)818 static void Joy_Check (void)
819 {
820  joypos jp;
821  unsigned char joystatus;
822  if (!gotjoy)
823   return;
824  _JoyGetPos (&jp);
825  joystatus=inportb (0x201);
826  switch (expansionmode)
827  {
828   case 0:
829   case 5:
830   case 6:
831   case 7:
832    if (jp.x<(joycentre.x*3/4))
833     JoystickJoyState[0]&=0xF7FF;
834    else
835     if (jp.x>(joycentre.x*5/4))
836      JoystickJoyState[0]&=0xFDFF;
837    if (jp.y<(joycentre.y*3/4))
838     JoystickJoyState[0]&=0xFEFF;
839    else
840     if (jp.y>(joycentre.y*5/4))
841      JoystickJoyState[0]&=0xFBFF;
842    if ((joystatus&0x10)==0)
843     JoystickJoyState[0]&=(swapbuttons&1)? 0xFFBF:0xBFFF;
844    if ((joystatus&0x20)==0)
845     JoystickJoyState[0]&=(swapbuttons&1)? 0xBFFF:0xFFBF;
846    if ((joystatus&0x40)==0)
847     JoystickJoyState[0]=(JoyState[0]&0xFFF0)|12;
848    if ((joystatus&0x80)==0)
849     JoystickJoyState[0]=(JoyState[0]&0xFFF0)|13;
850    break;
851   case 2:
852    JoySortOutAnalogue (&jp);
853    mouse_x=jp.x;
854    mouse_y=jp.y;
855    mouse_buttons=0;
856    if ((joystatus&0x10)==0)
857     mouse_buttons|=(swapbuttons&1)? 2:1;
858    if ((joystatus&0x20)==0)
859     mouse_buttons|=(swapbuttons&1)? 1:2;
860    if ((joystatus&0x40)==0)
861     mouse_buttons|=4;
862    if ((joystatus&0x80)==0)
863     mouse_buttons|=8;
864    Mouse_SetJoyState ();
865    break;
866   case 3:
867    if (jp.y<(joycentre.y*3/4))
868     JoystickJoyState[0]&=0xFEFF;
869    JoySortOutAnalogue (&jp);
870    mouse_x=(jp.x/2);
871    mouse_y=0;
872    Mouse_SetJoyState ();
873    if ((joystatus&0x10)==0)
874     JoystickJoyState[1]&=(swapbuttons&1)? 0xFBFF:0xFEFF;
875    if ((joystatus&0x20)==0)
876     JoystickJoyState[1]&=(swapbuttons&1)? 0xFEFF:0xFBFF;
877    if ((joystatus&0x40)==0)
878     JoystickJoyState[1]&=0xF7FF;
879    if ((joystatus&0x80)==0)
880     JoystickJoyState[1]&=0xFDFF;
881    break;
882  }
883 }
884 
885 /****************************************************************************/
886 /** Deallocate all resources taken by InitMachine()                        **/
887 /****************************************************************************/
TrashMachine(void)888 void TrashMachine(void)
889 {
890  Mouse_Exit ();
891  VGA_Reset ();
892  if(Verbose) printf("\n\nShutting down...\n");
893  TrashSound ();
894  RestoreTimer ();
895  Keyb_Reset ();
896  ExitStacks ();
897 }
898 
NextFile(char * s)899 static int NextFile (char *s)
900 {
901  char *p;
902  p=s+strlen(s)-1;
903  if (*p=='9')
904  {
905   *p='0';
906   --p;
907   if (*p=='9')
908   {
909    (*p)++;
910    if (*p=='0')
911     return 0;
912   }
913   else
914    (*p)++;
915  }
916  else
917   (*p)++;
918  return 1;
919 }
920 
NextBitmapFile(void)921 static int NextBitmapFile (void)
922 {
923  return NextFile (szBitmapFile);
924 }
925 
NextSnapshotFile(void)926 static int NextSnapshotFile (void)
927 {
928  return NextFile (szSnapshotFile);
929 }
930 
931 /****************************************************************************/
932 /** Allocate resources needed by MS-DOS-dependent code                     **/
933 /****************************************************************************/
InitMachine(void)934 int InitMachine(void)
935 {
936  int i,j,c;
937  FILE *bitmapfile,*snapshotfile;
938  if (Verbose) printf ("Initialising MSDOS drivers...\n");
939  if (videomode>2 || videomode<0)
940   videomode=0;
941  JoyState[0]=JoyState[1]=MouseJoyState[0]=MouseJoyState[1]=
942  JoystickJoyState[0]=JoystickJoyState[1]=0x7F7F;
943  cs_alias=_my_ds();
944  DosSelector=_dos_ds;
945  if (Verbose)
946   printf ("  Allocating stack space... ");
947  i=InitStacks (NUM_STACKS,STACK_SIZE);
948  if (!i)
949  {
950   if (Verbose) puts ("FAILED\n");
951   return 0;
952  }
953  memset (DisplayBuf,0,sizeof(DisplayBuf));
954  for (i=0;i<16;++i)
955   PalBuf[i]=i+1;
956  if (Verbose)
957   printf ("OK\n  Initialising conversion buffer... ");
958  for (i=0;i<16;++i)
959   for (j=0;j<16;++j)
960    for (c=0;c<16;++c)
961    {
962     unsigned a;
963     a=0;
964 #ifdef LSB_FIRST
965     if (c&0x08) a|=PalBuf[i]; else a|=PalBuf[j];
966     if (c&0x04) a|=(PalBuf[i]<<8); else a|=(PalBuf[j]<<8);
967     if (c&0x02) a|=(PalBuf[i]<<16); else a|=(PalBuf[j]<<16);
968     if (c&0x01) a|=(PalBuf[i]<<24); else a|=(PalBuf[j]<<24);
969 #else
970     if (c&0x01) a|=PalBuf[i]; else a|=PalBuf[j];
971     if (c&0x02) a|=(PalBuf[i]<<8); else a|=(PalBuf[j]<<8);
972     if (c&0x04) a|=(PalBuf[i]<<16); else a|=(PalBuf[j]<<16);
973     if (c&0x08) a|=(PalBuf[i]<<24); else a|=(PalBuf[j]<<24);
974 #endif
975     font2screen[i*16*16+j*16+c]=a;
976    }
977  if (Verbose) puts ("OK");
978  InitSound ();
979  if (expansionmode==2 || expansionmode==3 ||
980      (expansionmode!=1 && expansionmode!=4 && joystick))
981  {
982   if (Verbose)
983    printf ("  Detecting joystick... ");
984   i=Joy_Init ();
985   if (Verbose)
986    printf ((i)? "Found\n" : "Not found\n");
987  }
988  if (expansionmode==1 || expansionmode==4 ||
989      expansionmode==5 || expansionmode==6 ||
990      expansionmode==7)
991  {
992   if (Verbose)
993    printf ("  Detecting mouse... ");
994   i=Mouse_Detect ();
995   if (Verbose)
996    printf ((i)? "Found\n" : "Not found\n");
997  }
998  if (mouse_sens<=0 || mouse_sens>1000)
999   mouse_sens=default_mouse_sens;
1000  switch (expansionmode)
1001  {
1002   case 2:
1003   case 3:
1004    if (!gotjoy)
1005    {
1006     expansionmode=0;
1007     break;
1008    }
1009    CalibrateJoystick ();
1010    break;
1011   case 1:
1012   case 4:
1013   case 5:
1014   case 6:
1015   case 7:
1016    if (!got_mouse)
1017     expansionmode=0;
1018    break;
1019   default:
1020    expansionmode=0;
1021    default_mouse_sens*=5;
1022    break;
1023  }
1024  StartTimer ();
1025  if (syncemu)
1026   OldTimer=ReadTimer ();
1027  /* Parse keyboard mapping string */
1028  sscanf (szKeys,"%02X%02X%02X%02X%02X%02X%02X%02X",
1029          &KEY_LEFT,&KEY_RIGHT,&KEY_UP,&KEY_DOWN,
1030          &KEY_BUTTONA,&KEY_BUTTONB,&KEY_BUTTONC,&KEY_BUTTOND);
1031  Keyb_Init ();
1032  while ((bitmapfile=fopen(szBitmapFile,"rb"))!=NULL)
1033  {
1034   fclose (bitmapfile);
1035   if (!NextBitmapFile())
1036    break;
1037  }
1038  while ((snapshotfile=fopen(szSnapshotFile,"rb"))!=NULL)
1039  {
1040   fclose (snapshotfile);
1041   if (!NextSnapshotFile())
1042    break;
1043  }
1044  if (Verbose)
1045  {
1046   printf ("  Next screenshot will be %s\n"
1047           "  Next snapshot will be %s\n",
1048           szBitmapFile,szSnapshotFile);
1049  }
1050  if (Verbose)
1051  {
1052   fprintf (stderr,"Press space to run rom code...\n");
1053   while (!keybstatus[VK_Space]);
1054  }
1055  makeshot=0; makesnap=0;
1056  for (i=0;i<16*3;++i) VGA_Palette[i+3]=Coleco_Palette[i];
1057  VGA_Init ();
1058  VGA_SetBkColour (0);
1059  Mouse_Init ();
1060  keyboardmode=(EmuMode)? 1:0;
1061  return 1;
1062 }
1063 
1064 /****************************************************************************/
1065 /** Routines to modify the Coleco gamport status                           **/
1066 /****************************************************************************/
numkeypressed(int nScanCode)1067 static int numkeypressed (int nScanCode)
1068 {
1069  int nOr;
1070  switch (nScanCode)
1071  {
1072   case VK_1:
1073   case VK_End:
1074    nOr=1;
1075    break;
1076   case VK_2:
1077   case VK_Down:
1078    nOr=2;
1079    break;
1080   case VK_3:
1081   case VK_PageDown:
1082    nOr=3;
1083    break;
1084   case VK_4:
1085   case VK_Left:
1086    nOr=4;
1087    break;
1088   case VK_5:
1089   case VK_NumPad5:
1090    nOr=5;
1091    break;
1092   case VK_6:
1093   case VK_Right:
1094    nOr=6;
1095    break;
1096   case VK_7:
1097   case VK_Home:
1098    nOr=7;
1099    break;
1100   case VK_8:
1101   case VK_Up:
1102    nOr=8;
1103    break;
1104   case VK_9:
1105   case VK_PageUp:
1106    nOr=9;
1107    break;
1108   case VK_Equal:
1109   case VK_Enter:
1110    nOr=10;
1111    break;
1112   case VK_Minus:
1113   case VK_Del:
1114    nOr=11;
1115    break;
1116   default:
1117    nOr=0;
1118  }
1119  return nOr;
1120 }
1121 
Joysticks(void)1122 static void Joysticks (void)
1123 {
1124  int i,tmp,tmp2;
1125  MouseJoyState[0]|=0x7F7F;
1126  MouseJoyState[1]|=0x7F7F;
1127  Mouse_Check ();
1128  JoystickJoyState[0]|=0x7F7F;
1129  JoystickJoyState[1]|=0x7F7F;
1130  Joy_Check ();
1131  JoyState[1]=(MouseJoyState[0] & JoystickJoyState[0]);
1132  JoyState[0]=(MouseJoyState[1] & JoystickJoyState[1]);
1133  if (!keyboardmode)
1134  {
1135   if (keybstatus[KEY_BUTTONA])
1136    JoyState[0]&=(swapbuttons&2)? 0xFFBF:0xBFFF;
1137   if (keybstatus[KEY_BUTTONB])
1138    JoyState[0]&=(swapbuttons&2)? 0xBFFF:0xFFBF;
1139   if (keybstatus[KEY_DOWN])
1140    JoyState[0]&=0xFBFF;
1141   if (keybstatus[KEY_UP])
1142    JoyState[0]&=0xFEFF;
1143   if (keybstatus[KEY_LEFT])
1144    JoyState[0]&=0xF7FF;
1145   if (keybstatus[KEY_RIGHT])
1146    JoyState[0]&=0xFDFF;
1147   for (i=VK_1;i<=VK_Equal;++i)
1148    if (keybstatus[i])
1149    {
1150     tmp=numkeypressed(i);
1151     JoyState[0]=(JoyState[0]&0xFFF0)|tmp;
1152    }
1153   if (keybstatus[KEY_BUTTONC])
1154    JoyState[0]=(JoyState[0]&0xFFF0)|12;
1155   if (keybstatus[KEY_BUTTOND])
1156    JoyState[0]=(JoyState[0]&0xFFF0)|13;
1157   for (i=VK_Home;i<=VK_PageUp;++i)
1158    if (keybstatus[i])
1159    {
1160     tmp=numkeypressed((keypadmode)? (i-VK_Home+VK_End) : i);
1161     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1162    }
1163   for (i=VK_Left;i<=VK_Right;++i)
1164    if (keybstatus[i])
1165    {
1166     tmp=numkeypressed(i);
1167     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1168    }
1169   for (i=VK_End;i<=VK_PageDown;++i)
1170    if (keybstatus[i])
1171    {
1172     tmp=numkeypressed((keypadmode)? (i-VK_End+VK_Home) : i);
1173     JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1174    }
1175   if (keybstatus[VK_Insert])
1176   {
1177    tmp=numkeypressed((keypadmode)? VK_Del : VK_Insert);
1178    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1179   }
1180   if (keybstatus[VK_Del])
1181   {
1182    tmp=numkeypressed((keypadmode)? VK_Insert : VK_Del);
1183    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1184   }
1185   if (keybstatus[VK_Enter+128])
1186   {
1187    tmp=numkeypressed(VK_Enter);
1188    JoyState[1]=(JoyState[1]&0xFFF0)|tmp;
1189   }
1190   if (keybstatus[VK_PlusNumPad])
1191    JoyState[1]=(JoyState[1]&0xFFF0)|13;
1192   if (keybstatus[VK_MinusNumPad])
1193    JoyState[1]=(JoyState[1]&0xFFF0)|12;
1194  }
1195  switch (expansionmode)
1196  {
1197   case 1:                         /* emulate roller controller with mouse   */
1198   case 2:                         /* emulate RC with joystick               */
1199    if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13)
1200     JoyState[1]|=0x0F;
1201    if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13)
1202     JoyState[0]|=0x0F;
1203    tmp=JoyState[1];
1204    JoyState[1]=(JoyState[0]&0x707F)|0x0F00;
1205    JoyState[0]=(tmp&0x7F7F);
1206    if ((JoyState[1]&0xF)!=0xF)
1207     JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1208    JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0x0F);
1209    break;
1210   case 3:                         /* emulate driving module with joystick   */
1211   case 4:                         /* emulate driving module with mouse      */
1212    if ((JoyState[1]&0x0F)==12 || (JoyState[1]&0x0F)==13)
1213     JoyState[1]|=0x0F;
1214    if ((JoyState[0]&0x0F)==12 || (JoyState[0]&0x0F)==13)
1215     JoyState[0]|=0x0F;
1216    if ((JoyState[1]&0xF)!=0xF)
1217     JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1218    if ((JoyState[1]&0x0100)==0)
1219     JoyState[1]&=0xBFFF;
1220    else
1221     JoyState[1]|=0x4000;
1222    JoyState[1]|=0x0F7F;
1223    tmp=JoyState[1];
1224    JoyState[1]=JoyState[0];
1225    JoyState[0]=tmp|0x0040;
1226    break;
1227   default:
1228    switch (joystick)
1229    {
1230     case 1:                       /* Joystick 1=Joystick 2                  */
1231      tmp=JoyState[0]&0x0F;
1232      tmp2=JoyState[1]&0x0F;
1233      if (tmp==12 || tmp==13)
1234       JoyState[1]=(JoyState[1]&0xFFF0)|(JoyState[0]&0xF);
1235      else
1236       if (tmp2==12 || tmp2==13)
1237        JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0xF);
1238       else
1239        if (tmp2!=15)
1240        {
1241         JoyState[0]=(JoyState[0]&0xFFF0)|(JoyState[1]&0x0F);
1242         JoyState[1]|=15;
1243        }
1244      JoyState[0]&=(JoyState[1]|0xF);
1245      JoyState[1]&=(JoyState[0]|0xF);
1246      break;
1247     case 2:                       /* Joystick 1=keyb, Joystick 2=joystick   */
1248      break;
1249     case 3:                       /* Joystick 1=joystick, Joystick 2=keyb   */
1250      tmp=JoyState[0];
1251      JoyState[0]=JoyState[1];
1252      JoyState[1]=tmp;
1253      break;
1254    }
1255    break;
1256  }
1257 }
1258 
1259 /****************************************************************************/
1260 /*** Parse keyboard events                                                ***/
1261 /****************************************************************************/
1262 extern byte *RAM;
Keyboard(void)1263 void Keyboard (void)
1264 {
1265  int tmp;
1266  /* Check if reset combination is pressed */
1267  if (AltPressed())
1268  {
1269   if (keybstatus[VK_F12]) ResetColeco (0);
1270   if (keybstatus[VK_F11]) ResetColeco (1);
1271  }
1272  /* Update keyboard buffer */
1273  do
1274  {
1275   tmp=LocalGetKeyboardChar ();
1276   if (tmp) AddToKeyboardBuffer (tmp);
1277  }
1278  while (tmp);
1279  /* Check mouse and joystick events */
1280  Joysticks ();
1281  /* Check if video mode should be switched */
1282  if (SwitchVideoMode)
1283  {
1284   SwitchVideoMode=0;
1285   AutoText80=0;
1286   if (Text80)
1287    ResetText80();
1288   else
1289    InitText80();
1290  }
1291  /* Check is PAUSE is pressed */
1292  if (PausePressed)
1293  {
1294   StopSound ();
1295   tmp=0;
1296   if (PausePressed==2)
1297   {
1298    tmp=1;
1299    VGA_SetBkColour (1);
1300    inportb (0x3BA);
1301    inportb (0x3DA);
1302    outportb (0x3C0,0);
1303   }
1304   while (PausePressed);
1305   if (tmp)
1306   {
1307    VGA_SetBkColour (VDP.BGColour);
1308    inportb (0x3BA);
1309    inportb (0x3DA);
1310    outportb (0x3C0,0x20);
1311   }
1312   ResumeSound ();
1313   if (syncemu)
1314    OldTimer=ReadTimer ();
1315  }
1316  /* Check if a screen shot should be taken */
1317  if (makeshot)
1318  {
1319   sound (440);
1320   WriteBitmap (szBitmapFile,8,17,WIDTH,256,192,
1321                DisplayBuf+(WIDTH-256)/2+(HEIGHT-192)*WIDTH,VGA_Palette);
1322   NextBitmapFile ();
1323   makeshot--;
1324   nosound ();
1325  }
1326  if (makesnap)
1327  {
1328   sound (220);
1329   SaveSnapshotFile (szSnapshotFile);
1330   NextSnapshotFile ();
1331   nosound ();
1332   makesnap--;
1333  }
1334 #ifdef DEBUG
1335  if (dumpram)
1336  {
1337   FILE *f;
1338   char buf[20];
1339   static int dumpram_count=0;
1340   sprintf (buf,"RAM.%03d",dumpram_count);
1341   dumpram_count++; if (dumpram_count>999) dumpram_count=0;
1342   f=fopen (buf,"wb");
1343   for (tmp=0;tmp<256;++tmp) fwrite (AddrTabl[tmp],1,256,f);
1344   fclose (f);
1345   dumpram--;
1346  }
1347 #endif
1348  /* Check if OptionsDialogue() should be called */
1349  if (calloptions)
1350  {
1351   in_options_dialogue=1;
1352   calloptions=0;
1353   StopSound ();
1354   VGA_Reset ();
1355   fflush (stdin);
1356   OptionsDialogue ();
1357   VGA_Init ();
1358   if (Text80) InitText80();
1359   in_options_dialogue=0;
1360   ResumeSound ();
1361   RefreshScreen (1);
1362   if (syncemu) OldTimer=ReadTimer();
1363  }
1364 }
1365 
1366 /****************************************************************************/
1367 /** Interrupt routines                                                     **/
1368 /****************************************************************************/
1369 /* Gets called 50 times per second */
CheckScreenRefresh(void)1370 int CheckScreenRefresh (void)
1371 {
1372  static int skipped=0;
1373  if (syncemu)
1374  {
1375   NewTimer=ReadTimer ();
1376   OldTimer+=1192380/IFreq;
1377   if ((OldTimer-NewTimer)>0)
1378   {
1379    do
1380     NewTimer=ReadTimer ();
1381    while ((NewTimer-OldTimer)<0);
1382    skipped=0;
1383    return 1;
1384   }
1385   else
1386    if (++skipped>=UPeriod)
1387    {
1388     OldTimer=ReadTimer ();
1389     skipped=0;
1390     return 1;
1391    }
1392    else
1393     return 0;
1394  }
1395  return 2;
1396 }
1397 
1398 /****************************************************************************/
1399 /** Screen refresh drivers                                                 **/
1400 /****************************************************************************/
1401 #define USE_LOOKUP_TABLE              /* Use font2screen for faster refresh */
1402 #define _8BPP                         /* We have an 8 bpp video device      */
1403 
1404 #include "Common.h"
1405