diff --git a/assets/disk0/AUTOEXEC.BAT b/assets/disk0/AUTOEXEC.BAT index c409e7e..53256dd 100644 --- a/assets/disk0/AUTOEXEC.BAT +++ b/assets/disk0/AUTOEXEC.BAT @@ -4,4 +4,4 @@ rem put set-xxx commands here: set PATH=\tvdos\tuidev;$PATH rem this line specifies which shell to be presented after the boot precess: -command /fancy +command diff --git a/src/net/torvald/tsvm/AppLoader.java b/src/net/torvald/tsvm/AppLoader.java index 0e71662..a3e54ed 100644 --- a/src/net/torvald/tsvm/AppLoader.java +++ b/src/net/torvald/tsvm/AppLoader.java @@ -3,6 +3,7 @@ package net.torvald.tsvm; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.backends.lwjgl.LwjglApplication; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import net.torvald.tsvm.peripheral.*; diff --git a/src/net/torvald/tsvm/VMGUI.kt b/src/net/torvald/tsvm/VMGUI.kt index e5bb65a..1da8f60 100644 --- a/src/net/torvald/tsvm/VMGUI.kt +++ b/src/net/torvald/tsvm/VMGUI.kt @@ -3,39 +3,50 @@ package net.torvald.tsvm import com.badlogic.gdx.ApplicationAdapter import com.badlogic.gdx.Gdx import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration -import com.badlogic.gdx.graphics.OrthographicCamera +import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.SpriteBatch import kotlinx.coroutines.* import net.torvald.tsvm.CompressorDelegate.GZIP_HEADER -import net.torvald.tsvm.peripheral.CharacterLCDdisplay -import net.torvald.tsvm.peripheral.GenericBios -import net.torvald.tsvm.peripheral.GraphicsAdapter -import net.torvald.tsvm.peripheral.TexticsAdapter +import net.torvald.tsvm.peripheral.* import java.io.File fun ByteArray.startsWith(other: ByteArray) = this.sliceArray(other.indices).contentEquals(other) class VMGUI(val vm: VM, val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() { - lateinit var gpu: GraphicsAdapter - lateinit var batch: SpriteBatch lateinit var camera: OrthographicCamera + lateinit var gpu: GraphicsAdapter lateinit var vmRunner: VMRunner - lateinit var coroutineJob: Job - lateinit var memvwr: Memvwr + lateinit var fullscreenQuad: Mesh val usememvwr = false override fun create() { super.create() + fullscreenQuad = Mesh( + true, 4, 6, + VertexAttribute.Position(), + VertexAttribute.ColorUnpacked(), + VertexAttribute.TexCoords(0) + ) + updateFullscreenQuad(appConfig.width, appConfig.height) + + batch = SpriteBatch() + camera = OrthographicCamera(appConfig.width.toFloat(), appConfig.height.toFloat()) + camera.setToOrtho(false) + camera.update() + batch.projectionMatrix = camera.combined + //Gdx.gl20.glViewport(0, 0, appConfig.width, appConfig.height) + + //gpu = GraphicsAdapter(vm, GraphicsAdapter.DEFAULT_CONFIG_COLOR_CRT) - gpu = TexticsAdapter(vm) - //gpu = CharacterLCDdisplay(vm) + //gpu = TexticsAdapter(vm) + gpu = CharacterLCDdisplay(vm) vm.peripheralTable[1] = PeripheralEntry( VM.PERITYPE_GPU_AND_TERM, @@ -47,13 +58,6 @@ class VMGUI(val vm: VM, val appConfig: LwjglApplicationConfiguration) : Applicat Gdx.input.inputProcessor = vm.getIO() - batch = SpriteBatch() - camera = OrthographicCamera(appConfig.width.toFloat(), appConfig.height.toFloat()) - camera.setToOrtho(false) - camera.update() - batch.projectionMatrix = camera.combined - Gdx.gl20.glViewport(0, 0, appConfig.width, appConfig.height) - vm.getPrintStream = { gpu.getPrintStream() } vm.getErrorStream = { gpu.getErrorStream() } vm.getInputStream = { gpu.getInputStream() } @@ -71,6 +75,9 @@ class VMGUI(val vm: VM, val appConfig: LwjglApplicationConfiguration) : Applicat private var updateRate = 1f / 60f override fun render() { + gdxClearAndSetBlend(.094f, .094f, .094f, 0f) + setCameraPosition(0f, 0f) + Gdx.graphics.setTitle("${AppLoader.appTitle} $EMDASH F: ${Gdx.graphics.framesPerSecond}") if (usememvwr) memvwr.update() @@ -99,14 +106,37 @@ class VMGUI(val vm: VM, val appConfig: LwjglApplicationConfiguration) : Applicat fun poke(addr: Long, value: Byte) = vm.poke(addr, value) private fun renderGame(delta: Float) { - gpu.render(delta, batch, 0f, 0f) - + gpu.render(delta, batch, camera, 0f, 0f) + //batch.inUse { batch.draw(testTex, 0f, 0f) } } + private fun setCameraPosition(newX: Float, newY: Float) { + camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f) // deliberate integer division + camera.update() + batch.setProjectionMatrix(camera.combined) + } + + private fun gdxClearAndSetBlend(r: Float, g: Float, b: Float, a: Float) { + Gdx.gl.glClearColor(r,g,b,a) + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + Gdx.gl.glEnable(GL20.GL_TEXTURE_2D) + Gdx.gl.glEnable(GL20.GL_BLEND) + } + + private fun updateFullscreenQuad(WIDTH: Int, HEIGHT: Int) { // NOT y-flipped quads! + fullscreenQuad.setVertices(floatArrayOf( + 0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 1f, + WIDTH.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 1f, + WIDTH.toFloat(), HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 0f, + 0f, HEIGHT.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 0f + )) + fullscreenQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0)) + } override fun dispose() { super.dispose() batch.dispose() + fullscreenQuad.dispose() coroutineJob.cancel() vm.dispose() } diff --git a/src/net/torvald/tsvm/peripheral/CharacterLCDdisplay.kt b/src/net/torvald/tsvm/peripheral/CharacterLCDdisplay.kt index c920ed1..e341a8a 100644 --- a/src/net/torvald/tsvm/peripheral/CharacterLCDdisplay.kt +++ b/src/net/torvald/tsvm/peripheral/CharacterLCDdisplay.kt @@ -26,7 +26,7 @@ class CharacterLCDdisplay(vm: VM) : GraphicsAdapter(vm, AdapterConfig( } } - override fun render(delta: Float, batch: SpriteBatch, xoff: Float, yoff: Float) { + /*override fun render(delta: Float, batch: SpriteBatch, xoff: Float, yoff: Float) { /*batch.shader = null batch.inUse { batch.color = Color.WHITE @@ -34,8 +34,7 @@ class CharacterLCDdisplay(vm: VM) : GraphicsAdapter(vm, AdapterConfig( } super.render(delta, batch, xoff+200, yoff-200) */ - super.render(delta, batch, xoff, yoff) - } + }*/ override fun dispose() { machine.dispose() diff --git a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt index 2542238..be9f998 100644 --- a/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt +++ b/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -1,10 +1,7 @@ package net.torvald.tsvm.peripheral import com.badlogic.gdx.Gdx -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.graphics.GL20 -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.glutils.FrameBuffer import net.torvald.UnsafeHelper @@ -106,6 +103,9 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super private var textTex = Texture(textPixmap) private val outFBOs = Array(2) { FrameBuffer(Pixmap.Format.RGBA8888, WIDTH, HEIGHT, false) } + private val outFBObatch = SpriteBatch() + private val outFBOcamera = OrthographicCamera(WIDTH.toFloat(), HEIGHT.toFloat()) + private val memTextCursorPosOffset = 2978L private val memTextForeOffset = 2980L @@ -145,6 +145,10 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super private fun toTtyTextOffset(x: Int, y: Int) = y * TEXT_COLS + x init { + outFBOcamera.setToOrtho(false) + outFBOcamera.update() + outFBObatch.projectionMatrix = outFBOcamera.combined + framebuffer.blending = Pixmap.Blending.None textForePixmap.blending = Pixmap.Blending.None textBackPixmap.blending = Pixmap.Blending.None @@ -565,6 +569,7 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super } override fun dispose() { + testTex.dispose() framebuffer.dispose() rendertex.dispose() spriteAndTextArea.destroy() @@ -575,6 +580,7 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super textShader.dispose() faketex.dispose() outFBOs.forEach { it.dispose() } + outFBObatch.dispose() try { textForeTex.dispose() } catch (_: Throwable) {} try { textBackTex.dispose() } catch (_: Throwable) {} @@ -588,16 +594,17 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super private var glowDecay = config.decay private var decayColor = Color(1f, 1f, 1f, 1f - glowDecay) - open fun render(delta: Float, batch: SpriteBatch, xoff: Float, yoff: Float) { + open fun render(delta: Float, uiBatch: SpriteBatch, uiCamera: Camera, xoff: Float, yoff: Float) { rendertex.dispose() rendertex = Texture(framebuffer, Pixmap.Format.RGBA8888, false) outFBOs[1].inUse { - batch.shader = null - batch.inUse { - blendNormal(batch) - batch.color = decayColor - batch.draw(outFBOs[0].colorBufferTexture, 0f, HEIGHT.toFloat(), WIDTH.toFloat(), -HEIGHT.toFloat()) + outFBObatch.shader = null + outFBObatch.projectionMatrix = outFBOcamera.combined + outFBObatch.inUse { + blendNormal(outFBObatch) + outFBObatch.color = decayColor + outFBObatch.draw(outFBOs[0].colorBufferTexture, 0f, HEIGHT.toFloat(), WIDTH.toFloat(), -HEIGHT.toFloat()) } } @@ -609,31 +616,32 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) - batch.shader = null - batch.inUse { - blendNormal(batch) + outFBObatch.shader = null + outFBObatch.projectionMatrix = outFBOcamera.combined + outFBObatch.inUse { + blendNormal(outFBObatch) // clear screen - batch.color = if (theme.startsWith("pmlcd")) LCD_BASE_COL else clearCol - batch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) + outFBObatch.color = if (theme.startsWith("pmlcd")) LCD_BASE_COL else clearCol + outFBObatch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) // initiialise draw - batch.color = Color.WHITE - batch.shader = paletteShader + outFBObatch.color = Color.WHITE + outFBObatch.shader = paletteShader // feed palette data // must be done every time the shader is "actually loaded" // try this: if above line precedes 'batch.shader = paletteShader', it won't work - batch.shader.setUniform4fv("pal", paletteOfFloats, 0, paletteOfFloats.size) - if (theme.startsWith("pmlcd")) batch.shader.setUniformf("lcdBaseCol", LCD_BASE_COL) + outFBObatch.shader.setUniform4fv("pal", paletteOfFloats, 0, paletteOfFloats.size) + if (theme.startsWith("pmlcd")) outFBObatch.shader.setUniformf("lcdBaseCol", LCD_BASE_COL) // draw framebuffer - batch.draw(rendertex, 0f, 0f) + outFBObatch.draw(rendertex, 0f, 0f) // draw texts or sprites - batch.color = Color.WHITE + outFBObatch.color = Color.WHITE if (!graphicsUseSprites) { // draw texts @@ -695,7 +703,7 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super chrrom0.bind(1) faketex.bind(0) - batch.shader = textShader + outFBObatch.shader = textShader textShader.setUniformi("foreColours", 4) textShader.setUniformi("backColours", 3) textShader.setUniformi("tilemap", 2) @@ -705,14 +713,14 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super textShader.setUniformf("screenDimension", WIDTH.toFloat(), HEIGHT.toFloat()) textShader.setUniformf("tilesInAtlas", 16f, 16f) textShader.setUniformf("atlasTexSize", chrrom0.width.toFloat(), chrrom0.height.toFloat()) - if (theme.startsWith("pmlcd")) batch.shader.setUniformf("lcdBaseCol", LCD_BASE_COL) + if (theme.startsWith("pmlcd")) outFBObatch.shader.setUniformf("lcdBaseCol", LCD_BASE_COL) - batch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) + outFBObatch.draw(faketex, 0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat()) - batch.shader = null + outFBObatch.shader = null } else { // draw sprites - batch.shader = paletteShader + outFBObatch.shader = paletteShader // feed palette data // must be done every time the shader is "actually loaded" @@ -723,28 +731,42 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super } - batch.shader = null + outFBObatch.shader = null } outFBOs[1].inUse { - batch.shader = null - batch.inUse { - blendNormal(batch) + outFBObatch.shader = null + outFBObatch.projectionMatrix = outFBOcamera.combined + outFBObatch.inUse { + blendNormal(outFBObatch) - batch.color = decayColor - batch.draw(outFBOs[0].colorBufferTexture, 0f, HEIGHT.toFloat(), WIDTH.toFloat(), -HEIGHT.toFloat()) + outFBObatch.color = decayColor + outFBObatch.draw(outFBOs[0].colorBufferTexture, 0f, HEIGHT.toFloat(), WIDTH.toFloat(), -HEIGHT.toFloat()) } } - batch.shader = null - batch.inUse { + outFBOs[1].inUse { + outFBObatch.shader = null + outFBObatch.projectionMatrix = outFBOcamera.combined + outFBObatch.inUse { + blendNormal(outFBObatch) + outFBObatch.color = Color.WHITE + outFBObatch.draw(testTex, 0f, 0f) + } + } + + uiBatch.shader = null + uiBatch.projectionMatrix = uiCamera.combined + uiBatch.inUse { Gdx.gl.glClearColor(0f, 0f, 0f, 1f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) - blendNormal(batch) + blendNormal(uiBatch) - batch.color = Color.WHITE - batch.draw(outFBOs[1].colorBufferTexture, xoff, HEIGHT.toFloat() + yoff, WIDTH.toFloat(), -HEIGHT.toFloat()) + uiBatch.color = Color.WHITE + //uiBatch.draw(outFBOs[1].colorBufferTexture, xoff, HEIGHT.toFloat() + yoff, WIDTH.toFloat(), -HEIGHT.toFloat()) + uiBatch.draw(testTex, 0f, 0f) + uiBatch.draw(outFBOs[1].colorBufferTexture, 0f, 0f) } @@ -756,6 +778,8 @@ open class GraphicsAdapter(val vm: VM, val config: AdapterConfig, val sgr: Super } + private val testTex = Texture("./assets/pal.png"); + private fun blendNormal(batch: SpriteBatch) { Gdx.gl.glEnable(GL20.GL_TEXTURE_2D) Gdx.gl.glEnable(GL20.GL_BLEND) diff --git a/src/net/torvald/tsvm/peripheral/TexticsAdapter.kt b/src/net/torvald/tsvm/peripheral/TexticsAdapter.kt index 2aa3706..e00bffe 100644 --- a/src/net/torvald/tsvm/peripheral/TexticsAdapter.kt +++ b/src/net/torvald/tsvm/peripheral/TexticsAdapter.kt @@ -1,5 +1,6 @@ package net.torvald.tsvm.peripheral +import com.badlogic.gdx.graphics.Camera import com.badlogic.gdx.graphics.Color import com.badlogic.gdx.graphics.GL20 import com.badlogic.gdx.graphics.Texture @@ -62,8 +63,8 @@ class TexticsAdapter(vm: VM) : GraphicsAdapter(vm, AdapterConfig( private val ALIGN = (HEIGHT - TEX_HEIGHT).absoluteValue / 2f private val phosphorCol = crtColor[theme.substring(4)] ?: crtColor["white"] - override fun render(delta: Float, batch: SpriteBatch, xoff: Float, yoff: Float) { - super.render(delta, batch, xoff, yoff) + override fun render(delta: Float, batch: SpriteBatch, camera: Camera, xoff: Float, yoff: Float) { + super.render(delta, batch, camera, xoff, yoff) batch.inUse { diff --git a/src/net/torvald/tsvm/vdc/V2kRunTest.kt b/src/net/torvald/tsvm/vdc/V2kRunTest.kt index 80b6222..c4f8787 100644 --- a/src/net/torvald/tsvm/vdc/V2kRunTest.kt +++ b/src/net/torvald/tsvm/vdc/V2kRunTest.kt @@ -89,7 +89,7 @@ class V2kRunTest(val appConfig: LwjglApplicationConfiguration) : ApplicationAdap } private fun renderGame(delta: Float) { - gpu.render(delta, batch, 0f, 0f) + gpu.render(delta, batch, camera, 0f, 0f) }