diff --git a/dos/file.inc b/dos/file.inc index 0e5bf07a..0b69f820 100644 --- a/dos/file.inc +++ b/dos/file.inc @@ -4,6 +4,7 @@ .global file_read .global file_write .global file_read_block +.global file_write_block .global set_errno_status .global convert_errno_status diff --git a/dos/file.s b/dos/file.s index 22ad609b..0c0653ee 100644 --- a/dos/file.s +++ b/dos/file.s @@ -321,6 +321,89 @@ file_read_block: @eoi: sec bra @end + + +;--------------------------------------------------------------- +; file_write_block +; +; Write up to 256 bytes to the current context. The +; implementation is free to write any number of bytes, +; optimizing for speed and simplicity. +; +; In: y:x pointer to data +; a number of bytes to write +; =0: up to 256 +; c =0: regular save from memory +; =1: stream from single address (e.g. VERA_data0) +; Out: y:x number of bytes written +; c =1: error +;--------------------------------------------------------------- +file_write_block: + stx fat32_ptr + sty fat32_ptr + 1 + tax + ; backup krn_ptr1 and use as load type: MSB clear=ram / MSB set=single address + lda krn_ptr1 + pha + lda #0 + ror ; store carry flag as MSB of krn_ptr1 + sta krn_ptr1 ; fat32_read examines it to determine which copy routine to use. + txa + bne @1 + stz fat32_size + 0 + lda #1 + sta fat32_size + 1 + bra @2 + + ; A!=0: read A bytes +@1: sta fat32_size + 0 + stz fat32_size + 1 + + +@2: ; preserve requested size + lda fat32_size + 1 + pha + lda fat32_size + 0 + pha + + bit cur_mode + bpl @not_present + + ; Write + fat32_call fat32_write + ; restore krn_ptr1 (doesn't affect C) + bcc @error + + clc +@end: + ; restore preserved requested size + ; and calculate how much was written + ; so that it can be returned to the caller + pla + ply + php + sec + sbc fat32_size + 0 + tax + tya + sbc fat32_size + 1 + tay + plp + pla + sta krn_ptr1 + rts + +@error: + sec + lda fat32_errno + beq @end + + jsr set_errno_status +@not_present: + sec + bra @end + + ;--------------------------------------------------------------- file_write: bit cur_mode diff --git a/dos/jumptab.s b/dos/jumptab.s index 6ff36f71..b4cd8a7e 100644 --- a/dos/jumptab.s +++ b/dos/jumptab.s @@ -3,7 +3,7 @@ ;---------------------------------------------------------------------- ; (C)2020 Michael Steil, License: 2-clause BSD -.import dos_secnd, dos_tksa, dos_acptr, dos_ciout, dos_untlk, dos_unlsn, dos_listn, dos_talk, dos_macptr +.import dos_secnd, dos_tksa, dos_acptr, dos_ciout, dos_untlk, dos_unlsn, dos_listn, dos_talk, dos_macptr, dos_mciout .import dos_init, dos_set_time @@ -32,3 +32,4 @@ jmp dos_set_time ; 16 jmp dos_macptr ; 17 + jmp dos_mciout ; 18 diff --git a/dos/main.s b/dos/main.s index cb4307fe..0017d6fc 100644 --- a/dos/main.s +++ b/dos/main.s @@ -28,7 +28,7 @@ .import skip_mask ; jumptab.s -.export dos_secnd, dos_tksa, dos_acptr, dos_ciout, dos_untlk, dos_unlsn, dos_listn, dos_talk, dos_macptr +.export dos_secnd, dos_tksa, dos_acptr, dos_ciout, dos_untlk, dos_unlsn, dos_listn, dos_talk, dos_macptr, dos_mciout .export dos_set_time ; from declare.s, so that state can be cleared @@ -543,3 +543,38 @@ dos_macptr: @1: sec ; error: unsupported bra @end + +;--------------------------------------------------------------- +; BLOCK-WISE SEND +; +; In: y:x pointer to data +; a number of bytes to write +; =0: implementation decides; up to 512 +; Out: y:x number of bytes written +; c =1: unsupported/error +;--------------------------------------------------------------- +dos_mciout: + BANKING_START + bit cur_context + bmi @1 + + stz ieee_status + + jsr file_write_block + bcc @end + + phx + phy + jsr file_close_clr_channel + lda #$01 ; write timeout to indicate error + tsb ieee_status + clc + ply + plx + +@end: + BANKING_END + rts +@1: sec ; error: unsupported + bra @end + diff --git a/fat32/fat32.s b/fat32/fat32.s index 7344c01d..3199eb13 100644 --- a/fat32/fat32.s +++ b/fat32/fat32.s @@ -24,6 +24,7 @@ .import fat32_errno .import fat32_readonly +.macpack longbranch FLAG_IN_USE = 1<<0 ; Context in use FLAG_DIRTY = 1<<1 ; Buffer is dirty @@ -3345,6 +3346,7 @@ fat32_write_byte: ; ; fat32_ptr : pointer to data to write ; fat32_size (16-bit): size of data to write +; krn_ptr1 : if MSb set, copy all bytes from same source address. ; ; * c=0: failure; sets errno ;----------------------------------------------------------------------------- @@ -3368,7 +3370,6 @@ fat32_write: rts @1: lda #2 sta bytecnt + 1 - @nonzero: ; if (fat32_size - bytecnt < 0) bytecnt = fat32_size sec @@ -3388,6 +3389,15 @@ fat32_write: @3: ; Copy bytecnt bytes into buffer ldy bytecnt + bit krn_ptr1 + jmi @stream_save + lda fat32_ptr + 1 + cmp #$9f ; $9Fxx can overflow into $Axxx + bcc @3a ; source below banked RAM + cmp #$c0 + bcs @3a ; source above banked RAM + jmp @banked_save +@3a: dey beq @4b @4: lda (fat32_ptr), y @@ -3396,9 +3406,10 @@ fat32_write: bne @4 @4b: lda (fat32_ptr), y sta (fat32_bufptr), y - +@4c: ; fat32_ptr += bytecnt, fat32_bufptr += bytecnt, fat32_size -= bytecnt, file_offset += bytecnt add16 fat32_ptr, fat32_ptr, bytecnt +@4d: add16 fat32_bufptr, fat32_bufptr, bytecnt sub16 fat32_size, fat32_size, bytecnt add32_16 cur_context + context::file_offset, cur_context + context::file_offset, bytecnt @@ -3429,6 +3440,58 @@ fat32_write: @6: sec ; Indicate success rts +@stream_save: + ; Copy bytecnt bytes into buffer + ldy #0 +@7: lda (fat32_ptr) + sta (fat32_bufptr), y + iny + cpy bytecnt + bne @7 + jmp @4d +@banked_save: + ; save contents of temporary zero page + lda krn_ptr1 + pha + lda krn_ptr1+1 + pha + + ldx bank_save ; .X holds the destination bank # + sty tmp_done ; .Y holds bytecnt - save here for comparison during loop + ldy #0 ; .Y is now the loop counter. Start at 0 and count up. + + ; set up the tmp_swapindex + lda #0 + sec + sbc fat32_ptr + sta tmp_swapindex + +@loop: + ; Copy one byte from banked RAM to buffer + stx ram_bank + lda (fat32_ptr),y + stz ram_bank + sta (fat32_bufptr),y + iny + cpy tmp_swapindex + bne @nowrap + lda fat32_ptr+1 + cmp #$bf ; only wrap when leaving page $BF + bne @nowrap + inx + lda #$9f + sta fat32_ptr+1 +@nowrap: + cpy tmp_done + bne @loop + ; restore temporary zero page + stx bank_save + pla + sta krn_ptr1+1 + pla + sta krn_ptr1 + jmp @4c + ;----------------------------------------------------------------------------- ; fat32_get_free_space diff --git a/inc/kernal.inc b/inc/kernal.inc index 965f0d9d..816ea14a 100644 --- a/inc/kernal.inc +++ b/inc/kernal.inc @@ -138,3 +138,4 @@ kbdbuf_get_modifiers = $fec0 kbdbuf_put = $fec3 bsave = $feba +mciout = $feb1 diff --git a/kernal/cbm/channel/channel.s b/kernal/cbm/channel/channel.s index f6567ede..14c55967 100644 --- a/kernal/cbm/channel/channel.s +++ b/kernal/cbm/channel/channel.s @@ -32,6 +32,7 @@ stop = $ffe1 acptr = $ffa5 macptr= $ff44 ciout = $ffa8 +mciout = $feb1 listn = $ffb1 secnd = $ff93 talk = $ffb4 diff --git a/kernal/cbm/channel/save.s b/kernal/cbm/channel/save.s index 2bcc3333..51aaae84 100644 --- a/kernal/cbm/channel/save.s +++ b/kernal/cbm/channel/save.s @@ -53,11 +53,36 @@ sv25 jsr openi ldy #0 jsr rd300 lda verck - bne sv30 ; check for headerless + bne sv26 ; check for headerless lda sal jsr ciout lda sah jsr ciout +sv26 jsr cmpste ; try mciout + bcs sv50 + cmp #$ff + lda #0 + bcc sv27 ; not last page + + sec ; last and potentially partial page + lda eal + sbc sal + clc +sv27 ldx sal + ldy sah + jsr mciout + bcs sv29 ; unsupported + txa + adc sal + sta sal + tya + adc sah + sta sah + jsr stop + beq break + bra sv26 + +sv29 ldy #0 sv30 jsr cmpste ;compare start to end bcs sv50 ;have reached end lda (sal),y diff --git a/kernal/ieee_switch.s b/kernal/ieee_switch.s index e32b55c5..9708e63c 100644 --- a/kernal/ieee_switch.s +++ b/kernal/ieee_switch.s @@ -37,6 +37,7 @@ .export listn .export talk .export macptr +.export mciout .export led_update @@ -166,6 +167,15 @@ macptr: .byte BANK_CBDOS rts +mciout: + bit cbdos_flags + bmi :+ + sec ; error: unsupported + rts +: jsr jsrfar + .word $c000 + 3 * 18 + .byte BANK_CBDOS + rts ; Called by SECOND: If it's a CLOSE command, upload the curent time. upload_time: diff --git a/kernal/vectors.s b/kernal/vectors.s index ed127543..2260f0d6 100644 --- a/kernal/vectors.s +++ b/kernal/vectors.s @@ -5,7 +5,7 @@ .feature labels_without_colons -.import plot, scrorg, iclall, igetin, istop, savesp, loadsp, ibsout, ibasin, iclrch, ickout, ichkin, iclose, iopen, setnam, setlfs, readst, talk, listn, unlsn, untlk, ciout, acptr, settmo, kbd_scan, tksa, secnd, setmsg, ramtas, ioinit, cint, cmpare, stash, indfet, jsrfar, screen_set_charset, screen_mode, lkupsa, lkupla, close_all, enter_basic, macptr +.import plot, scrorg, iclall, igetin, istop, savesp, loadsp, ibsout, ibasin, iclrch, ickout, ichkin, iclose, iopen, setnam, setlfs, readst, talk, listn, unlsn, untlk, ciout, acptr, settmo, kbd_scan, tksa, secnd, setmsg, ramtas, ioinit, cint, cmpare, stash, indfet, jsrfar, screen_set_charset, screen_mode, lkupsa, lkupla, close_all, enter_basic, macptr, mciout .import FB_move_pixels, FB_filter_pixels, FB_fill_pixels, FB_set_8_pixels_opaque, FB_set_8_pixels, FB_set_pixels, FB_set_pixel, FB_get_pixels, FB_get_pixel, FB_cursor_next_line, FB_cursor_position, FB_set_palette, FB_get_info, FB_init .import memory_decompress, memory_crc, memory_copy, memory_fill .import monitor @@ -42,7 +42,7 @@ .byte 0,0,0 ; $FEA8 .byte 0,0,0 ; $FEAB .byte 0,0,0 ; $FEAE - .byte 0,0,0 ; $FEB1 + jmp mciout ; $FEB1 .byte 0,0,0 ; $FEB4 .byte 0,0,0 ; $FEB7 jmp savehl ; $FEBA diff --git a/kernsup/kernsup.inc b/kernsup/kernsup.inc index b8945ccb..86470927 100644 --- a/kernsup/kernsup.inc +++ b/kernsup/kernsup.inc @@ -1,7 +1,7 @@ .byte 0,0,0 ; $FEA8 .byte 0,0,0 ; $FEAB .byte 0,0,0 ; $FEAE -.byte 0,0,0 ; $FEB1 +bridge mciout ; $FEB1 .byte 0,0,0 ; $FEB4 .byte 0,0,0 ; $FEB7 bridge bsave ; $FEBA