ƒGeosKeyboard    XfPRG formatted GEOS file V1.0 ¾~ ð€Paint OVERLAYOARD    f¿ÿÿÿ€ÿˆ‹ÿÁŠAŠÿñŠ€ŠŽŠ€Š¿‘Š€ŠŸŠ€Š¿‘Ž€‚¿‘ƒ€€€€ÿñÿÿÿƒÿÿWrite Image V2.1geoWrite V2.1ðcommodoreta V2.3Please Select Option:new documentexisting documentto deskTopFile exists %  7 ö Á ¨ ´ / pÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(XP XXXXXX(Œ@GEOSŒTMŒ Œ@Keyboard Scanning Notes-Œ (c) 1988 by Michael Schell All rights reseved. (XP XXXXXX( One of the aspects of GEOS most questioned by programmers is the keyboard scan. The question is asked in many forms. Some ask "How does GEOS detect the shift key?" Others ask "How can I redefine a key?" Understanding the methods used by GEOS to decode the keyboard is a small step to a greater understanding GEOS itself. The following is a map of all the routines and data tables used by GEOS to decode the keyboard. Hopefully no errors have crept in. This data was originally compiled using V1.2 in order to add the extra C128 keyboard characters to GEOS. The data was then used to create the DVORAK keyboard for GEOS. These three programs are on Q-link if you need more ideas. Sorry but the source code for those programs has long sinced disappeared (Thats why V1.3, etc. where never created.) Each routine follows the same format- ________________________________________________________ Œ@RoutineName ŒEntry addresses for v1.2/v1.3/Œ@v2.0 Œ& v128 Œ@Purpose:Œ A brief explanation of purpose. Œ@(Vector):Œ If the entry location is vectored that address is here. Œ@Actual Entry AddressŒ: Same as above. Œ@Called by :Œ A partial listing of where the routine is called from by v1.2/v1.3/Œ@v2.0Œ- v128. Œ@Input and/or Output Requirements:Œ Œ@DescriptionŒ: A longer description of what the routine does. (XP XXXXXX(____________________________________________________________ ŒCommented mapping of codeŒ ____________________________________________________________ (XP XXXXXX( Sorry, but I don't have the courage to include a disassembly of the code. You can use either geoDebuggerŒTMŒ if you use the 64 Version or if you use the C128 just go to BASIC from DESKTOP and type MONITOR. Just remember that GEOS is in BANK 1. Obviously the first routine needed is the interrupt routine which calls the keyboard scanning routines. Â&y(XP XXXXXX(0Œ (XP XXXXXX(______________________________________________________________Œ@ (XP XXXXXX(0IRQŒ $E2E9/$FAAA/Œ@$FAB0 Œ$C408 Œ@Purpose:Œ M(XP XXXXXX(0Œ (XP XXXXXX(______________________________________________________________Œ@ (XP XXXXXX(0IRQŒ $E2E9/$FAAA/Œ@$FAB0 Œ$C408 Œ@Purpose:Œ Main IRQ handling routine. Œ@65XX Hardware Vector:Œ $FFFE (64 version only) Œ@Actual Entry Address:Œ $E2E9/$FAAA/Œ@$FAB0Œ - $C408 Œ@Called by:Œ IRQVECTOR ($FFFE). Œ@Description: ŒGEOS sets up the system to cause interrupts 60 times a second. This routine handle these interrupts. (XP XXXXXX(______________________________________________________________ (XP XXXXXX(0Commodore 64 versions enter here: 1) $E2E9/FAAA/Œ@FAB0Œ: Push the X and Y-Registers on to the stack. Commodore 128 version enters here: 2) (Not in 64 versions)- $C2FE: Push $8897, $8898, $8899, $9E15, $9E14, $CA7C, and $CA81 onto the stack. 3) $E2ED/FAAE/Œ@FAB4Œ - $C424: Push JMPVEC Œ($41,42 on the 64- $42,43 on the 128)Œ onto the stack. 4) $E2F3/FAB4/Œ@FABAŒ - $C42A: Push returnAddress Œ($3D,3E)Œ onto the stack. 5) $E2F9/FABA/Œ@FAC0Œ - $C430: Push r0 thru r15 Œ($02 thru $21)Œ onto the stack. 6) $E303/$FAC4Œ@/FACAŒ: 64 Version pushes the RAM/ROM configuration to stack and switches in all RAM. 7) $E30A/FACB/Œ@FAD1Œ - $C43A: If dblClickCount Œ($8515)Œ is zero THEN: $E30D/FACE/Œ@FAD4Œ - $C43D: branch to step 9 (8 in 128 Version). ELSE: $E30F/FAD0/Œ@FAD9Œ - $C43F: Decrement double click count flag Œ($8515)Œ. 8) (not in 64 versions)- $C442: Call $F5CE ? 9) $E312/FAD3/Œ@FAD9 Œ- $C445: If QFLAG Œ($87D9)Œ is not zero THEN: $E317/FAD8/Œ@FADEŒ - $C44A: If the value of QFLAG + 1 is not zero THEN: $E31B/FADB/Œ@FAE1Œ - $C44D: Decrement QFLAG Œ($87D9)Œ. 10) $E31E/FADE/Œ@FAE4Œ - $C450: Call intKeyscan Œ($E36F/FB1F/ŒPFB25 Œ- $C4AA).Œ 11) (not in 64 version)- $C453: Call SetMouse Œ($FE89).Œ 12) $E321/FAE1/Œ@FAE7Œ - $C453: If alarmSetFlag Œ($880A on the 64- $881C on the 128)Œ is not zero THEN: $E326/FAE6/FAEC - $C45B: Decrement alarmSetFlagŒ($880A on the 64- $881C on the 128)Œ. 13) $E32A/FAE9/Œ@FAEFŒ - $C45E: Call intTop through intTopVector Œ($849D)Œ which usually points to InterruptMain Œ($C100)Œ by calling CallRoutineŒ ($C1D8)Œ. 14) $E333/FAF2/Œ@FAF8Œ - $C467: Call intBot through intBotVectorŒ ($849F)Œ which usually points to an application's interrupt handling routine by calling CallRoutineŒ ($C1D8). ¢$|(XPøXXXXXX(0Œ Œ@IRQŒ (cont) 15) $E33C/FAFB/Œ@FB01Œ - $C470: Clear the Raster Compare latch of giŒrq Œ(Œ$D019Œ)Œ by wŒriting a one to it. This re-enables normal GEOS inter(XPøXXXXXX(0Œ Œ@IRQŒ (cont) 15) $E33C/FAFB/Œ@FB01Œ - $C470: Clear the Raster Compare latch of giŒrq Œ(Œ$D019Œ)Œ by wŒriting a one to it. This re-enables normal GEOS interrupt request. 16) $E341/FB00/Œ@FB06Œ: Pull RAM/ROM configuration back off the stack. 17) $E344/FB03Œ@/FB09Œ - $C475: Pull r0 thruŒ r15 Œ(Œ$02 thru $21Œ)Œ baŒck off the stack. 18) $E34C/FB0B/Œ@FB12Œ - $C47D: Pull returnAdŒdress Œ(Œ$3D,3EŒ) Œ back Œoff the stack. 19) $E352/FB11/Œ@FB18Œ - $C483: Push JMŒPVECŒ (Œ$41,42 on the 64- $42,43 on the 128Œ)Œ on to the stack.Œ 20) (Not in 64)- $C489: Pull $8897, $8898, $8899, $9E15, $9E14, $CA7C, and $CA81 back off the stack (inverse order of course). 21) $E358/FB17/Œ@FB1EŒ - $C4A5: Pull the X and Y-Registers back off the stack. 22) $E35C/FB1B/Œ@FB21Œ: Load Accumulator from $880B. 23) $E35F/FB1E/Œ@FB24Œ - $C4A9: Exit. (XPx È XXX(______________________________________________________________ (XPx È XXX(0Œ@intKeyscanŒ $E36F/$FB1F/Œ@$FB25 Œ$C4AA Œ@PurposeŒ: Part IRQ routine which handles the scanning of the keyboard. Œ@Entry AddressŒ: $E36F/FB1F/Œ@FB25Œ - $C4AA Œ@Called byŒ: IRQ at JSR at $E31E/FADE/Œ@FAE4Œ - $C450 Œ@Description:Œ Checks the keyboard matrix saving the character of the key pressed on the keyboard queue. (XPx È XXX(_____________________________________________________________ (XPx È XXX(0 1) $E36F/FB1F/Œ@FB25Œ - $C4AA: If there is a value iŒn NXTKEY Œ(Œ$87EAŒ)Œ which shouŒld be placed in keyboard queue (i.eŒ. QFLAG Œ(Œ$87D9Œ)Œ eŒquals zero) THEN: 1a) $E374/FB24/Œ@FB2AŒ - $C4AF: Add NXTŒKEY Œ(Œ$87EAŒ)Œ to theŒ kŒeyboard queue by calling addKey Œ(Œ$E4F9/FCA8/ŒFCA6 Œ- $C677Œ).Œ 1b) $E37A/FB2A/Œ@FB30Œ - $C4B5: RŒeset QFLAGŒ (Œ$87D9Œ).Œ 2) $E37F/FB2F/Œ@FB35Œ - $C4BA: Set r1Œ+1Œ (Œ$05Œ)Œ to Œzero for later use as GEOS' version of SHFLAG. 3) $E383/FB33/Œ@FB39Œ - $C4BE: Test for any keypress by calliŒng keyPressedŒ (Œ$E389/FB69/ŒFB6F Œ-Œ Œ$C500Œ)Œ. 4) $E386/FB36/ŒFB3CŒ - $C4C1:Œ If no key is pressed then EXIT (step 7). 5) $E388/FB38/Œ@FB3EŒ - $C4C3: Test for SHIFT, CONTROL, & COMMODORE keysŒ by calling ShCmdrCntrl Œ(Œ$E547/FCF7/ŒFCF5 Œ- $C6C6Œ)Œ. LOOP: (C64 Version - From Y-Register = 7 Œto 0) (C128 Version - From Y-Register = 10 to 0) 6) $E38B/FB3BŒ@/FB41Œ - $C4C3: 6a) $E38D/FB3D/Œ@FB43Œ - $C4C8: ŒTest for keypress by calling keyPressed Œ(Œ$E389/FB69/ŒFB6F Œ-Œ Œ$C500Œ)Œ.  {(XPx È¨XXX(0Œ Œ@intKeyscanŒ (Cont.) 6b) $E390/FB40Œ@/FB46Œ - $C4CB: If no key is pressed then EXIT (step 7). 6c) $E392/FB42/Œ@FB48Œ - $C4CD: Scan matrix(XPx È¨XXX(0Œ Œ@intKeyscanŒ (Cont.) 6b) $E390/FB40Œ@/FB46Œ - $C4CB: If no key is pressed then EXIT (step 7). 6c) $E392/FB42/Œ@FB48Œ - $C4CD: Scan matrix line Y. 6d) $E39B/FB4BŒ@/FB51Œ - $C4E8: If key pressed for only one IRQ cycle, SKIP to end of loop. 6e) $E3A3/FB53/Œ@FB57 Œ- $C4ED: If key held for more than 2 IRQ cycles, SKIP to end of loop. 6f) $E3A8/FB58Œ@/FB5CŒ - $C4EF: Save matrix key press data on stack. 6g) $E3A9/FB59/Œ@FB64Œ - $C4F5: IF only one key pressed decode key into ASCII by calling decodeKey Œ($E3C4/FB74/ŒPFB7A Œ- $C510)Œ. 6h) $E3B1/FB61Œ@/FB67Œ - $C4F8: Save matrix key press from stack to memory. 6i) $E3B5/FB65/Œ@FB6BŒ - $C4FD: Repeat LOOP while Y-Register is positive. 7) $E3B8/FB68/Œ@FB6EŒ - $C4FF: Exit. (XPx È¨XXX(______________________________________________________ (XPx È XXX(0Œ@keyPressedŒ $E389/$FB69/Œ@$FB6F Œ$C500 (XPx È¨XXX(0Œ@Purpose:Œ Test for any keys pressed on keyboard matrix. Œ@Entry AddressŒ: $E389/FB69/Œ@FB6FŒ - $C500 Œ@Called by:Œ intKeyscan at $E383/FB33/Œ@FB39Œ - $C4BE and $E38D/FB3D/Œ@FB43Œ - $C4C8. Œ@Description:Œ Returns with ZERO flag in processor status register set if no keys on the keyboard are pressed. (XPx È¨XXX(______________________________________________________________ (XPx È¨XXX(01) $E3B9/FB69/Œ@FB6FŒ - $C500: Read all lines on keyboard matrix by setting all rows high. 2) $E3C1/FB71Œ@/FB77Œ - $C50D: Compare with no keys pressed (#$FF) and exit. (XPx È¨XXX(______________________________________________________ (XPx È XXX(0Œ@ShCmdrCntr Œ$E547/$FCF7Œ@/$FCF5 Œ$C6C6 (XPx È¨XXX(0Œ@PurposeŒ: Read SHIFT, COMMODORE, & CONTROL keys. Œ@Entry AddressŒ: $E547/FCF7Œ@/FCF5Œ - $C6C6 Œ@Called by: ŒintKeyscan at $E388/FB38/Œ@FB3EŒ - $C4C3 Œ@DescriptionŒ: Test SHIFT, C=, & CTRL key and set flags in r1H ($05). (XPx È¨XXX(______________________________________________________________ (XPx È¨XXX(01) $E547/FCF7/Œ@FCF5Œ - $C6C6: If LEFT SHIFT pressed (row 1, column 7) OR 2) $E556/FD07/Œ@FD05Œ - $C6D6: If RIGHT SHIFT pressed (row 6, col. 4) set bit 7 of r1H Œ($05)Œ. 3) $E569/FD19/Œ@FD17Œ - $C6E8: If COMMODORE key pressed (row 6, col. 5) set bit 6 of r1H Œ($05)Œ. 4) $E57D/FD2D/Œ@FD2BŒ - $C6FC: If CONTROL key pressed (row 6, col. 2) set bit 5 of r1H Œ($05).Œ 5) $E591/FD41/Œ@FD3FŒ - $C710: Exit. (XPx È¨XXX(______________________________________________________________ (XPx È¨XXX(0Œ@NOTEŒ: Each key is tested by first setting CIA#1 PORT A Œ($DC00)Œ so that every bit is high except for the keyboard row in question (i.e. since the left shift key is in row 1/column 7 CIA#1 Port A is set to $FD (%11111101)). Then CIA#1 Port B Œ($DC01)Œ is read, the bit settings are inverted (i.e. EOR #$FF), and all the bits except for the keyboard column in question are masked out (i.e. in case of left shift AND #$80 (%10000000)). Now the appropriate bits in $05 are set with OR. ¢ |(X(XPx Èð XX(0Œ______________________________________________________________ Œ@decodeKeyŒ $E3C4/$FB74/Œ@$FB7AŒ $C510 Œ@2_decodeKey Œ(in line code used on the 64) ($C527) Œ@PurposeŒ: Decode keyboard. Œ@Entry Address:Œ $E3C4/FB74/Œ@FB7AŒ - $C510 Œ@Called by:Œ IKYSCN at $E3A9/FB59/Œ@FB64Œ - $C4F5. Œ@DescriptionŒ: Decodes the keyboard. Œ@NoteŒ: On the 128 the routine is split into two routines: A main loop and the actual decoding routine. For clarity the addresses used by 2Œ€ ŒdecodeKey are in parenthesis. __________________________________________________________________ 1) $E3C4/FB74/Œ@FB7AŒ - $C510: Save key pressed passed from intKeyscan in r0LŒ ($02)Œ. LOOP: (from r1L Œ($04)Œ equals 7 to 0) 2) $E3C6/FB76/Œ@FB7CŒ - $C512: 2a) $E3CA/FB7A/Œ@FB80Œ - $C516: Put key pressed stored in r0L Œ($02)Œ into Accumulator, and loop counter stored in r1L Œ($04)Œ into X-Register. 2b) $E3CE/FB7E/Œ@FB84Œ - $C51A: If X-th bit of Accumulator is not set then skip to end of loop. 2c) (not in 64 version)- $C51F: Call 2Œ€_ŒdecodeKey Œ($C527)Œ to do steps 2d thru 2o. 2d) $E3D3/FB83/Œ@FB89Œ - ($C527): Set X-Register equal to Y-Register (keyboard matrix row) times eight+r1LŒ ($04-Œ keyboard matrix column). 2e) $E3DA/FB8A/Œ@FB90Œ - ($C52E): If SHIFT key pressed (bit 7 of r1H Œ($05)Œ is set) THEN: $E3DE/FB8E/Œ@FB94Œ - ($C532): Load Accumulator with shifted ASCII character from shiftedKeys Œ($E4B8/FC68/ŒPFC66 Œ- $C61F).Œ ELSE: $E3E4/FB94/Œ@FB9AŒ - ($C538): Load Accumulator with unshifted ASCII character from unshiftedKeys Œ($E478/FC28/ŒPFC26 Œ- $C5C7)Œ. 2f) (not in 64 version)- ($C53D): If CAPS LOCK key down THEN: (not in 64 version)- ($C543): Convert lowercase characters to uppercase by calling toUpper Œ($C711)Œ. 2g) $E3E7/FB97/Œ@FB9FŒ - ($C54A): If CONTROL key pressed (bit 5 of r1H Œ($05 is set)Œ THEN: 2g-1) $E3EF/FB9FŒ@/FBA5Œ - ($C550): Convert lowercase characters to uppercase by calling toUpper Œ($E592/FD42/ŒPFD40Œ - $C711).Œ 2g-2) $E3F4/FBA4/Œ@FBAAŒ - ($C555): If character is not between 'A' and 'Z' THEN: $E3FC/FBAC/Œ@FBB2Œ - ($C55D): ASCII Code equals character minus $40. 2h) $E401/FBB1Œ@/FBB7Œ - ($C562): If COMMODORE key pressed (bit 6 of r1H Œ($05)Œ is set) set bit 7 of ASCII character. 2i) $E40B/FBB8/Œ@FBC1Œ - ($C569): Load Accumulator with ASCII code saved in r0H Œ($03)Œ, and save Y-Register (keyboard matrix row) in r0H Œ($03)Œ. LOOP2: (from Y-Register equals 8 to 0) ÂG{(XPx Èð¨XX(0Œ Œ@decodeKeyŒ (co(XPx Èð¨XX(0Œ Œ@decodeKeyŒ (cont)Œ@ (XPx Èð XX(0Œ 2j) $E40F/FBBF/Œ@FBC5Œ - ($C570): Œ If Accumulator equals a Y-th commodoreKey Œ(Œ$E456/FC06/ŒFC0CŒ - $C5ADŒ)Œ THEN: Œ $E41B/FBCB/Œ@FBD1Œ - ($C57C): A special ASCII characteŒr from specialKey Œ(Œ$E45F/FC0F/ŒFC15Œ Œ- $C5B6Œ)Œ is needed to represent a key not on the keyboard. REPEAT LOOP 2.Œ 2k) $E41E/FBCE/Œ@FBD4Œ - ($C57F): Load Y-Register with keyboard matrix row in rŒ0HŒ (Œ$03Œ)Œ, and save Accumulator (ASCII code of key pressed) in r0H Œ(Œ$03Œ)Œ.Œ 2l) $E422/FBD2/Œ@FBD8 Œ- ($C583): If the ASCII code of the key press is $1F THEN: $E426/FBD6/Œ@FBDCŒ - ($C587) Branch to step 2m-2. 2m) $E428/FBD8/Œ@FBDEŒ - ($C589) Load X-Register Œwith r1L Œ(Œ$04 -loop counterŒ),Œ the Accumulator with r0L Œ(Œ$02 - key pressedŒ).Œ All Œbut X-th bit of the key pressed is masked out. This value is then masked against Y-th entry at mulŒtiKey Œ(Œ$87F3 on the 64 - $87F6 onŒ Œthe 128Œ)Œ. If the result iŒs not zero THEN: 2m-1) $E434/FBE4/Œ@FBEFŒ - ($C595): Put ASCŒII code for character in QUEUE by calling addKey Œ(Œ$E4F9/FCA8/ŒFCA6Œ- $C677Œ).Œ ELSE:Œ 2m-2) $E444/FBF4/Œ@FBFFŒ - ($C592): Report no keycode in NXTKEY. 2n) C128 version Only: 2Œ€ ŒdecodeKey returns to decodeKey. 2o): REPEAT LOOP ($E44E/FBFE/Œ@FC05Œ - $C522). 3) $E455/FC05/Œ@FC0BŒ - $C526: Exit. (XPx Èð   ( (XPx Èð   (_________________________________________________________________ (XPx Èð   (Œ@addKey Œ$E4F8/$FCA8Œ@/$FCA6 Œ$C677 Œ@Purpose:Œ Adds a key to keyboard queue. Œ@Entry AddressŒ: $E4F8/FCA8/Œ@FCA6Œ - $C677 Œ@Called by:Œ intKeyscan at $E377/FB27/Œ@FB2DŒ - $C4B2 and decodeKey at $E43E/FBEE/Œ@FBF4Œ - $C59F. Œ@DescriptionŒ: Adds a key to tail of keyboard queue, and updates pointers to reflect change. (XPx Èð   (________________________________________________________________ (XPx Èð   ( 1) (Version 2.0 only Œ@FCA6Œ): Save processor status in order to save interrupt flag value and disable interrupts. Entry point v1.2/v1.3 & v128. 2) $E4F8/FCA8/Œ@FCA8Œ - $C677: Set bit 7 oŒf pressFlag Œ(Œ$39Œ)Œ to show that Œthere is data in queue. 3) $E501/FCB1/Œ@FCB2Œ - $C680:StorŒe key at TAILŒ(Œ$87D8Œ)Œ of QUEUE Œ(Œ$87DAŒ)Œ. 4) $E508/FCB8/FCB9 - $C687:Œ IF TAIL + 1Œ does not equal HEAD Œ(Œ$87D9Œ) ŒTHEN: Inc TAIL moŒd 16 by calling incXŒmod16 Œ(Œ$E535/FCE5/ŒFCE3 Œ- $C6B4Œ)Œ. 5) Version 2.0- Œ$FCC1Œ@ ŒRestore status register (interrupt flag). 6) $E513/FCC3/Œ@FCC2Œ - $C692: Exit. ¢I|(XPx Èð XX(0Œ@incXmod16Œ Œ$E535/$FCE5/Œ@$FCE3Œ $C6B4 (XPx Èð XX(0Œ@incXmod16Œ Œ$E535/$FCE5/Œ@$FCE3Œ $C6B4 Œ@Purpose:Œ Cycle X-Register from 0-15 ($0-$F) Œ@Entry Address:Œ $E535/FCE5/Œ@FCE3Œ - $C6B4 (XPx Èð  X(Œ@Called by:Œ addKey at $E508/FCB8/Œ@FCB6Œ - $C687 and popKey at $E520/FCD0/Œ@FCCEŒ - $C69F. Œ@Description:Œ Inc X-Register until reaches $10, then resets to $00. (XPx Èð XX(___________________________________________________________________ 1) $E535/FCE5/Œ@FCE3Œ - $C6B4: Increment X-Register. 2) $E536/FCE6/Œ@FCE9Œ - $C6B5: If X-Register equals $10 set X-Register to zero. 3) $E53C/FCEC/Œ@FCEAŒ - $C6BB Exit (XPx Èð XX(__________________________________________________________________ (XPx Èð XX(Œ@toUpper Œ$E592/$FD42/Œ@$FD40Œ $C711 Œ@Purpose:Œ Converts lowercase ASCII to UPPERCASE. Œ@Entry Address:Œ $E592/FD42/Œ@FD40Œ - $C711 Œ@Called by: ŒdecodeKey at (128 only) $C546* and at $E3F2/FBA2/Œ@FBA7Œ - $C553*. *actually 2Œ€ ŒdecodeKey in 128 version.Œ@ DescriptionŒ: Compares character in Accumulator to see if it is lowercase ASCII. If so it subtracts $20 to convert to uppercase ASCII. (XPx Èð XX(_________________________________________________________________ (XPx Èð XX(1) $E592/FD42/Œ@FD40Œ - $C711: Save character onto stack. 2) $E593/FD43/Œ@FD41Œ - $C712: If character is lowercase THEN: 2a) $E59E/FD4E/Œ@FD4DŒ - $C71D: Subtract $20 to make uppercase. 2b) $E5A1/FD51/Œ@FD50Œ - $C720: Replace the character on the stack. 3) $E5A2/FD52/Œ@FD51Œ - $C721: Pull the ASCII character of the stack. 4) $E5A3/FD53/Œ@FD52Œ - $C722: EXIT. _______________________________________________________________ Œ@commodoreKeyŒ $E456/$FC06/Œ@$FC0CŒ $C5AD Œ@specialKeyŒ $E45F/$FC0F/Œ@$FC15Œ $C5B6 Œ@PurposeŒ: Translates COMMODORE key codes to special ASCII codes. Œ@Entry AddressŒ:commodoreKey: $E456/FC06/Œ@FCOC Œ- $C5AD specialKey: $E45F/FC0F/Œ@FC15 Œ- $C5B6 Œ@Called by:Œ commodoreKey: decodeKey at LDA,X at $E411/FBC1/Œ@FBC7Œ - $C572. specialKey: decodeKey at LDA,X at $E41B/FBCB/Œ@FBD1Œ - $C57C. Œ@DescriptionŒ: Translates C= key codes to special ASCII codes: $DB- C= ']' OR $BA- C= ':' becomes $7B- ASCII open bracket $DD- C= ']' OR $BB- C= ';' becomes $7D- ASCII closed bracket $DE- C= '?' becomes $7C- ASCII vertical line $AD- C= '-' becomes $5F- ASCII back arrow $AF- C= '/' becomes $5C- ASCII back slash $AA- C= '*' becomes $7E- ASCII back double quotes $C0- C= '@' becomes $60- ASCII accent (XPx Èð XX(___________________________________________________________ (XPx Èð XX($E456/FC06/Œ@FC0CŒ-$C5AD COMKEY .BYTE $DB,$DD,$DE,$AD,$AF,$AA,$C0,$BA ,$BB $E45F/FC0F/Œ@FC15Œ-$C5B6 SPASCI .BYTE $7B,$7D,$7C,$5F,$5C,$7E,$60,$7B, $7D ÂÅx(XPx Èð XX(0Œ@unshiftedKeysŒ $E478/$FC28/Œ@$FC26(XPx Èð XX(0Œ@unshiftedKeysŒ $E478/$FC28/Œ@$FC26Œ $C5C7 (XPx Èð   (Œ@Purpose:Œ Keyboard lookup table for unshifted keys. Œ@Entry Address:Œ $E478/FC28/Œ@FC26Œ - $C5C7 Œ@Called by:Œ decodeKey at $E3E4/FB94/Œ@FB9AŒ - $C538. Œ@Description:Œ Keyboard lookup table for un-shifted characters. (XPx Èð¨Ð (Œ@ COLUMN: 0 1 2 3 4 5 6 7 (XPx Èð È (Œ1) ROW 0: (XPx Èð¨È (2) ROW 1: 3 w a 4 x s e (XPx Èð¨Ð (3) ROW 2: 5 r d 6 c f t x 4) ROW 3: 7 y g 8 b h u v 5) ROW 4: 9 i j 0 m k o n 6) ROW 5: + p l - . : @ , 7) ROW 6: * ; = ? / 8) ROW 7: 1 2 q 128 Version Only: 9) Row 8: 8 5 2 4 7 1 A) Row 9: + - 6 9 3 (XPx Èð È (B) Row A: 0 * (XPx Èð¨Ð (________________________________________________________________ (XPx Èð¨Ð (Œ@notesŒ: 1- DELete returns $1D. 2- RETURN returns $0D. 3- CRSR RIGHT returns $1E. 4- F7 returns $0E. 5- F1 returns $01. 6- F3 returns $03. 7- F5 returns $05. 8- CRSR DN returns $11 9- SHIFT KEYS, CNTRL, and COMMODORE keys return $1F. A- British Pound key returns $18. B- HOME key returns $12. C- Back arrow returns $14. D- RUN/STOP returns $16. Œ@C128 Extra Keys: ŒG- HELP key returns $19. J- TAB key returns $09. K- ESC key return $1B. M- LINE FEED key returns $0A. N- ENTER key returns $0B. P- ALT key returns $1A. Q- CRSR UP ARROW key returns $10. R- CRSR DOWN ARROW key returns $11. S- CRSR LEFT ARROW key returns $08. T- CRSR RIGHT ARROW key returns $1e. U- NO SCROLL key returns $07. ¢Á|(X XXXXXXX(0Œ@shiftedKeysŒ $E4B8/$FC68/Œ@$FC66Œ $C61F Œ@PurposeŒ: Keyboard lookup table for shifted keys. Œ@Entry Address:Œ $E4B8/FC68/Œ@FC66Œ - $C61F Œ@Called b(X XXXXXXX(0Œ@shiftedKeysŒ $E4B8/$FC68/Œ@$FC66Œ $C61F Œ@PurposeŒ: Keyboard lookup table for shifted keys. Œ@Entry Address:Œ $E4B8/FC68/Œ@FC66Œ - $C61F Œ@Called by:Œ decodeKey at LDA,X at $E3DE/FB8E/Œ@FB94Œ - $C532. Œ@Description:Œ Keyboard lookup table for shift characters. (X        (0Œ@ COLUMN: 0 1 2 3 4 5 6 7Œ 1) ROW 0: 2) ROW 1: # W A $ Z S E 3) ROW 2: % R D & C F T X 4) ROW 3: ' Y G ( B H U V 5) ROW 4: ) I J 0 M K O N 6) ROW 5: + P L - > @ < 7) ROW 6: * = ^ ? 8) ROW 7: ! " Q Œ@128 Version Only:Œ 9) Row 8: 8 5 2 4 7 1 10) Row 9: + - 6 9 3 11) Row 10: 0 * (X        (_____________________________________________________________ (X        (0Œ@notes xX        xŒ1- INSert returns $1C. xX€      x2- RETURN returns $0D. 3- CRSR LEFT returns $08. 4- F8 returns $0F. 5- F2 returns $02. 6- F4 returns $04. 7- F6 returns $06. 8- CRSR UP returns $10. 9- SHIFT KEYS, CNTRL, and COMMODORE keys return $1F. A- British Pound key returns $18. B- CLR key returns $13. C- Back arrow returns $14. D- SHIFT RUN/STOP returns $17. E- Shift ':' returns $5B, true ASCII open square bracket. F- Shift ';' returns $5D, true ASCII closed square bracket. xX€       (Œ@C128 Extra Keys:Œ xX€      xG- HELP key returns $19. J- TAB key returns $09. K- ESC key return $1B. M- LINE FEED key returns $0A. N- ENTER key returns $0B. P- ALT key returns $1A. Q- CRSR UP ARROW key returns $10. R- CRSR DOWN ARROW key returns $11. S- CRSR LEFT ARROW key returns $08. T- CRSR RIGHT ARROW key returns $1e. xX€       xU- NO SCROLL key returns $07. (X€       (And thats about it, HOPE IT HELPS, Mike (MichaelS30 on Q-link) Œ@Note:Œ If you find this useful please make a tax deductible donation to your local Œ@Cystic Fibrosis Œfoundation.ò>‰kŒ - $C721: Pull the ASCII character of the stack. 4) $E5A3/FD53/Œ@FD52Œ - $C722: EXIT. ______________