Annotation of hatari/src/ikbd.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   The keyboard processor(6301) handles any joystick/mouse task and sends bytes to the ACIA(6850)
                      5:   When a byte arrives in the ACIA (which takes just over 7000 CPU cycles) an MFP interrupt is flagged.
                      6:   The CPU can now read the byte from the ACIA by reading address $fffc02.
                      7:   An annoying bug can be found in Dungeon Master. This, when run, turns off the mouse input - but of course
                      8:   then you are unable to play the game! A bodge flag has been added so we need to be told twice to turn off
                      9:   the mouse input(although I think this causes errors in other games...)
                     10:   Also, the ACIA_CYCLES time is very important for games such as Carrier Command. The keyboard handler
                     11:   in this game has a bug in it, which corrupts its own registers if more than one byte is queued up. This
                     12:   value was found by a test program on a real ST and has correctly emulated the behaviour.
                     13: */
                     14: 
                     15: #include "main.h"
                     16: #include "debug.h"
                     17: #include "decode.h"
                     18: #include "gemdos.h"
                     19: #include "ikbd.h"
                     20: #include "int.h"
                     21: #include "joy.h"
                     22: #include "m68000.h"
                     23: #include "memAlloc.h"
                     24: #include "memorySnapShot.h"
                     25: #include "mfp.h"
                     26: #include "misc.h"
                     27: #include "screen.h"
                     28: #include "video.h"
                     29: #include "vdi.h"
                     30: 
                     31: #define DBL_CLICK_HISTORY  0x07     /* Number of frames since last click to see if need to send one or two clicks */
                     32: #define ACIA_CYCLES    7200         /* Cycles(Multiple of 4) between sent to ACIA from keyboard along serial line - 500Hz/64, (approx' 6920-7200cycles from test program) */
                     33: 
                     34: #define IKBD_RESET_CYCLES  400000   /* Cycles after RESET before complete */
                     35: 
                     36: #define ABS_X_ONRESET    0          /* Initial XY for absolute mouse position after RESET command */
                     37: #define ABS_Y_ONRESET    0
                     38: #define ABS_MAX_X_ONRESET  320      /* Initial absolute mouse limits after RESET command */
                     39: #define ABS_MAY_Y_ONRESET  200      /* These values are never actually used as user MUST call 'IKBD_Cmd_AbsMouseMode' before ever using them */
                     40: 
                     41: #define ABS_PREVBUTTONS    (0x02|0x8)  /* Don't report any buttons up on first call to 'IKBD_Cmd_ReadAbsMousePos' */
                     42: 
                     43: #define SCALE_MOUSE_INPUT           /* Scale mouse so correct aspect ratio when in 320x200, 640x200, 640x400 */
                     44: 
                     45: /* Keyboard state */
                     46: KEYBOARD Keyboard;
                     47: 
                     48: /* Keyboard processor */
                     49: KEYBOARD_PROCESSOR KeyboardProcessor;   /* Keyboard processor details */
1.1.1.2 ! root       50: BOOL DoubleClickPattern[] = {           /* Pattern of mouse button up/down in ST frames (run off a double-click message) */
        !            51:  BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE,
        !            52:  0,0,0,0,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE,BUTTON_MOUSE };
        !            53: BOOL bMouseDisabled, bJoystickDisabled, bDuringResetCriticalTime;
1.1       root       54: 
                     55: /* ACIA */
                     56: unsigned char ACIAControlRegister = 0;
                     57: unsigned char ACIAStatusRegister = ACIA_STATUS_REGISTER__TX_BUFFER_EMPTY;  /* Pass when read 0xfffc00 */
                     58: unsigned char ACIAByte;                 /* When a byte has arrived at the ACIA(from the keyboard) it is stored here */
                     59: BOOL bByteInTransitToACIA = FALSE;      /* Is a byte being sent to the ACIA from the keyboard? */
                     60: 
                     61: /*
                     62:   6850 ACIA (Asynchronous Communications Inferface Apdater)
                     63:   Page 41, ST Internals. Also ST Update Magazine, February 1989 (I glad I kept that!)
                     64: 
                     65:   Pins:-
                     66:     Vss
                     67:     RX DATA Receive Data
                     68:     RX CLK Receive Clock
                     69:     TX CLK Transmitter Clock
                     70:     RTS Request To Send
                     71:     TX DATA Transmitter Data
                     72:     IRQ Interrupt Request
                     73:     CS 0,1,2 Chip Select
                     74:     RS Register Select
                     75:     Vcc Voltage
                     76:     R/W Read/Write
                     77:     E Enable
                     78:     D0-D7 Data
                     79:     DCD Data Carrier Detect
                     80:     CTS Clear To Send
                     81: 
                     82:   Registers:-
                     83:     0xfffc00 Keyboard ACIA Control (write)/Status(read)
                     84:     0xfffc02 Keyboard ACIA Data
                     85:     0xfffc04 MIDI ACIA Control (write)/Status(read)
                     86:     0xfffc06 MIDI ACIA Data
                     87: 
                     88:   Control Register (0xfffc00 write):-
                     89:     Bits 0,1 - These bits determine by which factor the transmitter and receiver
                     90:       clock will be divided. These bits also are joined with a master reset
                     91:       function. The 6850 has no separate reset line, so it must be
                     92:       accomplished though software.
                     93:         0 0    RXCLK/TXCLK without division
                     94:         0 1    RXCLK/TXCLK by 16 (MIDI)
                     95:         1 0    RXCLK/TXCLK by 64 (Keyboard)
                     96:         1 1    Master RESET
                     97:     Bits 2,3,4 - These so-called Word Select bits tell whether 7 or 8 data-bits are
                     98:       involved; whether 1 or 2 stop-bits are transferred; and the type of parity
                     99:     Bits 5,6 - These Transmitter Control bits set the RTS output pin, and allow or prevent
                    100:       an interrupt through the ACIA when the send register is emptied. Also, BREAK signals
                    101:       can be sent over the serial output by this line. A BREAK signal is nothing more than
                    102:       a long seqence of null bits
                    103:         0 0    RTS low, transmitter IRQ disabled
                    104:         0 1    RTS low, transmitter IRQ enabled
                    105:         1 0    RTS high, transmitter IRQ disabled
                    106:         1 1    RTS low, transmitter IRQ disabled, BREAK sent
                    107:     Bit 7 - The Receiver Interrupt Enable bit determines whether the receiver interrupt
                    108:       will be on. An interrupt can be caused by the DCD line chaning from low to high, or
                    109:       by the receiver data buffer filling. Besides that, an interrupt can occur from an
                    110:       OVERRUN ( a received character isn't properly read from the processior).
                    111:         0 Interrupt disabled
                    112:         1 Interrupt enabled
                    113: 
                    114:   Status Register (0xfffc00 read):-
                    115:     Bit 0 - When this bit is high, the RX data register is full. The byte must be read
                    116:       before a new character is received (otherwise an OVERRUN happens)
                    117:     Bit 1 - This bit reflects the status of the TX data buffer. An empty register
                    118:       set the bit.
                    119:     Bit 2 - A low-high change in pin DCD sets bit 2. If the receiver interrupt is allowable, the IRQ
                    120:       is cancelled. The bit is cleared when the status register and the receiver register are
                    121:       read. This also cancels the IRQ. Bit 2 register remains highis the signal on the DCD pin
                    122:       is still high; Bit 2 register low if DCD becomes low.
                    123:     Bit 3 - This line shows the status of CTS. This signal cannot be altered by a mater reset,
                    124:       or by ACIA programming.
                    125:     Bit 4 - Shows 'Frame Errors'. Frame errors are when no stop-bit is recognized in receiver
                    126:       switching. It can be set with every new character.
                    127:     Bit 5 - This bit display the previously mentioned OVERRUN condition. Bit 5 is reset when the
                    128:       RX buffer is read.
                    129:     Bit 6 - This bit recognizes whether the parity of a received character is correct. The bit is
                    130:       set on an error.
                    131:     Bit 7 - This signals the state of the IRQ pins; this bit make it possible to switch several
                    132:       IRQ lines on one interrupt input. In cases where an interrupt is program-generated, bit 7
                    133:       can tell which IC cut off the interrupt.
                    134:         
                    135:   ST ACIA:-
                    136:     Note CTS,DCD and RTS are not connected! Phew!
                    137:     The keyboard ACIA are address 0xfffc000 and 0xfffc02.
                    138:     Default parameters are :- 8-bit word, 1 stopbit, no parity, 77812.5 baud; 500KHz/64 (keyboard clock div)
                    139:     Default MIDI parameters are are above but :- 31250 baud; 500KHz/16 (MIDI clock div)
                    140: */
                    141: 
1.1.1.2 ! root      142: /* List of possible keyboard commands, others are seen as NOPs by keyboard processor */
1.1       root      143: IKBD_COMMAND_PARAMS KeyboardCommands[] = {
1.1.1.2 ! root      144:   /* Known messages, counts include command byte */
1.1       root      145:   0x80,2,  IKBD_Cmd_Reset,
                    146:   0x07,2,  IKBD_Cmd_MouseAction,
                    147:   0x08,1,  IKBD_Cmd_RelMouseMode,
                    148:   0x09,5,  IKBD_Cmd_AbsMouseMode,
                    149:   0x0A,3,  IKBD_Cmd_MouseCursorKeycodes,
                    150:   0x0B,3,  IKBD_Cmd_SetMouseThreshold,
                    151:   0x0C,3,  IKBD_Cmd_SetMouseScale,
                    152:   0x0D,1,  IKBD_Cmd_ReadAbsMousePos,
                    153:   0x0E,6,  IKBD_Cmd_SetInternalMousePos,
                    154:   0x0F,1,  IKBD_Cmd_SetYAxisDown,
                    155:   0x10,1,  IKBD_Cmd_SetYAxisUp,
                    156:   0x11,1,  IKBD_Cmd_StartKeyboardTransfer,
                    157:   0x12,1,  IKBD_Cmd_TurnMouseOff,
                    158:   0x13,1,  IKBD_Cmd_StopKeyboardTransfer,
                    159:   0x14,1,  IKBD_Cmd_ReturnJoystickAuto,
                    160:   0x15,1,  IKBD_Cmd_StopJoystick,
                    161:   0x16,1,  IKBD_Cmd_ReturnJoystick,
                    162:   0x17,2,  IKBD_Cmd_SetJoystickDuration,
                    163:   0x18,1,  IKBD_Cmd_SetJoystickFireDuration,
                    164:   0x19,7,  IKBD_Cmd_SetCursorForJoystick,
                    165:   0x1A,1,  IKBD_Cmd_DisableJoysticks,
                    166:   0x1B,7,  IKBD_Cmd_SetClock,
                    167:   0x1C,1,  IKBD_Cmd_ReadClock,
                    168:   0x20,4,  IKBD_Cmd_LoadMemory,
                    169:   0x21,3,  IKBD_Cmd_ReadMemory,
                    170:   0x22,3,  IKBD_Cmd_Execute,
                    171: 
1.1.1.2 ! root      172:   /* Report message (top bit set) - ignore for now... */
1.1       root      173:   0x88,1,  IKBD_Cmd_NullFunction,
                    174:   0x89,1,  IKBD_Cmd_NullFunction,
                    175:   0x8A,1,  IKBD_Cmd_NullFunction,
                    176:   0x8B,1,  IKBD_Cmd_NullFunction,
                    177:   0x8C,1,  IKBD_Cmd_NullFunction,
                    178:   0x8F,1,  IKBD_Cmd_NullFunction,
                    179:   0x90,1,  IKBD_Cmd_NullFunction,
                    180:   0x92,1,  IKBD_Cmd_NullFunction,
                    181:   0x94,1,  IKBD_Cmd_NullFunction,
                    182:   0x95,1,  IKBD_Cmd_NullFunction,
                    183:   0x99,1,  IKBD_Cmd_NullFunction,
                    184: 
1.1.1.2 ! root      185:   0xFF  /* Term */
1.1       root      186: };
                    187: 
