From: Christian Groessler Date: Wed, 12 Jun 2013 11:27:28 +0000 (+0200) Subject: intermediate check-in -- added handling of read requests X-Git-Tag: V2.15~223^2~100 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=e5f409e357a82a4ae69374b1fcd692ec5b3eb6a3;p=cc65 intermediate check-in -- added handling of read requests --- diff --git a/libsrc/atari/shadow_ram_handlers.s b/libsrc/atari/shadow_ram_handlers.s index 564568130..9bd9e11c3 100644 --- a/libsrc/atari/shadow_ram_handlers.s +++ b/libsrc/atari/shadow_ram_handlers.s @@ -9,6 +9,7 @@ .include "atari.inc" .include "save_area.inc" + .include "zeropage.inc" .import __CHARGEN_START__ .export sram_init @@ -19,19 +20,14 @@ 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 @@ -42,7 +38,7 @@ cont: .segment "INIT" -enable_count: .res 1 +;enable_count: .res 1 ; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer @@ -55,7 +51,7 @@ sram_init: ; disable ROMs ;inx - stx enable_count + ;stx enable_count disable_rom ; setup interrupt vectors @@ -95,16 +91,22 @@ sram_init: rts +.segment "EXTZP" : zeropage + +zpptr1: .res 2 +zpptr2: .res 2 + .segment "LOWBUFS" ; bounce buffers for CIO and SIO calls -CIOV_buffer: .res BUFSZ_CIO -SIOV_buffer: .res BUFSZ_SIO +CIO_buffer: .res BUFSZ_CIO +SIO_buffer: .res BUFSZ_SIO .segment "LOWCODE" + ; Interrupt handlers ; ------------------ @@ -142,20 +144,85 @@ my_RESET_han: ; System request handlers ; ----------------------- + +; for filenames we assume they will fit into our bounce buffer + +; one filename, terminated by "invalid character", located at ICBAL/ICBAH + +CIO_filename: + jsr setup_zpptr1_y0 + jsr copy_filename +CIO_fn_cont: + jsr ciobuf_to_iocb + ldy CIO_y + jsr CIO_call_a ; call CIO (maybe A isn't needed, then we could call CIO_call) + php + pha +;@@@ check if X is preserved over CIO call + jsr restore_icba ; restore original ICBAL/ICBAH + pla + plp + rts ; back to application + + +; two filenames, terminated and separated by "invalid character", located at ICBAL/ICBAH + +CIO_filename2: + jsr setup_zpptr1_y0 + jsr copy_filename + iny + jsr copy_filename + jmp CIO_fn_cont + + + +CIO_call_a: + lda CIO_a + +CIOV_call: + pha + lda PORTB + sta cur_CIOV_PORTB + enable_rom + pla + jsr CIOV_org + php + pha + lda cur_CIOV_PORTB + sta PORTB + pla + plp + rts + + + + +CIO_write: + lda ICBLL,x + ora ICBLH,x + beq CIO_call_a ; special I/O through A register in case buffer length is 0 + + ;... + bne CIO_call_a + + ; 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. +; Some functions don't care about any of them (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.) +; sure about Y as input, but let's preserve it for now.) ; ; FIXME: Currently only the requests used by the runtime lib are handled. my_CIOV: + ;jmp CIOV_call + ;brk + ; @@@ TODO: check X for valid IOCB index ((X < $80) and ((X & $F) == 0)) sta CIO_a @@ -169,84 +236,279 @@ my_CIOV: bcc CIO_read ; input (GETREC or GETCHR) cmp #CLOSE bcc CIO_write ; output (PUTREC or PUTCHR) - beq CIO_pass ; pass through, buffer not used + beq CIO_call_a ; 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 + cmp #GETCWD + bcc CIO_filename ; filename as input parameter in buffer, length not used beq CIO_read ; input - bcs CIO_pass ; other command: assume no buffers + bcs CIO_call_a ; other commands: assume no buffer +; not reached + +CIO_read: + lda ICBLL,x + ora ICBLH,x + beq CIO_call_a ; special I/O through A register in case buffer length is 0 + +; If the data length is larger than our bounce buffer, we have to split the request into smaller ones. +; Otherwise we can get away with one call and a copy to the final destination afterwards. + lda ICBLH,x ; get high byte of length + bne big_read ; not zero -> 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 #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 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 - cmp #$C0 ; if buffer is above $C000, it's definitely inside ROM area - bcs need_work + sta orig_ptr+1 + rts - 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: +; 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 -; 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 #CIO_buffer + sta ICBAH,x + rts -; Request buffer is larger than our bounce buffer. -hard_work: +; 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 -.endif ; crap alert -CIOV_call: - pha - lda PORTB - sta cur_CIOV_PORTB - enable_rom - pla - jsr CIOV_org - php - pha - lda cur_CIOV_PORTB - sta PORTB - pla - plp +; 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 @@ -263,6 +525,7 @@ my_SIOV: plp rts +;--------------------------------------------------------- KEYBDV_wrapper: @@ -284,8 +547,16 @@ kret: pha 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__)