; ; Atari XL shadow RAM handlers ; ; Christian Groessler, chris@groessler.org, 2013 ; .if .defined(__ATARIXL__) .include "atari.inc" .include "save_area.inc" .import __CHARGEN_START__ .export sram_init .export KEYBDV_wrapper BUFSZ = 128 BUFSZ_CIO = BUFSZ BUFSZ_SIO = BUFSZ .macro disable_rom .local cont ;dec enable_count ;bne cont lda PORTB and #$fe sta PORTB lda #>__CHARGEN_START__ sta CHBAS sta CHBASE cont: .endmacro .macro enable_rom ;inc enable_count 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 ;inx stx enable_count 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 "LOWBUFS" ; bounce buffers for CIO and SIO calls CIOV_buffer: .res BUFSZ_CIO SIOV_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 #(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 cur_CIOV_PORTB: .res 1 cur_SIOV_PORTB: .res 1 cur_KEYBDV_PORTB: .res 1 .endif ; .if .defined(__ATARIXL__)