-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.asm
1083 lines (919 loc) · 20.4 KB
/
main.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
*=$c000
#import "include/all.asm"
.label DATA = $83
.label REM = $8f
.label PRINT = $99
.label QUOTE = $22
.label BUFFER = $200
// Set these to the start/end tokens for commands and functions.
// You can find the table of tokens below at NewTab
.label CMDSTART = $cc
.label CMDEND = $db
.label FUNSTART = CMDEND + $01
.label FUNEND = $de
/*
Set up our vectors
*/
Init:
ldx #<ConvertToTokens
ldy #>ConvertToTokens
stx vectors.ICRNCH
sty vectors.ICRNCH + $01
ldx #<ConvertFromTokens
ldy #>ConvertFromTokens
stx vectors.IQPLOP
sty vectors.IQPLOP + $01
ldx #<ExecuteCommand
ldy #>ExecuteCommand
stx vectors.IGONE
sty vectors.IGONE + $01
ldx #<ExecuteFunction
ldy #>ExecuteFunction
stx vectors.IEVAL
sty vectors.IEVAL + $01
rts
#import "memory.asm" // Memory commands
#import "reu.asm" // REU functions/commands
#import "sprites.asm" // Sprite commands and functions
#import "include/timer.asm" // Timer functions
/*
Add your commands and functions here. The last byte of each command/function name
must have $80 added to it. Your commands should come first starting from $cc. You can
let the execution routine know how to identify commands and functions above in CMDSTART,
CMDEND, FUNSTART, FUNEND. These are the token numbers for each block of commands/functions.
Our tokens start at $cc and can go up to $fe ($ff is pi). Both the tokenization and
detokenization routines use this table, so adding them here will ensure that BASIC
will recognize them as you enter them and will detokenize them when LISTed.
*/
NewTab:
// Commands start here
.text "BORDE" // $cc
.byte 'R' + $80
.text "BACKGROUN" // $cd
.byte 'D' + $80
.text "WOK" // $ce
.byte 'E' + $80
.text "CL" // $cf
.byte 'S' + $80
.text "MEMCOP" // $d0
.byte 'Y' + $80
.text "MEMFIL" // $d1
.byte 'L' + $80
.text "SCREE" // $d2
.byte 'N' + $80
.text "BAN" // $d3
.byte 'K' + $80
.text "STAS" // $d4
.byte 'H' + $80
.text "FETC" // $d5
.byte 'H' + $80
.text "SPRSE" // $d6
.byte 'T' + $80
.text "SPRPO" // $d7
.byte 'S' + $80
.text "SPRCOLO" // $d8
.byte 'R' + $80
.text "MEMLOA" // $d9
.byte 'D' + $80
.text "MEMSAV" // $da
.byte 'E' + $80
.text "DI" // $db
.byte 'R' + $80
// Functions start here
.text "WEE" // $dc
.byte 'K' + $80
.text "SCRLO" // $dd
.byte 'C' + $80
.text "RE" // $de
.byte 'U' + $80
.byte 0
CmdTab: // A table of vectors pointing at your commands' execution addresses
.word BorderCmd - 1 // Address - 1 of first command. Token = CMDSTART
.word BackgroundCmd - 1
.word WokeCmd - 1
.word ClsCmd - 1
.word MemCopyCmd - 1
.word MemFillCmd - 1
.word ScreenCmd - 1
.word BankCmd - 1
.word StashCmd - 1
.word FetchCmd - 1
.word SpriteSetCmd - 1
.word SpritePosCmd - 1
.word SpriteColorCmd - 1
.word MemLoadCmd - 1
.word MemSaveCmd - 1
.word DirectoryCmd - 1
FunTab: // A table of vectors pointing at your functions' execution addresses
.word WeekFun // Address of first function. Token = FUNSTART
.word ScrLocFun
.word ReuFun
/*
Command Execution. This is the meat of it. This is where the magic happens.
We first have to figure out whether we're executing one of our custom functions. We
do this by looking at the current token that's returned by CHRGET. If this token
is in the range of CMDSTART to CMDEND, then it's one of ours and we should find its
routine in a lookup table. If it's not, then just perform the normal BASIC command
handler.
*/
ExecuteCommand:
jsr zp.CHRGET
jsr TestCmd
jmp basic.NEWSTT
TestCmd:
cmp #CMDSTART
bcc OldCmd
cmp #CMDEND + 1
bcc OkNew
OldCmd:
jsr zp.CHRGOT
jmp basic.EXECOLD
OkNew:
sec
sbc #CMDSTART
asl
tax
lda CmdTab+1, x
pha
lda CmdTab, x
pha
jmp zp.CHRGET
/*
Function Execution. This is the meat of it. This is where the magic happens.
We first have to figure out whether we're executing one of our custom functions. We
do this by looking at the current token that's returned by CHRGET. If this token
is in the range of FUNSTART to FUNEND, then it's one of ours and we should find its
routine in a lookup table. If it's not, then just perform the normal BASIC function
handler.
*/
ExecuteFunction:
lda #0
sta zp.VALTYP
jsr zp.CHRGET
cmp #'$' // Is this a HEX number?
beq ProcessHex
cmp #'%' // Is this a binary number?
beq ProcessBinary
cmp #FUNSTART // Is this one of ours?
bcc OldFun
cmp #FUNEND + 1
bcc Ok1New
OldFun:
jsr zp.CHRGOT // It's a built-in Commodore function, so re-fetch the token
jmp basic.FUNCTOLD // and call the normal BASIC function handler.
Ok1New:
sec
sbc #FUNSTART // We need to get an index to the function in the vector table
asl // Start by subtracting to get a 0 based index, and then mult by 2.
pha
jsr zp.CHRGET
jsr basic.PARCHK // Grab whatever is in parens and evaluate it. This is passed to our function.
pla
tay
lda FunTab, y // Get the function's vector address...
sta zp.JMPER + 1
lda FunTab + 1, y
sta zp.JMPER + 2
jsr zp.JMPER // ... and then call it.
rts
/*
Allow us to represent numbers as HEX using $ABCD syntax
*/
ProcessHex:
jsr ClearFAC
!:
jsr zp.CHRGET
bcc !+
cmp #'A'
bcc !+++
cmp #'F' + 1
bcs !+++
sec
sbc #$07
!:
sec
sbc #'0'
pha
lda zp.EXP
beq !+
clc
adc #$04
bcs !+++
sta zp.EXP
!:
pla
beq !---
jsr basic.FINLOG
jmp !---
!:
jmp zp.CHRGOT
!:
jmp basic.OVERR
/*
Allow us to represent numbers as binary using %1010101 syntax
*/
ProcessBinary:
jsr ClearFAC
!:
jsr zp.CHRGET
cmp #'2'
bcs !---
cmp #'0'
bcc !---
sbc #'0'
pha
lda zp.EXP
beq !+
inc zp.EXP
beq !+
!:
pla
beq !--
jsr basic.FINLOG
jmp !--
ClearFAC:
lda #$00
ldx #$0a
!:
sta zp.FLOAT, x
dex
bpl !-
rts
/*
Clear the screen using PETSCII $93. Easy peasey.
Example: CLS
*/
ClsCmd:
lda #$93
jmp kernal.VEC_CHROUT
/*
Set the border color
Example: BORDER 0. Sets the border color to black
*/
BorderCmd:
jsr GetColor
sta vic.EXTCOL
rts
/*
Set the background color
Example: BACKGROUND 0. Sets the background color to black
*/
BackgroundCmd:
jsr GetColor
sta vic.BGCOL0
rts
/*
Execute a POKE but allow passing in a word for the address and the value.
Example: WOKE 250, 65535. Puts 255 in location 250 and 251.
*/
WokeCmd:
jsr Get16Bit // Get the address to WOKE to
lda $14
sta $57
lda $15
sta $58
jsr basic.CHKCOM // Make sure we have a comma
jsr Get16Bit // Get the 16-bit word to WOKE
ldy #$00 // WOKE IT!
lda $14
sta ($57), y
lda $15
iny
sta ($57), y
rts
/*
Select the VIC bank (0-3)
Example: BANK 0 would specify 0-16384 as the range of locations that the VIC sees
*/
BankCmd:
jsr Get8Bit // Get the bank #
tya
pha
and #$fc // Strip the bottom 2 bits.
cmp #$00 // Is the value > 0? That means we specified a number > 3
bne !+ // Illegal quantity
pla
sta r0L
lda #$03 // The bit patterns are backwards. 11 means bank 0 and 00 means bank 3
sec
sbc r0L
sta r0H
lda $dd00 // Read the existing value from $dd00
and #$fc // Set just the bank selection bits (0 & 1)
ora r0H
sta $dd00
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Get the current VIC bank 0-3
*/
CurrentBank:
lda $dd00
and #$03
sta r0L
lda #$03
sec
sbc r0L
rts
/*
Set the screen location within the current VIC bank
Example: SCREEN 1 would set the screen location to offset $0400 of the current VIC bank.
If in bank 0, this would be $0400 since bank 0 starts at $0000. This is also the default
at startup.
*/
ScreenCmd:
jsr CurrentBank // Get the current VIC bank
sta r0L
jsr Get8Bit // Get the screen number (0-15)
tya
pha
and #$f0 // Strip the bottom 4 bits
cmp #$00 // Is the value > 0? Means we've specified a number > 15
bne !+ // Illegal quantity
pla
tay
sty r0H // Tuck away the screen number (0-15)
lda $d018 // Set the screen number in $d018
and #$0f
ora ScreenLoc, y
sta $d018
lda r0H // Now let BASIC know where that screen is
asl // Multiply by 4
asl
sta r0H
lda r0L
asl
asl
asl
asl
asl
asl
ora r0H
sta $288
rts
!:
jmp basic.ILLEGAL_QUANTITY
SpriteDiskCommandCommon:
pha
jsr $ad9e // TODO: Add this to the basic.asm
jsr $b6a3 // TODO: Add this to the basic.asm
sta r0L // Filename length
lda $22
sta r1L // Filename
lda $23
sta r1H
jsr basic.CHKCOM
jsr Get8Bit
sty r0H // Device number
jsr basic.CHKCOM
jsr Get16Bit
lda $14
sta r2L // Load/Save address
lda $15
sta r2H
pla
beq !+ // If this is a save, we need to fetch the end address
jsr basic.CHKCOM
jsr Get16Bit
lda $14
sta r3L // Number of bytes to save
lda $15
sta r3H
!:
lda r0L
ldx r1L
ldy r1H
jsr kernal.VEC_SETNAM
lda #$02
ldx r0H
ldy #$02
jsr kernal.VEC_SETLFS
jsr kernal.VEC_OPEN
bcs !+
ldx #$02
ldy #$00
rts
!:
lda #<DiskError
ldy #>DiskError
jmp CustomError
DiskClose:
lda #$02
jsr kernal.VEC_CLOSE
jsr kernal.VEC_CLRCHN
rts
/*
Load bytes from disk directly into memory.
Example: MEMLOAD "SPRITES.SPR", 8, $2000 would load the file SPRITES.SPR from device 8 into memory at $2000
*/
MemLoadCmd:
lda #$00
jsr SpriteDiskCommandCommon
jsr kernal.VEC_CHKIN
!: // LOOP
jsr kernal.VEC_READST
bne !++ // EOF
jsr kernal.VEC_CHRIN
bcs !--
sta (r2), y
inc r2L
bne !+ // SKIP2
inc r2H
!: // SKIP2
jmp !-- // LOOP
!: // EOF
ora #$40
cmp #$40
bne !----
!: // CLOSE
jmp DiskClose
/*
Save memory to disk.
Example: MEMSAVE "@:SPRITES.SPR,P,W", 8, $2000, $2040 would save memory from $2000 - $2040 to the file SPRITES.SPR on device 8.
*/
MemSaveCmd:
lda #$80
jsr SpriteDiskCommandCommon
jsr kernal.VEC_CHKOUT
!: // LOOP
jsr kernal.VEC_READST
bne !------ // WERROR
lda (r2), y
jsr kernal.VEC_CHROUT
bcs !------
inc r2L
bne !+ // SKIP
inc r2H
!: // SKIP
lda r2L
cmp r3L
lda r2H
sbc r3H
bcc !-- // LOOP
!: // CLOSE
jmp DiskClose
/*
Perform a non-destructive directory listing.
Pilfered from https://csdb.dk/forums/?roomid=11&topicid=17487
Example: DIR 8 would list the directory of device 8
*/
DirectoryCmd:
jsr Get8Bit
tya
pha
lda #$01
tax
ldy #$e8
jsr kernal.VEC_SETNAM
pla
sta $ba
lda #$60
sta $b9
jsr $f3d5
jsr $f219
ldy #$04
!:
jsr $ee13
dey
bne !-
lda $c6
ora $90
bne !++
jsr $ee13
tax
jsr $ee13
jsr $bdcd
!:
jsr $ee13
jsr $e716
bne !-
jsr $aad7
ldy #$02
bne !--
!:
jsr $f642
jsr $f6f3
!:
rts
/*
Grab the sprite number as the first argument for the sprite commands. Stores in r0L
*/
SpriteCommon:
jsr Get8Bit // Get the sprite number (0-7)
cpy #$08
bcs !+
sty r0L // Sprite #
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Set a sprite's color
*/
SpriteColorCmd:
jsr SpriteCommon
jsr basic.CHKCOM
jsr GetColor
ldy r0L
sta vic.SP0COL, y
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Set a sprite's X and Y position
Example: SPRPOS 0, 100, 100 would set sprite 0's X position to 100 and its Y position to 100
The x position can be 0-511.
*/
SpritePosCmd:
jsr SpriteCommon
jsr basic.CHKCOM
jsr Get16Bit
lda $14
sta r1L // X
lda $15
sta r1H
jsr basic.CHKCOM
jsr Get8Bit
sty r2L // Y
jsr PositionSprite
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Turn a sprite on or off and set its shape data location
Example: SPRSET 0, 1, $0d would turn sprite 0 on and set its shape data pointer to $0d in the current bank,
which by default would be location $340 (bank 0 starts at $0 + $40 * $0d)
*/
SpriteSetCmd:
jsr SpriteCommon
jsr basic.CHKCOM
jsr Get8Bit
cpy #$02
bcs !+
tya
ror
ror
sta r1L // On/Off
jsr basic.CHKCOM
jsr Get8Bit
sty r3L // Pointer to shape data in the current bank
lda #SPR_VISIBLE
sta r0H
jsr ChangeSpriteAttribute
lda $288 // Get the page number of the current screen
clc
adc #$03 // Add 1016 to the start of screen RAM to get the sprite pointers
sta r0H
lda #$00
clc
adc #$f8
sta r0L
ldy #$00
lda r3L
sta (r0), y // Write the pointer to the sprite data
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Execute a PEEK function but return a 16-bit word instead of an 8-bit byte.
Example: PRINT WEEK(250). Would return the 16-bit value in 250 & 251.
*/
WeekFun:
jsr basic.GETADR // Get the WEEK address
ldy #$00
lda ($14), y
sta $63
iny
lda ($14), y
sta $62
// Thanks to Gregory Naçu for this trick. It allows writing a uint16 to the FAC
// https://c64os.com/post/floatingpointmath
ldx #$90
sec
jmp $bc49
/*
Return the start address of the current screen.
Example: PRINT SCRLOC(0). In the default C64 configuration, this would return 1024.
*/
ScrLocFun:
lda $288
sta $62
lda #$00
sta $63
ldx #$90
sec
jmp $bc49
/*
Check to see if there's a REU attached
TODO: The reudetect routine is completely broken and needs a lot of work
*/
ReuFun:
jsr reudetect
lda #$00
sta $62
sta $63
ldx #$90
sec
jmp $bc49
/*
Store data from the C64's memory into an REU
Example: STASH $400, $0, 1000, 0 would store the default screen to the REU at address $0, bank $0
*/
StashCmd:
jsr ReuCommandCommon
jsr REUStash
rts
/*
Retrieve data from the REU and store it in the C64's memory
Example: FETCH $400, $0, 1000, 0 would retrieve 1000 bytes from the REU starting at address $0, bank $0 and store it to the default screen
*/
FetchCmd:
jsr ReuCommandCommon
jsr REUFetch
rts
/*
Copy a block of memory.
Example: MEMCOPY $a000, $a000, $2000 would copy BASIC from ROM to RAM
*/
MemCopyCmd:
jsr MemCommon
jsr basic.CHKCOM
jsr Get16Bit
lda $14
sta r2L
lda $15
sta r2H
jsr MemCopy
rts
/*
Fill a block of memory with a character
Example: MEMFILL $0400, $03e8, $20 would fill the screen with space characters.
*/
MemFillCmd:
jsr MemCommon
jsr basic.CHKCOM
jsr Get8Bit
sty r2L
jsr MemFill
rts
/*
Set up parameters for STASH and FETCH since they're pretty much identical
*/
ReuCommandCommon:
jsr MemCommon
jsr basic.CHKCOM
jsr Get16Bit // Transfer length
lda $14
sta r2L
lda $15
sta r2H
jsr basic.CHKCOM
jsr Get8Bit // REU bank number
sty r3L
rts
/*
The existing memory routines start with 2 16-bit values and they're written to
the same registers.
*/
MemCommon:
jsr Get16Bit
lda $14
sta r0L
lda $15
sta r0H
jsr basic.CHKCOM
jsr Get16Bit
lda $14
sta r1L
lda $15
sta r1H
rts
/*
Fetch a 16 bit value from the current pointer. Value is returned in $14/$15
*/
Get16Bit:
lda #$00
sta zp.VALTYP
jsr basic.FRMNUM
jsr basic.GETADR
rts
/*
Fetch an 8 bit value which is returned in Y
*/
Get8Bit:
jsr basic.FRMEVL // Evaluate the expression after the token
jsr $ad8d
jsr basic.FACINX // Convert the value in FAC1 to A(H)&Y(L)
cmp #$00 // Is the high byte 0? (>255)
bne !+ // Yup. Illegal quantity
rts
!:
jmp basic.ILLEGAL_QUANTITY
/*
Common routine to grab some text, ensure it's a number and make sure
it's < 16. This is used for the Background and Border commands which
set the colors of each. Returns the value in A
*/
GetColor:
jsr Get8Bit
cpy #$10 // Is the color > 15?
bcs !+
tya
rts
!:
lda #<InvalidColorError
ldy #>InvalidColorError
jmp CustomError
/*
Display a custom error. Pass in the LB of the error message in A and the HB in Y
*/
CustomError:
sta $22
tya
jmp basic.CUSTERROR
/*
Detokenize. Converts tokens back into PETSCII. This is called when you list a program
with custom commands. It ensures that those commands expand correctly to their PETSCII
form.
*/
ConvertFromTokens:
bpl Out
bit zp.GARBFL
bmi Out
cmp #$ff
beq Out
cmp #CMDSTART
bcs NewList
jmp $a724
Out:
jmp $a6f3
NewList:
sec
sbc #$cb
tax
sty zp.FORPNT
ldy #-1
Next:
dex
beq Found
Loop:
iny
lda NewTab, y
bpl Loop
bmi Next
Found:
iny
lda NewTab, y
bmi OldEnd
jsr basic.CHAROUT
bne Found
OldEnd:
jmp $a6ef
/*
Tokenize. Converts PETSCII commands into tokens. This routine is called
as you enter commands in either immediate mode, or as you enter lines of
BASIC code.
*/
ConvertToTokens:
ldx zp.TXTPTR
ldy #4
sty zp.GARBFL
NextChar:
lda BUFFER, x
bpl Normal
cmp #$ff
beq TakChar
inx
bne NextChar
Normal:
cmp #' '
beq TakChar
sta zp.ENDCHAR
cmp #QUOTE
beq GetChar
bit zp.GARBFL
bvs TakChar
cmp #'?'
bne Skip
lda #PRINT
bne TakChar
Skip:
cmp #'0'
bcc Skip1
cmp #'<'
bcc TakChar
Skip1:
sty zp.FBUFPT
ldy #0
sty zp.COUNT
dey
stx zp.TXTPTR
dex
CmpLoop:
iny
inx
TestNext:
lda BUFFER, x
sec
sbc basic.RESLST, y
beq CmpLoop
cmp #$80
bne NextCmd
ora zp.COUNT
TakChar1:
ldy zp.FBUFPT
TakChar:
inx
iny
sta BUFFER-5, y
cmp #0
beq End
sec
sbc #':'
beq Skip2
cmp #DATA-':'
bne Skip3
Skip2:
sta zp.GARBFL
Skip3:
sec
sbc #REM-':'
bne NextChar
sta zp.ENDCHAR
RemLoop: