more work on the Terminal, ComputerCraft compatibility layer (wip), quarried stone texture
Former-commit-id: 1fd1b5ce05663dd41d6077077b64e08ac0f1b5a0 Former-commit-id: bd52729417fc4dfcd8ad11f00d34507943156a83
BIN
assets/graphics/fonts/cp949.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.0.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.1.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/graphics/fonts/cp949.png.10.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/graphics/fonts/cp949.png.11.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.12.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.13.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.14.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.15.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/graphics/fonts/cp949.png.2.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.3.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/graphics/fonts/cp949.png.4.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.5.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/graphics/fonts/cp949.png.6.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.7.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.8.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/cp949.png.9.png
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
assets/graphics/fonts/teletype_9x12.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 353 KiB |
BIN
lib/natives/아카이브.zip
Normal file
@@ -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<Int, Int>()
|
||||
private val mappingTable = HashMap<Int, Int>()*/
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
168
src/net/torvald/terrarum/virtualcomputer/assets/lua/CCAPI.lua
Normal file
@@ -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
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ".")
|
||||
}
|
||||
@@ -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<Int, Int>()
|
||||
|
||||
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]
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||