profile.json rw wip

This commit is contained in:
minjaesong
2022-10-27 13:06:03 +09:00
parent 60b4834c72
commit 024e97c31c
3 changed files with 174 additions and 10 deletions

View File

@@ -0,0 +1,91 @@
package net.torvald.terrarum.utils
import com.badlogic.gdx.utils.JsonReader
import com.badlogic.gdx.utils.JsonValue
/**
* Created by minjaesong on 2016-02-15.
*/
object JsonFetcher {
private var jsonString: StringBuffer? = null
@Throws(java.io.IOException::class)
operator fun invoke(jsonFilePath: String): JsonValue {
jsonString = StringBuffer() // reset buffer every time it called
readJsonFileAsString(jsonFilePath)
// printdbg(this, "Reading JSON $jsonFilePath")
if (jsonString == null) {
throw Error("[JsonFetcher] jsonString is null!")
}
return JsonReader().parse(jsonString.toString())
}
@Throws(java.io.IOException::class)
operator fun invoke(jsonFile: java.io.File): JsonValue {
jsonString = StringBuffer() // reset buffer every time it called
readJsonFileAsString(jsonFile.canonicalPath)
// printdbg(this, "Reading JSON ${jsonFile.path}")
if (jsonString == null) {
throw Error("[JsonFetcher] jsonString is null!")
}
return JsonReader().parse(jsonString.toString())
}
@Throws(java.io.IOException::class)
private fun readJsonFileAsString(path: String) {
java.nio.file.Files.lines(java.nio.file.FileSystems.getDefault().getPath(path)).forEach(
{ jsonString!!.append(it) }
) // JSON does not require line break
}
/**
* Iterates [JsonValue] over its siblings.
*
* @param map JsonValue to iterate over
* @param action A `function(`Name of the sibling or a stringified integer if the `map` is an array`, `JsonValue representation of the sibling`)` -> `Unit`
*/
fun forEachSiblings(map: JsonValue, action: (String, JsonValue) -> Unit) {
var counter = 0
var entry = map.child
while (entry != null) {
action(entry.name ?: "$counter", entry)
entry = entry.next
counter += 1
}
}
/**
* Iterates [JsonValue] over its siblings.
*
* @param map JsonValue to iterate over
* @param action A `function(index, `Name of the sibling or a stringified integer if the `map` is an array`, `JsonValue representation of the sibling`)` -> `Unit`
*/
fun forEachSiblingsIndexed(map: JsonValue, action: (Int, String, JsonValue) -> Unit) {
var counter = 0
var entry = map.child
while (entry != null) {
action(counter, entry.name ?: "$counter", entry)
entry = entry.next
counter += 1
}
}
}
/**
* Iterates [JsonValue] over its siblings.
* @param action A function(`Name of the sibling or a stringified integer if the `map` is an array`, `JsonValue representation of the sibling`)` -> `Unit`
*/
fun JsonValue.forEachSiblings(action: (String, JsonValue) -> Unit) = JsonFetcher.forEachSiblings(this, action)
/**
* Iterates [JsonValue] over its siblings.
* @param action A `function(index, `Name of the sibling or a stringified integer if the `map` is an array`, `JsonValue representation of the sibling`)` -> `Unit`
*/
fun JsonValue.forEachSiblingsIndexed(action: (Int, String, JsonValue) -> Unit) = JsonFetcher.forEachSiblingsIndexed(this, action)

View File

@@ -0,0 +1,32 @@
package net.torvald.tsvm
import com.badlogic.gdx.utils.Json
import com.badlogic.gdx.utils.JsonValue
import com.badlogic.gdx.utils.JsonWriter
import java.math.BigInteger
/**
* Created by minjaesong on 2022-10-27.
*/
object ProfileSerialiser {
val jsoner = Json(JsonWriter.OutputType.json)
init {
jsoner.ignoreUnknownFields = true
jsoner.setUsePrototypes(false)
jsoner.setIgnoreDeprecated(false)
// BigInteger
jsoner.setSerializer(BigInteger::class.java, object : Json.Serializer<BigInteger> {
override fun write(json: Json, obj: BigInteger?, knownType: Class<*>?) {
json.writeValue(obj?.toString())
}
override fun read(json: Json, jsonData: JsonValue, type: Class<*>?): BigInteger? {
return if (jsonData.isNull) null else BigInteger(jsonData.asString())
}
})
//
}
}

View File

