From 4f43cc3443dc30cbd7f0e25e209872ee9ac406fc Mon Sep 17 00:00:00 2001 From: Bobbi Webber-Manners Date: Wed, 23 Oct 2019 19:09:51 -0400 Subject: [PATCH] Check in latest version of code for qkumba --- SOFTCARD65#ff2000 | Bin 0 -> 393 bytes SOFTCARD65.S#040000 | 2 +- SOFTCARD80.ASM#040000 | 2058 ----------------------------------------- zapple2.po | Bin 819200 -> 819200 bytes 4 files changed, 1 insertion(+), 2059 deletions(-) create mode 100644 SOFTCARD65#ff2000 delete mode 100644 SOFTCARD80.ASM#040000 diff --git a/SOFTCARD65#ff2000 b/SOFTCARD65#ff2000 new file mode 100644 index 0000000000000000000000000000000000000000..2e97fe5e85be390debe063ee28858d0a708efea4 GIT binary patch literal 393 zcmY+Ay-EW?6oqFKvpWlFqLt;878d#dwra812`Q&Dg)bpEb`gDpDO{Z!h?q`e;ZH)y zgrGyTkbp&CH-%=CWeI}H5_f|{(j4x0&VhTmu*P&C%mBnN2xf9r(ob+#SBb9C#gUq} zDM7v4SZ0-DAwjZ&c)~YHJ0!cp+7QJrkxxK=0m%2Cy+5`wM3tfuD>({@3FKJhQI#x$ zwJuP+hv9ljCtg^?>XX8CbckRE*%VQoLSuqZn2h7(bsGOuaHo>_=cn3B<-S$Dy1aOh zkC}GI_j_(pO5PlF9541 then call UNIMP - LD HL,BDOSVEC ; Start of vector table - SLA C ; Multiply C by 2 - LD B,0 ; MSB of BC is zero - ADD HL,BC ; Address of vector in HL - LD C,(HL) ; Read LSB of address to jump to - INC HL ; Read MSB of address to jump to - LD H,(HL) ; ... - LD L,C ; Address needs to be in HL - JP (HL) ; Jump to it! - -; Vector table -BDOSVEC DEFW C_TERMCPM ; C=00H - DEFW C_READ ; C=01H - DEFW C_WRITE ; C=02H - DEFW UNIMP ; C=03H (A_READ) AUX - DEFW UNIMP ; C=04H (A_WRITE) AUX - DEFW UNIMP ; C=05H (L_WRITE) PRN - DEFW C_RAWIO ; C=06H - DEFW GET_IOB ; C=07H - DEFW SET_IOB ; C=08H - DEFW C_WRITESTR ; C=09H - DEFW C_READSTR ; C=0AH - DEFW C_STAT ; C=0BH - DEFW S_BDOSVER ; C=0CH - DEFW DRV_ALLRST ; C=0DH - DEFW DRV_SET ; C=0EH - DEFW F_OPEN ; C=0FH - DEFW F_CLOSE ; C=10H - DEFW F_SFIRST ; C=11H - DEFW F_SNEXT ; C=12H - DEFW F_DELETE ; C=13H - DEFW F_READ ; C=14H - DEFW F_WRITE ; C=15H - DEFW F_MAKE ; C=16H - DEFW F_RENAME ; C=17H - DEFW DRV_LOGVEC ; C=18H - DEFW DRV_GET ; C=19H - DEFW F_DMAOFF ; C=1AH - DEFW DRV_AVEC ; C=1BH - DEFW DRV_SETRO ; C=1CH - DEFW DRV_ROVEC ; C=1DH - DEFW UNIMP ; C=1EH (F_ATTRIB) - DEFW DRV_DPB ; C=1FH - DEFW F_USERNUM ; C=20H - DEFW F_READRAND ; C=21H - DEFW F_WRITERAND ; C=22H - DEFW F_SIZE ; C=23H - DEFW F_RANDREC ; C=24H - DEFW DRV_RESET ; C=25H - DEFW UNIMP ; C=26H (*nothing* in CP/M 2.2) - DEFW UNIMP ; C=27H (*nothing* in CP/M 2.2) - DEFW F_WRITERAND ; C=28H (F_WRITEZF) - -; Unimplemented BDOS call, just ring the bell -UNIMP LD HL,BELL ; We are going to call BELL - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - RET ; Return to calling program - -; System reset. Jump to $0000 - doesn't return -C_TERMCPM RST 0 ; Quick jump to zero - -; Wait for a character from the console, return it in A and L -; Also echoes the char to the console -C_READ LD HL,RDKEY ; We are going to call RDKEY - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - LD A,(AREG) ; Grab the return value - PUSH AF ; Preserve A (and F) - - LD HL,COUT ; Echo the character using COUT - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - - POP AF ; Restore A (and F) - AND 7FH ; Mask high bit - LD L,A ; Copy A to L - RET ; Return to calling program - -; Write character in E to the console -; TODO: Handle tabs -C_WRITE LD A,80H ; Set high bit - OR E ; ... - CP 8AH ; Check for linefeed - RET Z ; If LF, don't print it - LD (AREG),A ; Pass char to COUT in 6502 A - LD HL,COUT ; We are going to call COUT - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - RET ; Return to calling program - -; If E if 0FFH then input a character from console and return it in A and L -; without echoing the input character. Otherwise output char in E to the -; console (no tabs, ^S or ^Q supported) -C_RAWIO LD A,E ; See if E if 0FFH - CP 0FFH ; ... - JP Z,RIS1 ; If so, then read - - ; Write to console - LD A,80H ; Set high bit - OR E ; ... - CP 8AH ; Check for linefeed - RET Z ; If LF, don't print it - LD (AREG),A ; Pass char to COUT in 6502 A - LD HL,COUT ; We are going to call COUT - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - RET - - ; If character is waiting, read from console & return in A - ; Otherwise, return 00H in A -RIS1 LD A,3 ; CMD=3 means peek at keyboard - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it - LD A,(AREG) ; Grab the return value - CP 0 ; If zero, no chars are waiting - JP Z,RIS2 ; ... - LD HL,RDKEY ; We are going to call RDKEY - LD (ADDR),HL ; ... - LD A,1 ; CMD=1 means call 6502 sub - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - LD A,(AREG) ; Grab the return value - AND 7FH ; Mask high bit - LD L,A ; Copy A to L - RET ; -RIS2 XOR A ; No chars waiting, A=0 - LD L,A ; Return in L also - RET - -; Get the IOBYTE in A and L -GET_IOB LD A,(IOBYTE) ; - LD L,A ; Copy to L - RET - -; Set the IOBYTE -; E contains the IOBYTE value to set -SET_IOB LD A,E ; - LD (IOBYTE),A ; - RET - -; Write ASCII string to console. '$' is the terminator -; DE contains the address of the string -C_WRITESTR LD A,(DE) ; Fetch character from string - CP '$' ; Is it '$'? - RET Z ; If so, we are done - PUSH DE ; We are gonna need E - LD E,A ; For C_WRITE - CALL C_WRITE ; Sent char to console - POP DE ; Recover the pointer - INC DE ; Advance pointer - JP C_WRITESTR ; Handle the next char - -; Read console string -; DE points to the string buffer. First byte of the buffer is the capacity -; of the buffer. This function writes the number of bytes written in second -; byte. Entry finishes on CR or when the buffer is filled up. -; TODO: Line editing is supposed to be supported here -C_READSTR LD H,D ; HL will be the working pointer - LD L,E ; ... - INC HL ; Advance to first character ... - INC HL ; ... 3rd byte of the buffer - PUSH DE ; Put DE into IX - POP IX ; ... - XOR A ; Set number of chars read to zero - LD (IX+1),A ; ... -CRSL1 PUSH HL ; Preserve HL - CALL C_READ ; Read a character into A - POP HL ; Restore HL - CP 13 ; Carriage return? - RET Z ; If so, we are done - CP 10 ; Line feed? - RET Z ; If so, we are done - LD B,A ; Stash character in B - LD A,(IX+0) ; Buffer capacity -> A - SUB (IX+1) ; Subtract characters read - CP 0 ; If no space left ... - RET Z ; ... we are done - LD (HL),B ; Write character to buffer - INC HL ; Advance to next character - INC (IX+1) ; Increment character count - JP CRSL1 ; Loop - RET - -; Returns 0 in A and L if no chars waiting, non zero otherwise -C_STAT LD A,3 ; CMD=3 means peek at keyboard - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it - LD A,(AREG) ; Grab the return value - LD L,A ; Copy A to L - RET - -; Returns system type in B and H, BDOS version in A and L -S_BDOSVER LD B,0 ; System is 8080 CP/M - LD H,B ; Also in H - LD A,22H ; Pretend to v2.2 - LD L,A ; Also in A - RET - -; Reset disks -; Makes A: drive the default -DRV_ALLRST LD A,(CURDRV) ; Contains both user & current drive - AND 0F0H ; Set drive to 0, meaning A: - LD (CURDRV),A ; Store in CURDRV - LD BC,FILEBUF ; FILEBUF is at 0080H - LD (DMAADDR),BC ; Reset DMA address - LD HL,FLMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI to flush all files - RET - -; Select disk -; Disk to select is passed in E (A: is 0, B: is 1 etc.) -; Return 00 for success, 0FFH for error in A and L -DRV_SET LD A,E ; Prepare to compare disk number - CP 16 ; Support 16 'drives' A: - P: - JP NC,DSERR ; If A>15 ... error - LD B,A ; Stash in B for now - LD A,(CURDRV) ; Has both user number & current drive - AND 0F0H ; Mask out old drive number - OR B ; Replace with new drive number - LD (CURDRV),A ; Store the requested drive number - XOR A ; A=0: Return code meaning success - JP DSRET ; -DSERR LD A,0FFH ; Return code for error -DSRET LD L,A ; Return code in L too - RET - -; Open file -; DE is the address of the FCB describing the file to open -; Returns error codes in A and L: -; Returns 0 for success. The FCB for the file opened is left at DMAADDR (slot 0) -; Returns 0FFH if file not found -; TODO: F_OPEN should use the record count field of the FCB and (if non zero) seek -; to appropriate point in the file -F_OPEN PUSH DE ; Preserve pointer to FCB - CALL F_SFIRST ; Find first matching directory entry - POP DE ; Restore pointer to FCB - -; Alternative entrypoint used for opening ProDOS directory file only -_F_OPEN LD IX,PATHBUF ; Destination buffer - CALL FCB2PATH ; Populate PATHLEN and PATH - - PUSH DE ; Copy pointer to FCB ... - POP IY ; ... into IY - - ; Work out which IOBUF to allocate for this file - XOR A ; Looking for FRN slot with value 0 - CALL GETIOADDR ; Returns FRN slot in A, IOBUF in HL - CP 0FFH ; Check for error - JP Z,FOERR ; If no slots available, error out - - LD (TEMPBYTE),A ; Record the buffer index in local var - LD BC,OFFSET ; Add offset to convert to 6502 address - ADD HL,BC ; ... - LD (FOMLII),HL ; Store in parameter list - - LD HL,FOMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FOERR ; Handle error - - ; Store ProDOS FRN in S2 field of FCB - LD A,(FOMLIN) ; Get ProDOS file reference number - LD (IY+0EH),A ; Store file reference number in S2 field - - ; ProDOS GET_EOF call - ; Assumes no files > 64K on ProDOS filesystem - LD (GEMLIN),A ; Store file ref num in param list - LD HL,GEMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI (GET_EOF) - - ; Convert length in bytes to length in records - LD HL,(GEMLIE2) ; Load 16 bit length - CALL LEN2RECS ; Leaves number of records in A - - ; Store records used - LD (IY+0FH),A ; Set records used field - - ; Set sequential record number to zero - XOR A ; Zero the sequential record number - LD (IY+20H),A ; ... - - ; Store ProDOS FRN in slot FRN1 - FRN4 - LD A,(TEMPBYTE) ; Obtain IOBUF idx (1,2,3,4) - LD HL,FRN1-1 ; Compute address of FRN slot to use - LD B,0 ; ... - LD C,A ; ... - ADD HL,BC ; ... - LD A,(FOMLIN) ; Get ProDOS file reference number - LD (HL),A ; Store in FRN slot - - XOR A ; Success - LD L,A ; Copy to L - RET ; Done - -FOERR LD A,0FFH ; Error return status - LD L,A ; Copy to L - RET ; Done (error) - -; Close file -; DE is the address of the FCB describing the file to close -; Returns error codes in A and L: -F_CLOSE LD H,D ; Pointer to FCB ... - LD L,E ; ... into HL - LD BC,0EH ; Offset to S2 field (reserved field) - ADD HL,BC ; Compute address - LD A,(HL) ; Obtain file reference num from FCB S2 - CP 0 ; If file reference number is zero ... - JP Z,FCSUCC ; ... Nothing to do, just return - LD (FCMLIN),A ; Store in parameter list - LD HL,FCMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FCERR ; Handle error - - LD A,(FCMLIN) ; Obtain file reference number again - CALL GETIOADDR ; Returns FRN slot in A, IOBUF in HL - CP 0FFH ; Check for error - JP Z,FCERR ; If FRN not found, error out - - LD HL,FRN1-1 ; Compute addr of FRN slot to set to zero - LD B,0 ; ... - LD C,A ; ... - ADD HL,BC ; ... - XOR A ; And zero it - LD (HL),A ; ... - - PUSH DE ; Copy pointer to FCB ... - POP IX ; ... into IX - XOR A ; Zero out the S2 field - LD (IX+0EH),A ; ... - -FCSUCC XOR A ; Return zero for error - LD L,A ; Return in L also - RET - -FCERR LD A,0FFH ; 0FFH for error - LD L,A ; Return code in L also - RET - -DIRHDSZ EQU 2BH ; Size of ProDOS directory header -FILEENTSZ EQU 27H ; Size of ProDOS file entry -ENTPERBLK EQU 0DH ; Number of file entries per block - -; Search for first match of filename in directory -; DE is the address of the FCB describing the file to look for -; Returns error codes in A and L: 0 for success, 0FFH for not found -; The matching FCB is always in slot 0, so success return code always 0 -; TODO: Should handle '?' in extent field also -F_SFIRST LD (TEMPWORD),DE ; Store pointer to search FCB - LD A,(DE) ; Obtain drive number - LD (DFCBDRV),A ; Copy to directory FCB - LD DE,DFCB ; Use this FCB to open the directory - CALL F_CLOSE ; Close the directory, if open - LD DE,DFCB ; Use this FCB to open the directory - CALL _F_OPEN ; Open the directory (avoiding recursion!) - -FSFL1 CALL RDDIRBLK ; Read first 512 byte block - CP 0 ; See if it was an error - JP NZ,FSFS2 ; If error, assume EOF & just return - - LD HL,DIRBUF ; Skip over directory header - LD BC,DIRHDSZ ; ... - ADD HL,BC ; ... - LD (CDBPTR),HL ; Start out at first file entry - XOR A ; Set file count to zero - LD (CDBCOUNT),A ; ... - - LD DE,(TEMPWORD) ; Get ptr to search FCB back - CALL CHKDIRBLK ; Search directory block - CP 0 ; See if it was a match - JP Z,FSFS1 ; If so, return - JP FSFL1 ; Loop - -FSFS1 XOR A ; Match - RET ; -FSFS2 LD A,0FFH ; No match - RET - -; Search for next match of filename in directory -; DE is the address of the FCB describing the file to look for -; Returns error codes in A and L: 0 for success, 0FFH for not found -; The matching FCB is always in slot 0, so success return code always 0 -; TODO: Should handle '?' in extent field also -F_SNEXT LD (TEMPWORD),DE ; Store pointer to search FCB - LD HL,(CDBPTR) ; Pointer into current block - LD A,(CDBCOUNT) ; File count for current block -FSNL1 CALL CHKDIRBLK ; Search directory block - CP 0 ; See if it was a match - JP Z,FSNS1 ; If so, return - - CALL RDDIRBLK ; Read next 512 byte block - CP 0 ; See if it was an error - JP NZ,FSNS2 ; If error, assume EOF & just return - - LD HL,DIRBUF ; Skip over directory header - LD BC,DIRHDSZ ; ... - ADD HL,BC ; ... - LD (CDBPTR),HL ; Start out at first file entry - XOR A ; Set file count to zero - LD (CDBCOUNT),A ; ... - - JP FSNL1 ; Loop - -FSNS1 XOR A ; Match - RET ; -FSNS2 LD A,0FFH ; No match - RET - -; Delete file -; DE is the address of the FCB describing the file to delete -; Returns error codes in A and L: -F_DELETE CALL F_SFIRST ; Search for file, create FCB - CP 0FFH ; If not found ... - JP Z,FDERR ; ... Return with error - LD IX,PATHBUF ; Destination buffer - CALL FCB2PATH ; Populate PATHLEN and PATH - LD HL,FDMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FDERR ; Handle error - LD L,A ; ... and L too - RET -FDERR LD A,0FFH ; 0FFH for error - LD L,A ; Return code in L also - RET - -; Read next record -; DE is the address of the FCB describing the file from which to read -; Returns error codes in A and L: -; 0 OK, 1 EOF, 9 invalid FCB, 10 media changed, 0FFH h/w error -F_READ PUSH DE ; Copy pointer to FCB ... - POP IX ; ... into IX - LD A,(IX+0EH) ; Obtain file reference num from FCB S2 - LD (SMMLIN),A ; Store in parameter list for SET_MARK - LD (FRMLIN),A ; Store in parameter list for READ - - LD A,(IX+20H) ; Obtain sequential record number - LD B,(IX+0CH) ; Obtain extent from FCB - CALL EXRC2LEN ; Leaves the length in bytes in HL - LD (SMMLIP1),HL ; Write 16 bit length in FRMLIP1,FRMLIP2 - XOR A ; Set FRMLIP3 to zero - LD (SMMLIP3),A ; ... - LD HL,SMMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - SET_MARK - CP 4DH ; See if position was out of range - JP Z,FRBFCB ; If so, return invalid FCB code (9) - CP 43H ; See if it was a bad file ref number - JP Z,FRBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FRERR ; If so, return code 0FFH (h/w error) - - LD HL,(DMAADDR) ; Read from DMA buffer address - LD BC,OFFSET ; Convert to 6502 address - ADD HL,BC ; ... - LD (FRMLIDB),HL ; Store I/O buffer address in parm list - - LD HL,FRMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - READ - CP 4CH ; See if it was EOF - JP Z,FREOF ; If so, return EOF code (1) - CP 43H ; See if it was a bad file ref number - JP Z,FRBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FRERR ; If so, return code 0FFH (h/w error) - - LD A,(IX+20H) ; Get sequential rec num from FCB - INC (IX+20H) ; Increment sequential record number - CP 129 ; Is it 129? 128 is the max - JP NZ,FRS1 ; If not, then nothing else to do - XOR A ; Set sequential rec num to zero - LD (IX+20H),A ; ... - INC (IX+0CH) ; Increment the extent - -FRS1 XOR A ; Zero for success - LD L,A ; Return code in L also - RET ; Done -FREOF LD A,1 ; EOF return code - LD L,A ; Return code in L also - RET ; Done (EOF) -FRBFCB LD A,9 ; Invalid FCB return code - LD L,A ; Return code in L also - RET ; Done (Bad FCB) -FRERR LD A,0FFH ; All other errors are 0FFH - LD L,A ; Return code in L aslo - RET ; Done (error) - -; Write next record -; DE is the address of the FCB describing the file to which to write -; Returns error codes in A and L: -; 0 OK, 1 dir full, 2 disk full, 9 invalid FCB, 10 media changed, 0FFH h/w error -F_WRITE PUSH DE ; Copy pointer to FCB ... - POP IX ; ... into IX - LD A,(IX+0EH) ; Obtain file reference num from FCB S2 - LD (SMMLIN),A ; Store in parameter list for SET_MARK - LD (FWMLIN),A ; Store in parameter list for WRITE - - LD A,(IX+20H) ; Obtain sequential record number - LD B,(IX+0CH) ; Obtain extent from FCB - CALL EXRC2LEN ; Leaves the length in bytes in HL - -;; ; DEBUG -;; PUSH HL -;; LD DE,HEXBUF ; Generate hex string to HEXBUF -;; CALL NUM2HEX ; ... -;; LD DE,HEXBUF ; Write hex value to console -;; CALL C_WRITESTR ; -;; POP HL -;; ; END DEBUG - - LD (SMMLIP1),HL ; Write 16 bit length in SMMLIP1,SMMLIP2 - XOR A ; Set SMMLIP3 to zero - LD (SMMLIP3),A ; ... - LD HL,SMMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - SET_MARK - CP 4DH ; See if position was out of range - JP Z,FWBFCB ; If so, return invalid FCB code (9) - CP 43H ; See if it was a bad file ref number - JP Z,FWBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FWERR ; If so, return code 0FFH (h/w error) - - LD HL,(DMAADDR) ; Write data at DMA address - LD BC,OFFSET ; Convert to 6502 address - ADD HL,BC ; ... - LD (FWMLIDB),HL ; Store I/O buffer address in parm list - - LD HL,FWMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - WRITE - CP 43H ; See if it is a bad reference number - JP Z,FWBFCB ; If so, return invalid FCB code (9) - CP 48H ; See if it was an overrun error - JP Z,FWDF ; If so, return disk full code (2) - CP 0 ; See if there was some other error - JP NZ,FWERR ; If so, return code 0FFH (h/w error) - - LD A,(IX+20H) ; Get sequential rec num from FCB - INC (IX+20H) ; Increment sequential record number - CP 129 ; Is it 129? 128 is the max - JP NZ,FWS1 ; If not, then nothing else to do - XOR A ; Set sequential rec num to zero - LD (IX+20H),A ; ... - INC (IX+0CH) ; Increment the extent - -FWS1 XOR A ; Zero for success - LD L,A ; Return code in L also - RET ; Done -FWBFCB LD A,9 ; Invalid FCB return code - LD L,A ; Return code in L also - RET ; Done (EOF) -FWDF LD A,2 ; Disk full return code - LD L,A ; Return code in L also - RET ; Done (Disk Full) -FWERR LD A,0FFH ; All other errors are 0FFH - LD L,A ; Return code in L aslo - RET ; Done (error) - -; Create (and open) file -; DE is the address of the FCB describing the file to create -; Returns error codes in A and L: -; 0 for success, 0FFH if file could not be created -F_MAKE LD IX,PATHBUF ; Destination buffer - CALL FCB2PATH ; Populate PATHLEN and PATH - LD HL,FMMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FMERR ; Handle error - CALL F_OPEN ; Open the file using same FCB (DE ptr) - RET ; Return with status from F_OPEN -FMERR LD A,0FFH ; 0FFH for error - LD L,A ; Return code in L also - RET - -; Rename file -; DE is the address of the FCB describing the file to be renamed. The new name -; is stuffed into FCB+16 (where the allocation map usually goes) -; Returns error codes in A and L - 0 for success, 0FFH for file not found -F_RENAME CALL F_SFIRST ; Search for file, create FCB - CP 0FFH ; If not found ... - JP Z,FRNERR ; ... Return with error - LD IX,PATHBUF ; Destination buffer 1 - CALL FCB2PATH ; Populate PATHLEN and PATH for first file - LD IX,PATHBUF2 ; Destination buffer 2 - LD H,D ; DE -> HL for addition - LD L,E ; ... - LD BC,16 ; Increment by 16 bytes to 2nd part of FCB - ADD HL,BC ; ... - LD D,H ; HL back to DE - LD E,L ; ... - CALL FCB2PATH ; Populate PATHLEN and PATH for second file - LD HL,FRNMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FRNERR ; Handle error - XOR A ; Success - LD L,A ; Return code in L also - RET -FRNERR LD A,0FFH ; 0FFH for error - LD L,A ; Return code in L also - RET - -; Return bitmap of logged-in drives in HL -DRV_LOGVEC LD HL,(LOGVEC) ; - RET - -; Return current drive in A -DRV_GET LD A,(CURDRV) ; Contains user number & current drive - AND 0FH ; Mask out user number - RET - -; Set DMA address -; DMA address is passed in DE -F_DMAOFF LD (DMAADDR),DE ; - RET - -; Return address of allocation map in HL -DRV_AVEC LD HL,ALLOCVEC ; - RET - -; Software write-protect current disk -DRV_SETRO LD B,80H ; Set MS-bit in B, will rotate this below - LD A,(CURDRV) ; Current drive (0 A:, 1 B: ...) - AND 0FH ; Mask out user number - INC A ; It is easier if A: is 1, B is 2 etc. - CP 9 ; See if it in LS-byte or MS-byte of ROVEC - JP NC,DSRMSB ; If A>8 then drive bit in in MS-byte -DSRL1 RL B ; - DEC A ; - JP NZ,DSRL1 ; - LD A,(ROVEC) ; Fetch the LS-byte of ROVEC - OR B ; Set the bit using OR - LD (ROVEC),A ; Store LS-byte back to ROVEC - RET ; We're done -DSRMSB LD C,8 ; Subtract 8 from the drive number - SUB C ; A = A-8 -DSRL2 RL B ; - DEC A ; - JP NZ,DSRL2 ; - LD A,(ROVEC+1) ; Fetch the MS-byte of ROVEC - OR B ; Set the bit using OR - LD (ROVEC+1),A ; Store MS-byte back to ROVEC - RET - -; Return bitmap of read-only drives in HL -DRV_ROVEC LD HL,(ROVEC) ; Bit 0 of L is A:, bit 7 of H is P: - RET - -; Return pointer to Drive Parameter Block in HL -DRV_DPB LD HL,DPB ; Pointer to drive parameter block - RET - -; Get/set user number -; E contains the user number to set, or 0FFH to get current user number -; If E is 0FFH then user number is returned in A -F_USERNUM LD A,E ; See if it is get or set - CP 0FFH ; 0FFH means 'get' - JP Z,FUNS1 ; It is 'get' - LD B,A ; Stash the user number to set in B - SLA B ; Left shift four times - SLA B ; ... - SLA B ; ... - SLA B ; ... - LD A,(CURDRV) ; Contains user number & current drive - AND 0FH ; Mask out current user number - OR B ; OR in the new user number - LD (CURDRV),A ; Store updated user number & curr drv - RET ; -FUNS1 LD A,(CURDRV) ; Contains user number & current drive - AND 0F0H ; Mask out current drive - SRA A ; Right shift the user number 4 times - SRA A ; ... - SRA A ; ... - SRA A ; ... - RET - -; Random access read record -; DE contains address of FCB describing the file to read -; Return code in A and L: -; 0 success, 1 reading unwritten data, 4 reading unwritten extent, -; 6 rec number out of range, 9 invalid FCB, 10 media changed, 0FFH h/w err -F_READRAND PUSH DE ; Copy pointer to FCB ... - POP IX ; ... - LD A,(IX+0EH) ; Obtain file reference num from FCB S2 - LD (SMMLIN),A ; Store in parameter list for SET_MARK - LD (FRMLIN),A ; Store in parameter list for READ - - LD H,(IX+21H) ; Load LSB of random record number - LD L,(IX+22H) ; ... - CALL RRN2LEN ; Leaves the length in bytes in HL - LD (SMMLIP1),HL ; Write 16 bit length in FRMLIP1,FRMLIP2 - XOR A ; Set FRMLIP3 to zero - LD (SMMLIP3),A ; ... - LD HL,SMMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - SET_MARK - CP 4DH ; See if position was out of range - JP Z,FRRBFCB ; If so, return invalid FCB code (9) - CP 43H ; See if it was a bad file ref number - JP Z,FRRBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FRRERR ; If so, return code 0FFH (h/w error) - - LD HL,(DMAADDR) ; Read from DMA buffer address - LD BC,OFFSET ; Convert to 6502 address - ADD HL,BC ; ... - LD (FRMLIDB),HL ; Store I/O buffer address in parm list - LD HL,FRMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - READ - CP 4CH ; See if it was EOF - JP Z,FRREOF ; If so, return EOF code (1) - CP 43H ; See if it was a bad file ref number - JP Z,FRBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FRRERR ; If so, return code 0FFH (h/w error) - - LD H,(IX+21H) ; Load LSB of random record number - LD L,(IX+22H) ; ... - CALL RECS2EXRC ; Puts extent in B, recs in A - LD A,(IX+20H),A ; Update sequential record number - LD B,(IX+0CH),B ; Update sequential extent number - - XOR A ; Zero for success - LD L,A ; Return code in L also - RET ; Done -FRREOF LD A,1 ; EOF return code - LD L,A ; Return code in L also - RET ; Done (EOF) -FRRBFCB LD A,9 ; Invalid FCB return code - LD L,A ; Return code in L also - RET ; Done (Bad FCB) -FRRERR LD A,0FFH ; All other errors are 0FFH - LD L,A ; Return code in L aslo - RET ; Done (error) - -; Random access write record -; DE contains address of FCB describing the file to write -; Return code in A and L: -; 0 success, 1 reading unwritten data, 4 reading unwritten extent, -; 6 rec number out of range, 9 invalid FCB, 10 media changed, 0FFH h/w err -F_WRITERAND PUSH DE ; Copy pointer to FCB ... - POP IX ; ... - LD A,(IX+0EH) ; Obtain file reference num from FCB S2 - LD (GEMLIN),A ; Store in parameter list for GET_EOF - LD (SEMLIN),A ; Store in parameter list for SET_EOF - LD (SMMLIN),A ; Store in parameter list for SET_MARK - LD (FWMLIN),A ; Store in parameter list for WRITE - - LD HL,GEMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - GET_EOF - - LD H,(IX+21H) ; Load LSB of random record number - LD L,(IX+22H) ; ... - CALL RRN2LEN ; Leaves the length in bytes in HL - LD (SMMLIP1),HL ; 16 bit len in SMMLIP1,2 for SET_MARK - XOR A ; Set SMMLIP3 to zero - LD (SMMLIP3),A ; ... - - LD HL,(GEMLIE1) ; Load current EOF into HL - LD BC,(SMMLIP1) ; Load requested offset into BC - AND A ; Clear carry - SBC HL,BC ; Subtract requested byte offset from EOF - JP NC,FWRS1 ; If >=0 no need to SET_EOF - - LD (SEMLIE1),BC ; Requested offset for SET_EOF - LD HL,SEMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - SET_EOF - -FWRS1 LD HL,SMMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - SET_MARK - CP 4DH ; See if position was out of range - JP Z,FWRBFCB ; If so, return invalid FCB code (9) - CP 43H ; See if it was a bad file ref number - JP Z,FWRBFCB ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FWRERR ; If so, return code 0FFH (h/w error) - - LD HL,(DMAADDR) ; Get DMA buffer address - LD BC,OFFSET ; Convert to 6502 address - ADD HL,BC ; ... - LD (FWMLIDB),HL ; Store I/O buffer address in parm list - LD HL,FWMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - WRITE - CP 43H ; See if it was a bad file ref number - JP Z,FWRBFCB ; If so, return invalid FCB code (9) - CP 48H ; See if it was a bad file ref number - JP Z,FWRDF ; If so, return invalid FCB code (9) - CP 0 ; See if there was some other error - JP NZ,FWRERR ; If so, return code 0FFH (h/w error) - - LD H,(IX+21H) ; Load LSB of random record number - LD L,(IX+22H) ; ... - CALL RECS2EXRC ; Puts extent in B, recs in A - LD A,(IX+20H),A ; Update sequential record number - LD B,(IX+0CH),B ; Update sequential extent number - - XOR A ; Zero for success - LD L,A ; Return code in L also - RET ; Done -FWRBFCB LD A,9 ; Invalid FCB return code - LD L,A ; Return code in L also - RET ; Done (Disk Full) -FWRDF LD A,2 ; Disk fill return code - LD L,A ; Return code in L also - RET ; Done (Bad FCB) -FWRERR LD A,0FFH ; All other errors are 0FFH - LD L,A ; Return code in L aslo - RET ; Done (error) - - -; Compute file size -; DE contains address of FCB describing the file -; Error codes are returned in A and L (0 for success, 0FFH if file not found) -; Returns the number of 128 byte records in random record count field of FCB -F_SIZE CALL FCB2PATH ; Populate PATHLEN and PATH - LD HL,FSMLI ; Pass address of 6502 JSR instruction - CALL PRODOS ; Invoke ProDOS MLI - CP 0 ; See if there was an error - JP NZ,FSERR ; Handle error - LD HL,(FSMLIBU) ; Obtain the blocks used field - ADD HL,HL ; Mult x 2 to get 128 byte records - - ; Store records used in R0,R1 fields of FCB - PUSH DE ; Copy DE ... - POP IX ; ... into IX - LD (IX+21H),L ; Store LSB of recs used in R0 - LD (IX+22H),H ; Store LSB of recs used in R1 - XOR A ; Store zero in R2 - LD (IX+23H),A ; ... - - XOR A ; Success - LD L,A ; Return in L also - RET -FSERR LD A,0FFH ; File not found - LD L,A ; Return in L also - RET - -; Update random access pointer -; DE contains the pointer to the FCB to update -; Sets the random access record of the FCB to the value of the last record -; read or written sequentially -F_RANDREC PUSH DE ; Copy pointer to FCB ... - POP IX ; ... into IX - LD A,(IX+20H) ; Obtain sequential record number - LD B,(IX+0CH) ; Obtain extent from FCB - CALL EXRC2RECS ; Leaves the length in records in HL - DEC HL ; Because F_READ/F_WRITE advance this - LD (IX+21H),L ; Store in random access pointer ... - LD (IX+22H),H ; ... In little endian format - RET - -; Selectively reset disk drives -; DE contains bitmap of drives to reset (bit 0 of E if A:, bit 7 of D is P:) -; Returns A=00H if okay, A=FFH if error -; Resetting means removing the read-only status -DRV_RESET LD A,(ROVEC) ; Do the LSB ... - XOR E ; ... with E - LD (ROVEC),A ; - LD A,(ROVEC+1) ; Then the MSB ... - XOR D ; ... with D - LD (ROVEC+1),A ; - RET - -; Make a ProDOS MLI call -; Address of 6502 JSR instruction in front of ProDOS parameter list is -; passed in in register pair HL, in Z80 address space -; Return code is passed back in A -PRODOS LD BC,OFFSET ; Add offset to convert Z80->6502 address - ADD HL,BC ; ... - LD (ADDR),HL ; Store it for 6502 - LD A,2 ; CMD=2 means ProDOS MLI call - LD (CMD),A ; ... - LD (SOFTCARD),A ; Do it! - LD A,(AREG) ; Get return code from the MLI call - RET - -; Populate the PATH buffer (and PATHLEN) by copying from FCB -; If the FCB contains A:TEST____.TXT then the PATH buffer will be A/TEST.TXT -; DE contains a pointer to the FCB -; IX contains pointer to the path buffer into which to write -FCB2PATH PUSH IX ; Copy IX->IY - POP IY ; So IY keeps track of size byte at start - INC IX ; Advance past the size byte before writing - LD A,(DE) ; Get drive number from FCB - CP 0 ; See if it is zero (default drive) - JP NZ,F2PS1 ; If drive explicit - LD A,(CURDRV) ; If default drive use CURDRV - AND 0FH ; Mask out user number - INC A ; CURDRV is zero based -F2PS1 ADD A,'A'-1 ; Convert to drive letter - LD (IX+0),A ; Store as first char of path - INC IX ; Advance IX to next char of path to write - LD A,'/' ; Second char of path is '/' - LD (IX+0),A ; Store as second char of path - INC IX ; Advance IX to next char of path to write - LD C,2 ; Use C to count chars in filename - LD H,D ; Copy address of FCB from DE ... - LD L,E ; ... to HL - INC HL ; HL points to filename in FCB - - LD A,(HL) ; First character of filename - CP ' ' ; Is it space? ie: no file specified - JP Z,F2PS6 ; Don't handle filename or extension - -F2PL1 ; Handle the filename - up to 8 characters - LD A,(HL) ; Obtain filename character - CP ' ' ; See if it is a space - JP Z,F2PS3 ; If so we are done with filename - EX AF,AF' ; We need to re-use A here - LD A,C ; Get character count - CP 10 ; Drive letter, slash and 8 char filename - JP Z,F2PS2 ; If so we are done with filename - EX AF,AF' ; Swap back to original A reg - LD (IX+0),A ; Copy to PATH buffer - INC C ; Increment filename char count - INC HL ; Next byte of filename in FCB - INC IX ; Next byte of PATH buffer - JP F2PL1 ; Loop till done - -F2PS2 EX AF,AF' ; Swap back to original A reg - -F2PS3 ; Eat any space characters at end of filename -F2PL2 LD A,(HL) ; Read next character from FCB - CP ' ' ; Is it space? - JP NZ,F2PS4 ; If not, we are done eating! - INC HL ; Otherwise advance to next char - JP F2PL2 ; And loop - -F2PS4 LD A,'.' ; Separator is a period - LD (IX+0),A ; Write to buffer - INC C ; Count the character! - INC IX ; Advance to next character in buffer - LD B,0 ; Use B to track num chars in extension - - ; Handle the extension - up to 3 characters -F2PL3 LD A,(HL) ; Obtain extension character - CP ' ' ; See if it is a space (? or NULL maybe?) - JP Z,F2PS6 ; If so we are done with extension - EX AF,AF' ; We need to re-use A here - LD A,B ; Get character count - CP 3 ; Extension can be up to 3 chars - JP Z,F2PS5 ; If so we are done with filename - EX AF,AF' ; Swap back to original A reg - LD (IX+0),A ; Copy to PATH buffer - INC C ; Count the chars (overall) - INC B ; Count the chars (in extension) - INC HL ; Next byte of filename in FCB - INC IX ; Next byte of PATH buffer - JP F2PL3 ; Loop till done - -F2PS5 EX AF,AF' ; Swap back to original A reg - -F2PS6 LD A,C ; Store length of string - LD (IY+0),A ; We kept size byte in IY at start - RET ; - -; This operation is almost the inverse of FCB2PATH. It takes a pointer to the -; beginning of the ProDOS dirent and converts it to FCB format (8.3 with -; spaces for any unused characters.) -; HL points to the file entry in the ProDOS directory -; B contains the drive number (1 for A:, 2 for B: etc) -; The FCB is written to the buffer pointed to by DMAADDR -; Trashes pretty much all registers (except IX, IY) -PATH2FCB EX DE,HL ; Stash HL in DE so we can use HL here - - LD HL,(DMAADDR) ; Set all 32 bytes to FCB to zero - LD C,0 ; ... - XOR A ; ... -P2FL1 LD (HL),C ; ... - INC HL ; ... - INC A ; ... - CP 32 ; ... - JP NZ,P2FL1 ; ... - - LD HL,(DMAADDR) ; Set all filename chars in FCB to space - INC HL ; ... - LD C,' ' ; ... - XOR A ; ... -P2FL2 LD (HL),C ; ... - INC HL ; ... - INC A ; ... - CP 8+3 ; ... - JP NZ,P2FL2 ; ... - - EX DE,HL ; Get file entry pointer back in HL - - LD A,(HL) ; Obtain first char of ProDOS dirent - AND 0FH ; Mask to obtain length of the name - LD C,A ; Stash source character count in C - LD DE,(DMAADDR) ; Initialize DE as write pointer - LD A,B ; Move drive number to A - LD (DE),A ; Write drive number - LD B,0 ; Use B to count chars written -P2FL3 INC HL ; Advance source pointer - INC DE ; Advance destination pointer - LD A,C ; Get count of chars remaining - CP 0 ; If none left ... - RET Z ; We are done - LD A,B ; Get count of chars written - CP 8+3 ; If 8+3 chars have been written ... - RET Z ; We are done - LD A,(HL) ; Read character - CP '.' ; See if it is a period - JP Z,P2FS2 ; Initialize things to copy the extension - LD (DE),A ; Write character - INC B ; Increment count of chars written -P2FS1 DEC C ; Decrement count of chars remaining - JP P2FL3 ; Loop -P2FS2 LD DE,(DMAADDR) ; Destination is start of extension - INC DE ; - INC DE ; - INC DE ; - INC DE ; - INC DE ; - INC DE ; - INC DE ; - INC DE ; - LD B,8 ; 8 chars have been written - JP P2FS1 ; Jump back into the read-write loop - -; Read 512 byte block of directory -; Used by F_SFIRST and F_SNEXT -; Trashes HL + registers trashed by F_READ (best to assume all of them!) -; Returns A=0 for success, A=0FFH on error -RDDIRBLK LD HL,(DMAADDR) ; Save existing DMA address - PUSH HL ; ... - - ; Read first 512 byte block of directory - LD DE,DFCB ; Use this FCB to open the directory - LD HL,DIRBUF1 ; Set DMAADDR to point to DIRBUF1 - LD (DMAADDR),HL ; ... - CALL F_READ ; Read first record of directory - CP 0 ; See if there was an error - JP NZ,RDBS1 ; If so, quit with error code - - LD DE,DFCB ; Use this FCB to open the directory - LD HL,DIRBUF2 ; Set DMAADDR to point to DIRBUF2 - LD (DMAADDR),HL ; ... - CALL F_READ ; Read second record of directory - CP 0 ; See if there was an error - JP NZ,RDBS1 ; If so, quit with error code - - LD DE,DFCB ; Use this FCB to open the directory - LD HL,DIRBUF3 ; Set DMAADDR to point to DIRBUF3 - LD (DMAADDR),HL ; ... - CALL F_READ ; Read third record of directory - CP 0 ; See if there was an error - JP NZ,RDBS1 ; If so, quit with error code - - LD DE,DFCB ; Use this FCB to open the directory - LD HL,DIRBUF4 ; Set DMAADDR to point to DIRBUF4 - LD (DMAADDR),HL ; ... - CALL F_READ ; Read fourth record of directory - CP 0 ; See if there was an error - JP NZ,RDBS1 ; If so, quit with error code - - XOR A ; Return code for success - JP RDBS2 ; Successful return - -RDBS1 LD A,0FFH ; Error return code - -RDBS2 POP HL ; Reset DMA address as we found it - LD (DMAADDR),HL ; ... - RET - -; Match FCBs -; Used by CHKDIRENT -; DE is the address of the FCB describing the file to look for -; Compare with FCB at DMAADDR already created by PATH2FCB -; Returns A=0 if entry matches, A=FFH if no match -; Trashes A,BC,DE,HL -MATCHFCB INC DE ; Skip over drive byte in FCB - LD HL,(DMAADDR) ; Will read FCB at DMAADDR pointer - INC HL ; Skip over drive byte in FCB - LD C,0 ; Initialize character counter -MFL1 LD A,(DE) ; Load byte of search pattern - - CP '?' ; Is it '?' wildcard? - JP Z,MFS1 ; If so, automatic char match - LD B,(HL) ; Load byte of match candidate - - CP B ; See if the characters match - JP NZ,MFS2 ; If not, then no match -MFS1 INC DE ; Advance source pointer - INC HL ; Advance match candidate pointer - INC C ; Increment counter - LD A,8+3 ; Compare character counter - CP C ; ... - JP NZ,MFL1 ; Loop if characters left - XOR A ; We have a match - RET ; -MFS2 LD A,0FFH ; No match - RET - -; Compare a ProDOS directory file entry to see if it matches -; Used by F_SFIRST and F_SNEXT -; DE is the address of the FCB describing the file to look for -; HL points to the first file entry in the ProDOS directory -; Returns A=0 if entry matches, A=FFH if no match -CHKDIRENT LD B,0 ; Hardcode drive A: MATCHFCB ignores it - LD A,(HL) ; Get first byte of file entry - AND 0FH ; Mask to get the filename length - CP 0 ; If zero ... - JP Z,CDES1 ; File is deleted - no match - PUSH HL ; Preserve HL - PUSH DE ; Preserve DE - CALL PATH2FCB ; Create FCB in DMA buffer - POP DE ; Recover DE - POP HL - PUSH HL - PUSH DE - CALL MATCHFCB ; Compare search FCB w/ FCB in DMA buffer - POP DE - POP HL ; Restore HL - CP 0 ; Does it match? - JP Z,CDES2 ; If so, return -CDES1 LD A,0FFH ; No match - RET ; -CDES2 XOR A ; Match - RET - -; Search a 512 byte block of a ProDOS directory for a matching file entry -; Used by F_SFIRST and F_SNEXT -; DE is the address of the FCB describing the file to look for -; CDBPTR points to the next ProDOS file entry to parse -; CDBCOUNT is set to the number of file entries already parsed in this block -; Returns A=0 if entry matches, A=FFH if no match -CHKDIRBLK LD A,(CDBCOUNT) ; File entry counter - LD HL,(CDBPTR) ; Pointer to next file entry -CDBL1 CALL CHKDIRENT ; Match the file entry at HL - EX AF,AF' ; Stash return code for now - LD BC,FILEENTSZ ; Advance to next file entry - ADD HL,BC ; ... - LD (CDBPTR),HL ; Store the pointer - LD A,(CDBCOUNT) ; File entry counter - INC A ; Increment count of file entries - LD (CDBCOUNT),A ; Store the counter - EX AF,AF' ; Get return code back in A - CP 0 ; Was it a match? - JP Z,CDBS1 ; If so, we are done - LD A,(CDBCOUNT) ; Get the counter back - CP ENTPERBLK ; Done all of them in this block? - JP NZ,CDBL1 ; If not, loop - LD A,0FFH ; No match - RET ; -CDBS1 XOR A ; Match - RET - -; The following variables are used to preserve state between calls -CDBPTR DEFW 0000H ; Stores pointer to next file entry -CDBCOUNT DEFB 0 ; Stores file entry counter - -; Find IOBUF address for a file reference number -; Scan through FRN1, FRN2, FRN3, FRN4 to find the file reference number in A -; If found, return FRN slot# 1,2,3,4 in A, I/O buffer address in HL -; If not found, return A=0FFH -; Trashes B -GETIOADDR LD B,A ; Stash file ref number into B - LD A,(FRN1) ; Does it match FRN1? - CP B ; ... - JP Z,GIOAS1 ; ... - LD A,(FRN2) ; Does it match FRN2? - CP B ; ... - JP Z,GIOAS2 ; ... - LD A,(FRN3) ; Does it match FRN3? - CP B ; ... - JP Z,GIOAS3 ; ... - LD A,(FRN4) ; Does it match FRN4? - CP B ; ... - JP Z,GIOAS4 ; ... - LD A,0FFH ; No match, return A=0FFH - RET ; ... -GIOAS1 LD HL,IOBUF1 ; Address of I/O buf 1 -> HL - LD A,1 ; FRN slot 1 - RET -GIOAS2 LD HL,IOBUF2 ; Address of I/O buf 2 -> HL - LD A,2 ; FRN slot 2 - RET -GIOAS3 LD HL,IOBUF3 ; Address of I/O buf 3 -> HL - LD A,3 ; FRN slot 3 - RET -GIOAS4 LD HL,IOBUF4 ; Address of I/O buf 4 -> HL - LD A,4 ; FRN slot 4 - RET - -; Convert length in bytes to the number of 128 byte records -; Length in bytes is passed in HL -; Length in records is returned in A -; Only works for files whose size in multiple of 128 bytes -LEN2RECS LD A,H ; Most significant byte of length - SLA A ; Shift left to make space - LD B,A ; Stash in B for now - LD A,L ; Least significant byte of length - AND 80H ; Keep most significant bit, mask off others - SRA A ; Move to LSB (shift seven times) - SRA A ; ... - SRA A ; ... - SRA A ; ... - SRA A ; ... - SRA A ; ... - SRA A ; ... - OR B ; Leaves file length in records in A - RET - -; Convert pos in extent/recs format to a linear position in 128 byte records -; Extent number is passed in B -; Records within the extent is passed in A -; Returns the length in records in HL - HL = (B*128)+A -EXRC2RECS LD L,B ; Extent number in LSB of HL - LD H,0 ; ... - ADD HL,HL ; Shift left seven times - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - LD B,0 ; Put recs in this extent in BC - LD C,A ; ... - ADD HL,BC ; Now we have total offset in records - RET - -; Convert random record number of 128 byte records to length in bytes -; Length in records is passed in HL -; Returns the length in bytes in HL -RRN2LEN ADD HL,HL ; Shift left seven times - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - ADD HL,HL ; ... - RET - -; Convert position in terms of random record number to extent/recs -; Length in records in passed in HL -; Returns extent number in B and records within extent in A -RECS2EXRC SLA H ; 7 MS-bits of extent number - BIT 7,L ; See if MS-bit is set - JP NZ,R2ERS1 ; If set ... - INC H ; ... set LSB of extent number -R2ERS1 LD B,H ; Return extent in B - LD A,L ; Now for the recs in the extent - AND 7FH ; Just need to mask out MS-bit - RET - -; Convert pos in extent/recs format to a linear position in bytes -; Extent number is passed in B -; Records within the extent is passed in A -; Returns the length in bytes in HL - HL = ((B*128)+A)*128 -EXRC2LEN CALL EXRC2RECS ; Does most of the work - CALL RRN2LEN ; Does the rest! - RET - -; Convert value in HL into an HEX ASCII string, pointed to by DE -; Courtesy of http://map.grauw.nl/sources/external/z80bits.html#5.2 -; Trashes A -NUM2HEX LD A,H ; - CALL N2H1 ; - LD A,H ; - CALL N2H2 ; - LD A,L ; - CALL N2H1 ; - LD A,L ; - JR N2H2 ; -N2H1 RRA ; - RRA ; - RRA ; - RRA ; -N2H2 OR 0F0H ; - DAA ; - ADD A,0A0H ; - ADC A,40H ; - LD (DE),A ; - INC DE ; - RET - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; Additional private scratch space for BDOS -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; ProDOS Parameter Lists -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Parameter list for ProDOS CREATE call -FMMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0C0H ; ProDOS CREATE call - DEFW FMMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FMMLIPL DEFB 7 ; ProDOS PL: Seven parameters -FMMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: Pointer to path in 6502 addr -FMMLIA DEFB 0C3H ; ProDOS PL: Access (0C3H full access) -FMMLIT DEFB 0 ; ProDOS PL: File type (0 means typeless) -FMMLIAT DEFW 0000H ; ProDOS PL: Aux file type (always 0000H) -FMMLIS DEFB 1 ; ProDOS PL: Storage type (1 for file) -FMMLICD DEFW 0000H ; ProDOS PL: Create date (always 0000H) -FMMLICT DEFW 0000H ; ProDOS PL: Create time (always 0000H) - -; Parameter list for ProDOS DESTROY call -FDMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0C1H ; ProDOS DESTROY call - DEFW FDMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FDMLIPL DEFB 1 ; ProDOS PL: Seven parameters -FDMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: Pointer to path in 6502 addr - -; Parameter list for ProDOS RENAME call -FRNMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0C2H ; ProDOS RENAME call - DEFW FRNMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FRNMLIPL DEFB 2 ; ProDOS PL: Two parameters -FRNMLIP1 DEFW PATHBUF+OFFSET ; ProDOS PL: Pointer to path in 6502 addr -FRNMLIP2 DEFW PATHBUF2+OFFSET ; ProDOS PL: Pointer to path in 6502 addr - -; Parameter list for ProDOS GET_FILE_INFO call -FSMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0C4H ; ProDOS GET_FILE_INFO call - DEFW FSMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FSMLIPL DEFB 0AH ; ProDOS PL: Ten parameters -FSMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: Pointer to path in 6502 addr -FSMLIAC DEFB 0 ; ProDOS PL: Access -FSMLIT DEFB 0 ; ProDOS PL: File type -FSMLIAT DEFW 0000H ; ProDOS PL: Aux type -FSMLIS DEFB 1 ; ProDOS PL: Storage type -FSMLIBU DEFW 0000H ; ProDOS PL: Blocks used -FSMLIMD DEFW 0000H ; ProDOS PL: Modification date -FSMLIMT DEFW 0000H ; ProDOS PL: Modification time -FSMLICD DEFW 0000H ; ProDOS PL: Create date -FSMLICT DEFW 0000H ; ProDOS PL: Create time - -; Parameter list for ProDOS OPEN call -FOMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0C8H ; ProDOS OPEN call - DEFW FOMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FOMLIPL DEFB 3 ; ProDOS PL: Three parameters -FOMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: pointer to path in 6502 addr -FOMLII DEFW 0000H ; ProDOS PL: pointer to IO buffer -FOMLIN DEFB 0 ; ProDOS PL: File reference number - -; Parameter list for ProDOS READ call -FRMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0CAH ; ProDOS READ call - DEFW FRMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FRMLIPL DEFB 4 ; ProDOS PL: Four parameters -FRMLIN DEFB 0 ; ProDOS PL: File reference number -FRMLIDB DEFW 0000H ; ProDOS PL: Data buffer -FRMLIRC DEFW 128 ; ProDOS PL: Request count (bytes to read) -FRMLITC DEFW 0000H ; ProDOS PL: Number of bytes transferred - -; Parameter list for ProDOS WRITE call -FWMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0CBH ; ProDOS WRITE call - DEFW FWMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FWMLIPL DEFB 4 ; ProDOS PL: Four parameters -FWMLIN DEFB 0 ; ProDOS PL: File reference number -FWMLIDB DEFW 0000H ; ProDOS PL: Data buffer -FWMLIRC DEFW 128 ; ProDOS PL: Request count (bytes to read) -FWMLITC DEFW 0000H ; ProDOS PL: Number of bytes transferred - -; Parameter list for ProDOS CLOSE call -FCMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0CCH ; ProDOS CLOSE call - DEFW FCMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FCMLIPL DEFB 1 ; ProDOS PB: One parameter -FCMLIN DEFB 0 ; ProDOS PB: File reference number - -; Parameter list for ProDOS FLUSH call -FLMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0CDH ; ProDOS FLUSH call - DEFW FLMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -FLMLIPL DEFB 1 ; ProDOS PL: One parameter -FLMLIN DEFB 0 ; ProDOS PL: File ref num (0 = all files) - -; Parameter list for ProDOS SET_MARK call -SMMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0CEH ; ProDOS SET_MARK call - DEFW SMMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -SMMLIPL DEFB 2 ; ProDOS PL: Two parameters -SMMLIN DEFB 0 ; ProDOS PL: File reference number -SMMLIP1 DEFB 0 ; ProDOS PL: Position (LSB) -SMMLIP2 DEFB 0 ; ProDOS PL: Position -SMMLIP3 DEFB 0 ; ProDOS PL: Position (MSB) - -; Parameter list for ProDOS SET_EOF call -SEMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0D0H ; ProDOS SET_EOF call - DEFW SEMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -SEMLIPL DEFB 2 ; ProDOS PL: Two parameters -SEMLIN DEFB 0 ; ProDOS PL: File reference number -SEMLIE1 DEFB 0 ; ProDOS PL: EOF position (LS-byte) -SEMLIE2 DEFB 0 ; ProDOS PL: EOF position -SEMLIE3 DEFB 0 ; ProDOS PL: EOF position (MS-byte) - -; Parameter list for ProDOS GET_EOF call -GEMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code - DEFB 0D1H ; ProDOS GET_EOF call - DEFW GEMLIPL+OFFSET ; Pointer to parm list in 6502 addr space - DEFB 60H ; RTS in 6502 code -GEMLIPL DEFB 2 ; ProDOS PL: Two parameters -GEMLIN DEFB 0 ; ProDOS PL: File reference number -GEMLIE1 DEFB 0 ; ProDOS PL: EOF position (LS-byte) -GEMLIE2 DEFB 0 ; ProDOS PL: EOF position -GEMLIE3 DEFB 0 ; ProDOS PL: EOF position (MS-byte) - -; FCB used for opening ProDOS directory corresponding to drive -DFCB ; File control block for directory -DFCBDRV DEFB 00H ; FCB Drive (0 current, 1 A:, 2 B: etc) -DFCBNAM DEFM ' ' ; FCB filename and extension (all spaces) -DFCBEX DEFB 00H ; FCB extent field -DFCBS1 DEFB 00H ; FCB S1 field -DFCBS2 DEFB 00H ; FCB S2 field -DFCBRC DEFB 00H ; FCB RC field -DFCBMAP DEFS 16 ; Map of blocks in file -DFCBSR DEFB 0 ; FCB seq record number -DFCBRR DEFB 0,0,0 ; FCB rand record number - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; End of ProDOS Parameter Lists -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -; Drive parameter block (CP/M 2.2 format) -; See Johnson-Laird Pg 33-34 -DPB DEFW 32 ; # 128 byte records per track (for Disk II) - DEFB 7 ; Block shift (16384 byte allocation blocks) - DEFB 127 ; Block mask (16384 byte allocation blocks) - DEFB 7 ; Extent mask - DEFW 2047 ; # allocation blocks on disk (32MB) - DEFW 1023 ; # directory entries - DEFB 0 ; Directory allocation bitmap byte 1 - DEFB 0 ; Directory allocation bitmap byte 2 - DEFW 0 ; Checksum vector size - DEFW 0 ; # of reserved tracks - -; Fake allocation vector (2048 allocation blocks / 8 = 256 bytes) -ALLOCVEC DEFS 256 ; TODO: This is a waste of memory - ; Get rid of it? - -; 64 byte buffer for storing a file path as a Pascal style string -PATHBUF -PATHLEN DEFB 0 -PATH DEFS 64 - -; 64 byte buffer for storing a second file path as a Pascal style string -PATHBUF2 -PATHLEN2 DEFB 0 -PATH2 DEFS 64 - -; Record file reference numbers for each I/O buffer -; Or 0 if no file is using the buffer -FRN1 DEFB 0 -FRN2 DEFB 0 -FRN3 DEFB 0 -FRN4 DEFB 0 - -; Buffer for printing hex numbers to console -HEXBUF DEFB 0,0,0,0,'$' - -; 512 byte buffer for reading directories (used by F_SFIRST and F_SNEXT) -DIRBUF -DIRBUF1 DEFS 128 -DIRBUF2 DEFS 128 -DIRBUF3 DEFS 128 -DIRBUF4 DEFS 128 - -; Four 1024 byte ProDOS I/O buffers -; These must start on a page boundary -; ProDOS occupies the space from $BF00 up (in 6502 addresses) -; Also ProDOS has one buffer from $BB00-$BEFF I think. (Check with John Brooks!) -; IOBUF1 $AB00-$ADFF = starts at 9B00H for Z80 -; IOBUF2 $AF00-$B2FF -; IOBUF3 $B300-$B6FF -; IOBUF4 $B700-$BAFF - - ORG 7000H ; Set to 7000H by experiment ... -IOBUF1 DEFS 1024 - ORG 7400H -IOBUF2 DEFS 1024 - ORG 7800H -IOBUF3 DEFS 1024 - ORG 7C00H -IOBUF4 DEFS 1024 - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - diff --git a/zapple2.po b/zapple2.po index a2f27cddff6ab58a32477d511485f12a40cfef70..f486f8d36e4a8fe58b98675601894a862fc411d3 100644 GIT binary patch delta 4370 zcmbtX|8E;-89zHte3zwN#{`|GF}+3F7tl1pM5pbCNh?EzNufxTspYqbO``Av{{U2% z(q;&xL!eBt_ywI(r}LGzIBiv@P1O z(k2~eBS5V`#hiL@#yF)qoc3Hp9=+^9)CV`Y44kYaOj0SI|ZT4zXXMs4t{_C z58vANgKxjO_vM3vAcRIkL&D)N!Z%}gXcS<5SI3{|e|GSh9p0g5#$WIM^4G#o;^VGE zFNB{A3Qrw;3r>IQ?E|mwg>!;1a3T~C-obCi?l&)t_MZqo|8&m`z8CIS`UApm0>X2% z<-{&9L;9|k6Tu6C;NJr02WNwQf)GA_ZRpq6h63;j!lw^DA^7yeX8=Co#I+&u7h{pf zF7{ua7#ClU$VbIv%+I1~oJ3E}(2VPR&}S#G!7-X(~##kX+1gP03_DuFA6{ zXO}IvW;cml1+}(bD3a`73S^~It%B{GKBwy@KM~Jl(8HW4>xxn=`KACdH^c8CWmhQq zq*kw!6^x>e&QfOHy;Exwt5R_kNHBwePddC9V zEp=8=L8l73AXraNu9#Ff?i%1^=2Q=u=m8hHz^h(ny6R>C#SCvy_8{i6kMZ;@sVC!L z=SogDbJNU$82BY?XO;k%vRi9Va;%n^%OIO!B1O&SQ(Huk%%@e<5m1cqh0@j6&{((bafe59zpAxOilO!9V%o`agUTl`ueZ~*t*VtTwQ-CoZ|HHtb9w*C7c^PNTutB#fC zhZRzWidGbbdnOl4idrzQ_uzBwHf^lbDeECtoN%vm@P+qy>``wZThOdZFD8{=9T&G=fG zgnR3W3r5;ByH+P5aZSQdlRRX-07WrNZgy&}f~K$=3dU_r{&ngyKOhTGD;*$IYz$NX z9+MV<8!7St@`jn7)44d6dsv#v6^d!@uZd)2QeY52!b_s`S}6Q3OqC!1^yi6vLsBY` z2=0_V%gPwLS6AKG|Ci8BeN*TTTHQW$UXiALyOjDf_Q!&Zy}U(^AyF(#3<^Nj&)eYe zHRpL4LFdkKeW@IrO4aQ))C;?2ez>@p>Xk>kQ~pvJN~2pJ%EDYWpDPrM$ZvzvA+h^Z z4N7|t6N3{SmaJD$$aBDu9xF!U2_V76Hf{4aGsJ2Wn3XNtv79v+Rtv@J5ESPdl7+!n zv+A{b?=MTImIqg4xaVdCX9iXWQV?gL9Br<;cW?%^U6^gFK67F-^75#21UQ1mfJ&x; znwD_#%vJ7MO`vF;n47t{rymOt<+7JIoR@y3<1OfEWI42^)3QSw6vivkVH+y8Vbz+< zCC(gpqnt0yQW5Oq{Mot@y*}kr0b91PAVY`vvB6aEM*$aZkO6u66@&To9=!Wk)CVnZ zYDUB4oyzTcUF#W@aTfVjH;dvA+vFOIxzY_hge}WvnSXw>;NjyNO4fH-?qzGTY&Ac0 zA-`5-63T|R7`N!P+ZHAtko;FRH<--Hu)I)akM+p^86ZE7n!HPTC`Av-*EbSe}a|Q=KdpGNsgpS$HYlt`Bv*qy29KHa^qH8%W zvIXEQ4xELJlRcq7ZG>kGRL+ak*DYgGktzY}-eIUDXuYNK&3Ka!8`fYp#=tg4!>$JA z7C7N#P)H?BaGwxwtVYrY^%s zePkS<5#(SWY8y9yAVkZB)sX!hU;_#eW{M+VrAL?PzdE=Ev-RJHlo%umKM^ozCC6&E z5g-Gv;*@)2y7-WX*@m65eY$YOdHVqP3){k@^Q9nSn3WJx_?9I!-OCojKPOj_1AWq- z#J-U9r$D6IFLj>9X;doc1;64Ka#?~^4?_*|7kMo#-I(}T>I{0@A9M=*Zj8y=H^v4u zG8Wc^F;R<+NvbeC@CUIvU<9k-stEt3DJiQN|C|!DhmFdx5F>|Uq!DXLWO<$ZBsRQ1 zc6KeM1U2OejokBIA7igY4IpR3_@Df4ok$w_eM}K_@&#@9jhKLT#>5-)^Z;qBXGG)f zh;|t~iH(KHcVd7a(dN64+Uf3BCi!^tV^6BlO_H6PDQj1km{j~7Nu3>6RGE>Hie#h? zT~U#MR7OBy73mLt?g<~=aAPBVr(?pb01xv4Z6qYDKYstdfRDLd+DJf{8psMp|B)k* zjcmYpYO3+w7pKCf#Hd8x(Z<5>izg)U$XH_}8#DqV**@d(mxRB5y7J!*^%f=4z33#&J2bUp_d2${i9Rg92)))F1mXQ delta 646 zcmaJ-OK1~O6rFjQN#++x#U^N}yeza*ikM);F8$z2P+Fz9(F(e8E3QO4+N!w7LPqjd zVh{6QZT)U{Ca+5*n2$-!D7yI6;|4VC@XT|jd5ej^mOsdH zJdXk$W;+JhAU*Zq;dBEFc4PM#8tt8>o01QBQ4p{<&UE-VoG)H1Eq#jTVc9ZF9h%)dP7b(f zn9jn^p6J;U|2f03C#mdJj(tVqlMQF7J#1?kUHQn{X%g_{<8?N%&Q-XLZ(5~V(>K3w p;Vb`0^l|;@nx8y|i5eT?{D_PQ{m2&)XylIwYT^htnK&+-{{w@zEu{be