X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=libsrc%2Fatari%2Fshadow_ram_handlers.s;h=a8ba611b6ca45407f15c465d9fd0ca63d906008b;hb=fdce8fb34d9917033f1fdd008a771ec37119a66e;hp=56ddc76c3fc4d2e50bdac8addf6192ef2d6d851d;hpb=68fc4a1b1577f897d582dd605376fb6d4151101c;p=cc65 diff --git a/libsrc/atari/shadow_ram_handlers.s b/libsrc/atari/shadow_ram_handlers.s index 56ddc76c3..a8ba611b6 100644 --- a/libsrc/atari/shadow_ram_handlers.s +++ b/libsrc/atari/shadow_ram_handlers.s @@ -4,88 +4,75 @@ ; Christian Groessler, chris@groessler.org, 2013 ; -DEBUG = 1 +;DEBUG = 1 +CHKBUF = 1 ; check if bounce buffering is needed (bounce buffering is always done if set to 0) -.if .defined(__ATARIXL__) +.ifdef __ATARIXL__ - SHRAM_HANDLERS = 1 +SHRAM_HANDLERS = 1 .include "atari.inc" - .include "save_area.inc" + .include "save_area.inc" .include "zeropage.inc" - .import __CHARGEN_START__ - - .export sram_init - .export KEYBDV_handler - .export CIO_handler - .export SIO_handler - .export SETVBV_handler - -BUFSZ = 128 ; bounce buffer size -BUFSZ_SIO = 256 - -.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 + .include "romswitch.inc" + + .import __CHARGEN_START__ -.segment "INIT" + .export sram_init + .export KEYBDV_handler + .export CIO_handler + .export SIO_handler + .export SETVBV_handler + .export XMOVE_handler + +BUFSZ = 128 ; bounce buffer size +BUFSZ_SIO = 256 + +.segment "ONCE" ; Turn off ROMs, install system and interrupt wrappers, set new chargen pointer sram_init: ; disable all interrupts - sei - ldx #0 - stx NMIEN ; disable NMI + ldx #0 + stx NMIEN ; disable NMI + sei ; disable ROMs - disable_rom + disable_rom ; setup interrupt vectors - lda #my_IRQ_han - sta $ffff + lda #my_IRQ_han + sta $ffff - lda #my_RESET_han - sta $fffd + lda #my_RESET_han + sta $fffd - lda #my_NMI_han - sta $fffb + lda #my_NMI_han + sta $fffb ; enable interrupts - lda #$40 - sta NMIEN - cli + cli + lda #$40 + sta NMIEN - rts + rts .segment "EXTZP" : zeropage -zpptr1: .res 2 +zpptr1: .res 2 -.segment "LOWBUFS" +.segment "LOWBSS" ; bounce buffers for CIO and SIO calls -bounce_buffer: .res BUFSZ_SIO +bounce_buffer: .res BUFSZ_SIO .segment "LOWCODE" @@ -100,71 +87,71 @@ bounce_buffer: .res BUFSZ_SIO ; 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 #ret + pha + lda # data too large for our buffers - ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES - 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 + jsr cmp_orig_len_bnc_bufsz ; is transfer length > bounce buffer size? + bcs br_last ; no, last transfer, use remaining size - lda #>BUFSZ - sta ICBLH,x ; set data length - lda #BUFSZ + sta ICBLH,x ; set data length + lda # data too large for our buffers - ; CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES - 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 + jsr cmp_orig_len_bnc_bufsz ; is transfer length > bounce buffer size? + bcs bw_last ; no, last transfer, use remaining size - lda #>BUFSZ - sta ICBLH,x ; set data length - lda #BUFSZ + sta ICBLH,x ; set data length + lda #BUFSZ - sbc orig_len+1 - rts + sec + lda #BUFSZ + 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 +; 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 bounce_buffer,y - sta (zpptr1),y - cpy #0 - bne @copy + ldy ICBLL,x ; get # of bytes read (CHANGE HERE TO SUPPORT BOUNCE BUFFERS > 255 BYTES) + beq @copy_done +@copy: dey + lda bounce_buffer,y + sta (zpptr1),y + cpy #0 + bne @copy @copy_done: - rts + rts ; copy data from user buffer into bounce buffer ; input: X - IOCB index ; zpptr1 - pointer to user buffer ; output: A - destroyed -; Y - 0 +; 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 bounce_buffer,y - cpy #0 - bne @copy + 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 bounce_buffer,y + cpy #0 + bne @copy @copy_done: - rts + 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 + 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 + 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 + 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 + 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 bncbuf_to_iocb: - lda #bounce_buffer - sta ICBAH,x - rts + lda #bounce_buffer + sta ICBAH,x + rts ; copy file name pointed to by 'zpptr1' to 'bounce_buffer' @@ -667,15 +668,15 @@ bncbuf_to_iocb: ; output: Y - points to first invalid byte after file name ; A - destroyed copy_filename: - lda (zpptr1),y - sta bounce_buffer,y - beq copy_fn_done - iny - cmp #ATEOL - bne copy_filename - dey + lda (zpptr1),y + sta bounce_buffer,y + beq copy_fn_done + iny + cmp #ATEOL + bne copy_filename + dey copy_fn_done: - rts + rts ; write IOCB buffer address into zpptr1 @@ -683,13 +684,132 @@ copy_fn_done: ; output: Y - 0 (for setup_zpptr1_y0, else unchanged) ; A - destroyed setup_zpptr1_y0: - ldy #0 + ldy #0 setup_zpptr1: - lda ICBAL,x ; put buffer address into zp pointer - sta zpptr1 - lda ICBAH,x - sta zpptr1+1 - rts + lda ICBAL,x ; put buffer address into zp pointer + sta zpptr1 + lda ICBAH,x + sta zpptr1+1 + rts + + +.if CHKBUF + +; get length of file name pointed to by 'zpptr1' +; input: Y - index into file name +; output: Y - length +; A - destroyed +get_fn_len: + lda (zpptr1),y + beq @done + iny + cmp #ATEOL + bne get_fn_len + dey +@done: + rts + + +chk_CIO_buf_fn2: + tya + pha + lda ICBLL,x + pha + lda ICBLH,x + pha + jsr setup_zpptr1_y0 + jsr get_fn_len + iny ; include terminating zero + bne fn_cont + +chk_CIO_buf_fn: + tya + pha + lda ICBLL,x + pha + lda ICBLH,x + pha + jsr setup_zpptr1_y0 +fn_cont:jsr get_fn_len + iny ; include terminating zero + tya + sta ICBLL,x + lda #0 + sta ICBLH,x + jsr chk_CIO_buf + pla + sta ICBLH,x + pla + sta ICBLL,x + pla + tay + rts + + +; check if a CIO input/output buffer overlaps with ROM area (>= $C000) +; input: X - IOCB index +; ICBAL/ICBAH/ICBLL/ICBLH - buffer address and length +; output: CF - 1/0 for overlap/no overlap +; A - destroyed + +chk_CIO_buf: + lda ICBAH,x + cmp #$c0 + bcc @cont +@ret: +.ifdef DEBUG + jsr CIO_buf_noti +.endif + rts + +@cont: lda ICBAL,x + clc + adc ICBLL,x + lda ICBAH,x + adc ICBLH,x + bcs @ret ; ??? wraparound + cmp #$c0 +.ifdef DEBUG + jsr CIO_buf_noti +.endif + rts + +.ifdef DEBUG +; write to screen memory on 2nd line: +; pos 0: # of accesses without buffering +; pos 1: # of accesses with buffering +CIO_buf_noti: + php + pha + tya + pha + bcc @nobuf + + inc CIObnval_dobuf + jmp @cont + +@nobuf: inc CIObnval_nobuf + +@cont: ldy #40 + lda CIObnval_nobuf + sta (SAVMSC),y + ldy #41 + lda CIObnval_dobuf + sta (SAVMSC),y + + pla + tay + pla + plp + rts + +CIObnval_dobuf: + .byte 0 +CIObnval_nobuf: + .byte 0 +.endif + +.endif ; .if CHKBUF ;--------------------------------------------------------- @@ -699,37 +819,36 @@ setup_zpptr1: ; For other function we return NVALID status code. SIO_handler: - lda DCOMND ; get command - cmp #SIO_STAT - beq SIO_stat - cmp #SIO_READ - beq SIO_read - cmp #SIO_WRITE - beq SIO_write - cmp #SIO_WRITEV - beq SIO_write - - ; unhandled command - lda #NVALID -SIO_err:sta DSTATS - rts + lda DCOMND ; get command + cmp #SIO_STAT + beq SIO_stat + cmp #SIO_READ + beq SIO_read + cmp #SIO_WRITE + beq SIO_write + cmp #SIO_WRITEV + beq SIO_write + + ; unhandled command + lda #NVALID +SIO_err:sta DSTATS + rts ; SIO_STAT is always called with a low buffer (by the runtime) SIO_stat: - ; fall thru + ; fall thru SIO_call: - lda PORTB - sta cur_SIOV_PORTB - enable_rom - jsr SIOV_org - php - pha - lda cur_SIOV_PORTB - sta PORTB - pla - plp - rts + lda PORTB + sta cur_SIOV_PORTB + enable_rom + jsr SIOV_org + php + pha + disable_rom_val cur_SIOV_PORTB + pla + plp + rts ; SIO read handler @@ -737,48 +856,51 @@ SIO_call: SIO_read: -; @@@ TODO: check if bounce buffer is really needed because buffer is in ROM area +.if CHKBUF + jsr chk_SIO_buf + bcc SIO_call +.endif ; we only support transfers <= bounce buffer size - jsr cmp_sio_len_bnc_bufsz - bcs sio_read_len_ok + jsr cmp_sio_len_bnc_bufsz + bcs sio_read_len_ok - lda #DERROR ; don't know a better status code for this - bne SIO_err + lda #DERROR ; don't know a better status code for this + bne SIO_err sio_read_len_ok: - lda DBUFLO - sta zpptr1 ; remember destination buffer address - lda DBUFHI - sta zpptr1+1 + lda DBUFLO + sta zpptr1 ; remember destination buffer address + lda DBUFHI + sta zpptr1+1 - jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI + jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI - jsr SIO_call ; do the operation - pha - lda DSTATS ; get status - bmi sio_read_ret ; error + jsr SIO_call ; do the operation + pha + lda DSTATS ; get status + bmi sio_read_ret ; error - ; copy data to user buffer + ; copy data to user buffer sio_read_ok: - lda DBYTHI ; could be 1 for 256 bytes - beq srok1 - ldy #0 - beq srok2 -srok1: ldy DBYTLO -srok2: dey + lda DBYTHI ; could be 1 for 256 bytes + beq srok1 + ldy #0 + beq srok2 +srok1: ldy DBYTLO +srok2: dey sio_read_copy: - lda bounce_buffer,y - sta (zpptr1),y - dey - cpy #$ff - bne sio_read_copy + lda bounce_buffer,y + sta (zpptr1),y + dey + cpy #$ff + bne sio_read_copy sio_read_ret: - jsr orgbuf_to_dbuf + jsr orgbuf_to_dbuf - pla - rts ; success return + pla + rts ; success return ; SIO write handler @@ -786,42 +908,45 @@ sio_read_ret: SIO_write: -; @@@ TODO: check if bounce buffer is really needed because buffer is in ROM area +.if CHKBUF + jsr chk_SIO_buf + bcc SIO_call +.endif ; we only support transfers <= bounce buffer size - jsr cmp_sio_len_bnc_bufsz - bcs sio_write_len_ok + jsr cmp_sio_len_bnc_bufsz + bcs sio_write_len_ok - lda #DERROR ; don't know a better status code for this - bne SIO_err + lda #DERROR ; don't know a better status code for this + jmp SIO_err sio_write_len_ok: - lda DBUFLO - sta zpptr1 ; get source buffer address - lda DBUFHI - sta zpptr1+1 - - ; copy data from user buffer to bounce buffer - lda DBYTHI ; could be 1 for 256 bytes - beq swok1 - ldy #0 - beq swok2 -swok1: ldy DBYTLO -swok2: dey + lda DBUFLO + sta zpptr1 ; get source buffer address + lda DBUFHI + sta zpptr1+1 + + ; copy data from user buffer to bounce buffer + lda DBYTHI ; could be 1 for 256 bytes + beq swok1 + ldy #0 + beq swok2 +swok1: ldy DBYTLO +swok2: dey sio_write_copy: - lda (zpptr1),y - sta bounce_buffer,y - dey - cpy #$ff - bne sio_write_copy + lda (zpptr1),y + sta bounce_buffer,y + dey + cpy #$ff + bne sio_write_copy - jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI + jsr bncbuf_to_dbuf ; put bounce buffer address to DBUFLO/DBUFHI - jsr SIO_call ; do the operation - pha - jsr orgbuf_to_dbuf - pla - rts + jsr SIO_call ; do the operation + pha + jsr orgbuf_to_dbuf + pla + rts ; check if SIO length is larger than bounce buffer size @@ -829,85 +954,168 @@ sio_write_copy: ; output: A - destroyed ; CF - 0/1 for larger/not larger cmp_sio_len_bnc_bufsz: - sec - lda #BUFSZ_SIO - sbc DBYTHI - rts + sec + lda #BUFSZ_SIO + sbc DBYTHI + rts ; put bounce buffer address into DBUFLO/DBUFHI ; input: (--) ; output: A - destroyed bncbuf_to_dbuf: - lda #bounce_buffer - sta DBUFHI - rts + lda #bounce_buffer + sta DBUFHI + rts ; put original buffer address into DBUFLO/DBUFHI ; input: zpptr1 - original pointer ; output: A - destroyed orgbuf_to_dbuf: - lda zpptr1 - sta DBUFLO - lda zpptr1+1 - sta DBUFHI - rts + lda zpptr1 + sta DBUFLO + lda zpptr1+1 + sta DBUFHI + rts + +.if CHKBUF + +; check if a SIO input/output buffer overlaps with ROM area (>= $C000) +; input: DBUFLO/DBUFHI/DBYTLO/DBYTHI - buffer address and length +; output: CF - 1/0 for overlap/no overlap +; A - destroyed + +chk_SIO_buf: + lda DBUFHI + cmp #$c0 + bcc @cont +@ret: +.ifdef DEBUG + jsr SIO_buf_noti +.endif + rts + +@cont: lda DBUFLO + clc + adc DBYTLO + lda DBUFHI + adc DBYTHI + bcs @ret ; ??? wraparound + cmp #$c0 +.ifdef DEBUG + jsr SIO_buf_noti +.endif + rts + +.ifdef DEBUG +; write to screen memory on 2nd line: +; pos 38: # of accesses without buffering +; pos 39: # of accesses with buffering +SIO_buf_noti: + php + pha + tya + pha + bcc @nobuf + + inc SIObnval_dobuf + jmp @cont + +@nobuf: inc SIObnval_nobuf + +@cont: ldy #78 + lda SIObnval_nobuf + sta (SAVMSC),y + ldy #79 + lda SIObnval_dobuf + sta (SAVMSC),y + + pla + tay + pla + plp + rts + +SIObnval_dobuf: + .byte 0 +SIObnval_nobuf: + .byte 0 +.endif + +.endif ; .if CHKBUF ;--------------------------------------------------------- KEYBDV_handler: - lda #>(kret-1) - pha - lda #<(kret-1) - pha - lda PORTB - sta cur_KEYBDV_PORTB - enable_rom - lda KEYBDV+5 + 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 + rts ; call keyboard handler +kret: pha + disable_rom_val cur_KEYBDV_PORTB + pla + rts ;--------------------------------------------------------- SETVBV_handler: - pha - lda PORTB - sta cur_SETVBV_PORTB - enable_rom - pla - jsr SETVBV_org - php - pha - lda cur_SETVBV_PORTB - sta PORTB - pla - plp - 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 -cur_SETVBV_PORTB: .res 1 -orig_ptr: .res 2 -orig_len: .res 2 -req_len: .res 2 -retlen: .res 2 - -.endif ; .if .defined(__ATARIXL__) + pha + lda PORTB + sta cur_SETVBV_PORTB + enable_rom + pla + jsr SETVBV_org + php + pha + disable_rom_val cur_SETVBV_PORTB + pla + plp + rts + +;--------------------------------------------------------- + +XMOVE_handler: + + pha + lda PORTB + sta cur_XMOVE_PORTB + enable_rom + pla + jsr XMOVE_org + php + pha + disable_rom_val cur_XMOVE_PORTB + pla + plp + 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 +cur_SETVBV_PORTB: .res 1 +cur_XMOVE_PORTB: .res 1 +orig_ptr: .res 2 +orig_len: .res 2 +req_len: .res 2 +retlen: .res 2 + +.endif ; .ifdef __ATARIXL__