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

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

unix.superglobalmegacorp.com

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