diff --git a/TerranBASICexecutable/src/net/torvald/tsvm/TerranBASIC.java b/TerranBASICexecutable/src/net/torvald/tsvm/TerranBASIC.java index 7120f17..bf54738 100644 --- a/TerranBASICexecutable/src/net/torvald/tsvm/TerranBASIC.java +++ b/TerranBASICexecutable/src/net/torvald/tsvm/TerranBASIC.java @@ -29,7 +29,8 @@ public class TerranBASIC { appConfig.setWindowedMode(WIDTH, HEIGHT); HashMap watchdogs = new HashMap<>(); - watchdogs.put("TEVD_SYNC", TevdSyncWatchdog.INSTANCE); + watchdogs.put("TEVD_COMMIT", TevdPartialDomCommitWatchdog.INSTANCE); + watchdogs.put("TEVD_SYNC", TevdPartialDomSyncWatchdog.INSTANCE); VM tbasvm = new VM("./assets", 64 << 10, new TheRealWorld(), new VMProgramRom[]{TBASRelBios.INSTANCE}, 2, watchdogs); EmulInstance tbasrunner = new EmulInstance(tbasvm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", "assets/disk0", 560, 448); diff --git a/assets/DOSBOOT.tevd b/assets/DOSBOOT.tevd index 147c1ec..c1e54bd 100644 Binary files a/assets/DOSBOOT.tevd and b/assets/DOSBOOT.tevd differ diff --git a/assets/DOSBOOT.tevd.original b/assets/DOSBOOT.tevd.original index 147c1ec..c1e54bd 100644 Binary files a/assets/DOSBOOT.tevd.original and b/assets/DOSBOOT.tevd.original differ diff --git a/lib/TerranVirtualDisk-src.jar b/lib/TerranVirtualDisk-src.jar index 98fdccc..e504ef6 100644 Binary files a/lib/TerranVirtualDisk-src.jar and b/lib/TerranVirtualDisk-src.jar differ diff --git a/lib/TerranVirtualDisk.jar b/lib/TerranVirtualDisk.jar index b447482..f14aff8 100644 Binary files a/lib/TerranVirtualDisk.jar and b/lib/TerranVirtualDisk.jar differ diff --git a/tsvm_core/src/net/torvald/tsvm/VMWatchdog.kt b/tsvm_core/src/net/torvald/tsvm/VMWatchdog.kt index d20cf95..ff6bc15 100644 --- a/tsvm_core/src/net/torvald/tsvm/VMWatchdog.kt +++ b/tsvm_core/src/net/torvald/tsvm/VMWatchdog.kt @@ -1,6 +1,6 @@ package net.torvald.tsvm -import com.badlogic.gdx.utils.Queue +import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.PartialDOM import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VirtualDisk import java.io.File @@ -29,15 +29,15 @@ abstract class VMWatchdog(val interval: Float) { } -object TevdSyncWatchdog : VMWatchdog(5f) { +object TevdPartialDomCommitWatchdog : VMWatchdog(5f) { - private val messageQueue = ArrayList>() + private val messageQueue = ArrayList>() override fun consumeMessages() { synchronized(this) { messageQueue.forEach { (outfile, dom) -> - VDUtil.dumpToRealMachine(dom, outfile) -// println("[${this.javaClass.simpleName}] dump ${outfile.path}") + dom.commit() + println("[${this.javaClass.simpleName}] commit ${outfile.path}") } messageQueue.clear() } @@ -45,7 +45,33 @@ object TevdSyncWatchdog : VMWatchdog(5f) { override fun addMessage(message: Array) { val file = message[0] as File - val dom = message[1] as VirtualDisk + val dom = message[1] as PartialDOM + + val hasDup = messageQueue.fold(false) { acc, pair -> acc or (pair.first.path == file.path) } + if (!hasDup) { + messageQueue.add(file to dom) + } + } +} + + +object TevdPartialDomSyncWatchdog : VMWatchdog(120f) { + + private val messageQueue = ArrayList>() + + override fun consumeMessages() { + synchronized(this) { + messageQueue.forEach { (outfile, dom) -> + dom.sync() + println("[${this.javaClass.simpleName}] sync ${outfile.path}") + } + messageQueue.clear() + } + } + + override fun addMessage(message: Array) { + val file = message[0] as File + val dom = message[1] as PartialDOM val hasDup = messageQueue.fold(false) { acc, pair -> acc or (pair.first.path == file.path) } if (!hasDup) { diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt index ed8932c..82af524 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt @@ -47,9 +47,15 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t } } - + private var tevdSyncFilteringCounter = 0 fun notifyDiskCommit() { - vm.watchdogs["TEVD_SYNC"]?.addMessage(arrayOf(tevdPath, DOM)) + vm.watchdogs["TEVD_COMMIT"]?.addMessage(arrayOf(tevdPath, DOM)) + + if (tevdSyncFilteringCounter >= 1) { + vm.watchdogs["TEVD_SYNC"]?.addMessage(arrayOf(tevdPath, DOM)) + tevdSyncFilteringCounter = 0 + } + tevdSyncFilteringCounter += 1 } @@ -98,12 +104,24 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t override fun writeoutImpl(inputData: ByteArray) { printdbg("inputString=${inputData.trimNull().toString(VM.CHARSET)}") - if (writeMode || appendMode) { + if ((writeMode || appendMode) && writeModeLength >= 0) { + printdbg("writeout with inputdata length of ${inputData.size}") //println("[DiskDrive] writeout with inputdata length of ${inputData.size}") //println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}") if (!fileOpen) throw InternalError("File is not open but the drive is in write mode") + if (!file.exists()) { + printdbg("File '${file.path}' not exists, creating new...") + val (result, failReason) = file.createNewFile() + if (failReason != null) { + throw failReason + } + else { + printdbg("Operation successful") + } + } + System.arraycopy(inputData, 0, writeBuffer, writeBufferUsage, minOf(writeModeLength - writeBufferUsage, inputData.size, BLOCK_SIZE)) writeBufferUsage += inputData.size @@ -121,6 +139,8 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t } } else if (fileOpenMode == 17) { + printdbg("File open mode 17") + if (!fileOpen) throw InternalError("Bootloader file is not open but the drive is in boot write mode") val inputData = if (inputData.size != BLOCK_SIZE) ByteArray(BLOCK_SIZE) { if (it < inputData.size) inputData[it] else 0 } @@ -140,6 +160,8 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t notifyDiskCommit() } else { + printdbg("(cmd mode)") + val inputString = inputData.trimNull().toString(VM.CHARSET) if (inputString.startsWith("DEVRST\u0017")) { @@ -222,7 +244,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t return } try { - val successful = file.delete() + val (successful, whyFailed) = file.delete() if (!successful) { statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_FAILED) return @@ -381,7 +403,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t return } try { - val status = file.mkdir() + val (status, whyFailed) = file.mkdir() statusCode.set(if (status) 0 else 1) if (status) { printdbg("Notifying disk commit (mkdir)") @@ -402,7 +424,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t return } try { - val f1 = file.createNewFile() + val (f1, whyFailed) = file.createNewFile() statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED) if (f1) { printdbg("Notifying disk commit (mkfile)") @@ -427,7 +449,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t return } try { - val f1 = file.setLastModified(vm.worldInterface.currentTimeInMills()) + val (f1, whyFailed) = file.setLastModified(vm.worldInterface.currentTimeInMills()) statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED) if (f1) { printdbg("Notifying disk commit (touch)") @@ -452,11 +474,16 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t return } if (!file.exists()) { - val f1 = file.createNewFile() + val (f1, whyFailed) = file.createNewFile() statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED) if (!f1) { return } } +// if (fileOpenMode == 1) { writeMode = true; appendMode = false } +// else if (fileOpenMode == 2) { writeMode = false; appendMode = true } writeModeLength = inputString.substring(5, inputString.length).toInt() + + printdbg("WRITE issued with len $writeModeLength") + writeBuffer = ByteArray(writeModeLength) writeBufferUsage = 0 statusCode.set(TestDiskDrive.STATE_CODE_STANDBY) @@ -493,8 +520,10 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t // DOM.entries.clear() // DOM.diskName = newName.toByteArray(VM.CHARSET) } - else + else { + printdbg("Illegal command: ${inputString}") statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND) + } } } diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt index 17752d7..117b945 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdFileDescriptor.kt @@ -9,7 +9,12 @@ import java.io.IOException */ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { - val path = _pathstr.replace('\\', '/') + val path = _pathstr.replace('\\', '/').let { + var s = it.substring(0) + while (s.startsWith("/")) + s = s.substring(1) + s + } val vdPath = VDUtil.VDPath(path, VM.CHARSET) val entryID: EntryID? @@ -84,16 +89,19 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { return (DOM.requestFile(path) != null) } - fun delete(): Boolean { + fun delete(): Pair { return try { val parentDir = vdPath.getParent().toString() DOM.removeFile(path) - DOM.requestFile(parentDir)!!.modificationDate = VDUtil.currentUnixtime + DOM.requestFile(parentDir)!!.let { + it.modificationDate = VDUtil.currentUnixtime + DOM.touchFile(it) + } - true + true to null } catch (e: KotlinNullPointerException) { - false + false to e } } @@ -119,7 +127,7 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { return fileContent.getContent().toByteArray() } - fun mkdir(): Boolean { + fun mkdir(): Pair { return try { val parentDir = vdPath.getParent().toString() @@ -131,18 +139,19 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { val newDir = DiskEntry(newID, dir.entryID, nameBytes, newTime, newTime, EntryDirectory()) DOM.addNewFile(newDir) + DOM.touchFile(dir) dirContent.add(newID) dir.modificationDate = newTime - true + true to null } catch (e: KotlinNullPointerException) { - false + false to e } } - fun createNewFile(): Boolean { + fun createNewFile(): Pair { val fileContent = EntryFile(ByteArray64()) val time_t = System.currentTimeMillis() / 1000 val newFile = DiskEntry(-1, -1, nameBytes, time_t, time_t, fileContent) @@ -159,24 +168,28 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { newFile.parentEntryID = dir.entryID DOM.addNewFile(newFile) + DOM.touchFile(dir) dirContent.add(newID) dir.modificationDate = newTime - true + true to null } catch (e: KotlinNullPointerException) { - false + false to e } } - fun setLastModified(newTime_t: Long): Boolean { + fun setLastModified(newTime_t: Long): Pair { return try { - DOM.requestFile(path)!!.modificationDate = newTime_t - true + DOM.requestFile(path)!!.let { + it.modificationDate = newTime_t + DOM.touchFile(it) + } + true to null } catch (e: KotlinNullPointerException) { - false + false to e } } diff --git a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java index 0e17f6c..aaede09 100644 --- a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java +++ b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java @@ -3,11 +3,8 @@ package net.torvald.tsvm; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; import com.badlogic.gdx.graphics.glutils.ShaderProgram; -import kotlin.Pair; -import kotlin.collections.CollectionsKt; import net.torvald.tsvm.peripheral.*; -import java.io.File; import java.util.HashMap; public class AppLoader { @@ -32,7 +29,8 @@ public class AppLoader { appConfig.setWindowedMode(WIDTH, HEIGHT); HashMap watchdogs = new HashMap<>(); - watchdogs.put("TEVD_SYNC", TevdSyncWatchdog.INSTANCE); + watchdogs.put("TEVD_COMMIT", TevdPartialDomCommitWatchdog.INSTANCE); + watchdogs.put("TEVD_SYNC", TevdPartialDomSyncWatchdog.INSTANCE); String diskPath = "assets/disk0"; diff --git a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt index 6bea231..683529e 100644 --- a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt +++ b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt @@ -65,9 +65,13 @@ class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var pa */ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: Int, var panelsY: Int, val diskPathRoot: String) : ApplicationAdapter() { - val TEVD_SYNC = TevdSyncWatchdog + val TEVD_COMMIT = TevdPartialDomCommitWatchdog + val TEVD_SYNC = TevdPartialDomCommitWatchdog - val watchdogs = hashMapOf("TEVD_SYNC" to TEVD_SYNC) + val watchdogs = hashMapOf( + "TEVD_COMMIT" to TEVD_COMMIT, + "TEVD_SYNC" to TEVD_SYNC + ) data class VMRunnerInfo(val vm: VM, val profileName: String)