@@ -2,22 +2,22 @@ package net.torvald.tsvm
import com.badlogic.gdx.ApplicationAdapter import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.files.FileHandle
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.JsonReader
import com.badlogic.gdx.utils.JsonValue import com.badlogic.gdx.utils.JsonValue
import com.badlogic.gdx.utils.JsonWriter
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.torvald.terrarum.FlippingSpriteBatch import net.torvald.terrarum.FlippingSpriteBatch
import net.torvald.terrarum.imagefont.TinyAlphNum import net.torvald.terrarum.imagefont.TinyAlphNum
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT
import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.SQTEX import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.SQTEX
import net.torvald.tsvm.peripheral.* import net.torvald.tsvm.peripheral.*
import java.io.File
import java.util.*
class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var panelsX: Int, var panelsY: Int, val diskPathRoot: String) : ApplicationAdapter() { class VMEmuExecutableWrapper(val windowWidth: Int, val windowHeight: Int, var panelsX: Int, var panelsY: Int, val diskPathRoot: String) : ApplicationAdapter() {
@@ -77,6 +77,17 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
var vmRunners = HashMap<Int, VMRunner>() // <VM's identifier, VMRunner> var vmRunners = HashMap<Int, VMRunner>() // <VM's identifier, VMRunner>
var coroutineJobs = HashMap<Int, Job>() // <VM's identifier, Job> var coroutineJobs = HashMap<Int, Job>() // <VM's identifier, Job>
companion object {
val APPDATADIR = System.getProperty("os.name").toUpperCase().let {
if (it.contains("WIN")) System.getenv("APPDATA") + "/tsvmdevenv"
else if (it.contains("OS X") || it.contains("MACOS")) System.getProperty("user.home") + "/Library/Application Support/tsvmdevenv"
else System.getProperty("user.home") + "/.tsvmdevenv"
}
val FILE_CONFIG = Gdx.files.absolute("$APPDATADIR/config.json")
val FILE_PROFILES = Gdx.files.absolute("$APPDATADIR/profiles.json")
}
val fullscreenQuad = Mesh( val fullscreenQuad = Mesh(
true, 4, 6, true, 4, 6,
VertexAttribute.Position(), VertexAttribute.Position(),
@@ -84,6 +95,26 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
VertexAttribute.TexCoords(0) VertexAttribute.TexCoords(0)
) )
val profiles = HashMap<String, JsonValue>()
fun writeProfilesToFile(outFile: FileHandle) {
val out = StringBuilder()
out.append('{')
profiles.forEach { name, jsonValue ->
out.append("\"$name\":{")
out.append(jsonValue.toJson(JsonWriter.OutputType.json))
out.append("},")
}
out.deleteCharAt(out.lastIndex).append('}')
val outstr = out.toString()
println(outstr)
outFile.writeString(outstr, false)
}
override fun create() { override fun create() {
super.create() super.create()
@@ -98,6 +129,18 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
fbatch.projectionMatrix = camera.combined fbatch.projectionMatrix = camera.combined
// create profiles.json if the file is not there
if (!FILE_PROFILES.exists()) {
FILE_PROFILES.writeString("{${defaultProfile}}", false)
}
// read profiles
JsonFetcher(FILE_PROFILES.file()).let {
JsonFetcher.forEachSiblings(it) { profileName, profileJson ->
profiles[profileName] = profileJson
}
}
// 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")))
@@ -326,8 +369,6 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
private val tabPos = (menuTabs + "").mapIndexed { index, _ -> 1 + menuTabs.subList(0, index).sumBy { it.length } + 2 * index } private val tabPos = (menuTabs + "").mapIndexed { index, _ -> 1 + menuTabs.subList(0, index).sumBy { it.length } + 2 * index }
private val tabs = listOf(ProfilesMenu(menuTabW, menuTabH)) private val tabs = listOf(ProfilesMenu(menuTabW, menuTabH))
private var menuTabSel = 0 private var menuTabSel = 0
private val profilesPath = "profiles.json"
private val configPath = "config.json"
private fun drawMenu(batch: SpriteBatch, x: Float, y: Float) { private fun drawMenu(batch: SpriteBatch, x: Float, y: Float) {
batch.inUse { batch.inUse {
@@ -388,9 +429,9 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
"ramsize":8388608, "ramsize":8388608,
"cardslots":8, "cardslots":8,
"roms":["./assets/bios/tsvmbios.js"], "roms":["./assets/bios/tsvmbios.js"],
"com1":{"class":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "./assets/disk0/"]}, "com1":{"cls":"net.torvald.tsvm.peripheral.TestDiskDrive", "args":[0, "./assets/disk0/"]},
"com2":{"class":"net.torvald.tsvm.peripheral.HttpModem", "args":[]}, "com2":{"cls":"net.torvald.tsvm.peripheral.HttpModem", "args":[]},
"card4":{"class":"net.torvald.tsvm.peripheral.RamBank", "args":[256]} "card4":{"cls":"net.torvald.tsvm.peripheral.RamBank", "args":[256]}
} }
""".trimIndent() """.trimIndent()
@@ -415,7 +456,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
// install peripherals // install peripherals
listOf("com1", "com2", "com3", "com4").map { json.get(it) }.forEachIndexed { index, jsonValue -> listOf("com1", "com2", "com3", "com4").map { json.get(it) }.forEachIndexed { index, jsonValue ->
jsonValue?.let { deviceInfo -> jsonValue?.let { deviceInfo ->
val className = deviceInfo.getString("class") val className = deviceInfo.getString("cls")
val loadedClass = Class.forName(className) val loadedClass = Class.forName(className)
@@ -454,7 +495,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
} }
(2..cardslots).map { it to json.get("card$it") }.forEach { (index, jsonValue) -> (2..cardslots).map { it to json.get("card$it") }.forEach { (index, jsonValue) ->
jsonValue?.let { deviceInfo -> jsonValue?.let { deviceInfo ->
val className = deviceInfo.getString("class") val className = deviceInfo.getString("cls")
val loadedClass = Class.forName(className) val loadedClass = Class.forName(className)
val argTypes = loadedClass.declaredConstructors[0].parameterTypes val argTypes = loadedClass.declaredConstructors[0].parameterTypes