; ; Atari XL shadow RAM handlers ; ; Christian Groessler, chris@groessler.org, 2013 ; DEBUG = 1 .if .defined(__ATARIXL__) .include "atari.inc" .include "save_area.inc" .include "zeropage.inc" .import __CHARGEN_START__ .export sram_init .export KEYBDV_wrapper BUFSZ = 128 BUFSZ_CIO = BUFSZ BUFSZ_SIO = BUFSZ .macro disable_rom lda PORTB and #$fe sta PORTB lda #>__CHARGEN_START__ sta CHBAS sta CHBASE .endmacro .macro enable_rom lda PORTB ora #1 sta PORTB lda #$E0 sta CHBAS sta CHBASE .endmacro .segment "INIT" ;enable_count: .res 1 ; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer sram_init: ; disable all interrupts sei ldx #0 stx NMIEN ; disable NMI ; disable ROMs disable_rom ; setup interrupt vectors lda #my_IRQ_han sta $ffff lda #my_RESET_han sta $fffd lda #my_NMI_han sta $fffb ; setup pointers to CIOV and SIOV wrappers lda #$4C ; JMP opcode sta CIOV lda #my_CIOV sta CIOV+2 lda #$4C ; JMP opcode sta SIOV lda #my_SIOV sta SIOV+2 ; enable interrupts lda #$40 sta NMIEN cli rts .segment "EXTZP" : zeropage zpptr1: .res 2 .segment "LOWBUFS" ; bounce buffers for CIO and SIO calls CIO_buffer: .res BUFSZ_CIO SIO_buffer: .res BUFSZ_SIO .segment "LOWCODE" ; Interrupt handlers ; ------------------ ; The interrupt handlers don't look at the current state of PORTB and ; unconditionally disable the ROMs on exit. ; Please note that this works, since if the ROMs are enabled we anyway ; aren't being called here because the vectors are pointing to their ; original ROM locations. .macro int_wrap orgvec .local ret pha enable_rom lda #>ret pha lda # data too large for our buffers ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES lda # bounce buffer size? bcs br_last ; no, last transfer, use remaining size lda #>BUFSZ_CIO sta ICBLH,x ; set data length lda # data too large for our buffers ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES lda # bounce buffer size? bcs bw_last ; no, last transfer, use remaining size lda #>BUFSZ_CIO sta ICBLH,x ; set data length lda #BUFSZ_CIO sbc orig_len+1 rts ; copy data from bounce buffer into user buffer ; input: X - IOCB index ; zpptr1 - pointer to user buffer ; output: A - destroyed ; Y - 0 copy_to_user: ldy ICBLL,x ; get # of bytes read (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) beq @copy_done @copy: dey lda CIO_buffer,y sta (zpptr1),y cpy #0 bne @copy @copy_done: rts ; copy data from user buffer into bounce buffer ; input: X - IOCB index ; zpptr1 - pointer to user buffer ; output: A - destroyed ; Y - 0 copy_from_user: ldy ICBLL,x ; get # of bytes to write (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) beq @copy_done @copy: dey lda (zpptr1),y sta CIO_buffer,y cpy #0 bne @copy @copy_done: rts ; copy ICBLL/ICBLH to 'orig_len' ; input: X - IOCB index ; output: A - destroyed iocblen_to_orig_len: lda ICBLL,x sta orig_len lda ICBLH,x sta orig_len+1 rts ; copy ICBAL/ICBAH to 'orig_ptr' ; input: X - IOCB index ; output: A - destroyed iocbptr_to_orig_ptr: lda ICBAL,x sta orig_ptr lda ICBAH,x sta orig_ptr+1 rts ; copy 'orig_ptr' to ICBAL/ICBAH ; input: X - IOCB index ; output: A - destroyed orig_ptr_to_iocbptr: lda orig_ptr sta ICBAL,x lda orig_ptr+1 sta ICBAH,x rts ; restore original contents of ICBAL/ICBAH from 'zpptr1' ; input: X - IOCB index ; output: A - destroyed restore_icba: lda zpptr1 sta ICBAL,x lda zpptr1+1 sta ICBAH,x rts ; put bounce buffer address into ICBAL/ICBAH ; input: X - IOCB index ; output: A - destroyed ciobuf_to_iocb: lda #CIO_buffer sta ICBAH,x rts ; copy file name pointed to by 'zpptr1' to bounce buffer 'CIO_buffer' ; input: Y - index into file name buffer and CIO_buffer ; output: Y - points to first invalid byte after file name ; A - destroyed copy_filename: lda (zpptr1),y sta CIO_buffer,y beq copy_fn_done iny cmp #ATEOL bne copy_filename dey copy_fn_done: rts ; write IOCB buffer address into zpptr1 ; input: X - IOCB index ; output: Y - 0 (for setup_zpptr1_y0, else unchanged) ; A - destroyed setup_zpptr1_y0: ldy #0 setup_zpptr1: lda ICBAL,x ; put buffer address into zp pointer sta zpptr1 lda ICBAH,x sta zpptr1+1 rts ;--------------------------------------------------------- my_SIOV: pha lda PORTB sta cur_SIOV_PORTB enable_rom pla jsr SIOV_org php pha lda cur_SIOV_PORTB sta PORTB pla plp rts ;--------------------------------------------------------- KEYBDV_wrapper: lda #>(kret-1) pha lda #<(kret-1) pha lda PORTB sta cur_KEYBDV_PORTB enable_rom lda KEYBDV+5 pha lda KEYBDV+4 pha rts ; call keyboard handler kret: pha lda cur_KEYBDV_PORTB sta PORTB pla rts CIO_a: .res 1 CIO_x: .res 1 CIO_y: .res 1 CIO_p: .res 1 cur_CIOV_PORTB: .res 1 cur_SIOV_PORTB: .res 1 cur_KEYBDV_PORTB: .res 1 orig_ptr: .res 2 orig_len: .res 2 req_len: .res 2 retlen: .res 2 .endif ; .if .defined(__ATARIXL__)