-
Notifications
You must be signed in to change notification settings - Fork 1
/
x16-spsc.s
2860 lines (2732 loc) · 40.3 KB
/
x16-spsc.s
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
; SpeedScript 3.1
;
; first I copied it by hand out of the pdf here:
;
; then I did a bunch of porting to make it work on x16
.PSC02
.org $0801
; memory map
TEXEND_INIT = $9E00
TEXBUF_INIT = $D000
BUFEND_INIT = $FF00
INSCOLOR = 14
TOPFGCOLOR = 1
DEFAULT_DEVICE = 1
; PETSCII constants
PETSCII_CLR = 147
PETSCII_MODE = $8F
space = 32
;COLUMNS = $D9
COLUMNS = $D9
ROWS = $DA
CURRENT_COLUMN = $D3
QUOTE_MODE = $D4
INSERT_MODE = $D8
; allow some dasm things
.feature missing_char_term
.feature labels_without_colons
.code
; sys2061
.word BASICEND ; end of basic
.word 10 ; line number
.byte $9E ; SYS token
.ASSERT BEGIN<10000, error, "SYS number would be too high"
.byte $30 + (BEGIN .MOD 10000)/1000
.byte $30 + (BEGIN .MOD 1000)/100
.byte $30 + (BEGIN .MOD 100)/10
.byte $30 + (BEGIN .MOD 10)
; now I can put stuff here
.byte 0
BASICEND: .byte 0,0
; some macros
.macro copy16 src, dst, dst2
lda src
sta dst
.ifnblank dst2
sta dst2
.endif
lda src+1
sta dst+1
.ifnblank dst2
sta dst2+1
.endif
.endmacro
.macro add16 left,right
clc
lda left
adc right
sta left
lda left+1
adc right+1
sta left+1
.endmacro
;Compares two 16-bit values, and sets the C and Z flags the
;same as a LDA and CMP;instruction would for 8-bit addresses.
.macro COMP16 left,right
sec
lda left
sbc right
sta temp
lda left+1
sbc right+1
ora temp
.endmacro
; Compares two 16-bit values but only affects the C flag.
.macro COMPC16 left,right
SEC
LDA left
SBC right
LDA left+1
SBC right+1
.endmacro
; sub16 left,right : left - right -> left
; sub16 left,right,dst : left - right -> dst
.macro sub16 left,right,dst
sec
lda left
sbc right
.ifnblank dst
sta dst
.else
sta left
.endif
lda left+1
sbc right+1
.ifnblank dst
sta dst+1
.else
sta left+1
.endif
.endmacro
; Subtract an 8-bit value from a 16-bit one
.macro sub8 left,right,dst,dst2
sec
lda left
sbc right
.ifnblank dst
sta dst
.ifnblank dst2
sta dst2
.endif
.else
sta left
.endif
lda left+1
sbc #0
.ifnblank dst
sta dst+1
.ifnblank dst2
sta dst2+1
.endif
.else
sta left+1
.endif
.endmacro
.macro PrintMessage message
LDA #<message
LDY #>message
JSR PRMSG
.endmacro
.macro TopPrintMessage message
jsr topclr
PrintMessage message
.endmacro
;Display a 16-bit integer from the A and X registers
;in decimal using CHROUT.
.macro display_number
jsr displaynum
.endmacro
;TODO: convert to something that works on X16
; should branch if the SHIFT and CTRL keys are
; specifically held down.
.macro B_UNLESS_SHIFT_CTRL addr
LDA 653
CMP #5
BNE addr
.endmacro
;TODO: convert to something that works on X16
; should branch if the SHIFT key is held down,
; regardless of any other qualifiers
.macro B_UNLESS_SHIFT addr
LDA 653
AND #1
BNE addr
.endmacro
;Locations used by high-speed memory
;move routines:
froml = $26
fromh = $27
destl = $28
desth = $29
llen = $2A
hlen = $2B
;curr: Position of cursor within text
;memory. scr: used by the refresh
;routine.
curr = $39
;tex: An alternate location used in tan-
;dem with curr. COLR is used by RE-
;FRESH. temp is used throughout as a
;reusable scratchpad pointer. INDIR is
;also a reusable indirect pointer.
;UNDERCURS stores the value of the
;character highlighted by the cursor.
tex = $FB
temp = $3B
indir = $FD
UNDERCURS = $FA
;WINDCOLR: Color of command line
;window supported by refresh. MAP
;is the 6510's built-in I/O port, used for
;mapping in and out ROMs from the
;address space. RETCHAR is the screen-
;code value of the return mark (a left-
;pointing arrow).
windcolr = $0C
map = $01
retchar = 31
;Kernal Routines
;(refer to the Commodore 64 Programmer's Reference ;Guide):
SCREEN = $FFED
PLOT = $FFF0
chrout = $FFD2
stop = $FFE1
setlfs = $FFBA
setnam = $FFBD
clall = $FFE7
open = $FFC0
chrin = $FFCF
chkin = $FFC6
chkout = $FFC9
getin = $FFE4
clrchn = $FFCC
close = $FFC3
load = $FFD5
save = $FFD8
ioinit = $FF84
;scnkey = $FF9F ; not supported in x16?
; VERA I/O registers
V_H = $9f22
V_M = $9f21
V_L = $9f20
V_1 = $9f23
CTRL = $9F25
;Called only when run from BASIC. It is
;assumed that the author's initials (that
;conveniently work out in hex) are not
;normally present in memory. If they
;are, we know that SpeedScript has been
;run before, so we avoid the ERASE
;routine to preserve the text in memory.
BEGIN JSR INIT
LDA #$CB
CMP firstrun
STA firstrun
BEQ SKIPERAS
JSR erase
SKIPERAS JSR INIT2
JMP main
;UMOVE is a high-speed memory move
;routine. It gets its speed from self-
;modifying code (the $0000's at
;MOVLOOP are replaced by actual ad-
;dresses when UMOVE is called). Some
;assemblers may assemble this as a
;zero-page mode, so you may want to
;change the $0000's to $FFFF's. UMOVE
;is used to move an overlapping range
;of memory upward, so it is used to de-
;lete. Set froml/fromh to point to
;the source area of memory,
;destl/desth to point to the destina-
;tion, and llen/hlen to hold the
;length of the area being moved.
umove LDA froml
STA MOVLOOP+1
LDA fromh
STA MOVLOOP+2
LDA destl
STA MOVLOOP+4
LDA desth
STA MOVLOOP+5
LDX hlen
BEQ SKIPMOV
MOV1 LDA #0
MOV2 STA endpos
LDY #0
MOVLOOP LDA $0000,Y
STA $0000,Y
INY
CPY endpos
BNE MOVLOOP
INC MOVLOOP+2
INC MOVLOOP+5
CPX #0
BEQ OUT
DEX
BNE MOV1
SKIPMOV LDA llen
BNE MOV2
OUT RTS
;DMOVE uses the same variables as UMOVE, but is used to move an
;overlapping block of memory down ward, so it is used to insert. If the block
;of memory to be moved does not overlap the destination area, then either
;routine can be used.
dmove LDA hlen
TAX
ORA llen
BNE NOTNULL
RTS
NOTNULL CLC
TXA
ADC fromh
STA DMOVLOOP+2
LDA froml
STA DMOVLOOP+1
CLC
TXA
ADC desth
STA DMOVLOOP+5
LDA destl
STA DMOVLOOP+4
INX
LDY llen
BNE DMOVLOOP
BEQ SKIPDMOV
DMOV1 LDY #255
DMOVLOOP LDA $0000,Y
STA $0000,Y
DEY
CPY #255
BNE DMOVLOOP
SKIPDMOV DEC DMOVLOOP+2
DEC DMOVLOOP+5
DEX
BNE DMOV1
RTS
; displaynum replaces the call to BASIC $BCDC
; from the original one.
nums .word 1,10,100,1000,10000
numarg .word 0
numspace .byte $20
displaynum
stx numarg
sta numarg+1
;lda #space
;jsr chrout ; leading space just like real one
basicdisplaynum
ldy #8
dnzz lda numarg+1
cmp nums+1,y
bcc dn2
bne startout
lda numarg
cmp nums,y
bcs startout
dn2 dey
dey
bne dnzz
startout
lda #$30
sta numspace
diglp
lda numarg+1
cmp nums+1,y
bcc digitout
bne dontcmp
lda numarg
sbc nums,y ;carry already set
bcc digitout
bcs digsub
dontcmp
lda numarg
sbc nums,y ;carry already set
digsub ; subtract value of digit
inc numspace
sta numarg ;already subtracted
lda numarg+1
sbc nums+1,y
sta numarg+1
jmp diglp
digitout
lda numspace
jsr chrout
dey
dey
bpl startout
rts
;refresh copies a screenful of text
;from the area of memory pointed to by
;toplin. It works like a printer routine,
;fitting a line of text between the screen
;margins, wrapping words, and restarts
;at the left margin after printing a car-
;riage return. SpeedScript constantly calls
;this routine while the cursor is blink-
;ing, so it has to be very fast. To elimi-
;nate flicker, it also clears out the end of
;each line instead of first clearing the
;screen. It stores the length of the first
;screen line for the sake of the check
;routine (which scrolls up by adding
;that length to toplin), the last text
;location referenced (so check can see
;if the cursor has moved off the visible
;screen).
refresh
; set topline and border color elsewhere
; set pointer tex to top of document
copy16 toplin,tex
; set VERA to skip color memory
LDA #$20
STA V_H
; set VERA pointer to beginning of 2nd line
LDX #1
STX V_M
STZ V_L
PPAGE LDY #0
PLINE LDA (tex),Y
STA lbuff,Y
INY
AND #127
CMP #retchar
BEQ BREAK
CPY COLUMNS ;COLUMNS
BNE PLINE
; hit column 39 without end-of-paragraph
; backspace until it hits a space
DEY
SLOOP LDA (tex),Y
AND #127
NXCUR CMP #space
BEQ SBRK ; wrap at this character
DEY
BNE SLOOP
LDY COLUMNS ; columns
DEY
; copy line onto screen
SBRK INY
BREAK STY temp
LDY #0
COPY LDA lbuff,Y
STA V_1
INY
CPY temp
BMI COPY
LDY temp
CLC
TYA
ADC tex
STA tex
LDA tex+1
ADC #0
STA tex+1
CPX #1
BNE CLRLN
STY LENTABLE
; fill rest of line with spaces
CLRLN CPY COLUMNS ; columns
BEQ CLEARED
LDA #32
STA V_1
INY
BRA CLRLN
CLEARED
; move screen pointer to next row
STZ V_L
INC V_M
INX
CPX ROWS ; rows
BEQ pdone
BRA PPAGE
pdone copy16 tex,BOTSCR
RTS
; comment from left column of page 99
erase LDA texstart
STA tex
STA toplin
STA lastline
STA curr
LDA texstart+1
STA tex+1
STA toplin+1
STA lastline+1
STA curr+1
SEC
LDA texend+1
SBC texstart+1
TAX
LDA #space
CLRLOOP LDY #255
DEC tex+1
STA (tex),Y
INY
INC tex+1
CLR2 STA (tex),Y
INY
BNE CLR2
INC tex+1
DEX
BNE CLR2
STA (tex),Y
RTS
; PRMSG is used anytime we need to
; print something at the top of the screen
; (the command line). Pass it the address
; of the message to be printed by storing
; the low .byte of the address in the accu
; mulator, and the high .byte in the
; register. The message in memory must
; end with a zero .byte. The routine does
; not add a carriage return.
PRMSG STA temp
STY temp+1
LDY #0
PRLOOP LDA (temp),Y
BEQ PREXIT
JSR chrout
INY
BNE PRLOOP
PREXIT RTS
getakey JSR getin
BEQ getakey
RTS
;The initialization routine sets up the
;memory map, clears out certain flags,
;and enables the raster interrupt
INIT
; for x16 only: fit
JSR SCREEN
STX COLUMNS
STY ROWS
LDA TEXCOLR
STA 646
LDA #PETSCII_MODE
JSR chrout
LDA #PETSCII_CLR
JSR chrout
;LDA #54
;STA map ; DISABLE BASIC if possible
LDA #TOPFGCOLOR
STA INSMODE
STZ texstart
STZ texend
STZ texbuf
STZ bufend
STZ huntlen
STZ replen
LDA #>END ;
INC
STA texstart+1
LDA #>TEXEND_INIT
STA texend+1
LDA #<TEXBUF_INIT
STA texbuf+1
LDA #<BUFEND_INIT
STA bufend+1
STA fpos+1
JMP ioinit
INIT2 JSR killbuff
; moved forward to match binary
; TODO: confirm or convert 650/$9D settings
INIT3 LDA #128
;STA 650 ;Set all keys to repeat.
;STA $9D ;Display system messages, hide I/O errors
copy16 texstart,curr
; display program title
JSR sysmsg
; display author name
PrintMessage MSG2
INC msgflg
RTS
;sysmsg displays "SpeedScript" and the version.
sysmsg LDA INSMODE
STA windcolr
JSR topclr
PrintMessage MSG1
STZ msgflg
RTS
V_H_INC1 = $10
;topclr keeps the command line clean.
;It is called before most messages.
;It's like a one-line clear-screen.
topclr LDX COLUMNS ; columns
LDA #V_H_INC1 ; write both text & color
STA V_H
STZ V_M
STZ V_L
LDA #space
LDY windcolr
STY 646
toploop STA V_1
STY V_1
DEX
BPL toploop
LDA #19 ;HOME
JMP chrout
;Converts PETSCII to screen codes.
astoin PHA
AND #128
LSR
STA temp
PLA
AND #63
ORA temp
RTS
;The MAIN loop blinks the cursor,
;checks for keystrokes, converts
;them from ASCII to screen codes,
;puts them in text at the CURRent position, and increments
;the CURRent position and lastline. It also checks for special
;cases like the back-arrow and the return key and passes control
;characters to the CONTROL routine. SHIFTed spaces are turned into
;unSHIFTed ones. The INSMODE flag is checked to see if we should
;insert a space before a character.
main STZ blinkflag
LDA (curr)
STA UNDERCURS
main2 LDA (curr)
EOR #$80
STA (curr)
LDA blinkflag
EOR #1
STA blinkflag
JSR refresh
WAIT JSR getin
BNE KEYPRESS
LDA 162 ;TODO: TI seconds counter
AND #16
BEQ WAIT
STZ 162
JMP main2
KEYPRESS TAX
LDA UNDERCURS
STA (curr)
STZ blinkflag
CPX #95
BNE NOTBKS
JSR left
LDA #32
STA (curr)
JMP main
NOTBKS LDA msgflg
BEQ nomsg
PHX
jsr sysmsg
PLX
nomsg TXA
CMP #13
BNE notcr
ldx #retchar+64
notcr txa
AND #127
CMP #32
BCC CONTROL
CPX #160
BNE NESHIFT
LDX #space
NESHIFT TXA
PHA
LDY #0
LDA (curr),Y
CMP #retchar
BEQ DOINS
LDA INSMODE
AND #$F0 ; background color
BEQ NOTINST
DOINS JSR inschar
NOTINST PLA
JSR astoin
PUTCHR STA (curr)
JSR refresh
SEC
LDA curr
SBC lastline
STA temp
LDA curr+1
SBC lastline+1
ORA temp
BCC INKURR
LDA curr
ADC #0
STA lastline
LDA curr+1
ADC #0
STA lastline+1
INKURR INC curr
BNE NOINC2
INC curr+1
NOINC2 JSR check
JMP main
;CONTROl looks up a keyboard command in the list
;of control codes at CTBL. The first .byte of
;CTBL is the actual number of commands. Once the
;position is found, this position is doubled as
;an index to the two-byte address table at VECT.
;The address of MAIN-1 is put on the stack,
;simulating the return address; then the address
;of the command routine taken from VECT is pushed.
;We then perform an RTS. RTS pulls the .bytes off
;the stack as if they were put there by a JSR.
;This powerful technique is used to simulate
;ON+GOTO in machine language.
CONTROL TXA
LDX CTBL
SRCH CMP CTBL,X
BEQ FOUND
DEX
BNE SRCH
JMP main
FOUND DEX
TXA
ASL
TAX
LDA #>(main-1)
PHA
LDA #<(main-1)
PHA
LDA VECT+1,X
PHA
LDA VECT,X
PHA
RTS
CTBL .BYTE 39
.BYTE 29,157,137,133,2,12,138,134,20,148
.BYTE 4,19,9,147,135,139,5,136,140
.BYTE 22,145,17,159,18,24,26,16
.BYTE 28,30,6,1,11,8,31,3,131
.BYTE 10,141,7
VECT .WORD right-1,left-1,wleft-1,wright-1,BORDER-1,LETTERS-1
.WORD sleft-1,sright-1,DELCHAR-1,inschar-1,DELETE-1
.WORD HOME-1,instgl-1,CLEAR-1,paright-1,parleft-1
.WORD ERAS-1,TLOAD-1,TSAVE-1,verify-1
.WORD sleft-1,sright-1,catalog-1,insbuffer-1,switch-1
.WORD endtex-1,print-1,FORMAT-1,dcmnd-1
.WORD DELIN-1,alpha-1,killbuff-1,HUNT-1,FREEMEM-1,tab-1
.WORD lottaspaces-1,repstart-1,endpar-1,SANDR-1
;The check routine first prevents the cursor from
;disappearing past the beginning or end-of-text memory,
;and prevents us from cursoring past the end-of-text pointer.
;It also checks to see if the cursor has left the visible
;screen, scrolling with REFRESH to make the cursor visible.
check JSR check2
COMPC16 curr,toplin
BCS OK1
COMP16 toplin,texstart
BEQ OK1
copy16 curr,toplin
JSR refresh
OK1 SEC
LDA BOTSCR
SBC curr
STA tex
LDA BOTSCR+1
SBC curr+1
STA tex+1
ORA tex
BEQ EQA
BCS OK2
EQA CLC
LDA toplin
ADC LENTABLE
STA toplin
LDA toplin+1
ADC #0
STA toplin+1
REF JSR refresh
JMP OK1
OK2 RTS
check2 SEC
lda lastline
SBC texend
STA temp
lda lastline+1
SBC texend+1
ORA temp
BCC CK3
LDA texend
STA lastline
LDA texend+1
STA lastline+1
CK3 SEC
LDA curr
SBC texstart
STA temp
LDA curr+1
SBC texstart+1
ORA temp
BCS INRANGE
LDA texstart
STA curr
LDA texstart+1
STA curr+1
RTS
INRANGE SEC
LDA curr
SBC lastline
STA temp
LDA curr+1
SBC lastline+1
ORA temp
BCS OUTRANGE
RTS
OUTRANGE
copy16 lastline,curr
RTS
; move cursor right.
right INC curr
BNE NOINCR
INC curr+1
NOINCR JMP check
; Cursor left.
left LDA curr
BNE NODEC
DEC curr+1
NODEC DEC curr
JMP check
; Word left. We look backward for a space.
wleft
copy16 curr,tex
DEC tex+1
LDY #$FF
STRIP LDA (tex),Y
CMP #space
BEQ STRLOOP
CMP #retchar
BNE WLOOP
STRLOOP DEY
BNE STRIP
WLOOP LDA (tex),Y
CMP #space
BEQ wrout
CMP #retchar
BEQ wrout
DEY
BNE WLOOP
RTS
wrout
SEC
TYA
ADC tex
STA curr
LDA tex+1
ADC #0
STA curr+1
JMP check
;Word right. We scan forward
;for a space. OIDS is not a meaningful label.
wright LDY #0
RLOOP LDA (curr),Y
CMP #space
BEQ ROUT
CMP #retchar
BEQ ROUT
INY
BNE RLOOP
RTS
ROUT INY
BNE OIDS
INC curr+1
LDA curr+1
CMP lastline+1
BCC OIDS
BNE lastword
OIDS LDA (curr),Y
CMP #space
BEQ ROUT
CMP #retchar
BEQ ROUT
; add Y to curr to move the cursor
; check prevents illegal cursor movement.
; LASTWORD is called if the end
; of the word cannot be found within 255 characters.
adycurr CLC
TYA
ADC curr
STA curr
LDA curr+1
ADC #0
STA curr+1
wrtn JMP check
lastword
copy16 lastline,curr
jmp check
;endtex is tricky, (p103)
endtex STZ toplin
lda lastline+1
SEC
SBC #4
CMP texstart+1
BCS SAFE
LDA texstart+1
SAFE STA toplin+1
JSR refresh
JMP lastword
BORDER LDA TEXCOLR
CLC
ADC #$10
STA TEXCOLR
COLORALL LDA #$20
STA V_H
LDX #1
LDA TEXCOLR
colorrow
STX V_M
LDY #1
STY V_L
LDY COLUMNS ;Columns
colorcol
STA V_1
DEY
BNE colorcol
INX
CPX ROWS ;ROWS
BNE colorrow
rts
scrcol .BYTE 12 ; gray
;TEXCOLR (text color) is used in the refresh routine
;and stored into color memory. Both SCRCOL and TEXCOLR
;are stored within the SpeedScript code so that after
;they're changed, you can resave SpeedScript and it
;will come up with your color choice in the future.
LETTERS LDA TEXCOLR
INA
AND #$0F
TAX
LDA TEXCOLR
AND #$F0
STX TEXCOLR
ORA TEXCOLR
STA TEXCOLR
BRA COLORALL
TEXCOLR .BYTE $cb ;dark gray on light gray
;Sentence left. We look backward for ending punctuation
;or a return mark, then go forward until we run out of spaces.
.MACRO B_IF_PUNCT dst
CMP #'.
BEQ dst
CMP #'!
BEQ dst
CMP #'?
BEQ dst
.ENDMACRO
sleft
copy16 curr,tex
DEC tex+1
LDY #$FF
PMANY LDA (tex),Y
B_IF_PUNCT PSRCH
CMP #retchar
BNE psloop
PSRCH DEY
BNE PMANY
RTS
psloop LDA (tex),Y
B_IF_PUNCT PUNCT
CMP #retchar
BEQ PUNCT
DEY
BNE psloop
DEC tex+1
LDA tex+1
CMP texstart
BCS psloop
JMP firstword