;license:MIT ;(c) 2018-9 by 4am & qkumba ; ; ProRWTS2 glue functions ; ; Public functions ; - LoadFile ; - LoadFileAt ; - LoadDHRFile ; - SaveSmallFile ; - CloseHandles ; - SaveScreenHoles ; ; A general note about paths: ; ; LoadFile, LoadFileAt, LoadDHRFile, and SaveSmallFile support subdirectories. ; Directories are delimited by '/' like ProDOS. At program startup, we get the ; current directory and save it; that is the PROGRAM ROOT DIRECTORY. All ; pathnames are relative to the PROGRAM ROOT DIRECTORY. There is no concept of ; setting or changing the 'current' directory. ; ; The PROGRAM ROOT DIRECTORY is not guaranteed to be the root directory of the ; underlying ProDOS disk (although it can be). But it doesn't matter, because ; these functions provide no access to any directory above the PROGRAM ROOT ; DIRECTORY. You can't use '..' to access the parent directory, and you can't ; start a pathname with '/' to access the root directory of the underlying ; ProDOS disk. ; ; 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 ;------------------------------------------------------------------------------ ; LoadFile ; Load a file into memory all at once, using ProRWTS2, at the load address ; specified by the file's ProDOS metadata. Hey, do you have a text file that ; doesn't have a load address? This routine will happily load it at $0000, and ; your program will likely crash as a result. So give it a load address as if ; it were a binary file. ; ; supports paths, see note ; ; in: gPathname contains filename ; out: all flags clobbered ; all registers clobbered ; gPathname clobbered ;------------------------------------------------------------------------------ LoadFile +LDADDR gPathname +STAY namlo ; set filename +READ_RAM2_WRITE_RAM2 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 sta sizelo sta sizehi ; 0 = query load address jsr hddopendir ; call ProRWTS2 lda ldrlo2 sta ldrlo lda ldrhi2 sta ldrhi dec sizehi ; read entire file (ProRWTS2 will figure out exact size) jsr hddopendir ; exit via ProRWTS2 (must re-open the file after query) +READ_RAM1_WRITE_RAM1 rts ;------------------------------------------------------------------------------ ; LoadFileAt ; Load a file into memory all at once, using ProRWTS2, at the load address ; specified by the passed parameter. ; ; supports paths, see note ; ; in: gPathname contains filename ; stack contains 2 bytes of parameters: ; +1 address to load file ; out: all flags clobbered ; all registers clobbered ; gPathname clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ LoadFileAt +PARAMS_ON_STACK 2 +LDPARAM 1 +STAY ldrlo ; set load address +LDADDR gPathname +STAY namlo ; set filename +READ_RAM2_WRITE_RAM2 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 jsr hddopendir ; exit via ProRWTS2 +READ_RAM1_WRITE_RAM1 rts ;------------------------------------------------------------------------------ ; 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: gPathname contains filename ; out: all flags clobbered ; all registers clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ LoadDHRFile +LDADDR gPathname +STAY namlo ; set filename +READ_RAM2_WRITE_RAM2 jsr traverse ; go to subdirectory, set up filename for read lda #$00 ; read first $2000 bytes sta sizelo sta ldrlo lda #$20 sta sizehi asl sta ldrhi 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 asl sta ldrhi dec auxreq ; 0 = read into main memory clc ; not a subdirectory jsr hddrdwrpart ; call ProRWTS2 +READ_RAM1_WRITE_RAM1 rts ;------------------------------------------------------------------------------ ; 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 2 bytes of parameters: ; +1 address of data buffer ; out: all flags clobbered ; all registers clobbered ; stack set to next instruction after parameters ;------------------------------------------------------------------------------ SaveSmallFile +PARAMS_ON_STACK 2 +LDPARAM 1 +STAY ldrlo ; set data buffer address for ProRWTS2 +LDADDR gPathname +STAY namlo ; set filename for ProRWTS2 +READ_RAM2_WRITE_RAM2 jsr traverse ; go to subdirectory, set up filename for read ;;if the write address is always a fixed value then we can discard the query lda #cmdread ; read (instead of write) sta reqcmd lda #0 ; 0 = read into main memory sta sizelo sta sizehi ; 0 = query load address jsr hddopendir ; call ProRWTS2 lda ldrlo2 sta ldrlo lda ldrhi2 sta ldrhi lda #cmdwrite ; write (instead of read) sta reqcmd sta sizelo ; non-zero jsr hddopendir ; exit via ProRWTS2 (must re-open the file after query) +READ_RAM1_WRITE_RAM1 rts ;------------------------------------------------------------------------------ ; traverse [private] ; ; in: (namlo) points to length-prefixed pathname+filename ; out: all flags clobbered ; all registers clobbered ;------------------------------------------------------------------------------ traverse +LDAY gRootDirectory sta (reloc + unrhddblocklo - unrelochdd) + 1 sty (reloc + unrhddblockhi - unrelochdd) + 1 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 [private] ; ; tiny ProDOS-style interface for ProRWTS ; in: whatever ProDOS expects for the supported functions ; out: carry clear, A=0 ; X, Y, and other flags clobbered ;------------------------------------------------------------------------------ promote !pseudopc $bf00 { php sei lda $c012 !byte $24 !if * != $bf06 { !error "$BF06 misplaced (",*,")" } rts ;clock interface, must be RTS on real ProDOS if program uses $20x asl lda $c011 bit $c083 jmp ProDOS_LC !text "4Q" !if * != $bf13 { !error "$BF13 misplaced (",*,")" } !byte $c1 !word $c2d1, $c3d1, $c4d1, $c5d1, $c6d1, $c7d1 ProDOS_LC bit $c083 jmp ProDOS_enter ProDOS_exit sta $c082, x ProDOS_savedX ldx #$d1 ProDOS_savedY ldy #$d1 plp clc !byte $24 ProDOS_unit !if * != $bf30 { !error "$BF30 misplaced (",*,")" } !byte $d1 lda #0 rts ProDOS_fatal ;only for debugging, will be removed bit $c081 pha jsr $fe89 jsr $fe93 pla jsr $fdda jmp $ff65 *=$bf58 !fill $18 ProDOS_prefix=$bfd0 ; !fill $2e } end_promote ;------------------------------------------------------------------------------ ; SaveOrRestoreScreenHoles ; preserve screen hole contents across demo execution ; to avoid crashing later on disk access ; ; in: nothing ; out: all flags clobbered ; all registers clobbered ;------------------------------------------------------------------------------ SaveOrRestoreScreenHoles lda #4 sta namhi ldx #0 stx namlo sta bloklo -- ldy #$78 - lda (namlo),y pha lda holey_stuff,x holepatch ;sta->lda lda (namlo),y pla sta holey_stuff,x inx tya eor #$80 tay bmi - iny bpl - inc namhi dec bloklo bne -- rts holey_stuff !fill 64