neilsf / xc-basic3

A BASIC cross compiler for MOS 6502-based machines
MIT License
44 stars 5 forks source link

PET: Support for LOCATE to position cursor #271

Open kochs-online opened 1 month ago

kochs-online commented 1 month ago

According to the documentation of LOCATE this keyword is not supported for PET targets.

I used this code to successfully position the cursor using the Kernal editor ROM routine to set screen pointers:

pha        ; store current content of accumulator
lda #$07   ; set column (X) to 7
sta SCR_COL
lda #$02   ; set row/line (Y) to 2
sta SCR_ROW
pla        ; re-store accumulator content
jsr SET_SCR_PTR  ; set screen pointers

SCR_COL is $E2 for BASIC 1 and $C6 for BASIC 2 & BASIC 4. SCR_ROW is $F5 for BASIC 1 and $D8 for BASIC 2 & BASIC 4. SET_SCR_PTR is $E5DB for BASIC 1, $E25D for BASIC 2, $E071 for BASIC 4 (40 columns) and $E067 for BASIC 4 (80 columns); I haven't found the address for BASIC 1, BASIC 2 and BASIC 4 (40 column) yet.

neilsf commented 1 month ago

Great, thanks. I can implement LOCATE for the PET once we have the ROM address for all targets.

kochs-online commented 1 month ago

I added the missing ROM addresses above and tested all of them successfully in VICE:

Trying to find the addresses I noticed, that the routines mentioned above are edtior ROM routines (located within $E000-$E0FF memory range). Considering how many different editor ROMs are around I wasn't so sure anymore, if using the ROM routines really is a good idea…

Maybe it would be better (in terms of compatibility with different editor ROMs) to implement LOCATE the same way these ROM routines do it one way or another?

So I tried to understand how it works and in the end the routines only perform a lookup of the screen memory address using the given row/line. This address is then written to a zero-page address. The given column is written directly to another zero-page address.

Here is an example for BASIC 4 (80 columns) from the PET BASIC and Kernal 4.0 ROM Disassembly:

; - Set Screen Pointers

E067    iE067   LDX $D8     ; Current Cursor Physical Line Number
E069        JMP $E06F

E06C    iE06C   LDY $E2     ; 4.80: first column of window (left margin)
E06E        DEY
E06F    iE06F   LDA $E755,X ; - Screen Line Addresses LO        DATA
E072        STA $C4     ; Pointer: Current Screen Line Address
E074        LDA $E76E,X ; - Screen Line Addresses HI        DATA
E077        STA $C5
E079        RTS

So the routine only reads the desired cursor position line number from $D8, performs a lookup of the address (low byte & high byte) of the first column of this line and stores this address at $C4 and $C5. (The desired cursor position row number is stored in $C6 elsewhere.)

The lookup addresses (here: $E755 and $E76E) differ of course for all the ROMs, but since we know the screen memory always starts at $8000 (it does, does it?!) we can calculate the address. All we need to know is the physical screen line length (40 or 80 characters/columns) of the target machine. This length value is already stored in zero-page address $D5 for BASIC 2 & BASIC 4 and $F2 for BASIC 1.

In the end all that is required is this pseudo-code (I'm not yet fluent enough in Assembler, sorry!):

; SCR_LN_ADDR = SCR_MEM_START + y_pos * (SCR_WDTH + 1)
lda #SCR_LN_ADDR[LO]
sta SCR_LN_PTR[LO]
lda #SCR_LN_ADDR[HI]
sta SCR_LN_PTR[HI]
lda x_pos
sta CRS_COL
lda y_pos
sta CRS_ROW   ; required for next call of editor ROM subroutine by Kernal or BASIC
These are the required addresses for different PET targets: BASIC 1 BASIC 2 & 4 Description
$8000 $8000 SCR_MEM_START: starting address of screen memory
$F2 $D5 SCR_WIDTH: length of screen line (39 or 79)
$E0-$E1 $C4-$C5 SCR_LN_PTR: pointer to screen RAM position of start of current line
$E2 $C6 CRS_COL: position of cursor along line (column)
$F5 $D8 CRS_ROW: screen line of cursor (row)
neilsf commented 1 month ago

Thanks! This is why many I/O commands aren't implemented for the PET, which does not expose a consistent KERNAL API. The second approach seems easy though, I'll give it a shot.

kochs-online commented 1 month ago

Great, thank you! Let me know, if I can be of any assistance!