Closed hoglet67 closed 2 years ago
This is the code in the MOS that does the padding required to output *HELP MOS nicely into multiple columns, each 20 characters wide.
The cause of this bug is that the *HELP MOS code directly accesses the VDU variable POS (the X location of the cursor), and this is not being updated when output is redirected to the Pi VDU driver.
JSR LE25C X = Window Right - Window Left
CPX #&13 Exactly 20 characters wide?
BEQ L9EEF Force a newline
.L9ECB
JSR LE252 X = POS, Y = VPOS
TXA
BEQ L9EA0 POS of 0 means we have already wrapped, so handle next item (this works in the 80 col case)
CPX #&14
BEQ L9EA0 POS of 20 means we are done padding, so handle next item
BCC L9EE4 POS of <20 means more padding to do
CPX #&28
BEQ L9EA0 POS of 40 means we are done padding, so handle next item
BCS L9EE9 POS > 40
JSR LE25C X = Window Right - Window Left
CPX #&27 Exactly 40 characters wide?
BEQ L9EEF
.L9EE4
JSR L9F0C Print Space
BRA L9ECB
.L9EE9
CPX #&3C
BCC L9EE4 POS of <60 means more padding to do
BEQ L9EA0 POS of 60 means we are done padding, so handle next tiem
.L9EEF
JSR L9F1E Force a newline
BRA L9EA0 handle next item
This is the section of MOS code the loops forever, captured using ICE-65C02:
14.089772 : 9ECB : 20 52 E2 : JSR $E252
14.089778 : E252 : 20 6D E2 : JSR $E26D
14.089784 : E26D : A9 02 : LDA #$02
14.089786 : E26F : A0 10 : LDY #$10 ; access &0318 (X)
14.089788 : E271 : A2 00 : LDX #$00 ; subtract &0308 (window left)
14.089790 : E273 : 20 8A E2 : JSR $E28A
14.089796 : E28A : 38 : SEC
14.089798 : E28B : 2C 66 03 : BIT $0366 ; test bit 1 of VDU 23,16 setting
14.089802 : E28E : F0 0B : BEQ $E29B
14.089805 : E29B : B9 08 03 : LDA $0308,Y
14.089809 : E29E : FD 08 03 : SBC $0308,X
14.089813 : E2A1 : 60 : RTS
14.089819 : E276 : 48 : PHA ; push POS
14.089822 : E277 : A9 04 : LDA #$04
14.089824 : E279 : C8 : INY ; access &0319 (Y)
14.089826 : E27A : A2 03 : LDX #$03 ; subtract &030B (window top)
14.089828 : E27C : 20 8A E2 : JSR $E28A
14.089834 : E28A : 38 : SEC
14.089836 : E28B : 2C 66 03 : BIT $0366 ; test bit 2 of VDU 23,16 setting
14.089840 : E28E : F0 0B : BEQ $E29B
14.089843 : E29B : B9 08 03 : LDA $0308,Y
14.089847 : E29E : FD 08 03 : SBC $0308,X
14.089851 : E2A1 : 60 : RTS
14.089857 : E27F : AA : TAX ; X = VPOS
14.089859 : E280 : A8 : TAY ; Y = VPOS
14.089861 : E281 : A9 08 : LDA #$08
14.089863 : E283 : 2C 66 03 : BIT $0366 ; test bit 3 of VDU 23,16 setting
14.089867 : E286 : F0 24 : BEQ $E2AC
14.089870 : E2AC : FA : PLX ; X = POS
14.089874 : E2AD : 60 : RTS
14.089880 : E255 : 2C 6C 03 : BIT $036C ; b7 set when cursor off righthand edge of screen
14.089884 : E258 : 10 01 : BPL $E25B
14.089887 : E25B : 60 : RTS
14.089893 : 9ECE : 8A : TXA ; A = POS
14.089895 : 9ECF : F0 CF : BEQ $9EA0
14.089897 : 9ED1 : E0 14 : CPX #$14
14.089899 : 9ED3 : F0 CB : BEQ $9EA0 ; A = 20
14.089901 : 9ED5 : 90 0D : BCC $9EE4
14.089904 : 9EE4 : 20 0C 9F : JSR $9F0C ; Print a space
14.089910 : 9F0C : A9 20 : LDA #$20
14.089912 : 9F0E : DA : PHX
14.089915 : 9F0F : A6 B0 : LDX $B0
14.089918 : 9F11 : DA : PHX
14.089921 : 9F12 : A6 B1 : LDX $B1
14.089924 : 9F14 : 20 EE FF : JSR $FFEE
14.089930 : FFEE : 6C 0E 02 : JMP ($020E)
14.089936 : 0900 : 48 : PHA
14.089939 : 0901 : A9 03 : LDA #$03only on the Pi VDU dsriver,
14.089941 : 0903 : 8D E2 FE : STA $FEE2
14.089945 : 0906 : 68 : PLA
14.089949 : 0907 : 8D E4 FE : STA $FEE4
14.089953 : 090A : 60 : RTS
14.089959 : 9F17 : 86 B1 : STX $B1
14.089962 : 9F19 : FA : PLX
14.089966 : 9F1A : 86 B0 : STX $B0
14.089969 : 9F1C : FA : PLX
14.089973 : 9F1D : 60 : RTS
14.089979 : 9EE7 : 80 E2 : BRA $9ECB
I was originally thinking we could fix this by intercepting OSBYTE &86 on the host to read POS, VPOS from the Pi Frame Buffer, but:
Instead, I've solved this by extending our host side VDU driver to maintain POS at &0318:
;; Host-side OSWRCH Redirector
;;
;; This redirects OSWRCH calls on the host back over to the Pi VDU driver
;;
;; It's used for the output of MOS command (like *CAT, *HELP, etc)
.host_oswrch_start
;; Stack the character to be printed
PHA
;; Emulate the POS VDU variable at &0318
;; This is used directly by *HELP MOS for padding and also by *CAT in ADFS
CMP #12 ; Clear screen returns cursor to POS=0
BEQ zero_pos
CMP #13 ; So does carriage returnhome
BEQ zero_pos
CMP #30 ; So does home cursor
BEQ zero_pos
;; There are other cases we ignore for now (VDU 8; VDU 9; VDU 31,x,y; VDU 127)
;; as these are very unlikely to be emitted by the POS commands that read back POS
CMP #32 ; Set C=1 if printable char (i.e. space or greater)
BCC write_fifo
INC &0318 ; printable char, so increment POS by one
LDA &0318 ; compare POS to the window width
CLC
ADC &0308 ; plus Window Left
CMP &030A ; compare to Window Right
BCC write_fifo ; Still within window?
.zero_pos
;; Zero pos (cursor in left most columb)
LDA #&00
STA &0318
.write_fifo
;; Select the VDU FIFO at &FEE4
LDA #&03
STA &FEE2
;; Restore the character to be printed
PLA
;; Write character to the VDU FIFO
STA &FEE4
RTS
.host_oswrch_end
This is because the *HELP code in the MOS reads the POS VDU variable directly.