1.1.1.2 ! root      188: 
        !           189: /*-----------------------------------------------------------------------*/
1.1       root      190: /*
                    191:   Reset the IKBD processor
                    192: */
                    193: void IKBD_Reset(BOOL bCold)
                    194: {
1.1.1.2 ! root      195:   /* Reset internal keyboard processor details */
1.1       root      196:   if (bCold)
                    197:     KeyboardProcessor.bReset = FALSE;
                    198:   KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL;
                    199:   KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK;
                    200: 
                    201:   KeyboardProcessor.Rel.X =  KeyboardProcessor.Rel.Y = 0;
                    202:   KeyboardProcessor.Rel.PrevX = KeyboardProcessor.Rel.PrevY = 0;
                    203:   KeyboardProcessor.Abs.X = ABS_X_ONRESET;  KeyboardProcessor.Abs.Y = ABS_Y_ONRESET;
                    204:   KeyboardProcessor.Abs.MaxX = ABS_MAX_X_ONRESET;  KeyboardProcessor.Abs.MaxY = ABS_MAY_Y_ONRESET;
                    205:   KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS;
                    206: 
                    207:   KeyboardProcessor.Mouse.DeltaX = KeyboardProcessor.Mouse.DeltaY = 0;
                    208:   KeyboardProcessor.Mouse.XScale = KeyboardProcessor.Mouse.YScale = 0;
                    209:   KeyboardProcessor.Mouse.XThreshold = KeyboardProcessor.Mouse.YThreshold = 1;
1.1.1.2 ! root      210:   KeyboardProcessor.Mouse.YAxis = 1;          /* Y origin at top */
1.1       root      211:   KeyboardProcessor.Mouse.Action = 0;
                    212: 
                    213:   KeyboardProcessor.Joy.PrevJoyData[0] = KeyboardProcessor.Joy.PrevJoyData[1] = 0;
                    214: 
1.1.1.2 ! root      215:   /* Reset our ACIA status */
1.1       root      216:   bByteInTransitToACIA = FALSE;
                    217:   ACIAControlRegister = 0;
                    218:   ACIAStatusRegister = ACIA_STATUS_REGISTER__TX_BUFFER_EMPTY;
1.1.1.2 ! root      219:   /* And our keyboard states and clear key state table */
1.1       root      220:   Keyboard.BufferHead = Keyboard.BufferTail = 0;
                    221:   Keyboard.nBytesInInputBuffer = 0;
                    222:   Memory_Clear(Keyboard.KeyStates,sizeof(Keyboard.KeyStates));
                    223:   Keyboard.bLButtonDown = BUTTON_NULL;
                    224:   Keyboard.bRButtonDown = BUTTON_NULL;
                    225:   Keyboard.bOldLButtonDown = Keyboard.bOldRButtonDown = BUTTON_NULL;
                    226:   Keyboard.LButtonDblClk = Keyboard.RButtonDblClk = 0;
                    227:   Keyboard.LButtonHistory = Keyboard.RButtonHistory = 0;
                    228: 
1.1.1.2 ! root      229:   /* Store BOOL for when disable mouse or joystick - do emulate hardware 'quirk' where */
        !           230:   /* if disable both with 'x' time of a RESET command they are ignored! */
1.1       root      231:   bMouseDisabled = bJoystickDisabled = bDuringResetCriticalTime = FALSE;
                    232: }
                    233: 
1.1.1.2 ! root      234: 
        !           235: /*-----------------------------------------------------------------------*/
1.1       root      236: /*
                    237:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
                    238: */
                    239: void IKBD_MemorySnapShot_Capture(BOOL bSave)
                    240: {
1.1.1.2 ! root      241:   /* Save/Restore details */
1.1       root      242:   MemorySnapShot_Store(&Keyboard,sizeof(Keyboard));
                    243:   MemorySnapShot_Store(&KeyboardProcessor,sizeof(KeyboardProcessor));
                    244:   MemorySnapShot_Store(&ACIAControlRegister,sizeof(ACIAControlRegister));
                    245:   MemorySnapShot_Store(&ACIAStatusRegister,sizeof(ACIAStatusRegister));
                    246:   MemorySnapShot_Store(&ACIAByte,sizeof(ACIAByte));
                    247:   MemorySnapShot_Store(&bByteInTransitToACIA,sizeof(bByteInTransitToACIA));
                    248: }
                    249: 
1.1.1.2 ! root      250: 
        !           251: /*-----------------------------------------------------------------------*/
1.1       root      252: /*
                    253:   Calculate out 'delta' that mouse has moved by each frame, and add this to our internal keyboard position
                    254: */
                    255: void IKBD_UpdateInternalMousePosition(void)
                    256: {
                    257:   BOOL bHalveX=FALSE,bHalveY=FALSE;
                    258: 
                    259: #ifdef SCALE_MOUSE_INPUT
1.1.1.2 ! root      260:   /* According to chosen resolution, halve XY axis to give smoother mouse movement! */
        !           261:   /* When using VDI or mono leave mouse as is */
1.1       root      262:   if (!bUseVDIRes) {
                    263:     if (STRes==ST_LOW_RES) {
                    264:       bHalveX = bHalveY = TRUE;
                    265:     }
                    266:     if ( (STRes==ST_MEDIUM_RES) || (STRes==ST_LOWMEDIUM_MIX_RES) ) {
                    267:       bHalveY = TRUE;
                    268:     }
                    269:   }
                    270: 
                    271:   if (bHalveX)
                    272:     KeyboardProcessor.Mouse.DeltaX = (KeyboardProcessor.Rel.X-KeyboardProcessor.Rel.PrevX)>>1;
                    273:   else
                    274:     KeyboardProcessor.Mouse.DeltaX = KeyboardProcessor.Rel.X-KeyboardProcessor.Rel.PrevX;
                    275:   if (bHalveY)
                    276:     KeyboardProcessor.Mouse.DeltaY = (KeyboardProcessor.Rel.Y-KeyboardProcessor.Rel.PrevY)>>1;
                    277:   else
                    278:     KeyboardProcessor.Mouse.DeltaY = KeyboardProcessor.Rel.Y-KeyboardProcessor.Rel.PrevY;
                    279: #else
                    280:   KeyboardProcessor.Mouse.DeltaX = KeyboardProcessor.Rel.X-KeyboardProcessor.Rel.PrevX;
                    281:   KeyboardProcessor.Mouse.DeltaY = KeyboardProcessor.Rel.Y-KeyboardProcessor.Rel.PrevY;
                    282: #endif
1.1.1.2 ! root      283: 
        !           284:   /* Accellerating mouse in ST-Low - is this a good idea? */
        !           285:   if(!bUseHighRes)
        !           286:    {  KeyboardProcessor.Mouse.DeltaX*=2; KeyboardProcessor.Mouse.DeltaY*=2;  }
1.1       root      287: 
                    288:   /* Retain fraction for next time around!?? */
                    289:   if (bHalveX)
                    290:     KeyboardProcessor.Rel.PrevX = KeyboardProcessor.Rel.X&~0x1;
                    291:   else
                    292:     KeyboardProcessor.Rel.PrevX = KeyboardProcessor.Rel.X;
                    293:   if (bHalveY)
                    294:     KeyboardProcessor.Rel.PrevY = KeyboardProcessor.Rel.Y&~0x1;
                    295:   else
                    296:     KeyboardProcessor.Rel.PrevY = KeyboardProcessor.Rel.Y;
                    297: 
1.1.1.2 ! root      298:   /* Update internal mouse coords - Y axis moves according to YAxis setting(up/down) */
        !           299:   /* Limit to Max X/Y(inclusive) */
1.1       root      300:   KeyboardProcessor.Abs.X += KeyboardProcessor.Mouse.DeltaX;
                    301:   if (KeyboardProcessor.Abs.X<0)
                    302:     KeyboardProcessor.Abs.X = 0;
                    303:   if (KeyboardProcessor.Abs.X>KeyboardProcessor.Abs.MaxX)
                    304:     KeyboardProcessor.Abs.X = KeyboardProcessor.Abs.MaxX;
1.1.1.2 ! root      305:   KeyboardProcessor.Abs.Y += KeyboardProcessor.Mouse.DeltaY*KeyboardProcessor.Mouse.YAxis;  /* Needed '+' for Falcon... */
1.1       root      306:   if (KeyboardProcessor.Abs.Y<0)
                    307:     KeyboardProcessor.Abs.Y = 0;
                    308:   if (KeyboardProcessor.Abs.Y>KeyboardProcessor.Abs.MaxY)
                    309:     KeyboardProcessor.Abs.Y = KeyboardProcessor.Abs.MaxY;
                    310: }
                    311: 
1.1.1.2 ! root      312: 
        !           313: /*-----------------------------------------------------------------------*/
