ability to load vm using json configuration

This commit is contained in:
minjaesong
2022-10-26 21:27:15 +09:00
parent 22472e6103
commit 60b4834c72
3 changed files with 67 additions and 17 deletions

View File

@@ -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'

View File

@@ -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));

View File

@@ -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<Class<*>>?): Array<Any> {
TODO("Not yet implemented")
private fun JsonValue.allIntoJavaType(argTypes: Array<Class<*>>): Array<Any?> {
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 <T> Array<T>.tail(): Array<T> = this.sliceArray(1..this.lastIndex)
}