1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-07-20 13:28:56 +00:00

FileIO library for Apple 1 and ///, divmod function in cmdsys

This commit is contained in:
David Schmenk 2017-12-05 19:22:35 -08:00
parent 40ae932940
commit f5ea22af02
15 changed files with 302 additions and 49 deletions

View File

@ -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
end

View File

@ -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

View File

@ -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)

View File

@ -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 <FAT filename>"); putln
fin
done
done

View File

@ -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 <filename>"); putln
fin
done
done

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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.
//

View File

@ -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.
//

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.