1.1       root      314: /*
                    315:   When running in maximum speed the emulation will not see 'double-clicks' of the mouse
                    316:   as it is running so fast. In this case, we check for a Windows double-click and pass
                    317:   the 'up'/'down' messages in emulation time to simulate the double-click effect!
                    318: */
                    319: void IKBD_CheckForDoubleClicks(void)
                    320: {
                    321:   // OK, our Window responds to double-clicks but this sends the WM_xxxxx messages:-
                    322:   // WM_LBUTTONDOWN,WM_LBUTTONUP,WM_LBUTTONDBLCLK,WM_LBUTTONUP. When running emulation
                    323:   // in normal speed we simply interpret the WM_LBUTTONDBLCLK as a WM_LBUTTONDOWN and
                    324:   // all runs well. Things get a little complicated when running max speed as a normal
                    325:   // double-click is a load of 1's, followed by 0's, 1's and 0's - But the ST does
                    326:   // not see this as a double click as the space in 'ST' time between changes is so great.
                    327:   // Now, when we see a WM_LBUTTONDBLCLK in max speed we actually send the down/up/down/up
                    328:   // in ST time. To get this correct(and not send three clicks) we look in a history buffer
                    329:   // and start at an index which gives the correct number of clicks! Phew!
                    330: 
1.1.1.2 ! root      331:   /* Handle double clicks!!! */
1.1       root      332:   if (Keyboard.LButtonDblClk) {
                    333:     if (Keyboard.LButtonDblClk==1) {          /* First pressed! */
                    334:       if ((Keyboard.LButtonHistory&0x3f)==0)  /* If not pressed button in long time do full dbl-click pattern */
                    335:         Keyboard.LButtonDblClk = 1;
                    336:       else {
                    337:         Keyboard.LButtonDblClk = 4;           /* Otherwise, check where to begin to give 1111000011110000 pattern */
                    338:         if ((Keyboard.LButtonHistory&0x7)==0) 
                    339:           Keyboard.LButtonDblClk = 8;
                    340:         else if ((Keyboard.LButtonHistory&0x3)==0) 
                    341:           Keyboard.LButtonDblClk = 7;
                    342:         else if ((Keyboard.LButtonHistory&0x1)==0) 
                    343:           Keyboard.LButtonDblClk = 6;
                    344:       }
                    345:     }
                    346: 
                    347:     Keyboard.bLButtonDown = DoubleClickPattern[Keyboard.LButtonDblClk];
                    348:     Keyboard.LButtonDblClk++;
                    349:     if (Keyboard.LButtonDblClk>=13) {         /* Check for end of sequence */
                    350:       Keyboard.LButtonDblClk = 0;
                    351:       Keyboard.bLButtonDown = FALSE;
                    352:     }
                    353:   }
                    354:   if (Keyboard.RButtonDblClk) {
                    355:     if (Keyboard.RButtonDblClk==1) {          /* First pressed! */
                    356:       if ((Keyboard.RButtonHistory&0x3f)==0)  /* If not pressed button in long time do full dbl-click pattern */
                    357:         Keyboard.RButtonDblClk = 1;
                    358:       else {
                    359:         Keyboard.RButtonDblClk = 4;           /* Otherwise, check where to begin to give 1111000011110000 pattern */
                    360:         if ((Keyboard.RButtonHistory&0x7)==0) 
                    361:           Keyboard.RButtonDblClk = 8;
                    362:         else if ((Keyboard.RButtonHistory&0x3)==0) 
                    363:           Keyboard.RButtonDblClk = 7;
                    364:         else if ((Keyboard.RButtonHistory&0x1)==0) 
                    365:           Keyboard.RButtonDblClk = 6;
                    366:       }
                    367:     }
                    368: 
                    369:     Keyboard.bRButtonDown = DoubleClickPattern[Keyboard.RButtonDblClk];
                    370:     Keyboard.RButtonDblClk++;
                    371:     if (Keyboard.RButtonDblClk>=13) {         /* Check for end of sequence */
                    372:       Keyboard.RButtonDblClk = 0;
                    373:       Keyboard.bRButtonDown = FALSE;
                    374:     }
                    375:   }
                    376: 
1.1.1.2 ! root      377:   /* Store presses into history */
1.1       root      378:   Keyboard.LButtonHistory = (Keyboard.LButtonHistory<<1);
                    379:   if (Keyboard.bLButtonDown)
                    380:     Keyboard.LButtonHistory |= 0x1;
                    381:   Keyboard.RButtonHistory = (Keyboard.RButtonHistory<<1);
                    382:   if (Keyboard.bRButtonDown)
                    383:     Keyboard.RButtonHistory |= 0x1;
                    384: }
                    385: 
1.1.1.2 ! root      386: 
        !           387: /*-----------------------------------------------------------------------*/
1.1       root      388: /*
                    389:   Convert button to BOOL value
                    390: */
                    391: BOOL IKBD_ButtonBool(int Button)
                    392: {
1.1.1.2 ! root      393:   /* Button pressed? */
1.1       root      394:   if (Button)
                    395:     return(TRUE);
                    396:   return(FALSE);
                    397: }
                    398: 
1.1.1.2 ! root      399: 
        !           400: /*-----------------------------------------------------------------------*/
1.1       root      401: /*
                    402:   Return TRUE if buttons match, use this as buttons are a mask and not BOOLean
                    403: */
                    404: BOOL IKBD_ButtonsEqual(int Button1,int Button2)
                    405: {
1.1.1.2 ! root      406:   /* Return BOOL compare */
1.1       root      407:   return(IKBD_ButtonBool(Button1)==IKBD_ButtonBool(Button2));
                    408: }
                    409: 
1.1.1.2 ! root      410: 
        !           411: /*-----------------------------------------------------------------------*/
1.1       root      412: /*
                    413:   According to if the mouse if enabled or not the joystick 1 fire button/right mouse button
                    414:   will become the same button, ie pressing one will also press the other and vise-versa
                    415: */
                    416: void IKBD_DuplicateMouseFireButtons(void)
                    417: {
1.1.1.2 ! root      418:   /* If mouse is off then joystick fire button goes to joystick */
1.1       root      419:   if (KeyboardProcessor.MouseMode==AUTOMODE_OFF) {
1.1.1.2 ! root      420:     /* If pressed right mouse button, should go to joystick 1 */
1.1       root      421:     if (Keyboard.bRButtonDown&BUTTON_MOUSE)
                    422:       KeyboardProcessor.Joy.JoyData[1] |= 0x80;
1.1.1.2 ! root      423:     /* And left mouse button, should go to joystick 0 */
1.1       root      424:     if (Keyboard.bLButtonDown&BUTTON_MOUSE)
                    425:       KeyboardProcessor.Joy.JoyData[0] |= 0x80;
                    426:   }
1.1.1.2 ! root      427:   /* If mouse if on, joystick 1 fire button goes to mouse not to the joystick */
1.1       root      428:   else {
1.1.1.2 ! root      429:     /* Is fire button pressed? */
1.1       root      430:     if (KeyboardProcessor.Joy.JoyData[1]&0x80) {
1.1.1.2 ! root      431:       KeyboardProcessor.Joy.JoyData[1] &= 0x7f;  /* Clear fire button bit */
        !           432:       Keyboard.bRButtonDown |= BUTTON_JOYSTICK;  /* Mimick on mouse right button */
1.1       root      433:     }
                    434:     else
                    435:       Keyboard.bRButtonDown &= ~BUTTON_JOYSTICK;
                    436:   }
                    437: }
                    438: 
1.1.1.2 ! root      439: 
        !           440: /*-----------------------------------------------------------------------*/
1.1       root      441: /*
                    442:   Send 'relative' mouse position
                    443: */
                    444: void IKBD_SendRelMousePacket(void)
                    445: {
                    446:   int ByteRelX,ByteRelY;
                    447:   unsigned char Header;
                    448: 
                    449:   if ( (KeyboardProcessor.Mouse.DeltaX!=0) || (KeyboardProcessor.Mouse.DeltaY!=0)
                    450:    || (!IKBD_ButtonsEqual(Keyboard.bOldLButtonDown,Keyboard.bLButtonDown)) || (!IKBD_ButtonsEqual(Keyboard.bOldRButtonDown,Keyboard.bRButtonDown)) ) {
1.1.1.2 ! root      451:     /* Send packet to keyboard process */
1.1       root      452:     while(TRUE) {
                    453:       ByteRelX = KeyboardProcessor.Mouse.DeltaX;
                    454:       if (ByteRelX>127)  ByteRelX = 127;
                    455:       if (ByteRelX<-128)  ByteRelX = -128;
                    456:       ByteRelY = KeyboardProcessor.Mouse.DeltaY;
                    457:       if (ByteRelY>127)  ByteRelY = 127;
                    458:       if (ByteRelY<-128)  ByteRelY = -128;
                    459: 
                    460:       Header = 0xf8;
                    461:       if (Keyboard.bLButtonDown)
                    462:         Header |= 0x02;
                    463:       if (Keyboard.bRButtonDown)
                    464:         Header |= 0x01;
                    465:       IKBD_AddKeyToKeyboardBuffer(Header);
                    466:       IKBD_AddKeyToKeyboardBuffer(ByteRelX);
                    467:       IKBD_AddKeyToKeyboardBuffer(ByteRelY*KeyboardProcessor.Mouse.YAxis);
                    468: 
                    469:       KeyboardProcessor.Mouse.DeltaX -= ByteRelX;
                    470:       KeyboardProcessor.Mouse.DeltaY -= ByteRelY;
                    471: 
                    472:       if ( (KeyboardProcessor.Mouse.DeltaX==0) && (KeyboardProcessor.Mouse.DeltaY==0) )
                    473:         break;
                    474: 
1.1.1.2 ! root      475:       /* Store buttons for next time around */
1.1       root      476:       Keyboard.bOldLButtonDown = Keyboard.bLButtonDown;
                    477:       Keyboard.bOldRButtonDown = Keyboard.bRButtonDown;
                    478:     }
                    479:   }
                    480: }
                    481: 
1.1.1.2 ! root      482: 
        !           483: /*-----------------------------------------------------------------------*/
