diff --git a/compiler/res/prog8lib/virtual/diskio.p8 b/compiler/res/prog8lib/virtual/diskio.p8 index 5d4707ee9..848f54cdb 100644 --- a/compiler/res/prog8lib/virtual/diskio.p8 +++ b/compiler/res/prog8lib/virtual/diskio.p8 @@ -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) + }} } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 48a406258..ebb95291c 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -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: diff --git a/virtualmachine/src/prog8/vm/SysCalls.kt b/virtualmachine/src/prog8/vm/SysCalls.kt index 0cbb2e9d9..a2047a4c6 100644 --- a/virtualmachine/src/prog8/vm/SysCalls.kt +++ b/virtualmachine/src/prog8/vm/SysCalls.kt @@ -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.. { 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.. { - 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.. { 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) + } } } }