diff --git a/SOFTCARD80.ASM#040000 b/SOFTCARD80.ASM#040000 index ef908b1..bae020d 100644 --- a/SOFTCARD80.ASM#040000 +++ b/SOFTCARD80.ASM#040000 @@ -60,9 +60,10 @@ RVEC7 DEFW 0000H ; Restart vector 7 DMAADDR DEFW 0080H ; DMA address defaults to FILEBUF (0080H) LOGVEC DEFW 0000H ; Vector of logged in drives ROVEC DEFW 0000H ; Vector of read-only drives -USERNUM DEFB 00H ; User number +USERNUM DEFB 00H ; User number TODO: This goes elsewhere ; End of private, implementation dependent space +;TODO: There are two FCBS and the address here is wrong ORG 0060H ; Standard addr of 32 byte FCB FCB1 ; File control block #1 FCB1DRV DEFB 00H ; FCB Drive (0 current, 1 A:, 2 B: etc) @@ -85,37 +86,35 @@ FILEBUF DEFS 128 ; Command args go here too (Pascal string) ; Print signon message using C_WRITESTR PROGSTRT LD DE,WELCOME ; Address of string - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; ; Print the alphabet using C_WRITE - LD B,'A' + LD B,'A' ; First character L1 LD E,B ; Character to print - - LD C,02H ; C_WRITE call + LD C,B_C_WRITE ; PUSH BC ; Preserve B (and C) - CALL BDOS ; CP/M BDOS call + CALL BDOS ; POP BC ; Restore B (and C) - - INC B - LD A,'Z' - CP B - JP Z,S1 - JP L1 + INC B ; + LD A,'Z' ; Last character + CP B ; + JP Z,S1 ; + JP L1 ; ; Loop until there is a keystroke waiting using C_STAT -S1 LD C,0BH ; C_STAT call - CALL BDOS ; CP/M BDOS call +S1 LD C,B_C_STAT ; + CALL BDOS ; CP 0 ; Anything? JR Z,S1 ; If not, loop ; Print a couple of asterisks LD E,'*' ; - LD C,02H ; C_WRITE call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRITE ; + CALL BDOS ; LD E,'*' ; - LD C,2 ; C_WRITE call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRITE ; + CALL BDOS ; ; Create an FCB LD A,1 ; A: drive @@ -143,62 +142,104 @@ S1 LD C,0BH ; C_STAT call LD A,'P' ; Extension LD (FCB1NAM+10),A ; - ; Create a file using ProDOS MLI + ; Create and open a file using ProDOS MLI ; Creates 'A/TESTFILE.TMP' ; Directory 'A' needs to exist already LD DE,CMSG ; Address of string - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; LD DE,FCB1 ; Default FCB address - LD C,16H ; F_MAKE call - CALL BDOS ; CP/M BDOS call + LD C,B_F_MAKE ; + CALL BDOS ; CALL CHECKOK - ; Open the file just created + ; Write to the file (two 128 byte records) - LD DE,OMSG ; Address of string - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD DE,WMSG ; Address of string + LD C,B_C_WRTSTR ; + CALL BDOS ; LD DE,FCB1 ; Default FCB address - LD C,0FH ; F_OPEN call - CALL BDOS ; CP/M BDOS call + LD C,B_F_WRITE ; + CALL BDOS ; + + CALL CHECKOK + + LD DE,FCB1 ; Default FCB address + LD C,B_F_WRITE ; + CALL BDOS ; CALL CHECKOK ; Close the file LD DE,CLMSG ; Address of string - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; LD DE,FCB1 ; Default FCB address - LD C,10H ; F_CLOSE call - CALL BDOS ; CP/M BDOS call + LD C,B_F_CLOSE ; + CALL BDOS ; + + CALL CHECKOK + + ; Open the file + + LD DE,OMSG ; Address of string + LD C,B_C_WRTSTR ; + CALL BDOS ; + + LD DE,FCB1 ; Default FCB address + LD C,B_F_OPEN ; + CALL BDOS ; + + CALL CHECKOK + + ; Read from the file + + LD DE,RMSG ; Address of string + LD C,B_C_WRTSTR ; + CALL BDOS ; + + LD DE,FCB1 ; Default FCB address + LD C,B_F_READ ; + CALL BDOS ; + + CALL CHECKOK + + ; Close the file + + LD DE,CLMSG ; Address of string + LD C,B_C_WRTSTR ; + CALL BDOS ; + + LD DE,FCB1 ; Default FCB address + LD C,B_F_CLOSE ; + CALL BDOS ; CALL CHECKOK ; Delete the file - LD DE,DMSG ; Address of string - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call - - LD DE,FCB1 ; Default FCB address - LD C,13H ; F_DELETE call - CALL BDOS ; CP/M BDOS call - - CALL CHECKOK +; LD DE,DMSG ; Address of string +; LD C,B_C_WRTSTR ; +; CALL BDOS ; +; +; LD DE,FCB1 ; Default FCB address +; LD C,B_F_DELETE ; +; CALL BDOS ; +; +; CALL CHECKOK ; Read keyboard and echo to screen C_READ, C_WRITE -L2 LD C,1 ; C_READ call - CALL BDOS ; CP/M BDOS call +L2 LD C,B_C_READ ; + CALL BDOS ; LD E,A ; Prepare to echo keystroke - LD C,2 ; C_WRITE call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRITE ; + CALL BDOS ; JP L2 ; Forever and ever ; Check an MLI call was successful and print out message accordingly @@ -206,8 +247,8 @@ CHECKOK LD A,(AREG) ; Look at the return code CP 0 ; Success? JP Z,SUCC ; LD DE,FAILMSG1 ; Fail message - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; LD L,A ; Copy to HL for NUM2HEX LD H,0 ; ... LD DE,HEXBUF ; Generate hex string to HEXBUF @@ -215,15 +256,15 @@ CHECKOK LD A,(AREG) ; Look at the return code LD A,0FFH ; 0FFH for error LD L,A ; Return code in L also LD DE,HEXBUF+2 ; Write hex value to console - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; LD DE,FAILMSG2 ; Fail message - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; RET ; SUCC LD DE,SUCCMSG ; Success message - LD C,09H ; C_WRITESTR call - CALL BDOS ; CP/M BDOS call + LD C,B_C_WRTSTR ; + CALL BDOS ; RET WELCOME DEFB 13 @@ -231,15 +272,23 @@ WELCOME DEFB 13 DEFB 13, '$' CMSG DEFB 13 - DEFM 'Creating A/TESTFILE.TMP' + DEFM 'Creating & opening A/TESTFILE.TMP' + DEFB 13, '$' + +WMSG DEFB 13 + DEFM 'Writing record to A/TESTFILE.TMP' + DEFB 13, '$' + +CLMSG DEFB 13 + DEFM 'Closing A/TESTFILE.TMP' DEFB 13, '$' OMSG DEFB 13 DEFM 'Opening A/TESTFILE.TMP' DEFB 13, '$' -CLMSG DEFB 13 - DEFM 'Closing A/TESTFILE.TMP' +RMSG DEFB 13 + DEFM 'Reading record from A/TESTFILE.TMP' DEFB 13, '$' DMSG DEFB 13 @@ -256,28 +305,31 @@ FAILMSG2 DEFM ')' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Implementation of CP/M STYLE BDOS -; Function to invoke is passed in C -; C=00H C_TERMCPM System reset -; C=01H C_READ Console read -; C=02H C_WRITE Console write -; C=07H GET_IOB Get IOBYTE -; C=08H SET_IOB Set IOBYTE -; C=09H C_WRITESTR Console write string -; C=0BH C_STAT Console status -; C=0CH S_BDOSVER Return version number -; C=0DH DRV_ALLRESET Reset disks -; C=0EH DRV_SET Select disk -; C=0FH F_OPEN Open file -; C=10H F_CLOSE Close file (IN PROGRESS) -; C=13H F_DELETE Delete file -; C=16H F_MAKE Create file (IN PROGRESS) -; C=17H DRV_LOGVEC Return bitmap of logged-in drives -; C=19H DRV_GET Return current drive -; C=1AH F_DMAOFF Set DMA address -; C=1CH DRV_SETRO Software write-protect current drive -; C=1DH DRV_ROVEC Return bitmap of read-only drives -; C=20H F_USERNUM Get/set user number -; C=25H DRV_RESET Selectively reset disk drives +; Function to invoke is passed in C, as follows: +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +B_C_TERMCPM EQU 00H ; System reset +B_C_READ EQU 01H ; Console read +B_C_WRITE EQU 02H ; Console write +B_GET_IOB EQU 07H ; Get IOBYTE +B_SET_IOB EQU 08H ; Set IOBYTE +B_C_WRTSTR EQU 09H ; Console write string +B_C_STAT EQU 0BH ; Console status +B_S_BDOSVER EQU 0CH ; Return version number +B_DRV_ALLRST EQU 0DH ; Reset disks +B_DRV_SET EQU 0EH ; Select disk +B_F_OPEN EQU 0FH ; Open file +B_F_CLOSE EQU 10H ; Close file +B_F_DELETE EQU 13H ; Delete file +B_F_READ EQU 14H ; Read file +B_F_WRITE EQU 15H ; Write file +B_F_MAKE EQU 16H ; Create and open file +B_DRV_LOGVEC EQU 17H ; Return bitmap of logged-in drives +B_DRV_GET EQU 19H ; Return current drive +B_F_DMAOFF EQU 1AH ; Set DMA address +B_DRV_SRO EQU 1CH ; Software write-protect current drive +B_DRV_ROVEC EQU 1DH ; Return bitmap of read-only drives +B_F_USERNUM EQU 20H ; Get/set user number +B_DRV_RESET EQU 25H ; Selectively reset disk drives ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ORG BDOSADDR @@ -286,6 +338,7 @@ BDOSINIT LD SP,STCKTOP ; Initialize SP LD A,0 ; LD (IOBYTE),A ; Initialize IOBYTE LD (CURDRV),A ; Drive A: + LD (FILEBUF),A ; Zero chars in command tail LD (FRN1),A ; Initialize FRNs to zero LD (FRN2),A ; ... LD (FRN3),A ; ... @@ -330,8 +383,8 @@ BDOSVEC DEFW C_TERMCPM ; C=00H DEFW UNIMP ; C=11H (F_SFIRST) DEFW UNIMP ; C=12H (F_SNEXT) DEFW F_DELETE ; C=13H - DEFW UNIMP ; C=14H (F_READ) - DEFW UNIMP ; C=15H (F_WRITE) + DEFW F_READ ; C=14H + DEFW F_WRITE ; C=15H DEFW F_MAKE ; C=16H DEFW UNIMP ; C=17H (F_RENAME) DEFW DRV_LOGVEC ; C=18H @@ -520,17 +573,17 @@ FOS5 LD (FOIOB),A ; Record the buffer index in local var CP 3 ; Is it 3? ... JP Z,FOS8 ; ... yes JP FOS9 ; Must be 4 -FOS6 LD A,(FOMLIN) ; - LD (FRN1),A ; +FOS6 LD A,(FOMLIN) ; IOBUF1: Store file ref number in FRN1 + LD (FRN1),A ; ... JP FOS10 ; -FOS7 LD A,(FOMLIN) ; - LD (FRN2),A ; +FOS7 LD A,(FOMLIN) ; IOBUF2: Store file ref number in FRN2 + LD (FRN2),A ; ... JP FOS10 ; -FOS8 LD A,(FOMLIN) ; - LD (FRN3),A ; +FOS8 LD A,(FOMLIN) ; IOBUF3: Store file ref number in FRN3 + LD (FRN3),A ; ... JP FOS10 ; -FOS9 LD A,(FOMLIN) ; - LD (FRN4),A ; +FOS9 LD A,(FOMLIN) ; IOBUF4: Store file ref number in FRN4 + LD (FRN4),A ; ... JP FOS10 ; FOS10 LD A,0 ; Success LD L,A ; Copy to L @@ -553,16 +606,21 @@ FOIOB DEFB 0 ; Local variable to record IOBUF idx ; 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 ... +F_CLOSE LD H,D ; Pointer to FCB ... LD L,E ; ... into HL LD BC,14 ; Offset to S2 field (reserved field) ADD HL,BC ; Compute address LD A,(HL) ; Obtain file reference num from FCB S2 + 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 + + ; + ; TODO - SET THE APPROPRIATE FRN[1234] TO ZERO TO FREE BUFFER + ; + LD L,A ; Return in L also RET FCERR LD A,0FFH ; 0FFH for error @@ -597,6 +655,87 @@ FDMLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code FDMLIPL DEFB 1 ; ProDOS PL: Seven parameters FDMLIP DEFW PATHLEN+OFFSET ; ProDOS PL: Pointer to path in 6502 addr +; 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 LD H,D ; Pointer to FCB ... + LD L,E ; ... into HL + LD BC,14 ; Offset to S2 field (reserved field) + ADD HL,BC ; Compute address + LD A,(HL) ; Obtain file reference num from FCB S2 + LD (FRMLIN),A ; Store in parameter list + CALL GETIOADDR ; Get I/O address + CP 0FFH ; See if it was an error + JP Z,FRERR ; If so, abort + 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 + CP 0 ; See if there was an error + JP NZ,FRERR ; Handle error + LD L,A ; Return code in L also + RET ; Done +FRERR LD A,0FFH ; TODO: All errors are 0FFH for now + LD L,A ; Return code in L aslo + RET ; Done (error) + +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 + +; 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 LD H,D ; Pointer to FCB ... + LD L,E ; ... into HL + LD BC,14 ; Offset to S2 field (reserved field) + ADD HL,BC ; Compute address + LD A,(HL) ; Obtain file reference num from FCB S2 + LD (FWMLIN),A ; Store in parameter list + CALL GETIOADDR ; Get I/O address + CP 0FFH ; See if it was an error + JP Z,FWERR ; If so, abort + LD BC,OFFSET ; Convert to 6502 address + ADD HL,BC ; ... + LD (FWMLIDB),HL ; Store I/O buffer address in parm list + +; DEBUG ------------------------------------------- +; LD DE,HEXBUF ; Generate hex string to HEXBUF +; CALL NUM2HEX ; ... +; LD DE,HEXBUF ; Write hex value to console +; LD C,B_C_WRTSTR ; +; CALL BDOS +; END DEBUG --------------------------------------- + + LD HL,FWMLI ; Pass address of 6502 JSR instruction + CALL PRODOS ; Invoke ProDOS MLI + CP 0 ; See if there was an error + JP NZ,FWERR ; Handle error + LD L,A ; Return code in L also + RET ; Done +FWERR LD A,0FFH ; TODO: All errors are 0FFH for now + LD L,A ; Return code in L aslo + RET ; Done (error) + +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 + ; Create (and open) file ; DE is the address of the FCB describing the file to create ; Returns error codes in A and L: @@ -606,9 +745,7 @@ F_MAKE CALL MAKEPATH ; Populate PATHLEN and PATH 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) - LD A,0 ;;; TEMP DEBUG - SHOULD CALL F_OPEN ABOVE ;;; - LD L,A ; Return code in L also + CALL F_OPEN ; Open the file using same FCB (DE ptr) RET FMERR LD A,0FFH ; 0FFH for error LD L,A ; Return code in L also @@ -743,6 +880,36 @@ MPS3 ; EXTENSION LD (PATHLEN),A ; ... RET +; 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 A=0, HL=I/O buffer address +; If not found, return A=0FFH +GETIOADDR LD A,B ; Stash A + 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,(FRN3) ; Does it match FRN4? + CP B ; ... + JP Z,GIOAS3 ; ... + LD A,0FFH ; No match, return A=0FFH + RET ; ... +GIOAS1 LD HL,IOBUF1 ; Address of I/O buf 1 -> HL + JP GIOAS5 ; ... +GIOAS2 LD HL,IOBUF2 ; Address of I/O buf 2 -> HL + JP GIOAS5 ; ... +GIOAS3 LD HL,IOBUF3 ; Address of I/O buf 3 -> HL + JP GIOAS5 ; ... +GIOAS4 LD HL,IOBUF4 ; Address of I/O buf 4 -> HL + JP GIOAS5 ; ... +GIOAS5 LD A,0 ; Success! + 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 NUM2HEX LD A,H @@ -793,10 +960,13 @@ HEXBUF DEFB 0,0,0,0,'$' ; IOBUF4 $B700-$BAFF ORG 7000H ; Set to 7000H by experiment ... -IOBUF1 DEFS 1024 ; ... we need BASIC.SYSTEM for now since we use EXEC! -IOBUF2 DEFS 1024 -IOBUF3 DEFS 1024 -IOBUF4 DEFS 1024 +IOBUF1 DEFM 'Mary had a little lamb' + ORG 7400H +IOBUF2 DEFM 'His fleece was white as snow' + ORG 7800H +IOBUF3 DEFM 'And everywhere that Mary went' + ORG 7C00H +IOBUF4 DEFM 'That sheep was sure to go' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/SOFTCARD80.BIN#041000 b/SOFTCARD80.BIN#041000 index 4618428..bafa957 100644 Binary files a/SOFTCARD80.BIN#041000 and b/SOFTCARD80.BIN#041000 differ diff --git a/zapple2.po b/zapple2.po index 45883a2..d782d8b 100644 Binary files a/zapple2.po and b/zapple2.po differ