1.1       root      484: /*
                    485:   Send 'joysticks' bit masks
                    486: */
                    487: void IKBD_SelAutoJoysticks(void)
                    488: {
                    489:   unsigned char JoyData;
                    490: 
1.1.1.2 ! root      491:   /* Did joystick 0/mouse change? */
1.1       root      492:   JoyData = KeyboardProcessor.Joy.JoyData[0];
                    493:   if (JoyData!=KeyboardProcessor.Joy.PrevJoyData[0]) {
1.1.1.2 ! root      494:     IKBD_AddKeyToKeyboardBuffer(0xFE);    /* Joystick 0/Mouse */
1.1       root      495:     IKBD_AddKeyToKeyboardBuffer(JoyData);
                    496: 
                    497:     KeyboardProcessor.Joy.PrevJoyData[0] = JoyData;
                    498:   }
                    499: 
1.1.1.2 ! root      500:   /* Did joystick 1(default) change? */
1.1       root      501:   JoyData = KeyboardProcessor.Joy.JoyData[1];
                    502:   if (JoyData!=KeyboardProcessor.Joy.PrevJoyData[1]) {
1.1.1.2 ! root      503:     IKBD_AddKeyToKeyboardBuffer(0xFF);    /* Joystick 1 */
1.1       root      504:     IKBD_AddKeyToKeyboardBuffer(JoyData);
                    505: 
                    506:     KeyboardProcessor.Joy.PrevJoyData[1] = JoyData;
                    507:   }
                    508: }
                    509: 
                    510: /*-----------------------------------------------------------------------*/
                    511: /*
                    512:   Send packets which are generated from the mouse action settings
                    513:   If relative mode is on, still generate these packets
                    514: */
                    515: void IKBD_SendOnMouseAction(void)
                    516: {
                    517:   BOOL bReportPosition = FALSE;
                    518: 
                    519:   /* Report buttons as keys? Do in relative/absolute mode */
                    520:   if (KeyboardProcessor.Mouse.Action&0x4) {
                    521:     /* Left button? */
                    522:     if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) )
                    523:       IKBD_AddKeyToKeyboardBuffer(0x74);    /* Left */
                    524:     else if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) )
                    525:       IKBD_AddKeyToKeyboardBuffer(0x74|0x80);
                    526:     /* Right button? */
                    527:     if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) )
                    528:       IKBD_AddKeyToKeyboardBuffer(0x75);    /* Right */
                    529:     else if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) )
                    530:       IKBD_AddKeyToKeyboardBuffer(0x75|0x80);
                    531: 
                    532:     /* Ignore bottom two bits, so return now */
                    533:     return;
                    534:   }
                    535: 
                    536:   /* Check MouseAction - report position on press/release */
                    537:   /* MUST do this before update relative positions as buttons get reset */
                    538:   if (KeyboardProcessor.Mouse.Action&0x3) {
                    539:     /* Check for 'press'? */
                    540:     if (KeyboardProcessor.Mouse.Action&0x1) {
                    541:       /* Did 'press' mouse buttons? */
                    542:       if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) ) {
                    543:         bReportPosition = TRUE;
                    544:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x04;
                    545:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x02;
                    546:       }
                    547:       if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) ) {
                    548:         bReportPosition = TRUE;
                    549:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x01;
                    550:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x08;
                    551:       }
                    552:     }
                    553:     /* Check for 'release'? */
                    554:     if (KeyboardProcessor.Mouse.Action&0x2) {
                    555:       /* Did 'release' mouse buttons? */
                    556:       if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) ) {
                    557:         bReportPosition = TRUE;
                    558:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x08;
                    559:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x01;
                    560:       }
                    561:       if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) ) {
                    562:         bReportPosition = TRUE;
                    563:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons &= ~0x02;
                    564:         KeyboardProcessor.Abs.PrevReadAbsMouseButtons |= 0x04;
                    565:       }
                    566:     }
                    567: 
                    568:     /* Do need to report? */
                    569:     if (bReportPosition) {
                    570:       /* Only report if mouse in absolute mode */
                    571:       if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSEABS) {
                    572: #ifdef DEBUG_OUTPUT_IKBD
                    573:         Debug_IKBD("Report ABS on MouseAction\n");
                    574: #endif
                    575:         IKBD_Cmd_ReadAbsMousePos();
                    576:       }
                    577:     }
                    578:   }
                    579: }
                    580: 
1.1.1.2 ! root      581: 
        !           582: /*-----------------------------------------------------------------------*/
1.1       root      583: /*
                    584:   Send mouse movements as cursor keys
                    585: */
                    586: void IKBD_SendCursorMousePacket(void)
                    587: {
                    588:   int i=0;
                    589: 
1.1.1.2 ! root      590:   /* Run each 'Delta' as cursor presses */
        !           591:   /* Limit to '10' loops as Windows cursor is a VERY poor quality. Eg, a single mouse movement */
        !           592:   /* on and ST gives delta's of '1', mostly, but Windows goes as high as 20+! */
1.1       root      593:   while ( (i<10) && ((KeyboardProcessor.Mouse.DeltaX!=0) || (KeyboardProcessor.Mouse.DeltaY!=0)
                    594:    || (!IKBD_ButtonsEqual(Keyboard.bOldLButtonDown,Keyboard.bLButtonDown)) || (!IKBD_ButtonsEqual(Keyboard.bOldRButtonDown,Keyboard.bRButtonDown))) ) {
1.1.1.2 ! root      595:     /* Left? */
1.1       root      596:     if (KeyboardProcessor.Mouse.DeltaX<0) {
1.1.1.2 ! root      597:       IKBD_AddKeyToKeyboardBuffer(75);    /* Left cursor */
1.1       root      598:       IKBD_AddKeyToKeyboardBuffer(75|0x80);
                    599:       KeyboardProcessor.Mouse.DeltaX++;
                    600:     }
1.1.1.2 ! root      601:     /* Right? */
1.1       root      602:     if (KeyboardProcessor.Mouse.DeltaX>0) {
1.1.1.2 ! root      603:       IKBD_AddKeyToKeyboardBuffer(77);    /* Right cursor */
1.1       root      604:       IKBD_AddKeyToKeyboardBuffer(77|0x80);
                    605:       KeyboardProcessor.Mouse.DeltaX--;
                    606:     }
1.1.1.2 ! root      607:     /* Up? */
1.1       root      608:     if (KeyboardProcessor.Mouse.DeltaY<0) {
1.1.1.2 ! root      609:       IKBD_AddKeyToKeyboardBuffer(72);    /* Up cursor */
1.1       root      610:       IKBD_AddKeyToKeyboardBuffer(72|0x80);
                    611:       KeyboardProcessor.Mouse.DeltaY++;
                    612:     }
1.1.1.2 ! root      613:     /* Down? */
1.1       root      614:     if (KeyboardProcessor.Mouse.DeltaY>0) {
1.1.1.2 ! root      615:       IKBD_AddKeyToKeyboardBuffer(80);    /* Down cursor */
1.1       root      616:       IKBD_AddKeyToKeyboardBuffer(80|0x80);
                    617:       KeyboardProcessor.Mouse.DeltaY--;
                    618:     }
                    619: 
1.1.1.2 ! root      620:     /* Left button? */
1.1       root      621:     if ( (IKBD_ButtonBool(Keyboard.bLButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldLButtonDown))) )
1.1.1.2 ! root      622:       IKBD_AddKeyToKeyboardBuffer(0x74);    /* Left */
1.1       root      623:     else if ( (IKBD_ButtonBool(Keyboard.bOldLButtonDown) && (!IKBD_ButtonBool(Keyboard.bLButtonDown))) )
                    624:       IKBD_AddKeyToKeyboardBuffer(0x74|0x80);
1.1.1.2 ! root      625:     /* Right button? */
1.1       root      626:     if ( (IKBD_ButtonBool(Keyboard.bRButtonDown) && (!IKBD_ButtonBool(Keyboard.bOldRButtonDown))) )
1.1.1.2 ! root      627:       IKBD_AddKeyToKeyboardBuffer(0x75);    /* Right */
1.1       root      628:     else if ( (IKBD_ButtonBool(Keyboard.bOldRButtonDown) && (!IKBD_ButtonBool(Keyboard.bRButtonDown))) )
                    629:       IKBD_AddKeyToKeyboardBuffer(0x75|0x80);
                    630: 
                    631:     Keyboard.bOldLButtonDown = Keyboard.bLButtonDown;
                    632:     Keyboard.bOldRButtonDown = Keyboard.bRButtonDown;
                    633: 
1.1.1.2 ! root      634:     /* Count, so exit if try too many times! */
1.1       root      635:     i++;
                    636:   }
                    637: }
                    638: 
1.1.1.2 ! root      639: 
        !           640: /*-----------------------------------------------------------------------*/
1.1       root      641: /*
                    642:   Return packets from keyboard for auto, rel mouse, joystick etc...
                    643: */
                    644: void IKBD_SendAutoKeyboardCommands(void)
                    645: {
                    646:   /* Ignore anything until we've redirected our GEM handlers */
                    647: //FM  if (!bInitGemDOS)
                    648: //FIXME    return;
                    649: 
1.1.1.2 ! root      650:   /* Do not send auto commands directly after a reset command. */
        !           651:   /* I hope that it is okay that I added this here - Thothy */
        !           652: //  if( bDuringResetCriticalTime )
        !           653: //    return;
        !           654: 
1.1       root      655:   /* Don't do anything until processor is first reset */
                    656:   if (!KeyboardProcessor.bReset)
                    657:     return;
                    658: 
                    659:   /* Read joysticks for this frame */
                    660:   /* If mouse is on, joystick 0 is not connected */
                    661:   KeyboardProcessor.Joy.JoyData[0] = (KeyboardProcessor.MouseMode==AUTOMODE_OFF) ? Joy_GetStickData(0):0x00;
                    662:   KeyboardProcessor.Joy.JoyData[1] = Joy_GetStickData(1);
                    663: 
                    664:   /* Check for double-clicks in maximum speed mode */
                    665:   IKBD_CheckForDoubleClicks();
                    666: 
                    667:   /* Handle Joystick/Mouse fire buttons */
                    668:   IKBD_DuplicateMouseFireButtons();
                    669:   
                    670:   /* Send any packets which are to be reported by mouse action */
                    671:   IKBD_SendOnMouseAction();
                    672: 
                    673:   /* Update internal mouse absolute position by find 'delta' of mouse movement */
                    674:   IKBD_UpdateInternalMousePosition();
                    675: 
                    676:   /* Send automatic joystick packets */
                    677:   if (KeyboardProcessor.JoystickMode==AUTOMODE_JOYSTICK)
                    678:     IKBD_SelAutoJoysticks();
                    679:   /* Send automatic relative mouse positions(absolute are not send automatically) */
                    680:   if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSEREL)
                    681:     IKBD_SendRelMousePacket();
                    682:   /* Send cursor key directions for movements */
                    683:   else if (KeyboardProcessor.MouseMode==AUTOMODE_MOUSECURSOR)
                    684:     IKBD_SendCursorMousePacket();
                    685: 
                    686:   /* Store buttons for next time around */
                    687:   Keyboard.bOldLButtonDown = Keyboard.bLButtonDown;
                    688:   Keyboard.bOldRButtonDown = Keyboard.bRButtonDown;
                    689: 
                    690:   /* Send joystick button '2' as 'Space bar' key - MUST do here so does not get mixed up in middle of joystick packets! */
                    691:   if (JoystickSpaceBar) {
                    692:     /* As we simulating space bar? */
                    693:     if (JoystickSpaceBar==JOYSTICK_SPACE_DOWN) {
1.1.1.2 ! root      694:       IKBD_PressSTKey(57,TRUE);         /* Press */
1.1       root      695:       JoystickSpaceBar = JOYSTICK_SPACE_UP;
                    696:     }
                    697:     else { //if (JoystickSpaceBar==JOYSTICK_SPACE_UP) {
1.1.1.2 ! root      698:       IKBD_PressSTKey(57,FALSE);        /* Release */
        !           699:       JoystickSpaceBar = FALSE;         /* Complete */
1.1       root      700:     }
                    701:   }
                    702: }
                    703: 
