From 883edaab3c35e298fef1c19ff87a584d09e0391b Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 21 Sep 2021 21:48:16 +0900 Subject: [PATCH] graphics: hardware scroll for pixels --- assets/disk0/scrolltest.js | 4 ++++ src/net/torvald/tsvm/AppLoader.java | 10 ++++----- .../torvald/tsvm/GraphicsJSR223Delegate.kt | 18 +++++++++++++++ .../tsvm/peripheral/GraphicsAdapter.kt | 22 ++++++++++++++++++- terranmon.txt | 8 +++++-- 5 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 assets/disk0/scrolltest.js diff --git a/assets/disk0/scrolltest.js b/assets/disk0/scrolltest.js new file mode 100644 index 0000000..8498047 --- /dev/null +++ b/assets/disk0/scrolltest.js @@ -0,0 +1,4 @@ +while (true) { + graphics.scrollFrame(1,1); + sys.spin(); +} \ No newline at end of file diff --git a/src/net/torvald/tsvm/AppLoader.java b/src/net/torvald/tsvm/AppLoader.java index ad65a4c..9e635d5 100644 --- a/src/net/torvald/tsvm/AppLoader.java +++ b/src/net/torvald/tsvm/AppLoader.java @@ -28,13 +28,13 @@ public class AppLoader { appConfig.setWindowedMode(WIDTH, HEIGHT); - //VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, BasicRom.INSTANCE}); - //VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{OEMBios.INSTANCE, BasicRom.INSTANCE}); - //VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{TandemBios.INSTANCE, BasicRom.INSTANCE}); - //VM vm = new VM(128 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, WPBios.INSTANCE}); +// VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, BasicRom.INSTANCE}); +// VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{OEMBios.INSTANCE, BasicRom.INSTANCE}); + VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{TandemBios.INSTANCE, BasicRom.INSTANCE}); +// VM vm = new VM(128 << 10, new TheRealWorld(), new VMProgramRom[]{BasicBios.INSTANCE, WPBios.INSTANCE}); // uncomment to target the TerranBASIC runner - VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{TBASRelBios.INSTANCE}); +// VM vm = new VM(64 << 10, new TheRealWorld(), new VMProgramRom[]{TBASRelBios.INSTANCE}); EmulInstance reference = new EmulInstance(vm, "net.torvald.tsvm.peripheral.ReferenceGraphicsAdapter", "assets/disk0"); EmulInstance reference2 = new EmulInstance(vm, "net.torvald.tsvm.peripheral.ReferenceLikeLCD", "assets/disk0"); diff --git a/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt b/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt index 0345c80..780a6d1 100644 --- a/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt +++ b/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt @@ -2,6 +2,7 @@ package net.torvald.tsvm import net.torvald.UnsafeHelper import net.torvald.tsvm.peripheral.GraphicsAdapter +import net.torvald.tsvm.peripheral.fmod class GraphicsJSR223Delegate(val vm: VM) { @@ -42,6 +43,23 @@ class GraphicsJSR223Delegate(val vm: VM) { } } + /** + * Sets absolute position of scrolling + */ + fun setFramebufferScroll(x: Int, y: Int) { + getFirstGPU()?.let { + it.framebufferScrollX = x + it.framebufferScrollY = y + } + } + + fun scrollFrame(xdelta: Int, ydelta: Int) { + getFirstGPU()?.let { + it.framebufferScrollX = (it.framebufferScrollX + xdelta) fmod it.framebuffer.width + it.framebufferScrollY = (it.framebufferScrollY + ydelta) fmod it.framebuffer.height + } + } + fun getPixelDimension(): IntArray { getFirstGPU()?.let { return intArrayOf(it.framebuffer.width, it.framebuffer.height) } return intArrayOf(-1, -1) diff --git a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt index d78ce6e..3bb5828 100644 --- a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt +++ b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -81,6 +81,8 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super private var currentChrRom = 0 private var chrWidth = 7f private var chrHeight = 14f + var framebufferScrollX = 0 + var framebufferScrollY = 0 override var ttyFore: Int = TTY_FORE_DEFAULT // cannot be Byte override var ttyBack: Int = TTY_BACK_DEFAULT // cannot be Byte @@ -178,6 +180,10 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super val adi = addr.toInt() return when (addr) { in 0 until 250880 -> framebuffer.pixels.get(adi)//framebuffer.getPixel(adi % WIDTH, adi / WIDTH).toByte() + 250896L -> framebufferScrollX.toByte() + 250897L -> framebufferScrollX.ushr(8).toByte() + 250898L -> framebufferScrollY.toByte() + 250899L -> framebufferScrollY.ushr(8).toByte() in 250880 until 250972 -> unusedArea[adi - 250880] in 250972 until 261632 -> spriteAndTextArea[addr - 250972] in 261632 until 262144 -> peekPalette(adi - 261632) @@ -201,6 +207,10 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super unusedArea[adi - 250880] = byte runCommand(byte) } + 250896L -> framebufferScrollX = framebufferScrollX.and(0xFFFFFF00.toInt()).or(bi) + 250897L -> framebufferScrollX = framebufferScrollX.and(0xFFFF00FF.toInt()).or(bi shl 8) + 250898L -> framebufferScrollY = framebufferScrollY.and(0xFFFFFF00.toInt()).or(bi) + 250899L -> framebufferScrollY = framebufferScrollY.and(0xFFFF00FF.toInt()).or(bi shl 8) in 250880 until 250972 -> unusedArea[adi - 250880] = byte in 250972 until 261632 -> spriteAndTextArea[addr - 250972] = byte in 261632 until 262144 -> pokePalette(adi - 261632, byte) @@ -587,6 +597,9 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super rendertex.dispose() rendertex = Texture(framebuffer, Pixmap.Format.RGBA8888, false) + val texOffX = (framebufferScrollX fmod framebuffer.width) * -1f + val texOffY = (framebufferScrollY fmod framebuffer.height) * 1f + outFBOs[1].inUse { outFBObatch.inUse { outFBObatch.shader = null @@ -625,7 +638,10 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super paletteShader.setUniformf("lcdBaseCol", LCD_BASE_COL) // draw framebuffer - outFBObatch.draw(rendertex, 0f, 0f) + outFBObatch.draw(rendertex, texOffX, texOffY) + outFBObatch.draw(rendertex, texOffX + framebuffer.width, texOffY) + outFBObatch.draw(rendertex, texOffX + framebuffer.width, texOffY - framebuffer.height) + outFBObatch.draw(rendertex, texOffX, texOffY - framebuffer.height) // draw texts or sprites @@ -1591,6 +1607,10 @@ void main() { } } +infix fun Int.fmod(other: Int): Int { + return Math.floorMod(this, other) +} + fun FrameBuffer.inUse(action: () -> Unit) { this.begin() action() diff --git a/terranmon.txt b/terranmon.txt index f22af8f..63f8f77 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -156,10 +156,14 @@ From the start of the memory space: command (writing to this memory address changes the status) 1: reset palette to default 2: fill framebuffer with given colour (arg1) -2 bytes +12 bytes argument for "command" (arg1: Byte, arg2: Byte) write to this address FIRST and then write to "command" to execute the command -76 bytes +2 bytes + framebuffer scroll X +2 bytes + framebuffer scroll Y +62 bytes *Unused* 2988 bytes