Search code examples
6502

6502 JSR changes on stack required for RTS utility as "function call"


6502 JSR call pushes 2bytes onto the stack, which have to be on "top" of the stack for RTS.

Is there a good practice for using JSR for organizing 6502 code into functions that solves the following predicaments: Assuming the following 1:"function call" and 2:"function"

ldx #$00
ldy #$01
lda cursor_x
pha
lda cursor_y
jsr set_sprite_x_y_sa

set_sprite_x_y_sa: 
;u have to use stack..
;or ram/rom
;ldx #$00
;ldy #$01
;lda cursor_x ;(!)
;pha          ;(!)
;lda cursor_y ;(!)

; y position
sta oam, X
inx
; tile
tya ; transfer val y to a
sta oam, X
inx
; attributes
lda #%00000000 ; no flip
sta oam, X
inx
; x position
pla
sta oam, X
rts

The program will fail to run unless lines marked by (!) are not commented out because pla returns part of the return address from stack. The stack could be popped and stored twice to get the intended value from the stack, then pushed back on twice to please rts, but there are not enough registers to do that (X has to be used). So is the only remaining option to use only the stack in combination with the accumulator, and have x, and y registers sit idle storing the 16 bits that have to be pushed back on before rts? Or is there some clever and fast way to manipulate the stack with SP?


Solution

  • I have a table of control code bytes (CONCODEC) which I scan to find the matching code and thus give me an index to the required jump address.

    That value is loaded into .Y which indexes into the subroutine address hi/lo byte tables (CONCODEL/CONCODEH).

    These hi/lo bytes get pushed to the stack and then RTS'd to (essentially an ON...GOSUB switch in BASIC terms). Those subroutines RTS back to whatever called the jump logic in the first place.

    You have to ensure the address hi-bytes have 1 subtracted, as RTS will add that back automatically.

        CONCODEC:
        .pc = * "CONCODEC"      // Control character code data
        .byte vic20.screencodes.WHITE,vic20.screencodes.CBMOFF, ... etc
    
        CONCODEL:
        .pc = * "CONCODEL"      // Control character handler lo-bytes
        .byte <controlcode_handler.set_colour_byte-1,<controlcode_handler.shift_cbm-1, ... etc
    
        CONCODEH:
        .pc = * "CONCODEH"      // Control character handler hi-bytes
        .byte >controlcode_handler.set_colour_byte-1,>controlcode_handler.shift_cbm-1, ... etc
    
    
        // Switch to subroutine with CONCODEC in .Y
        lda CONCODEH,y          // [4]  get control code handler address hi-byte
        pha                     // [3]  push to Stack
        lda CONCODEL,y          // [4]  get control code handler address lo-byte
        pha                     // [3]  push to Stack
        rts                     // [6]  return via control code handler