1.1.1.2 ! root      704: 
        !           705: /*-----------------------------------------------------------------------*/
1.1       root      706: /*
                    707:   On ST if disable Mouse AND Joystick with a set time of a RESET command they are
                    708:   actually turned back on! (A number of games do this so can get mouse and joystick
                    709:   packets at the same time)
                    710: */
                    711: void IKBD_CheckResetDisableBug(void)
                    712: {
                    713:   /* Have disabled BOTH mouse and joystick? */
                    714:   if (bMouseDisabled && bJoystickDisabled) {
                    715:     /* And in critical time? */
                    716:     if (bDuringResetCriticalTime) {
                    717:       /* Emulate relative mouse and joystick reports being turned back on */
                    718:       KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL;
                    719:       KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK;
                    720: #ifdef DEBUG_OUTPUT_IKBD
                    721:       Debug_IKBD("IKBD Mouse+Joystick disabled during RESET. Revert.\n");
                    722:       Debugger_TabIKBD_AddListViewItem("( Mouse+Joystick disabled during RESET. Revert. )");
                    723: #endif
                    724:     }
                    725:   }
                    726: }
                    727: 
1.1.1.2 ! root      728: 
        !           729: /*-----------------------------------------------------------------------*/
1.1       root      730: /*
                    731:   Start timer after keyboard RESET command to emulate 'quirk'
                    732:   If some IKBD commands are sent during time after a RESET they may be ignored
                    733: */
                    734: void IKBD_InterruptHandler_ResetTimer(void)
                    735: {
1.1.1.2 ! root      736:   /* Remove this interrupt from list and re-order */
1.1       root      737:   Int_AcknowledgeInterrupt();
                    738: 
1.1.1.2 ! root      739:   /* Critical timer is over */
1.1       root      740:   bDuringResetCriticalTime = FALSE;
                    741: }
                    742: 
                    743: 
                    744: 
1.1.1.2 ! root      745: /*-----------------------------------------------------------------------*/
1.1       root      746: /*
                    747:   List of keyboard commands
                    748: */
                    749: 
                    750: 
1.1.1.2 ! root      751: /*-----------------------------------------------------------------------*/
1.1       root      752: /*
                    753:   Blank function for some keyboard commands - this can be used to find errors
                    754: */
                    755: void IKBD_Cmd_NullFunction(void)
                    756: {
                    757: #ifdef DEBUG_OUTPUT_IKBD
                    758:   Debug_IKBD("IKBD_Cmd_NullFunction\n");
                    759:   Debugger_TabIKBD_AddListViewItem("( NullFunction )");
                    760: #endif
                    761: }
                    762: 
1.1.1.2 ! root      763: 
        !           764: /*-----------------------------------------------------------------------*/
1.1       root      765: /*
                    766:   RESET
                    767: 
                    768:   0x80
                    769:   0x01
                    770: 
                    771:   Performs self test and checks for stuck (closed) keys, if OK returns 0xF0. Otherwise
                    772:   returns break codes for keys
                    773: */
                    774: void IKBD_Cmd_Reset(void)
                    775: {
                    776:   /* Check for error series of bytes, eg 0x80,0x01 */
                    777:   if (Keyboard.InputBuffer[1]==0x01) {
                    778: #ifdef DEBUG_OUTPUT_IKBD
                    779:     Debug_IKBD("KEYBOARD ON\n");
                    780: #endif
                    781:     KeyboardProcessor.bReset = TRUE;      /* Turn processor on; can now process commands */
                    782: 
                    783:     /* Set defaults */
                    784:     KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL;
                    785:     KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK;
                    786:     KeyboardProcessor.Abs.X = ABS_X_ONRESET;  KeyboardProcessor.Abs.Y = ABS_Y_ONRESET;
                    787:     KeyboardProcessor.Abs.MaxX = ABS_MAX_X_ONRESET;  KeyboardProcessor.Abs.MaxY = ABS_MAY_Y_ONRESET;
                    788:     KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS;
                    789: 
                    790:     IKBD_AddKeyToKeyboardBuffer(0xF0);    /* Assume OK, return correct code */
                    791: 
                    792:     /* Start timer - some commands are send during this time they may be ignored(see real ST!) */
                    793:     Int_AddRelativeInterrupt(IKBD_RESET_CYCLES,INTERRUPT_IKBD_RESETTIMER);
                    794:     /* Set this 'critical' flag, gets reset when timer expires */
                    795:     bMouseDisabled = bJoystickDisabled = FALSE;
                    796:     bDuringResetCriticalTime = TRUE;
                    797:   }
                    798:   /* else if not 0x80,0x01 just ignore */
                    799: #ifdef DEBUG_OUTPUT_IKBD
                    800:   Debug_IKBD("IKBD_Cmd_Reset\n");
                    801:   Debugger_TabIKBD_AddListViewItem("RESET");
                    802: #endif
                    803: }
                    804: 
1.1.1.2 ! root      805: 
        !           806: /*-----------------------------------------------------------------------*/
1.1       root      807: /*
                    808:   SET MOUSE BUTTON ACTION
                    809: 
                    810:   0x07
                    811:   %00000mss  ; mouse button action
                    812:         ;  (m is presumed =1 when in MOUSE KEYCODE mode)
                    813:         ; mss=0xy, mouse button press or release causes mouse
                    814:         ;  position report
                    815:         ;  where y=1, mouse key press causes absolute report
                    816:         ;  and x=1, mouse key release causes absolute report
                    817:         ; mss=100, mouse buttons act like keys 
                    818: */
                    819: void IKBD_Cmd_MouseAction(void)
                    820: {
                    821:   KeyboardProcessor.Mouse.Action = Keyboard.InputBuffer[1];
                    822:   KeyboardProcessor.Abs.PrevReadAbsMouseButtons = ABS_PREVBUTTONS;
                    823: #ifdef DEBUG_OUTPUT_IKBD
                    824:   Debug_IKBD("IKBD_Cmd_MouseAction %d\n",(unsigned int)KeyboardProcessor.Mouse.Action);
                    825:   Debugger_TabIKBD_AddListViewItem("MouseAction %d",(unsigned int)KeyboardProcessor.Mouse.Action);
                    826: #endif
                    827: }
                    828: 
1.1.1.2 ! root      829: 
        !           830: /*-----------------------------------------------------------------------*/
1.1       root      831: /*
                    832:   SET RELATIVE MOUSE POSITION REPORTING
                    833: 
                    834:   0x08
                    835: */
                    836: void IKBD_Cmd_RelMouseMode(void)
                    837: {
                    838:   KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL;
                    839: #ifdef DEBUG_OUTPUT_IKBD
                    840:   Debug_IKBD("IKBD_Cmd_RelMouseMode\n");
                    841:   Debugger_TabIKBD_AddListViewItem("RelMouseMode");
                    842: #endif
                    843: }
                    844: 
1.1.1.2 ! root      845: 
        !           846: /*-----------------------------------------------------------------------*/
1.1       root      847: /*
                    848:   SET ABSOLUTE MOUSE POSITIONING
                    849: 
                    850:   0x09
                    851:   XMSB      ;X maximum (in scaled mouse clicks)
                    852:   XLSB
                    853:   YMSB      ;Y maximum (in scaled mouse clicks)
                    854:   YLSB
                    855: */
                    856: void IKBD_Cmd_AbsMouseMode(void)
                    857: {
                    858:   /* These maximums are 'inclusive' */
                    859:   KeyboardProcessor.MouseMode = AUTOMODE_MOUSEABS;
                    860:   KeyboardProcessor.Abs.MaxX = (((unsigned int)Keyboard.InputBuffer[1])<<8) | (unsigned int)Keyboard.InputBuffer[2];
                    861:   KeyboardProcessor.Abs.MaxY = (((unsigned int)Keyboard.InputBuffer[3])<<8) | (unsigned int)Keyboard.InputBuffer[4];
                    862: #ifdef DEBUG_OUTPUT_IKBD
                    863:   Debug_IKBD("IKBD_Cmd_AbsMouseMode %d,%d\n",KeyboardProcessor.Abs.MaxX,KeyboardProcessor.Abs.MaxY);
                    864:   Debugger_TabIKBD_AddListViewItem("AbsMouseMode %d,%d",KeyboardProcessor.Abs.MaxX,KeyboardProcessor.Abs.MaxY);
                    865: #endif
                    866: }
                    867: 
1.1.1.2 ! root      868: 
        !           869: /*-----------------------------------------------------------------------*/
1.1       root      870: /*
                    871:   SET MOUSE KEYCODE MODE
                    872: 
                    873:   0x0A
                    874:   deltax      ; distance in X clicks to return (LEFT) or (RIGHT)
                    875:   deltay      ; distance in Y clicks to return (UP) or (DOWN)
                    876: */
                    877: void IKBD_Cmd_MouseCursorKeycodes(void)
                    878: {
                    879:   KeyboardProcessor.MouseMode = AUTOMODE_MOUSECURSOR;
                    880:   KeyboardProcessor.Mouse.KeyCodeDeltaX = Keyboard.InputBuffer[1];
                    881:   KeyboardProcessor.Mouse.KeyCodeDeltaY = Keyboard.InputBuffer[2];  
                    882: #ifdef DEBUG_OUTPUT_IKBD
                    883:   Debug_IKBD("IKBD_Cmd_MouseCursorKeycodes %d,%d\n",(int)KeyboardProcessor.Mouse.KeyCodeDeltaX,(int)KeyboardProcessor.Mouse.KeyCodeDeltaY);
                    884:   Debugger_TabIKBD_AddListViewItem("MouseCursorKeycodes %d,%d",(int)KeyboardProcessor.Mouse.KeyCodeDeltaX,(int)KeyboardProcessor.Mouse.KeyCodeDeltaY);
                    885: #endif
                    886: }
                    887: 
