forked from utz82/HoustonTracker2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkeyhand.asm
1847 lines (1523 loc) · 30.7 KB
/
keyhand.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;************************************************************************************
;the key handler
;************************************************************************************
waitForKeyRelease ;wait for key release function.
_rdkeys
in a,(kbd)
cpl ;4 ;would be nice to skip these two lines
or a ;4 ;but somehow that doesn't work
jr nz,_rdkeys
_wait
ld b,a
ld a,(LastKey) ;reset ALPHA mode if last key pressed was not ALPHA
or a
jr nz,_resetLK
xor a
ld (AlphaFlag),a
setXYat #28, #88
call clearPrintBuf ;clear print buffer
call printBuf ;remove Alpha mode marker from screen
;ld b,0 ;unnecessary, printBuf returns with b=0 anyway
jr _waitlp
_resetLK
xor a ;clear LastKey flag
ld (LastKey),a
_waitlp ;waiting for keypad bounce
ex (sp),hl
ex (sp),hl
ld a,(hl)
;IF MODEL = TI83 || MODEL = TI8X || MODEL = TI8XS
IF MODEL != TI82
ld a,(hl)
ENDIF
djnz _waitlp
ret ;5
;*******************************************************************************
inputSlotNr
ld a,KBD_GROUP_ZERO
out (kbd),a
key_delay
in a,(kbd)
rra
jr nc,ik0
rra
jr nc,ik1
rra
jr nc,ik4
rra
jr nc,ik7
ld a,KBD_GROUP_DOT
out (kbd),a
key_delay
in a,(kbd)
rra
rra
jr nc,ik2
rra
jr nc,ik5
ld a,KBD_GROUP_MINUS ;group (-)/3/6/9/)/G/VARS
out (kbd),a
key_delay
in a,(kbd)
rra
rra
jr nc,ik3
rra
jr nc,ik6
jr inputSlotNr
ik0
ld b,0
jr kSlotSelect
ik1
ld b,1
jr kSlotSelect
ik2
ld b,2
jr kSlotSelect
ik3
ld b,3
jr kSlotSelect
ik4
ld b,4
jr kSlotSelect
ik5
ld b,5
jr kSlotSelect
ik6
ld b,6
jr kSlotSelect
ik7
ld b,7
kSlotSelect ;print state selection, and update it
setXYat #2b, #b2
ld a,b
ld (StateSelect),a ;store selected state
jr reprint
;call printCharL ;reprint current
;xor a
;ld (InputType),a ;reset input type
;call printCsr ;print cursor
;jp waitForKeyRelease
;**************
inputSingle ;aka set current octave
setXYat #23, #88
ld a,b
cp 7 ;check if input digit is in range 0..6
ret nc ;ignore keypress if it isn't
ld (COct),a ;store new current oct
reprint
call printCharL ;reprint current oct
xor a
ld (InputType),a ;reset input type
jp kdirskip2 ;print cursor & wait for key release
inputDouble ;input a double digit hex value
;IN: set iPrintPos and iUpdatePos
push af
iPrintPos equ $+1
ld de,0
call setXY
iUpdatePos equ $+1
ld hl,0
pop af
rra
jr c,inputDoubleLow ;if input val=6, we're inputting the low nibble
ld a,6 ;the next hex input should be a low nibble
ld (InputType),a
ld a,b ;load input digit
push af
add a,a
add a,a
add a,a
add a,a
ld (hl),a
pop af
call printCharL ;print it as upper nibble
iDUpdate
jp waitForKeyRelease
;ret
inputDoubleLow
xor a ;reset input type
ld (InputType),a
ld a,b
or (hl)
ld (hl),a
call printCharsNoFF
ld a,(CScrType) ;check what type of cursor to print
cp 2
jr nz,_normal
call printCsr2
jr wordSwitch-1
_normal
call printCsr
wordSwitch equ $+1
ld a,0
or a
jr z,iDUpdate
xor a
ld (wordSwitch),a
call waitForKeyRelease
ld hl,usrDrum
setXYat #2b, #a6
jp kSetBFull
inputWord
ex af,af'
ld a,1
ld (wordSwitch),a
ex af,af'
jr inputDouble
kHexInp ;handle hex digit input
ld b,a ;preserve the input value
or a ;clear carry
ld a,(InputType) ;determine input type
rra
jp c,inputSingle
rra
jp c,inputDouble
rra
jp c,inputWord
ld a,(CScrType) ;check screen type
or a
jp nz,kHexNoSeq
call getSeqOffset ;now seq. pointer in HL, current ptn# in (CPtn)
ld a,(AlphaFlag) ;check for Alpha mode
or a
jr z,_noalpha
ld a,b ;check if input char was 0
or a
jr nz,_noalpha ;if both Alpha mode and 0, delete pattern # at cursor
ld a,#ff
ld (hl),a
jp pagescroll+3
;ld a,(CsrPos)
;ld (OldCsrPos),a
;call printSeqScr0
;call printCsr
;jp waitForKeyRelease
_noalpha
ld a,(CsrPos) ;check whether we need to shift the digit to upper nibble
rra
ld a,b ;retrieve input value
jr c,_noShift
add a,a ;shift left 4 bits
add a,a
add a,a
add a,a
ld b,a
ld a,(CPtn) ;load current ptn value
and %00001111 ;delete upper nibble
jr _byteUpdate
_noShift
ld a,(CPtn) ;load current ptn value
and %11110000 ;delete lower nibble
_byteUpdate
or b ;combine with input value
ld e,a ;preserve in E
ld d,#7f ;make sure ptn# does not exceed #7f
ld a,(CsrPos) ;check column type
and 7 ;mask out bits that are irrelevant to horizontal pos
cp 6
jr c,_skip ;if column > 5
ld d,#3f ;we're setting fx ptn# - make sure it doesn't exceed #3f
_skip
ld a,e
and d
ld (hl),a ;and store it at song pointer
ld (CPtn),a
call setPrintPos
call updateSeqScr
ld a,(AutoInc) ;check AutoInc mode
or a
;jp z,kright
jp z,kRnoalpha ;if AutoInc mode is on, update cursor as if RIGHT key had been pressed
;jp printCsr ;else, simply reprint the cursor at the current position
jp kdirskip2
updateSeqScr ;update an entry on the sequence screen
ld a,(CsrPos) ;load cursor pos
and 3 ;check what type of column is being printed
cp 0 ;and select the print function accordingly
jr z,uRight
cp 1
jr z,uLeft
uBoth
ld a,(CPtn)
jp printChars
;ret
uRight
ld a,(CPtn)
push de
call printCharR
pop de
inc d
call setXY
ld a,(CPtn)
jp printCharL
;ret
uLeft
ld a,(CPtn)
push de
call printCharL
pop de
dec d
call setXY
ld a,(CPtn)
jp printCharR
;ret
;************************************************************************************
kHexNoSeq ;handling input on ptn screen
;IN: B=hex digit
dec a ;check if we're on an fx ptn screen
jp nz,kHexFX
kHexPtn
call findCurrPtn ;get ptn pointer into DE
ld h,0
ld a,(CsrPos) ;get cursor position
ld c,a ;preserve it in C
cpl ;convert it to ptn data offset
and #10
rrca
ld l,a
ld a,c
and #7
add a,l
ld l,a
add hl,de ;position to edit now referenced by HL
push hl ;a08a
ld a,c ;retrieve cursor position and determine if input is a note name or an octave
and 8
ld a,b ;retrieve input digit
jr nz,inputOct
inputNote
or a
jr z,_exitlp
cp #a ;check if input digit is A..G... handle G seperatly?
jp c,ignoreKeypress ;ignore keypress if it isn't
ld c,a ;preserve input digit in C
ld hl,notevals ;load note val conversion LUT pointer
add a,l ;add offset
ld l,a
ld a,(COct) ;fetch current octave
ld b,a
inc b
ld a,(AlphaFlag) ;check if ALPHA mode is active
or a
jr z,_skip ;if it is
ld a,#b ;check if input note was a B
sub c
jr z,_skip ;skip raising halftone if it was
ld a,1 ;add a half-tone (TODO: check if it's a valid halftone - or ignore and always go a halftone higher, also fine)
_skip
add a,(hl) ;get base note val
ld c,a ;preserve it in C
_lp
dec b
jp z,_exitlp
add a,12
jr _lp
_exitlp ;note val now in A
pop hl
ld (hl),a ;update note byte
or a
jr z,reprintDash
_reprint
call setPrintPos
push de
ld a,c ;restore base note val
dec a ;note names are offset by 1, correct it
ld hl,notenames ;point to note name LUT
add a,a ;A=A*2
ld e,a
ld d,0
add hl,de ;add offset to LUT pointer
ld d,(hl) ;get string into DE
inc hl
ld e,(hl)
call printDE
pop de ;retrieve print pos
inc d ;inc horiz. pos by 1
call setXY
ld a,(COct) ;print current octave
call printCharL
ld a,(RowPlay)
or a
call nz,rowPlay
skipRP
ld a,(AutoInc) ;move cursor down if AutoInc is enabled
or a
jp z,kpdown
jp kdirskip2 ;else return normally
reprintDash ;print dashes if new note byte = 0
call setPrintPos
push de
printTwoChars CHAR_DASH, CHAR_DASH
pop de
inc d
call setXY
call clearPrintBuf
ld a,CHAR_DASH
call printCharLNC
jr skipRP
inputOct
pop hl
cp 7 ;check if input digit is 0..6
jp nc,ignoreKeypress+1 ;ignore keypress if it isn't
push bc
ld a,(hl) ;load current note val
or a ;if no note is set
jp z,ignoreKeypress ;ignore keypress
call divNoteVal ;returns current octave in B, base note val in C
ld a,c
pop bc
ld c,b ;preserve input digit (new octave) in C
inc b
_lp
dec b
jr z,_skip
add a,12 ;for each octave >0, add 12 to base note val
jr _lp
_skip
inc a ;note vals are offset by 1
ld (hl),a ;store new load value
call setPrintPos
ld a,c ;retrieve input digit (new oct)
call printCharL ;print it
jr skipRP ;and update cursor
;************************************************************************************
kHexFX ;handle hex input on fx ptn scr
;IN: B=hex digit
ld a,(CPtn) ;locate current fx ptn in mem
ld hl,fxptntab
call findCurrFxPtn ;ptn pointer now in DE
ld hl,0
ld a,(CsrPos) ;read cursor position
ld c,a ;backup in C
bit 4,a ;convert cursor position into ptn data offset
jr z,_skip3
inc l
_skip3
and #20
rrca
add a,l
ld l,a
ld a,c
and #7
rlca
add a,l
ld l,a
add hl,de ;byte to edit now referenced by HL
ld a,c ;restore csrpos
and %00001000 ;determine whether input is hi or low nibble
ld a,b ;restore input val
jr nz,_skip ;if Z then it's a hi nibble
add a,a ;shift input value left 4 bits
add a,a
add a,a
add a,a
ld b,a
ld a,(hl)
and %00001111 ;clear upper nibble
jr _set
_skip
ld a,(hl)
and %11110000 ;clear lower nibble
_set
or b ;combine low and hi nibble
ld (hl),a
ld c,a
ld hl,CsrTab2
call setPrintPosFx
ld a,c
call printCharsNoFF
ld a,(AutoInc)
or a
jp z,kfdown
call printCsr2
jp waitForKeyRelease
ignoreKeypress
pop hl ;clear stack
;ret ;and back to where we came from
jp waitForKeyRelease
;************************************************************************************
setPrintPos ;set print position based on current cursor pos
;IN: nothing | OUT: print pos set and in DE; HL, A destroyed
ld hl,CsrTab
setPrintPosFx ;entry point for FX patterns, HL must be set to CsrTab2
ld a,(CsrPos)
add a,a
add a,l
ld l,a
ld a,(hl)
and %01111111 ;mask out bit 7 since cursor type is irrelevant at this point
ld d,a
inc l
ld a,(hl)
sub 5 ;actual horiz. pos = CsrPos - 5
ld e,a
jp setXY ;using the ret from setXY
;************************************************************************************
kfdown
call delCsr2 ;delete cursor
ld a,(CsrPos)
inc a ;jump to next row
ld d,a
and %00000111
or a
ld a,d
jr nz,kdirskipF ;if bottom row reached
add a,#18 ;jump to top of same column, 2nd half
cp #40
jr c,kdirskipF ;if bottom row on 2nd half reached
sub #40 ;jump to top of same colum, 1st half
kdirskipF
ld (CsrPos),a
call printCsr2
jp waitForKeyRelease
;ret
kfleft
ld a,(AlphaFlag) ;check Alpha mode
or a
jr z,_noalpha
;if Alpha is on, cycle through patterns
setXYat #23, #82 ;TODO: optimize | set printing pos
ld a,(CPtn) ;increment "current pattern" value
dec a
and #3f ;make sure we don't go above #7f
ld (CPtn),a
jp printFxScrNoInit ;and print the new pattern
_noalpha
call delCsr2 ;delete cursor
ld a,(CsrPos)
sub 8 ;jump to previous column
jr nc,kdirskipF ;if already in the 1st column
add a,#40 ;wrap to last column
jr kdirskipF
kfright
ld a,(AlphaFlag) ;check Alpha mode
or a
jr z,_noalpha
;if Alpha is on, cycle through patterns
setXYat #23, #82 ;TODO: optimize | set printing pos
ld a,(CPtn) ;increment "current pattern" value
inc a
and #3f ;make sure we don't go above #7f
ld (CPtn),a
jp printFxScrNoInit ;and print the new pattern
_noalpha
call delCsr2 ;delete cursor
ld a,(CsrPos)
add a,8 ;jump to next column
cp #40
jr c,kdirskipF ;if already in the last column
sub #40 ;wrap to first column
jr kdirskipF
kfup
call delCsr2
ld a,(CsrPos)
dec a
ld d,a
and %00000111
cp #7
ld a,d
jr nz,kdirskipF
sub #18 ;#ff-#18 doesn't set carry,
or a ;so we need to check if result was negative
jp p,kdirskipF ;like that
add a,#40
jr kdirskipF
kpdown
call delCsr ;delete cursor
ld a,(CsrPos)
inc a ;jump to next row
ld d,a
and %00000111
or a ;TODO: redundant?
ld a,d
jp nz,kdirskip ;if bottom row reached
add a,#8 ;jump to top of same column, 2nd half
cp #70
jp c,kdirskip ;if bottom row on 2nd half reached
sub #20 ;jump to top of same colum, 1st half
jp kdirskip
kpleft
ld a,(AlphaFlag) ;check Alpha mode
or a
jr z,_noalpha
;if Alpha is on, cycle through patterns
setXYat #23, #82 ;TODO: optimize | set printing pos
ld a,(CPtn) ;increment "current pattern" value
dec a
and #7f ;make sure we don't go above #7f
ld (CPtn),a
jp printPtnScrNoInit ;and print the new pattern
_noalpha
call delCsr
ld a,(CsrPos)
sub 8
cp #50
jp nc,kdirskip
add a,#20
jp kdirskip
kpright
ld a,(AlphaFlag) ;check Alpha mode
or a
jr z,_noalpha
;if Alpha is on, cycle through patterns
setXYat #23, #82 ;TODO: optimize | set printing pos
ld a,(CPtn) ;increment "current pattern" value
inc a
and #7f ;make sure we don't go above #7f
ld (CPtn),a
jp printPtnScrNoInit ;and print the new pattern
_noalpha ;do normal cursor movement
call delCsr
ld a,(CsrPos)
add a,8
cp #70
jp c,kdirskip
sub #20
jp kdirskip
kpup
call delCsr
ld a,(CsrPos)
dec a
ld d,a
and %00000111
cp #7
ld a,d
jp nz,kdirskip
sub #8
cp #50
jp nc,kdirskip
add a,#20
jp kdirskip
kup
ld a,(CsrPos)
ld (OldCsrPos),a
ld a,(AlphaFlag)
or a
jr z,kuskip
xor a
ld (FirstLineMS),a
call printSeqScr
jp kdirskip2
kuskip
call delCsr ;delete cursor
ld a,(CsrPos)
sub 8 ;subtract 8 from cursor pos
jp nc,kdirskip ;and that's it, unless cursor is about to go off-screen
ld a,(FirstLineMS) ;in that case, check what's the first line of sequence data on screen
or a
jp z,kdirskip2 ;if it's 0, don't change anything and that's it
dec a ;else, decrement FirstLine
;ld (FirstLineMS),a ;and store it
;call printSeqScr0 ;reprint sequence screen (without setting screen type / kdir jump table offset)
;jp kdirskip2
jr seqScrReprint
kright
ld a,(AlphaFlag) ;check for Alpha mode
or a
jr z,kRnoalpha
ld a,(FirstLineMS) ;if Alpha mode is set, scroll 1 page (10 lines)
add a,#a ;add 10 to FirstLine
pagescroll0
cp #f7
jr c,pagescroll ;if result is >#f6
ld a,#f6 ;set FirstLine to #f6
pagescroll
ld (FirstLineMS),a
reprintX
ld a,(CsrPos)
ld (OldCsrPos),a
reprintY
call printSeqScr0
call printCsr
jp waitForKeyRelease
kRnoalpha
call delCsr
ld a,(CsrPos)
inc a
cp #50 ;check if cursor pos limit reached
jr nz,kdirskip
;xor a
ld a,#48 ;if yes, move cursor to beginning of the same row
ld (OldCsrPos),a
jr kdskip+3 ;and scroll screen
kdown
ld a,(CsrPos)
ld (OldCsrPos),a
ld a,(AlphaFlag)
or a
jr z,kdskip
ld a,#f6
ld (FirstLineMS),a
call printSeqScr
jr kdirskip2
kdskip
call delCsr
ld a,(CsrPos)
add a,8
cp #50
jr c,kdirskip
ld a,(FirstLineMS) ;need to implement scroll/wrap here
cp #f6 ;#100 - 0a
jr z,kdirskip2
inc a
seqScrReprint
ld (FirstLineMS),a
call printSeqScr0
jr kdirskip2
kleft
ld a,(AlphaFlag) ;check for Alpha mode
or a
jr z,_noalpha
ld a,(FirstLineMS) ;if Alpha mode is set, scroll 1 page (10 lines)
sub #a
jr pagescroll0
_noalpha
call delCsr
ld a,(CsrPos)
sub 1
jr nc,kdirskip
;ld a,#4f
ld a,7
ld (OldCsrPos),a
jp kuskip+3
kdirskip
ld (CsrPos),a
kdirskip2
call printCsr
kdirskip3
jp waitForKeyRelease
;ret
kdir ;determine which direction key has been pressed
rra
jr nc,_kp
inc d
jp kdir
_kp
ld h,HIGH(kjumptab) ;set hi byte of jump table pointer
kdirswitch equ $+1 ;switch for changing the response to keypress according to ptn type
ld a,LOW(kjumptab)
add a,d ;add D*2
add a,d
ld l,a ;set lo byte of jump table pointer
ld e,(hl) ;get jump value into DE
inc l
ld d,(hl)
ex de,hl ;swap jump value into HL
jp (hl) ;and jump
;************************************************************************************
keyhand ;the main keyhandler
ld a,KBD_GROUP_DIRPAD ;group dirpad
out (kbd),a
IF MODEL != TI82
nop
nop
ENDIF
ld e,#ff
ld d,0
in a,(kbd)
cp e
jr nz,kdir
ld a,KBD_GROUP_ENTER ;group ENTER/+/-/*/div/^/CLEAR
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rra ;ENTER
jp nc,kenter
rra
jp nc,kplus ;+
rra
jp nc,kminus ;-
rra
jp nc,kmult ;*
rra
jp nc,kdiv ;/
rra
jp nc,kpot ;^
rra
jp nc,kclear ;CLEAR
ld a,KBD_GROUP_MINUS ;group (-)/3/6/9/)/G/VARS
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rra
jp nc,kneg
rra
jp nc,k3
rra
jp nc,k6
rra
jp nc,k9
rra
jp nc,kcbracket
rra
jp nc,kG
rra
jp nc,kvars
ld a,KBD_GROUP_DOT ;group ./2/5/8/(/COS/PRGM/STAT
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rra
jp nc,kdot
rra
jp nc,k2
rra
jp nc,k5
rra
jp nc,k8
rra
jp nc,kobracket
rra
jp nc,kF
rra
jp nc,kC
rra
jp nc,kstat
ld a,KBD_GROUP_ZERO ;group 0/1/4/7/'/SIN/APPS/XTθn
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rra
jp nc,k0
rra
jp nc,k1
rra
jp nc,k4
rra
jp nc,k7
rra
jp nc,kcomma
rra
jp nc,kE
rra
jp nc,kB
rra
jp nc,kxto
ld a,KBD_GROUP_ALPHA ;group ALPHA/MATH/X-1/X2/LOG/LN/STO
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rla
jr nc,kalpha
rla
jr nc,kA
rla
jr nc,kD
rla
jr nc,kxsq
rla
jr nc,klog
rla
jr nc,kln
rla
jr nc,ksto
ld a,KBD_GROUP_GRAPH ;group GRAPH/TRACE/ZOOM/WINDOW/Y=/2nd/MODE/DEL
out (kbd),a
;nop
;nop
key_delay
in a,(kbd)
rra
jp nc,kgraph
rra
jp nc,ktrace
rra