mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-11 23:34:04 +09:00
ability to load vm using json configuration
This commit is contained in:
@@ -10,7 +10,7 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* @param driveNum 0 for COM drive number 1, but the file path will still be zero-based
|
* @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 {
|
companion object {
|
||||||
const val STATE_CODE_STANDBY = 0
|
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")
|
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 fileOpen = false
|
||||||
private var fileOpenMode = -1 // 1: 'W", 2: 'A'
|
private var fileOpenMode = -1 // 1: 'W", 2: 'A'
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class AppLoader {
|
|||||||
// VM vm = new VM("./assets", 8192 << 10, new TheRealWorld(), new VMProgramRom[]{OpenBios.INSTANCE}, 8);
|
// 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 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));
|
vm.getIO().getBlockTransferPorts()[1].attachDevice(new HttpModem(vm));
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import com.badlogic.gdx.ApplicationAdapter
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
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 com.badlogic.gdx.utils.JsonValue
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
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
|
// 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")))
|
vm.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm, 0, File("assets/disk0")))
|
||||||
initVMenv(vm)
|
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)
|
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)
|
initVMenv(vm2)
|
||||||
vms[1] = VMRunnerInfo(vm2, "Initial VM2")
|
vms[1] = VMRunnerInfo(vm2, "Initial VM2")
|
||||||
|
|
||||||
@@ -379,8 +387,8 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
|
|||||||
"assetsdir":"./assets",
|
"assetsdir":"./assets",
|
||||||
"ramsize":8388608,
|
"ramsize":8388608,
|
||||||
"cardslots":8,
|
"cardslots":8,
|
||||||
"roms":["bios/tsvmbios.js"],
|
"roms":["./assets/bios/tsvmbios.js"],
|
||||||
"com1":{"class":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "disk0/"]},
|
"com1":{"class":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "./assets/disk0/"]},
|
||||||
"com2":{"class":"net.torvald.tsvm.peripheral.HttpModem", "args":[]},
|
"com2":{"class":"net.torvald.tsvm.peripheral.HttpModem", "args":[]},
|
||||||
"card4":{"class":"net.torvald.tsvm.peripheral.RamBank", "args":[256]}
|
"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 assetsDir = json.getString("assetsdir")
|
||||||
val ramsize = json.getLong("ramsize")
|
val ramsize = json.getLong("ramsize")
|
||||||
val cardslots = json.getInt("cardslots")
|
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)
|
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 className = deviceInfo.getString("class")
|
||||||
|
|
||||||
val loadedClass = Class.forName(className)
|
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) ->
|
(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 loadedClass = Class.forName(className)
|
||||||
val argTypes = loadedClass.declaredConstructors[0].parameterTypes
|
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 loadedClassConstructor = loadedClass.getConstructor(*argTypes)
|
||||||
val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args)
|
val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args)
|
||||||
|
|
||||||
@@ -438,9 +472,25 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
|
|||||||
return vm
|
return vm
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun JsonValue.allIntoJavaType(argTypes: Array<Class<*>>?): Array<Any> {
|
private fun JsonValue.allIntoJavaType(argTypes: Array<Class<*>>): Array<Any?> {
|
||||||
TODO("Not yet implemented")
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user