1.1.1.2 ! root      888: 
        !           889: /*-----------------------------------------------------------------------*/
1.1       root      890: /*
                    891:   SET MOUSE THRESHOLD
                    892: 
                    893:   0x0B
                    894:   X      ; x threshold in mouse ticks (positive integers)
                    895:   Y      ; y threshold in mouse ticks (positive integers)
                    896: */
                    897: void IKBD_Cmd_SetMouseThreshold(void)
                    898: {
                    899:   KeyboardProcessor.Mouse.XThreshold = (unsigned int)Keyboard.InputBuffer[1];
                    900:   KeyboardProcessor.Mouse.YThreshold = (unsigned int)Keyboard.InputBuffer[2];
                    901: #ifdef DEBUG_OUTPUT_IKBD
                    902:   Debug_IKBD("IKBD_Cmd_SetMouseThreshold %d,%d\n",KeyboardProcessor.Mouse.XThreshold,KeyboardProcessor.Mouse.YThreshold);
                    903:   Debugger_TabIKBD_AddListViewItem("SetMouseThreshold %d,%d",KeyboardProcessor.Mouse.XThreshold,KeyboardProcessor.Mouse.YThreshold);
                    904: #endif
                    905: }
                    906: 
1.1.1.2 ! root      907: 
        !           908: /*-----------------------------------------------------------------------*/
1.1       root      909: /*
                    910:   SET MOUSE SCALE
                    911: 
                    912:   0x0C
                    913:   X      ; horizontal mouse ticks per internel X
                    914:   Y      ; vertical mouse ticks per internel Y
                    915: */
                    916: void IKBD_Cmd_SetMouseScale(void)
                    917: {
                    918:   KeyboardProcessor.Mouse.XScale = (unsigned int)Keyboard.InputBuffer[1];
                    919:   KeyboardProcessor.Mouse.YScale = (unsigned int)Keyboard.InputBuffer[2];
                    920: #ifdef DEBUG_OUTPUT_IKBD
                    921:   Debug_IKBD("IKBD_Cmd_SetMouseScale %d,%d\n",KeyboardProcessor.Mouse.XScale,KeyboardProcessor.Mouse.YScale);
                    922:   Debugger_TabIKBD_AddListViewItem("SetMouseScale %d,%d",KeyboardProcessor.Mouse.XScale,KeyboardProcessor.Mouse.YScale);
                    923: #endif
                    924: }
                    925: 
                    926: /*-----------------------------------------------------------------------*/
                    927: /*
                    928:   INTERROGATE MOUSE POSITION
                    929: 
                    930:   0x0D
                    931:     Returns:  0xF7  ; absolute mouse position header
                    932:       BUTTONS
                    933:         0000dcba
                    934:         where a is right button down since last interrogation
                    935:         b is right button up since last
                    936:         c is left button down since last
                    937:         d is left button up since last
                    938:       XMSB      ; X coordinate
                    939:       XLSB
                    940:       YMSB      ; Y coordinate
                    941:       YLSB
                    942: */
                    943: void IKBD_Cmd_ReadAbsMousePos(void)
                    944: {
                    945:   unsigned char Buttons,PrevButtons;
                    946: 
                    947:   /* Test buttons */
                    948:   Buttons = 0;
                    949:   /* Set buttons to show if up/down */
                    950:   if (Keyboard.bRButtonDown)
                    951:     Buttons |= 0x01;
                    952:   else
                    953:     Buttons |= 0x02;
                    954:   if (Keyboard.bLButtonDown)
                    955:     Buttons |= 0x04;
                    956:   else
                    957:     Buttons |= 0x08;
                    958:   /* Mask off it didn't send last time */
                    959:   PrevButtons = KeyboardProcessor.Abs.PrevReadAbsMouseButtons;
                    960:   KeyboardProcessor.Abs.PrevReadAbsMouseButtons = Buttons;
                    961:   Buttons &= ~PrevButtons;
                    962: 
                    963:   /* And send packet */
                    964:   IKBD_AddKeyToKeyboardBuffer(0xf7);
                    965:   IKBD_AddKeyToKeyboardBuffer(Buttons);
                    966:   IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.X>>8);
                    967:   IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.X&0xff);
                    968:   IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.Y>>8);
                    969:   IKBD_AddKeyToKeyboardBuffer((unsigned int)KeyboardProcessor.Abs.Y&0xff);
                    970: 
                    971: #ifdef DEBUG_OUTPUT_IKBD
                    972:   Debug_IKBD("IKBD_Cmd_ReadAbsMousePos %d,%d 0x%X\n",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y,Buttons);
                    973:   Debugger_TabIKBD_AddListViewItem("ReadAbsMousePos %d,%d 0x%X",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y,Buttons);
                    974: #endif
                    975: }
                    976: 
                    977: /*-----------------------------------------------------------------------*/
                    978: /*
                    979:   LOAD MOUSE POSITION
                    980: 
                    981:   0x0E
                    982:   0x00      ; filler
                    983:   XMSB      ; X coordinate
                    984:   XLSB      ; (in scaled coordinate system)
                    985:   YMSB      ; Y coordinate
                    986:   YLSB
                    987: */
                    988: void IKBD_Cmd_SetInternalMousePos(void)
                    989: {  
                    990:   /* Setting these do not clip internal position(this happens on next update) */
                    991:   KeyboardProcessor.Abs.X = (((unsigned int)Keyboard.InputBuffer[2])<<8) | (unsigned int)Keyboard.InputBuffer[3];
                    992:   KeyboardProcessor.Abs.Y = (((unsigned int)Keyboard.InputBuffer[4])<<8) | (unsigned int)Keyboard.InputBuffer[5];
                    993: #ifdef DEBUG_OUTPUT_IKBD
                    994:   Debug_IKBD("IKBD_Cmd_SetInternalMousePos %d,%d\n",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y);
                    995:   Debugger_TabIKBD_AddListViewItem("SetInternalMousePos %d,%d",KeyboardProcessor.Abs.X,KeyboardProcessor.Abs.Y);
                    996: #endif
                    997: }
                    998: 
1.1.1.2 ! root      999: 
        !          1000: /*-----------------------------------------------------------------------*/
1.1       root     1001: /*
                   1002:   SET Y=0 AT BOTTOM
                   1003: 
                   1004:   0x0F
                   1005: */
                   1006: void IKBD_Cmd_SetYAxisDown(void)
                   1007: {
                   1008:   KeyboardProcessor.Mouse.YAxis = -1;
                   1009: #ifdef DEBUG_OUTPUT_IKBD
                   1010:   Debug_IKBD("IKBD_Cmd_SetYAxisDown\n");
                   1011:   Debugger_TabIKBD_AddListViewItem("SetYAxisDown");
                   1012: #endif
                   1013: }
                   1014: 
1.1.1.2 ! root     1015: 
        !          1016: /*-----------------------------------------------------------------------*/
1.1       root     1017: /*
                   1018:   SET Y=0 AT TOP
                   1019: 
                   1020:   0x10
                   1021: */
                   1022: void IKBD_Cmd_SetYAxisUp(void)
                   1023: {
                   1024:   KeyboardProcessor.Mouse.YAxis = 1;
                   1025: #ifdef DEBUG_OUTPUT_IKBD
                   1026:   Debug_IKBD("IKBD_Cmd_SetYAxisUp\n");
                   1027:   Debugger_TabIKBD_AddListViewItem("SetYAxisUp");
                   1028: #endif
                   1029: }
                   1030: 
1.1.1.2 ! root     1031: 
        !          1032: /*-----------------------------------------------------------------------*/
1.1       root     1033: /*
                   1034:   RESUME
                   1035: 
                   1036:   0x11
                   1037: */
                   1038: void IKBD_Cmd_StartKeyboardTransfer(void)
                   1039: {
                   1040: #ifdef DEBUG_OUTPUT_IKBD
                   1041:   Debug_IKBD("IKBD_Cmd_StartKeyboardTransfer\n");
                   1042:   Debugger_TabIKBD_AddListViewItem("StartKeyboardTransfer");
                   1043: #endif
                   1044: }
                   1045: 
1.1.1.2 ! root     1046: 
        !          1047: /*-----------------------------------------------------------------------*/
1.1       root     1048: /*
                   1049:   DISABLE MOUSE
                   1050: 
                   1051:   0x12
                   1052: */
                   1053: void IKBD_Cmd_TurnMouseOff(void)
                   1054: {
                   1055:   KeyboardProcessor.MouseMode = AUTOMODE_OFF;
                   1056:   bMouseDisabled = TRUE;
                   1057: #ifdef DEBUG_OUTPUT_IKBD
                   1058:   Debug_IKBD("IKBD_Cmd_TurnMouseOff\n");
                   1059:   Debugger_TabIKBD_AddListViewItem("TurnMouseOff");
                   1060: #endif
                   1061: 
                   1062:   IKBD_CheckResetDisableBug();
                   1063: }
                   1064: 
1.1.1.2 ! root     1065: 
        !          1066: /*-----------------------------------------------------------------------*/
1.1       root     1067: /*
                   1068:   PAUSE OUTPUT
                   1069: 
                   1070:   0x13
                   1071: */
                   1072: void IKBD_Cmd_StopKeyboardTransfer(void)
                   1073: {
                   1074: #ifdef DEBUG_OUTPUT_IKBD
                   1075:   Debug_IKBD("IKBD_Cmd_StopKeyboardTransfer\n");
                   1076:   Debugger_TabIKBD_AddListViewItem("StopKeyboardTransfer");
                   1077: #endif
                   1078: }
                   1079: 
1.1.1.2 ! root     1080: 
        !          1081: /*-----------------------------------------------------------------------*/
