From 3282faf9e60c1cecc180990d77f79c1877b8a94c Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 28 Dec 2022 04:54:14 +0900 Subject: [PATCH] cpu halted flag on vm's mmio --- assets/disk0/!BOOTSEC | 2 +- assets/disk0/root.bootable/!BOOTSEC | 2 +- assets/disk0/root.live/!BOOTSEC | 2 +- assets/disk0/tvdos/installer/!BOOTSEC | 2 +- assets/disk0/tvdos/installer/install.js | 55 +++++++++++++++++++ terranmon.txt | 10 +++- .../src/net/torvald/tsvm/VMSetupBroker.kt | 2 + .../tsvm/peripheral/GraphicsAdapter.kt | 11 ++-- .../net/torvald/tsvm/peripheral/IOSpace.kt | 10 ++++ .../torvald/tsvm/peripheral/TevdDiskDrive.kt | 27 +++++++++ .../net/torvald/terrarum/imagefont/font.tga | 2 +- .../src/net/torvald/tsvm/ProfilesMenu.kt | 5 +- 12 files changed, 116 insertions(+), 14 deletions(-) diff --git a/assets/disk0/!BOOTSEC b/assets/disk0/!BOOTSEC index faca567..518291b 100644 --- a/assets/disk0/!BOOTSEC +++ b/assets/disk0/!BOOTSEC @@ -1 +1 @@ -let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power"); \ No newline at end of file +let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power");sys.poke(-90,128) \ No newline at end of file diff --git a/assets/disk0/root.bootable/!BOOTSEC b/assets/disk0/root.bootable/!BOOTSEC index faca567..518291b 100644 --- a/assets/disk0/root.bootable/!BOOTSEC +++ b/assets/disk0/root.bootable/!BOOTSEC @@ -1 +1 @@ -let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power"); \ No newline at end of file +let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power");sys.poke(-90,128) \ No newline at end of file diff --git a/assets/disk0/root.live/!BOOTSEC b/assets/disk0/root.live/!BOOTSEC index b8af513..90b2c0d 100644 --- a/assets/disk0/root.live/!BOOTSEC +++ b/assets/disk0/root.live/!BOOTSEC @@ -1 +1 @@ -let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("The Installation Medium seems to be damaged. Please contact your reseller or system administrators.");else println("TVDOS.SYS not found");println();println("Remove the Installation Medium, close the tray (if any), then shut off and restart the computer to finish the installation."); \ No newline at end of file +let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("The Installation Medium seems to be damaged. Please contact your reseller or system administrators.");else println("TVDOS.SYS not found");println();println("Remove the Installation Medium, close the tray (if any), then shut off and restart the computer to finish the installation.");sys.poke(-90,128) \ No newline at end of file diff --git a/assets/disk0/tvdos/installer/!BOOTSEC b/assets/disk0/tvdos/installer/!BOOTSEC index faca567..518291b 100644 --- a/assets/disk0/tvdos/installer/!BOOTSEC +++ b/assets/disk0/tvdos/installer/!BOOTSEC @@ -1 +1 @@ -let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power"); \ No newline at end of file +let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode(p[0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power");sys.poke(-90,128) \ No newline at end of file diff --git a/assets/disk0/tvdos/installer/install.js b/assets/disk0/tvdos/installer/install.js index 0893f3c..8a9b486 100644 --- a/assets/disk0/tvdos/installer/install.js +++ b/assets/disk0/tvdos/installer/install.js @@ -1,5 +1,49 @@ println("let's install!") +/* procedure: + +CANCELLED_BY_USER := + println("Installation of TVDOS was cancelled by the user.") + exit with errorlevel 1 + + +1. show the list of installable drives. Read-only drives are considered not installable +1.1 if there is at least one installable drives, show the following message: + select drive to install [B,C,D]: +1.2 else, show the following message: + No suitable drives were detected for installing TVDOS. The setup program will exit. (exit with errorlevel 2) + +2. check if the drive has boot sector. if there is, show message: + This drive appears to be bootable, which means there might be other operation system on this drive. + Proceed anyway? [Y/N]: +2.1. if read().trim().toLowercase() is not "y", do CANCELLED_BY_USER + +3. show the following message: + In order to install TVDOS to the drive ${destDrive}, the drive must be wiped clean first. + THIS PROCESS WILL IRREVERSIBLY DESTROY ALL THE DATA IN THE DRIVE ${destDrive}! + Type "yes, I consent" to proceed, or type any other text to cancel the installation process: +3.1. if read().trim().toLowercase() is not "yes, i consent" or "yes i consent", do CANCELLED_BY_USER + +4. show the following message: + Enter the new name for the drive that TVDOS will be installed: + +5. show the following message: + The destination disk will be wiped now. Do not turn off the power... + +6. formatDrive(destDrive, newName, driveNum) + +7. show following message: + TVDOS will be installed into the drive ${destDrive}... + +8. copyFiles(destDrive) + +9. show following message + TVDOS is successfully installed. You may continue using the Live Boot environment. + To boot from the newly-installed TVDOS, turn off the computer, remove the installation medium, then start the + computer again. (exit with errorlevel 0) + +*/ + function copyFiles(destDrive) { function dir(path) { @@ -36,4 +80,15 @@ function copyFiles(destDrive) { com.sendMessage(port, "FLUSH");com.sendMessage(port, "CLOSE") +} + +function formatDrive(destDrive, newName, driveNum) { + let [port, poru] = _TVDOS.DRV.FS.SERIAL._toPorts(destDrive)[0] + com.sendMessage(port, "FLUSH");com.sendMessage(port, "CLOSE") + com.sendMessage(port, `TEVDDISCARDDRIVE"${newName}",${poru}`) + let status = com.getStatusCode(port[0]) + if (status != 0) + throw Error("Formatting the disk failed: "+status) + + } \ No newline at end of file diff --git a/terranmon.txt b/terranmon.txt index d89145d..dbf15ba 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -88,14 +88,18 @@ MMIO 88 RW: Rom mapping -89 RO: BMS flags - 0b b000 00ca +89 RW: BMS flags + 0b P000 b0ca a: 1 if charging (accepting power from the AC adapter) c: 1 if battery is detected b: 1 if the device is battery-operated + P: 1 if CPU halted (so that the "smart" power supply can shut itself down) + + note: only the high nybbles are writable! + if the device is battery-operated but currently running off of an AC adapter and there is no battery inserted, - the flag would be 1000 0001 + the flag would be 0000 1001 90 RO: BMS calculated battery percentage where 255 is 100% 91 RO: BMS battery voltage multiplied by 10 (127 = "12.7 V") diff --git a/tsvm_core/src/net/torvald/tsvm/VMSetupBroker.kt b/tsvm_core/src/net/torvald/tsvm/VMSetupBroker.kt index 0545e84..e3627bb 100644 --- a/tsvm_core/src/net/torvald/tsvm/VMSetupBroker.kt +++ b/tsvm_core/src/net/torvald/tsvm/VMSetupBroker.kt @@ -34,6 +34,7 @@ object VMSetupBroker { vm.getPrintStream = { gpu.getPrintStream() } vm.getErrorStream = { gpu.getErrorStream() } vm.getInputStream = { gpu.getInputStream() } + vm.poke(-90L, 0) vmRunners[vm.id] = VMRunnerFactory(vm.assetsDir, vm, "js") coroutineJobs[vm.id] = GlobalScope.launch { vmRunners[vm.id]?.executeCommand(vm.roms[0]!!.readAll()) } @@ -56,6 +57,7 @@ object VMSetupBroker { vm.getPrintStream = { TODO() } vm.getErrorStream = { TODO() } vm.getInputStream = { TODO() } + vm.poke(-90L, -128) vmRunners[vm.id]?.close() coroutineJobs[vm.id]?.cancel("VM kill command received") diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt index b9ec36d..73b6fda 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -7,6 +7,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.math.Matrix4 +import com.badlogic.gdx.utils.GdxRuntimeException import net.torvald.UnsafeHelper import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint import net.torvald.tsvm.FBM @@ -937,9 +938,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi override fun dispose() { //testTex.dispose() - framebuffer.destroy() - framebuffer2?.destroy() - framebufferOut.dispose() + try { framebuffer.destroy() } catch (_: GdxRuntimeException) {} + try { framebuffer2?.destroy() } catch (_: GdxRuntimeException) {} + try { framebufferOut.dispose() } catch (_: GdxRuntimeException) {} rendertex.dispose() textArea.destroy() textForePixmap.dispose() @@ -951,8 +952,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi outFBOs.forEach { it.dispose() } outFBObatch.dispose() - try { textForeTex.dispose() } catch (_: Throwable) {} - try { textBackTex.dispose() } catch (_: Throwable) {} + try { textForeTex.dispose() } catch (_: GdxRuntimeException) {} + try { textBackTex.dispose() } catch (_: GdxRuntimeException) {} chrrom0.dispose() chrrom.dispose() diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt index 82d2e11..8cb7657 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt @@ -42,6 +42,11 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { private val keyEventBuffers = ByteArray(8) + private var acpiShutoff = true + private var bmsIsCharging = false + private var bmsHasBattery = false + private var bmsIsBatteryOperated = false + init { //blockTransferPorts[1].attachDevice(TestFunctionGenerator()) //blockTransferPorts[0].attachDevice(TestDiskDrive(vm, 0, File("assets"))) @@ -76,6 +81,7 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { } } + override fun peek(addr: Long): Byte? { return mmio_read(addr) } @@ -105,6 +111,9 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { 88L -> vm.romMapping.toByte() + 89L -> ((acpiShutoff.toInt() shl 7) or (bmsIsBatteryOperated.toInt() shl 3) or (bmsHasBattery.toInt() shl 1) + or bmsIsCharging.toInt()).toByte() + in 1024..2047 -> peripheralFast[addr - 1024] 4076L -> blockTransferPorts[0].statusCode.toByte() @@ -164,6 +173,7 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { } 88L -> vm.romMapping = bi + 89L -> { acpiShutoff = byte.and(-128).isNonZero() } in 1024..2047 -> peripheralFast[addr - 1024] = byte diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt index 8a39d73..4a031ed 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt @@ -464,6 +464,33 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, private val t recipient?.writeout(TestDiskDrive.composePositiveAns("USED${DOM.usedBytes}/TOTAL${DOM.capacity}")) statusCode.set(TestDiskDrive.STATE_CODE_STANDBY) } + else if (inputString.startsWith("TEVDDISCARDDRIVE\"")) { + // the actual capacity of the floppy must be determined when the floppy gameitem was created + + if (DOM.isReadOnly) { + printdbg("! disk is read-only") + statusCode.set(TestDiskDrive.STATE_CODE_READ_ONLY) + return + } + + var commaIndex = inputString.lastIndex + while (commaIndex > 6) { + if (inputString[commaIndex] == ',') break; commaIndex -= 1 + } + // sanity check if path is actually enclosed with double-quote + if (commaIndex != 6 && inputString[commaIndex - 1] != '"') { + statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND) + return + } + val newName = inputString.substring(6, if (commaIndex == 6) inputString.lastIndex else commaIndex - 1) + val driveNum = + if (commaIndex == 6) null else inputString.substring(commaIndex + 1, inputString.length).toInt() + + // TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it + + DOM.entries.clear() + DOM.diskName = newName.toByteArray(VM.CHARSET) + } else statusCode.set(TestDiskDrive.STATE_CODE_ILLEGAL_COMMAND) } diff --git a/tsvm_executable/src/net/torvald/terrarum/imagefont/font.tga b/tsvm_executable/src/net/torvald/terrarum/imagefont/font.tga index b88a9b9..21aeaf2 100644 --- a/tsvm_executable/src/net/torvald/terrarum/imagefont/font.tga +++ b/tsvm_executable/src/net/torvald/terrarum/imagefont/font.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:00ff0568aa4d4e0b528cc1c9ae7bcfb8ac5b4cdba305247ff96af72984529d58 +oid sha256:51ebf1ce9e983a5f682d066adb85da03169fff0df3106001432bf8c3775d4b31 size 93202 diff --git a/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt b/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt index 292bc17..de6ebdd 100644 --- a/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt +++ b/tsvm_executable/src/net/torvald/tsvm/ProfilesMenu.kt @@ -5,6 +5,7 @@ import com.badlogic.gdx.Input.Buttons import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.g2d.SpriteBatch import net.torvald.tsvm.VMEmuExecutableWrapper.Companion.FONT +import kotlin.experimental.and /** * Created by minjaesong on 2022-10-25. @@ -103,6 +104,7 @@ class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : Em private val STR_PLAY = "\u00D2\u00D3" private val STR_STOP = "\u00D0\u00D1" + private val STR_POWER = "\u00D4\u00D5" override fun render(batch: SpriteBatch) { batch.inUse { @@ -198,7 +200,8 @@ class ProfilesMenu(parent: VMEmuExecutable, x: Int, y: Int, w: Int, h: Int) : Em FONT.draw(batch, STR_STOP, 377f, 382f) batch.setColourBy { theVM?.isRunning == true } FONT.draw(batch, STR_PLAY, 398f, 382f) - + batch.setColourBy(Color.RED, Color.LIME) { (theVM?.peek(-90)?.and(-128) ?: 0.toByte()).toInt() != 0 } + FONT.draw(batch, STR_POWER, 419f, 382f) } } }