From 8a71a4c852a67c18937e4e1bf7f7b7981541ce9f Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Wed, 5 Oct 2016 16:35:01 +0900 Subject: [PATCH] improved terminal drawing performance, and I BROKE COLOUR FILTER Former-commit-id: ea137e0f9bc94d7c4f246ce45e7570877e4cc534 Former-commit-id: 3f66e2f12e3c42262adbc00f04a6ee9d76c0a49c --- src/net/torvald/aa/AAFrame.kt | 11 ++- src/net/torvald/terrarum/StateVTTest.kt | 38 +++++++-- .../virtualcomputer/assets/lua/BOOT.lua | 2 +- .../virtualcomputer/luaapi/Filesystem.kt | 5 +- .../terminal/SimpleTextTerminal.kt | 85 ++++++++++--------- 5 files changed, 92 insertions(+), 49 deletions(-) diff --git a/src/net/torvald/aa/AAFrame.kt b/src/net/torvald/aa/AAFrame.kt index 067828717..65e0058ca 100644 --- a/src/net/torvald/aa/AAFrame.kt +++ b/src/net/torvald/aa/AAFrame.kt @@ -1,13 +1,16 @@ package net.torvald.aa import net.torvald.terrarum.gameworld.toUint +import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal import org.newdawn.slick.* /** + * @param terminal: for sending redraw only + * * Created by minjaesong on 16-08-10. */ class AAFrame @Throws(SlickException::class) -constructor(var width: Int, var height: Int) { +constructor(var width: Int, var height: Int, var terminal: SimpleTextTerminal) { /** * 0000_0000_00000000 @@ -30,6 +33,8 @@ constructor(var width: Int, var height: Int) { if (y * width + x >= frameBuffer.size || y * width + x < 0) throw ArrayIndexOutOfBoundsException("x: $x, y; $y") frameBuffer[y * width + x] = ((c.toInt().and(0xFF)) + colourKey.shl(8)).toChar() + + terminal.redraw() } fun drawBuffer(x: Int, y: Int, raw: Char): Boolean = @@ -37,6 +42,7 @@ constructor(var width: Int, var height: Int) { false else { frameBuffer[y * width + x] = raw + terminal.redraw() true } @@ -45,6 +51,7 @@ constructor(var width: Int, var height: Int) { val char = (other[i].toUint().shl(8) + other[i + 1].toUint()).toChar() frameBuffer[i.ushr(1)] = char } + terminal.redraw() } fun getBackgroundColour(x: Int, y: Int): Int { @@ -71,6 +78,7 @@ constructor(var width: Int, var height: Int) { drawBuffer(x, y, 0.toChar(), background.shl(4)) } } + terminal.redraw() } fun drawFromOther(other: AAFrame) { @@ -80,6 +88,7 @@ constructor(var width: Int, var height: Int) { frameBuffer[y * width + x] = other.getRaw(x, y)!! } } + terminal.redraw() } private fun checkOOB(x: Int, y: Int) = (x < 0 || y < 0 || x >= width || y >= height) diff --git a/src/net/torvald/terrarum/StateVTTest.kt b/src/net/torvald/terrarum/StateVTTest.kt index c2f9bb5c6..e7f6cc88b 100644 --- a/src/net/torvald/terrarum/StateVTTest.kt +++ b/src/net/torvald/terrarum/StateVTTest.kt @@ -21,8 +21,8 @@ class StateVTTest : BasicGameState() { // HiRes: 100x64, LoRes: 80x25 val computerInside = BaseTerrarumComputer(8) - val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25, - computerInside, colour = true, hires = false) + val vt = SimpleTextTerminal(SimpleTextTerminal.WHITE, 80, 25, + computerInside, colour = false, hires = false) val vtUI = Image(vt.displayW, vt.displayH) @@ -47,14 +47,40 @@ class StateVTTest : BasicGameState() { private val paperColour = Color(0xfffce6) + val vtUIrenderX = Terrarum.WIDTH.minus(vtUI.width).div(2f) + val vtUIrenderY = Terrarum.HEIGHT.minus(vtUI.height).div(2f) + override fun render(container: GameContainer, game: StateBasedGame, g: Graphics) { vt.render(container, vtUI.graphics) - g.drawImage(vtUI, - Terrarum.WIDTH.minus(vtUI.width).div(2f), - Terrarum.HEIGHT.minus(vtUI.height).div(2f)) - vtUI.graphics.flush() + blendNormal() + g.drawImage(vtUI, vtUIrenderX, vtUIrenderY) + + + // cursor + if (vt.cursorBlinkOn) { + g.color = vt.getColor(if (vt.cursorBlink) vt.foreDefault else vt.backDefault) + + g.fillRect( + vt.fontW * vt.cursorX.toFloat() + vt.borderSize + vtUIrenderX, + vt.fontH * vt.cursorY.toFloat() + vt.borderSize + vtUIrenderY, + vt.fontW.toFloat(), + vt.fontH.toFloat() + ) + } + + + // not-pure-black screen + /*g.color = vt.colourScreen + blendScreen() + g.fillRect(vtUIrenderX, vtUIrenderY, vt.displayW.toFloat(), vt.displayH.toFloat()) + + + // colour overlay + g.color = vt.phosphor + blendMul() + g.fillRect(vtUIrenderX, vtUIrenderY, vt.displayW.toFloat(), vt.displayH.toFloat())*/ } override fun keyPressed(key: Int, c: Char) { diff --git a/src/net/torvald/terrarum/virtualcomputer/assets/lua/BOOT.lua b/src/net/torvald/terrarum/virtualcomputer/assets/lua/BOOT.lua index 8500d8bf1..eaf6ceda0 100644 --- a/src/net/torvald/terrarum/virtualcomputer/assets/lua/BOOT.lua +++ b/src/net/torvald/terrarum/virtualcomputer/assets/lua/BOOT.lua @@ -10,7 +10,7 @@ _G._TERRARUM = true -- for multi-env programs -- global functions _G.runscript = function(s, src, ...) - if s:byte(1) == 27 then error("Bytecode execution is prohibited.") end -- untested; it's Lua 5.1 code and we're 5.2 + if s:byte(1) == 0x1b then error("Bytecode execution is prohibited.") end -- exact MAGIC is 0x1b 'L' 'u' 'a' local code, reason = load(s, src) diff --git a/src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt b/src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt index ee38dbbbf..15ccf09f8 100644 --- a/src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt +++ b/src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt @@ -141,7 +141,10 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) { val table = LuaTable() val file = File(computer.getRealPath(path)).absoluteFile - file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) } + try { + file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) } + } + catch (e: NullPointerException) {} return table } } diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt index bb10a6460..b2f9a0138 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt @@ -62,15 +62,15 @@ open class SimpleTextTerminal( ) // THESE ARE THE STANDARD val phosphor = if (colour) WHITE7500 else phosphorColour - open protected val colourScreen = if (colour) Color(8, 8, 8) else Color(19, 19, 19) + open val colourScreen = if (colour) Color(8, 8, 8) else Color(19, 19, 19) override val coloursCount: Int get() = colours.size val errorColour = if (coloursCount > 4) 6 else 1 - open protected val backDefault = 0 // STANDARD - open protected val foreDefault = 3 // STANDARD + open val backDefault = 0 // STANDARD + open val foreDefault = 3 // STANDARD override var backColour = backDefault override var foreColour = foreDefault @@ -81,7 +81,7 @@ open class SimpleTextTerminal( override var cursorY = 0 override var cursorBlink = true - val screenBuffer = AAFrame(width, height) + val screenBuffer = AAFrame(width, height, this) open protected val fontRef = "./assets/graphics/fonts/${ @@ -90,11 +90,11 @@ open class SimpleTextTerminal( else "milkymda.png" }" open protected val fontImg = Image(fontRef) - open protected val fontW = fontImg.width / 16 - open protected val fontH = fontImg.height / 16 + open val fontW = fontImg.width / 16 + open val fontH = fontImg.height / 16 open protected val font = ColouredFastFont(this, fontRef, fontW, fontH) - private val borderSize = 20 + val borderSize = 20 override val displayW = fontW * width + 2 * borderSize override val displayH = fontH * height + 2 * borderSize @@ -103,9 +103,12 @@ open class SimpleTextTerminal( private var cursorBlinkTimer = 0 private val cursorBlinkLen = 250 - private var cursorBlinkOn = true + var cursorBlinkOn = true + private set + private var redrawSemaphore = false + override fun getColor(index: Int): Color = colours[index] @@ -140,63 +143,65 @@ open class SimpleTextTerminal( * pass UIcanvas to the parameter "g" */ override fun render(gc: GameContainer, g: Graphics) { + // FIXME don't redraw every time it's slow g.font = font - blendNormal() - // black background (this is mandatory) - g.color = Color.black - g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat()) + // don't redraw() every fucking time, you're wasting your precious process cycle + if (redrawSemaphore) { + + blendNormal() + + // black background (this is mandatory) + g.color = Color.black + g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat()) - // screen buffer - for (y in 0..height - 1) { - for (x in 0..width - 1) { - val ch = screenBuffer.getChar(x, y) + // screen buffer + for (y in 0..height - 1) { + for (x in 0..width - 1) { + val ch = screenBuffer.getChar(x, y) - // background - g.color = getColor(screenBuffer.getBackgroundColour(x, y)) - g.fillRect(fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize, - fontW.toFloat(), fontH.toFloat()) + // background + g.color = getColor(screenBuffer.getBackgroundColour(x, y)) + g.fillRect(fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize, + fontW.toFloat(), fontH.toFloat()) - // foreground - if (ch.toInt() != 0 && ch.toInt() != 32) { - g.color = getColor(screenBuffer.getForegroundColour(x, y)) - g.drawString( - Character.toString(ch), - fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize) + // foreground + if (ch.toInt() != 0 && ch.toInt() != 32) { + g.color = getColor(screenBuffer.getForegroundColour(x, y)) + g.drawString( + Character.toString(ch), + fontW * x.toFloat() + borderSize, fontH * y.toFloat() + borderSize) + } } } + + redrawSemaphore = false } // cursor - g.color = getColor(foreDefault) - if (cursorBlinkOn && cursorBlink) + /*if (cursorBlinkOn) { + g.color = getColor(if (cursorBlink) foreDefault else backDefault) + g.fillRect( fontW * cursorX.toFloat() + borderSize, fontH * cursorY.toFloat() + borderSize, fontW.toFloat(), fontH.toFloat() ) - - - // not-pure-black screen - g.color = colourScreen - blendScreen() - g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat()) - - - // colour overlay - g.color = phosphor - blendMul() - g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat()) + }*/ blendNormal() } + fun redraw() { + redrawSemaphore = true + } + /** Unlike lua function, this one in Zero-based. */ override fun setCursor(x: Int, y: Int) { cursorX = x