;license:MIT ;(c) 2018 by 4am & qkumba ; ; ProRWTS2 glue functions ; ; Public functions ; - LoadFile ; - LoadDHRFile ; - SaveSmallFile ; ; A general note about paths: ; ; LoadFile, LoadDHRFile, and SaveSmallFile support files in subdirectories. ; Paths are delimited by '/' like ProDOS. HOWEVER, you should never include a ; disk volume name. At program startup, we get the current directory and save ; it; that is the PROGRAM ROOT DIRECTORY. The first '/' always points to the ; PROGRAM ROOT DIRECTORY. All pathnames are relative to the PROGRAM ROOT ; DIRECTORY. ; ; The PROGRAM ROOT DIRECTORY is not guaranteed to be the root directory of the ; underlying ProDOS disk (although it can be). These functions provide no ; access to any directory above the PROGRAM ROOT DIRECTORY, i.e. you can't use ; '..' to access the parent directory. ; ; Examples: ; '/PREFS.CONF' points to a file named 'PREFS.CONF' in the PROGRAM ROOT ; DIRECTORY. ; ; '/FX/RIPPLE' points to a file named 'RIPPLE' in a directory named 'FX' in the ; PROGRAM ROOT DIRECTORY. gRootDirectory !word $FDFD gPrefix !word $FDFD ;------------------------------------------------------------------------------ ; LoadFile ; load a file into memory all at once, using ProRWTS2 ; supports paths, see note ; uses file's load address ; ; in: stack contains 2 bytes of parameters: ; +1 address of filename ; out: all flags clobbered ; all registers clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ LoadFile +PARAMS_ON_STACK 2 +LDPARAM 1 +STAY namlo ; set filename +STAY gPrefix ; remember path jsr traverse ; go to subdirectory, set up filename for read lda #cmdread ; read (instead of write) sta reqcmd lda #0 ; 0 = read into main memory sta auxreq lda #$FF ; read entire file (ProRWTS2 will figure out exact size) sta sizehi jmp hddopendir ; exit via ProRWTS2 ;------------------------------------------------------------------------------ ; LoadDHRFile ; load .A2FC file (uncompressed double hi-res graphics) into memory ; all at once, using ProRWTS2 ; first $2000 bytes of file are loaded into auxiliary memory $2000..$3FFF ; second $2000 bytes of file are loaded into main memory $2000..$3FFF ; supports paths, see note ; ; in: stack contains 2 bytes of parameters: ; +1 address of filename ; out: all flags clobbered ; all registers clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ LoadDHRFile +PARAMS_ON_STACK 2 +LDPARAM 1 +STAY namlo ; set filename jsr traverse ; go to subdirectory, set up filename for read lda #$00 ; read first $2000 bytes sta sizelo lda #$20 sta sizehi lda #1 ; 1 = read into aux memory sta auxreq lda #cmdread ; read (instead of write) sta reqcmd jsr hddopendir ; call ProRWTS2 lda #$20 ; read next $2000 bytes sta sizehi dec auxreq ; 0 = read into main memory clc ; not a subdirectory jmp hddrdwrpart ; call ProRWTS2 ;------------------------------------------------------------------------------ ; SaveSmallFile ; Save a file into memory all at once, using ProRWTS2. ; /!\ Only first block (512 bytes) is written. Keep those files small. /!\ ; /!\ All 512 bytes are written to disk. Clear buffer before calling. /!\ ; supports paths, see note ; ; in: stack contains 4 bytes of parameters: ; +1 address of filename ; +3 address of data buffer ; out: all flags clobbered ; all registers clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ SaveSmallFile +PARAMS_ON_STACK 4 +LDPARAM 1 +STAY namlo ; set filename for ProRWTS2 +STAY gPrefix ; remember path +LDPARAM 3 +STAY ldrlo ; set data buffer address for ProRWTS2 jsr traverse ; go to subdirectory, set up filename for read lda #cmdwrite ; write (instead of read) sta reqcmd lda #0 ; 0 = data buffer is in main memory (instead of auxmem) sta auxreq jmp hddopendir ; exit via ProRWTS2 ;------------------------------------------------------------------------------ ; traverse [private] ; ; in: (namlo) points to length-prefixed pathname+filename ; out: all flags clobbered ; all registers clobbered ;------------------------------------------------------------------------------ traverse +LDAY gRootDirectory sta @myreadblock+1 sty @myreadblock+3 ; reset 'root' directory (saved at program start) ;search for '/' character in filename ldx #0 ldy #0 lda (namlo), y tay - inx dey bmi @go ; no '/', just do the read lda (namlo), y cmp #'/' bne - sty sizelo txa pha @myreadblock @myx80_parms ldx #2 lda #0 jsr hddreaddirsel lda #NAME_LENGTH sta bloklo lda #>(hdddirbuf - 1) sta blokhi ;there can be only one page crossed, so we can increment here @mynextent1 inc blokhi @mynextent ldy #0 lda (bloklo), y pha and #$0f tax -- iny lda (bloklo), y cmp (namlo), y beq @myfoundname ;match failed, move to next directory in this block, if possible - pla @myskiphdr clc lda bloklo adc #ENTRY_SIZE sta bloklo bcs @mynextent1 cmp #$ff ;4 + ($27 * $0d) bne @mynextent ;read next directory block when we reach the end of this block lda hdddirbuf + NEXT_BLOCK_LO ldx hdddirbuf + NEXT_BLOCK_HI bcs + @myfoundname dex bne -- ;parse path until last directory is seen iny lda (namlo), y cmp #'/' bne - pla and #$20 ;Volume Directory Header XOR subdirectory bne @myskiphdr tya eor #$ff adc sizelo sta sizelo clc tya adc namlo sta namlo ;cache block number of current directory ;as starting position for subsequent searches ldy #(KEY_POINTER + 1) lda (bloklo), y tax dey lda (bloklo), y sta (reloc + unrhddblocklo - unrelochdd) + 1 stx (reloc + unrhddblockhi - unrelochdd) + 1 + sta @myx80_parms + 1 stx @myx80_parms + 3 ++ lda sizelo bne @myreadblock tay pla sta (namlo), y @go rts promote !pseudopc $bf00 { lda $c08b clc bcc @do_enter ;$bf06 rts ;clock interface, must be RTS on real ProDOS if program uses $20x @do_enter lda $c08b jmp ProDOS_enter !text "q4!" ;$bf10 !word $c1d1, $c2d1, $c3d1, $c4d1, $c5d1, $c6d1, $c7d1 ProDOS_exit lda $c081 pla ;saved inside ProDOS_enter tay pla tax lda #0 rts ProDOS_fatal ;only for debugging, will be removed pha lda $c081 jsr $fe89 jsr $fe93 pla jsr $fdda jmp $ff59 ProDOS_prefix=$bfd0 ; !fill $2e } end_promote ;------------------------------------------------------------------------------ ; ProDOS_enter ; intercept certain ProDOS requests ; wrap them to ProRWTS2 file requests ; ; in: return address+1 is command and pointer to parameter block ; out: all flags clobbered ; A=0, X and Y preserved ; stack set to next instruction after parameters ; ; to do: preserve non-$4x zpage locations for titles that open files after start ;------------------------------------------------------------------------------ packet = $40 ;word buffer = $42 ;word ProDOS_enter pla sta @fetchaddr+1 pla sta @fetchaddr+2 jsr @fetchbyte sta @request+1 jsr @fetchbyte sta packet jsr @fetchbyte sta packet+1 lda @fetchaddr+2 pha lda @fetchaddr+1 pha txa pha tya pha @request lda #$d1 cmp #$c4 beq @do_getattrib cmp #$c7 beq @do_prefix cmp #$c8 beq @do_open cmp #$ca beq @do_read cmp #$cb beq @do_write cmp #$cc beq @do_close cmp #$ce beq @do_seek ;;any others?? jmp ProDOS_fatal @do_getattrib jsr @imp_getattrib jmp ProDOS_exit @do_prefix jsr @imp_prefix jmp ProDOS_exit @do_open jsr @imp_open jmp ProDOS_exit @do_read jsr @imp_read jmp ProDOS_exit @do_write jsr @imp_write jmp ProDOS_exit @do_close jsr @imp_close jmp ProDOS_exit @do_seek jsr @imp_seek jmp ProDOS_exit @imp_getattrib lda packet+1 pha lda packet pha ldx #namlo jsr @setbuffer1 lda #$60 sta attribpatch jsr hddopendir lda #$10 sta attribpatch pla sta packet pla sta packet+1 ldy #5 lda ldrlo2 sta (packet), y iny lda ldrlo2+1 sta (packet), y rts @imp_prefix ldx #buffer jsr @setbuffer1 ldy ProDOS_prefix @copy_prefix lda ProDOS_prefix, y sta (buffer), y dey bpl @copy_prefix rts @imp_open ldx #namlo jsr @setbuffer1 iny inc @handles+1 @handles ldx #0 iny lda (packet), y sta @handle-1, x tax jsr @patch_buffer iny lda #1 sta (packet), y lda #0 sta reqcmd sta sizehi sta sizelo jsr hddopendir ldx encbufpatch1+1 inx stx @block_index2+2 lda #0 beq @block_index2 ;always @imp_seek lda #cmdseek !byte $2c @imp_read lda #cmdread !byte $2c @imp_write lda #cmdwrite sta reqcmd jsr @set_rdwrbuff ldx encbufpatch1+1 inx stx @block_index1+2 stx @block_index2+2 @block_index1 lda $d1ff sta blkidx clc ;not a subdirectory jsr hddrdwrpart lda blkidx @block_index2 sta $d1ff rts @imp_close dec @handles+1 bne @close_ret lda #>hddencbuf @patch_buffer sta encbufpatch1+1 sta encbufpatch2+1 tax inx stx dirbufpatch1+1 inx stx dirbufpatch2+2 stx dirbufpatch3+2 stx dirbufpatch4+2 stx dirbufpatch6+1 stx dirbufpatch7+2 stx dirbufpatch9+2 stx dirbufpatch10+1 inx stx dirbufpatch5+2 stx dirbufpatch8+2 @close_ret rts @fetchbyte inc @fetchaddr+1 bne @fetchaddr lda @fetchaddr+2 @fetchaddr lda $d1d1 rts @set_rdwrbuff ldy #1 lda (packet), y tax lda @handle-1, x tax jsr @patch_buffer ldx #ldrlo iny jsr @setbuffer ldx #sizelo iny !byte $2c @setbuffer1 ldy #1 @setbuffer lda (packet), y sta $0,x iny lda (packet), y sta $1,x rts @handle !byte 0, 0 ;only up to two handles at a time