/* $Revision Header *** Header built automatically - do not edit! *********** * * (C) Copyright 1991 by Peter Vorwerk * * Name .....: PCKeyMap.c * Created ..: Saturday 16-Mar-91 10:39 * Revision .: 0 * * Date Author Comment * ========= ======== ==================== * 16-Mar-91 Peter Vorwerk Created this file! * * $Revision Header ********************************************************/ #define REVISION 0 #define VERSION 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void Input_Code(void); /* Predefine the ASM-Handler */ struct MsgPort *IPort = NULL; struct IOStdReq *InputRequest = NULL; struct Interrupt Input_Handler; struct Task *MyTask; ULONG User_Routine; ULONG Qualifier , Code , MySignal, data , SigNum = 0L; /* These codes are PC RawCodes. PC_ALT means press the ALT key PC_nALT means release the ALT key PC_x means press the x key of the numeric block */ /* Remember, you MUST press and relase control keys as CTRL, ALT or SHIFT, while normal keys need only be pressed. */ #define PC_ALT (UBYTE) '\070' #define PC_nALT (UBYTE) '\270' #define PC_0 (UBYTE) '\122' #define PC_1 (UBYTE) '\117' #define PC_2 (UBYTE) '\120' #define PC_3 (UBYTE) '\121' #define PC_4 (UBYTE) '\113' #define PC_5 (UBYTE) '\114' #define PC_6 (UBYTE) '\115' #define PC_7 (UBYTE) '\107' #define PC_8 (UBYTE) '\110' #define PC_9 (UBYTE) '\111' struct IntuitionBase *IntuitionBase; struct Library *JanusBase = NULL; UBYTE *KeyB = NULL; UBYTE *IntR = NULL; /****************************** * * * PCKeyB() * * * ******************************/ /* Calculate the address of the keyboard-register (KeyB) and the keyboard-interrupt (IntR) of the XT/AT board. By writing a value in the KeyB and sending the interrupt, the XT/AT will assume we have pressed or released this key on the keyboard. */ void PCKeyB(void) { UBYTE *ptr; UWORD *offset; /* Die Keyboard Addresse ist als positiver Offset 0x72 in der Janus.library abgelegt. */ /* Achtung! Im 'Amiga SYSTEM-Handbuch wird die feste Addresse 0x7ffff als Keyboard Addresse genannt. Bei meinem Amiga 2000 mit AT Karte stimmte dies, jedoch nicht beim SideCar. Die Offset Struktur wurde experimentell ( teilweiser Speicherdump vom Programm PCWINDOW ) ermittelt. Zum Glück stimmte wenigstens die Adresse des Interrupts, so konnte ich im Speicher nach dem Auftreten dieser Kombination suchen und die nähere Umgebung disassemblieren. */ /* Keyboard address. Please note 0x7ffff is NOT the correct address in ALL Systems. You must calculate it by contents of (JanusBase + 0x72) + 0x7e000 !! */ /* I found this by disassembling the file PCWINDOW. */ KeyB = (UBYTE *) JanusBase; KeyB += 0x72; offset = (UWORD *) KeyB; ptr = (UBYTE *) GetJanusStart(); KeyB = ptr + 0x7e000; KeyB += *offset; IntR = ptr + 0x7fffb; /* Addresse aus 'Amiga SYSTEM-Handbuch' */ } /******************************* * * * Handler() * * * *******************************/ /* This is the C-code of my handler. This function will test, if a key has been pressed or released. If so this function test, if the actual window title start with the sequence " PC ". If this is true also, send a signal to the main process. The main process will determine which action should be done. */ struct InputEvent *Handler(struct InputEvent *Input, ULONG *Data) { char *s; struct InputEvent *Next; Next = Input; while(Next) { /* Is the Event produced of the keyboard ? */ if (Next->ie_Class == IECLASS_RAWKEY) { /* Starts the actual window with the sequence " PC " ? */ s = (char *) IntuitionBase->ActiveWindow->Title; if (strncmp(" PC ",s,4) == 0) { /* Save the Code and the Qualifier of the last Event ... */ Qualifier = Next->ie_Qualifier; Code = Next->ie_Code; /* ... and send a signal to the main process. */ Signal(MyTask,MySignal); } } /* Search for the next Event. */ Next = Next->ie_NextEvent; } /* Return the Event to the System, so that the other handlers can use it too. */ return(Input); } /*********************** * * * InitHandler() * * * ***********************/ /* Start the Handler. */ void InitHandler(void) { data = 0L; User_Routine = (ULONG) Handler; Input_Handler.is_Data = (APTR) &data; Input_Handler.is_Code = (void (*)())Input_Code; Input_Handler.is_Node.ln_Pri = 51; Input_Handler.is_Node.ln_Name = "PCKeyMap-Handler"; InputRequest->io_Data = (APTR) &Input_Handler; InputRequest->io_Command = IND_ADDHANDLER; DoIO((struct IORequest *) InputRequest); } /********************** * * * Input_Code() * * * **********************/ /* This is the assembler routine of the handler. We need it, because the system will send the parameter in a register. But a C-funtion search for the parameter on the stack. */ #asm public _geta4 public _Input_Code _Input_Code: move.l a4,-(sp) jsr _geta4 movem.l a0/a1,-(sp) move.l _User_Routine,a0 jsr (a0) movem.l (sp)+,a0/a1 move.l (sp)+,a4 rts #endasm /******************** * * * CloseAll() * * * ********************/ /* Normaly this function is not called. Only if an error occurs during the setup this function will be called. Try to close all open stuff. */ void CloseAll(void) { if (SigNum) { FreeSignal(SigNum); } if (InputRequest->io_Device) { CloseDevice((struct IORequest *) InputRequest); } if (InputRequest) { DeleteStdIO(InputRequest); } if (IPort) { DeletePort(IPort); } exit(10); } /************************ * * * OpenAll() * * * ************************/ /* Open the libraries and the ports. */ void OpenAll(void) { if (!(JanusBase = ArpOpenLibrary("janus.library",0L))) { Printf("\nCan't find JANUS.library\nAborted...\n"); exit(10); } if (!(IPort = CreatePort(NULL,0L))) { CloseAll(); } if (!(InputRequest = CreateStdIO(IPort))) { CloseAll(); } if (OpenDevice("input.device",0L,(struct IORequest *) InputRequest,0L)) { CloseAll(); } /* Get a signal for our own Task */ if ((SigNum = AllocSignal(-1L)) < 0) { CloseAll(); } MySignal = 1 << SigNum; /* Now start the Handler. */ InitHandler(); } /******************** * * * SendKey() * * * ********************/ /* This function will send the values to the keyboard-register and send the interrupt. */ void SendKey(UBYTE k1, UBYTE k2, UBYTE k3) { *KeyB = PC_ALT; *IntR = '\377'; /* 0xff */ Delay(1); *KeyB = k1; *IntR = '\377'; /* 0xff */ Delay(1); *KeyB = k2; *IntR = '\377'; /* 0xff */ Delay(1); *KeyB = k3; *IntR = '\377'; /* 0xff */ Delay(1); *KeyB = PC_nALT; *IntR = '\377'; /* 0xff */ Delay(1); } /******************** * * * CheckKey() * * * ********************/ /* Check which key has been pressed. */ void CheckKey(void) { switch(Code) { case 0x00: if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_1,PC_2,PC_6); } else { SendKey(PC_0,PC_9,PC_6); } break; case 0x01: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_1,PC_7,PC_3); } else { SendKey(PC_0,PC_4,PC_9); } } break; case 0x02: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_6,PC_4); } else { SendKey(PC_0,PC_5,PC_0); } } break; case 0x03: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_3,PC_5); } else { SendKey(PC_0,PC_5,PC_1); } } break; case 0x04: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_3,PC_6); } else { SendKey(PC_0,PC_5,PC_2); } } break; case 0x05: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_3,PC_7); } else { SendKey(PC_0,PC_5,PC_3); } } break; case 0x06: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_9,PC_4); } else { SendKey(PC_0,PC_5,PC_4); } } break; case 0x07: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_3,PC_8); } else { SendKey(PC_0,PC_5,PC_5); } } break; case 0x08: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_4,PC_2); } else { SendKey(PC_0,PC_5,PC_6); } } break; case 0x09: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_4,PC_0); } else { SendKey(PC_0,PC_5,PC_7); } } break; case 0x0a: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_4,PC_1); } else { SendKey(PC_0,PC_4,PC_8); } } break; case 0x0b: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_9,PC_5); } else { SendKey(PC_0,PC_4,PC_5); } } break; case 0x0c: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_4,PC_3); } else { SendKey(PC_0,PC_6,PC_1); } } break; case 0x0d: if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_1,PC_2,PC_4); } else { SendKey(PC_0,PC_9,PC_2); } break; case 0x1a: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_1,PC_2,PC_3); } else { SendKey(PC_0,PC_9,PC_1); } } break; case 0x1b: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_1,PC_2,PC_5); } else { SendKey(PC_0,PC_9,PC_3); } } break; case 0x29: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_5,PC_8); } else { SendKey(PC_0,PC_5,PC_9); } } break; case 0x2a: if (Qualifier & IEQUALIFIER_LALT || Qualifier & IEQUALIFIER_RALT ) { if (Qualifier & IEQUALIFIER_LSHIFT || Qualifier & IEQUALIFIER_RSHIFT ) { SendKey(PC_0,PC_3,PC_4); } else { SendKey(PC_0,PC_3,PC_9); } } break; } } int main(int argc, char *argv[]) { if (MyTask = FindTask("PCKeyMap-Handler")) { Printf("PCKeyMap is already installed !\n"); exit(5); } if (!(MyTask = FindTask(NULL))) { CloseAll(); } MyTask->tc_Node.ln_Name = "PCKeyMap-Handler"; /* Set own process name, so we can determine if the program is already in memory. */ OpenAll(); Printf("Installing PCKeyMap V%ld.%ld by Peter Vorwerk\tPUBLIC DOMAIN\n",VERSION,REVISION); PCKeyB(); /* Calculate the KeyBoardAddress. */ /* Do forever ... */ for(;;) { Wait(MySignal); CheckKey(); } /* We will never reach this statement, but my Compiler needs it. */ return(0); }