?login_element?

Subversion Repositories NedoOS

Rev

Rev 1405 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;requires pg5 in 0x4000!!!
  2. ;; MASK-INT
  3. L0038   PUSH    AF              ; save the registers.
  4.         PUSH    HL              ; but not IY unfortunately.
  5.         LD      HL,(0x5C78)      ; fetch two bytes at FRAMES1.
  6.         INC     HL              ; increment lowest two bytes of counter.
  7.         LD      (0x5C78),HL      ; place back in FRAMES1.
  8.         LD      A,H             ; test if the result
  9.         OR      L               ; was zero.
  10.         JR      NZ,L0048        ; forward to KEY-INT if not.
  11.  
  12.         INC     (IY+0x40)        ; otherwise increment FRAMES3 the third byte.
  13.  
  14. ; now save the rest of the main registers and read and decode the keyboard.
  15.  
  16. ;; KEY-INT
  17. L0048   PUSH    BC              ; save the other
  18.         PUSH    DE              ; main registers.
  19.         CALL    L02BF           ; routine KEYBOARD executes a stage
  20.                                 ; in the process of reading a key-press.
  21.         POP     DE              ;
  22.         POP     BC              ; restore registers.
  23.         POP     HL              ;
  24.         POP     AF              ;
  25.         EI                      ; enable interrupts.
  26.         RET                     ; return.
  27.  
  28. ;-----------
  29. ; Key tables
  30. ;-----------
  31. ; These six look-up tables are used by the keyboard reading routine
  32. ; to decode the key values.
  33.  
  34. ; The first table contains the maps for the 39 keys of the standard
  35. ; 40-key Spectrum keyboard. The remaining key [SHIFT $27] is read directly.
  36. ; The key values 0-38 map to their ascii upper-case characters except for
  37. ; symbol-shift $0E.
  38.  
  39. ;; MAIN-KEYS
  40. L0205   DEFB    $42             ; B
  41.         DEFB    $48             ; H
  42.         DEFB    $59             ; Y
  43.         DEFB    $36             ; 6
  44.         DEFB    $35             ; 5
  45.         DEFB    $54             ; T
  46.         DEFB    $47             ; G
  47.         DEFB    $56             ; V
  48.         DEFB    $4E             ; N
  49.         DEFB    $4A             ; J
  50.         DEFB    $55             ; U
  51.         DEFB    $37             ; 7
  52.         DEFB    $34             ; 4
  53.         DEFB    $52             ; R
  54.         DEFB    $46             ; F
  55.         DEFB    $43             ; C
  56.         DEFB    $4D             ; M
  57.         DEFB    $4B             ; K
  58.         DEFB    $49             ; I
  59.         DEFB    $38             ; 8
  60.         DEFB    $33             ; 3
  61.         DEFB    $45             ; E
  62.         DEFB    $44             ; D
  63.         DEFB    $58             ; X
  64.         DEFB    $0E             ; SYMBOL SHIFT
  65.         DEFB    $4C             ; L
  66.         DEFB    $4F             ; O
  67.         DEFB    $39             ; 9
  68.         DEFB    $32             ; 2
  69.         DEFB    $57             ; W
  70.         DEFB    $53             ; S
  71.         DEFB    $5A             ; Z
  72.         DEFB    $20             ; SPACE
  73.         DEFB    $0D             ; ENTER
  74.         DEFB    $50             ; P
  75.         DEFB    $30             ; 0
  76.         DEFB    $31             ; 1
  77.         DEFB    $51             ; Q
  78.         DEFB    $41             ; A
  79.  
  80.  
  81. ;; E-UNSHIFT
  82. L022C   DEFB    $E3             ; READ
  83.         DEFB    $C4             ; BIN
  84.         DEFB    $E0             ; LPRINT
  85.         DEFB    $E4             ; DATA
  86.         DEFB    $B4             ; TAN
  87.         DEFB    $BC             ; SGN
  88.         DEFB    $BD             ; ABS
  89.         DEFB    $BB             ; SQR
  90.         DEFB    $AF             ; CODE
  91.         DEFB    $B0             ; VAL
  92.         DEFB    $B1             ; LEN
  93.         DEFB    $C0             ; USR
  94.         DEFB    $A7             ; PI
  95.         DEFB    $A6             ; INKEY$
  96.         DEFB    $BE             ; PEEK
  97.         DEFB    $AD             ; TAB
  98.         DEFB    $B2             ; SIN
  99.         DEFB    $BA             ; INT
  100.         DEFB    $E5             ; RESTORE
  101.         DEFB    $A5             ; RND
  102.         DEFB    $C2             ; CHR$
  103.         DEFB    $E1             ; LLIST
  104.         DEFB    $B3             ; COS
  105.         DEFB    $B9             ; EXP
  106.         DEFB    $C1             ; STR$
  107.         DEFB    $B8             ; LN
  108.  
  109.  
  110. ;; EXT-SHIFT
  111. L0246   DEFB    $7E             ; ~
  112.         DEFB    $DC             ; BRIGHT
  113.         DEFB    $DA             ; PAPER
  114.         DEFB    $5C             ; \
  115.         DEFB    $B7             ; ATN
  116.         DEFB    $7B             ; {
  117.         DEFB    $7D             ; }
  118.         DEFB    $D8             ; CIRCLE
  119.         DEFB    $BF             ; IN
  120.         DEFB    $AE             ; VAL$
  121.         DEFB    $AA             ; SCREEN$
  122.         DEFB    $AB             ; ATTR
  123.         DEFB    $DD             ; INVERSE
  124.         DEFB    $DE             ; OVER
  125.         DEFB    $DF             ; OUT
  126.         DEFB    $7F             ; (Copyright character)
  127.         DEFB    $B5             ; ASN
  128.         DEFB    $D6             ; VERIFY
  129.         DEFB    $7C             ; |
  130.         DEFB    $D5             ; MERGE
  131.         DEFB    $5D             ; ]
  132.         DEFB    $DB             ; FLASH
  133.         DEFB    $B6             ; ACS
  134.         DEFB    $D9             ; INK
  135.         DEFB    $5B             ; [
  136.         DEFB    $D7             ; BEEP
  137.  
  138.  
  139. ;; CTL-CODES
  140. L0260   DEFB    $0C             ; DELETE
  141.         DEFB    $07             ; EDIT
  142.         DEFB    $06             ; CAPS LOCK
  143.         DEFB    $04             ; TRUE VIDEO
  144.         DEFB    $05             ; INVERSE VIDEO
  145.         DEFB    $08             ; CURSOR LEFT
  146.         DEFB    $0A             ; CURSOR DOWN
  147.         DEFB    $0B             ; CURSOR UP
  148.         DEFB    $09             ; CURSOR RIGHT
  149.         DEFB    $0F             ; GRAPHICS
  150.  
  151.  
  152. ;; SYM-CODES
  153. L026A   DEFB    $E2             ; STOP
  154.         DEFB    $2A             ; *
  155.         DEFB    $3F             ; ?
  156.         DEFB    $CD             ; STEP
  157.         DEFB    $C8             ; >=
  158.         DEFB    $CC             ; TO
  159.         DEFB    $CB             ; THEN
  160.         DEFB    $5E             ; ^
  161.         DEFB    $AC             ; AT
  162.         DEFB    $2D             ; -
  163.         DEFB    $2B             ; +
  164.         DEFB    $3D             ; =
  165.         DEFB    $2E             ; .
  166.         DEFB    $2C             ; ,
  167.         DEFB    $3B             ; ;
  168.         DEFB    $22             ; "
  169.         DEFB    $C7             ; <=
  170.         DEFB    $3C             ; <
  171.         DEFB    $C3             ; NOT
  172.         DEFB    $3E             ; >
  173.         DEFB    $C5             ; OR
  174.         DEFB    $2F             ; /
  175.         DEFB    $C9             ; <>
  176.         DEFB    $60             ; pound
  177.         DEFB    $C6             ; AND
  178.         DEFB    $3A             ; :
  179.  
  180. ;; E-DIGITS
  181. L0284   DEFB    $D0             ; FORMAT
  182.         DEFB    $CE             ; DEF FN
  183.         DEFB    $A8             ; FN
  184.         DEFB    $CA             ; LINE
  185.         DEFB    $D3             ; OPEN#
  186.         DEFB    $D4             ; CLOSE#
  187.         DEFB    $D1             ; MOVE
  188.         DEFB    $D2             ; ERASE
  189.         DEFB    $A9             ; POINT
  190.         DEFB    $CF             ; CAT
  191.  
  192.  
  193. ;*******************************
  194. ;** Part 2. KEYBOARD ROUTINES **
  195. ;*******************************
  196.  
  197. ; Using shift keys and a combination of modes the Spectrum 40-key keyboard
  198. ; can be mapped to 256 input characters
  199.  
  200. ;----------------------------------------------------------------------------
  201. ;
  202. ;         0     1     2     3     4 -Bits-  4     3     2     1     0
  203. ; PORT                                                                    PORT
  204. ;
  205. ; F7FE  [ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ]  |  [ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 0 ]   EFFE
  206. ;  ^                                   |                                   v
  207. ; FBFE  [ Q ] [ W ] [ E ] [ R ] [ T ]  |  [ Y ] [ U ] [ I ] [ O ] [ P ]   DFFE
  208. ;  ^                                   |                                   v
  209. ; FDFE  [ A ] [ S ] [ D ] [ F ] [ G ]  |  [ H ] [ J ] [ K ] [ L ] [ ENT ] BFFE
  210. ;  ^                                   |                                   v
  211. ; FEFE  [SHI] [ Z ] [ X ] [ C ] [ V ]  |  [ B ] [ N ] [ M ] [sym] [ SPC ] 7FFE
  212. ;  ^     $27                                                 $18           v
  213. ; Start                                                                   End
  214. ;        00100111                                            00011000
  215. ;
  216. ;----------------------------------------------------------------------------
  217. ; The above map may help in reading.
  218. ; The neat arrangement of ports means that the B register need only be
  219. ; rotated left to work up the left hand side and then down the right
  220. ; hand side of the keyboard. When the reset bit drops into the carry
  221. ; then all 8 half-rows have been read. Shift is the first key to be
  222. ; read. The lower six bits of the shifts are unambiguous.
  223.  
  224. ;------------------
  225. ; Keyboard scanning
  226. ;------------------
  227. ; from keyboard and s-inkey$
  228. ; returns 1 or 2 keys in DE, most significant shift first if any
  229. ; key values 0-39 else 255
  230.  
  231. ;; KEY-SCAN
  232. L028E   LD      L,$2F           ; initial key value
  233.                                 ; valid values are obtained by subtracting
  234.                                 ; eight five times.
  235.         LD      DE,$FFFF        ; a buffer for 2 keys.
  236.        ld ix,keymatrix+7
  237.         LD      BC,$FEFE        ; the commencing port address
  238.                                 ; B holds 11111110 initially and is also
  239.                                 ; used to count the 8 half-rows
  240. ;; KEY-LINE
  241. L0296   ;IN      A,(C)           ; read the port to A - bits will be reset
  242.                                 ; if a key is pressed else set.
  243.        ld a,(ix)
  244.        dec ix
  245.         CPL                     ; complement - pressed key-bits are now set
  246.         AND     $1F             ; apply 00011111 mask to pick up the
  247.                                 ; relevant set bits.
  248.  
  249.         JR      Z,L02AB         ; forward to KEY-DONE if zero and therefore
  250.                                 ; no keys pressed in row at all.
  251.  
  252.         LD      H,A             ; transfer row bits to H
  253.         LD      A,L             ; load the initial key value to A
  254.  
  255. ;; KEY-3KEYS
  256. L029F   INC     D               ; now test the key buffer
  257.         RET     NZ              ; if we have collected 2 keys already
  258.                                 ; then too many so quit.
  259.  
  260. ;; KEY-BITS
  261. L02A1   SUB     $08             ; subtract 8 from the key value
  262.                                 ; cycling through key values (top = $27)
  263.                                 ; e.g. 2F>   27>1F>17>0F>07
  264.                                 ;      2E>   26>1E>16>0E>06
  265.         SRL     H               ; shift key bits right into carry.
  266.         JR      NC,L02A1        ; back to KEY-BITS if not pressed
  267.                                 ; but if pressed we have a value (0-39d)
  268.  
  269.         LD      D,E             ; transfer a possible previous key to D
  270.         LD      E,A             ; transfer the new key to E
  271.         JR      NZ,L029F        ; back to KEY-3KEYS if there were more
  272.                                 ; set bits - H was not yet zero.
  273.  
  274. ;; KEY-DONE
  275. L02AB   DEC     L               ; cycles 2F>2E>2D>2C>2B>2A>29>28 for
  276.                                 ; each half-row.
  277.         RLC     B               ; form next port address e.g. FEFE > FDFE
  278.         JR      C,L0296         ; back to KEY-LINE if still more rows to do.
  279.  
  280.         LD      A,D             ; now test if D is still FF ?
  281.         INC     A               ; if it is zero we have at most 1 key
  282.                                 ; range now $01-$28  (1-40d)
  283.         RET     Z               ; return if one key or no key.
  284.  
  285.         CP      $28             ; is it capsshift (was $27) ?
  286.         RET     Z               ; return if so.
  287.  
  288.         CP      $19             ; is it symbol shift (was $18) ?
  289.         RET     Z               ; return also
  290.  
  291.         LD      A,E             ; now test E
  292.         LD      E,D             ; but first switch
  293.         LD      D,A             ; the two keys.
  294.         CP      $18             ; is it symbol shift ?
  295.         RET                     ; return (with zero set if it was).
  296.                                 ; but with symbol shift now in D
  297.  
  298. ;-------------------------------
  299. ; Scan keyboard and decode value
  300. ;-------------------------------
  301. ; from interrupt 50 times a second
  302. ;
  303.  
  304. ;; KEYBOARD
  305. L02BF   CALL    L028E           ; routine KEY-SCAN
  306.         RET     NZ              ; return if invalid combinations
  307.  
  308. ; then decrease the counters within the two key-state maps
  309. ; as this could cause one to become free.
  310. ; if the keyboard has not been pressed during the last five interrupts
  311. ; then both sets will be free.
  312.  
  313.  
  314.         LD      HL,$5C00        ; point to KSTATE-0
  315.  
  316. ;; K-ST-LOOP
  317. L02C6   BIT     7,(HL)          ; is it free ?  ($FF)
  318.         JR      NZ,L02D1        ; forward to K-CH-SET if so
  319.  
  320.         INC     HL              ; address 5-counter
  321.         DEC     (HL)            ; decrease counter
  322.         DEC     HL              ; step back
  323.         JR      NZ,L02D1        ; forward to K-CH-SET if not at end of count
  324.  
  325.         LD      (HL),$FF        ; else mark it free.
  326.  
  327. ;; K-CH-SET
  328. L02D1   LD      A,L             ; store low address byte.
  329.         LD      HL,$5C04        ; point to KSTATE-4
  330.                                 ; (ld l, $04)
  331.         CP      L               ; have 2 been done ?
  332.         JR      NZ,L02C6        ; back to K-ST-LOOP to consider this 2nd set
  333.  
  334. ; now the raw key (0-38) is converted to a main key (uppercase).
  335.  
  336.         CALL    L031E           ; routine K-TEST to get main key in A
  337.         RET     NC              ; return if single shift
  338.  
  339.         LD      HL,$5C00        ; point to KSTATE-0
  340.         CP      (HL)            ; does it match ?
  341.         JR      Z,L0310         ; forward to K-REPEAT if so
  342.  
  343. ; if not consider the second key map.
  344.  
  345.         EX      DE,HL           ; save kstate-0 in de
  346.         LD      HL,$5C04        ; point to KSTATE-4
  347.         CP      (HL)            ; does it match ?
  348.         JR      Z,L0310         ; forward to K-REPEAT if so
  349.  
  350. ; having excluded a repeating key we can now consider a new key.
  351. ; the second set is always examined before the first.
  352.  
  353.         BIT     7,(HL)          ; is it free ?
  354.         JR      NZ,L02F1        ; forward to K-NEW if so.
  355.  
  356.         EX      DE,HL           ; bring back kstate-0
  357.         BIT     7,(HL)          ; is it free ?
  358.         RET     Z               ; return if not.
  359.                                 ; as we have a key but nowhere to put it yet.
  360.  
  361. ; continue or jump to here if one of the buffers was free.
  362.  
  363. ;; K-NEW
  364. L02F1   LD      E,A             ; store key in E
  365.         LD      (HL),A          ; place in free location
  366.         INC     HL              ; advance to interrupt counter
  367.         LD      (HL),$05        ; and initialize to 5
  368.         INC     HL              ; advance to delay
  369.         LD      A,($5C09)       ; pick up system variable REPDEL
  370.         LD      (HL),A          ; and insert that for first repeat delay.
  371.         INC     HL              ; advance to last location of state map.
  372.  
  373.         LD      C,(IY+$07)      ; pick up MODE  (3 bytes)
  374.         LD      D,(IY+$01)      ; pick up FLAGS (3 bytes)
  375.         PUSH    HL              ; save state map location
  376.                                 ; Note. could now have used.
  377.                                 ; ld l,$41; ld c,(hl); ld l,$3B; ld d,(hl).
  378.                                 ; six and two threes of course.
  379.         CALL    L0333           ; routine K-DECODE
  380.         POP     HL              ; restore map pointer
  381.         LD      (HL),A          ; put decoded key in last location of map.
  382.  
  383. ;; K-END
  384. L0308   LD      ($5C08),A       ; update LASTK system variable.
  385.         SET     5,(IY+$01)      ; FLAGS  - signal new key.
  386.         RET                     ; done
  387.  
  388. ;-------------------
  389. ; Repeat key routine
  390. ;-------------------
  391. ; A possible repeat has been identified. HL addresses the raw (main) key.
  392. ; The last location holds the decoded key (from the first context).
  393.  
  394. ;; K-REPEAT
  395. L0310   INC     HL              ; advance
  396.         LD      (HL),$05        ; maintain interrupt counter at 5
  397.         INC     HL              ; advance
  398.         DEC     (HL)            ; decrease REPDEL value.
  399.         RET     NZ              ; return if not yet zero.
  400.  
  401.         LD      A,($5C0A)       ; REPPER
  402.         LD      (HL),A          ; but for subsequent repeats REPPER will be used.
  403.         INC     HL              ; advance
  404.                                 ;
  405.         LD      A,(HL)          ; pick up the key decoded possibly in another
  406.                                 ; context.
  407.         JR      L0308           ; back to K-END
  408.  
  409. ;---------------
  410. ; Test key value
  411. ;---------------
  412. ; also called from s-inkey$
  413. ; begin by testing for a shift with no other.
  414.  
  415. ;; K-TEST
  416. L031E   LD      B,D             ; load most significant key to B
  417.                                 ; will be $FF if not shift.
  418.         LD      D,$00           ; and reset D to index into main table
  419.         LD      A,E             ; load least significant key from E
  420.         CP      $27             ; is it higher than 39d   i.e. FF
  421.         RET     NC              ; return with just a shift (in B now)
  422.  
  423.         CP      $18             ; is it symbol shift ?
  424.         JR      NZ,L032C        ; forward to K-MAIN if not
  425.  
  426. ; but we could have just symbol shift and no other
  427.  
  428.         BIT     7,B             ; is other key $FF (ie not shift)
  429.         RET     NZ              ; return with solitary symbol shift
  430.  
  431.  
  432. ;; K-MAIN
  433. L032C   LD      HL,L0205        ; address: MAIN-KEYS
  434.         ADD     HL,DE           ; add offset 0-38
  435.         LD      A,(HL)          ; pick up main key value
  436.         SCF                     ; set carry flag
  437.         RET                     ; return    (B has other key still)
  438.  
  439. ;------------------
  440. ; Keyboard decoding
  441. ;------------------
  442. ; also called from s-inkey$
  443.  
  444. ;; K-DECODE
  445. L0333   LD      A,E             ; pick up the stored main key
  446.         CP      $3A             ; an arbitrary point between digits and letters
  447.         JR      C,L0367         ; forward to K-DIGIT with digits,space,enter
  448.  
  449.         DEC     C               ; decrease MODE ( 0='KLC', 1='E', 2='G')
  450.  
  451.         JP      M,L034F         ; to K-KLC-LET if was zero
  452.  
  453.         JR      Z,L0341         ; to K-E-LET if was 1 for extended letters.
  454.  
  455. ; proceed with graphic codes.
  456. ; Note. should selectively drop return address if code > 'U' ($55).
  457. ; i.e. abort the KEYBOARD call.
  458. ; e.g. cp 'V'; jr c addit; pop af; ;;addit etc. (5 bytes of instruction).
  459. ; (s-inkey$ never gets into graphics mode.)
  460.  
  461. ;; addit
  462.         ADD     A,$4F           ; add offset to augment 'A' to graphics A say.
  463.         RET                     ; return.
  464.                                 ; Note. ( but [GRAPH] V gives RND, etc ).
  465.  
  466. ; the jump was to here with extended mode with uppercase A-Z.
  467.  
  468. ;; K-E-LET
  469. L0341   LD      HL,L022C-$41    ; base address of E-UNSHIFT L022c
  470.                                 ; ( $01EB in standard ROM )
  471.         INC     B               ; test B is it empty i.e. not a shift
  472.         JR      Z,L034A         ; forward to K-LOOK-UP if neither shift
  473.  
  474.         LD      HL,L0246-$41    ; Address: $0205 L0246-$41 EXT-SHIFT base
  475.  
  476. ;; K-LOOK-UP
  477. L034A   LD      D,$00           ; prepare to index
  478.         ADD     HL,DE           ; add the main key value
  479.         LD      A,(HL)          ; pick up other mode value
  480.         RET                     ; return
  481.  
  482. ; the jump was here with mode = 0
  483.  
  484. ;; K-KLC-LET
  485. L034F   LD      HL,L026A-$41    ; base of sym-codes
  486.         BIT     0,B             ; shift=$27 sym-shift=$18
  487.         JR      Z,L034A         ; back to K-LOOK-UP with symbol-shift
  488.  
  489.         BIT     3,D             ; test FLAGS is it 'K' mode (from OUT-CURS)
  490.         JR      Z,L0364         ; skip to K-TOKENS if so
  491.  
  492.         BIT     3,(IY+$30)      ; test FLAGS2 - consider CAPS LOCK ?
  493.         RET     NZ              ; return if so with main code.
  494.  
  495.         INC     B               ; is shift being pressed ?
  496.                                 ; result zero if not
  497.         RET     NZ              ; return if shift pressed.
  498.  
  499.         ADD     A,$20           ; else convert the code to lower case.
  500.         RET                     ; return.
  501.  
  502. ; the jump was here for tokens
  503.  
  504. ;; K-TOKENS
  505. L0364   ADD     A,$A5           ; add offset to main code so that 'A'
  506.                                 ; becomes 'NEW' etc.
  507.         RET                     ; return
  508.  
  509. ; the jump was here with digits, space, enter and symbol shift (< $xx)
  510.  
  511. ;; K-DIGIT
  512. L0367   CP      $30             ; is it '0' or higher ?
  513.         RET     C               ; return with space, enter and symbol-shift
  514.  
  515.         DEC     C               ; test MODE (was 0='KLC', 1='E', 2='G')
  516.         JP      M,L039D         ; jump to K-KLC-DGT if was 0.
  517.  
  518.         JR      NZ,L0389        ; forward to K-GRA-DGT if mode was 2.
  519.  
  520. ; continue with extended digits 0-9.
  521.  
  522.         LD      HL,L0284-$30    ; $0254 - base of E-DIGITS
  523.         BIT     5,B             ; test - shift=$27 sym-shift=$18
  524.         JR      Z,L034A         ; to K-LOOK-UP if sym-shift
  525.  
  526.         CP      $38             ; is character '8' ?
  527.         JR      NC,L0382        ; to K-8-&-9 if greater than '7'
  528.  
  529.         SUB     $20             ; reduce to ink range $10-$17
  530.         INC     B               ; shift ?
  531.         RET     Z               ; return if not.
  532.  
  533.         ADD     A,$08           ; add 8 to give paper range $18 - $1F
  534.         RET                     ; return
  535.  
  536. ; 89
  537.  
  538. ;; K-8-&-9
  539. L0382   SUB     $36             ; reduce to 02 and 03  bright codes
  540.         INC     B               ; test if shift pressed.
  541.         RET     Z               ; return if not.
  542.  
  543.         ADD     A,$FE           ; subtract 2 setting carry
  544.         RET                     ; to give 0 and 1    flash codes.
  545.  
  546. ;  graphics mode with digits
  547.  
  548. ;; K-GRA-DGT
  549. L0389   LD      HL,L0260-$30    ; $0230 base address of CTL-CODES
  550.         CP      $39             ; '9' ?
  551.         JR      Z,L034A         ; to K-LOOK-UP changed to $0F
  552.  
  553.         CP      $30             ; '0' ?
  554.         JR      Z,L034A         ; to K-LOOK-UP changed to $0C
  555.  
  556. ; for keys '0' - '7' we assign a mosaic character depending on shift.
  557.  
  558.         AND     $07             ; convert character to number. 0 - 7.
  559.         ADD     A,$80           ; add offset - they start at $80
  560.  
  561.         INC     B               ; destructively test for shift
  562.         RET     Z               ; and return if not pressed.
  563.  
  564.         XOR     $0F             ; toggle bits becomes range $88-$8F
  565.         RET                     ; return.
  566.  
  567. ; now digits in 'KLC' mode
  568.  
  569. ;; K-KLC-DGT
  570. L039D   INC     B               ; return with digit codes if neither
  571.         RET     Z               ; shift pressed.
  572.  
  573.         BIT     5,B             ; test for caps shift
  574.         LD      HL,L0260-$30    ; base of table CTL-CODES
  575.         JR      NZ,L034A        ; back to K-LOOK-UP
  576.  
  577. ; must have been symbol shift
  578.  
  579.         SUB     $10             ; for ascii most will now be correct
  580.                                 ; on a standard typewriter.
  581.         CP      $22             ; but '@' is not - see below.
  582.         JR      Z,L03B2         ; forward to to K-@-CHAR if so
  583.  
  584.         CP      $20             ; '_' is the other one that fails
  585.         RET     NZ              ; return if not.
  586.  
  587.         LD      A,$5F           ; substitute ascii '_'
  588.         RET                     ; return.
  589.  
  590. ;; K-@-CHAR
  591. L03B2   LD      A,$40           ; substitute ascii '@'
  592.         RET                     ; return.
  593.  
  594.