From 60b4834c72aabeb96f0e145cc78341ca13c34dcc Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 26 Oct 2022 21:27:15 +0900 Subject: [PATCH] ability to load vm using json configuration --- .../torvald/tsvm/peripheral/TestDiskDrive.kt | 4 +- .../src/net/torvald/tsvm/AppLoader.java | 2 +- .../src/net/torvald/tsvm/VMEmuExecutable.kt | 78 +++++++++++++++---- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/TestDiskDrive.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/TestDiskDrive.kt index 50184b8..ead434b 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/TestDiskDrive.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/TestDiskDrive.kt @@ -10,7 +10,7 @@ import java.util.* /** * @param driveNum 0 for COM drive number 1, but the file path will still be zero-based */ -class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath: File? = null) : BlockTransferInterface(false, true) { +class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath: String? = null) : BlockTransferInterface(false, true) { companion object { const val STATE_CODE_STANDBY = 0 @@ -63,7 +63,7 @@ class TestDiskDrive(private val vm: VM, private val driveNum: Int, theRootPath: if (DBGPRN) println("[TestDiskDrive] $msg") } - private val rootPath = theRootPath ?: File("test_assets/test_drive_$driveNum") + private val rootPath = File(theRootPath) ?: File("test_assets/test_drive_$driveNum") private var fileOpen = false private var fileOpenMode = -1 // 1: 'W", 2: 'A' diff --git a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java index 0353f62..e6848a5 100644 --- a/tsvm_executable/src/net/torvald/tsvm/AppLoader.java +++ b/tsvm_executable/src/net/torvald/tsvm/AppLoader.java @@ -42,7 +42,7 @@ public class AppLoader { // VM vm = new VM("./assets", 8192 << 10, new TheRealWorld(), new VMProgramRom[]{OpenBios.INSTANCE}, 8); // VM pipvm = new VM("./assets", 4096, new TheRealWorld(), new VMProgramRom[]{PipBios.INSTANCE, PipROM.INSTANCE}, 8); - vm.getIO().getBlockTransferPorts()[0].attachDevice(new TestDiskDrive(vm, 0, new File(diskPath))); + vm.getIO().getBlockTransferPorts()[0].attachDevice(new TestDiskDrive(vm, 0, diskPath)); vm.getIO().getBlockTransferPorts()[1].attachDevice(new HttpModem(vm)); diff --git a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt index 6ce8a67..9236442 100644 --- a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt +++ b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt @@ -4,6 +4,8 @@ import com.badlogic.gdx.ApplicationAdapter import com.badlogic.gdx.Gdx import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.SpriteBatch +import com.badlogic.gdx.utils.Json +import com.badlogic.gdx.utils.JsonReader import com.badlogic.gdx.utils.JsonValue import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job @@ -97,13 +99,19 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: // install the default VM on slot 0 - val vm = VM("./assets", 8192 shl 10, TheRealWorld(), arrayOf(TsvmBios), 8) + /*val vm = VM("./assets", 8192 shl 10, TheRealWorld(), arrayOf(TsvmBios), 8) vm.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm, 0, File("assets/disk0"))) initVMenv(vm) - vms[0] = VMRunnerInfo(vm, "Initial VM") + vms[0] = VMRunnerInfo(vm, "Initial VM")*/ + + val testJson = JsonReader().parse("{$defaultProfile}") + val vm1 = makeVMfromJson(testJson.get("Initial VM")) + initVMenv(vm1) + vms[0] = VMRunnerInfo(vm1, "Initial VM") + val vm2 = VM("./assets", 64 shl 10, TheRealWorld(), arrayOf(TsvmBios), 8) - vm2.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm2, 0, File("assets/disk0"))) + vm2.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm2, 0, "assets/disk0")) initVMenv(vm2) vms[1] = VMRunnerInfo(vm2, "Initial VM2") @@ -379,8 +387,8 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: "assetsdir":"./assets", "ramsize":8388608, "cardslots":8, - "roms":["bios/tsvmbios.js"], - "com1":{"class":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "disk0/"]}, + "roms":["./assets/bios/tsvmbios.js"], + "com1":{"class":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "./assets/disk0/"]}, "com2":{"class":"net.torvald.tsvm.peripheral.HttpModem", "args":[]}, "card4":{"class":"net.torvald.tsvm.peripheral.RamBank", "args":[256]} } @@ -400,7 +408,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: val assetsDir = json.getString("assetsdir") val ramsize = json.getLong("ramsize") val cardslots = json.getInt("cardslots") - val roms = json.get("roms").iterator().map { VMProgramRom("$assetsDir/${it.asString()}") }.toTypedArray() + val roms = json.get("roms").iterator().map { VMProgramRom(it.asString()) }.toTypedArray() val vm = VM(assetsDir, ramsize, TheRealWorld(), roms, cardslots) @@ -410,12 +418,38 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: val className = deviceInfo.getString("class") val loadedClass = Class.forName(className) - val argTypes = loadedClass.declaredConstructors[0].parameterTypes - val args = deviceInfo.get("args").allIntoJavaType(argTypes) - val loadedClassConstructor = loadedClass.getConstructor(*argTypes) - val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args) - vm.getIO().blockTransferPorts[index].attachDevice(loadedClassInstance as BlockTransferInterface) + val argTypess = loadedClass.declaredConstructors + var successful = false + var k = 0 + // just try out all the possible argTypes + while (!successful && k < argTypess.size) { + try { + val argTypes = argTypess[k].parameterTypes + + println("loadedClass = $className") + println("trying constructor args[${k}/${argTypess.lastIndex}]: ${argTypes.joinToString { it.canonicalName }}") + + val args = deviceInfo.get("args").allIntoJavaType(argTypes.tail()) + val loadedClassConstructor = loadedClass.getConstructor(*argTypes) + val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args) + + vm.getIO().blockTransferPorts[index].attachDevice(loadedClassInstance as BlockTransferInterface) + println("COM${index+1} = ${loadedClassInstance.javaClass.canonicalName}: ${args.joinToString()}") + + successful = true + } + catch (e: IllegalArgumentException) { +// e.printStackTrace() + } + finally { + k += 1 + } + } + if (!successful) { + throw RuntimeException("Invalid or insufficient arguments for ${className}") + } + } } (2..cardslots).map { it to json.get("card$it") }.forEach { (index, jsonValue) -> @@ -424,7 +458,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: val loadedClass = Class.forName(className) val argTypes = loadedClass.declaredConstructors[0].parameterTypes - val args = deviceInfo.get("args").allIntoJavaType(argTypes) + val args = deviceInfo.get("args").allIntoJavaType(argTypes.tail()) val loadedClassConstructor = loadedClass.getConstructor(*argTypes) val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args) @@ -438,9 +472,25 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX: return vm } - private fun JsonValue.allIntoJavaType(argTypes: Array>?): Array { - TODO("Not yet implemented") + private fun JsonValue.allIntoJavaType(argTypes: Array>): Array { + val values = this.iterator().toList() + if (values.size != argTypes.size) throw IllegalArgumentException("# of args: ${values.size}, # of arg types: ${argTypes.size}") + + return argTypes.mapIndexed { index, it -> when (it.canonicalName) { + "float", "java.lang.Float" -> values[index].asFloat() + "double", "java.lang.Double" -> values[index].asDouble() + "byte", "java.lang.Byte" -> values[index].asByte() + "char", "java.lang.Character" -> values[index].asChar() + "short", "java.lang.Short" -> values[index].asShort() + "int", "java.lang.Integer" -> values[index].asInt() + "long", "java.lang.Long" -> values[index].asLong() + "boolean", "java.lang.Boolean" -> values[index].asBoolean() + "java.lang.String" -> values[index].asString() + else -> throw NotImplementedError("No conversion for ${it.canonicalName} exists") + } }.toTypedArray() } + + private fun Array.tail(): Array = this.sliceArray(1..this.lastIndex) }