-
Notifications
You must be signed in to change notification settings - Fork 8
/
mainmem.shr.s
2016 lines (1849 loc) · 71.3 KB
/
mainmem.shr.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
* MAINMEM.SHR.S
* (c) Bobbi 2022 GPLv3
*
* Routines for drawing bitmapped text and graphics in SHR mode
* on Apple IIGS (640x200 4 colour, or 320x200 16 colour.)
*
* This code is in main memory only to save space in aux LC.
*
******************************************************************************
* Data in bank $E1
******************************************************************************
SHRFONTXPLD EQU $A000 ; Explode SHR font to $E1:A000
******************************************************************************
* 21 bytes of persistent storage, also accessed by mainmem code
* TODO: Move to SHRZP maybe
SHRPIXELS DB $00 ; Main memory copy of VDUPIXELS
SHRVDUQ DS 16 ; Main memory copy of VDUQ
SHRGFXFGMASK DB $00 ; Foreground colour mask
SHRGFXFGMSK2 DB $00 ; Copy of foreground colour mask
SHRGFXBGMASK DB $00 ; Background colour mask
SHRGFXACTION DB $00 ; GCOL action for point plotting
* These are all persistent locals (14 bytes of ZP)
SHRXPIXEL EQU SHRZP+0 ; Prev point in screen coords (word)
SHRYPIXEL EQU SHRZP+2 ; Prev point in screen coords (word)
SHRWINLFT EQU SHRZP+4 ; Gfx win - left (0-639) (word)
SHRWINRGT EQU SHRZP+6 ; Gfx win - right (0-639) (word)
SHRWINTOP EQU SHRZP+8 ; Gfx win - top (0-199) (word)
SHRWINBTM EQU SHRZP+10 ; Gfx win - bottom (0-199) (word)
* Colours in the following order.
* For 16 colour modes ...
* BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, ...
* For 4 colour modes ...
* BLACK, RED, YELLOW, WHITE
* GB 0R
PALETTE320 DB $00, $00 ; BLACK
DB $00, $0F ; RED
DB $F0, $00 ; GREEN
DB $F0, $0F ; YELLOW
DB $0F, $00 ; BLUE
DB $0F, $0F ; MAGENTA
DB $FF, $00 ; CYAN
DB $FF, $0F ; WHITE
DB $44, $04 ; Dark grey
DB $88, $0F ; RED (light)
DB $F8, $08 ; GREEN (light)
DB $F8, $0F ; YELLOW (light)
DB $8F, $08 ; BLUE (light)
DB $8F, $0F ; MAGENTA (light)
DB $FF, $08 ; CYAN (light)
DB $AA, $0A ; Light grey
PALETTE640 DB $00, $00 ; BLACK
DB $00, $0F ; RED
DB $F0, $0F ; YELLOW
DB $FF, $0F ; WHITE
DB $00, $00 ; BLACK
DB $00, $0F ; RED
DB $F0, $0F ; YELLOW
DB $F8, $0F ; WHITE
DB $00, $00 ; BLACK
DB $00, $0F ; RED
DB $F0, $0F ; YELLOW
DB $FF, $0F ; WHITE
DB $00, $00 ; BLACK
DB $00, $0F ; RED
DB $F0, $0F ; YELLOW
DB $FF, $0F ; WHITE
* Explode font to generate SHRFONTXPLD table
* This is 2 bytes x 8 rows for each character in 640 mode
* or 4 bytes x 8 rows for each character in 320 mode
SHRXPLDFONT >>> ENTMAIN
LDA #<SHRFONTXPLD ; Use A3L/H to point to ..
STA A3L ; .. start of table to write
LDA #>SHRFONTXPLD
STA A3H
LDA #$E1 ; Memory bank $E1
STA A4L
LDA #32 ; First char number
:L1 JSR SHRXPLDCHAR ; Explode char A
INC A
CMP #128 ; 96 chars in FONT8
BNE :L1
JSR SHRCLR24 ; Clear row 24
>>> XF2AUX,SHRV22RET
* Explode one character to location pointed to by A3L
* On entry: A - character to explode
SHRXPLDCHAR PHA
SEC
SBC #32
STA A1L ; A*8 -> A1L/H
STZ A1H
ASL A1L
ROL A1H
ASL A1L
ROL A1H
ASL A1L
ROL A1H
CLC ; FONT8+A*8 -> A1L/H
LDA A1L
ADC #<FONT8
STA A1L
LDA A1H
ADC #>FONT8
STA A1H
LDY #$00 ; First row of char
:L1 LDA (A1L),Y ; Load row of font
JSR SHRXPLDROW
INY ; Next row of font
CPY #$08 ; Last row?
BNE :L1
PLA
RTS
* Explode one pixel row of user defined graphics char
SHRUSERCHAR >>> ENTMAIN
LDA #<SHRFONTXPLD ; Use A3L/H to point to ..
STA A3L ; .. start of table to write
LDA #>SHRFONTXPLD
STA A3H
LDA #$E1 ; Bank $E1
STA A4L
LDA SHRVDUQ+0 ; Character number
CMP #32 ; < 32? Then bail out
BCC :DONE
SEC ; Otherwise, subtract 32
SBC #32
TAY
LDA #16 ; Bytes/char in 640 mode
LDX SHRPIXELS ; Pixels per byte
CPX #$02 ; 2 is 320-mode (MODE 1)
BNE :S0
LDA #32 ; Bytes/char in 320 mode
:S0 STA :INCREMENT
:L0 CPY #$00
BEQ :S1
CLC
LDA A3L
ADC :INCREMENT
STA A3L
LDA A3H
ADC #$00
STA A3H
DEY
BRA :L0
:S1 LDY #$00
:L1 LDA SHRVDUQ+1,Y ; Row of pixels
JSR SHRXPLDROW
INY
CPY #$08 ; Last row?
BNE :L1
:DONE >>> XF2AUX,VDUXXRET
:INCREMENT DB $00
* Explode one row of pixels. Used by SHRXPLDCHAR & SHRUSERCHAR
* On entry: A contains row of font data
SHRXPLDROW LDX SHRPIXELS ; Pixels per byte
CPX #$02 ; 2 is 320-mode (MODE 1)
BNE :S1
JSR SHRCHAR320
BRA :S2
:S1 JSR SHRCHAR640
:S2 LDX SHRPIXELS ; Pixels per byte
CPX #$02 ; 2 is 320-mode (MODE 1)
BNE :S3
CLC ; 320 mode: add 4 to A3L
LDA A3L
ADC #$04
STA A3L
LDA A3H
ADC #$00
STA A3H
BRA :S4
:S3 CLC ; 640 mode: add 2 to A3L
LDA A3L
ADC #$02
STA A3L
LDA A3H
ADC #$00
STA A3H
:S4 RTS
* Clear text row 24 (0-based index)
SHRCLR24 CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDX #$00
LDA #$00
:L1 STAL $E19800,X
INX
INX
CPX #$0500
BNE :L1
SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
RTS
* Explode one pixel row of font in 320 mode
* 4 bytes per char, 4 bits per pixel
* On entry: A contains row of font data
SHRCHAR320 PHY ; Preserve Y
LDY #$00 ; Dest byte index
:L0 STZ A2L
LDX #$00 ; Source bit index
:L1 ASL ; MS bit -> C
PHP ; Preserve C
ROL A2L ; C -> LS bit
PLP ; Recover C
PHP
ROL A2L ; C -> LS bit
PLP ; Recover C
PHP
ROL A2L ; C -> LS bit
PLP ; Recover C
ROL A2L ; C -> LS bit
INX
CPX #$02 ; Processed two bits of font?
BNE :L1
PHA ; Preserve partially shifted font
LDA A2L
STA [A3L],Y
PLA ; Recover partially shifted font
INY
CPY #$04 ; Done 4 bytes?
BNE :L0
PLY ; Recover Y
RTS
* Explode one pixel row of font in 640 mode
* 2 bytes per char, 2 bits per pixel
* On entry: A contains row of font data
SHRCHAR640 PHY ; Preserve Y
LDY #$00 ; Dest byte index
:L0 STZ A2L
LDX #$00 ; Source bit index
:L1 ASL ; MS bit -> C
PHP ; Preserve C
ROL A2L ; C -> LS bit
PLP ; Recover C
ROL A2L ; C -> LS bit
INX
CPX #$04
BNE :L1
PHA ; Preserve partially shifted font
LDA A2L
STA [A3L],Y
PLA ; Recover partially shifted font
INY
CPY #$02 ; Done 2 bytes?
BNE :L0
PLY ; Recover Y
RTS
* Handle plotting & unplotting cursors
* On entry: character in A, flags in Y
* pointer to screen address in SHRVDUQ+0..1
SHRCURSM >>> ENTMAIN
PHY ; Preserve flags
PHA ; Preserve character
LDA SHRVDUQ+0 ; Copy pointer to A3L/H
STA A3L
LDA SHRVDUQ+1
STA A3H
LDA #$E1 ; Bank $E1
STA A4L
LDA SHRPIXELS ; Pixels per byte
CMP #$02 ; 2 is 320-mode (MODE 1)
BNE :MODE0
LDA #$04 ; 4 bytes in 320 mode
LDX #$71 ; White/red
BRA :S1
:MODE0 LDA #$02 ; 2 bytes in 640 mode
LDX #%11011101 ; White/red/white/red
:S1 STA :BYTES ; Bytes per char
STX :CURSBYTE
LDA A3L ; LSB
CLC
ADC #<$460 ; $460 is seven rows
STA A3L
LDA A3H ; MSB
ADC #>$460 ; $460 is seven rows
STA A3H
LDY #$00
LDX #$00
PLA ; Recover character
PLP ; Recover flags
BVC :S2 ; VC: Write cursor
INX ; Advance to 2nd half of :SAVEBYTES
INX
INX
INX
:S2 BCC :CURSOROFF ; CC: Remove cursor
:CURSORON
LDAL [A3L],Y ; See if cursor shown
CMP :CURSBYTE
BEQ :DONE ; Cursor shown already, skip
:L1 LDAL [A3L],Y
STA :SAVEBYTES,X ; Preserve bytes under cursor
LDA :CURSBYTE ; Byte of cursor data
STAL [A3L],Y
INX
INY
CPY :BYTES
BNE :L1
>>> XF2AUX,SHRCURSRET
:CURSOROFF
LDAL [A3L],Y ; See if cursor shown
CMP :CURSBYTE
BNE :DONE ; Cursor not shown, skip
:L2 LDA :SAVEBYTES,X ; Restore bytes under cursor
STAL [A3L],Y
INX
INY
CPY :BYTES
BNE :L2
:DONE >>> XF2AUX,SHRCURSRET
:BYTES DB $00 ; 2 for 640-mode, 4 for 320-mode
:CURSBYTE DB $00 ; Cursor byte for mode
:SAVEBYTES DS 8 ; Bytes under cursors
* VDU5 plot char at graphics cursor position
SHRVDU5CH >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
AND #$00FF
STA A1L ; A*16 -> A1L/H
ASL A1L
ASL A1L
ASL A1L
ASL A1L
LDA SHRPIXELS ; Pixels per byte
AND #$00FF
CMP #$02 ; 2 is 320-mode (MODE 1)
BNE :MODE0
LDA #$04 ; 4 bytes per row in MODE 1
ASL A1L ; A*32 -> A1L/H in MODE 1
BRA :S0
:MODE0 LDA #$02 ; 2 bytes per row in MODE 0
:S0 STA :BYTES
CLC ; Add SHRFONTXPLD to A1L/H
LDA A1L
ADC #SHRFONTXPLD
STA A1L
LDA SHRYPIXEL ; y coordinate
SEC
SBC #8 ; Height of this row
CMP SHRWINBTM
BMI :NEWPAGE
LDA SHRYPIXEL
CMP SHRWINTOP
BEQ :S1
BPL :NEWPAGE
:S1 LDA SHRXPIXEL ; x coordinate
CMP SHRWINLFT
BMI :NEWPAGE
CMP SHRWINRGT
BEQ :S2
BPL :NEWPAGE
BRA :S2
:NEWPAGE LDA SHRWINTOP
STA SHRYPIXEL
LDA SHRWINLFT
STA SHRXPIXEL
:S2 SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
LDX SHRYPIXEL ; Screen row (Y-coord)
LDA SHRROWSL,X ; Look up addr (LS byte)
STA A3L ; Stash in A3L
LDA SHRROWSH,X ; Look up addr (MS byte)
STA A3H ; Stash in A3H
LDA #$E1 ; Bank $E1
STA A4L
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDX SHRXPIXEL ; Screen col (X-coord)
STX A2L
LSR A2L ; Divide by 2
LDA SHRPIXELS
AND #$00FF
CMP #$02
BEQ :M1 ; MODE 1
LSR A2L ; Divide by 2 again
:M1 LDX A1L ; Index into exploded font
STZ :ROWCTR
:L0
PHX
LDY #$00
STZ :PIXBUF+2 ; Clear bytes 3,4 of shift buf
STZ :PIXBUF+4 ; Clear bytes 5,6 of shift buf
:LOOP LDAL $E10000,X ; Read a word of exploded font
STA :PIXBUF,Y ; Store word to shift buffer
INX
INX
INY
INY
CPY :BYTES
BNE :LOOP
LDA SHRXPIXEL
JSR SHRSHIFT ; Shift :PIXBUF to the right
LDY A2L ; Index into row of pixels
STZ :COLCTR
LDX #$00
INC :BYTES
:L1 LDA :PIXBUF,X ; Read word of exploded font
PHX
SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
JSR SHRPLOTBYTE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
PLX
INX ; Next byte of font
INY ; Next byte on screen
INC :COLCTR
LDA :COLCTR
CMP :BYTES ; Bytes per row
BNE :L1
DEC :BYTES
PLA ; Restore saved X -> A
CLC ; Add bytes per row
ADC :BYTES
TAX ; Back to X
LDA A3L ; Increment A3L/H to next row
CLC
ADC #$A0
STA A3L
LDA A3H
ADC #$00
STA A3H
INC :ROWCTR
LDA :ROWCTR
CMP #$08 ; 8 rows
BNE :L0
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,SHRPRCH320RET
* Zero page
:COLCTR EQU TMPZP+0
:ROWCTR EQU TMPZP+2
:BYTES EQU TMPZP+4 ; Bytes per char row
:PIXBUF EQU TMPZP+6 ; Shift buffer (6 bytes)
* Shifts one character row of pixels to the right
* Called in 65816 native mode, 16 bit M & X
* On entry: A - x-coordinate of char
SHRSHIFT MX %00 ; Tell merlin we are 16 bit M&X
PHA
LDA SHRPIXELS ; Pixels per byte
AND #$00FF
CMP #$02 ; 2 is 320-mode (MODE 1)
BNE :MODE0
PLA
AND #$0001 ; Bits to shift in MODE 1
ASL
PHA
:MODE0 PLA
AND #$0003 ; Bits to shift in MODE 0
PHA
LDA :PIXBUF ; Put bytes in big-endian order
XBA
STA :PIXBUF
LDA :PIXBUF+2
XBA
STA :PIXBUF+2
LDA :PIXBUF+4
XBA
STA :PIXBUF+4
PLA
:L1 CMP #$0000
BEQ :S1
LSR :PIXBUF ; Shift :PIXBUF to the right 1 bit
ROR :PIXBUF+2
ROR :PIXBUF+4
LSR :PIXBUF ; Shift right again
ROR :PIXBUF+2
ROR :PIXBUF+4
DEC A
BRA :L1
:S1 LDA :PIXBUF ; Put bytes back in little-endian
XBA
STA :PIXBUF
LDA :PIXBUF+2
XBA
STA :PIXBUF+2
LDA :PIXBUF+4
XBA
STA :PIXBUF+4
RTS
MX %11
* Handle cursor left in VDU5 mode
SHRVDU08 >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRXPIXEL
SEC
SBC #$08 ; Move to previous column
CMP SHRWINLFT
BMI :PREVLINE ; x-pos < SHRWINLFT
STA SHRXPIXEL
BRA :DONE
:PREVLINE LDA SHRYPIXEL
CLC ; Add 8 rows (go up)
ADC #$08
CMP SHRWINTOP
BCS :HOME ; y-pos >= SHRWINTOP
STA SHRYPIXEL
LDA SHRWINRGT
SEC
SBC #$07
STA SHRXPIXEL
BRA :DONE
:HOME LDA SHRWINTOP
STA SHRYPIXEL
LDA SHRWINLFT
STA SHRXPIXEL
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,VDUXXRET
* Handle cursor right in VDU5 mode
SHRVDU09 >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRXPIXEL
CLC
ADC #$08 ; Advance to next column
CMP SHRWINRGT
BCS :NEWLINE ; x-pos >= SHRWINRGT
STA SHRXPIXEL
BRA :DONE
:NEWLINE LDA SHRWINLFT
STA SHRXPIXEL
JSR SHRVDU5LF
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,VDUXXRET
* Handle cursor down / linefeed in VDU5 mode
SHRVDU10 >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
JSR SHRVDU5LF
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,VDUXXRET
* Handle cursor up in VDU5 mode
SHRVDU11 >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRYPIXEL
CLC
ADC #$08 ; Height of row of text
CMP SHRWINTOP
BCS :TOP ; y-pos >= SHRWINTOP
STA SHRYPIXEL
BRA :DONE
:TOP LDA SHRWINTOP
STA SHRYPIXEL
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,VDUXXRET
* Handle linefeed in VDU5 mode - does the actual work
* Called in 65816 native mode, 16 bit M & X
SHRVDU5LF MX %00 ; Tell Merlin
LDA SHRYPIXEL
SEC
SBC #16 ; Height of this+next row
CMP SHRWINBTM
BCC :NEWPAGE ; Less than 16 rows left
LDA SHRYPIXEL
SEC
SBC #$08
STA SHRYPIXEL
BRA :DONE
:NEWPAGE LDA SHRWINTOP
STA SHRYPIXEL
:DONE RTS
MX %11 ; 8 bit again
* Handle carriage return in VDU5 mode
SHRVDU13 >>> ENTMAIN
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRWINLFT
STA SHRXPIXEL
:DONE SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
>>> XF2AUX,VDUXXRET
* Handle erasing char for VDU127 in VDU5 mode
* Called after SHRVDU08 has already backspaced cursor
SHRVDU127 >>> ENTMAIN
LDX SHRYPIXEL ; Screen row (Y-coord)
LDA SHRROWSL,X ; Look up addr (LS byte)
STA A3L ; Stash in A3L
LDA SHRROWSH,X ; Look up addr (MS byte)
STA A3H ; Stash in A3H
LDA #$E1 ; Bank $E1
STA A4L
LDX SHRPIXELS
CPX #$02
BNE :MODE0
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRXPIXEL ; Screen col (X-coord)
LSR A ; Divide by 2
BRA :MODE1
:MODE0 CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA SHRXPIXEL ; Screen col (X-coord)
LSR A ; Divide by 2
LSR A ; Divide by 4
TAY
LDX #$00
SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
:L1 LDA SHRGFXBGMASK
STAL [A3L],Y
INY
STAL [A3L],Y
DEY
JSR SHRNXTROWM ; Advance A3L/H to next pixel row
INX
CPX #$08 ; Erased all 8 rows?
BNE :L1
BRA :DONE
:MODE1 MX %00 ; Tell Merlin it's 16 bit M&X
TAY
LDX #$00
SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
:L2 LDA SHRGFXBGMASK
STAL [A3L],Y
INY
STAL [A3L],Y
INY
STAL [A3L],Y
INY
STAL [A3L],Y
DEY
DEY
DEY
JSR SHRNXTROWM ; Advance A3L/H to next pixel row
INX
CPX #$08 ; Erased all 8 rows?
BNE :L2
:DONE SEC ; 65816 emulation mode
XCE
>>> XF2AUX,VDUXXRET
* Advance A3L/H to next pixel row on screen
SHRNXTROWM LDA A3L ; Advance A3L/H to next row
CLC
ADC #160
STA A3L
LDA A3H
ADC #$00
STA A3H
RTS
* Plot actions: PLOT k,x,y
* k is in SHRVDUQ+4
* x is in SHRVDUQ+5,SHRVDUQ+6
* y is in SHRVDUQ+7,SHRVDUQ+8
*
* Plot actions:
* $00+x - move/draw lines Where x: 0 - Move relative
* $40+x - plot point 1 - Draw relative FG
* [$50+x - fill triangle] 2 - Draw relative Inv FG
* [$60+x - fill rectangle] 3 - Draw relative BG
* [$90+x - draw circle] 4 - Move absolute
* [$98+x - fill circle] 5 - Draw abs FG
* 6 - Draw abs Inv FG
* 7 - Draw abs BG
* Note: abs/rel handled in auxmem.vdu.s
* TODO: No triangle filling or other fancy ops yet
SHRPLOT >>> ENTMAIN
>>> SHRCOORD ; Convert coordinates
LDA A1L ; Preserve converted x
PHA
LDA A1H
PHA
LDA A2L ; Preserve converted y
PHA
LDA A2H
PHA
LDA SHRVDUQ+4 ; k
AND #$03
CMP #$00 ; Bits 0,1 clear -> just move
BEQ :S2
JSR SHRPLOTCOL ; Handle colour selection
LDA SHRVDUQ+4 ; k
AND #$F0 ; Keep MS nybble
CMP #$00 ; Move or draw line
BNE :S1
JSR SHRLINE
BRA :S2
:S1 CMP #$40 ; Plot point
BNE :BAIL ; Other? Bail out
CLC ; 65816 native mode
XCE
SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
JSR SHRPOINT
SEC ; 65816 emulation mode
XCE
MX %11 ; Tell Merlin
BRA :S2
:S2 PLA ; Store prev pt in screen coords
STA SHRYPIXEL+1
PLA
STA SHRYPIXEL+0
PLA
STA SHRXPIXEL+1
PLA
STA SHRXPIXEL+0
:DONE >>> XF2AUX,GFXPLOTRET
:BAIL PLA
PLA
PLA
PLA
LDA SHRGFXFGMSK2 ; Restore original FG colour
STA SHRGFXFGMASK
BRA :DONE
* Handle colour selection for PLOT
SHRPLOTCOL LDA SHRGFXFGMASK ; Preserve FG colour
STA SHRGFXFGMSK2
LDA SHRVDUQ+4 ; k
AND #$03
CMP #$02 ; Inverse fFG
BNE :S1
LDA SHRGFXFGMASK ; Load FG mask
EOR #$FF ; Negate / invert
INC A
STA SHRGFXFGMASK ; Overwrite GF mask
BRA :DONE
:S1 CMP #$03 ; BG
BNE :DONE
LDA SHRGFXBGMASK ; Load BG mask
STA SHRGFXFGMASK ; Overwrite FG mask
:DONE RTS
* Plot a point
* Called in 65816 native mode, 8 bit M & X
* On entry: A1L/H x-coordinate, A2L/H y-coordinate
SHRPOINT REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA A2L ; y coordinate
CMP SHRWINBTM
BMI :OUT
CMP SHRWINTOP
BEQ :S1
BPL :OUT
:S1 LDA A1L ; x coordinate
CMP SHRWINLFT
BMI :OUT
CMP SHRWINRGT
BEQ SHRPOINT2
BPL :OUT
BRA SHRPOINT2
:OUT SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
RTS
SHRPOINT2 SEP #$30 ; 8 bit M & X
MX %11 ; Tell Merlin
LDX A2L ; Screen row (Y-coord)
LDA SHRROWSL,X ; Look up addr (LS byte)
STA A3L ; Stash in A3L
LDA SHRROWSH,X ; Look up addr (MS byte)
STA A3H ; Stash in A3H
LDA #$E1 ; Bank $E1
STA A4L
LDX A1L ; Store X-coord for later
LSR A1H ; Divide by 2
ROR A1L
LDA SHRPIXELS ; Pixels per byte
CMP #$02 ; 2 is 320-mode (MODE 1)
BNE :MODE0
LDY A1L ; Index into row of pixels
TXA
AND #$01 ; Keep LSB bit only
TAX ; Index into :BITS320
LDA :BITS320,X ; Get bit pattern for pixel to set
BRA SHRPLOTBYTE
:MODE0 LSR A1H ; Divide X-coord by 2 again
ROR A1L
LDY A1L ; Index into row of pixels
TXA
AND #$03 ; Keep LSB two bits only
TAX ; Index into :BITS640
LDA :BITS640,X ; Get bit pattern for pixel to set
SHRPLOTBYTE PHA
LDA SHRGFXACTION ; GCOL action
AND #$0007 ; Avoid table overflows
ASL
TAX
PLA ; Recover bit pattern
JMP (:PLOTTBL, X) ; Jump using jump table
:BITS320 DB %11110000 ; Bit patterns for pixel ..
DB %00001111 ; .. within byte
:BITS640 DB %11000000 ; Bit patterns for pixel ..
DB %00110000 ; .. within byte
DB %00001100
DB %00000011
:PLOTTBL DW SHRPLOTSET ; Jump table for GCOL actions
DW SHRPLOTOR
DW SHRPLOTAND
DW SHRPLOTXOR
DW SHRPLOTNOT
DW SHRPLOTNOP
DW SHRPLOTCLR
DW SHRPLOTNOP
* Plot the specified colour (GCOL action 0)
* Pixel bit pattern in A
SHRPLOTSET TAX ; Keep copy of bit pattern
EOR #$FF ; Invert bits
AND [A3L],Y ; Load existing byte, clearing pixel
STA A1L
TXA ; Get bit pattern back
AND SHRGFXFGMASK ; Mask to set colour
ORA A1L ; OR into existing byte
STA [A3L],Y ; Write to screen
RTS
* OR with colour on screen (GCOL action 1)
* Pixel bit pattern in A
SHRPLOTOR AND SHRGFXFGMASK ; Mask to set colour
ORA [A3L],Y ; OR into existing byte
STA [A3L],Y ; Write to screen
RTS
* AND with colour on screen (GCOL action 2)
* Pixel bit pattern in A
SHRPLOTAND TAX ; Keep copy of bit pattern
AND [A3L],Y ; Mask bits to work on
STA A1L
TXA ; Get bit pattern back
AND SHRGFXFGMASK ; Mask to set colour
AND A1L ; AND with screen data
STA A1L
TXA ; Get bit pattern back
EOR #$FF ; Invert
AND [A3L],Y ; Mask remaining bits
ORA A1L ; Combine
STA [A3L],Y ; Write to screen
RTS
* XOR with colour on screen (GCOL action 3)
* Pixel bit pattern in A
SHRPLOTXOR AND SHRGFXFGMASK ; Mask to set colour
EOR [A3L],Y ; EOR into existing byte
STA [A3L],Y ; Write to screen
RTS
* NOT colour on screen (GCOL action 4)
* Pixel bit pattern in A
SHRPLOTNOT TAX ; Keep copy of bit pattern
STX A1L
LDA [A3L],Y ; Load existing byte
EOR #$FF ; Negate / invert existing byte
AND A1L ; Mask with bit pattern
STA A1L
TXA ; Get bit pattern back
EOR #$FF ; Invert bits
AND [A3L],Y ; Mask remaining bits
ORA A1L ; Combine
STA [A3L],Y ; Write to screen
RTS
* NO-OP (GCOL action 5)
* Pixel bit pattern in A
SHRPLOTNOP RTS
* Clear (GCOL action 6)
* Pixel bit pattern in A, and also at top of stack
SHRPLOTCLR EOR #$FF ; Invert bits
AND [A3L],Y ; Load existing byte, clearing pixel
STA [A3L],Y ; Write to screen
RTS
* Bresenham line drawing algorithm, entry point
* x0 is in SHRXPIXEL+0,SHRPIXEL+1
* y0 is in SHRYPIXEL
* x1 in A1L,A1H
* y1 in A2L
* Called in emulation mode.
* Uses TMPZP+0,+1
SHRLINE LDA A2L ; y1
SEC
SBC SHRYPIXEL ; Subtract y0
BPL :S1 ; Skip if +ve
EOR #$FF ; Negate if -ve
INC A
:S1 STA TMPZP+0 ; abs(y1 - y0)
STZ TMPZP+1 ; Pad to 16 bit
CLC ; 65816 native mode
XCE
REP #$30 ; 16 bit M & X
MX %00 ; Tell Merlin
LDA A1L ; Load x1 (A1L,A1H)
SEC
SBC SHRXPIXEL ; Subtract x0
BPL :S2 ; Skip if +ve
EOR #$FFFF ; Negate if -ve
INC A
:S2 CMP TMPZP ; Cmp abs(x1 - x0) w/ abs(y1 - y0)
BCC :YDOM ; abs(x1 - x0) < abs(y1 - y0)