mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
graphics: hardware scroll for pixels
This commit is contained in:
4
assets/disk0/scrolltest.js
Normal file
4
assets/disk0/scrolltest.js
Normal file
@@ -0,0 +1,4 @@
|
||||
while (true) {
|
||||
graphics.scrollFrame(1,1);
|
||||
sys.spin();
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user