mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
modeling of a program ROM
This commit is contained in:
2
assets/romtest.js
Normal file
2
assets/romtest.js
Normal file
@@ -0,0 +1,2 @@
|
||||
sys.mapRom((exec_args[1]|0)||0);
|
||||
println(sys.romReadAll());
|
||||
@@ -4,6 +4,7 @@ import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
|
||||
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
|
||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
|
||||
import net.torvald.tsvm.peripheral.GenericBios;
|
||||
|
||||
public class AppLoader {
|
||||
|
||||
@@ -24,7 +25,10 @@ public class AppLoader {
|
||||
appConfig.width = 560;
|
||||
appConfig.height = 448;
|
||||
|
||||
new LwjglApplication(new VMGUI(appConfig), appConfig);
|
||||
|
||||
// val vm = VM(64.kB(), TheRealWorld(), arrayOf(GenericBios))
|
||||
VM vm = new VM(64 << 10, new TheRealWorld(), new GenericBios[]{GenericBios.INSTANCE});
|
||||
new LwjglApplication(new VMGUI(vm, appConfig), appConfig);
|
||||
}
|
||||
|
||||
public static ShaderProgram loadShaderFromFile(String vert, String frag) {
|
||||
|
||||
@@ -3,59 +3,22 @@ package net.torvald.tsvm
|
||||
import net.torvald.UnsafeHelper
|
||||
import net.torvald.UnsafePtr
|
||||
import net.torvald.tsvm.firmware.Firmware
|
||||
import net.torvald.tsvm.firmware.Firmware.Companion.toLuaValue
|
||||
import net.torvald.tsvm.peripheral.IOSpace
|
||||
import net.torvald.tsvm.peripheral.PeriBase
|
||||
import org.luaj.vm2.LuaValue
|
||||
import net.torvald.tsvm.peripheral.VMProgramRom
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.io.PrintStream
|
||||
import java.util.*
|
||||
import kotlin.math.ceil
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* 1 byte = 2 pixels
|
||||
*
|
||||
* 560x448@4bpp = 125 440 bytes
|
||||
* 560x448@8bpp = 250 880 bytes
|
||||
*
|
||||
* -> 262144 bytes (256 kB)
|
||||
*
|
||||
* [USER AREA | HW AREA]
|
||||
* Number of pheripherals = 8, of which the computer itself is considered as a peri.
|
||||
*
|
||||
* HW AREA = [Peripherals | MMIO | INTVEC]
|
||||
*
|
||||
* User area: 8 MB, hardware area: 8 MB
|
||||
*
|
||||
* 8192 kB
|
||||
* User Space
|
||||
* 1024 kB
|
||||
* Peripheral #8
|
||||
* 1024 kB
|
||||
* Peripheral #7
|
||||
* ...
|
||||
* 1024 kB
|
||||
* MMIO and Interrupt Vectors
|
||||
* 128 kB
|
||||
* MMIO for Peri #8
|
||||
* 128 kB
|
||||
* MMIO for Peri #7
|
||||
* ...
|
||||
* 128 kB
|
||||
* MMIO for the computer
|
||||
* 130816 bytes
|
||||
* MMIO for Ports, etc.
|
||||
* 256 bytes
|
||||
* Vectors for 64 interrupts
|
||||
*
|
||||
*
|
||||
* A class representing an instance of a Virtual Machine
|
||||
*/
|
||||
|
||||
class VM(
|
||||
_memsize: Long,
|
||||
val worldInterface: WorldInterface
|
||||
val worldInterface: WorldInterface,
|
||||
val roms: Array<VMProgramRom?> // first ROM must contain the BIOS
|
||||
) {
|
||||
|
||||
val id = java.util.Random().nextInt()
|
||||
@@ -81,6 +44,9 @@ class VM(
|
||||
|
||||
val startTime: Long
|
||||
|
||||
var romMapping = 255
|
||||
internal set
|
||||
|
||||
init {
|
||||
peripheralTable[0] = PeripheralEntry(
|
||||
"io",
|
||||
@@ -217,9 +183,6 @@ class VM(
|
||||
mallocSizes.remove(index)
|
||||
}
|
||||
|
||||
//fun Byte.toLuaValue() = LuaValue.valueOf(this.toInt())
|
||||
|
||||
|
||||
internal data class VMNativePtr(val address: Int, val size: Int)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@ import com.badlogic.gdx.graphics.OrthographicCamera
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||
import kotlinx.coroutines.*
|
||||
import net.torvald.tsvm.CompressorDelegate.GZIP_HEADER
|
||||
import net.torvald.tsvm.peripheral.GenericBios
|
||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||
import java.io.File
|
||||
|
||||
fun ByteArray.startsWith(other: ByteArray) = this.sliceArray(other.indices).contentEquals(other)
|
||||
|
||||
class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
||||
class VMGUI(val vm: VM, val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
||||
|
||||
val vm = VM(64.kB(), TheRealWorld())
|
||||
lateinit var gpu: GraphicsAdapter
|
||||
|
||||
lateinit var batch: SpriteBatch
|
||||
@@ -54,19 +54,10 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter()
|
||||
|
||||
memvwr = Memvwr(vm)
|
||||
|
||||
// load test bios
|
||||
|
||||
val bios = File("./assets/bios1.bin").readBytes()
|
||||
// check if bios is compressed in gzip
|
||||
val biosStr = if (bios.startsWith(GZIP_HEADER))
|
||||
CompressorDelegate.decomp(bios).toString(VM.CHARSET)
|
||||
else
|
||||
bios.toString(VM.CHARSET)
|
||||
|
||||
vmRunner = VMRunnerFactory(vm, "js")
|
||||
coroutineJob = GlobalScope.launch {
|
||||
//vmRunner.executeCommand(File("./assets/zippytest.js").readText(VM.CHARSET))
|
||||
vmRunner.executeCommand(biosStr)
|
||||
vmRunner.executeCommand(vm.roms[0]!!.readAll())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,13 @@ class VMJSR223Delegate(val vm: VM) {
|
||||
fun nanoTime() = System.nanoTime()
|
||||
fun malloc(size: Int) = vm.malloc(size)
|
||||
fun free(ptr: Int) = vm.free(ptr)
|
||||
fun mapRom(slot: Int) {
|
||||
vm.romMapping = slot.and(255)
|
||||
}
|
||||
fun romReadAll(): String {
|
||||
if (vm.romMapping == 255) return ""
|
||||
return vm.roms[vm.romMapping]!!.readAll()
|
||||
}
|
||||
|
||||
fun uptime(): Long {
|
||||
vm.poke(-69, -1)
|
||||
|
||||
@@ -93,6 +93,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
in 72..79 -> systemUptime.ushr((adi - 72) * 8).and(255).toByte()
|
||||
in 80..87 -> rtc.ushr((adi - 80) * 8).and(255).toByte()
|
||||
|
||||
88L -> vm.romMapping.toByte()
|
||||
|
||||
4076L -> blockTransferPorts[0].statusCode.toByte()
|
||||
4077L -> blockTransferPorts[1].statusCode.toByte()
|
||||
4078L -> blockTransferPorts[2].statusCode.toByte()
|
||||
@@ -119,6 +121,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
in 12288..16383 -> blockTransferRx[2][addr - 12288]
|
||||
in 16384..20479 -> blockTransferRx[3][addr - 16384]
|
||||
|
||||
in 65536..131071 -> if (vm.romMapping == -1) 255.toByte() else vm.roms[vm.romMapping]?.get(adi - 65536)
|
||||
|
||||
in 131072..262143 -> vm.peripheralTable[1].peripheral?.mmio_read(addr - 131072)
|
||||
in 262144..393215 -> vm.peripheralTable[2].peripheral?.mmio_read(addr - 262144)
|
||||
in 393216..524287 -> vm.peripheralTable[3].peripheral?.mmio_read(addr - 393216)
|
||||
@@ -147,6 +151,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
|
||||
RTClatched = byte.and(0b10).isNonZero()
|
||||
}
|
||||
|
||||
88L -> vm.romMapping = bi
|
||||
|
||||
4076L -> blockTransferPorts[0].statusCode = bi
|
||||
4077L -> blockTransferPorts[1].statusCode = bi
|
||||
4078L -> blockTransferPorts[2].statusCode = bi
|
||||
|
||||
31
src/net/torvald/tsvm/peripheral/VMProgramRom.kt
Normal file
31
src/net/torvald/tsvm/peripheral/VMProgramRom.kt
Normal file
@@ -0,0 +1,31 @@
|
||||
package net.torvald.tsvm.peripheral
|
||||
|
||||
import net.torvald.tsvm.CompressorDelegate
|
||||
import net.torvald.tsvm.CompressorDelegate.GZIP_HEADER
|
||||
import net.torvald.tsvm.VM
|
||||
import net.torvald.tsvm.startsWith
|
||||
import java.io.File
|
||||
|
||||
interface VMProgramRom {
|
||||
fun readAll(): String
|
||||
operator fun get(addr: Int): Byte
|
||||
}
|
||||
|
||||
object GenericBios : VMProgramRom {
|
||||
private val contents: ByteArray
|
||||
|
||||
init {
|
||||
val bytes = File("./assets/bios/bios1.bin").readBytes()
|
||||
contents = bytes.sliceArray(0 until minOf(65536, bytes.size))
|
||||
}
|
||||
|
||||
override fun readAll(): String {
|
||||
// check if bios is compressed in gzip
|
||||
return if (contents.startsWith(GZIP_HEADER))
|
||||
CompressorDelegate.decomp(contents).toString(VM.CHARSET)
|
||||
else
|
||||
contents.toString(VM.CHARSET)
|
||||
}
|
||||
|
||||
override fun get(addr: Int): Byte = contents[addr]
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||
|
||||
class V2kRunTest(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() {
|
||||
|
||||
val vm = VM(64.kB(), TheRealWorld())
|
||||
val vm = VM(64.kB(), TheRealWorld(), arrayOf())
|
||||
lateinit var gpu: GraphicsAdapter
|
||||
|
||||
lateinit var batch: SpriteBatch
|
||||
|
||||
@@ -82,6 +82,8 @@ MMIO
|
||||
72..79 RO: System uptime in nanoseconds
|
||||
80..87 RO: RTC in microseconds
|
||||
|
||||
88 RW: Rom mapping
|
||||
|
||||
4076..4079 RW: 8-bit status code for the port
|
||||
4080..4083 RO: 8-bit status code for connected device
|
||||
|
||||
@@ -119,6 +121,8 @@ MMIO
|
||||
12288..16383 RW: Buffer for block transfer lane #3
|
||||
16384..20479 RW: Buffer for block transfer lane #4
|
||||
|
||||
65536..131071 RO: Mapped to ROM
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
VRAM Bank 0 (256 kB)
|
||||
|
||||
Reference in New Issue
Block a user