M/C Part 11 Right. Now first things first - we've got to work out what these routines are going to do. Well, I can't see anyone needing more than 8 keys scanned in most games, so we can return the result of a scan easily in 1 byte. Now, to save time the routine will just look at the 8 keys in question. The easiest way to do this is to have a little table of 8 bytes at the end which defines the keys to use. The coding method is quite simple:- Firstly take the key half-row no. [ The rows are numbered from 0 - 8. 0 is "1" to "5"; 3 is "SHIFT" to "V"; 4 is "6" to "0"; 5 is "B" to "SYMBOL". This coincides with the Speccy keyboard layout, since the Coupe keyboard is just a Speccy's with a few bits stuck on. The other keys are each allocated a half-row to share with the "Speccy's" keys. In fact, here's a list of the rows: 0. 1 2 3 4 5 ESC TAB CAPS 1. Q W E R T F7 F8 F9 2. A S D F G F4 F5 F6 3. SHIFT Z X C V F1 F2 F3 4. 0 9 8 7 6 - + DEL 5. P O I U Y = " F0 6. ENTER L K J H ; : EDIT 7. SPACE SYMBL M N B , . INV 8. CTRL UP DOWN LEFT RIGHT Key no. > 0 1 2 3 4 5 6 7 Certain keys (SHIFT,SYMBOL, full stop/decimal point) are repeated on the keyboard but are treated by the coupe as exactly the same key. Now, once you have your row number, multiply it by 8 and remember it. Look up the key number in the table above, and add this on. This gives you your final data value. Right, now for the actual key scan routine. kscan LD BC,#0800 ; Empty C and set B to no. of ; keys to scan (8). kscan1 LD A,(HL) ; Get the key value from the ; data table RRA RRA ; Divide by 8 to get the half- RRA ; row no. AND %00001111 ; Strip away unwanted bits. LD E,A LD D,0 LD A,(HL) INC HL PUSH HL ; Save HL for later. LD HL,key_address ADD HL,DE ; key_address is a table of port ; values, in the same order as ; the rows listed above. This ; instruction will find the ; right one. LD D,A ; Use D as a temp. store. PUSH BC ; Save BC for later. LD C,254 ; Each half-row listed above ; contains 8 keys. The first 5 ; are input from port 254, the ; others from port 249. The ; base port, found in the ; table above, remains the MSB ; for both. This goes into B. LD B,(HL) IN A,(C) ; Input from the first port. AND %00011111 ; Strip away everything but the ; 5 keys. LD E,A ; Store it in E. LD C,249 IN A,(C) ; Input from the other port. AND %11100000 ; Isolate the 3 keys. OR E ; Merge this input with the ; input from earlier. CPL ; Invert it. The raw input from ; the ports gives, for each ; key, 0 if the key is pressed ; and 1 if is isn't. We want ; this the other way round, ; and CPL changes all the 1's ; to 0's and 0's to 1's. LD E,A ; Put this into E. POP BC ; Reclaim the values we saved POP HL ; earlier. LD A,D AND 7 ; Rotate our input from the JR Z,kscan3 ; ports until the key we want kscan2 RR E ; to study is bit 0. DEC A JR NZ,kscan2 kscan3 RR E ; Put bit 0 into carry, and then RL C ; carry into C. DJNZ kscan1 ; Loop back for other keys. RET key_address DB #F7,#FB,#FD,#FE,#EF,#DF,#BF,#7F,#FF To call our routine, we load HL with the address of out key data table, call kscan, and our output is in C. eg. LD HL,key_table CALL kscan RR C CALL C,fire . . C returns with each bit holding the status of a key, 1 means pressed, and 0 means the opposite. (That's not pressed, gimp!) The most significant bit holds the status of the first key in your table. In the above example, bit 0 hold the status of the fire button. You could use the 8 bits to cover the following: d0 FIRE d1 DOWN d2 UP d3 RIGHT d4 LEFT d5 PAUSE d6 QUIT d7 MUSIC ON/OFF At least, that's what I did! If you want to scan more than 8 keys, why not make two or more calls with different tables. For example, to scan for the keys Q,A,O,P & SPACE, together with joystick 1 and H (pause), ESC (quit), and F9 (music on/off): key_table DB 15,5,52,41,40,8,16,56 joy_table DB 15,5,52,36,35,33,34,32 scan_for_both LD HL,key_table CALL kscan PUSH BC LD HL,joy_table CALL kscan LD A,C POP BC OR C LD C,A RET Of course, this only applies if the same player can use either keys or joystick - not if player 2 is to use one of them too. This prevents the need for the player to select whether he wants to use keys or joystick. Now, I have a quibble with other games-writers. Of all the commercial games I have, only Triltex has the option to redefine keys. WHY? I reckon that this is really important, so here's the redefine keys routine from that very game: redefine LD HL,key_table LD B,8 r1 LD (HL),255 ; Fill the table with a INC HL ; dummy value DJNZ r1 LD B,8 LD IY,key_table ; Use IY to mark the ; position in the table of ; the current key we want. LD IX,redefine_tx ; IX is used to keep the ; address of the text of ; whatever key is wanted. ; You'll have to write a ; print text routine of ; your own, which uses IX ; to hold the start ; address. r2 PUSH BC ; Save BC CALL text ; Print the text. redef_scan LD HL,key_addresses+8 LD D,9 ; Work backwards through the ; port table, scanning all ; the keys and finding one ; that's pressed. ; Use D as a counter. r3 LD B,(HL) LD C,249 IN A,(C) CPL AND %11100000 LD E,A LD C,254 ; Scan all the keys in that IN A,(C) ; port. CPL AND %00011111 OR E LD B,8 ; Go though them to see if r4 RLCA ; one has been pressed. JR C,r5 ; If it has, jump to another DJNZ r4 ; part of the routine. DEC HL ; Otherwise, move on in the DEC D ; port table, scanning all JR NZ,r3 ; the keys. JR redef_scan ; If none have been pressed, ; start scanning again. r5 LD A,D ; Get the row number (1-9) DEC A ; Take away 1, to get a RLCA ; value between 0 and 8. RLCA ; Then multiply by 8. RLCA DEC B ; Find the key number, and OR B ; merge it in. LD HL,key_table ; Go through the key table LD B,8 ; and check that the key r6 CP (HL) ; is not already being JR Z,redef_scan ; used. If you have more INC HL ; than one table, add DJNZ r6 ; more scan checks. LD (IY+0),A ; If everything is OK, store INC IY ; the key value, and move ; on to the next key. POP BC ; Recover our key counter. DJNZ r2 ; Loop back for other keys. RET redefine_tx DM " PRESS....MUSIC " DB 255 DM " PRESS.....QUIT " DB 255 DM " PRESS.....HOLD " DB 255 DM " PRESS.....LEFT " DB 255 DM " PRESS....RIGHT " DB 255 DM " PRESS.......UP " DB 255 DM " PRESS.....DOWN " DB 255 DM " PRESS.....FIRE " DB 255