diff --git a/.idea/misc.xml b/.idea/misc.xml
index e0844bc..07115cd 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/tsvm_core/src/net/torvald/tsvm/VM.kt b/tsvm_core/src/net/torvald/tsvm/VM.kt
index 82eac7d..a61a5bc 100644
--- a/tsvm_core/src/net/torvald/tsvm/VM.kt
+++ b/tsvm_core/src/net/torvald/tsvm/VM.kt
@@ -52,7 +52,7 @@ class VM(
var getErrorStream: () -> OutputStream = { TODO() }
var getInputStream: () -> InputStream = { TODO() }
- var startTime: Long = -1
+ var startTime: Long = -1; private set
var resetDown = false
var stopDown = false
@@ -117,8 +117,14 @@ class VM(
killAllContexts()
usermem.destroy()
peripheralTable.forEach { it.peripheral?.dispose() }
+ disposed = true
}
+ /**
+ * To check if the VM has started, check if startTime >= 0
+ */
+ var disposed = false; private set
+
/**
* @return system uptime in milliseconds
*/
diff --git a/tsvm_executable/src/net/torvald/tsvm/EmuMenu.kt b/tsvm_executable/src/net/torvald/tsvm/EmuMenu.kt
index 6c0634a..80d38fe 100644
--- a/tsvm_executable/src/net/torvald/tsvm/EmuMenu.kt
+++ b/tsvm_executable/src/net/torvald/tsvm/EmuMenu.kt
@@ -5,10 +5,11 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
/**
* Created by minjaesong on 2022-10-25.
*/
-interface EmuMenu {
+abstract class EmuMenu(val parent: VMEmuExecutable, val x: Int, val y: Int, val w: Int, val h: Int) {
- fun update()
-
- fun render(batch: SpriteBatch)
+ abstract fun show()
+ abstract fun hide()
+ abstract fun update()
+ abstract fun render(batch: SpriteBatch)
}
\ No newline at end of file
diff --git a/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt b/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt
index 8a6b02c..b6d003d 100644
--- a/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt
+++ b/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt
@@ -2,19 +2,69 @@ package net.torvald.tsvm
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
+import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT
/**
* Created by minjaesong on 2022-10-25.
*/
-class ProfilesMenu(val w: Int, val h: Int) : EmuMenu {
+class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : EmuMenu(parent, x, y, w, h) {
+
+ companion object {
+ const val PROFILES_ROWS = 17 // 1 profile-row takes up 2 text-rows
+ }
+
+ private val profileNames = ArrayList()
+ private var profilesScroll = 0
+
+ private var selectedProfileIndex: Int? = null
+
+ private fun resetState() {
+ profilesScroll = 0
+ }
+
+ override fun show() {
+ profileNames.clear()
+ profileNames.addAll(parent.profiles.keys.sorted())
+ }
+
+ override fun hide() {
+
+ }
override fun update() {
}
override fun render(batch: SpriteBatch) {
batch.inUse {
- batch.color = Color.LIME
- batch.fillRect(0, 0, w, h)
+ batch.color = EmulatorGuiToolkit.Theme.COL_WELL
+ it.fillRect(10, 11, 228, 446)
+
+ for (i in 0 until Math.min(PROFILES_ROWS, profileNames.size)) {
+ val index = profilesScroll + i
+
+ val colBack = if (index == selectedProfileIndex) EmulatorGuiToolkit.Theme.COL_HIGHLIGHT
+ else if (i % 2 == 0) EmulatorGuiToolkit.Theme.COL_WELL
+ else EmulatorGuiToolkit.Theme.COL_WELL2
+ val colFore = if (index == selectedProfileIndex) EmulatorGuiToolkit.Theme.COL_ACTIVE
+ else EmulatorGuiToolkit.Theme.COL_ACTIVE2
+
+ val theVM = parent.getVMbyProfileName(profileNames[index])
+ val isVMrunning = if (theVM != null) !theVM.disposed && theVM.startTime >= 0 else false
+ val vmViewport = parent.getViewportForTheVM(theVM)
+
+ val vmRunStatusText = if (isVMrunning) "Running" else "Idle"
+ val vmViewportText = if (vmViewport != null) "on viewport #${vmViewport+1}" else "hidden"
+
+ batch.color = colBack
+ it.fillRect(10, 11 + i*2*FONT.H, 228, 26)
+
+ batch.color = colFore
+ FONT.draw(batch, profileNames[index], 12f, 11f + i*2*FONT.H)
+ batch.color = EmulatorGuiToolkit.Theme.COL_ACTIVE3
+ FONT.draw(batch, "$vmRunStatusText, $vmViewportText", 12f, 11f+FONT.H + i*2*FONT.H)
+
+
+ }
}
}
}
\ No newline at end of file
diff --git a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt
index c4c5103..bdacf5c 100644
--- a/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt
+++ b/tsvm_executable/src/net/torvald/tsvm/VMEmuExecutable.kt
@@ -98,7 +98,18 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
val profiles = HashMap()
- fun writeProfilesToFile(outFile: FileHandle) {
+ private val currentlyLoadedProfiles = HashMap()
+ fun getVMbyProfileName(name: String): VM? {
+ if (profiles.containsKey(name)) {
+ return currentlyLoadedProfiles.getOrPut(name) { _makeVMfromJson(profiles[name]!!) }
+ }
+ else
+ return null
+ }
+
+ fun getViewportForTheVM(vm: VM?): Int? = if (vm == null) null else vms.indexOfFirst { vm.id == it?.vm?.id }.let { if (it < 0) null else it }
+
+ private fun writeProfilesToFile(outFile: FileHandle) {
val out = StringBuilder()
out.append('{')
@@ -116,6 +127,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
outFile.writeString(outstr, false)
}
+
override fun create() {
super.create()
@@ -151,7 +163,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
vms[0] = VMRunnerInfo(vm, "Initial VM")*/
val testJson = JsonReader().parse("{$defaultProfile}")
- val vm1 = makeVMfromJson(testJson.get("Initial VM"))
+ val vm1 = getVMbyProfileName("Initial VM")!!
initVMenv(vm1)
vms[0] = VMRunnerInfo(vm1, "Initial VM")
@@ -267,7 +279,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
updateMenu()
}
- private val defaultGuiBackgroundColour = Color(0x303039ff)
+ val defaultGuiBackgroundColour = Color(0x303039ff)
private fun renderGame(delta: Float) {
vms.forEachIndexed { index, vmInfo ->
@@ -369,13 +381,24 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
private val menuTabW = windowWidth - 4
private val menuTabH = windowHeight - 4 - FONT.H
+ private val menuTabX = windowWidth * (panelsX-1) + 2
+ private val menuTabY =windowHeight * (panelsY-1) + FONT.H + 2
- private val menuTabs = listOf("Profiles", "Machine", "Peripherals", "Cards")
+ private val menuTabs = listOf("Profiles", "Machine", "COMs", "Cards", "Setup")
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(this, menuTabX, menuTabY, menuTabW, menuTabH))
private var menuTabSel = 0
+ private var tabChangeRequested: Int? = 0 // null: not requested
+
private fun drawMenu(batch: SpriteBatch, x: Float, y: Float) {
+ if (tabChangeRequested != null) {
+ tabs[menuTabSel].hide()
+ tabs[tabChangeRequested!!].show()
+ menuTabSel = tabChangeRequested!!
+ tabChangeRequested = null
+ }
+
batch.inUse {
// background for the entire area
batch.color = defaultGuiBackgroundColour
@@ -403,7 +426,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
}
// draw the window frame inside the tab
- batch.color = EmulatorGuiToolkit.Theme.COL_INACTIVE
+ batch.color = EmulatorGuiToolkit.Theme.COL_LAND
batch.fillRect(x, y + FONT.H, windowWidth, windowHeight - FONT.H)
batch.color = EmulatorGuiToolkit.Theme.COL_HIGHLIGHT
batch.fillRect(x, y + FONT.H, windowWidth.toFloat(), 2f)
@@ -412,7 +435,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
batch.fillRect(x + windowWidth - 2f, y + FONT.H, 2f, windowHeight - FONT.H - 2f)
}
- setCameraPosition(windowWidth * (panelsX-1) + 2f, windowHeight * (panelsY-1) + FONT.H + 2f)
+ setCameraPosition(menuTabX.toFloat(), menuTabY.toFloat())
tabs[menuTabSel].render(batch)
}
@@ -440,6 +463,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
}
""".trimIndent()
+
/**
* You'll want to further init the things using the VM this function returns, such as:
*
@@ -450,7 +474,7 @@ class VMEmuExecutable(val windowWidth: Int, val windowHeight: Int, var panelsX:
* }
* ```
*/
- private fun makeVMfromJson(json: JsonValue): VM {
+ private fun _makeVMfromJson(json: JsonValue): VM {
val assetsDir = json.getString("assetsdir")
val ramsize = json.getLong("ramsize")
val cardslots = json.getInt("cardslots")
@@ -547,10 +571,15 @@ object EmulatorGuiToolkit {
val COL_INACTIVE2 = Color(0x5a5a5fff.toInt())
val COL_ACTIVE = Color(0x23ff00ff.toInt()) // neon green
val COL_ACTIVE2 = Color(0xfff600ff.toInt()) // yellow
+ val COL_ACTIVE3 = Color.WHITE
val COL_HIGHLIGHT = Color(0xe43380ff.toInt()) // magenta
val COL_DISABLED = Color(0xaaaaaaff.toInt())
val COL_TAB_NOT_SELECTED = Color(0x503cd4ff) // dark blue
+
+ val COL_LAND = Color(0x6b8ba2ff.toInt())
+ val COL_WELL = Color(0x374854ff.toInt())
+ val COL_WELL2 = Color(0x3e5261ff.toInt())
}
}