mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-12 07:44:03 +09:00
slight improvements to the long-abandoned v2k
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package net.torvald.tsvm
|
package net.torvald.tsvm
|
||||||
|
|
||||||
|
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||||
|
import net.torvald.tsvm.vdc.Videotron2K
|
||||||
import org.graalvm.polyglot.Context
|
import org.graalvm.polyglot.Context
|
||||||
import org.graalvm.polyglot.HostAccess
|
import org.graalvm.polyglot.HostAccess
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
@@ -26,7 +28,7 @@ object VMRunnerFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when (extension) {
|
return when (extension) {
|
||||||
/*"vt2" -> {
|
"vt2" -> {
|
||||||
object : VMRunner(extension) {
|
object : VMRunner(extension) {
|
||||||
|
|
||||||
val engine =
|
val engine =
|
||||||
@@ -36,6 +38,10 @@ object VMRunnerFactory {
|
|||||||
engine.eval(command)
|
engine.eval(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun eval(command: String) {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun evalGlobal(command: String) {
|
override suspend fun evalGlobal(command: String) {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
@@ -44,7 +50,7 @@ object VMRunnerFactory {
|
|||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
"js" -> {
|
"js" -> {
|
||||||
object : VMRunner(extension) {
|
object : VMRunner(extension) {
|
||||||
private val ringOneParallel = Parallel(vm)
|
private val ringOneParallel = Parallel(vm)
|
||||||
|
|||||||
@@ -1667,6 +1667,11 @@ void main() {
|
|||||||
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0.64f, TEXT_TILING_SHADER_LCD, DRAW_SHADER_FRAG_LCD
|
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0.64f, TEXT_TILING_SHADER_LCD, DRAW_SHADER_FRAG_LCD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val DEFAULT_CONFIG_FOR_TESTING = AdapterConfig(
|
||||||
|
"crt_color",
|
||||||
|
560, 448, 80, 32, 253, 255, 256.kB(), "FontROM7x14.png", 0f, TEXT_TILING_SHADER_COLOUR
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
val DEFAULT_PALETTE = intArrayOf( // 0b rrrrrrrr gggggggg bbbbbbbb aaaaaaaa
|
val DEFAULT_PALETTE = intArrayOf( // 0b rrrrrrrr gggggggg bbbbbbbb aaaaaaaa
|
||||||
255,
|
255,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import net.torvald.tsvm.peripheral.GraphicsAdapter
|
|||||||
|
|
||||||
class V2kRunTest : ApplicationAdapter() {
|
class V2kRunTest : ApplicationAdapter() {
|
||||||
|
|
||||||
val vm = VM(64.kB(), TheRealWorld(), arrayOf())
|
val vm = VM("./assets", 64.kB(), TheRealWorld(), arrayOf())
|
||||||
lateinit var gpu: GraphicsAdapter
|
lateinit var gpu: GraphicsAdapter
|
||||||
|
|
||||||
lateinit var batch: SpriteBatch
|
lateinit var batch: SpriteBatch
|
||||||
@@ -29,7 +29,7 @@ class V2kRunTest : ApplicationAdapter() {
|
|||||||
override fun create() {
|
override fun create() {
|
||||||
super.create()
|
super.create()
|
||||||
|
|
||||||
gpu = GraphicsAdapter(vm, GraphicsAdapter.DEFAULT_CONFIG_COLOR_CRT)
|
gpu = GraphicsAdapter("./assets", vm, GraphicsAdapter.DEFAULT_CONFIG_FOR_TESTING)
|
||||||
|
|
||||||
vm.peripheralTable[1] = PeripheralEntry(
|
vm.peripheralTable[1] = PeripheralEntry(
|
||||||
gpu,
|
gpu,
|
||||||
@@ -39,11 +39,11 @@ class V2kRunTest : ApplicationAdapter() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
batch = SpriteBatch()
|
batch = SpriteBatch()
|
||||||
camera = OrthographicCamera(net.torvald.tsvm.AppLoader.WIDTH.toFloat(), net.torvald.tsvm.AppLoader.WIDTH.toFloat())
|
camera = OrthographicCamera(560f, 448f)
|
||||||
camera.setToOrtho(false)
|
camera.setToOrtho(false)
|
||||||
camera.update()
|
camera.update()
|
||||||
batch.projectionMatrix = camera.combined
|
batch.projectionMatrix = camera.combined
|
||||||
Gdx.gl20.glViewport(0, 0, net.torvald.tsvm.AppLoader.WIDTH, net.torvald.tsvm.AppLoader.HEIGHT)
|
Gdx.gl20.glViewport(0, 0, 560, 448)
|
||||||
|
|
||||||
vm.getPrintStream = { gpu.getPrintStream() }
|
vm.getPrintStream = { gpu.getPrintStream() }
|
||||||
vm.getErrorStream = { gpu.getErrorStream() }
|
vm.getErrorStream = { gpu.getErrorStream() }
|
||||||
@@ -51,7 +51,7 @@ class V2kRunTest : ApplicationAdapter() {
|
|||||||
|
|
||||||
vdc = Videotron2K(gpu)
|
vdc = Videotron2K(gpu)
|
||||||
|
|
||||||
vmRunner = VMRunnerFactory(vm, "js")
|
vmRunner = VMRunnerFactory("./assets", vm, "js")
|
||||||
coroutineJob = GlobalScope.launch {
|
coroutineJob = GlobalScope.launch {
|
||||||
vdc.eval(Videotron2K.screenfiller)
|
vdc.eval(Videotron2K.screenfiller)
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ class V2kRunTest : ApplicationAdapter() {
|
|||||||
private var updateRate = 1f / 60f
|
private var updateRate = 1f / 60f
|
||||||
|
|
||||||
override fun render() {
|
override fun render() {
|
||||||
Gdx.graphics.setTitle("${net.torvald.tsvm.AppLoader.appTitle} $EMDASH F: ${Gdx.graphics.framesPerSecond} $EMDASH VF: ${(1.0 / vdc.statsFrameTime).toInt()}")
|
Gdx.graphics.setTitle("V2K — F: ${Gdx.graphics.framesPerSecond} — VF: ${(1.0 / vdc.statsFrameTime).toInt()}")
|
||||||
|
|
||||||
super.render()
|
super.render()
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package net.torvald.tsvm.vdc
|
package net.torvald.tsvm.vdc
|
||||||
|
|
||||||
import net.torvald.UnsafeHelper
|
import net.torvald.UnsafeHelper
|
||||||
import torvald.random.HQRNG
|
|
||||||
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
import net.torvald.tsvm.peripheral.GraphicsAdapter
|
||||||
|
import net.torvald.tsvm.vdc.Command.instSet
|
||||||
import java.lang.NumberFormatException
|
import java.lang.NumberFormatException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
@@ -72,21 +72,27 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
val screenfiller = """
|
val screenfiller = """
|
||||||
DEFINE RATEF 60
|
DEFINE RATEF 6000000
|
||||||
DEFINE height 448
|
DEFINE height 448
|
||||||
DEFINE width 560
|
DEFINE width 560
|
||||||
|
|
||||||
mov r6 12345
|
mov r6 0
|
||||||
|
|
||||||
SCENE rng ; r6 is RNG value
|
SCENE rng ; r6 is RNG value
|
||||||
mul r6 r6 48271
|
mul r6 r6 48271
|
||||||
mod r6 r6 2147483647
|
mod r6 r6 2147483647
|
||||||
exit
|
exit
|
||||||
END SCENE
|
END SCENE
|
||||||
|
|
||||||
|
SCENE next_colour
|
||||||
|
add r6 r6 20
|
||||||
|
mod r6 r6 255
|
||||||
|
exit
|
||||||
|
END SCENE
|
||||||
|
|
||||||
SCENE fill_line
|
SCENE fill_line
|
||||||
@ mov px 0
|
@ mov px 0
|
||||||
perform rng
|
; perform rng
|
||||||
plot r6
|
plot r6
|
||||||
; plot c1 ; will auto-increment px by one
|
; plot c1 ; will auto-increment px by one
|
||||||
; inc c1
|
; inc c1
|
||||||
@@ -101,12 +107,19 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
inc py
|
inc py
|
||||||
cmp r1 py 448
|
cmp r1 py 448
|
||||||
movzr r1 py 0
|
movzr r1 py 0
|
||||||
|
performzr r1 next_colour
|
||||||
next
|
next
|
||||||
; exeunt
|
; exeunt
|
||||||
; there's no EXIT command so this scene will make the program to go loop indefinitely
|
; there's no EXIT command so this scene will make the program to go loop indefinitely
|
||||||
END SCENE
|
END SCENE
|
||||||
|
|
||||||
perform loop_frame
|
SCENE fill_loop_frame
|
||||||
|
fillscr r6
|
||||||
|
perform next_colour
|
||||||
|
next
|
||||||
|
END SCENE
|
||||||
|
|
||||||
|
perform fill_loop_frame
|
||||||
|
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
}
|
}
|
||||||
@@ -149,7 +162,7 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
|
|
||||||
private val infoPrint = true
|
private val infoPrint = true
|
||||||
private val debugPrint = false
|
private val debugPrint = false
|
||||||
private val rng = torvald.random.HQRNG()
|
private val rng = Random()//HQRNG()
|
||||||
|
|
||||||
fun eval(command: String) {
|
fun eval(command: String) {
|
||||||
val rootStatements = parseCommands(command)
|
val rootStatements = parseCommands(command)
|
||||||
@@ -180,8 +193,8 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
|
|
||||||
if (it.prefix != StatementPrefix.INIT || it.prefix == StatementPrefix.INIT && !pcLoopedBack) {
|
if (it.prefix != StatementPrefix.INIT || it.prefix == StatementPrefix.INIT && !pcLoopedBack) {
|
||||||
if (debugPrint) println("Run-Scene: ${currentScene and 0xFFFFFFFFL}, Lindex: $currentLineIndex, Inst: $it")
|
if (debugPrint) println("Run-Scene: ${currentScene and 0xFFFFFFFFL}, Lindex: $currentLineIndex, Inst: $it")
|
||||||
Command.checkConditionAndRun(it.command, this, it.args)
|
Command.checkConditionAndRun(it.command, it.function, this, it.args)
|
||||||
if (debugPrint) println("Reg-r1: ${regs.getInt((REG_R1 and 0xF) * 4)}, c1: ${regs.getInt((REG_C1 and 0xF) * 4)}, px: ${regs.getInt((REG_PX and 0xF) * 4)}")
|
if (debugPrint) println("Reg-r1: ${regs.getInt((REG_R1 and 0xF))}, c1: ${regs.getInt((REG_C1 and 0xF))}, px: ${regs.getInt((REG_PX and 0xF))}")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -283,6 +296,7 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
lnum,
|
lnum,
|
||||||
if (isInit) StatementPrefix.INIT else StatementPrefix.NONE,
|
if (isInit) StatementPrefix.INIT else StatementPrefix.NONE,
|
||||||
cmd,
|
cmd,
|
||||||
|
instSet[cmd shr 3],
|
||||||
args.toLongArray()
|
args.toLongArray()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -321,7 +335,7 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
|
|||||||
private fun hasVar(name: String) = (varIdTable.containsKey(name.toUpperCase()))
|
private fun hasVar(name: String) = (varIdTable.containsKey(name.toUpperCase()))
|
||||||
|
|
||||||
|
|
||||||
private class VT2Statement(val lnum: Int, val prefix: Int = StatementPrefix.NONE, val command: Int, val args: LongArray) {
|
private class VT2Statement(val lnum: Int, val prefix: Int = StatementPrefix.NONE, val command: Int, val function: (Videotron2K, LongArray) -> Unit, val args: LongArray) {
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "L ${lnum.toString().padEnd(5, ' ')}" + StatementPrefix.toString(prefix) + " " + Command.reverseDict[command] + " " + (args.map { argsToString(it) })
|
return "L ${lnum.toString().padEnd(5, ' ')}" + StatementPrefix.toString(prefix) + " " + Command.reverseDict[command] + " " + (args.map { argsToString(it) })
|
||||||
}
|
}
|
||||||
@@ -508,7 +522,7 @@ object Command {
|
|||||||
instSet[MOV shr 3] = { instance, args -> // MOV register value
|
instSet[MOV shr 3] = { instance, args -> // MOV register value
|
||||||
if (args.size != 2) throw ArgsCountMismatch(2, args)
|
if (args.size != 2) throw ArgsCountMismatch(2, args)
|
||||||
checkRegisterLH(args[0])
|
checkRegisterLH(args[0])
|
||||||
instance.regs.setInt((args[0] and 0xF) * 4, resolveVar(instance, args[1]))
|
instance.regs.setInt((args[0] and 0xF), resolveVar(instance, args[1]))
|
||||||
}
|
}
|
||||||
instSet[MUL shr 3] = { instance, args -> // MUL ACC LH RH
|
instSet[MUL shr 3] = { instance, args -> // MUL ACC LH RH
|
||||||
twoArgArithmetic(instance, args) { a,b -> a*b }
|
twoArgArithmetic(instance, args) { a,b -> a*b }
|
||||||
@@ -522,15 +536,15 @@ object Command {
|
|||||||
instSet[INC shr 3] = { instance, args -> // INC register
|
instSet[INC shr 3] = { instance, args -> // INC register
|
||||||
if (args.size != 1) throw ArgsCountMismatch(1, args)
|
if (args.size != 1) throw ArgsCountMismatch(1, args)
|
||||||
checkRegisterLH(args[0])
|
checkRegisterLH(args[0])
|
||||||
instance.regs.setInt((args[0] and 0xF) * 4, 1 + instance.regs.getInt((args[0] and 0xF) * 4))
|
instance.regs.setInt((args[0] and 0xF), 1 + instance.regs.getInt((args[0] and 0xF)))
|
||||||
}
|
}
|
||||||
instSet[DEC shr 3] = { instance, args -> // DEC register
|
instSet[DEC shr 3] = { instance, args -> // DEC register
|
||||||
if (args.size != 1) throw ArgsCountMismatch(1, args)
|
if (args.size != 1) throw ArgsCountMismatch(1, args)
|
||||||
checkRegisterLH(args[0])
|
checkRegisterLH(args[0])
|
||||||
instance.regs.setInt((args[0] and 0xF) * 4, 1 - instance.regs.getInt((args[0] and 0xF) * 4))
|
instance.regs.setInt((args[0] and 0xF), 1 - instance.regs.getInt((args[0] and 0xF)))
|
||||||
}
|
}
|
||||||
instSet[NEXT shr 3] = { instance, _ ->
|
instSet[NEXT shr 3] = { instance, _ ->
|
||||||
instance.regs.setInt((Videotron2K.REG_FRM and 0xF) * 4, 1 + instance.regs.getInt((Videotron2K.REG_FRM and 0xF) * 4))
|
instance.regs.setInt((Videotron2K.REG_FRM and 0xF), 1 + instance.regs.getInt((Videotron2K.REG_FRM and 0xF)))
|
||||||
instance.sleepLatch = true
|
instance.sleepLatch = true
|
||||||
|
|
||||||
val timeTook = (System.nanoTime() - instance.performanceCounterTmr).toDouble()
|
val timeTook = (System.nanoTime() - instance.performanceCounterTmr).toDouble()
|
||||||
@@ -542,8 +556,8 @@ object Command {
|
|||||||
}
|
}
|
||||||
instSet[PLOT shr 3] = { instance, args -> // PLOT vararg-bytes
|
instSet[PLOT shr 3] = { instance, args -> // PLOT vararg-bytes
|
||||||
if (args.isNotEmpty()) {
|
if (args.isNotEmpty()) {
|
||||||
val px = instance.regs.getInt((Videotron2K.REG_PX and 0xF) * 4)
|
val px = instance.regs.getInt((Videotron2K.REG_PX and 0xF))
|
||||||
val py = instance.regs.getInt((Videotron2K.REG_PY and 0xF) * 4)
|
val py = instance.regs.getInt((Videotron2K.REG_PY and 0xF))
|
||||||
val width = instance.variableMap[Videotron2K.VARIABLE_WIDTH]!!
|
val width = instance.variableMap[Videotron2K.VARIABLE_WIDTH]!!
|
||||||
val memAddr = py * width + px
|
val memAddr = py * width + px
|
||||||
|
|
||||||
@@ -553,7 +567,7 @@ object Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// write back auto-incremented value
|
// write back auto-incremented value
|
||||||
instance.regs.setInt((Videotron2K.REG_PX and 0xF) * 4, (px + args.size) fmod width)
|
instance.regs.setInt((Videotron2K.REG_PX and 0xF), (px + args.size) fmod width)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instSet[PERFORM shr 3] = { instance, args -> // PERFORM scene
|
instSet[PERFORM shr 3] = { instance, args -> // PERFORM scene
|
||||||
@@ -571,6 +585,10 @@ object Command {
|
|||||||
instSet[EXEUNT shr 3] = { instance, _ ->
|
instSet[EXEUNT shr 3] = { instance, _ ->
|
||||||
instance.exeunt = true
|
instance.exeunt = true
|
||||||
}
|
}
|
||||||
|
instSet[FILLSCR shr 3] = { instance, args ->
|
||||||
|
instance.gpu?.poke(250884L, instance.regs.getInt(args[0] and 0xF).toByte())
|
||||||
|
instance.gpu?.poke(250883L, 2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun twoArgArithmetic(instance: Videotron2K, args: LongArray, operation: (Int, Int) -> Int) {
|
private inline fun twoArgArithmetic(instance: Videotron2K, args: LongArray, operation: (Int, Int) -> Int) {
|
||||||
@@ -578,16 +596,17 @@ object Command {
|
|||||||
checkRegisterLH(args[0])
|
checkRegisterLH(args[0])
|
||||||
val lh = resolveVar(instance, args[1])
|
val lh = resolveVar(instance, args[1])
|
||||||
val rh = resolveVar(instance, args[2])
|
val rh = resolveVar(instance, args[2])
|
||||||
instance.regs.setInt((args[0] and 0xF) * 4, operation(lh, rh))
|
instance.regs.setInt((args[0] and 0xF), operation(lh, rh))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkConditionAndRun(inst: Int, instance: Videotron2K, args: LongArray) {
|
fun checkConditionAndRun(inst: Int, operation: (Videotron2K, LongArray) -> Unit, instance: Videotron2K, args: LongArray) {
|
||||||
val opcode = inst shr 3
|
// val opcode = inst shr 3
|
||||||
val condCode = inst and 7
|
val condCode = inst and 7
|
||||||
|
|
||||||
if (condCode == 0) {
|
if (condCode == 0) {
|
||||||
//if (inst !in transferInst) instance.currentLineIndex += 1
|
//if (inst !in transferInst) instance.currentLineIndex += 1
|
||||||
instSet[opcode].invoke(instance, args)
|
// instSet[opcode].invoke(instance, args)
|
||||||
|
operation.invoke(instance, args)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,13 +622,14 @@ object Command {
|
|||||||
|
|
||||||
if (condition) {
|
if (condition) {
|
||||||
//if (inst !in transferInst) instance.currentLineIndex += 1
|
//if (inst !in transferInst) instance.currentLineIndex += 1
|
||||||
instSet[opcode].invoke(instance, args.sliceArray(1 until args.size))
|
// instSet[opcode].invoke(instance, args.sliceArray(1 until args.size))
|
||||||
|
operation.invoke(instance, args.sliceArray(1 until args.size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveVar(instance: Videotron2K, arg: Long): Int {
|
private fun resolveVar(instance: Videotron2K, arg: Long): Int {
|
||||||
return if (arg and Videotron2K.REGISTER_PREFIX == Videotron2K.REGISTER_PREFIX) {
|
return if (arg and Videotron2K.REGISTER_PREFIX == Videotron2K.REGISTER_PREFIX) {
|
||||||
instance.regs.getInt((arg and 0xF) * 4)
|
instance.regs.getInt((arg and 0xF))
|
||||||
}
|
}
|
||||||
else if (arg and Videotron2K.VARIABLE_PREFIX == Videotron2K.VARIABLE_PREFIX) {
|
else if (arg and Videotron2K.VARIABLE_PREFIX == Videotron2K.VARIABLE_PREFIX) {
|
||||||
instance.variableMap[arg] ?: throw NullVar()
|
instance.variableMap[arg] ?: throw NullVar()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$">
|
<content url="file://$MODULE_DIR$">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/src/net/torvald/tsvm/vdc" />
|
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
Reference in New Issue
Block a user