implemented a couple more diskio routines for the VM target

This commit is contained in:
Irmen de Jong 2024-03-09 17:36:39 +01:00
parent eef8ae00b8
commit 3a9919a377
3 changed files with 110 additions and 24 deletions

View File

@ -8,8 +8,12 @@ diskio {
sub directory() -> bool {
; -- Prints the directory contents to the screen. Returns success.
txt.print("@TODO: directory\n")
return false
%ir {{
loadm.w r65534,diskio.load.filenameptr
loadm.w r65535,diskio.load.address_override
syscall 61 (): r0.b
returnr.b r0
}}
}
sub list_filenames(uword pattern_ptr, uword filenames_buffer, uword filenames_buf_size) -> ubyte {
@ -18,7 +22,7 @@ diskio {
; After the last filename one additional 0 byte is placed to indicate the end of the list.
; Returns number of files (it skips 'dir' entries i.e. subdirectories).
; Also sets carry on exit: Carry clear = all files returned, Carry set = directory has more files that didn't fit in the buffer.
txt.print("@TODO: list_flienames\n")
txt.print("@TODO: list_filenames\n")
sys.clear_carry()
return 0
}
@ -115,17 +119,51 @@ diskio {
; ---- other functions ----
sub chdir(str path) {
; -- change current directory.
txt.print("@TODO: chdir\n")
}
sub mkdir(str name) {
; -- make a new subdirectory.
txt.print("@TODO: mkdir\n")
}
sub rmdir(str name) {
; -- remove a subdirectory.
txt.print("@TODO: rmdir\n")
}
sub curdir() -> uword {
; return current directory name or 0 if error
txt.print("@TODO: curdir\n")
return 0
}
sub status() -> str {
; -- retrieve the disk drive's current status message
return "ok"
return "unknown"
}
sub save(uword filenameptr, uword start_address, uword savesize) -> bool {
%ir {{
load.b r65532,0
loadm.w r65533,diskio.save.filenameptr
loadm.w r65534,diskio.save.start_address
loadm.w r65535,diskio.save.savesize
syscall 58 (r65533.w, r65534.w, r65535.w): r0.b
syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
returnr.b r0
}}
}
; like save() but omits the 2 byte prg header.
sub save_raw(uword filenameptr, uword startaddress, uword savesize) -> bool {
%ir {{
load.b r65532,1
loadm.w r65533,diskio.save.filenameptr
loadm.w r65534,diskio.save.start_address
loadm.w r65535,diskio.save.savesize
syscall 58 (r65532.b, r65533.w, r65534.w, r65535.w): r0.b
returnr.b r0
}}
}
@ -167,6 +205,10 @@ diskio {
sub rename(uword oldfileptr, uword newfileptr) {
; -- rename a file on the drive
txt.print("@TODO: rename\n")
%ir {{
loadm.w r65534,diskio.rename.oldfileptr
loadm.w r65535,diskio.rename.newfileptr
syscall 60 (r65534.w, r65535.w)
}}
}
}

View File

@ -26,7 +26,6 @@ Compiler:
- OR.... make all this more generic and use some %segment option to create real segments for 64tass?
- (need separate step in codegen and IR to write the "golden" variables)
- VM: implement more diskio support
- do we need (array)variable alignment tag instead of block alignment tag? You want to align the data, not the code in the block?
- ir: related to the one above: block alignment doesn't translate well to variables in the block (the actual stuff that needs to be aligned in memory) but: need variable alignment tag instead of block alignment tag, really
- ir: fix call() return value handling
@ -55,6 +54,7 @@ Libraries:
- fix the problems in atari target, and flesh out its libraries.
- c128 target: make syslib more complete (missing kernal routines)?
- pet32 target: make syslib more complete (missing kernal routines)?
- VM: implement more diskio support
Optimizations:

View File

@ -3,6 +3,8 @@ package prog8.vm
import prog8.intermediate.FunctionCallArgs
import prog8.intermediate.IRDataType
import java.io.File
import kotlin.io.path.Path
import kotlin.io.path.listDirectoryEntries
import kotlin.math.*
/*
@ -68,6 +70,8 @@ SYSCALLS:
57 = load_raw
58 = save
59 = delete
60 = rename
61 = directory
*/
enum class Syscall {
@ -130,7 +134,9 @@ enum class Syscall {
LOAD,
LOAD_RAW,
SAVE,
DELETE
DELETE,
RENAME,
DIRECTORY
;
companion object {
@ -632,41 +638,79 @@ object SysCalls {
Syscall.LOAD -> {
val (filenameA, addrA) = getArgValues(callspec.arguments, vm)
val filename = vm.memory.getString((filenameA as UShort).toInt())
val data = File(filename).readBytes()
val addr = if(addrA==0) data[0] + data[1]*256 else (addrA as UShort).toInt()
for(i in 0..<data.size-2) {
vm.memory.setUB(addr+i, data[i+2].toUByte())
if(File(filename).exists()) {
val data = File(filename).readBytes()
val addr = if (addrA == 0) data[0] + data[1] * 256 else (addrA as UShort).toInt()
for (i in 0..<data.size - 2) {
vm.memory.setUB(addr + i, data[i + 2].toUByte())
}
vm.registers.setUW(0, (addr + data.size - 2).toUShort())
} else {
vm.registers.setUW(0, 0u)
}
vm.registers.setUW(0, (addr+data.size-2).toUShort())
}
Syscall.LOAD_RAW -> {
val (filenameA, addrA) = getArgValues(callspec.arguments, vm)
val filename = vm.memory.getString((filenameA as UShort).toInt())
val addr = (addrA as UShort).toInt()
val data = File(filename).readBytes()
for(i in 0..<data.size) {
vm.memory.setUB(addr+i, data[i].toUByte())
if(File(filename).exists()) {
val data = File(filename).readBytes()
for (i in 0..<data.size) {
vm.memory.setUB(addr + i, data[i].toUByte())
}
vm.registers.setUW(0, (addr + data.size).toUShort())
} else {
vm.registers.setUW(0, 0u)
}
vm.registers.setUW(0, (addr+data.size).toUShort())
}
Syscall.SAVE -> {
val (filenamePtr, startA, sizeA) = getArgValues(callspec.arguments, vm)
val (raw, filenamePtr, startA, sizeA) = getArgValues(callspec.arguments, vm)
val size = (sizeA as UShort).toInt()
val data = ByteArray(size+2)
val startPtr = (startA as UShort).toInt()
data[0] = (startPtr and 255).toByte()
data[1] = (startPtr shr 8).toByte()
for(i in 0..<size) {
data[i+2] = vm.memory.getUB(startPtr+i).toByte()
val data: ByteArray
if(raw==0) {
// save with 2 byte PRG load address header
data = ByteArray(size+2)
data[0] = (startPtr and 255).toByte()
data[1] = (startPtr shr 8).toByte()
for (i in 0..<size) {
data[i + 2] = vm.memory.getUB(startPtr + i).toByte()
}
} else {
// 'raw' save, without header
data = ByteArray(size)
for (i in 0..<size) {
data[i] = vm.memory.getUB(startPtr + i).toByte()
}
}
val filename = vm.memory.getString((filenamePtr as UShort).toInt())
File(filename).writeBytes(data)
if (File(filename).exists())
vm.registers.setUB(0, 0u)
else {
File(filename).writeBytes(data)
vm.registers.setUB(0, 1u)
}
}
Syscall.DELETE -> {
val filenamePtr = getArgValues(callspec.arguments, vm).single() as UShort
val filename = vm.memory.getString(filenamePtr.toInt())
File(filename).delete()
}
Syscall.RENAME -> {
val (origFilenamePtr, newFilenamePtr) = getArgValues(callspec.arguments, vm)
val origFilename = vm.memory.getString((origFilenamePtr as UShort).toInt())
val newFilename = vm.memory.getString((newFilenamePtr as UShort).toInt())
File(origFilename).renameTo(File(newFilename))
}
Syscall.DIRECTORY -> {
// no arguments
val directory = Path(".")
println("Directory listing for ${directory.toAbsolutePath().normalize()}")
directory.listDirectoryEntries().sorted().forEach {
println("${it.toFile().length()}\t${it.normalize()}")
}
vm.registers.setUB(0, 1u)
}
}
}
}