tevd disk drive update and fixes

This commit is contained in:
minjaesong
2023-03-04 21:10:52 +09:00
parent 57a84ccfae
commit 2d000013b7
10 changed files with 108 additions and 37 deletions

View File

@@ -29,7 +29,8 @@ public class TerranBASIC {
appConfig.setWindowedMode(WIDTH, HEIGHT); appConfig.setWindowedMode(WIDTH, HEIGHT);
HashMap<String, VMWatchdog> watchdogs = new HashMap<>(); HashMap<String, VMWatchdog> 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); 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); EmulInstance tbasrunner = new EmulInstance(tbasvm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", "assets/disk0", 560, 448);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,6 @@
package net.torvald.tsvm 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.VDUtil
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VirtualDisk import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VirtualDisk
import java.io.File 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<Pair<File, VirtualDisk>>() private val messageQueue = ArrayList<Pair<File, PartialDOM>>()
override fun consumeMessages() { override fun consumeMessages() {
synchronized(this) { synchronized(this) {
messageQueue.forEach { (outfile, dom) -> messageQueue.forEach { (outfile, dom) ->
VDUtil.dumpToRealMachine(dom, outfile) dom.commit()
// println("[${this.javaClass.simpleName}] dump ${outfile.path}") println("[${this.javaClass.simpleName}] commit ${outfile.path}")
} }
messageQueue.clear() messageQueue.clear()
} }
@@ -45,7 +45,33 @@ object TevdSyncWatchdog : VMWatchdog(5f) {
override fun addMessage(message: Array<Any?>) { override fun addMessage(message: Array<Any?>) {
val file = message[0] as File 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<Pair<File, PartialDOM>>()
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<Any?>) {
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) } val hasDup = messageQueue.fold(false) { acc, pair -> acc or (pair.first.path == file.path) }
if (!hasDup) { if (!hasDup) {

View File

@@ -47,9 +47,15 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
} }
} }
private var tevdSyncFilteringCounter = 0
fun notifyDiskCommit() { 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) { override fun writeoutImpl(inputData: ByteArray) {
printdbg("inputString=${inputData.trimNull().toString(VM.CHARSET)}") 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("[DiskDrive] writeout with inputdata length of ${inputData.size}")
//println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}") //println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}")
if (!fileOpen) throw InternalError("File is not open but the drive is in write mode") 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)) System.arraycopy(inputData, 0, writeBuffer, writeBufferUsage, minOf(writeModeLength - writeBufferUsage, inputData.size, BLOCK_SIZE))
writeBufferUsage += inputData.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) { 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") 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 } 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() notifyDiskCommit()
} }
else { else {
printdbg("(cmd mode)")
val inputString = inputData.trimNull().toString(VM.CHARSET) val inputString = inputData.trimNull().toString(VM.CHARSET)
if (inputString.startsWith("DEVRST\u0017")) { if (inputString.startsWith("DEVRST\u0017")) {
@@ -222,7 +244,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
try { try {
val successful = file.delete() val (successful, whyFailed) = file.delete()
if (!successful) { if (!successful) {
statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_FAILED) statusCode.set(TestDiskDrive.STATE_CODE_OPERATION_FAILED)
return return
@@ -381,7 +403,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
try { try {
val status = file.mkdir() val (status, whyFailed) = file.mkdir()
statusCode.set(if (status) 0 else 1) statusCode.set(if (status) 0 else 1)
if (status) { if (status) {
printdbg("Notifying disk commit (mkdir)") printdbg("Notifying disk commit (mkdir)")
@@ -402,7 +424,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
try { try {
val f1 = file.createNewFile() val (f1, whyFailed) = file.createNewFile()
statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED) statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (f1) { if (f1) {
printdbg("Notifying disk commit (mkfile)") printdbg("Notifying disk commit (mkfile)")
@@ -427,7 +449,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
try { 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) statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (f1) { if (f1) {
printdbg("Notifying disk commit (touch)") printdbg("Notifying disk commit (touch)")
@@ -452,11 +474,16 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t
return return
} }
if (!file.exists()) { 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) statusCode.set(if (f1) TestDiskDrive.STATE_CODE_STANDBY else TestDiskDrive.STATE_CODE_OPERATION_FAILED)
if (!f1) { return } 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() writeModeLength = inputString.substring(5, inputString.length).toInt()
printdbg("WRITE issued with len $writeModeLength")
writeBuffer = ByteArray(writeModeLength) writeBuffer = ByteArray(writeModeLength)
writeBufferUsage = 0 writeBufferUsage = 0
statusCode.set(TestDiskDrive.STATE_CODE_STANDBY) 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.entries.clear()
// DOM.diskName = newName.toByteArray(VM.CHARSET) // DOM.diskName = newName.toByteArray(VM.CHARSET)
} }
else else {
printdbg("Illegal command: ${inputString}")
statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND) statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND)
}
} }
} }

View File

@@ -9,7 +9,12 @@ import java.io.IOException
*/ */
class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) { 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 vdPath = VDUtil.VDPath(path, VM.CHARSET)
val entryID: EntryID? val entryID: EntryID?
@@ -84,16 +89,19 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) {
return (DOM.requestFile(path) != null) return (DOM.requestFile(path) != null)
} }
fun delete(): Boolean { fun delete(): Pair<Boolean, Throwable?> {
return try { return try {
val parentDir = vdPath.getParent().toString() val parentDir = vdPath.getParent().toString()
DOM.removeFile(path) 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) { catch (e: KotlinNullPointerException) {
false false to e
} }
} }
@@ -119,7 +127,7 @@ class TevdFileDescriptor(val DOM: PartialDOM, _pathstr: String) {
return fileContent.getContent().toByteArray() return fileContent.getContent().toByteArray()
} }
fun mkdir(): Boolean { fun mkdir(): Pair<Boolean, Throwable?> {
return try { return try {
val parentDir = vdPath.getParent().toString() 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()) val newDir = DiskEntry(newID, dir.entryID, nameBytes, newTime, newTime, EntryDirectory())
DOM.addNewFile(newDir) DOM.addNewFile(newDir)
DOM.touchFile(dir)
dirContent.add(newID) dirContent.add(newID)
dir.modificationDate = newTime dir.modificationDate = newTime
true true to null
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
false false to e
} }
} }
fun createNewFile(): Boolean { fun createNewFile(): Pair<Boolean, Throwable?> {
val fileContent = EntryFile(ByteArray64()) val fileContent = EntryFile(ByteArray64())
val time_t = System.currentTimeMillis() / 1000 val time_t = System.currentTimeMillis() / 1000
val newFile = DiskEntry(-1, -1, nameBytes, time_t, time_t, fileContent) 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 newFile.parentEntryID = dir.entryID
DOM.addNewFile(newFile) DOM.addNewFile(newFile)
DOM.touchFile(dir)
dirContent.add(newID) dirContent.add(newID)
dir.modificationDate = newTime dir.modificationDate = newTime
true true to null
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
false false to e
} }
} }
fun setLastModified(newTime_t: Long): Boolean { fun setLastModified(newTime_t: Long): Pair<Boolean, Throwable?> {
return try { return try {
DOM.requestFile(path)!!.modificationDate = newTime_t DOM.requestFile(path)!!.let {
true it.modificationDate = newTime_t
DOM.touchFile(it)
}
true to null
} }
catch (e: KotlinNullPointerException) { catch (e: KotlinNullPointerException) {
false false to e
} }
} }

View File

@@ -3,11 +3,8 @@ package net.torvald.tsvm;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.graphics.glutils.ShaderProgram;
import kotlin.Pair;
import kotlin.collections.CollectionsKt;
import net.torvald.tsvm.peripheral.*; import net.torvald.tsvm.peripheral.*;
import java.io.File;
import java.util.HashMap; import java.util.HashMap;
public class AppLoader { public class AppLoader {
@@ -32,7 +29,8 @@ public class AppLoader {
appConfig.setWindowedMode(WIDTH, HEIGHT); appConfig.setWindowedMode(WIDTH, HEIGHT);
HashMap<String, VMWatchdog> watchdogs = new HashMap<>(); HashMap<String, VMWatchdog> 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"; String diskPath = "assets/disk0";

View File

@@ -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() { 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<String, VMWatchdog>("TEVD_SYNC" to TEVD_SYNC) val watchdogs = hashMapOf<String, VMWatchdog>(
"TEVD_COMMIT" to TEVD_COMMIT,
"TEVD_SYNC" to TEVD_SYNC
)
data class VMRunnerInfo(val vm: VM, val profileName: String) data class VMRunnerInfo(val vm: VM, val profileName: String)