1.1       root     1082: /*
                   1083:   SET JOYSTICK EVENT REPORTING
                   1084: 
                   1085:   0x14
                   1086: */
                   1087: void IKBD_Cmd_ReturnJoystickAuto(void)
                   1088: {
                   1089:  KeyboardProcessor.JoystickMode = AUTOMODE_JOYSTICK;
                   1090:  KeyboardProcessor.MouseMode = AUTOMODE_OFF;
                   1091:  /* Again, if try to disable mouse within time of a reset it isn't disabled! */
                   1092:  if (bDuringResetCriticalTime)
                   1093:    KeyboardProcessor.MouseMode = AUTOMODE_MOUSEREL;
                   1094: #ifdef DEBUG_OUTPUT_IKBD
                   1095:  Debug_IKBD("IKBD_Cmd_ReturnJoystickAuto\n");
                   1096: #endif
                   1097: }
                   1098: 
1.1.1.2 ! root     1099: 
        !          1100: /*-----------------------------------------------------------------------*/
1.1       root     1101: /*
                   1102:   SET JOYSTICK INTERROGATION MODE
                   1103: 
                   1104:   0x15
                   1105: */
                   1106: void IKBD_Cmd_StopJoystick(void)
                   1107: {
                   1108:   KeyboardProcessor.JoystickMode = AUTOMODE_OFF;
                   1109: //  Debug_IKBD("IKBD_Cmd_StopJoystick\n");
                   1110: }
                   1111: 
1.1.1.2 ! root     1112: 
        !          1113: /*-----------------------------------------------------------------------*/
1.1       root     1114: /*
                   1115:   JOYSTICK INTERROGATE
                   1116: 
                   1117:   0x16
                   1118: */
                   1119: void IKBD_Cmd_ReturnJoystick(void)
                   1120: {
                   1121:   IKBD_AddKeyToKeyboardBuffer(0xFD);
                   1122:   IKBD_AddKeyToKeyboardBuffer(Joy_GetStickData(0));
                   1123:   IKBD_AddKeyToKeyboardBuffer(Joy_GetStickData(1));
                   1124: #ifdef DEBUG_OUTPUT_IKBD
                   1125:   Debug_IKBD("IKBD_Cmd_ReturnJoystick\n");
                   1126:   Debugger_TabIKBD_AddListViewItem("ReturnJoystick");
                   1127: #endif
                   1128: }
                   1129: 
1.1.1.2 ! root     1130: 
        !          1131: /*-----------------------------------------------------------------------*/
1.1       root     1132: /*
                   1133:   SET JOYSTICK MONITORING
                   1134: 
                   1135:   0x17
                   1136:   rate      ; time between samples in hundreths of a second
                   1137:     Returns: (in packets of two as long as in mode)
                   1138:       %000000xy  where y is JOYSTICK1 Fire button
                   1139:           and x is JOYSTICK0 Fire button
                   1140:       %nnnnmmmm  where m is JOYSTICK1 state
                   1141:           and n is JOYSTICK0 state
                   1142: */
                   1143: void IKBD_Cmd_SetJoystickDuration(void)
                   1144: {
                   1145: #ifdef DEBUG_OUTPUT_IKBD
                   1146:   Debug_IKBD("IKBD_Cmd_SetJoystickDuration\n");
                   1147:   Debugger_TabIKBD_AddListViewItem("SetJoystickDuration");
                   1148: #endif
                   1149: }
                   1150: 
1.1.1.2 ! root     1151: 
        !          1152: /*-----------------------------------------------------------------------*/
1.1       root     1153: /*
                   1154:   SET FIRE BUTTON MONITORING
                   1155: 
                   1156:   0x18
                   1157:     Returns: (as long as in mode)
                   1158:       %bbbbbbbb  ; state of the JOYSTICK1 fire button packed
                   1159:             ; 8 bits per byte, the first sample if the MSB
                   1160: */
                   1161: void IKBD_Cmd_SetJoystickFireDuration(void)
                   1162: {
                   1163: #ifdef DEBUG_OUTPUT_IKBD
                   1164:   Debug_IKBD("IKBD_Cmd_SetJoystickFireDuration\n");
                   1165:   Debugger_TabIKBD_AddListViewItem("SetJoystickFireDuration");
                   1166: #endif
                   1167: }
                   1168: 
1.1.1.2 ! root     1169: 
        !          1170: /*-----------------------------------------------------------------------*/
1.1       root     1171: /*
                   1172:   SET JOYSTICK KEYCODE MODE
                   1173: 
                   1174:   0x19
                   1175:   RX        ; length of time (in tenths of seconds) until
                   1176:           ; horizontal velocity breakpoint is reached
                   1177:   RY        ; length of time (in tenths of seconds) until
                   1178:           ; vertical velocity breakpoint is reached
                   1179:   TX        ; length (in tenths of seconds) of joystick closure
                   1180:           ; until horizontal cursor key is generated before RX
                   1181:           ; has elapsed
                   1182:   TY        ; length (in tenths of seconds) of joystick closure
                   1183:           ; until vertical cursor key is generated before RY
                   1184:           ; has elapsed
                   1185:   VX        ; length (in tenths of seconds) of joystick closure
                   1186:           ; until horizontal cursor keystokes are generated after RX
                   1187:           ; has elapsed
                   1188:   VY        ; length (in tenths of seconds) of joystick closure
                   1189:           ; until vertical cursor keystokes are generated after RY
                   1190:           ; has elapsed
                   1191: */
                   1192: void IKBD_Cmd_SetCursorForJoystick(void)
                   1193: {
                   1194: #ifdef DEBUG_OUTPUT_IKBD
                   1195:   Debug_IKBD("IKBD_Cmd_SetCursorForJoystick\n");
                   1196:   Debugger_TabIKBD_AddListViewItem("SetCursorForJoystick");
                   1197: #endif
                   1198: }
                   1199: 
1.1.1.2 ! root     1200: 
        !          1201: /*-----------------------------------------------------------------------*/
1.1       root     1202: /*
                   1203:   DISABLE JOYSTICKS
                   1204: 
                   1205:   0x1A
                   1206: */
                   1207: void IKBD_Cmd_DisableJoysticks(void)
                   1208: {
                   1209:   KeyboardProcessor.JoystickMode = AUTOMODE_OFF;
                   1210:   bJoystickDisabled = TRUE;
                   1211: #ifdef DEBUG_OUTPUT_IKBD
                   1212:   Debug_IKBD("IKBD_Cmd_DisableJoysticks\n");
                   1213:   Debugger_TabIKBD_AddListViewItem("DisableJoysticks");
                   1214: #endif
                   1215: 
                   1216:   IKBD_CheckResetDisableBug();
                   1217: }
                   1218: 
1.1.1.2 ! root     1219: 
        !          1220: /*-----------------------------------------------------------------------*/
1.1       root     1221: /*
                   1222:   TIME-OF-DAY CLOCK SET
                   1223: 
                   1224:   0x1B
                   1225:   YY        ; year (2 least significant digits)
                   1226:   MM        ; month
                   1227:   DD        ; day
                   1228:   hh        ; hour
                   1229:   mm        ; minute
                   1230:   ss        ; second
                   1231: */
                   1232: void IKBD_Cmd_SetClock(void)
                   1233: {
                   1234: #ifdef DEBUG_OUTPUT_IKBD
                   1235:   Debug_IKBD("IKBD_Cmd_SetClock\n");
                   1236:   Debugger_TabIKBD_AddListViewItem("SetClock");
                   1237: #endif
                   1238: }
                   1239: 
1.1.1.2 ! root     1240: 
        !          1241: /*-----------------------------------------------------------------------*/
1.1       root     1242: /*
                   1243:   INTERROGATE TIME-OF-DAT CLOCK
                   1244: 
                   1245:   0x1C
                   1246:     Returns:
                   1247:       0xFC  ; time-of-day event header
                   1248:       YY    ; year (2 least significant digits)
                   1249:       MM    ; month
                   1250:       DD    ; day
                   1251:       hh    ; hour
                   1252:       mm    ; minute
                   1253:       ss    ; second
                   1254: */
                   1255: void IKBD_Cmd_ReadClock(void)
                   1256: {
                   1257: /* FIXME */
                   1258: /*
                   1259:   SYSTEMTIME SystemTime;
                   1260: 
                   1261:   // Get windows time
                   1262:   GetSystemTime(&SystemTime);
                   1263: 
                   1264:   // Return packet
                   1265:   IKBD_AddKeyToKeyboardBuffer(0xFC);
                   1266:   // Return time-of-day clock as yy-mm-dd-hh-mm-ss as BCD
                   1267:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wYear%100));  // yy - year(2 least significant digits)
                   1268:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wMonth));     // mm - Month
                   1269:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wDay));       // dd - Day
                   1270:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wHour));      // hh - Hour
                   1271:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wMinute));    // mm - Minute
                   1272:   IKBD_AddKeyToKeyboardBuffer(Misc_ConvertToBCD(SystemTime.wSecond));    // ss - Second
                   1273: */
                   1274: #ifdef DEBUG_OUTPUT_IKBD
                   1275:   Debug_IKBD("IKBD_Cmd_ReadClock\n");
                   1276:   Debugger_TabIKBD_AddListViewItem("ReadClock");
                   1277: #endif
                   1278: }
                   1279: 
1.1.1.2 ! root     1280: 
        !          1281: /*-----------------------------------------------------------------------*/
1.1       root     1282: /*
                   1283:   MEMORY LOAD
                   1284: 
                   1285:   0x20
                   1286:   ADRMSB      ; address in controller
                   1287:   ADRLSB      ; memory to be loaded
                   1288:   NUM        ; number of bytes (0-128)
                   1289:   { data }
                   1290: */
                   1291: void IKBD_Cmd_LoadMemory(void)
                   1292: {
                   1293: #ifdef DEBUG_OUTPUT_IKBD
                   1294:   Debug_IKBD("IKBD_Cmd_LoadMemory\n");
                   1295:   Debugger_TabIKBD_AddListViewItem("LoadMemory");
                   1296: #endif
                   1297: }
                   1298: 
1.1.1.2 ! root     1299: 
        !          1300: /*-----------------------------------------------------------------------*/
1.1       root     1301: /*
                   1302:   MEMORY READ
                   1303: 
                   1304:   0x21
                   1305:   ADRMSB        ; address in controller
                   1306:   ADRLSB        ; memory to be read
                   1307:     Returns:
                   1308:       0xF6    ; status header
                   1309:       0x20    ; memory access
                   1310:       { data }  ; 6 data bytes starting at ADR
                   1311: */
                   1312: void IKBD_Cmd_ReadMemory(void)
                   1313: {
                   1314: #ifdef DEBUG_OUTPUT_IKBD
                   1315:   Debug_IKBD("IKBD_Cmd_ReadMemory\n");
                   1316:   Debugger_TabIKBD_AddListViewItem("ReadMemory");
                   1317: #endif
                   1318: }
                   1319: 
