; Christian Groessler, chris@groessler.org, 2013
;
+
.if .defined(__ATARIXL__)
.include "atari.inc"
.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
.segment "INIT"
+enable_count: .res 1
+
; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer
sram_init:
stx NMIEN ; disable NMI
; disable ROMs
+ ;inx
+ stx enable_count
disable_rom
; setup interrupt vectors
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
int_wrap RESET_save
+; System request handlers
+; -----------------------
+
+; CIO handler
+; We have buffer pointer and length entries in the IOCB, but their
+; usage depends on the function.
+; Some functions don't care about both (pointer and length), and some
+; only use the pointer (like e.g. OPEN), and some use both.
+; So we need function specific handlers to correctly deal with
+; buffers which are overlapping with the ROM area.
+; All input and output registers need to be preserved (I'm not 100%
+; sure about Y, but let's preserve it for now.)
+;
+; FIXME: Currently only the requests used by the runtime lib are handled.
+
my_CIOV:
+
+; @@@ TODO: check X for valid IOCB index ((X < $80) and ((X & $F) == 0))
+
+ sta CIO_a
+ sty CIO_y
+ stx CIO_x
+
+ lda ICCOM,x ; get function
+ cmp #OPEN
+ beq CIO_filename ; filename as input parameter in buffer, length not used
+ cmp #PUTREC
+ bcc CIO_read ; input (GETREC or GETCHR)
+ cmp #CLOSE
+ bcc CIO_write ; output (PUTREC or PUTCHR)
+ beq CIO_pass ; pass through, buffer not used
+ cmp #RENAME ; 2 filenames as input parameters in buffer, length not used
+ beq CIO_filename2
+ cmp GETCWD
+ bcc CIO_filename ; filename as parameter in buffer, length not used
+ beq CIO_read ; input
+ bcs CIO_pass ; other command: assume no buffers
+
+
+
+.if 0 ; all crap
+; check if buffer is potentially used (buffer length != 0)
+
pha
+ lda ICBLL,x
+ ora ICBLH,x
+ bne could_be
+ pla
+ jmp CIOV_call
+
+; buffer might be used by the request
+
+could_be:
+
+; check if buffer is inside ROM area
+
+ lda ICBAH,x
+ cmp #$C0 ; if buffer is above $C000, it's definitely inside ROM area
+ bcs need_work
+
+ lda ICBAL,x ; low byte of buffer address
+ adc ICBLL,x ; low byte of buffer length
+ lda ICBAH,x ; high byte (address)
+ adc ICBLH,x ; high byte (length)
+ cmp #$C0
+ bcc CIOV_call ; no need to use bounce buffers, just forward call to CIO
+
+need_work:
+
+; Check if length is bigger than the size of our bounce buffer.
+; If yes, we need to split the call into multiple calls.
+; @@@ FIXME: currently only supports bounce buffers < 256 bytes
+
+ lda ICBLH,x ; high byte of length
+ bne hard_work
+ lda ICBLL,x ; low byte of length
+ cmp #<BUFSZ_CIO
+ beq little_work
+ bcs hard_work
+
+; Request buffer is smaller or equal to our bounce buffer.
+; Copy the data into the bounce buffer, set bounce buffer address
+; in the IOCB, call CIO, and copy the output data back.
+; @@@ TODO: check for read/write and do only one of the copy operations
+little_work:
+
+
+
+; Request buffer is larger than our bounce buffer.
+hard_work:
+
+.endif ; crap alert
+
+CIOV_call:
+ pha
+ lda PORTB
+ sta cur_CIOV_PORTB
enable_rom
pla
jsr CIOV_org
php
pha
- disable_rom
+ lda cur_CIOV_PORTB
+ sta PORTB
pla
plp
rts
+
my_SIOV:
pha
+ lda PORTB
+ sta cur_SIOV_PORTB
enable_rom
pla
jsr SIOV_org
php
pha
- disable_rom
+ 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
pha
rts ; call keyboard handler
kret: pha
- disable_rom
+ 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__)