diff --git a/src/inc/fileio.plh b/src/inc/fileio.plh index 46c3841..3cf4a8f 100644 --- a/src/inc/fileio.plh +++ b/src/inc/fileio.plh @@ -37,14 +37,23 @@ import fileio // // File functions // - predef getpfx, setpfx, getfileinfo - predef open, close, read, write, create, destroy, newline - // - // Block level I/O functions - // - predef readblock, writeblock + struc t_fileio + word getpfx + word setpfx + word getfileinfo + word open + word close + word read + word write + word create + word destroy + word newline + word readblock + word writeblock + end + word fileio // // Globally accessible error code // byte perr -end \ No newline at end of file +end diff --git a/src/libsrc/fileio.pla b/src/libsrc/fileio.pla index 91860c6..96d2c29 100644 --- a/src/libsrc/fileio.pla +++ b/src/libsrc/fileio.pla @@ -1,12 +1,61 @@ include "inc/cmdsys.plh" // -// ProDOS error code +// CFFA1 addresses. +// +const CFFA1Dest = $00 +const CFFA1FileName = $02 +const CFFA1OldName = $04 +const CFFA1FileType = $06 +const CFFA1AuxType = $07 +const CFFA1FileSize = $09 +const CFFA1EntryPtr = $0B +// +// All our file I/O routines +// +struc t_fileio + word getpfx + word setpfx + word getfileinfo + word open + word close + word read + word write + word create + word destroy + word newline + word readblock + word writeblock +end +predef a1getpfx, a1setpfx, a1getfileinfo, a1open, a1close, a1read, a1write, a1create, a1destroy +predef a1newline, a13readblock, a13writeblock +predef a2getpfx, a23setpfx, a2getfileinfo, a2open, a23close, a23read, a2write, a2create, a23destroy +predef a23newline, a2readblock, a2writeblock +predef a3getpfx, a3getfileinfo, a3open, a3write, a3create +// +// Exported function table. +// +export word fileio[] +// +// Platform specific function pointers (default to Apple II). +// +word a2io[] = @a2getpfx, @a23setpfx, @a2getfileinfo, @a2open, @a23close, @a23read, @a2write, @a2create, @a23destroy +word = @a23newline, @a2readblock, @a2writeblock +word a3io[] = @a3getpfx, @a23setpfx, @a3getfileinfo, @a3open, @a23close, @a23read, @a3write, @a3create, @a23destroy +word = @a23newline, @a13readblock, @a13writeblock +word a1io[] = @a1getpfx, @a1setpfx, @a1getfileinfo, @a1open, @a1close, @a1read, @a1write, @a1create, @a1destroy +word = @a1newline, @a13readblock, @a13writeblock +// +// SOS/ProDOS error code // export byte perr // -// ProDOS routines +// ProDOS/SOS routines // -export def getpfx(path) +def a1getpfx(path) + ^path = 0 + return path +end +def a2getpfx(path) byte params[3] ^path = 0 @@ -15,7 +64,19 @@ export def getpfx(path) perr = syscall($C7, @params) return path end -export def setpfx(path) +def a3getpfx(path) + byte params[3] + + params.0 = 2 + params:1 = path + params.3 = 64 + perr = syscall($C7, @params) + return path +end +def a1setpfx(path) + return path +end +def a23setpfx(path) byte params[3] params.0 = 1 @@ -23,7 +84,11 @@ export def setpfx(path) perr = syscall($C6, @params) return path end -export def getfileinfo(path, fileinfo) +def a1getfileinfo(path, fileinfo) + perr = $01 + return perr +end +def a2getfileinfo(path, fileinfo) byte params[18] params.0 = 10 @@ -32,7 +97,22 @@ export def getfileinfo(path, fileinfo) memcpy(fileinfo, @params + 3, 15) return perr end -export def open(path, buf) +def a3getfileinfo(path, fileinfo) + byte params[6] + + params.0 = 3 + params:1 = path + params:3 = fileinfo + params.5 = 15 + perr = syscall($C4, @params) + return perr +end +def a1open(path, buf) + *CFFA1FileName = path + *CFFA1Dest = buf + return 0 +end +def a2open(path, buf) byte params[6] params.0 = 3 @@ -42,7 +122,21 @@ export def open(path, buf) perr = syscall($C8, @params) return params.5 end -export def close(refnum) +def a3open(path, access) + byte params[7] + + params.0 = 4 + params:1 = path + params.3 = 0 + params:4 = @access + params.6 = 1 + syscall($C8, @params) + return params.3 +end +def a1close(refnum) + return perr +end +def a23close(refnum) byte params[2] params.0 = 1 @@ -50,7 +144,11 @@ export def close(refnum) perr = syscall($CC, @params) return perr end -export def read(refnum, buf, len) +def a1read(refnum, buf, len) + perr = syscall($22) // This reads the entire file on CFFA + return perr +end +def a23read(refnum, buf, len) byte params[8] params.0 = 4 @@ -61,7 +159,10 @@ export def read(refnum, buf, len) perr = syscall($CA, @params) return params:6 end -export def write(refnum, buf, len) +def a1write(refnum, buf, len) + return perr +end +def a2write(refnum, buf, len) byte params[8] params.0 = 4 @@ -72,7 +173,20 @@ export def write(refnum, buf, len) perr = syscall($CB, @params) return params:6 end -export def create(path, access, type, aux) +def a3write(refnum, buff, len) + byte params[6] + + params.0 = 3 + params.1 = refnum + params:2 = buff + params:4 = len + perr = syscall($CB, @params) + return perr +end +def a1create(path, access, type, aux) + return perr +end +def a2create(path, access, type, aux) byte params[12] params.0 = 7 @@ -86,7 +200,23 @@ export def create(path, access, type, aux) perr = syscall($C0, @params) return perr end -export def destroy(path) +def a3create(path, access, type, aux) + byte params[6] + byte options[4] + + params.0 = 3 + params:1 = path + params:3 = @options + params.5 = 3 + options.0 = type + options:1 = aux + perr = syscall($C0, @params) + return perr +end +def a1destroy(path) + return perr +end +def a23destroy(path) byte params[3] params.0 = 1 @@ -94,7 +224,10 @@ export def destroy(path) perr = syscall($C1, @params) return perr end -export def newline(refnum, emask, nlchar) +def a1newline(refnum, emask, nlchar) + return perr +end +def a23newline(refnum, emask, nlchar) byte params[4] params.0 = 3 @@ -104,7 +237,11 @@ export def newline(refnum, emask, nlchar) perr = syscall($C9, @params) return perr end -export def readblock(unit, buf, block) +def a13readblock(unit, buf, block) + perr = $27 // IOERR + return perr +end +def a2readblock(unit, buf, block) byte params[6] params.0 = 3 @@ -114,7 +251,11 @@ export def readblock(unit, buf, block) perr = syscall($80, @params) return perr end -export def writeblock(unit, buf, block) +def a13writeblock(unit, buf, block) + perr = $27 // IOERR + return perr +end +def a2writeblock(unit, buf, block) byte params[6] params.0 = 3 @@ -124,5 +265,16 @@ export def writeblock(unit, buf, block) perr = syscall($81, @params) return perr end - +// +// Machine specific initialization. +// +when MACHID & $C8 + is $08 // Apple 1 + memcpy(fileio, a1io, t_fileio) + break + is $C0 // Apple /// + memcpy(fileio, a3io, t_fileio) + break + otherwise // Apple ][ +wend done diff --git a/src/libsrc/sane.pla b/src/libsrc/sane.pla index 04c5593..cb0d09c 100644 --- a/src/libsrc/sane.pla +++ b/src/libsrc/sane.pla @@ -703,14 +703,14 @@ def loadcode(codefile) //puts(codefile); puts(":\n") pcode = 0 - ref = open(codefile, sysbuf) + ref = fileio:open(codefile, sysbuf) if ref pcode = heapmark - read(ref, pcode, 512) + fileio:read(ref, pcode, 512) //dumpheader(pcode) //putname(pcode + segname + 8); putc('='); prword(pcode); putln - seglen = read(ref, pcode, (pcode + t_diskinfo)=>codeaddr) - close(ref) + seglen = fileio:read(ref, pcode, (pcode + t_diskinfo)=>codeaddr) + fileio:close(ref) if !fp6502 and (MACHID & $30 == $30) seglen = fixup(AUXADDR, pcode + seglen - 2) - pcode auxmove(AUXADDR, pcode, seglen) diff --git a/src/samplesrc/fatget.pla b/src/samplesrc/fatget.pla index 81d9958..5b98d1d 100644 --- a/src/samplesrc/fatget.pla +++ b/src/samplesrc/fatget.pla @@ -126,9 +126,9 @@ def fatCopyFrom(src, dst, type, aux) // // Check if dst already exists // - ref = open(dst, sysbuf) + ref = fileio:open(dst, sysbuf) if ref - close(ref) + fileio:close(ref) puts("Overwrite "); puts(dst) if not getYN("(Y/N)?") heaprelease(freeAddr) @@ -140,10 +140,10 @@ def fatCopyFrom(src, dst, type, aux) // // Create dst file // - if create(dst, $C3, type, aux) + if fileio:create(dst, $C3, type, aux) puts("Create file error: "); putByte(perr); putln fin - ref = open(dst, sysbuf) + ref = fileio:open(dst, sysbuf) if not ref puts("Error opening file: "); puts(dst); putln puts("Open file error: "); putByte(perr); putln @@ -156,7 +156,7 @@ def fatCopyFrom(src, dst, type, aux) repeat copyLen = bigFatRead(copyBuf, COPY_BUF_SIZE) if copyLen - if write(ref, copyBuf, copyLen) <> copyLen + if fileio:write(ref, copyBuf, copyLen) <> copyLen puts("Error writing file:"); puts(dst); putln puts("Write file error: "); putByte(perr); putln copyLen = 0 // Force end of copy @@ -167,7 +167,7 @@ def fatCopyFrom(src, dst, type, aux) else puts("Error opening FAT file:"); puts(src); putln fin - close(ref) + fileio:close(ref) heaprelease(freeAddr) end @@ -180,4 +180,4 @@ if ^arg else puts("Usage: +FATGET "); putln fin -done \ No newline at end of file +done diff --git a/src/samplesrc/fatput.pla b/src/samplesrc/fatput.pla index d16d690..d2d3880 100644 --- a/src/samplesrc/fatput.pla +++ b/src/samplesrc/fatput.pla @@ -43,7 +43,7 @@ def mkFatName(proName, fatName) word l, n byte fileinfo[t_fileinfo] - if !getfileinfo(proName, @fileinfo) + if !fileio:getfileinfo(proName, @fileinfo) // // Scan backward looking for dir seperator // @@ -110,7 +110,7 @@ def fatCopyTo(src, dst) puts("Not enough free memory!\n"); putln return -1 fin - ref = open(src, sysbuf) + ref = fileio:open(src, sysbuf) if not ref puts("Error opening file: "); puts(src); putln puts("Open file error: "); putByte(perr); putln @@ -121,7 +121,7 @@ def fatCopyTo(src, dst) // if sdFAT:fileOpen(dst, O_READ | O_WRITE | O_CREAT) repeat - copyLen = read(ref, copyBuf, COPY_BUF_SIZE) + copyLen = fileio:read(ref, copyBuf, COPY_BUF_SIZE) if copyLen copyLen = bigFatWrite(copyBuf, copyLen) if !copyLen @@ -132,7 +132,7 @@ def fatCopyTo(src, dst) else puts("Error opening FAT file:"); puts(dst); putln fin - close(ref) + fileio:close(ref) heaprelease(freeAddr) end @@ -144,4 +144,4 @@ if ^arg else puts("Usage: +FATPUT "); putln fin -done \ No newline at end of file +done diff --git a/src/samplesrc/fatreaddsk.pla b/src/samplesrc/fatreaddsk.pla index b84886f..0cda2a6 100644 --- a/src/samplesrc/fatreaddsk.pla +++ b/src/samplesrc/fatreaddsk.pla @@ -107,7 +107,7 @@ def fatReadImage(src, drv, order) ^$24=^$20 // Move cursor to left edge puts("Reading blocks: "); puti(blocknum) for bufblk = 0 to COPY_BLK_CNT - if readblock(drv, inBuf + (bufblk << 9), blocknum + bufblk) + if fileio:readblock(drv, inBuf + (bufblk << 9), blocknum + bufblk) puts("Read disk error: $"); putb(perr); putln break fin diff --git a/src/samplesrc/fatwritedsk.pla b/src/samplesrc/fatwritedsk.pla index 5fc8b60..d6e29b4 100644 --- a/src/samplesrc/fatwritedsk.pla +++ b/src/samplesrc/fatwritedsk.pla @@ -113,7 +113,7 @@ def fatWriteImage(src, drv, order) trkSecToBlk(inBuf, outBuf) fin for bufblk = 0 to COPY_BLK_CNT - if writeblock(drv, outBuf + (bufblk << 9), blocknum + bufblk) + if fileio:writeblock(drv, outBuf + (bufblk << 9), blocknum + bufblk) puts("Write disk error: $"); putb(perr); putln break fin diff --git a/src/samplesrc/rod.pla b/src/samplesrc/rod.pla index 7ce8ee6..f312710 100644 --- a/src/samplesrc/rod.pla +++ b/src/samplesrc/rod.pla @@ -263,7 +263,7 @@ when MACHID & $C8 gotoxy = @a3gotoxy grmode = @a3grmode textmode = @a3textmode - if modaddr(@cmdsys):0 == $0010 + if modaddr(@cmdsys):0 == $0099 devcons = modaddr(@cmdsys).5 // devcons variable from cmdsys else puts(@a3err) diff --git a/src/vmsrc/a1cmd.pla b/src/vmsrc/a1cmd.pla index 354ad9e..a353bd6 100755 --- a/src/vmsrc/a1cmd.pla +++ b/src/vmsrc/a1cmd.pla @@ -34,7 +34,7 @@ predef syscall(cmd)#1, call(addr,areg,xreg,yreg,status)#1 predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1 predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr), releaseheap(newheap)#1, availheap()#1 predef memset(addr,value,size)#0, memcpy(dst,src,size)#0 -predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1 +predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1, divmod(a,b)#2 predef loadmod(mod)#1, execmod(modfile)#1, lookupstrmod(str)#1 // // System variables. @@ -88,6 +88,7 @@ byte uisgtstr[] = "ISUGT" byte uisgestr[] = "ISUGE" byte uisltstr[] = "ISULT" byte uislestr[] = "ISULE" +byte divmodstr[] = "DIVMOD" byte loadstr[] = "MODLOAD" byte execstr[] = "MODEXEC" byte modadrstr[] = "MODADDR" @@ -112,6 +113,7 @@ word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt word = @uislestr, @uword_isle +word = @divmodstr, @divmod word = @loadstr, @loadmod word = @execstr, @execmod word = @modadrstr, @lookupstrmod @@ -348,6 +350,30 @@ asm uword_islt(a,b)#1 INX RTS end +asm divmod(a,b)#2 + LDA #>(_divmod-1) + PHA + LDA #<(_divmod-1) + PHA + JSR INTERP + !BYTE $0A, $5C ; MOD, RET +_divmod DEX + LDA DSTL ; DVDNDL + STA ESTKL,X + LDA DSTH ; DVDNDH + STA ESTKH,X + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS + + RTS ++ LDA #$00 +; SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +end // // Addresses of internal routines. // diff --git a/src/vmsrc/cmd.pla b/src/vmsrc/cmd.pla index 555ac3d..6d5eb75 100755 --- a/src/vmsrc/cmd.pla +++ b/src/vmsrc/cmd.pla @@ -28,7 +28,7 @@ predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1 predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1 predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr)#1, releaseheap(newheap)#1, availheap()#1 predef memset(addr,value,size)#0, memcpy(dst,src,size)#0 -predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1 +predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1, divmod(a,b)#2 predef loadmod(mod)#1, execmod(modfile)#1, lookupstrmod(str)#1 // // System variable. @@ -65,6 +65,7 @@ byte uisgtstr = "ISUGT" byte uisgestr = "ISUGE" byte uisltstr = "ISULT" byte uislestr = "ISULE" +byte divmodstr = "DIVMOD" byte loadstr = "MODLOAD" byte execstr = "MODEXEC" byte modadrstr = "MODADDR" @@ -91,6 +92,7 @@ word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt word = @uislestr, @uword_isle +word = @divmodstr, @divmod word = @loadstr, @loadmod word = @execstr, @execmod word = @modadrstr, @lookupstrmod @@ -499,6 +501,30 @@ asm uword_islt(a,b)#1 INX RTS end +asm divmod(a,b)#2 + LDA #>(_divmod-1) + PHA + LDA #<(_divmod-1) + PHA + JSR $03D0 ; CALL DINTERP + !BYTE $0A, $5C ; MOD, RET +_divmod DEX + LDA DSTL ; DVDNDL + STA ESTKL,X + LDA DSTH ; DVDNDH + STA ESTKH,X + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS + + RTS ++ LDA #$00 +; SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +end // // Utility routines. // diff --git a/src/vmsrc/plvm01.s b/src/vmsrc/plvm01.s index 8a83f17..4b7ed50 100644 --- a/src/vmsrc/plvm01.s +++ b/src/vmsrc/plvm01.s @@ -138,6 +138,10 @@ DIV JSR _DIV ;* MOD TOS-1 BY TOS ;* MOD JSR _DIV + LDA ESTKL,X ; SAVE IN CASE OF DIVMOD + STA DSTL + LDA ESTKH,X + STA DSTH LDA TMPL ; REMNDRL STA ESTKL,X LDA TMPH ; REMNDRH diff --git a/src/vmsrc/plvm02.s b/src/vmsrc/plvm02.s index e3e28ce..c71e00c 100755 --- a/src/vmsrc/plvm02.s +++ b/src/vmsrc/plvm02.s @@ -560,6 +560,10 @@ DIV JSR _DIV ;* MOD TOS-1 BY TOS ;* MOD JSR _DIV + LDA ESTKL,X ; SAVE IN CASE OF DIVMOD + STA DSTL + LDA ESTKH,X + STA DSTH LDA TMPL ; REMNDRL STA ESTKL,X LDA TMPH ; REMNDRH diff --git a/src/vmsrc/plvm03.s b/src/vmsrc/plvm03.s index 2a9ccb3..d2b3649 100755 --- a/src/vmsrc/plvm03.s +++ b/src/vmsrc/plvm03.s @@ -286,6 +286,10 @@ DIV JSR _DIV ;* MOD TOS-1 BY TOS ;* MOD JSR _DIV + LDA ESTKL,X ; SAVE IN CASE OF DIVMOD + STA DSTL + LDA ESTKH,X + STA DSTH LDA TMPL ; REMNDRL STA ESTKL,X LDA TMPH ; REMNDRH diff --git a/src/vmsrc/plvm802.s b/src/vmsrc/plvm802.s index bc376a5..410f484 100644 --- a/src/vmsrc/plvm802.s +++ b/src/vmsrc/plvm802.s @@ -613,6 +613,8 @@ DIV JSR _DIV MOD JSR _DIV STA NOS,S ; REMNDR PLA + STA DST ; SAVE IN CASE OF DIVMOD + STX DVSIGN TXA AND #$0080 ; REMAINDER IS SIGN OF DIVIDEND BNE NEG diff --git a/src/vmsrc/soscmd.pla b/src/vmsrc/soscmd.pla index 87802a0..c361c0b 100755 --- a/src/vmsrc/soscmd.pla +++ b/src/vmsrc/soscmd.pla @@ -29,7 +29,7 @@ predef syscall(cmd,params)#1, call(addr,areg,xreg,yreg,status)#1 predef crout()#0, cout(c)#0, prstr(s)#0, print(i)#0, cin()#1, rdstr(p)#1, toupper(c)#1 predef markheap()#1, allocheap(size)#1, allocalignheap(size, pow2, freeaddr), releaseheap(newheap)#1, availheap()#1 predef memset(addr,value,size)#0, memcpy(dst,src,size)#0 -predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1 +predef uword_isgt(a,b)#1, uword_isge(a,b)#1, uword_islt(a,b)#1, uword_isle(a,b)#1, divmod(a,b)#2 predef loadmod(mod)#1, execmod(modfile)#1, lookupstrmod(str)#1 // // System variables. @@ -83,6 +83,7 @@ byte uisgtstr[] = "ISUGT" byte uisgestr[] = "ISUGE" byte uisltstr[] = "ISULT" byte uislestr[] = "ISULE" +byte divmodstr[] = "DIVMOD" byte loadstr[] = "MODLOAD" byte execstr[] = "MODEXEC" byte modadrstr[] = "MODADDR" @@ -108,6 +109,7 @@ word = @uisgtstr, @uword_isgt word = @uisgestr, @uword_isge word = @uisltstr, @uword_islt word = @uislestr, @uword_isle +word = @divmodstr, @divmod word = @loadstr, @loadmod word = @execstr, @execmod word = @modadrstr, @lookupstrmod @@ -232,9 +234,9 @@ asm memcpy(dst,src,size)#0 ; ; FORWARD COPY ; - LDA ESTKL-2,X + LDA ESTKL-1,X STA DSTL - LDA ESTKH-2,X + LDA ESTKH-1,X STA DSTH LDA ESTKL-2,X STA SRCL @@ -410,6 +412,30 @@ asm uword_islt(a,b)#1 INX RTS end +asm divmod(a,b)#2 + LDA #>(_divmod-1) + PHA + LDA #<(_divmod-1) + PHA + JSR INTERP + !BYTE $0A, $5C ; MOD, RET +_divmod DEX + LDA DSTL ; DVDNDL + STA ESTKL,X + LDA DSTH ; DVDNDH + STA ESTKH,X + LSR DVSIGN ; SIGN(RESULT) = (SIGN(DIVIDEND) + SIGN(DIVISOR)) & 1 + BCS + + RTS ++ LDA #$00 +; SEC + SBC ESTKL,X + STA ESTKL,X + LDA #$00 + SBC ESTKH,X + STA ESTKH,X + RTS +end // // Addresses of internal routines. // @@ -960,9 +986,9 @@ def loadmod(mod)#1 if refnum > 0 rdlen = read(refnum, @header, 128) modsize = header:0 - moddep = @header.1 - defofst = modsize - init = 0 + //moddep = @header.1 + //defofst = modsize + //init = 0 if rdlen > 4 and header:2 == $DA7F // DAVE+1 = magic number :-) // // This is an EXTended RELocatable (data+bytecode) module.