diff --git a/assets/graphics/fonts/cp949.png b/assets/graphics/fonts/cp949.png new file mode 100644 index 000000000..e2f92440e Binary files /dev/null and b/assets/graphics/fonts/cp949.png differ diff --git a/assets/graphics/fonts/cp949.png.0.png b/assets/graphics/fonts/cp949.png.0.png new file mode 100644 index 000000000..0fced4be2 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.0.png differ diff --git a/assets/graphics/fonts/cp949.png.1.png b/assets/graphics/fonts/cp949.png.1.png new file mode 100644 index 000000000..188d086b8 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.1.png differ diff --git a/assets/graphics/fonts/cp949.png.10.png b/assets/graphics/fonts/cp949.png.10.png new file mode 100644 index 000000000..4edc106f9 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.10.png differ diff --git a/assets/graphics/fonts/cp949.png.11.png b/assets/graphics/fonts/cp949.png.11.png new file mode 100644 index 000000000..b801aefbf Binary files /dev/null and b/assets/graphics/fonts/cp949.png.11.png differ diff --git a/assets/graphics/fonts/cp949.png.12.png b/assets/graphics/fonts/cp949.png.12.png new file mode 100644 index 000000000..5c95dfc60 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.12.png differ diff --git a/assets/graphics/fonts/cp949.png.13.png b/assets/graphics/fonts/cp949.png.13.png new file mode 100644 index 000000000..d5a874c2f Binary files /dev/null and b/assets/graphics/fonts/cp949.png.13.png differ diff --git a/assets/graphics/fonts/cp949.png.14.png b/assets/graphics/fonts/cp949.png.14.png new file mode 100644 index 000000000..624dc8019 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.14.png differ diff --git a/assets/graphics/fonts/cp949.png.15.png b/assets/graphics/fonts/cp949.png.15.png new file mode 100644 index 000000000..4c563987a Binary files /dev/null and b/assets/graphics/fonts/cp949.png.15.png differ diff --git a/assets/graphics/fonts/cp949.png.2.png b/assets/graphics/fonts/cp949.png.2.png new file mode 100644 index 000000000..fc39abdde Binary files /dev/null and b/assets/graphics/fonts/cp949.png.2.png differ diff --git a/assets/graphics/fonts/cp949.png.3.png b/assets/graphics/fonts/cp949.png.3.png new file mode 100644 index 000000000..2c4ff9619 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.3.png differ diff --git a/assets/graphics/fonts/cp949.png.4.png b/assets/graphics/fonts/cp949.png.4.png new file mode 100644 index 000000000..6fc19b1b1 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.4.png differ diff --git a/assets/graphics/fonts/cp949.png.5.png b/assets/graphics/fonts/cp949.png.5.png new file mode 100644 index 000000000..44d888c2f Binary files /dev/null and b/assets/graphics/fonts/cp949.png.5.png differ diff --git a/assets/graphics/fonts/cp949.png.6.png b/assets/graphics/fonts/cp949.png.6.png new file mode 100644 index 000000000..cd9306683 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.6.png differ diff --git a/assets/graphics/fonts/cp949.png.7.png b/assets/graphics/fonts/cp949.png.7.png new file mode 100644 index 000000000..771338099 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.7.png differ diff --git a/assets/graphics/fonts/cp949.png.8.png b/assets/graphics/fonts/cp949.png.8.png new file mode 100644 index 000000000..a5ddbced3 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.8.png differ diff --git a/assets/graphics/fonts/cp949.png.9.png b/assets/graphics/fonts/cp949.png.9.png new file mode 100644 index 000000000..54bb96ba0 Binary files /dev/null and b/assets/graphics/fonts/cp949.png.9.png differ diff --git a/assets/graphics/fonts/teletype_9x12.png b/assets/graphics/fonts/teletype_9x12.png new file mode 100644 index 000000000..12424cdcc Binary files /dev/null and b/assets/graphics/fonts/teletype_9x12.png differ diff --git a/assets/graphics/terrain/terrain.png b/assets/graphics/terrain/terrain.png deleted file mode 100644 index 87003e373..000000000 Binary files a/assets/graphics/terrain/terrain.png and /dev/null differ diff --git a/lib/natives/아카이브.zip b/lib/natives/아카이브.zip new file mode 100644 index 000000000..072628cb7 Binary files /dev/null and b/lib/natives/아카이브.zip differ diff --git a/src/net/torvald/imagefont/TinyAlphNum.kt b/src/net/torvald/imagefont/TinyAlphNum.kt index 3d55c4862..5343735b8 100644 --- a/src/net/torvald/imagefont/TinyAlphNum.kt +++ b/src/net/torvald/imagefont/TinyAlphNum.kt @@ -15,7 +15,7 @@ class TinyAlphNum : Font { internal val W = 8 internal val H = 8 - private val chars = arrayOf( + /*private val chars = arrayOf( '0','1','2','3','4','5','6','7', '8','9','[','#','@',':','>','?', ' ','A','B','C','D','E','F','G', @@ -25,11 +25,11 @@ class TinyAlphNum : Font { '+','/','S','T','U','V','W','X', 'Y','Z','_',',','%','=','"','!' ) - private val mappingTable = HashMap() + private val mappingTable = HashMap()*/ init { - fontSheet = SpriteSheet("./assets/graphics/fonts/alphanumeric_small.png", W, H) - chars.forEachIndexed { i, c -> mappingTable[c.toInt()] = i } + fontSheet = SpriteSheet("./assets/graphics/fonts/cp949.png", W, H) + //chars.forEachIndexed { i, c -> mappingTable[c.toInt()] = i } } override fun getHeight(str: String): Int = H @@ -52,15 +52,29 @@ class TinyAlphNum : Font { var thisCol = col var textPosOffset = 0 for (i in 0..text.length - 1) { - val index = charToSpriteNum(text.toUpperCase().codePointAt(i)) + //val index = charToSpriteNum(text.toUpperCase().codePointAt(i)) val ch = text[i] + val index = ch.toInt() and 0xFF if (ch.isColourCode()) { thisCol = GameFontBase.colourKey[ch]!! continue } if (index != null) { - fontSheet.getSubImage(index % 8, index / 8).draw( + // shadow + fontSheet.getSubImage(index % 16, index / 16).draw( + x + textPosOffset + 1, y, thisCol.darker(0.5f) + ) + fontSheet.getSubImage(index % 16, index / 16).draw( + x + textPosOffset + 1, y + 1, thisCol.darker(0.5f) + ) + fontSheet.getSubImage(index % 16, index / 16).draw( + x + textPosOffset, y + 1, thisCol.darker(0.5f) + ) + + + // main + fontSheet.getSubImage(index % 16, index / 16).draw( x + textPosOffset, y, thisCol ) } @@ -72,7 +86,7 @@ class TinyAlphNum : Font { throw UnsupportedOperationException() } - private fun charToSpriteNum(ch: Int): Int? = mappingTable[ch] + //private fun charToSpriteNum(ch: Int): Int? = mappingTable[ch] fun Char.isColourCode() = GameFontBase.colourKey.containsKey(this) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/StateVTTest.kt b/src/net/torvald/terrarum/StateVTTest.kt index d5a73926d..bddead353 100644 --- a/src/net/torvald/terrarum/StateVTTest.kt +++ b/src/net/torvald/terrarum/StateVTTest.kt @@ -2,7 +2,11 @@ package net.torvald.terrarum import net.torvald.terrarum.gamecontroller.Key import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer +import net.torvald.terrarum.virtualcomputer.terminal.ColouredTextTerminal import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal +import net.torvald.terrarum.virtualcomputer.terminal.Teletype +import net.torvald.terrarum.virtualcomputer.terminal.TeletypeTerminal +import org.newdawn.slick.Color import org.newdawn.slick.GameContainer import org.newdawn.slick.Graphics import org.newdawn.slick.Image @@ -16,7 +20,7 @@ import org.newdawn.slick.state.StateBasedGame */ class StateVTTest : BasicGameState() { - val vt = SimpleTextTerminal(SimpleTextTerminal.IBM_GREEN, 80, 25) + val vt = SimpleTextTerminal(SimpleTextTerminal.AMBER, 80, 25) val computerInside = BaseTerrarumComputer(vt) val vtUI = Image(vt.displayW, vt.displayH) @@ -38,6 +42,8 @@ class StateVTTest : BasicGameState() { override fun getID() = Terrarum.STATE_ID_TEST_TTY + private val paperColour = Color(0xfffce6) + override fun render(container: GameContainer, game: StateBasedGame, g: Graphics) { vt.render(container, vtUI.graphics) @@ -45,7 +51,7 @@ class StateVTTest : BasicGameState() { Terrarum.WIDTH.minus(vtUI.width).div(2f), Terrarum.HEIGHT.minus(vtUI.height).div(2f)) - //vtUI.graphics.flush() + vtUI.graphics.flush() } override fun keyPressed(key: Int, c: Char) { @@ -55,11 +61,11 @@ class StateVTTest : BasicGameState() { if (key == Key.RETURN) { val input = vt.closeInput() - computerInside.runCommand(input, "consoleinput") + computerInside.runCommand(input, "=prompt") vt.openInput() - computerInside.runCommand("io.write(_COMPUTER.prompt)", "prompt") + computerInside.runCommand("io.write(_COMPUTER.prompt)", "=prompt") } } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt index f121a42f7..875d86bd3 100644 --- a/src/net/torvald/terrarum/Terrarum.kt +++ b/src/net/torvald/terrarum/Terrarum.kt @@ -100,14 +100,14 @@ constructor(gamename: String) : StateBasedGame(gamename) { gc.graphics.clear() // clean up any 'dust' in the buffer - addState(StateVTTest()) + //addState(StateVTTest()) //addState(StateTestingSandbox()) //addState(StateSplash()) //addState(StateMonitorCheck()) //addState(StateFontTester()) - //ingame = StateInGame() - //addState(ingame) + ingame = StateInGame() + addState(ingame) } companion object { @@ -439,7 +439,8 @@ fun blendAlphaMap() { fun blendScreen() { GL11.glEnable(GL11.GL_BLEND) GL11.glColorMask(true, true, true, true) - GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_COLOR)} + GL11.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_COLOR) +} fun blendDisable() { GL11.glDisable(GL11.GL_BLEND) diff --git a/src/net/torvald/terrarum/tileproperties/TilePropCodex.kt b/src/net/torvald/terrarum/tileproperties/TilePropCodex.kt index 6cd89850c..df3161fcc 100644 --- a/src/net/torvald/terrarum/tileproperties/TilePropCodex.kt +++ b/src/net/torvald/terrarum/tileproperties/TilePropCodex.kt @@ -29,7 +29,7 @@ object TilePropCodex { try { // todo verify CSV using pre-calculated SHA256 hash - val records = CSVFetcher(CSV_PATH) + val records = CSVFetcher.readFromString(TilePropCSV.text) println("[TilePropCodex] Building tile properties table") diff --git a/src/net/torvald/terrarum/virtualcomputer/assets/lua/CCAPI.lua b/src/net/torvald/terrarum/virtualcomputer/assets/lua/CCAPI.lua new file mode 100644 index 000000000..fb0bc86d8 --- /dev/null +++ b/src/net/torvald/terrarum/virtualcomputer/assets/lua/CCAPI.lua @@ -0,0 +1,168 @@ +--[[ +-- ComputerCraft API compatibility layer + Usage: require("CCAPI") + + Created by minjaesong on 16-09-16. +--]] + +-------------- +-- PREAMBLE -- +-------------- + +if term.isTeletype() then error("This is a teletype; cannot use CCAPI layer") end + + +table.insert(_COMPUTER.loadedCLayer, "CCAPI") + + +local function intLog2(i) + if i == 0 then return 0 end + local log = 0 + if bit32.band(i, 0xffff0000) ~= 0 then i = bit32.rshift(i, 16) log = 16 end + if i >= 256 then i = bit32.rshift(i, 8) log = log + 8 end + if i >= 16 then i = bit32.rshift(i, 8) log = log + 4 end + if i >= 4 then i = bit32.rshift(i, 8) log = log + 2 end + return log + bit32.rshift(i, 1) +end + + +------------- +-- BIT API -- +------------- + +_G.bit = {} -- CC's weird BIT API + +bit.blshift = function(n, bits) bit32.lshift(n, bits) end +bit.brshift = function(n, bits) bit32.arshift(n, bits) end +bit.blogic_rshift = function(n, bits) bit32.brshift(n, bits) end +bit.bxor = function(m, n) bit32.bxor(m, n) end +bit.bor = function(m, n) bit32.bor(m, n) end +bit.band = function(m, n) bit32.band(m, n) end +bit.bnot = function(n) bit32.bnot(n) end + + +---------------- +-- COLORS API -- +---------------- + +_G.colors = {} + +colors.white = 0x1 +colors.orange = 0x2 +colors.magenta = 0x4 +colors.lightBlue = 0x8 +colors.yellow = 0x10 +colors.lime = 0x20 +colors.pink = 0x40 +colors.gray = 0x80 +colors.lightGray = 0x100 +colors.cyan = 0x200 +colors.purple = 0x400 +colors.blue = 0x800 +colors.brown = 0x1000 +colors.green = 0x2000 +colors.red = 0x4000 +colors.black = 0x8000 + +colors.combine = function(...) + local ret = 0 + for _, c in ipairs(...) do + ret = bor(ret, c) + end + return ret +end + +local function containsCol(target, cccol) + return bit32.band(target, cccol) > 0 +end + +colors.subtract = function(cccol, ...) + for _, c in ipairs(...) do + if not containsCol(cccol, c) then + cccol = bit32.bxor(cccol, c) + end + end + return cccol +end + + +local function normaliseCCcol(cccol) + if cccol >= 0x1 and cccol <= 0x8FFF then + return intLog2(cccol) + else + error("invalid CC Colors: "..cccol) + end +end + + +-------------- +-- TERM API -- +-------------- + +-- paint_index -> Terminal colour index +local ccToGameCol = {--pink + 1, 5, 7, 10, 4, 11, 15, 2, 3, 10, 8, 9, 14, 12, 6, 0 +} + +-- "a" -> 10, "3" -> 3 +local function cHexToInt(c) + if type(c) == "number" then -- char + if c >= 48 and c <= 57 then + return c - 48 + elseif c >= 65 and c <= 70 then + return c - 65 + elseif c >= 97 and c <= 102 then + return c - 97 + else + return 0 + end + elseif type(c) == "string" then -- single-letter string + if c:byte(1) >= 48 and c:byte(1) <= 57 then + return c:byte(1) - 48 + elseif c:byte(1) >= 65 and c:byte(1) <= 70 then + return c:byte(1) - 65 + elseif c:byte(1) >= 97 and c:byte(1) <= 102 then + return c:byte(1) - 97 + else + --error("unrepresentable: " .. c) + -- return black, as defined in http://www.computercraft.info/wiki/Term.blit + return 0 + end + else + error("bad argument (string or number expected, got "..type(c)..")") + end +end + +-- str, str, str +term.blit = function(text, foreCol, backCol) + assert( + type(text) == "string" and type(backCol) == "string" and type(foreCol) == "string", + "bad argument: (string, string, string expected, got "..type(text)..", "..type(foreCol)..", "..type(backCol)..")" + ) + if #text ~= #foreCol or #text ~= #backCol or #foreCol ~= #backCol then + error("rrguments must be the same length") + end + + for i = 1, #text do + term.setForeCol(cHexToInt(foreCol:byte(i))) + term.setBackCol(cHexToInt(backCol:byte(i))) + term.emit(text:byte(i)) + term.moveCursor(term.getX() + 1, term.getY()) + end +end + +term.getCursorPos = function() return term.getCursor() end +term.setCursorPos = function(x, y) term.moveCursor(x, y) end +term.setCursorBlink = function(b) term.blink(b) end +term.isColor = function() return term.isCol() end +term.getSize = function() return term.size() end +term.setTextColor = function(cccol) term.setForeCol(ccToGameCol[normaliseCCcol(cccol)]) end +term.getTextColor = function() return term.getForeCol() end +term.setBackgroundColor = function(cccol) term.setBackCol(ccToGameCol[normaliseCCcol(cccol)]) end +term.getBackgroundColor = function() return term.getBackCol() end + + + + + +if _COMPUTER.verbose then print("ComputerCraft compatibility layer successfully loaded.") end diff --git a/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMBASIC.lua b/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMBASIC.lua index 5a0f87f08..d3488b003 100644 --- a/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMBASIC.lua +++ b/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMBASIC.lua @@ -1,13 +1,33 @@ +--[[ + Must be loaded VERY FIRST! + + Created by minjaesong on 16-09-13. +--]] + +-- path for any ingame libraries +package.path = "/net/torvald/terrarum/virtualcomputer/assets/lua/?.lua;" .. package.path + -- global variables +_G.MONEYSYM = string.char(0x9D) -- currency sign +_G.MIDDOT = string.char(0xFA) -- middle dot sign _COMPUTER = {} -- standard console colours -_COMPUTER["DC1"] = string.char(17) -- black -_COMPUTER["DC2"] = string.char(18) -- white -_COMPUTER["DC3"] = string.char(19) -- dim grey -_COMPUTER["DC4"] = string.char(20) -- light grey -_COMPUTER["prompt"] = function() +_COMPUTER.DC1 = string.char(17) -- black +_COMPUTER.DC2 = string.char(18) -- white +_COMPUTER.DC3 = string.char(19) -- dim grey +_COMPUTER.DC4 = string.char(20) -- light grey +_COMPUTER.prompt = function() io.write(_COMPUTER.DC3 .. "> " .. _COMPUTER.DC4) end --- greet user +_COMPUTER.verbose = true -- print debug info +_COMPUTER.loadedCLayer = {} -- list of loaded compatibility layers + +-- load libraries that coded in Lua +require("ROMLIB") + + +-- load bios, if any + +-- load Lua prompt, if bios is not found print("Rom basic " .. _COMPUTER.DC2 .. _VERSION .. _COMPUTER.DC4) -- print(_COMPUTER.DC2 .. freemem .. _COMPUTER.DC4 .. " bytes free" print("Ok") diff --git a/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMLIB.lua b/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMLIB.lua new file mode 100644 index 000000000..531adbd89 --- /dev/null +++ b/src/net/torvald/terrarum/virtualcomputer/assets/lua/ROMLIB.lua @@ -0,0 +1,48 @@ +--[[ + Created by minjaesong on 16-09-15. +--]] + + +-------------- +-- HEXUTILS -- +-------------- + +_G.hexutils = {} + +_G.hexutils.toHexString = function(byteString) + assert(type(byteString) == "string", error("Expected string.")) + + -- speedup + local function iToHex(i) + if i == 0 then return "0" + elseif i == 1 then return "1" + elseif i == 2 then return "2" + elseif i == 3 then return "3" + elseif i == 4 then return "4" + elseif i == 5 then return "5" + elseif i == 6 then return "6" + elseif i == 7 then return "7" + elseif i == 8 then return "8" + elseif i == 9 then return "9" + elseif i == 10 then return "a" + elseif i == 11 then return "b" + elseif i == 12 then return "c" + elseif i == 13 then return "d" + elseif i == 14 then return "e" + elseif i == 15 then return "f" + else error("unrepresentable: " .. i) + end + end + + local ret = "" + + for i = 1, #byteString do + local c = byteString:byte(i) + local msb = iToHex(bit32.rshift(c, 4) % 16) + local lsb = iToHex(c % 16) + + ret = ret .. (msb .. lsb) + end + + return ret +end diff --git a/src/net/torvald/terrarum/virtualcomputer/computer/BaseTerrarumComputer.kt b/src/net/torvald/terrarum/virtualcomputer/computer/BaseTerrarumComputer.kt index e27efc7fa..2199833d3 100644 --- a/src/net/torvald/terrarum/virtualcomputer/computer/BaseTerrarumComputer.kt +++ b/src/net/torvald/terrarum/virtualcomputer/computer/BaseTerrarumComputer.kt @@ -5,10 +5,7 @@ import li.cil.repack.org.luaj.vm2.LuaError import li.cil.repack.org.luaj.vm2.LuaValue import li.cil.repack.org.luaj.vm2.lib.jse.JsePlatform import net.torvald.terrarum.virtualcomputer.lualib.TermLib -import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal -import net.torvald.terrarum.virtualcomputer.terminal.Terminal -import net.torvald.terrarum.virtualcomputer.terminal.TerminalInputStream -import net.torvald.terrarum.virtualcomputer.terminal.TerminalPrintStream +import net.torvald.terrarum.virtualcomputer.terminal.* import org.newdawn.slick.GameContainer import java.io.* @@ -19,7 +16,7 @@ import java.io.* * * Created by minjaesong on 16-09-10. */ -class BaseTerrarumComputer(term: Terminal?) { +class BaseTerrarumComputer(term: Teletype?) { val luaJ_globals: Globals = JsePlatform.standardGlobals() @@ -40,7 +37,8 @@ class BaseTerrarumComputer(term: Terminal?) { luaJ_globals.STDERR = termErr luaJ_globals.STDIN = termIn - loadTermLib(term) + // load libraries + TermLib(luaJ_globals, term) } // ROM BASIC @@ -135,21 +133,4 @@ class BaseTerrarumComputer(term: Terminal?) { val DEBUGTHRE = true } - - ///////////////////////// - // MANUAU LIBRARY LOAD // - ///////////////////////// - private fun loadTermLib(term: Terminal) { - luaJ_globals["term"] = LuaValue.tableOf() - luaJ_globals["term"]["test"] = TermLib.Test(term) - luaJ_globals["term"]["setCursorPos"] = TermLib.MoveCursor(term) - luaJ_globals["term"]["setcursorpos"] = TermLib.MoveCursor(term) - luaJ_globals["term"]["gotoxy"] = TermLib.MoveCursor(term) // pascal-style alias - luaJ_globals["term"]["getCursorPos"] = TermLib.GetCursorPos(term) - luaJ_globals["term"]["getcursorpos"] = TermLib.GetCursorPos(term) - luaJ_globals["term"]["setCursorBlink"] = TermLib.SetCursorBlink(term) - luaJ_globals["term"]["setcursorblink"] = TermLib.SetCursorBlink(term) - luaJ_globals["term"]["getSize"] = TermLib.GetSize(term) - luaJ_globals["term"]["getsize"] = TermLib.GetSize(term) - } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/lualib/SecurityLib.kt b/src/net/torvald/terrarum/virtualcomputer/lualib/SecurityLib.kt new file mode 100644 index 000000000..82dbdb4c1 --- /dev/null +++ b/src/net/torvald/terrarum/virtualcomputer/lualib/SecurityLib.kt @@ -0,0 +1,83 @@ +package net.torvald.terrarum.virtualcomputer.lualib + +import li.cil.repack.org.luaj.vm2.LuaValue +import li.cil.repack.org.luaj.vm2.lib.OneArgFunction +import net.torvald.terrarum.gameworld.toUint +import org.apache.commons.codec.binary.Base64 +import org.apache.commons.codec.digest.DigestUtils +import java.security.SecureRandom + +/** + * Created by minjaesong on 16-09-15. + */ +class SecurityLib { + /** @return byteArray as String */ + class SHA256sum : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + val hashBytes = DigestUtils.sha256(p0.checkjstring()) + return LuaValue.valueOf(hashBytes.toStringRepresentation()) + } + } + + /** @return byteArray as String */ + class SHA1sum: OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + val hashBytes = DigestUtils.sha1(p0.checkjstring()) + return LuaValue.valueOf(hashBytes.toStringRepresentation()) + } + } + + /** @return byteArray as String */ + class MD5sum: OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + val hashBytes = DigestUtils.md5(p0.checkjstring()) + return LuaValue.valueOf(hashBytes.toStringRepresentation()) + } + } + + /** @return byteArray as String */ + class SecureRandomHex: OneArgFunction() { + override fun call(byteSize: LuaValue): LuaValue { + val bytes = ByteArray(byteSize.checkint()) + SecureRandom().nextBytes(bytes) + + return LuaValue.valueOf(bytes.toStringRepresentation()) + } + } + + /** @return String */ + class DecodeBase64: OneArgFunction() { + override fun call(base64: LuaValue): LuaValue { + val decodedBytes = Base64.decodeBase64(base64.checkjstring()) + return LuaValue.valueOf(decodedBytes.toStringRepresentation()) + } + } + + /** @return byteArray as String */ + class EncodeBase64: OneArgFunction() { + override fun call(inputString: LuaValue): LuaValue { + val inputBytes = inputString.checkjstring().toByteArray(charset("UTF-8")) + return LuaValue.valueOf(Base64.encodeBase64(inputBytes).toStringRepresentation()) + } + } + + companion object { + val hexLookup = charArrayOf( + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + ) + + fun Byte.toHexString(): String { + val bInt = this.toUint() + return "${hexLookup[bInt.shr(8).and(0xf)]}${hexLookup[bInt.and(0xf)]}" + } + + /** essentially, 0xFC to 0xFC.toChar() */ + fun ByteArray.toStringRepresentation(): String { + val sb = StringBuilder() + for (b in this) + sb.append(b.toChar()) + return sb.toString() + } + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/lualib/TermLib.kt b/src/net/torvald/terrarum/virtualcomputer/lualib/TermLib.kt index 93fc41a4a..e85afde8b 100644 --- a/src/net/torvald/terrarum/virtualcomputer/lualib/TermLib.kt +++ b/src/net/torvald/terrarum/virtualcomputer/lualib/TermLib.kt @@ -2,6 +2,7 @@ package net.torvald.terrarum.virtualcomputer.lualib import li.cil.repack.org.luaj.vm2.* import li.cil.repack.org.luaj.vm2.lib.* +import net.torvald.terrarum.virtualcomputer.terminal.Teletype import net.torvald.terrarum.virtualcomputer.terminal.Terminal /** @@ -9,35 +10,135 @@ import net.torvald.terrarum.virtualcomputer.terminal.Terminal * * Created by minjaesong on 16-09-12. */ -internal class TermLib(val vt: Terminal) : ZeroArgFunction() { - var INSTANCE: TermLib? = null +internal class TermLib(globals: Globals, term: Teletype) { init { - if (INSTANCE == null) INSTANCE = this - } + // load things. WARNING: THIS IS MANUAL! + globals["term"] = LuaValue.tableOf() + globals["term"]["write"] = TermLib.WriteString(term) + globals["term"]["print"] = TermLib.PrintString(term) + globals["term"]["newLine"] = TermLib.NewLine(term) + globals["term"]["moveCursor"] = TermLib.MoveCursor(term) // TTY function + globals["term"]["width"] = TermLib.GetWidth(term) + globals["term"]["scroll"] = TermLib.Scroll(term) + globals["term"]["isTeletype"] = TermLib.IsTeletype(term) - override fun call(): LuaValue { - throw UnsupportedOperationException("""Invalid usage! -usage: - luaJ_globals["term"] = LuaValue.tableOf() - luaJ_globals["term"]["test"] = TermLib.Test(term) - ... -""") - } - - class Test(val term: Terminal) : ZeroArgFunction() { - override fun call(): LuaValue { - return LuaDouble.valueOf("TermTest") + if (term is Terminal) { + globals["term"]["emitRaw"] = TermLib.EmitRaw(term) + globals["term"]["emit"] = TermLib.Emit(term) + globals["term"]["resetColor"] = TermLib.ResetColour(term) + globals["term"]["resetColour"] = TermLib.ResetColour(term) + globals["term"]["clear"] = TermLib.Clear(term) + globals["term"]["clearLine"] = TermLib.ClearLine(term) + globals["term"]["moveCursor"] = TermLib.SetCursorPos(term) + globals["term"]["getCursor"] = TermLib.GetCursorPos(term) + globals["term"]["getX"] = TermLib.GetCursorX(term) + globals["term"]["getY"] = TermLib.GetCursorY(term) + globals["term"]["blink"] = TermLib.SetCursorBlink(term) + globals["term"]["size"] = TermLib.GetSize(term) + globals["term"]["isCol"] = TermLib.IsColour(term) + globals["term"]["setForeCol"] = TermLib.SetForeColour(term) + globals["term"]["setBackCol"] = TermLib.SetBackColour(term) + globals["term"]["foreCol"] = TermLib.GetForeColour(term) + globals["term"]["backCol"] = TermLib.GetBackColour(term) } } - class MoveCursor(val term: Terminal) : TwoArgFunction() { + class WriteString(val tty: Teletype) : LuaFunction() { + override fun call(p0: LuaValue): LuaValue { + if (tty is Terminal) + tty.writeString(p0.checkjstring()) + else + tty.writeChars(p0.checkjstring()) + return LuaValue.NONE + } + + override fun call(s: LuaValue, x: LuaValue, y: LuaValue): LuaValue { + if (tty is Terminal) + tty.writeString(s.checkjstring(), x.checkint(), y.checkint()) + else + throw LuaError("couldn't move cursor; TTY is one-dimensional") + return LuaValue.NONE + } + } + + class PrintString(val tty: Teletype) : LuaFunction() { + override fun call(p0: LuaValue): LuaValue { + if (tty is Terminal) + tty.printString(p0.checkjstring()) + else + tty.printChars(p0.checkjstring()) + return LuaValue.NONE + } + + override fun call(s: LuaValue, x: LuaValue, y: LuaValue): LuaValue { + if (tty is Terminal) + tty.printString(s.checkjstring(), x.checkint(), y.checkint()) + else + throw LuaError("couldn't move cursor; TTY is one-dimensional") + return LuaValue.NONE + } + } + + class NewLine(val tty: Teletype) : ZeroArgFunction() { + override fun call(): LuaValue { + tty.newLine() + return LuaValue.NONE + } + } + + class EmitRaw(val term: Terminal) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + term.emitChar(p0.checkint()) + return LuaValue.NONE + } + } + + class Emit(val term: Terminal) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + term.emitChar(p0.checkint().toChar()) + return LuaValue.NONE + } + } + + class ResetColour(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + term.resetColour() + return LuaValue.NONE + } + } + + class Clear(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + term.clear() + return LuaValue.NONE + } + } + + class ClearLine(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + term.clearLine() + return LuaValue.NONE + } + } + + /** term.setCursorPos(number x, number y) */ + class SetCursorPos(val term: Terminal) : TwoArgFunction() { override fun call(x: LuaValue, y: LuaValue): LuaValue { term.setCursor(x.checkint(), y.checkint()) return LuaValue.NONE } } + /** term.setCursorPos(number x) */ + class MoveCursor(val tty: Teletype) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + for (i in 1..p0.checkint()) + tty.printChar(' ') + return LuaValue.NONE + } + } + class GetCursorPos(val term: Terminal) : VarArgFunction() { override fun invoke(args: Varargs?): Varargs { val ret = arrayOf(LuaValue.valueOf(term.cursorX), LuaValue.valueOf(term.cursorY)) @@ -45,6 +146,19 @@ usage: } } + class GetCursorX(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(term.cursorX) + } + } + + class GetCursorY(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(term.cursorY) + } + } + + /** term.setCursorBlink(boolean bool) */ class SetCursorBlink(val term: Terminal) : OneArgFunction() { override fun call(p0: LuaValue): LuaValue { term.cursorBlink = p0.toboolean() @@ -59,9 +173,58 @@ usage: } } - class IsColor(val term: Terminal) : ZeroArgFunction() { + class GetWidth(val tty: Teletype) : ZeroArgFunction() { override fun call(): LuaValue { - throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + return LuaValue.valueOf(tty.width) + } + } + + class IsColour(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(term.coloursCount > 4) + } + } + + /** term.scroll(number n) */ + class Scroll(val tty: Teletype) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + if (tty is Terminal) tty.scroll(p0.checkint()) + else for (i in 1..p0.checkint()) tty.newLine() + return LuaValue.NONE + } + } + + /** term.setTextColor(number color) */ + class SetForeColour(val term: Terminal) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + term.foreColour = p0.checkint() + return LuaValue.NONE + } + } + + /** term.setBackgroundColor(number color) */ + class SetBackColour(val term: Terminal) : OneArgFunction() { + override fun call(p0: LuaValue): LuaValue { + term.backColour = p0.checkint() + return LuaValue.NONE + } + } + + class GetForeColour(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(term.foreColour) + } + } + + class GetBackColour(val term: Terminal) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(term.backColour) + } + } + + class IsTeletype(val termInQuestion: Teletype) : ZeroArgFunction() { + override fun call(): LuaValue { + return LuaValue.valueOf(termInQuestion.coloursCount == 0) } } diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/ColouredTextTerminal.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/ColouredTextTerminal.kt index a73c487ec..14f65ed35 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/ColouredTextTerminal.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/ColouredTextTerminal.kt @@ -9,31 +9,33 @@ import org.newdawn.slick.Image /** * Created by minjaesong on 16-09-12. */ -class ColouredTextTerminal(override val width: Int, override val height: Int +class ColouredTextTerminal( + override val width: Int, override val height: Int ) : SimpleTextTerminal(Color.white, width, height) { override val colours = arrayOf( - Color(0x00, 0x00, 0x00), // black - Color(0xff, 0xff, 0xff), // white - Color(0x55, 0x55, 0x55), // dim grey - Color(0xaa, 0xaa, 0xaa), // light grey + Color(0x00, 0x00, 0x00), // 0 black + Color(0xff, 0xff, 0xff), // 1 white + Color(0x55, 0x55, 0x55), // 2 dim grey + Color(0xaa, 0xaa, 0xaa), // 3 light grey - Color(0xff, 0xff, 0x00), // yellow - Color(0xff, 0x66, 0x00), // orange - Color(0xdd, 0x00, 0x00), // red - Color(0xff, 0x00, 0x99), // magenta + Color(0xff, 0xff, 0x00), // 4 yellow + Color(0xff, 0x66, 0x00), // 5 orange + Color(0xdd, 0x00, 0x00), // 6 red + Color(0xff, 0x00, 0x99), // 7 magenta - Color(0x33, 0x00, 0x99), // purple - Color(0x00, 0x00, 0xcc), // blue - Color(0x00, 0x99, 0xff), // cyan - Color(0x66, 0xff, 0x33), // lime + Color(0x33, 0x00, 0x99), // 8 purple + Color(0x00, 0x00, 0xcc), // 9 blue + Color(0x00, 0x99, 0xff), //10 cyan + Color(0x66, 0xff, 0x33), //11 lime - Color(0x00, 0xaa, 0x00), // green - Color(0x00, 0x66, 0x00), // dark green - Color(0x66, 0x33, 0x00), // brown - Color(0x99, 0x66, 0x33) // tan + Color(0x00, 0xaa, 0x00), //12 green + Color(0x00, 0x66, 0x00), //13 dark green + Color(0x66, 0x33, 0x00), //14 brown + Color(0x99, 0x66, 0x33) //15 tan ) // THESE ARE THE STANDARD - override val coloursCount = colours.size + override val coloursCount: Int + get() = colours.size override val backDefault = 0 override val foreDefault = 3 @@ -41,11 +43,11 @@ class ColouredTextTerminal(override val width: Int, override val height: Int override var backColour = backDefault override var foreColour = foreDefault - override val fontRef = "./assets/graphics/fonts/CGA.png" + override val fontRef = "./assets/graphics/fonts/cp949.png" override val fontImg = Image(fontRef) override val fontW = fontImg.width / 16 override val fontH = fontImg.height / 16 override val font = ColouredFastFont(this, fontRef, fontW, fontH) - override val colourScreen = Color.black + override val colourScreen: Color = Color.black } \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt index 1c8d24c5a..019bfe545 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/SimpleTextTerminal.kt @@ -31,7 +31,8 @@ open class SimpleTextTerminal( Color(0xaa, 0xaa, 0xaa) // light grey ) // THESE ARE THE STANDARD - override val coloursCount = colours.size + override val coloursCount: Int + get() = colours.size open protected val backDefault = 0 // STANDARD open protected val foreDefault = 3 // STANDARD @@ -59,14 +60,11 @@ open class SimpleTextTerminal( private val TABSIZE = 4 - private val ASCII_NUL = 0.toChar() - private var cursorBlinkTimer = 0 private val cursorBlinkLen = 250 private var cursorBlinkOn = true - override fun getColor(index: Int): Color = colours[index] override fun update(gc: GameContainer, delta: Int) { @@ -177,21 +175,6 @@ open class SimpleTextTerminal( screenBuffer.drawBuffer(cursorX, cursorY, c.toInt().and(0xFF).toChar(), colourKey) } - val asciiControlInUse = charArrayOf( - ASCII_NUL, - ASCII_BEL, - ASCII_BS, - ASCII_TAB, - ASCII_LF, - ASCII_FF, - ASCII_CR, - ASCII_DEL, - ASCII_DC1, - ASCII_DC2, - ASCII_DC3, - ASCII_DC4 - ) - /** Prints a char and move cursor accordingly. */ override fun printChar(c: Char) { wrap() @@ -204,7 +187,7 @@ open class SimpleTextTerminal( ASCII_BEL -> beep() ASCII_BS -> { cursorX -= 1; wrap() } ASCII_TAB -> { cursorX = (cursorX).div(TABSIZE).times(TABSIZE) + TABSIZE } - ASCII_LF -> { cursorX = 0; cursorY += 1; wrap() } + ASCII_LF -> newLine() ASCII_FF -> clear() ASCII_CR -> { cursorX = 0 } ASCII_DEL -> { cursorX -= 1; wrap(); emitChar(colourKey.shl(8)) } @@ -213,14 +196,30 @@ open class SimpleTextTerminal( } } - /** Emits a string and move cursor accordingly. */ + /** (TTY): Prints a series of chars and move cursor accordingly, then LF + * (term): printString() on current cursor pos */ + override fun printChars(s: String) { + printString(s, cursorX, cursorY) + } + + /** (TTY): Prints a series of chars and move cursor accordingly + * (term): writeString() on current cursor pos */ + override fun writeChars(s: String) { + writeString(s, cursorX, cursorY) + } + + /** Emits a string and move cursor accordingly, then do LF */ override fun printString(s: String, x: Int, y: Int) { + writeString(s, x, y) + newLine() + } + + /** Emits a string and move cursor accordingly. */ + override fun writeString(s: String, x: Int, y: Int) { setCursor(x, y) emitString(s) val absCursorPos = cursorX + cursorY * width + s.length setCursor(absCursorPos % width, absCursorPos / width) - - printChar(ASCII_LF) } /** Emits a string. Does not move cursor */ @@ -245,7 +244,13 @@ open class SimpleTextTerminal( screenBuffer.drawBuffer(i, cursorY, 0.toChar(), colourKey) } + override fun newLine() { + cursorX = 0; cursorY += 1; wrap() + } + override fun scroll(amount: Int) { + if (amount < 0) throw IllegalArgumentException("cannot scroll up") + val offset = amount * width for (i in offset..screenBuffer.sizeof.ushr(1) - 1) { screenBuffer.frameBuffer[i - offset] = screenBuffer.frameBuffer[i] @@ -341,7 +346,7 @@ open class SimpleTextTerminal( } /** for "beep code" on modern BIOS. Pattern: - . */ - override fun beep(pattern: String) { + override fun bell(pattern: String) { throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. } @@ -390,6 +395,7 @@ open class SimpleTextTerminal( val ELECTRIC_BLUE = Color(0, 239, 255) // imaginary, 486 nm val RED = Color(250, 0, 0) // <= 645 nm + val ASCII_NUL = 0.toChar() val ASCII_BEL = 7.toChar() // *BEEP!* val ASCII_BS = 8.toChar() // x = x - 1 val ASCII_TAB = 9.toChar() // move cursor to next (TABSIZE * yy) pos (5 -> 8, 3- > 4, 4 -> 8) @@ -401,6 +407,21 @@ open class SimpleTextTerminal( val ASCII_DC2 = 18.toChar() // foreground colour 1 val ASCII_DC3 = 19.toChar() // foreground colour 2 val ASCII_DC4 = 20.toChar() // foreground colour 3 + + val asciiControlInUse = charArrayOf( + ASCII_NUL, + ASCII_BEL, + ASCII_BS, + ASCII_TAB, + ASCII_LF, + ASCII_FF, + ASCII_CR, + ASCII_DEL, + ASCII_DC1, + ASCII_DC2, + ASCII_DC3, + ASCII_DC4 + ) } private val DEBUG = true diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/Teletype.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/Teletype.kt new file mode 100644 index 000000000..5a651a7b7 --- /dev/null +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/Teletype.kt @@ -0,0 +1,38 @@ +package net.torvald.terrarum.virtualcomputer.terminal + +import org.newdawn.slick.GameContainer +import org.newdawn.slick.Graphics + +/** + * Created by minjaesong on 16-09-14. + */ +interface Teletype { + val width: Int + val displayW: Int + + var cursorX: Int + + /** + * 0: Teletype + * 4: Non-colour terminal (Note that '2' is invalid!) + * >4: Colour terminal + */ + val coloursCount: Int + + fun update(gc: GameContainer, delta: Int) + fun render(gc: GameContainer, g: Graphics) + fun keyPressed(key: Int, c: Char) + + /** Prints a char and move cursor accordingly */ + fun printChar(c: Char) + /** (TTY): Prints a series of chars and move cursor accordingly, then LF + * (term): printString() on current cursor pos */ + fun printChars(s: String) + /** (TTY): Prints a series of chars and move cursor accordingly + * (term): writeString() on current cursor pos */ + fun writeChars(s: String) + fun newLine() + fun scroll(amount: Int = 1) + + fun bell(pattern: String = ".") +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/TeletypeTerminal.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/TeletypeTerminal.kt new file mode 100644 index 000000000..e3de74ee4 --- /dev/null +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/TeletypeTerminal.kt @@ -0,0 +1,223 @@ +package net.torvald.terrarum.virtualcomputer.terminal + +import net.torvald.imagefont.GameFontBase +import net.torvald.terrarum.blendMul +import net.torvald.terrarum.blendNormal +import org.newdawn.slick.* +import java.util.* + +/** + * Created by minjaesong on 16-09-15. + */ +class TeletypeTerminal : Teletype { + override val width = 40 + override val displayW: Int + get() = width * font.W + /** + * 0: Teletype + * 4: Non-colour terminal (Note that '2' is invalid!) + * >4: Colour terminal + */ + override val coloursCount = 0 + + override var cursorX = 0 + + private val font = TTYFont() + + private var lineBuffer = StringBuilder() + + private var currentJob = 0 + private var currentJobStep = 0 + private var currentJobLen = 0 + private var currentJobQueue: Any? = null + // make sure certain jobs deliberately take long time by doing them one-by-one, for each frame. + private val JOB_IDLE = 0 + private val JOB_MOVEHEAD = 1 + private val JOB_PRINTCHAR = 2 + private val JOB_LINEFEED = 3 + + override fun update(gc: GameContainer, delta: Int) { + wrap() + + /*when (currentJob) { + JOB_PRINTCHAR -> { + printChar((currentJobQueue!! as String)[currentJobStep]) + currentJobStep += 1 + } + JOB_LINEFEED -> { + newLine() + currentJobStep += 1 + } + }*/ + + if (currentJobStep > currentJobLen) { + currentJob = JOB_IDLE + currentJobLen = 0 + currentJobStep = 0 + currentJobQueue = null + } + } + + override fun render(gc: GameContainer, g: Graphics) { + g.font = font + g.drawString(lineBuffer.toString(), 0f, 0f) + } + + val TABSIZE = 4 + + /** Prints a char and move cursor accordingly */ + override fun printChar(c: Char) { + wrap() + if (c >= ' ' && c.toInt() != 127) { + lineBuffer.append(c) + cursorX += 1 + } + else { + when (c) { + SimpleTextTerminal.ASCII_BEL -> bell() + SimpleTextTerminal.ASCII_BS -> { cursorX -= 1; wrap() } + SimpleTextTerminal.ASCII_TAB -> { cursorX = (cursorX).div(TABSIZE).times(TABSIZE) + TABSIZE } + SimpleTextTerminal.ASCII_LF -> newLine() + SimpleTextTerminal.ASCII_FF -> newLine() + SimpleTextTerminal.ASCII_CR -> { cursorX = 0 } + SimpleTextTerminal.ASCII_DEL -> { } // NOT supported, do nothing + SimpleTextTerminal.ASCII_DC1, SimpleTextTerminal.ASCII_DC2, SimpleTextTerminal.ASCII_DC3, SimpleTextTerminal.ASCII_DC4 + -> { } // NOT supported, do nothing + } + } + } + + /** (TTY): Prints a series of chars and move cursor accordingly + * (term): writeString() on current cursor pos */ + override fun writeChars(s: String) { + /*currentJob = JOB_PRINTCHAR + currentJobLen = s.length + currentJobQueue = s*/ + for (i in 0..s.length - 1) + printChar(s[i]) + } + + /** (TTY): Prints a series of chars and move cursor accordingly, then LF + * (term): writeString() on current cursor pos */ + override fun printChars(s: String) { + /*currentJob = JOB_PRINTCHAR + currentJobLen = s.length + 1 + currentJobQueue = "$s\n"*/ + writeChars("$s\n") + } + + override fun newLine() { + lineBuffer = StringBuilder() + } + + override fun scroll(amount: Int) { + if (amount < 0) throw IllegalArgumentException("cannot scroll up") + if (amount == 1) { newLine(); return } + + currentJob = JOB_LINEFEED + currentJobLen = amount + } + + override fun bell(pattern: String) { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + private fun wrap() { + if (cursorX < 0) cursorX = 0 + else if (cursorX >= width) newLine() + } + + var sb: StringBuilder = StringBuilder() + private var inputOpen = false + val DEBUG = true + + /** + * Technically, this is different from Java's InputStream + */ + fun openInput() { + inputOpen = true + if (DEBUG) println("[SimpleTextTerminal] openInput()") + } + + fun closeInput(): String { + inputOpen = false + val ret = sb.toString() + sb = StringBuilder() + + if (DEBUG) println("[SimpleTextTerminal] closeInput(), $ret") + return ret + } + + override fun keyPressed(key: Int, c: Char) { + if (inputOpen) { + if (c == SimpleTextTerminal.ASCII_CR) + printChar(SimpleTextTerminal.ASCII_LF) + else + printChar(c) + if (!SimpleTextTerminal.asciiControlInUse.contains(c)) sb.append(c) + else if (c == SimpleTextTerminal.ASCII_DEL && sb.length > 0) sb.deleteCharAt(sb.length - 1) + } + } + + class TTYFont : Font { + + internal val fontSheet: SpriteSheet + + internal val W = 9 + internal val H = 12 + + private val chars = arrayOf( + '0','1','2','3','4','5','6','7', + '8','9','[','#','@',':','>','?', + ' ','A','B','C','D','E','F','G', + 'H','I','&','.',']','(','<','\\', + '^','J','K','L','M','N','O','P', // ^: escape for capital letter + 'Q','R','-','¤','*',')',';','\'', + '+','/','S','T','U','V','W','X', + 'Y','Z','_',',','%','=','"','!' + ) + private val mappingTable = HashMap() + + init { + fontSheet = SpriteSheet("./assets/graphics/fonts/teletype_9x12.png", W, H) + chars.forEachIndexed { i, c -> mappingTable[c.toInt()] = i } + } + + override fun getHeight(str: String): Int = H + + override fun getWidth(str: String): Int { + var ret = 0 + for (i in 0..str.length - 1) + ret += W + return ret + } + + override fun getLineHeight(): Int = H + + override fun drawString(x: Float, y: Float, text: String) = drawString(x, y, text, Color.white) + + override fun drawString(x: Float, y: Float, text: String, col: Color) { + var thisCol = col + var textPosOffset = 0 + + for (i in 0..text.length - 1) { + val index = charToSpriteNum(text.toUpperCase().codePointAt(i)) + val ch = text[i] + + if (index != null) { + // main + fontSheet.getSubImage(index % 8, index / 8).draw( + x + textPosOffset, y, thisCol + ) + } + textPosOffset += W + } + } + + override fun drawString(x: Float, y: Float, text: String, col: Color, startIndex: Int, endIndex: Int) { + throw UnsupportedOperationException() + } + + private fun charToSpriteNum(ch: Int): Int? = mappingTable[ch] + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/Terminal.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/Terminal.kt index 85c58509d..6df4e4fde 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/Terminal.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/Terminal.kt @@ -6,19 +6,19 @@ import org.newdawn.slick.Graphics import org.newdawn.slick.Input /** - * A tty (terminal) + * A terminal * - * Framebuffer : use net.torvald.aa.AAFrame + * Framebuffer: USE net.torvald.aa.AAFrame * * Background color is fixed; text color is variable * * Created by minjaesong on 16-09-07. */ -interface Terminal { - val width: Int +interface Terminal : Teletype { + override val width: Int val height: Int - val coloursCount: Int - var cursorX: Int + override val coloursCount: Int + override var cursorX: Int var cursorY: Int var cursorBlink: Boolean var backColour: Int @@ -27,13 +27,13 @@ interface Terminal { var lastInputByte: Int // to be used in UI - val displayW: Int + override val displayW: Int val displayH: Int fun getColor(index: Int): Color - fun update(gc: GameContainer, delta: Int) - fun render(gc: GameContainer, g: Graphics) - fun keyPressed(key: Int, c: Char) + override fun update(gc: GameContainer, delta: Int) + override fun render(gc: GameContainer, g: Graphics) + override fun keyPressed(key: Int, c: Char) // API calls fun setCursor(x: Int, y: Int) @@ -44,14 +44,17 @@ interface Terminal { * It is also not affected by the control sequences; just print them out as symbol */ fun emitChar(c: Char) /** Prints a char and move cursor accordingly. */ - fun printChar(c: Char) + override fun printChar(c: Char) /** Emits a string. Does not move cursor */ fun emitString(s: String) - /** Emits a string and move cursor accordingly. */ + /** Emits a string and move cursor accordingly, then do LF */ fun printString(s: String, x: Int = cursorX, y: Int = cursorY) + /** Emits a string and move cursor accordingly. */ + fun writeString(s: String, x: Int = cursorX, y: Int = cursorY) fun clear() fun clearLine() - fun scroll(amount: Int = 1) + override fun newLine() + override fun scroll(amount: Int) fun setColour(back: Int, fore: Int) fun resetColour() /** @@ -60,7 +63,7 @@ interface Terminal { */ fun beep(freq: Float = 1000f, duration: Int = 200) /** for "beep code" on modern BIOS. Pattern: - . */ - fun beep(pattern: String) + override fun bell(pattern: String) /** Requires keyPressed() event to be processed. * * null indicates the input stream is waiting for an input diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalInputStream.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalInputStream.kt index 90a999192..24cc1d614 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalInputStream.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalInputStream.kt @@ -6,10 +6,8 @@ import java.io.InputStream /** * Created by minjaesong on 16-09-10. */ -class TerminalInputStream(val term: Terminal) : InputStream() { +class TerminalInputStream(val term: Teletype) : InputStream() { override fun read(): Int { - val ret = term.lastInputByte - term.lastInputByte = -1 - return ret + return -1 } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalPrintStream.kt b/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalPrintStream.kt index 67a1fe787..66d6c4045 100644 --- a/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalPrintStream.kt +++ b/src/net/torvald/terrarum/virtualcomputer/terminal/TerminalPrintStream.kt @@ -6,10 +6,10 @@ import java.io.PrintStream /** * Created by minjaesong on 16-09-10. */ -class TerminalPrintStream(val term: Terminal) : PrintStream(TerminalOutputStream(term)) { +class TerminalPrintStream(val term: Teletype) : PrintStream(TerminalOutputStream(term)) { } -class TerminalOutputStream(val term: Terminal) : OutputStream() { +class TerminalOutputStream(val term: Teletype) : OutputStream() { override fun write(b: Int) = term.printChar(b.and(0xFF).toChar()) } \ No newline at end of file