mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-11 15:24:05 +09:00
reading config from config.json
This commit is contained in:
@@ -71,13 +71,13 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
val loadedClassInstance = loadedClassConstructor.newInstance("./assets", vm)
|
val loadedClassInstance = loadedClassConstructor.newInstance("./assets", vm)
|
||||||
gpu = (loadedClassInstance as GraphicsAdapter)
|
gpu = (loadedClassInstance as GraphicsAdapter)
|
||||||
|
|
||||||
vm.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm, 0, File(loaderInfo.diskPath)))
|
vm.getIO().blockTransferPorts[0].attachDevice(TestDiskDrive(vm, 0, loaderInfo.diskPath))
|
||||||
|
|
||||||
vm.peripheralTable[1] = PeripheralEntry(
|
vm.peripheralTable[1] = PeripheralEntry(
|
||||||
gpu,
|
gpu,
|
||||||
GraphicsAdapter.VRAM_SIZE,
|
// GraphicsAdapter.VRAM_SIZE,
|
||||||
16,
|
// 16,
|
||||||
0
|
// 0
|
||||||
)
|
)
|
||||||
|
|
||||||
vm.getPrintStream = { gpu!!.getPrintStream() }
|
vm.getPrintStream = { gpu!!.getPrintStream() }
|
||||||
@@ -99,9 +99,9 @@ class VMGUI(val loaderInfo: EmulInstance, val viewportWidth: Int, val viewportHe
|
|||||||
|
|
||||||
vm.peripheralTable[port] = PeripheralEntry(
|
vm.peripheralTable[port] = PeripheralEntry(
|
||||||
loadedClassInstance as PeriBase,
|
loadedClassInstance as PeriBase,
|
||||||
peri.memsize,
|
// peri.memsize,
|
||||||
peri.mmioSize,
|
// peri.mmioSize,
|
||||||
peri.interruptCount
|
// peri.interruptCount
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
102
tsvm_executable/src/net/torvald/terrarum/KVHashMap.kt
Normal file
102
tsvm_executable/src/net/torvald/terrarum/KVHashMap.kt
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package net.torvald.terrarum
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2015-12-30.
|
||||||
|
*/
|
||||||
|
open class KVHashMap {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
hashMap = HashMap<String, Any>()
|
||||||
|
}
|
||||||
|
|
||||||
|
protected constructor(newMap: HashMap<String, Any>) {
|
||||||
|
hashMap = newMap
|
||||||
|
}
|
||||||
|
|
||||||
|
var hashMap: HashMap<String, Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add key-value pair to the configuration table.
|
||||||
|
* If key does not exist on the table, new key will be generated.
|
||||||
|
* If key already exists, the value will be overwritten.
|
||||||
|
|
||||||
|
* @param key case insensitive
|
||||||
|
* *
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
open operator fun set(key: String, value: Any) {
|
||||||
|
hashMap.put(key.toLowerCase(), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get value using key from configuration table.
|
||||||
|
|
||||||
|
* @param key case insensitive
|
||||||
|
* *
|
||||||
|
* @return Object value
|
||||||
|
*/
|
||||||
|
operator fun get(key: String): Any? {
|
||||||
|
return hashMap[key.toLowerCase()]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAsInt(key: String): Int? {
|
||||||
|
val value = get(key)
|
||||||
|
|
||||||
|
if (value == null) return null
|
||||||
|
|
||||||
|
return value as Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAsDouble(key: String): Double? {
|
||||||
|
val value = get(key)
|
||||||
|
|
||||||
|
if (value == null) return null
|
||||||
|
|
||||||
|
if (value is Int)
|
||||||
|
return value.toDouble()
|
||||||
|
|
||||||
|
return value as Double
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAsFloat(key: String): Float? {
|
||||||
|
val value = get(key)
|
||||||
|
|
||||||
|
if (value == null) return null
|
||||||
|
|
||||||
|
if (value is Float) return value as Float
|
||||||
|
|
||||||
|
return getAsDouble(key)?.toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAsString(key: String): String? {
|
||||||
|
val value = get(key)
|
||||||
|
|
||||||
|
if (value == null) return null
|
||||||
|
|
||||||
|
return value as String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAsBoolean(key: String): Boolean? {
|
||||||
|
val value = get(key)
|
||||||
|
|
||||||
|
if (value == null) return null
|
||||||
|
|
||||||
|
return value as Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasKey(key: String) = hashMap.containsKey(key)
|
||||||
|
|
||||||
|
val keySet: Set<Any>
|
||||||
|
get() = hashMap.keys
|
||||||
|
|
||||||
|
open fun remove(key: String) {
|
||||||
|
if (hashMap[key] != null) {
|
||||||
|
hashMap.remove(key, hashMap[key]!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun clone(): KVHashMap {
|
||||||
|
val cloneOfMap = hashMap.clone() as HashMap<String, Any>
|
||||||
|
return KVHashMap(cloneOfMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Json
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
|
import com.badlogic.gdx.utils.JsonWriter
|
||||||
|
import net.torvald.terrarum.KVHashMap
|
||||||
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
|
import net.torvald.tsvm.TsvmEmulator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2021-09-19.
|
||||||
|
*/
|
||||||
|
object WriteConfig {
|
||||||
|
|
||||||
|
private val jsoner = Json(JsonWriter.OutputType.json)
|
||||||
|
|
||||||
|
init {
|
||||||
|
jsoner.ignoreUnknownFields = true
|
||||||
|
jsoner.setUsePrototypes(false)
|
||||||
|
jsoner.setIgnoreDeprecated(false)
|
||||||
|
|
||||||
|
// KVHashMap
|
||||||
|
jsoner.setSerializer(KVHashMap::class.java, object : Json.Serializer<KVHashMap> {
|
||||||
|
override fun write(json: Json, obj: KVHashMap, knownType: Class<*>?) {
|
||||||
|
json.writeObjectStart()
|
||||||
|
obj.hashMap.toSortedMap().forEach { (k, v) ->
|
||||||
|
json.writeValue(k, v)
|
||||||
|
}
|
||||||
|
json.writeObjectEnd()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun read(json: Json, jsonData: JsonValue, type: Class<*>?): KVHashMap {
|
||||||
|
val map = KVHashMap()
|
||||||
|
JsonFetcher.forEachSiblings(jsonData) { key, obj ->
|
||||||
|
map[key] = json.readValue(null, obj)
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fun getJson(): String {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
|
||||||
|
App.gameConfig.hashMap.toSortedMap().forEach { (k, v) ->
|
||||||
|
sb.append("$k:")
|
||||||
|
|
||||||
|
when (v) {
|
||||||
|
is DoubleArray -> { sb.append("[${v.joinToString(",")}]") }
|
||||||
|
is IntArray -> { sb.append("[${v.joinToString(",")}]") }
|
||||||
|
is Array<*> -> { sb.append("[${v.joinToString(",")}]") }
|
||||||
|
else -> { sb.append("$v") }
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
return "{\n$sb}"
|
||||||
|
}*/
|
||||||
|
|
||||||
|
operator fun invoke() {
|
||||||
|
val writer = java.io.FileWriter(TsvmEmulator.configDir, false)
|
||||||
|
//writer.write(getJson())
|
||||||
|
writer.write(jsoner.prettyPrint(TsvmEmulator.gameConfig))
|
||||||
|
writer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
15
tsvm_executable/src/net/torvald/tsvm/DefaultConfig.kt
Normal file
15
tsvm_executable/src/net/torvald/tsvm/DefaultConfig.kt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
package net.torvald.tsvm
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2022-11-02.
|
||||||
|
*/
|
||||||
|
object DefaultConfig {
|
||||||
|
|
||||||
|
val hashMap = hashMapOf<String, Any>(
|
||||||
|
"viewport_width" to 640,
|
||||||
|
"viewport_height" to 480,
|
||||||
|
"viewports_rows" to 2,
|
||||||
|
"viewports_cols" to 3
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package net.torvald.tsvm
|
package net.torvald.tsvm
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
import com.badlogic.gdx.Input.Buttons
|
||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT
|
import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT
|
||||||
@@ -32,12 +34,33 @@ class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : Em
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun update() {
|
override fun update() {
|
||||||
|
|
||||||
|
if (Gdx.input.isButtonPressed(Buttons.LEFT)) {
|
||||||
|
val mx = Gdx.input.x - x
|
||||||
|
val my = Gdx.input.y - y
|
||||||
|
|
||||||
|
if (mx in 10 until 10+228) {
|
||||||
|
if (my in 11 until 11+446) {
|
||||||
|
val li = (my - 11) / (2*FONT.H)
|
||||||
|
|
||||||
|
if (li < profileNames.size - profilesScroll)
|
||||||
|
selectedProfileIndex = li + profilesScroll
|
||||||
|
else
|
||||||
|
selectedProfileIndex = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun render(batch: SpriteBatch) {
|
override fun render(batch: SpriteBatch) {
|
||||||
batch.inUse {
|
batch.inUse {
|
||||||
batch.color = EmulatorGuiToolkit.Theme.COL_WELL
|
// draw list of installed profiles
|
||||||
it.fillRect(10, 11, 228, 446)
|
for (i in 0 until PROFILES_ROWS) {
|
||||||
|
batch.color = if (i % 2 == 0) EmulatorGuiToolkit.Theme.COL_WELL
|
||||||
|
else EmulatorGuiToolkit.Theme.COL_WELL2
|
||||||
|
batch.fillRect(10, 11 + i*2*FONT.H, 228, 2*FONT.H)
|
||||||
|
}
|
||||||
|
|
||||||
for (i in 0 until Math.min(PROFILES_ROWS, profileNames.size)) {
|
for (i in 0 until Math.min(PROFILES_ROWS, profileNames.size)) {
|
||||||
val index = profilesScroll + i
|
val index = profilesScroll + i
|
||||||
@@ -47,6 +70,8 @@ class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : Em
|
|||||||
else EmulatorGuiToolkit.Theme.COL_WELL2
|
else EmulatorGuiToolkit.Theme.COL_WELL2
|
||||||
val colFore = if (index == selectedProfileIndex) EmulatorGuiToolkit.Theme.COL_ACTIVE
|
val colFore = if (index == selectedProfileIndex) EmulatorGuiToolkit.Theme.COL_ACTIVE
|
||||||
else EmulatorGuiToolkit.Theme.COL_ACTIVE2
|
else EmulatorGuiToolkit.Theme.COL_ACTIVE2
|
||||||
|
val colFore2 = if (index == selectedProfileIndex) EmulatorGuiToolkit.Theme.COL_ACTIVE3
|
||||||
|
else EmulatorGuiToolkit.Theme.COL_INACTIVE3
|
||||||
|
|
||||||
val theVM = parent.getVMbyProfileName(profileNames[index])
|
val theVM = parent.getVMbyProfileName(profileNames[index])
|
||||||
val isVMrunning = if (theVM != null) !theVM.disposed && theVM.startTime >= 0 else false
|
val isVMrunning = if (theVM != null) !theVM.disposed && theVM.startTime >= 0 else false
|
||||||
@@ -56,14 +81,43 @@ class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : Em
|
|||||||
val vmViewportText = if (vmViewport != null) "on viewport #${vmViewport+1}" else "and hidden"
|
val vmViewportText = if (vmViewport != null) "on viewport #${vmViewport+1}" else "and hidden"
|
||||||
|
|
||||||
batch.color = colBack
|
batch.color = colBack
|
||||||
it.fillRect(10, 11 + i*2*FONT.H, 228, 26)
|
batch.fillRect(10, 11 + i*2*FONT.H, 228, 2*FONT.H)
|
||||||
|
|
||||||
batch.color = colFore
|
batch.color = colFore
|
||||||
FONT.draw(batch, profileNames[index], 12f, 11f + i*2*FONT.H)
|
FONT.draw(batch, profileNames[index], 12f, 11f + i*2*FONT.H)
|
||||||
batch.color = EmulatorGuiToolkit.Theme.COL_ACTIVE3
|
batch.color = colFore2
|
||||||
FONT.draw(batch, "$vmRunStatusText $vmViewportText", 12f, 11f+FONT.H + i*2*FONT.H)
|
FONT.draw(batch, "$vmRunStatusText $vmViewportText", 12f, 11f+FONT.H + i*2*FONT.H)
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw profile detals view
|
||||||
|
batch.color = EmulatorGuiToolkit.Theme.COL_WELL2
|
||||||
|
batch.fillRect(251, 11, 375, 403)
|
||||||
|
batch.fillRect(251, 427, 375, 26)
|
||||||
|
|
||||||
|
if (selectedProfileIndex != null) profileNames[selectedProfileIndex!!].let { profileName ->
|
||||||
|
val profile = parent.profiles[profileName]!!
|
||||||
|
|
||||||
|
val ramsize = profile.getLong("ramsize")
|
||||||
|
val cardslots = profile.getInt("cardslots")
|
||||||
|
val roms = profile.get("roms").iterator().map { it }
|
||||||
|
val extraRomCount = roms.size - 1
|
||||||
|
val coms = (1..4).map { profile.get("com$it")?.getString("cls") } // full classname of the COM device
|
||||||
|
val cards = (1 until cardslots).map { profile.get("card$it")?.getString("cls") } // full classname of the cards
|
||||||
|
|
||||||
|
batch.color = Color.WHITE
|
||||||
|
FONT.draw(batch, "Memory: $ramsize bytes", 253f, 11f)
|
||||||
|
FONT.draw(batch, "Card Slots: $cardslots", 253f, 11f + 1*FONT.H)
|
||||||
|
FONT.draw(batch, "Extra ROMs: ${if (extraRomCount == 0) "none" else extraRomCount}", 253f, 11f + 2*FONT.H)
|
||||||
|
FONT.draw(batch, "COM Ports:", 253f, 11f + 4*FONT.H)
|
||||||
|
for (i in 1..4) {
|
||||||
|
FONT.draw(batch, "$i) ${coms[i-1]?.let { it.substring(it.lastIndexOf('.')+1) } ?: ""}", 253f, 11f + (4+i)*FONT.H)
|
||||||
|
}
|
||||||
|
|
||||||
|
FONT.draw(batch, "Peripherals (cards):", 253f, 11f + 10*FONT.H)
|
||||||
|
FONT.draw(batch, "1) [Emulated Reference Graphics Adapter]", 253f, 11f + 11*FONT.H)
|
||||||
|
for (i in 2 until cardslots) {
|
||||||
|
FONT.draw(batch, "$i) ${cards[i-1]?.let { it.substring(it.lastIndexOf('.')+1) } ?: ""}", 253f, 11f + (10+i)*FONT.H)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,15 @@ import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
|
|||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.utils.JsonValue;
|
||||||
|
import net.torvald.terrarum.KVHashMap;
|
||||||
|
import net.torvald.terrarum.serialise.WriteConfig;
|
||||||
|
import net.torvald.terrarum.utils.JsonFetcher;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2022-10-22.
|
* Created by minjaesong on 2022-10-22.
|
||||||
@@ -15,14 +24,64 @@ public class TsvmEmulator {
|
|||||||
public static String appTitle = "tsvm";
|
public static String appTitle = "tsvm";
|
||||||
public static Lwjgl3ApplicationConfiguration appConfig;
|
public static Lwjgl3ApplicationConfiguration appConfig;
|
||||||
|
|
||||||
public static int WIDTH = 640 * 2;
|
public static int PANELS_X = 2;
|
||||||
public static int HEIGHT = 480 * 2;
|
public static int PANELS_Y = 2;
|
||||||
|
public static int VIEWPORT_W = 640;
|
||||||
|
public static int VIEWPORT_H = 480;
|
||||||
|
|
||||||
|
public static int WIDTH = VIEWPORT_W * PANELS_X;
|
||||||
|
public static int HEIGHT = VIEWPORT_H * PANELS_Y;
|
||||||
|
|
||||||
|
public static String OSName = System.getProperty("os.name");
|
||||||
|
public static String OSVersion = System.getProperty("os.version");
|
||||||
|
public static String operationSystem;
|
||||||
|
/** %appdata%/Terrarum, without trailing slash */
|
||||||
|
public static String defaultDir;
|
||||||
|
/** defaultDir + "/config.json" */
|
||||||
|
public static String configDir;
|
||||||
|
/** defaultDir + "/profiles.json" */
|
||||||
|
public static String profilesDir;
|
||||||
|
|
||||||
|
public static KVHashMap gameConfig = new KVHashMap();
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
ShaderProgram.pedantic = false;
|
ShaderProgram.pedantic = false;
|
||||||
|
|
||||||
|
getDefaultDirectory();
|
||||||
|
|
||||||
|
// initialise the game config
|
||||||
|
for (Map.Entry<String, Object> entry : DefaultConfig.INSTANCE.getHashMap().entrySet()) {
|
||||||
|
gameConfig.set(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually read the config.json
|
||||||
|
try {
|
||||||
|
// read from disk and build config from it
|
||||||
|
JsonValue map = JsonFetcher.INSTANCE.invoke(configDir);
|
||||||
|
|
||||||
|
// make config
|
||||||
|
for (JsonValue entry = map.child; entry != null; entry = entry.next) {
|
||||||
|
setToGameConfigForced(entry, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// write default config to game dir. Call th.is method again to read config from it.
|
||||||
|
try {
|
||||||
|
createConfigJson();
|
||||||
|
}
|
||||||
|
catch (IOException e1) {
|
||||||
|
System.out.println("[AppLoader] Unable to write config.json file");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PANELS_X = Math.max(2, getConfigInt("viewports_cols"));
|
||||||
|
PANELS_Y = Math.max(2, getConfigInt("viewports_rows"));
|
||||||
|
VIEWPORT_W = Math.max(560, getConfigInt("viewport_width"));
|
||||||
|
VIEWPORT_H = Math.max(448, getConfigInt("viewport_height"));
|
||||||
|
WIDTH = VIEWPORT_W * PANELS_X;
|
||||||
|
HEIGHT = VIEWPORT_H * PANELS_Y;
|
||||||
|
|
||||||
appConfig = new Lwjgl3ApplicationConfiguration();
|
appConfig = new Lwjgl3ApplicationConfiguration();
|
||||||
appConfig.setIdleFPS(60);
|
appConfig.setIdleFPS(60);
|
||||||
appConfig.setForegroundFPS(60);
|
appConfig.setForegroundFPS(60);
|
||||||
@@ -32,7 +91,224 @@ public class TsvmEmulator {
|
|||||||
|
|
||||||
appConfig.setWindowedMode(WIDTH, HEIGHT);
|
appConfig.setWindowedMode(WIDTH, HEIGHT);
|
||||||
|
|
||||||
new Lwjgl3Application(new VMEmuExecutableWrapper(640, 480, 2, 2,"assets/"), appConfig);
|
new Lwjgl3Application(new VMEmuExecutableWrapper(VIEWPORT_W, VIEWPORT_H, PANELS_X, PANELS_Y,"assets/"), appConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void getDefaultDirectory() {
|
||||||
|
String OS = OSName.toUpperCase();
|
||||||
|
if (OS.contains("WIN")) {
|
||||||
|
operationSystem = "WINDOWS";
|
||||||
|
defaultDir = System.getenv("APPDATA") + "/tsvmdevenv";
|
||||||
|
}
|
||||||
|
else if (OS.contains("OS X") || OS.contains("MACOS")) { // OpenJDK for mac will still report "Mac OS X" with version number "10.16", even on Big Sur and beyond
|
||||||
|
operationSystem = "OSX";
|
||||||
|
defaultDir = System.getProperty("user.home") + "/Library/Application Support/tsvmdevenv";
|
||||||
|
}
|
||||||
|
else if (OS.contains("NUX") || OS.contains("NIX") || OS.contains("BSD")) {
|
||||||
|
operationSystem = "LINUX";
|
||||||
|
defaultDir = System.getProperty("user.home") + "/.tsvmdevenv";
|
||||||
|
}
|
||||||
|
else if (OS.contains("SUNOS")) {
|
||||||
|
operationSystem = "SOLARIS";
|
||||||
|
defaultDir = System.getProperty("user.home") + "/.tsvmdevenv";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
operationSystem = "UNKNOWN";
|
||||||
|
defaultDir = System.getProperty("user.home") + "/.tsvmdevenv";
|
||||||
|
}
|
||||||
|
|
||||||
|
configDir = defaultDir + "/config.json";
|
||||||
|
profilesDir = defaultDir + "/profiles.json";
|
||||||
|
|
||||||
|
System.out.println(String.format("os.name = %s (with identifier %s)", OSName, operationSystem));
|
||||||
|
System.out.println(String.format("os.version = %s", OSVersion));
|
||||||
|
System.out.println(String.format("default directory: %s", defaultDir));
|
||||||
|
System.out.println(String.format("java version = %s", System.getProperty("java.version")));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void createConfigJson() throws IOException {
|
||||||
|
File configFile = new File(configDir);
|
||||||
|
|
||||||
|
if (!configFile.exists() || configFile.length() == 0L) {
|
||||||
|
WriteConfig.INSTANCE.invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will forcibly overwrite previously loaded config value.
|
||||||
|
*
|
||||||
|
* Key naming convention will be 'modName:propertyName'; if modName is null, the key will be just propertyName.
|
||||||
|
*
|
||||||
|
* @param value JsonValue (the key-value pair)
|
||||||
|
* @param modName module name, nullable
|
||||||
|
*/
|
||||||
|
public static void setToGameConfigForced(JsonValue value, String modName) {
|
||||||
|
gameConfig.set((modName == null) ? value.name : modName+":"+value.name,
|
||||||
|
value.isArray() ? value.asDoubleArray() :
|
||||||
|
value.isDouble() ? value.asDouble() :
|
||||||
|
value.isBoolean() ? value.asBoolean() :
|
||||||
|
value.isLong() ? value.asInt() :
|
||||||
|
value.asString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will not overwrite previously loaded config value.
|
||||||
|
*
|
||||||
|
* Key naming convention will be 'modName:propertyName'; if modName is null, the key will be just propertyName.
|
||||||
|
*
|
||||||
|
* @param value JsonValue (the key-value pair)
|
||||||
|
* @param modName module name, nullable
|
||||||
|
*/
|
||||||
|
public static void setToGameConfig(JsonValue value, String modName) {
|
||||||
|
String key = (modName == null) ? value.name : modName+":"+value.name;
|
||||||
|
if (gameConfig.get(key) == null) {
|
||||||
|
gameConfig.set(key,
|
||||||
|
value.isArray() ? value.asDoubleArray() :
|
||||||
|
value.isDouble() ? value.asDouble() :
|
||||||
|
value.isBoolean() ? value.asBoolean() :
|
||||||
|
value.isLong() ? value.asInt() :
|
||||||
|
value.asString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return true on successful, false on failure.
|
||||||
|
*/
|
||||||
|
private static Boolean readConfigJson() {
|
||||||
|
try {
|
||||||
|
// read from disk and build config from it
|
||||||
|
JsonValue map = JsonFetcher.INSTANCE.invoke(configDir);
|
||||||
|
|
||||||
|
// make config
|
||||||
|
for (JsonValue entry = map.child; entry != null; entry = entry.next) {
|
||||||
|
setToGameConfigForced(entry, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
// write default config to game dir. Call th.is method again to read config from it.
|
||||||
|
try {
|
||||||
|
createConfigJson();
|
||||||
|
}
|
||||||
|
catch (IOException e1) {
|
||||||
|
System.out.println("[AppLoader] Unable to write config.json file");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return config from config set. If the config does not exist, default value will be returned.
|
||||||
|
* @param key
|
||||||
|
* *
|
||||||
|
* @return Config from config set or default config if it does not exist.
|
||||||
|
* *
|
||||||
|
* @throws NullPointerException if the specified config simply does not exist.
|
||||||
|
*/
|
||||||
|
public static int getConfigInt(String key) {
|
||||||
|
Object cfg = getConfigMaster(key);
|
||||||
|
|
||||||
|
if (cfg instanceof Integer) return ((int) cfg);
|
||||||
|
|
||||||
|
double value = (double) cfg;
|
||||||
|
|
||||||
|
if (Math.abs(value % 1.0) < 0.00000001)
|
||||||
|
return (int) Math.round(value);
|
||||||
|
return ((int) cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return config from config set. If the config does not exist, default value will be returned.
|
||||||
|
* @param key
|
||||||
|
* *
|
||||||
|
* @return Config from config set or default config if it does not exist.
|
||||||
|
* *
|
||||||
|
* @throws NullPointerException if the specified config simply does not exist.
|
||||||
|
*/
|
||||||
|
public static double getConfigDouble(String key) {
|
||||||
|
Object cfg = getConfigMaster(key);
|
||||||
|
return (cfg instanceof Integer) ? (((Integer) cfg) * 1.0) : ((double) (cfg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return config from config set. If the config does not exist, default value will be returned.
|
||||||
|
* @param key
|
||||||
|
* *
|
||||||
|
* @return Config from config set or default config if it does not exist.
|
||||||
|
* *
|
||||||
|
* @throws NullPointerException if the specified config simply does not exist.
|
||||||
|
*/
|
||||||
|
public static String getConfigString(String key) {
|
||||||
|
Object cfg = getConfigMaster(key);
|
||||||
|
return ((String) cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return config from config set. If the config does not exist, default value will be returned.
|
||||||
|
* @param key
|
||||||
|
* *
|
||||||
|
* @return Config from config set or default config if it does not exist. If the default value is undefined, will return false.
|
||||||
|
*/
|
||||||
|
public static boolean getConfigBoolean(String key) {
|
||||||
|
try {
|
||||||
|
Object cfg = getConfigMaster(key);
|
||||||
|
return ((boolean) cfg);
|
||||||
|
}
|
||||||
|
catch (NullPointerException keyNotFound) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get config from config file. If the entry does not exist, get from defaults; if the entry is not in the default, NullPointerException will be thrown
|
||||||
|
*/
|
||||||
|
private static HashMap<String, Object> getDefaultConfig() {
|
||||||
|
return DefaultConfig.INSTANCE.getHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getConfigMaster(String key1) {
|
||||||
|
String key = key1.toLowerCase();
|
||||||
|
|
||||||
|
Object config;
|
||||||
|
try {
|
||||||
|
config = gameConfig.get(key);
|
||||||
|
}
|
||||||
|
catch (NullPointerException e) {
|
||||||
|
config = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object defaults;
|
||||||
|
try {
|
||||||
|
defaults = getDefaultConfig().get(key);
|
||||||
|
}
|
||||||
|
catch (NullPointerException e) {
|
||||||
|
defaults = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config == null) {
|
||||||
|
if (defaults == null) {
|
||||||
|
throw new NullPointerException("key not found: '" + key + "'");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setConfig(String key, Object value) {
|
||||||
|
gameConfig.set(key.toLowerCase(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import com.badlogic.gdx.Gdx
|
|||||||
import com.badlogic.gdx.files.FileHandle
|
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 com.badlogic.gdx.utils.JsonWriter
|
||||||
@@ -79,14 +78,10 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
|
|||||||
var coroutineJobs = HashMap<Int, Job>() // <VM's identifier, Job>
|
var coroutineJobs = HashMap<Int, Job>() // <VM's identifier, Job>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val APPDATADIR = System.getProperty("os.name").toUpperCase().let {
|
val APPDATADIR = TsvmEmulator.defaultDir
|
||||||
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_CONFIG = Gdx.files.absolute(TsvmEmulator.configDir)
|
||||||
val FILE_PROFILES = Gdx.files.absolute("$APPDATADIR/profiles.json")
|
val FILE_PROFILES = Gdx.files.absolute(TsvmEmulator.profilesDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fullscreenQuad = Mesh(
|
val fullscreenQuad = Mesh(
|
||||||
@@ -571,9 +566,10 @@ object EmulatorGuiToolkit {
|
|||||||
object Theme {
|
object Theme {
|
||||||
val COL_INACTIVE = Color(0x858585ff.toInt())
|
val COL_INACTIVE = Color(0x858585ff.toInt())
|
||||||
val COL_INACTIVE2 = Color(0x5a5a5fff.toInt())
|
val COL_INACTIVE2 = Color(0x5a5a5fff.toInt())
|
||||||
|
val COL_INACTIVE3 = Color.WHITE
|
||||||
val COL_ACTIVE = Color(0x23ff00ff.toInt()) // neon green
|
val COL_ACTIVE = Color(0x23ff00ff.toInt()) // neon green
|
||||||
val COL_ACTIVE2 = Color(0xfff600ff.toInt()) // yellow
|
val COL_ACTIVE2 = Color(0xfff600ff.toInt()) // yellow
|
||||||
val COL_ACTIVE3 = Color.WHITE
|
val COL_ACTIVE3 = Color(0x5ff8ffff.toInt()) // cyan
|
||||||
val COL_HIGHLIGHT = Color(0xe43380ff.toInt()) // magenta
|
val COL_HIGHLIGHT = Color(0xe43380ff.toInt()) // magenta
|
||||||
val COL_DISABLED = Color(0xaaaaaaff.toInt())
|
val COL_DISABLED = Color(0xaaaaaaff.toInt())
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user