diff --git a/applecorn.po b/applecorn.po index d790418..106a63b 100644 Binary files a/applecorn.po and b/applecorn.po differ diff --git a/applecorn.s b/applecorn.s index aaa2d28..1b72b4b 100644 --- a/applecorn.s +++ b/applecorn.s @@ -40,18 +40,6 @@ A2IRQV EQU $3FE MLI EQU $BF00 * IO Buffer for reading file (1024 bytes) -*IOBUF0 EQU $4000 ; For loading/saving, OSFILE, *. -*IOBUF1 EQU $4400 ; Four open files for langs -*IOBUF2 EQU $4800 -*IOBUF3 EQU $4C00 -*IOBUF4 EQU $5000 - -*IOBUF0 EQU $5000 ; For loading/saving, OSFILE, *. -*IOBUF1 EQU $5400 ; Four open files for langs -*IOBUF2 EQU $5800 -*IOBUF3 EQU $5C00 -*IOBUF4 EQU $6000 - IOBUF0 EQU $0C00 ; For loading/saving, OSFILE, *. IOBUF1 EQU $1000 ; Four open files for langs IOBUF2 EQU $1400 @@ -59,11 +47,8 @@ IOBUF3 EQU $1800 IOBUF4 EQU $1C00 * 512 byte buffer sufficient for one disk block -*BLKBUF EQU $5200 -*BLKBUFEND EQU $5400 - -BLKBUF EQU $6200 ; Is this ever used at same time -BLKBUFEND EQU $6400 ; as IOBUF0? +BLKBUF EQU $5000 ; Can't use $400 as ProDOS uses +BLKBUFEND EQU $5200 ; 'hidden' bytes within screen * Address in aux memory where ROM will be loaded AUXADDR EQU $8000 @@ -190,5 +175,6 @@ MAINZP MAC PUT AUXMEM.CHARIO PUT AUXMEM.MISC +* Automatically save the object file: SAV APPLECORN diff --git a/auxmem.hostfs.s b/auxmem.hostfs.s index bad7c53..bba53b9 100644 --- a/auxmem.hostfs.s +++ b/auxmem.hostfs.s @@ -5,6 +5,8 @@ * 29-Aug-2021 Generalised CHKERROR routone, checks for and * translates ProDOS errors into Acorn errors * Set &E0=&FF for testing to report ProDOS errors +* 30-Aug-2021 FSC commands moved to here +* Command line set by *RUN, and read by OSARGS FSXREG EQU $B0 @@ -13,6 +15,7 @@ FSAREG EQU $B2 FSCTRL EQU FSXREG FSPTR1 EQU $B4 FSPTR2 EQU $B6 +FSCMDLINE EQU $CE * OSFIND - open/close a file for byte access @@ -100,31 +103,54 @@ OSBGETRET * OSARGS - adjust file arguments * On entry, A=action +* Y<>0 A=FF Flush channel Y +* A=00 Read PTR#Y +* A=01 Write PTR#Y +* A=02 Read EXT#Y +* A=03 Write EXT#Y +* Y=0 A=FF Flush all channels +* A=00 Return filing system number in A +* A=01 Read command line address * X=>4 byte ZP control block * Y=file handle -ARGSHND PHA - PHX +* On exit, A=0 - implemented (except ARGS 0,0) +* A - preserved=unimplemented +* X,Y - preserved +* control block updated for 'read' calls +* control block preserved otherwise +* +ARGSHND PHX PHY + PHA CPY #$00 BNE :HASFILE CMP #$00 ; Y=0,A=0 => current file sys BNE :S1 - PLY - PLX PLA LDA #105 ; 105=AppleFS filing system + PLY + PLX RTS + :S1 CMP #$01 ; Y=0,A=1 => addr of CLI BNE :S2 -* TODO: Implement this for *RUN and *command - JSR BEEP - BRA :IEXIT + LDA FSCMDLINE+0 + STA $00,X + LDA FSCMDLINE+1 + STA $01,X + LDA #$FF + STA $02,X + STA $03,X + JMP OSARGSDONE ; Implemented + :S2 CMP #$FF ; Y=0,A=FF => flush all files BNE :IEXIT >>> WRTMAIN STZ MOSFILE ; Zero means flush all >>> WRTAUX - BRA :IFLUSH + JMP :FLUSH +:IEXIT JMP :EXIT ; Exit preserved + :HASFILE >>> WRTMAIN STY MOSFILE ; File ref num STX MOSFILE+1 ; Pointer to ZP control block @@ -135,8 +161,7 @@ ARGSHND PHA STZ MOSFILE+2 ; 0 means get pos >>> WRTAUX >>> XF2MAIN,TELL -:IEXIT BRA :IEXIT2 -:IFLUSH BRA :FLUSH + :S3 CMP #$01 ; Y!=0,A=1 => write seq ptr BNE :S4 >>> WRTMAIN @@ -148,25 +173,28 @@ ARGSHND PHA STA MOSFILE+4 >>> WRTAUX >>> XF2MAIN,SEEK -:IEXIT2 BRA :EXIT + :S4 CMP #$02 ; Y!=0,A=2 => read file len BNE :S5 >>> WRTMAIN STA MOSFILE+2 ; Non-zero means get len >>> WRTAUX >>> XF2MAIN,TELL + :S5 CMP #$FF ; Y!=0,A=FF => flush file BNE :EXIT :FLUSH >>> XF2MAIN,FLUSH -:EXIT PLY - PLX - PLA - RTS -OSARGSRET - >>> ENTAUX + +:EXIT PLA ; Unimplemented + PLY + PLX + RTS + +OSARGSRET >>> ENTAUX +OSARGSDONE PLA + LDA #0 ; Implemented PLY PLX - PLA RTS @@ -245,7 +273,7 @@ FILEHND PHX BEQ :LOAD ; A=FF -> LOAD CMP #$06 BEQ :DELETE ; A=06 -> DELETE -* BCC :INFO ; A=01-05 -> INFO + BCC :JMPINFO ; A=01-05 -> INFO CMP #$08 BEQ :MKDIR ; A=08 -> MKDIR * LDA #>> XF2MAIN,INFOFILE +:JMPINFO JMP :INFO :SAVE >>> XF2MAIN,SAVEFILE :LOAD >>> XF2MAIN,LOADFILE :DELETE >>> XF2MAIN,DELFILE :MKDIR >>> XF2MAIN,MAKEDIR +:INFO >>> XF2MAIN,INFOFILE * On return here, A<$20 return to caller, A>$1F ProDOS error OSFILERET @@ -387,6 +415,37 @@ OSFSCM ASC 'OSFSC.' DB $00 +* FSC Command Table +******************* +* These are commands specific to the filing system that can't be +* called via OSFILE, OSFSC, etc. +* +FSCCOMMAND ASC 'CHDIR' + DB $C0 + DW FSCCHDIR-1 ; Change directory, XY=>params + ASC 'CD' + DB $C0 + DW FSCCHDIR-1 ; Change directory, XY=>params + ASC 'DIR' + DB $C0 + DW FSCCHDIR-1 ; Change directory, XY=>params +* TO DO, CHDIR should be $80 for LPTR=>params + ASC 'DRIVE' + DB $80 + DW FSCDRIVE-1 ; Select drive, LPTR=>params + ASC 'FREE' + DB $80 + DW FSCFREE-1 ; FREE (, LPTR=>params + ASC 'ACCESS' + DB $80 + DW FSCACCESS-1 ; ACCESS params + ASC 'TITLE' + DB $80 + DW FSCTITLE-1 ; TITLE () , LPTR=>params +* + DB $FF ; Terminator + + * OSFSC - miscellanous file system calls ***************************************** * On entry, A=action, XY=>command line @@ -397,33 +456,35 @@ OSFSCM ASC 'OSFSC.' * * TO DO: use jump table FSCHND - CMP #$40 - BEQ FSCCHDIR - CMP #$41 - BEQ FSCDRIVE - CMP #$42 - BEQ FSCFREE - CMP #$43 - BEQ FSCACCESS - CMP #$42 - BEQ FSCTITLE +* CMP #$40 +* BEQ FSCCHDIR +* CMP #$41 +* BEQ FSCDRIVE +* CMP #$42 +* BEQ FSCFREE +* CMP #$43 +* BEQ FSCACCESS +* CMP #$42 +* BEQ FSCTITLE - CMP #$0C - BEQ FSCREN ; A=12 - *RENAME CMP #$00 BEQ FSOPT ; A=0 - *OPT CMP #$01 BEQ CHKEOF ; A=1 - Read EOF CMP #$02 BEQ FSCRUN ; A=2 - */filename + CMP #$03 + BEQ FSC03 ; A=3 - *command CMP #$04 BEQ FSCRUN ; A=4 - *RUN CMP #$05 - BEQ FSCCAT ; A=5 - *CAT + BEQ JMPCAT ; A=5 - *CAT CMP #$09 - BEQ FSCCAT ; A=9 - *EX + BEQ JMPCAT ; A=9 - *EX CMP #$0A - BEQ FSCCAT ; A=10 - *INFO + BEQ JMPCAT ; A=10 - *INFO + CMP #$0C + BEQ FSCREN ; A=12 - *RENAME FSCDRIVE FSCFREE FSCACCESS @@ -435,8 +496,29 @@ FSCUKN PHA PLA FSCNULL RTS +JMPCAT JMP FSCCAT + +FSC03 JSR XYtoLPTR + LDX #<FSCCOMMAND + LDY #>FSCCOMMAND + JSR CLILOOKUP + BEQ FSCNULL + JSR LPTRtoXY +* FSCRUN STX OSFILECB ; Pointer to filename STY OSFILECB+1 + JSR XYtoLPTR +FSCRUNLP LDA (OSLPTR),Y ; Look for command line + INY + CMP #'!' + BCS FSCRUNLP + DEY + JSR SKIPSPC + JSR LPTRtoXY + STX FSCMDLINE+0 ; Set CMDLINE=>command line + STY FSCMDLINE+1 ; Collected by OSARGS 1,0 +* +* *BUG* OSFILE &FF should give error if trying to load a directory! LDA #$FF ; OSFILE load flag STA OSFILECB+6 ; Use file's address LDX #<OSFILECB ; Pointer to control block @@ -445,12 +527,12 @@ FSCRUN STX OSFILECB ; Pointer to filename JSR :CALL LDA #$00 ; A=0 on return RTS -:CALL JMP (OSFILECB+6) ; Jump to EXEC addr - RTS +:CALL LDA #$01 ; A=1 - entering code + SEC ; Not from RESET + JMP (OSFILECB+6) ; Jump to EXEC addr FSCREN JSR XYtoLPTR ; Pointer to command line - JSR RENAME - RTS + JMP RENAME FSCCHDIR STX ZP1+0 STY ZP1+1 @@ -811,14 +893,15 @@ MKERROR4 * $55 - Volume Control Block table full. * $56 - Bad buffer address. * $57 - Duplicate volume. -* ($58) $27 - I/O error -* ($59) $28 - No device connected Disk not present +* ($58) $27 - I/O error (disk not formatted) +* ($59) $28 - No device connected (drive not present) Disk not present * $5A ($29) - Bit map disk address is impossible. Sector not found * $5B $2A - * ($5C) $2B - Disk write protected. Disk write protected * $5D ($2C) - (EOF during load or save) Data lost * $5E ($2D) - (Couldn't open to save) Can't save * ($5F) $2E - Disk switched Disk changed +* $2F - Device is offline (drive empty) * * AcornOS ProDOS diff --git a/auxmem.oscli.s b/auxmem.oscli.s index 99193e2..d38f168 100644 --- a/auxmem.oscli.s +++ b/auxmem.oscli.s @@ -43,19 +43,20 @@ CMDTABLE ASC 'CAT' ; Must be first command so matches '*.' ASC 'CDIR' DB $88 DW STARFILE-1 ; CDIR -> OSFILE 08, CBLK=>filename -* other filing commands - ASC 'CHDIR' - DB $C0 - DW STARFSC-1 ; Should be a FSC 3 call, XY=>params - ASC 'CD' - DB $C0 - DW STARFSC-1 ; Should be a FSC 3 call, XY=>params - ASC 'DIR' - DB $C0 - DW STARFSC-1 ; Should be a FSC 3 call, XY=>params - ASC 'DRIVE' - DB $C1 - DW STARFSC-1 ; Should be a FSC 3 call, XY=>params +* filing-system-specific commands +* Moved to HostFS +* ASC 'CHDIR' +* DB $C0 +* DW STARFSC-1 ; Should be a FSC 3 call, XY=>params +* ASC 'CD' +* DB $C0 +* DW STARFSC-1 ; Should be a FSC 3 call, XY=>params +* ASC 'DIR' +* DB $C0 +* DW STARFSC-1 ; Should be a FSC 3 call, XY=>params +* ASC 'DRIVE' +* DB $C1 +* DW STARFSC-1 ; Should be a FSC 3 call, XY=>params * FREE (<drive>) * ACCESS <file> <access> * TITLE (<drive>) <title> @@ -83,7 +84,79 @@ CMDTABLE ASC 'CAT' ; Must be first command so matches '*.' * TYPE <file> * BUILD <file> * terminator - DB $00 + DB $FF + + +* Command table lookup +* On entry, (OSLPTR)=>command string +* XY=>command table +* On exit, A=0 done, command called +* A<>0 no match +* +* Search command table +CLILOOKUP STX OSTEXT+0 ; Start of command table + STY OSTEXT+1 + LDX #0 ; (ZP,X)=>command table +CLILP4 LDY #0 ; Start of command line +CLILP5 LDA (OSTEXT,X) + BMI CLIMATCH ; End of table string + EOR (OSLPTR),Y + AND #$DF ; Force upper case match + BNE CLINOMATCH + JSR CLISTEP ; Step to next table char + INY ; Step to next command char + BNE CLILP5 ; Loop to check + +CLINOMATCH LDA (OSLPTR),Y + CMP #'.' ; Abbreviation? + BEQ CLIDOT +CLINEXT JSR CLISTEP ; No match, step to next entry + BPL CLINEXT +CLINEXT2 JSR CLISTEP ; Step past byte, address + JSR CLISTEP + JSR CLISTEP + BPL CLILP4 ; Loop to check next + RTS ; Exit, A>$7F + +CLIDOT LDA (OSTEXT,X) + BMI CLINEXT2 ; Dot after full word, no match +CLIDOT2 JSR CLISTEP ; Step to command address + BPL CLIDOT2 + INY ; Step past dot + BNE CLIMATCH2 ; Jump to this command + +CLIMATCH LDA (OSLPTR),Y + CMP #'.' + BEQ CLINEXT ; Longer abbreviation, eg 'CAT.' + CMP #'A' + BCS CLINEXT ; More letters, eg 'HELPER' +CLIMATCH2 JSR CLIMATCH3 ; Call the routine + LDA #0 + RTS ; Return A=0 to claim + +CLIMATCH3 JSR SKIPSPC ; (OSLPTR),Y=>parameters + LDA (OSTEXT,X) ; Command byte + PHA + JSR CLISTEP ; Address low byte + STA OSTEMP + JSR CLISTEP ; Address high byte + PLX ; Get command byte + PHA ; Push address high + LDA OSTEMP + PHA ; Push address low + TXA ; Command byte + PHA + ASL A ; Drop bit 7 + BEQ CLICALL ; If $80 don't convert LPTR + JSR LPTRtoXY ; XY=>parameters +CLICALL PLA ; A=command parameter +CLIDONE RTS ; Call command routine + +CLISTEP INC OSTEXT+0,X ; Point to next table byte + BNE CLISTEP2 + INC OSTEXT+1,X +CLISTEP2 LDA (OSTEXT,X) ; Get next byte + RTS * OSCLI HANDLER @@ -113,56 +186,11 @@ CLILP2 LDA (OSLPTR),Y DEY JSR LPTRtoXY ; Add Y to LPTR JSR XYtoLPTR ; LPTR=>start of actual command -* -* Search command table - LDX #0 ; Start of command table -CLILP4 LDY #0 ; Start of command line -CLILP5 LDA CMDTABLE,X - BEQ CLIUNKNOWN ; End of command table - BMI CLIMATCH ; End of table string - EOR (OSLPTR),Y - AND #$DF ; Force upper case match - BNE CLINOMATCH - INX ; Step to next table char - INY ; Step to next command char - BNE CLILP5 ; Loop to check - -CLINOMATCH LDA (OSLPTR),Y - CMP #'.' ; Abbreviation? - BEQ CLIDOT -CLINEXT INX ; No match, step to next entry - LDA CMDTABLE,X - BPL CLINEXT -CLINEXT2 INX ; Step past byte, address - INX - INX - BNE CLILP4 ; Loop to check next - -CLIDOT LDA CMDTABLE,X - BMI CLINEXT2 ; Dot after full word, no match -CLIDOT2 INX ; Step to command address - LDA CMDTABLE,X - BPL CLIDOT2 - INY ; Step past dot - BNE CLIMATCH2 ; Jump to this command - -CLIMATCH LDA (OSLPTR),Y - CMP #'.' - BEQ CLINEXT ; Longer abbreviation, eg 'CAT.' - CMP #'A' - BCS CLINEXT ; More letters, eg 'HELPER' -CLIMATCH2 JSR SKIPSPC ; (OSLPTR),Y=>parameters - LDA CMDTABLE+2,X ; Push destination address - PHA - LDA CMDTABLE+1,X - PHA - LDA CMDTABLE+0,X ; A=command parameter - PHA - ASL A ; Drop bit 7 - BEQ CLICALL ; If $80 don't convert LPTR - JSR LPTRtoXY ; XY=>parameters -CLICALL PLA ; A=command parameter -CLIDONE RTS + LDX #<CMDTABLE ; XY=>command table + LDY #>CMDTABLE + JSR CLILOOKUP ; Look for command + BNE CLIUNKNOWN ; No match + RTS CLISLASH JSR SKIPSPC BEQ CLIDONE ; */<cr> @@ -347,7 +375,7 @@ STARHELP1 LDX #0 JSR OSWRCH STARHELPLP1 LDY #10 LDA CMDTABLE,X - BEQ STARHELP4 + BMI STARHELP4 STARHELPLP2 LDA CMDTABLE,X BMI STARHELP3 JSR OSWRCH diff --git a/import b/import new file mode 100755 index 0000000..2cc6c9c --- /dev/null +++ b/import @@ -0,0 +1,14 @@ +#!/bin/bash + +# For importing JGH's files into Github + +for i in *.s; do + fromdos $i + sed -i s/^\;/\*/ $i + cadius outdentfile $i + cadius sethighbit $i + mv $i $i#040000 + cadius deletefile applecorn.po /APPLECORN/$i + cadius addfile applecorn.po /APPLECORN $i#040000 +done + diff --git a/loader.s b/loader.s index f686b55..a73687d 100644 --- a/loader.s +++ b/loader.s @@ -6,8 +6,9 @@ * Loads Acorn ROM file (16KB) from disk and writes it * to aux memory starting at $08000. Copies Applecorn MOS * to aux memory starting at AUXMOS1 and jumps to it. -* (Note that the MOS code will relocate itself to $D000.) +* (Note that the MOS code will copy itself to $D000.) START JSR ROMMENU + STZ :BLOCKS LDX #$00 :S1 JSR CROUT diff --git a/mainmem.s b/mainmem.s index bdbefd6..ad48bc1 100644 --- a/mainmem.s +++ b/mainmem.s @@ -9,9 +9,33 @@ * 27-Aug-2021 Delete and MkDir return ProDOS result to caller * 29-Aug-2021 All calls (seem to) return ProDOS result to caller * Set ?&E0=255 for testing to report ProDOS result +* 30-Aug-2021 INFOFILE semi-implemented, UPDFB returns moddate * Lots of tidying up possible once confirmed code working +* *BUG* LOAD loads full 512 bytes from last sector even when < 512 +* ProDOS string buffers +RTCBUF EQU $0200 ; Use by RTC calls, 40 bytes +* ; $0228-$023D +DRVBUF1 EQU $023E +DRVBUF2 EQU $023F ; Prefix on current drive, len+64 +CMDPATH EQU $0280 ; Path used to start Applecorn + +* Filename string buffers +MOSFILE1 EQU $0300 ; length + 64 bytes +MOSFILE2 EQU $0341 ; length + 64 bytes +MOSFILE EQU MOSFILE1 +* $0382 ; $3C bytes here +* +FILEBLK EQU $03BE +FBPTR EQU FILEBLK+0 ; Pointer to name (in aux) +FBLOAD EQU FILEBLK+2 ; Load address +FBEXEC EQU FILEBLK+6 ; Exec address +FBSIZE EQU FILEBLK+10 ; Size +FBSTRT EQU FILEBLK+10 ; Start address for SAVE +FBATTR EQU FILEBLK+14 ; Attributes +FBEND EQU FILEBLK+14 ; End address for SAVE + * ProDOS MLI command numbers QUITCMD EQU $65 GTIMECMD EQU $82 @@ -49,20 +73,20 @@ SETPRFX LDA #GPFXCMD :L1 JSR MLI :OPC7 DB $00 DW GSPFXPL - LDX $0300 + LDX DRVBUF1 ; was $0300 BNE RTSINST LDA $BF30 STA ONLNPL+1 ; Device number JSR MLI DB ONLNCMD DW ONLNPL - LDA $0301 + LDA DRVBUF2 ; was $0301 AND #$0F TAX INX - STX $0300 + STX DRVBUF1 ; was $0300 LDA #$2F - STA $0301 + STA DRVBUF2 ; was $0301 DEC :OPC7 BNE :L1 RTSINST RTS @@ -88,16 +112,16 @@ DISCONN LDA $BF98 BPL :L1 BMI :S1 :S3 LDA $BF32,Y - STA $0302 + STA DRVBUF2+1 ; was $0302 :L2 LDA $BF33,Y STA $BF32,Y BEQ :S4 INY BNE :L2 :S4 LDA $BF26 - STA $0300 + STA DRVBUF1 ; was $0300 LDA $BF27 - STA $0301 + STA DRVBUF2 ; was $0301 LDA $BF10 STA $BF26 LDA $BF11 @@ -147,11 +171,24 @@ COPYAUXBLK CLI RTS +* TO DO: All OSFILE calls combined and dispatch in here +* All start with PREPATH, UPDFB, COPYFB then branch +* to relevent routine. + + +INFOFILE >>> ENTMAIN +* TO DO: call PREPATH to check for drive, up, etc + JSR UPDFB ; Update FILEBLK + JSR COPYFB ; Copy back to aux mem + >>> XF2AUX,OSFILERET + + * ProDOS file handling to delete a file * Called by AppleMOS OSFILE * Return A=0 no object, A=1 file deleted, A=2 dir deleted * A>$1F ProDOS error DELFILE >>> ENTMAIN +* TO DO: call PREPATH to check for drive, up, etc JSR UPDFB ; Update FILEBLK JSR COPYFB ; Copy back to aux mem PHA ; Save object type @@ -190,23 +227,26 @@ DESTROY LDA #<MOSFILE ; Attempt to destroy file * Return A=02 on success (ie: 'directory') * A>$1F ProDOS error, translated by OSFILE handler MAKEDIR >>> ENTMAIN +* TO DO: call PREPATH to check for drive, up, etc JSR UPDFB ; Update FILEBLK JSR COPYFB ; Copy back to aux mem CMP #$02 BEQ :EXIT ; Dir already exists * Make into a subroutine + LDA #$0D ; 'Directory' + STA CREATEPL+7 ; ->Storage type + LDA #$0F ; 'Directory' + STA CREATEPL+4 ; ->File type +* subroutine.... LDA #<MOSFILE STA CREATEPL+1 LDA #>MOSFILE STA CREATEPL+2 LDA #$C3 ; 'Default access' STA CREATEPL+3 ; ->Access - LDA #$0F ; 'Directory' - STA CREATEPL+4 ; ->File type STZ CREATEPL+5 ; Aux type LSB STZ CREATEPL+6 ; Aux type MSB - LDA #$0D ; 'Directory' - STA CREATEPL+7 ; ->Storage type +* Don't we have to make a call to update BF90-BF93? LDA $BF90 ; Current date STA CREATEPL+8 LDA $BF91 @@ -216,6 +256,7 @@ MAKEDIR >>> ENTMAIN LDA $BF93 STA CREATEPL+11 JSR CRTFILE +* ... BCS :EXIT ; Failed, exit with ProDOS result JSR UPDFB ; Update FILEBLK JSR COPYFB ; Copy FILEBLK to aux mem @@ -245,10 +286,15 @@ DORENAME LDA #<MOSFILE OFILE >>> ENTMAIN PHA ; Preserve arg for later * TO DO: Mustn't write to a directory +* TO DO: call PREPATH to check for drive, up, etc CMP #$80 ; Write mode BNE :S0 JSR DESTROY * Make into a subroutine + LDA #$01 ; Storage type - file + STA CREATEPL+7 + LDA #$06 ; Filetype BIN + STA CREATEPL+4 LDA #<MOSFILE ; Attempt to create file STA CREATEPL+1 STA OPENPL+1 @@ -257,14 +303,10 @@ OFILE >>> ENTMAIN STA OPENPL+2 LDA #$C3 ; Access unlocked STA CREATEPL+3 - LDA #$06 ; Filetype BIN - STA CREATEPL+4 LDA #$00 ; Auxtype STA CREATEPL+5 LDA #$00 STA CREATEPL+6 - LDA #$01 ; Storage type - file - STA CREATEPL+7 LDA $BF90 ; Current date STA CREATEPL+8 LDA $BF91 @@ -274,7 +316,7 @@ OFILE >>> ENTMAIN LDA $BF93 STA CREATEPL+11 JSR CRTFILE - +* ... :S0 LDA #$00 ; Look for empty slot JSR FINDBUF STX BUFIDX @@ -474,12 +516,14 @@ TELL >>> ENTMAIN >>> MAINZP ; Alt ZP off, ROM back in BRA :EXIT + * ProDOS file handling for MOS OSFILE LOAD call * Invoked by AppleMOS OSFILE * Return A=01 if successful (meaning 'file') * A>$1F ProDOS error, translated by FILERET * TO DO: If object not a file, return $46 - File not found LOADFILE >>> ENTMAIN +* TO DO: call PREPATH to check for drive, up, etc STZ :BLOCKS LDA #<MOSFILE STA OPENPL+1 @@ -530,6 +574,8 @@ LOADFILE >>> ENTMAIN INC DEX BRA :L2 +* *BUG* This is copy all 512 bytes of last block instead of +* just the bytes used :S2 STA A4H SEC ; Main -> AUX JSR AUXMOVE @@ -574,6 +620,7 @@ COPYFB PHA * A>$1F ProDOS error translated by FILERET * TO DO: If dir exists, return $41 SAVEFILE >>> ENTMAIN +* TO DO: call PREPATH to check for drive, up, etc * TO DO: MUSTN'T OVERWITE A DIRECTORY LDA #<MOSFILE ; Attempt to destroy file STA DESTPL+1 @@ -584,6 +631,11 @@ SAVEFILE >>> ENTMAIN DW DESTPL STZ :BLOCKS * TO DO: Make this a subroutine + LDA #$01 ; Storage type - file + STA CREATEPL+7 + LDA #$06 ; Filetype BIN + STA CREATEPL+4 +* subroutine.... LDA #<MOSFILE STA CREATEPL+1 STA OPENPL+1 @@ -592,14 +644,10 @@ SAVEFILE >>> ENTMAIN STA OPENPL+2 LDA #$C3 ; Access unlocked STA CREATEPL+3 - LDA #$06 ; Filetype BIN - STA CREATEPL+4 LDA FBLOAD ; Auxtype = load address STA CREATEPL+5 LDA FBLOAD+1 STA CREATEPL+6 - LDA #$01 ; Storage type - file - STA CREATEPL+7 LDA $BF90 ; Current date STA CREATEPL+8 LDA $BF91 @@ -609,6 +657,7 @@ SAVEFILE >>> ENTMAIN LDA $BF93 STA CREATEPL+11 JSR CRTFILE +* ... BCS :FWD1 ; :CANTOPEN error JSR OPENFILE BCS :FWD1 ; :CANTOPEN error @@ -728,8 +777,10 @@ UPDFB LDA #<MOSFILE JSR MLI ; Call GET_FILE_INFO DB GINFOCMD DW GINFOPL - BCS :ERR - LDA GINFOPL+5 ; Aux type LSB + BCC :UPDFB1 + JMP CHKNOTFND + +:UPDFB1 LDA GINFOPL+5 ; Aux type LSB STA FBLOAD STA FBEXEC LDA GINFOPL+6 ; Aux type MSB @@ -739,6 +790,7 @@ UPDFB LDA #<MOSFILE STZ FBEXEC+2 STZ FBLOAD+3 STZ FBEXEC+3 +* LDA GINFOPL+3 ; Access byte CMP #$40 ; Locked? AND #$03 ; ------wr @@ -753,8 +805,37 @@ UPDFB LDA #<MOSFILE ORA #$08 ; --wrl--- :UPDFB2 ORA FBATTR+0 ; --wrl-wr STA FBATTR+0 - STZ FBATTR+1 ; TO DO: get mdate - STZ FBATTR+2 +* + LDA GINFOPL+11 ; yyyyyyym + PHA + ROR A ; ?yyyyyyy m + LDA GINFOPL+10 ; mmmddddd m + PHA + ROR A ; mmmmdddd + LSR A ; -mmmmddd + LSR A ; --mmmmdd + LSR A ; ---mmmmd + LSR A ; ----mmmm + STA FBATTR+2 + PLA ; mmmddddd + AND #31 ; ---ddddd + STA FBATTR+1 + PLA ; yyyyyyym + SEC + SBC #81*2 ; Offset from 1981 + BCS :UPDFB3 ; 1981-1999 -> 00-18 + ADC #100*2 ; 2000-2080 -> 19-99 +:UPDFB3 PHA ; yyyyyyym + AND #$E0 ; yyy----- + ORA FBATTR+1 ; yyyddddd + STA FBATTR+1 + PLA ; yyyyyyym + AND #$FE ; yyyyyyy0 + ASL A ; yyyyyy00 + ASL A ; yyyyy000 + ASL A ; yyyy0000 + ORA FBATTR+2 ; yyyymmmm + STA FBATTR+2 STZ FBATTR+3 JSR OPENFILE ; Open file @@ -777,9 +858,9 @@ UPDFB LDA #<MOSFILE LDA #$01 ; Prepare A=file LDX GINFOPL+7 CPX #$0D ; Is it a directory? - BNE :UPDFB3 + BNE :UPDFB5 LDA #$02 ; Return A=directory -:UPDFB3 RTS +:UPDFB5 RTS :ERR CHKNOTFND CMP #$44 ; Convert ProDOS 'not found' @@ -838,35 +919,7 @@ CATALOGRET * dir/file.ext filesystem, so '..' means parent dir (eg: '../SOMEDIR') * Also allows '^' as '^' is illegal character * Carry set on error, clear otherwise -* TO DO: drv: prefix, drv:/dir/file -PREPATH LDX MOSFILE ; Length - BEQ :EXIT ; If zero length - LDA MOSFILE+1 ; 1st char of filename - CMP #$3A ; Is it ':'? - BNE :NOTCLN ; Nope - CPX #$03 ; Len at least 3? - BCC :ERR ; Nope! - LDA MOSFILE+3 ; Drive - SEC - SBC #'1' - TAX - LDA MOSFILE+2 ; Slot - SEC - SBC #'0' - JSR DRV2PFX ; Slt/Drv->pfx in MOSFILE2 - JSR DEL1CHAR ; Delete ':' from MOSFILE - JSR DEL1CHAR ; Delete the two digits - JSR DEL1CHAR - LDA MOSFILE ; Is there more? - BEQ :APPEND ; Only ':sd' - CMP #$02 ; Len at least 2? - BCC :ERR ; Nope! - LDA MOSFILE+1 ; 1st char of filename - CMP #$2F ; '/' - BNE :ERR - JSR DEL1CHAR ; Delete '/' from MOSFILE - BRA :APPEND -:NOTCLN JSR GETPREF ; Current pfx -> MOSFILE2 +PREPATH JSR GETPREF ; Current pfx -> MOSFILE2 :REENTER LDA MOSFILE+1 ; First char of dirname CMP #'.' BEQ :UPDIR1 @@ -874,7 +927,7 @@ PREPATH LDX MOSFILE ; Length BEQ :CARET ; If '^' CMP #$2F ; '/' char - abs path BEQ :EXIT ; Nothing to do - BRA :APPEND + BRA :PARENT :UPDIR1 LDA MOSFILE+2 CMP #'.' ; '..' @@ -883,7 +936,7 @@ PREPATH LDX MOSFILE ; Length :CARET JSR DEL1CHAR ; Delete '^' from MOSFILE JSR PARENT ; Parent dir -> MOSFILE2 LDA MOSFILE ; Is there more? - BEQ :APPEND ; Only '^' + BEQ :PARENT ; Only '^' CMP #$02 ; Len at least two? BCC :ERR ; Nope! LDA MOSFILE+1 ; What is next char? @@ -891,7 +944,7 @@ PREPATH LDX MOSFILE ; Length BNE :ERR ; Nope! JSR DEL1CHAR ; Delete '/' from MOSFILE BRA :REENTER ; Go again! -:APPEND JSR APPMF2 ; Append MOSFILE->MOSFILE2 +:PARENT JSR APPMF2 ; Append MOSFILE->MOSFILE2 JSR COPYMF2 ; Copy back to MOSFILE :EXIT CLC RTS @@ -966,34 +1019,39 @@ PARENT LDX MOSFILE2 ; Length of string * Convert slot/drive to prefix * Expect slot number (1..7) in A, drive (0..1) in X -* Puts prefix (or empty string) in MOSFILE2 -DRV2PFX ASL - ASL - ASL - ASL - CPX #$00 - BEQ :S1 ; Drive 1 - ORA #$80 ; Drive 2 -:S1 STA ONLNPL+1 ; Device number +* Puts prefix (or empty string) in MOSFILE +DRV2PFX +* ASL +* ASL +* ASL +* ASL +* STX :TEMP ; Gets 0SSS000D +* ORA :TEMP ; Shouldn't this be DSSS00000 ? + + CLC ; Cy=0 A=00000sss + ROR A ; s 000000ss + ROR A ; s s000000s + ROR A ; s ss000000 + ROR A ; s sss00000 + CPX #1 ; d sss00000 + ROR A ; 0 dsss0000 + + STA ONLNPL+1 ; Device number JSR MLI ; Call ON_LINE DB ONLNCMD - DW ONLNPL ; Buffer set to $301 - LDA $301 ; Slot/Drive/Length + DW ONLNPL ; Buffer set to DRVBUF2 (was $301) + LDA DRVBUF2 ; was $301 ; Slot/Drive/Length AND #$0F ; Mask to get length + STA MOSFILE ; Store length TAX - INC ; Plus '/' at each end - INC - STA MOSFILE2 ; Store length - LDA #$2F ; '/' - STA MOSFILE2+1 - STA MOSFILE2+2,X -:L1 CPX #$00 ; Copy -> MOSFILE2 +:L1 CPX #$00 ; Copy -> MOSFILE BEQ :EXIT - LDA $301,X - STA MOSFILE2+1,X - DEX + LDA DRVBUF2,X ; was $301,X + STA MOSFILE,X ; Should be able to read + DEX ; directly to MOSFILE BRA :L1 :EXIT RTS +* :TEMP DB $00 * Delete first char of MOSFILE DEL1CHAR LDX MOSFILE ; Length @@ -1088,10 +1146,10 @@ FLSHPL HEX 01 ; Number of parameters ONLNPL HEX 02 ; Number of parameters DB $00 ; Unit num - DW $301 ; Buffer + DW DRVBUF2 ; was $301 ; Buffer GSPFXPL HEX 01 ; Number of parameters - DW $300 ; Buffer + DW DRVBUF1 ; was $300 ; Buffer GPFXPL HEX 01 ; Number of parameters DW MOSFILE2 ; Buffer @@ -1129,25 +1187,25 @@ QUITPL HEX 04 ; Number of parameters DB $00 DW $0000 -* Buffer for Acorn MOS filename -* Pascal string -MOSFILE DS 65 ; 64 bytes max prefix/file len +** Buffer for Acorn MOS filename +** Pascal string +*MOSFILE DS 65 ; 64 bytes max prefix/file len +* +** Buffer for second filename (for rename) +** Pascal string +*MOSFILE2 DS 65 ; 64 bytes max prefix/file len -* Buffer for second filename (for rename) -* Pascal string -MOSFILE2 DS 65 ; 64 bytes max prefix/file len - -* Acorn MOS format OSFILE param list -FILEBLK -FBPTR DW $0000 ; Pointer to name (in aux) -FBLOAD DW $0000 ; Load address - DW $0000 -FBEXEC DW $0000 ; Exec address - DW $0000 -FBSIZE -FBSTRT DW $0000 ; Size / Start address for SAVE - DW $0000 -FBATTR -FBEND DW $0000 ; Attributes / End address for SAVE - DW $0000 +** Acorn MOS format OSFILE param list +*FILEBLK +*FBPTR DW $0000 ; Pointer to name (in aux) +*FBLOAD DW $0000 ; Load address +* DW $0000 +*FBEXEC DW $0000 ; Exec address +* DW $0000 +*FBSIZE +*FBSTRT DW $0000 ; Size / Start address for SAVE +* DW $0000 +*FBATTR +*FBEND DW $0000 ; Attributes / End address for SAVE +* DW $0000 diff --git a/memmap.txt b/memmap.txt new file mode 100644 index 0000000..5b56aee --- /dev/null +++ b/memmap.txt @@ -0,0 +1,66 @@ +* Memory layout in main memory +* +* ; $0000-$00FF Zero page +* ; $0100-$01FF Stack +* ; $0200-$02FF ProDOS string buffers +* ; $0200-$022F Overwritten by RTC routines +* ; $0228-$023D +DRVBUF1 EQU $023E ; $023E Drive +DRVBUF2 EQU $023F ; $022F Prefix on current drive +CMDPATH EQU $0280 ; $0280 Path used to start Applecorn +* +* ; $0300-$03CF File system core workspace +* ; $0300-$0382 Filename string buffers +MOSFILE1 EQU $0300 ; $0300 length +* ; $0301 64 byte string +MOSFILE2 EQU $0341 ; $0341 length +* ; $0342 64 byte string +* ; $0382-$03BD $3C spare bytes +* ; +* ; $03BE-$03CF: local copy of control block +* ; $03BE FPTR FPTR +* ; $03BF CHANNEL +* ; $03C0 LOAD LOAD ADDR +* ; $03C4 EXEC EXEC COUNT +* ; $03C8 SIZE START OFFSET +* ; $03CC ATTR END +* ; $03D0-$03FF: ProDOS vectors, etc. +* ; $03D0-$03D2 JMP WARM +* ; $03D3-$03D5 JMP WARM +* ; $03D6-$03EC ProDOS +* ; $03ED-$03DE XFER address +* ; $03EF ProDOS +* ; $03F0-$03D1 BRKV +* ; $03F2-$03D3 RESETV +* ; $03F4 RESETV ACK +* ; $03F5-$03F7 JMP AMP +* ; $03F8-$03FA JMP USER +* ; $03FB-$03FD JMP MON +* ; $03FE-$03FF IRQV +* +* EQU $0400 ; $0400- Can't use as ProDOS uses 'hidden' bytes +* ; -$07FF within screen for workspace +SCREEN EQU $0800 ; $0800-$0BFF half 80-col screen or 40-col screen +IOBUF0 EQU $0C00 ; $0C00-$0FFF For loading ROM, OSFILE, *. +IOBUF1 EQU $1000 ; $1000-$13FF Four open files for langs +IOBUF2 EQU $1400 ; $1400-$17FF +IOBUF3 EQU $1800 ; $1800-$1BFF +IOBUF4 EQU $1C00 ; $1C00-$1FFF +* ; $2000- Code, to do: make code move itself +* -$4FFF +BLKBUF EQU $5000 ; $5000-$53FF 512-byte buffer plus channel data +BLKBUFEND EQU $5200 + + +* To do later: +* ; $2000-$3FFF Hi-Res screen 1 +* ; $4000-$5FFF Hi-Res screen 2 +* ; $6000- available +* ; -$95FF available +* ; $9600-$BDFF ProDOS buffers +* ; $BE00-$BEFF MLI Global workspace +* ; $BF00-$BFFF MLI API interface + +I think $0300-$03DF can be usefully used as filing system workspace, +the mainmem copies of the filename and control block, MOSNAME and CBFILE, +and later for OSGBPB.