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

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

unix.superglobalmegacorp.com

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