1.1.1.2 ! root     1320: 
        !          1321: /*-----------------------------------------------------------------------*/
1.1       root     1322: /*
                   1323:   CONTROLLER EXECUTE
                   1324: 
                   1325:   0x22
                   1326:   ADRMSB      ; address of subroutine in
                   1327:   ADRLSB      ; controller memory to be called
                   1328: */
                   1329: void IKBD_Cmd_Execute(void)
                   1330: {
                   1331: #ifdef DEBUG_OUTPUT_IKBD
                   1332:   Debug_IKBD("IKBD_Cmd_Execute\n");
                   1333:   Debugger_TabIKBD_AddListViewItem("Execute");
                   1334: #endif
                   1335: }
                   1336: 
                   1337: 
1.1.1.2 ! root     1338: /*-----------------------------------------------------------------------*/
1.1       root     1339: /*
                   1340:   Send data to keyboard processor via ACIA by writing to address 0xfffc02.
                   1341:   For our emulation we bypass the ACIA (I've yet to see anything check for this)
                   1342:   and add the byte directly into the keyboard input buffer.
                   1343: */
                   1344: void IKBD_RunKeyboardCommand(void)
                   1345: {
                   1346:   int i=0;
                   1347: 
1.1.1.2 ! root     1348:   /* Write into our keyboard input buffer */
1.1       root     1349:   Keyboard.InputBuffer[Keyboard.nBytesInInputBuffer++] = ACIAByte;
                   1350: 
1.1.1.2 ! root     1351:   /* Now check bytes to see if we have a valid/in-valid command string set */
1.1       root     1352:   while(KeyboardCommands[i].Command!=0xff) {
1.1.1.2 ! root     1353:     /* Found command? */
1.1       root     1354:     if (KeyboardCommands[i].Command==Keyboard.InputBuffer[0]) {
1.1.1.2 ! root     1355:       /* Is string complete, then can execute? */
1.1       root     1356:       if (KeyboardCommands[i].NumParameters==Keyboard.nBytesInInputBuffer) {
                   1357:         CALL_VAR(KeyboardCommands[i].pCallFunction);
                   1358:         Keyboard.nBytesInInputBuffer = 0;
                   1359:       }
                   1360: 
                   1361:       return;
                   1362:     }
                   1363:     
                   1364:     i++;
                   1365:   }
                   1366: 
1.1.1.2 ! root     1367:   /* Command not known, reset buffer(IKBD assumes a NOP) */
1.1       root     1368:   Keyboard.nBytesInInputBuffer = 0;
                   1369: }
                   1370: 
1.1.1.2 ! root     1371: 
        !          1372: /*-----------------------------------------------------------------------*/
1.1       root     1373: /*
                   1374:   Send byte to our keyboard processor, and execute
                   1375: */
                   1376: void IKBD_SendByteToKeyboardProcessor(unsigned short bl)
                   1377: {
1.1.1.2 ! root     1378:   ACIAByte = bl;              /* Store byte to pass */
        !          1379:   IKBD_RunKeyboardCommand();  /* And send */
1.1       root     1380: }
                   1381: 
1.1.1.2 ! root     1382: 
        !          1383: /*-----------------------------------------------------------------------*/
1.1       root     1384: /*
                   1385:   The byte stored in the ACIA 'ACIAByte' has been read by the CPU by reading from
                   1386:   address $fffc02. We clear the status flag and set the GPIP register to signal read.
                   1387: */
                   1388: unsigned short IKBD_GetByteFromACIA(void)
                   1389: {
1.1.1.2 ! root     1390:   /* ACIA is now reset */
1.1       root     1391:   ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__RX_BUFFER_FULL;
                   1392:   ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__INTERRUPT_REQUEST;
                   1393:   ACIAStatusRegister &= ~ACIA_STATUS_REGISTER__OVERRUN_ERROR;
                   1394: 
1.1.1.2 ! root     1395:   /* GPIP I4 - General Purpose Pin Keyboard/MIDI interrupt */
1.1       root     1396:   MFP_GPIP |= 0x10;
                   1397:   return ACIAByte;  /* Return byte from keyboard */
                   1398: }
                   1399: 
1.1.1.2 ! root     1400: 
        !          1401: /*-----------------------------------------------------------------------*/
1.1       root     1402: /*
                   1403:   Byte received in the ACIA from the keyboard processor. Store byte for read from $fffc02
                   1404:   and clear the GPIP I4 register. This register will be remain low until byte has been
                   1405:   read from ACIA.
                   1406: */
                   1407: void IKBD_InterruptHandler_ACIA(void)
                   1408: {
1.1.1.2 ! root     1409:   /* Remove this interrupt from list and re-order */
1.1       root     1410:   Int_AcknowledgeInterrupt();
                   1411: 
1.1.1.2 ! root     1412:   /* Copy keyboard byte, ready for read from $fffc02 */
1.1       root     1413:   ACIAByte = Keyboard.Buffer[Keyboard.BufferHead++];
                   1414:   Keyboard.BufferHead &= KEYBOARD_BUFFER_MASK;
                   1415:   
1.1.1.2 ! root     1416:   /* Did we get an over-run? Ie byte has arrived from keyboard processor BEFORE CPU has read previous one from ACIA */
1.1       root     1417:   if (ACIAStatusRegister&ACIA_STATUS_REGISTER__RX_BUFFER_FULL)
1.1.1.2 ! root     1418:     ACIAStatusRegister |= ACIA_STATUS_REGISTER__OVERRUN_ERROR;  /* Set over-run */
1.1       root     1419: 
1.1.1.2 ! root     1420:   /* ACIA buffer is now full */
1.1       root     1421:   ACIAStatusRegister |= ACIA_STATUS_REGISTER__RX_BUFFER_FULL;
1.1.1.2 ! root     1422:   /* Signal interrupt pending */
1.1       root     1423:   ACIAStatusRegister |= ACIA_STATUS_REGISTER__INTERRUPT_REQUEST;
1.1.1.2 ! root     1424:   /* GPIP I4 - General Purpose Pin Keyboard/MIDI interrupt */
        !          1425:   /* NOTE: GPIP will remain low(0) until keyboard data is read from $fffc02. */
1.1       root     1426:   MFP_GPIP &= ~0x10;
                   1427: 
1.1.1.2 ! root     1428:   /* Acknowledge in MFP circuit, pass bit,enable,pending */
1.1       root     1429:   MFP_InputOnChannel(MFP_KEYBOARD_BIT,MFP_IERB,&MFP_IPRB);
                   1430: 
1.1.1.2 ! root     1431:   /* Clear flag so can allow another byte to be sent along serial line */
1.1       root     1432:   bByteInTransitToACIA = FALSE;
1.1.1.2 ! root     1433:   /* If another key is waiting, start sending from keyboard processor now */
1.1       root     1434:   if (Keyboard.BufferHead!=Keyboard.BufferTail)
                   1435:     IKBD_SendByteToACIA();
                   1436: }
                   1437: 
                   1438: 
1.1.1.2 ! root     1439: /*-----------------------------------------------------------------------*/
1.1       root     1440: /*
                   1441:   Send a byte from the keyboard buffer to the ACIA. On a real ST this takes some time to send
                   1442:   so we must be as accurate in the timing as possible - bytes do not appear to the 68000 instantly!
                   1443:   We do this via an internal interrupt - neat!
                   1444: */
                   1445: void IKBD_SendByteToACIA(void)
                   1446: {
1.1.1.2 ! root     1447:   /* Transmit byte from keyboard processor to ACIA. This takes approx ACIA_CYCLES CPU clock cycles to complete */
1.1       root     1448:   if (!bByteInTransitToACIA) {
1.1.1.2 ! root     1449:     /* Send byte to ACIA */
1.1       root     1450:     Int_AddRelativeInterrupt(ACIA_CYCLES,INTERRUPT_IKBD_ACIA);
1.1.1.2 ! root     1451:     /* Set flag so only transmit one byte at a time */
1.1       root     1452:     bByteInTransitToACIA = TRUE;
                   1453:   }
                   1454: }
                   1455: 
1.1.1.2 ! root     1456: 
        !          1457: /*-----------------------------------------------------------------------*/
1.1       root     1458: /*
                   1459:   Add characer our internal keyboard buffer. These bytes are then sent one at a time to the ACIA.
                   1460:   This is done via a delay to mimick the STs internal workings, as this is needed for games such
                   1461:   as Carrier Command.
                   1462: */
                   1463: void IKBD_AddKeyToKeyboardBuffer(unsigned char Data)
                   1464: {
1.1.1.2 ! root     1465:   /* Is keyboard initialised yet? Ignore any bytes until it is */
1.1       root     1466:   if (!KeyboardProcessor.bReset)
                   1467:     return;
                   1468: 
1.1.1.2 ! root     1469:   /* Check we have space to add byte */
1.1       root     1470:   if (Keyboard.BufferHead!=((Keyboard.BufferTail+1)&KEYBOARD_BUFFER_MASK)) {
1.1.1.2 ! root     1471:     /* Add byte to our buffer */
1.1       root     1472:     Keyboard.Buffer[Keyboard.BufferTail++] = Data;
                   1473:     Keyboard.BufferTail &= KEYBOARD_BUFFER_MASK;
                   1474:     
1.1.1.2 ! root     1475:     /* We have character ready to transmit from the ACIA - see if can send it now */
1.1       root     1476:     IKBD_SendByteToACIA();
                   1477:   }
                   1478: }
                   1479: 
1.1.1.2 ! root     1480: 
        !          1481: /*-----------------------------------------------------------------------*/
1.1       root     1482: /*
                   1483:   When press/release key under Windows, execute this function
                   1484: */
                   1485: void IKBD_PressSTKey(unsigned char ScanCode,BOOL bPress)
                   1486: {
1.1.1.2 ! root     1487:   /* Ignore anything until we've redirected our GEM handlers */
1.1       root     1488: //FM  if (!bInitGemDOS)
                   1489: //FIXME    return;
                   1490:   if (!bPress)
                   1491:     ScanCode |= 0x80;    /* Set top bit if released key */
                   1492:   IKBD_AddKeyToKeyboardBuffer(ScanCode);  /* And send to keyboard processor */
                   1493: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.