bunch of codes:

- Test InputStream() on VirtualComputer (blocking/unblocking using simple semaphore) -- no more dirty lua impl of io.read
- Typealias Kotlin 1.1
- Primitive box drawing on VideoCard
- Removing unnecessary fonts


Former-commit-id: cece88af3a3430678e685856eec78b4a9d598b4f
Former-commit-id: 22eed3a7beb9b4cb34636cbab2ff0e94989bdb31
This commit is contained in:
Song Minjae
2017-03-02 02:11:50 +09:00
parent 5bc3999237
commit 74250150de
33 changed files with 507 additions and 453 deletions

14
.idea/kotlinc.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Kotlin2JsCompilerArguments">
<option name="moduleKind" value="plain" />
</component>
<component name="Kotlin2JvmCompilerArguments">
<option name="jvmTarget" value="1.8" />
</component>
<component name="KotlinCommonCompilerArguments">
<option name="languageVersion" value="1.1" />
<option name="apiVersion" value="1.1" />
<option name="coroutinesWarn" value="true" />
</component>
</project>

View File

@@ -2,79 +2,40 @@
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Lua" name="Lua">
<configuration SdkName="Kahlua" />
<configuration SdkName="LuaJ" />
</facet>
<facet type="kotlin-language" name="Kotlin">
<configuration version="1">
<option name="compilerInfo">
<KotlinCompilerInfo>
<option name="compilerSettings">
<CompilerSettings>
<option name="additionalArguments" value="-version" />
<option name="copyJsLibraryFiles" value="true" />
<option name="outputDirectoryForJsLibraryFiles" value="lib" />
</CompilerSettings>
<CompilerSettings />
</option>
<option name="k2jsCompilerArguments">
<K2JSCompilerArguments>
<option name="outputFile" />
<option name="noStdlib" value="false" />
<option name="libraryFiles" />
<option name="sourceMap" value="false" />
<option name="metaInfo" value="false" />
<option name="kjsm" value="false" />
<option name="target" />
<option name="moduleKind" />
<option name="main" />
<option name="outputPrefix" />
<option name="outputPostfix" />
<option name="languageVersion" />
<option name="apiVersion" />
<option name="suppressWarnings" value="false" />
<option name="verbose" value="false" />
<option name="version" value="false" />
<option name="help" value="false" />
<option name="extraHelp" value="false" />
<option name="noInline" value="false" />
<option name="repeat" />
<option name="pluginClasspaths" />
<option name="pluginOptions" />
<option name="freeArgs">
<list />
</option>
<option name="unknownExtraFlags">
<list />
</option>
<option name="moduleKind" value="plain" />
</K2JSCompilerArguments>
</option>
<option name="k2jvmCompilerArguments">
<K2JVMCompilerArguments>
<option name="jvmTarget" value="1.6" />
</K2JVMCompilerArguments>
</option>
<option name="_commonCompilerArguments">
<DummyImpl>
<option name="languageVersion" />
<option name="apiVersion" />
<option name="suppressWarnings" value="false" />
<option name="verbose" value="false" />
<option name="version" value="false" />
<option name="help" value="false" />
<option name="extraHelp" value="false" />
<option name="noInline" value="false" />
<option name="repeat" />
<option name="pluginClasspaths" />
<option name="pluginOptions" />
<option name="freeArgs">
<list />
</option>
<option name="unknownExtraFlags">
<list />
</option>
<option name="languageVersion" value="1.1" />
<option name="apiVersion" value="1.1" />
<option name="coroutinesEnable" value="true" />
</DummyImpl>
</option>
</KotlinCompilerInfo>
</option>
<option name="useProjectSettings" value="false" />
<option name="versionInfo">
<KotlinVersionInfo>
<option name="apiLevel" value="1.0" />
<option name="languageLevel" value="1.0" />
<option name="targetPlatformName" value="JVM 1.6" />
<option name="apiLevel" value="1.1" />
<option name="languageLevel" value="1.1" />
<option name="targetPlatformName" value="JVM 1.8" />
</KotlinVersionInfo>
</option>
</configuration>

View File

@@ -1,102 +0,0 @@
package net.torvald.aa
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
import org.newdawn.slick.Color
import org.newdawn.slick.Font
import org.newdawn.slick.Image
import org.newdawn.slick.SpriteSheet
import java.util.*
/**
* Based on multisheet slick spritesheef font (net.torvald.imagefont.GameFontBase) of my game project.
* Again, based on my Ba-AA project (github.com/minjaesong/ba-aa)
*
* Created by minjaesong on 16-08-12.
* Adopted by minjaesong on 16-09-07.
*/
class ColouredFastFont(val vt: Terminal, fontRef: String, val fontW: Int, val fontH: Int) : Font {
val colouredSheet = ArrayList<SpriteSheet>() // index zero: dark grey
private var sheetW = 0
private var sheetH = 0
private lateinit var sheetImageBuffer: Image
init {
val getSizeImg = Image(fontRef)
sheetW = getSizeImg.width
sheetH = getSizeImg.height
getSizeImg.destroy()
sheetImageBuffer = Image(sheetW, sheetH)
for (i in 0..vt.coloursCount - 1) {
val sheet = SpriteSheet("$fontRef.$i.tga", fontW, fontH)
colouredSheet.add(sheet)
//sheetImageBuffer.graphics.clear()
}
sheetImageBuffer.destroy()
}
private fun getIndexX(ch: Char) = ch.toInt() % (sheetW / fontW)
private fun getIndexY(ch: Char) = ch.toInt() / (sheetW / fontW)
override fun getHeight(p0: String): Int = fontH
override fun getWidth(p0: String): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getLineHeight(): Int = fontH
override fun drawString(p0: Float, p1: Float, p2: String) {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun drawString(p0: Float, p1: Float, p2: String, p3: Color) {
//search colour
var colourIndex = -1
for (i in 0..vt.coloursCount - 1) {
if (vt.getColor(i) == p3) {
colourIndex = i
break
}
}
if (colourIndex >= 0) {
colouredSheet[colourIndex].startUse()
for (i in 0..p2.length - 1) {
val ch = p2[i]
colouredSheet[colourIndex].renderInUse(
p0.floorInt() + (i * fontW),
p1.floorInt(),
getIndexX(ch),
getIndexY(ch)
)
}
colouredSheet[colourIndex].endUse()
}
else {
//System.err.println("[ColouredFastFont] unmatched colour! $p3")
}
}
override fun drawString(p0: Float, p1: Float, p2: String, p3: Color, p4: Int, p5: Int) {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
fun Float.floorInt() = this.toInt()
}

View File

@@ -1,6 +0,0 @@
package net.torvald.terrarum
/**
* Created by minjaesong on 15-12-30.
*/
class GameConfig : KVHashMap()

View File

@@ -4,16 +4,15 @@ import com.google.gson.JsonPrimitive
import java.util.*
import java.util.function.Consumer
typealias ActorValue = KVHashMap
typealias GameConfig = KVHashMap
/**
* Created by minjaesong on 15-12-30.
*/
open class KVHashMap {
class KVHashMap {
private val hashMap: HashMap<String, Any>
init {
hashMap = HashMap<String, Any>()
}
private val hashMap = HashMap<String, Any>()
/**
* Add key-value pair to the configuration table.
@@ -104,7 +103,8 @@ open class KVHashMap {
get() = hashMap.keys
fun remove(key: String) {
hashMap.remove(key, hashMap[key])
if (hashMap[key] != null)
hashMap.remove(key, hashMap[key]!!)
}
}

View File

@@ -2,7 +2,7 @@ package net.torvald.terrarum
import net.torvald.random.HQRNG
import net.torvald.terrarum.gameactors.roundInt
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.peripheral.PeripheralVideoCard
import net.torvald.terrarum.virtualcomputer.terminal.GraphicsTerminal
import org.lwjgl.opengl.GL11
@@ -16,7 +16,7 @@ import java.util.*
* Created by SKYHi14 on 2017-02-23.
*/
class StateGraphicComputerTest : BasicGameState() {
val computer = BaseTerrarumComputer(8)
val computer = TerrarumComputer(8)
val monitor = GraphicsTerminal(computer)
init {
@@ -30,7 +30,8 @@ class StateGraphicComputerTest : BasicGameState() {
override fun init(container: GameContainer?, game: StateBasedGame?) {
val vcard = (computer.getPeripheral("ppu") as PeripheralVideoCard).vram
(0..3).forEach { vcard.sprites[it].setPaletteSet(64,33,12,62) }
// it's a-me, Mario!
/*(0..3).forEach { vcard.sprites[it].setPaletteSet(64,33,12,62) }
vcard.sprites[0].setAll(intArrayOf(
0,0,0,0,0,1,1,1,
@@ -71,46 +72,18 @@ class StateGraphicComputerTest : BasicGameState() {
0,1,1,1,0,0,0,0,
0,0,2,2,2,0,0,0,
0,0,2,2,2,2,0,0
))
))*/
}
var angle = 0.0
override fun update(container: GameContainer, game: StateBasedGame?, delta: Int) {
Terrarum.appgc.setTitle("VT — F: ${container.fps}" +
" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M")
" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M" +
" ${Random().nextInt(100)}")
monitor.update(container, delta)
computer.update(container, delta)
val vcard = (computer.getPeripheral("ppu") as PeripheralVideoCard)
val sprites = vcard.vram.sprites
angle += delta / 1000.0
(0..3).forEach { vcard.vram.sprites[it].setPaletteSet(64,26,12,62) }
sprites[0].posX = (Math.cos(angle) * 80 + 100).roundInt() - 8
sprites[0].posY = (Math.sin(angle) * 0 + 100).roundInt() - 8
sprites[1].posX = (Math.cos(angle) * 80 + 100).roundInt()
sprites[1].posY = (Math.sin(angle) * 0 + 100).roundInt() - 8
sprites[2].posX = (Math.cos(angle) * 80 + 100).roundInt() - 8
sprites[2].posY = (Math.sin(angle) * 0 + 100).roundInt()
sprites[3].posX = (Math.cos(angle) * 80 + 100).roundInt()
sprites[3].posY = (Math.sin(angle) * 0 + 100).roundInt()
//sprite.pal0 = (sprite.pal0 + 1) % 65
//sprite.pal1 = (sprite.pal1 + 1) % 65
//sprite.pal2 = (sprite.pal2 + 1) % 65
//sprite.pal3 = (sprite.pal3 + 1) % 65
//kotlin.repeat(256) {
//vcard.vram.setBackgroundPixel(Random().nextInt(320), Random().nextInt(200), Random().nextInt(64))
//vcard.vram.setBackgroundPixel(Random().nextInt(320), Random().nextInt(200), 15)
//}
}
override fun getID() = Terrarum.STATE_ID_TEST_TTY
@@ -118,4 +91,8 @@ class StateGraphicComputerTest : BasicGameState() {
override fun render(container: GameContainer, game: StateBasedGame?, g: Graphics) {
monitor.render(container, g)
}
override fun keyPressed(key: Int, c: Char) {
monitor.keyPressed(key, c)
}
}

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
import net.torvald.terrarum.virtualcomputer.terminal.Teletype
import net.torvald.terrarum.virtualcomputer.terminal.TeletypeTerminal
@@ -20,7 +20,7 @@ import org.newdawn.slick.state.StateBasedGame
class StateVTTest : BasicGameState() {
// HiRes: 100x64, LoRes: 80x25
val computerInside = BaseTerrarumComputer(8)
val computerInside = TerrarumComputer(8)
val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25,
computerInside, colour = false, hires = false)

View File

@@ -135,7 +135,7 @@ constructor(gamename: String) : StateBasedGame(gamename) {
gc.graphics.clear() // clean up any 'dust' in the buffer
//addState(StateVTTest())
//addState(StateGraphicComputerTest())
addState(StateGraphicComputerTest())
//addState(StateTestingLightning())
//addState(StateSplash())
//addState(StateMonitorCheck())

View File

@@ -55,7 +55,7 @@ internal object GetAV : ConsoleCommand {
Echo("$ccW== ActorValue list for $ccY$actor $ccW==")
println("[GetAV] == ActorValue list for '$actor' ==")
if (keyset.size == 0) {
if (keyset.isEmpty()) {
Echo("$ccK(nothing)")
println("[GetAV] (nothing)")
}
@@ -114,7 +114,7 @@ internal object GetAV : ConsoleCommand {
override fun printUsage() {
Echo("${ccW}Get desired ActorValue of specific target.")
Echo("${ccW}Usage: ${ccY}getav ${ccG}(id) <av>")
Echo("${ccW}Usage: ${ccY}getav $ccG(id) <av>")
Echo("${ccW}blank ID for player")
}
}

View File

@@ -1,16 +1,13 @@
package net.torvald.terrarum.debuggerapp
import net.torvald.terrarum.ActorValue
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.console.SetAV
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.Actor
import net.torvald.terrarum.gameactors.ActorValue
import net.torvald.terrarum.gameactors.ActorWithSprite
import net.torvald.terrarum.mapdrawer.FeaturesDrawer
import java.awt.BorderLayout
import java.awt.Color
import java.awt.Dimension
import java.awt.GridLayout
import java.awt.event.MouseEvent
import java.awt.event.MouseListener

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG
import net.torvald.terrarum.ActorValue
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.itemproperties.ItemCodex
import org.newdawn.slick.GameContainer

View File

@@ -1,8 +0,0 @@
package net.torvald.terrarum.gameactors
import net.torvald.terrarum.KVHashMap
/**
* Created by minjaesong on 16-03-19.
*/
class ActorValue : KVHashMap()

View File

@@ -354,9 +354,9 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
isNoSubjectToFluidResistance = isPlayerNoClip
}
/**
* Actual physics thing (altering velocity) starts from here
*/
////////////////////////////////////////////////////////////////
// Codes that modifies velocity (moveDelta and externalForce) //
////////////////////////////////////////////////////////////////
// Combine velo and walk
applyMovementVelocity()
@@ -376,6 +376,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
// Set 'next' position (hitbox) from canonical and walking velocity
setNewNextHitbox()
///////////////////////////////////////////////////////
// Codes that (SHOULD) displaces nextHitbox directly //
///////////////////////////////////////////////////////
/**
* solveCollision()?
* If and only if:
@@ -386,6 +390,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
applyNormalForce()
}
//////////////////////////////////////////////////////////////
// Codes that modifies velocity (after hitbox displacement) //
//////////////////////////////////////////////////////////////
if (!immobileBody) { // TODO test no friction on immobileBody
setHorizontalFriction()
}
@@ -395,6 +403,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
setVerticalFriction()
}
// some spacing //
// apply our compensation to actual hitbox
updateHitbox()

View File

@@ -4,6 +4,7 @@ import net.torvald.JsonFetcher
import net.torvald.random.Fudge3
import net.torvald.terrarum.langpack.Lang
import com.google.gson.JsonObject
import net.torvald.terrarum.ActorValue
import net.torvald.terrarum.gameactors.ActorHumanoid
import org.newdawn.slick.SlickException
import java.io.IOException

View File

@@ -4,6 +4,7 @@ import net.torvald.JsonFetcher
import net.torvald.terrarum.gameactors.faction.Faction
import net.torvald.spriteanimation.SpriteAnimation
import com.google.gson.JsonObject
import net.torvald.terrarum.ActorValue
import net.torvald.terrarum.gameactors.ActorHumanoid
import net.torvald.terrarum.gameactors.faction.FactionFactory
import net.torvald.terrarum.gameitem.EquipPosition

View File

@@ -47,10 +47,10 @@ class LuaAIWrapper(private val scriptPath: String) : ActorAI {
override fun update(delta: Int) {
// run "update()" function in the script
luag.get("update").call(delta.toLuaValue())
luag.get("update").call(delta.toLua())
}
var currentExecutionThread = Thread()
lateinit var currentExecutionThread: Thread
var threadRun = false
fun runCommand(reader: Reader, filename: String) {
@@ -109,5 +109,5 @@ class LuaAIWrapper(private val scriptPath: String) : ActorAI {
}
}
fun Int.toLuaValue(): LuaValue = LuaInteger.valueOf(this)
fun Int.toLua(): LuaValue = LuaInteger.valueOf(this)
}

View File

@@ -1045,7 +1045,7 @@ require("ROMLIB")
speaker.enqueue(80, computer.bellpitch) -- term.bell sometimes get squelched
-- load bios, if any
--if fs.exists(computer.bootloader) then fs.dofile(computer.bootloader) end
if fs.exists(computer.bootloader) then fs.dofile(computer.bootloader) end
-- halt/run luaprompt upon the termination of bios.
-- Valid BIOS should load OS and modify 'shell.status' to 'shell.halt' before terminating itself.

View File

@@ -6,7 +6,7 @@
-- ALIASES --
-------------
_G.io = {} -- we make our own sandbox'd system
--_G.io = {} -- we make our own sandbox'd system
--[[fs.dofile = function(p, ...)
local f = fs.open(p, "r")
@@ -51,7 +51,7 @@ _G.__scanforline__ = function(echo) -- pass '1' to not echo; pass nothing to ech
_G.__scanMode__ = "line"
local s
repeat -- we can do this ONLY IF lua execution process is SEPARATE THREAD
s = machine.getLastStreamInput()
s = machine.__readFromStdin()
until s
-- input is closed when RETURN is hit. See above comments.
return s
@@ -75,16 +75,16 @@ end]] -- DELETED: use _G.input.isKeyDown(keycode)
--- ---
input.readLine = _G.__scanforline__
--input.readLine = _G.__scanforline__
io.__openfile__ = "stdin"
--[[io.__openfile__ = "stdin"
io.stdin = "stdin"
io.stdout = "stdout"
io.stderr = "stderr"
io.open = fs.open
io.open = fs.open]]
io.input = function(luafile)
--[[io.input = function(luafile)
io.__openfile__ = luafile
end
@@ -105,13 +105,18 @@ io.read = function(option)
options["*n"] = function() error("Read number is not supported, yet!") end--_readNumber
options["*a"] = _readAll
options["*l"] = _readLine
end]]
io.read = function()
return string.char(machine.__readFromStdin())
end
-----------------
-- PRINTSTREAM --
-----------------
io.write = function(...)
-- only useful when IO is "opening" stdin
--[[io.write = function(...)
local args = {...}
for _, v in ipairs(args) do
local s
@@ -122,10 +127,10 @@ io.write = function(...)
end
term.write(s)
end
end
end]]
-- for some reason, inputstream above kills 'print' function.
-- So we rewrite it.
_G.print = function(...)
--[[_G.print = function(...) -- dependent on above io.write reimpl
local args = {...}
io.write(args[1])
@@ -138,7 +143,7 @@ _G.print = function(...)
end
io.write("\n")
end
end]]
---------------

View File

@@ -30,7 +30,7 @@ import java.util.*
* @param term : terminal that is connected to the computer fixtures, null if not connected any.
* Created by minjaesong on 16-09-10.
*/
class BaseTerrarumComputer(peripheralSlots: Int) {
class TerrarumComputer(peripheralSlots: Int) {
var maxPeripherals: Int = peripheralSlots
private set
@@ -42,11 +42,11 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
lateinit var luaJ_globals: Globals
private set
var termOut: PrintStream? = null
var stdout: PrintStream? = null
private set
var termErr: PrintStream? = null
var stderr: PrintStream? = null
private set
var termIn: InputStream? = null
var stdin: InputStream? = null
private set
val processorCycle: Int // number of Lua statement to process per tick (1/100 s)
@@ -76,6 +76,10 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
val peripheralTable = ArrayList<Peripheral>()
var stdinInput: Int = -1
private set
// os-related functions. These are called "machine" library-wise.
private val startupTimestamp: Long = System.currentTimeMillis()
/** Time elapsed since the power is on. */
@@ -119,7 +123,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
if (peripheralTable.size < maxPeripherals) {
peripheralTable.add(peri)
peri.loadLib(luaJ_globals)
println("[BaseTerrarumComputer] loading peripheral $peri")
println("[TerrarumComputer] loading peripheral $peri")
}
else {
throw Error("No vacant peripheral slot")
@@ -129,7 +133,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
fun detachPeripheral(peri: Peripheral) {
if (peripheralTable.contains(peri)) {
peripheralTable.remove(peri)
println("[BaseTerrarumComputer] unloading peripheral $peri")
println("[TerrarumComputer] unloading peripheral $peri")
}
else {
throw IllegalArgumentException("Peripheral not exists: $peri")
@@ -144,13 +148,13 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
fun initSandbox(term: Teletype) {
luaJ_globals = JsePlatform.debugGlobals()
termOut = TerminalPrintStream(term)
termErr = TerminalPrintStream(term)
termIn = TerminalInputStream(term)
stdout = TerminalPrintStream(this)
stderr = TerminalPrintStream(this)
stdin = TerminalInputStream(this)
luaJ_globals.STDOUT = termOut
luaJ_globals.STDERR = termErr
luaJ_globals.STDIN = termIn
luaJ_globals.STDOUT = stdout
luaJ_globals.STDERR = stderr
luaJ_globals.STDIN = stdin
luaJ_globals["bit"] = luaJ_globals["bit32"]
@@ -191,73 +195,80 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
}
}
var threadTimer = 0
val threadMaxTime = 2000
fun update(gc: GameContainer, delta: Int) {
input = gc.input
if (currentExecutionThread.state == Thread.State.TERMINATED)
unsetThreadRun()
// time the execution time of the thread
if (threadRun) {
threadTimer += delta
// if too long, halt
if (threadTimer > threadMaxTime) {
//luaJ_globals.STDERR.println("Interrupted: Too long without yielding.")
//currentExecutionThread.interrupt()
unsetThreadRun()
}
if (currentExecutionThread.state == Thread.State.TERMINATED) {
threadRun = false
}
if (!isHalted) {
driveBeepQueueManager(delta)
}
else {
currentExecutionThread.interrupt()
}
}
fun keyPressed(key: Int, c: Char) {
stdinInput = c.toInt()
System.err.println("TerrarumComputer.keyPressed got input: $stdinInput")
// wake thread
runnableRunCommand.resume()
synchronized(stdin!!) {
(stdin as java.lang.Object).notifyAll()
}
}
var currentExecutionThread = Thread()
var threadRun = false
fun openStdin() {
System.err.println("TerrarumComputer.openStdin")
stdinInput = -1
// sleep the thread
runnableRunCommand.pause()
}
lateinit var currentExecutionThread: Thread
private set
lateinit var runnableRunCommand: ThreadRunCommand
private set
private var threadRun = false
fun runCommand(line: String, env: String) {
if (!threadRun && !isHalted) {
currentExecutionThread = Thread(ThreadRunCommand(luaJ_globals, line, env))
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, line, env)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
fun runCommand(reader: Reader, filename: String) {
if (!threadRun && !isHalted) {
currentExecutionThread = Thread(ThreadRunCommand(luaJ_globals, reader, filename))
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, reader, filename)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
private fun unsetThreadRun() {
threadRun = false
threadTimer = 0
}
class ThreadRunCommand : Runnable {
val mode: Int
val arg1: Any
val arg2: String
val lua: Globals
private val mode: Int
private val arg1: Any
private val arg2: String
private val lua: Globals
@Volatile private var running = true
@Volatile private var paused = false
private val pauseLock = java.lang.Object()
constructor(luaInstance: Globals, line: String, env: String) {
mode = 0
@@ -274,6 +285,32 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
}
override fun run() {
synchronized(pauseLock) {
if (!running) { // may have changed while waiting to
// synchronize on pauseLock
return
}
if (paused) {
try {
pauseLock.wait() // will cause this Thread to block until
// another thread calls pauseLock.notifyAll()
// Note that calling wait() will
// relinquish the synchronized lock that this
// thread holds on pauseLock so another thread
// can acquire the lock to call notifyAll()
// (link with explanation below this code)
}
catch (ex: InterruptedException) {
return
}
if (!running) { // running might have changed since we paused
return
}
}
}
try {
val chunk: LuaValue
if (mode == 0)
@@ -291,15 +328,35 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
lua.STDERR.println("${SimpleTextTerminal.ASCII_DLE}${e.message}${SimpleTextTerminal.ASCII_DC4}")
}
}
fun stop() {
running = false
// you might also want to do this:
//interrupt()
}
fun pause() {
// you may want to throw an IllegalStateException if !running
paused = true
}
fun resume() {
synchronized(pauseLock) {
paused = false
pauseLock.notifyAll() // Unblocks thread
System.err.println("ThreadRunCommand resume()")
}
}
}
class LuaFunGetTotalMem(val computer: BaseTerrarumComputer) : ZeroArgFunction() {
class LuaFunGetTotalMem(val computer: TerrarumComputer) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.memSize)
}
}
class ComputerEmitTone(val computer: BaseTerrarumComputer) : TwoArgFunction() {
class ComputerEmitTone(val computer: TerrarumComputer) : TwoArgFunction() {
override fun call(millisec: LuaValue, freq: LuaValue): LuaValue {
computer.playTone(millisec.checkint(), freq.checkdouble())
return LuaValue.NONE
@@ -357,7 +414,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
//AL.destroy()
if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear")
if (DEBUG) println("[TerrarumComputer] !! Beep queue clear")
}
fun enqueueBeep(duration: Int, freq: Double) {

View File

@@ -5,7 +5,7 @@ import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
import java.io.*
import java.nio.file.Files
@@ -26,7 +26,7 @@ import java.util.*
* Don't convert '\' to '/'! Rev-slash is used for escape character in sh, and we're sh-compatible!
* Use .absoluteFile whenever possible; there's fuckin oddity! (http://bugs.java.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097)
*/
internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
internal class Filesystem(globals: Globals, computer: TerrarumComputer) {
init {
// load things. WARNING: THIS IS MANUAL!
@@ -101,7 +101,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
* directs media/ directory to /<uuid> directory
*/
fun BaseTerrarumComputer.getRealPath(luapath: LuaValue) : String {
fun TerrarumComputer.getRealPath(luapath: LuaValue) : String {
// direct mounted paths to real path
val computerDir = Terrarum.currentSaveDir.absolutePath + "/computers/"
/* if not begins with "(/?)media/", direct to boot
@@ -138,7 +138,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
*
* actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
*/
class ListFiles(val computer: BaseTerrarumComputer) : OneArgFunction() {
class ListFiles(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -155,7 +155,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
/** Don't use this. Use isFile */
class FileExists(val computer: BaseTerrarumComputer) : OneArgFunction() {
class FileExists(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -163,7 +163,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
}
class IsDirectory(val computer: BaseTerrarumComputer) : OneArgFunction() {
class IsDirectory(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -174,7 +174,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
}
class IsFile(val computer: BaseTerrarumComputer) : OneArgFunction() {
class IsFile(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -198,7 +198,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
}
class IsReadOnly(val computer: BaseTerrarumComputer) : OneArgFunction() {
class IsReadOnly(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -207,7 +207,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
/** we have 4GB file size limit */
class GetSize(val computer: BaseTerrarumComputer) : OneArgFunction() {
class GetSize(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -220,7 +220,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/**
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Mkdir(val computer: BaseTerrarumComputer) : OneArgFunction() {
class Mkdir(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -231,7 +231,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/**
* moves a directory, overwrites the target
*/
class Mv(val computer: BaseTerrarumComputer) : TwoArgFunction() {
class Mv(val computer: TerrarumComputer) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(from)
Filesystem.ensurePathSanity(to)
@@ -250,7 +250,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
* copies a directory, overwrites the target
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Cp(val computer: BaseTerrarumComputer) : TwoArgFunction() {
class Cp(val computer: TerrarumComputer) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(from)
Filesystem.ensurePathSanity(to)
@@ -266,7 +266,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/**
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Rm(val computer: BaseTerrarumComputer) : OneArgFunction() {
class Rm(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -276,7 +276,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
}
class ConcatPath(val computer: BaseTerrarumComputer) : TwoArgFunction() {
class ConcatPath(val computer: TerrarumComputer) : TwoArgFunction() {
override fun call(base: LuaValue, local: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(base)
Filesystem.ensurePathSanity(local)
@@ -312,7 +312,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
* writeBytes = function(string as bytearray)
* }
*/
class OpenFile(val computer: BaseTerrarumComputer) : TwoArgFunction() {
class OpenFile(val computer: TerrarumComputer) : TwoArgFunction() {
override fun call(path: LuaValue, mode: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)
@@ -387,7 +387,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
}
}
class GetParentDir(val computer: BaseTerrarumComputer) : OneArgFunction() {
class GetParentDir(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path)

View File

@@ -1,8 +1,9 @@
package net.torvald.terrarum.virtualcomputer.luaapi
import net.torvald.terrarum.gameactors.ai.toLua
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
import net.torvald.terrarum.virtualcomputer.terminal.Teletype
import org.luaj.vm2.*
@@ -14,22 +15,19 @@ import org.luaj.vm2.*
*
* Created by minjaesong on 16-09-19.
*/
internal class HostAccessProvider(globals: Globals, computer: BaseTerrarumComputer) {
internal class HostAccessProvider(globals: Globals, computer: TerrarumComputer) {
init {
globals["machine"] = LuaTable()
globals["machine"]["println"] = PrintLn()
globals["machine"]["isHalted"] = IsHalted(computer)
globals["machine"]["closeInputString"] = NativeCloseInputString(computer.term)
globals["machine"]["closeInputKey"] = NativeCloseInputKey(computer.term)
globals["machine"]["openInput"] = NativeOpenInput(computer.term)
globals["machine"]["getLastStreamInput"] = NativeGetLastStreamInput(computer.term)
globals["machine"]["getLastKeyPress"] = NativeGetLastKeyPress(computer.term)
globals["machine"]["__readFromStdin"] = NativeReadStdin(computer)
globals["machine"]["milliTime"] = NativeGetMilliTime(computer)
globals["machine"]["sleep"] = NativeBusySleep(computer)
globals["machine"]["sleep"] = NativeThreadSleep(computer)
globals["__haltsystemexplicit__"] = HaltComputer(computer)
}
@@ -44,53 +42,19 @@ internal class HostAccessProvider(globals: Globals, computer: BaseTerrarumComput
}
}
class IsHalted(val computer: BaseTerrarumComputer): ZeroArgFunction() {
class IsHalted(val computer: TerrarumComputer): ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.isHalted)
}
}
class NativeCloseInputString(val term: Teletype) : ZeroArgFunction() {
class NativeReadStdin(val computer: TerrarumComputer) : ZeroArgFunction() {
override fun call(): LuaValue {
term.closeInputString()
return LuaValue.NONE
return computer.stdin!!.read().toLua()
}
}
class NativeCloseInputKey(val term: Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
//term.closeInputKey()
return LuaValue.NONE
}
}
class NativeOpenInput(val term: Teletype) : LuaFunction() {
override fun call(): LuaValue {
term.openInput(true)
return LuaValue.NONE
}
override fun call(echo: LuaValue): LuaValue {
term.openInput(if (echo.checkint() == 1) false else true)
return LuaValue.NONE
}
}
class NativeGetLastStreamInput(val term: Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
return if (term.lastStreamInput == null) LuaValue.NIL
else LuaValue.valueOf(term.lastStreamInput)
}
}
class NativeGetLastKeyPress(val term: Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
return if (term.lastKeyPress == null) LuaValue.NIL
else LuaValue.valueOf(term.lastKeyPress!!)
}
}
class HaltComputer(val computer: BaseTerrarumComputer) : ZeroArgFunction() {
class HaltComputer(val computer: TerrarumComputer) : ZeroArgFunction() {
override fun call() : LuaValue {
computer.isHalted = true
computer.luaJ_globals.load("""print(DC4.."system halted")""").call()
@@ -99,18 +63,15 @@ internal class HostAccessProvider(globals: Globals, computer: BaseTerrarumComput
}
/** Time elapsed since the power is on. */
class NativeGetMilliTime(val computer: BaseTerrarumComputer) : ZeroArgFunction() {
class NativeGetMilliTime(val computer: TerrarumComputer) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.milliTime)
}
}
class NativeBusySleep(val computer: BaseTerrarumComputer) : OneArgFunction() {
class NativeThreadSleep(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(mills: LuaValue): LuaValue {
val starttime = computer.milliTime
val sleeptime = mills.checkint()
if (sleeptime > 1000) throw LuaError("Cannot busy-sleep more than a second.")
while (computer.milliTime - starttime < sleeptime) { }
computer.currentExecutionThread.join(mills.checklong())
return LuaValue.NONE
}
}

View File

@@ -5,12 +5,12 @@ import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
/**
* Created by minjaesong on 16-09-25.
*/
class Input(globals: Globals, computer: BaseTerrarumComputer) {
class Input(globals: Globals, computer: TerrarumComputer) {
init {
globals["input"] = LuaTable()
@@ -23,7 +23,7 @@ class Input(globals: Globals, computer: BaseTerrarumComputer) {
val keys_caps = intArrayOf(Key.CAPS_LOCK, Key.BACKSPACE, Key.L_CONTROL)
}
class IsKeyDown(val host: BaseTerrarumComputer) : OneArgFunction() {
class IsKeyDown(val host: TerrarumComputer) : OneArgFunction() {
override fun call(keyCode: LuaValue): LuaValue {
val key = keyCode.checkint()

View File

@@ -5,7 +5,7 @@ import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import org.luaj.vm2.LuaFunction
import org.luaj.vm2.lib.OneArgFunction
@@ -16,7 +16,7 @@ import org.luaj.vm2.lib.OneArgFunction
*
* Created by minjaesong on 16-09-27.
*/
class PcSpeakerDriver(val globals: Globals, host: BaseTerrarumComputer) {
class PcSpeakerDriver(val globals: Globals, host: TerrarumComputer) {
init {
globals["speaker"] = LuaTable()
@@ -67,7 +67,7 @@ class PcSpeakerDriver(val globals: Globals, host: BaseTerrarumComputer) {
}
}
class EnqueueTone(val host: BaseTerrarumComputer) : TwoArgFunction() {
class EnqueueTone(val host: TerrarumComputer) : TwoArgFunction() {
/**
* @param freq: number (hertz) or string (A-4, A4, B#2, ...)
*/
@@ -84,7 +84,7 @@ class PcSpeakerDriver(val globals: Globals, host: BaseTerrarumComputer) {
}
}
class ClearQueue(val host: BaseTerrarumComputer) : ZeroArgFunction() {
class ClearQueue(val host: TerrarumComputer) : ZeroArgFunction() {
override fun call(): LuaValue {
host.clearBeepQueue()
return LuaValue.NONE

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.virtualcomputer.peripheral
import org.luaj.vm2.Globals
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
@@ -14,7 +14,7 @@ import java.net.URL
*
* Created by minjaesong on 16-09-24.
*/
internal class PeripheralInternet(val host: BaseTerrarumComputer)
internal class PeripheralInternet(val host: TerrarumComputer)
: Peripheral("internet"){
override fun loadLib(globals: Globals) {

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.virtualcomputer.peripheral
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
@@ -11,7 +11,7 @@ import org.luaj.vm2.LuaValue
*
* Created by minjaesong on 16-09-27.
*/
internal class PeripheralPSG(val host: BaseTerrarumComputer)
internal class PeripheralPSG(val host: TerrarumComputer)
: Peripheral("psg") {
override fun loadLib(globals: Globals) {

View File

@@ -2,17 +2,10 @@ package net.torvald.terrarum.virtualcomputer.peripheral
import net.torvald.terrarum.gameactors.DecodeTapestry
import net.torvald.terrarum.gameactors.ai.toLua
import net.torvald.terrarum.getPixel
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.*
import org.luaj.vm2.lib.*
import org.luaj.vm2.lib.ThreeArgFunction
import org.luaj.vm2.lib.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import org.lwjgl.opengl.GL11
import org.newdawn.slick.*
import java.util.*
/**
* Created by SKYHi14 on 2017-02-08.
@@ -20,8 +13,8 @@ import java.util.*
class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
Peripheral("ppu") {
companion object {
val blockW = 8
val blockH = 8
val blockW = 8 // MUST BE 8
val blockH = 8 // MUST BE 8
/**
* Converts consecutive lua table indexed from 1 as IntArray.
@@ -51,7 +44,7 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
val frameBufferImage = frameBuffer.image
// hard-coded 8x8
var fontRom = Array<IntArray>(256, { Array<Int>(blockH, { 0 }).toIntArray() })
var fontRom = Array<IntArray>(256, { IntArray(blockH) })
init {
// build it for first time
@@ -61,10 +54,20 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
}
val CLUT = VRAM.CLUT
val coloursCount = CLUT.size
val colorsCount = CLUT.size
val luaSpriteTable = LuaTable()
var color = 15 // black
set(value) {
if (value >= colorsCount || value < 0) {
throw IllegalArgumentException("Unknown colour: $value")
}
else {
field = value
}
}
init {
fun composeSpriteObject(spriteIndex: Int) : LuaValue {
val sprite = vram.sprites[spriteIndex]
@@ -109,16 +112,29 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
override fun loadLib(globals: Globals) {
globals["ppu"] = LuaTable()
globals["ppu"]["setForeColor"] = SetForeColor(this)
globals["ppu"]["getForeColor"] = GetForeColor(this)
globals["ppu"]["setBackColor"] = SetBackColor(this)
globals["ppu"]["getBackColor"] = GetBackColor(this)
globals["ppu"]["setTextForeColor"] = SetTextForeColor(this)
globals["ppu"]["getTextForeColor"] = GetTextForeColor(this)
globals["ppu"]["setTextBackColor"] = SetTextBackColor(this)
globals["ppu"]["getTextBackColor"] = GetTextBackColor(this)
globals["ppu"]["setColor"] = SetDrawColor(this)
globals["ppu"]["getColor"] = GetDrawColor(this)
globals["ppu"]["emitChar"] = EmitChar(this)
globals["ppu"]["clearAll"] = ClearAll(this)
globals["ppu"]["clearBack"] = ClearBackground(this)
globals["ppu"]["clearFore"] = ClearForeground(this)
globals["ppu"]["getSpritesCount"] = GetSpritesCount(this)
globals["ppu"]["getWidth"] = GetWidth(this)
globals["ppu"]["getHeight"] = GetHeight(this)
globals["ppu"]["getSprite"] = GetSprite(this)
globals["ppu"]["drawRectBack"] = DrawRectBack(this)
globals["ppu"]["drawRectFore"] = DrawRectFore(this)
globals["ppu"]["fillRectBack"] = FillRectBack(this)
globals["ppu"]["fillRectFore"] = FillRectFore(this)
globals["ppu"]["drawString"] = DrawString(this)
}
private val spriteBuffer = ImageBuffer(VSprite.width, VSprite.height)
@@ -171,44 +187,23 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
img.destroy()
}
fun ImageBuffer.softwareRender(other: ImageBuffer, posX: Int, posY: Int) {
for (y in 0..other.height - 1) {
for (x in 0..other.width - 1) {
val ix = posX + x
val iy = posY + y
if (ix >= 0 && iy >= 0 && ix < this.width && iy < this.height) {
if (other.rgba[4 * (y * other.width + x) + 3] != 0.toByte()) { // if not transparent
this.rgba[4 * (iy * this.texWidth + ix) + 0] = other.rgba[4 * (y * other.texWidth + x) + 0]
this.rgba[4 * (iy * this.texWidth + ix) + 1] = other.rgba[4 * (y * other.texWidth + x) + 1]
this.rgba[4 * (iy * this.texWidth + ix) + 2] = other.rgba[4 * (y * other.texWidth + x) + 2]
this.rgba[4 * (iy * this.texWidth + ix) + 3] = other.rgba[4 * (y * other.texWidth + x) + 3]
}
}
}
}
}
private var textColorFore = 49 // white
private var textColorBack = 64 // transparent
private var foreColor = 49 // white
private var backColor = 64 // transparent
fun drawChar(c: Char, x: Int, y: Int, colFore: Int = foreColor, colBack: Int = backColor) {
fun drawChar(c: Char, x: Int, y: Int, colFore: Int = textColorFore, colBack: Int = textColorBack) {
val glyph = fontRom[c.toInt()]
val fore = CLUT[colFore]
val back = CLUT[colBack]
// software render
for (gy in 0..blockH - 1) {
for (gx in 0..blockW - 1) {
val glyAlpha = glyph[gy].ushr(gx).and(1)
for (gy in 0..blockH - 1) { for (gx in 0..blockW - 1) {
val glyAlpha = glyph[gy] and (1 shl gx)
if (glyAlpha != 0) {
vram.foreground.setRGBA(x * blockW + gx, y * blockH + gy, fore.red, fore.green, fore.blue, fore.alpha)
}
else {
vram.foreground.setRGBA(x * blockW + gx, y * blockH + gy, back.red, back.green, back.blue, back.alpha)
}
if (glyAlpha != 0) {
vram.setForegroundPixel(x + gx, y + gy, colFore)
}
}
else {
vram.setForegroundPixel(x + gx, y + gy, colBack)
}
}}
}
@@ -231,9 +226,61 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
}
}
fun drawRectBack(x: Int, y: Int, w: Int, h: Int, c: Int = color) {
(0..w - 1).forEach {
vram.setBackgroundPixel(x + it, y, c)
vram.setBackgroundPixel(x + it, y + h - 1, c)
}
(1..h - 2).forEach {
vram.setBackgroundPixel(x, y + it, c)
vram.setBackgroundPixel(x + w - 1, y + it, c)
}
}
fun fillRectBack(x: Int, y: Int, w: Int, h: Int, c: Int = color) {
for (py in 0..h - 1) { for (px in 0..w - 1) {
vram.setBackgroundPixel(x + px, y + py, c)
}}
}
fun drawRectFore(x: Int, y: Int, w: Int, h: Int, c: Int = color) {
(0..w - 1).forEach {
vram.setForegroundPixel(x + it, y, c)
vram.setForegroundPixel(x + it, y + h - 1, c)
}
(1..h - 2).forEach {
vram.setForegroundPixel(x, y + it, c)
vram.setForegroundPixel(x + w - 1, y + it, c)
}
}
fun fillRectFore(x: Int, y: Int, w: Int, h: Int, c: Int = color) {
for (py in 0..h - 1) { for (px in 0..w - 1) {
vram.setForegroundPixel(x + px, y + py, c)
}}
}
fun getSprite(index: Int) = vram.sprites[index]
private fun ImageBuffer.softwareRender(other: ImageBuffer, posX: Int, posY: Int) {
for (y in 0..other.height - 1) {
for (x in 0..other.width - 1) {
val ix = posX + x
val iy = posY + y
if (ix >= 0 && iy >= 0 && ix < this.width && iy < this.height) {
if (other.rgba[4 * (y * other.texWidth + x) + 3] != 0.toByte()) { // if not transparent
this.rgba[4 * (iy * this.texWidth + ix) + 0] = other.rgba[4 * (y * other.texWidth + x) + 0]
this.rgba[4 * (iy * this.texWidth + ix) + 1] = other.rgba[4 * (y * other.texWidth + x) + 1]
this.rgba[4 * (iy * this.texWidth + ix) + 2] = other.rgba[4 * (y * other.texWidth + x) + 2]
this.rgba[4 * (iy * this.texWidth + ix) + 3] = other.rgba[4 * (y * other.texWidth + x) + 3]
}
}
}
}
}
/**
* Array be like, in binary; notice that glyphs are flipped horizontally:
* ...
@@ -268,27 +315,51 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
buildFontRom("./assets/graphics/fonts/milky.tga")
}
///////////////////
// Lua functions //
///////////////////
class SetForeColor(val videoCard: PeripheralVideoCard) : OneArgFunction() {
class SetTextForeColor(val videoCard: PeripheralVideoCard) : OneArgFunction() {
override fun call(arg: LuaValue): LuaValue {
videoCard.foreColor = arg.checkint()
videoCard.textColorFore = arg.checkint()
return LuaValue.NONE
}
}
class GetForeColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
class GetTextForeColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue {
return videoCard.foreColor.toLua()
return videoCard.textColorFore.toLua()
}
}
class SetBackColor(val videoCard: PeripheralVideoCard) : OneArgFunction() {
class SetTextBackColor(val videoCard: PeripheralVideoCard) : OneArgFunction() {
override fun call(arg: LuaValue): LuaValue {
videoCard.backColor = arg.checkint()
videoCard.textColorBack = arg.checkint()
return LuaValue.NONE
}
}
class GetBackColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
class GetTextBackColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue {
return videoCard.backColor.toLua()
return videoCard.textColorBack.toLua()
}
}
class SetDrawColor(val videoCard: PeripheralVideoCard) : OneArgFunction() {
override fun call(arg: LuaValue): LuaValue {
videoCard.color = arg.checkint()
return LuaValue.NONE
}
}
class GetDrawColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue {
return videoCard.color.toLua()
}
}
class GetWidth(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue {
return videoCard.width.toLua()
}
}
class GetHeight(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue {
return videoCard.height.toLua()
}
}
class EmitChar(val videoCard: PeripheralVideoCard) : ThreeArgFunction() {
@@ -326,6 +397,41 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
return videoCard.luaSpriteTable[arg.checkint() - 1]
}
}
class DrawRectBack(val videoCard: PeripheralVideoCard) : FourArgFunction() {
override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue, arg4: LuaValue): LuaValue {
videoCard.drawRectBack(arg1.checkint(), arg2.checkint(), arg3.checkint(), arg4.checkint())
return LuaValue.NONE
}
}
class FillRectBack(val videoCard: PeripheralVideoCard) : FourArgFunction() {
override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue, arg4: LuaValue): LuaValue {
videoCard.fillRectBack(arg1.checkint(), arg2.checkint(), arg3.checkint(), arg4.checkint())
return LuaValue.NONE
}
}
class DrawRectFore(val videoCard: PeripheralVideoCard) : FourArgFunction() {
override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue, arg4: LuaValue): LuaValue {
videoCard.drawRectFore(arg1.checkint(), arg2.checkint(), arg3.checkint(), arg4.checkint())
return LuaValue.NONE
}
}
class FillRectFore(val videoCard: PeripheralVideoCard) : FourArgFunction() {
override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue, arg4: LuaValue): LuaValue {
videoCard.fillRectFore(arg1.checkint(), arg2.checkint(), arg3.checkint(), arg4.checkint())
return LuaValue.NONE
}
}
class DrawString(val videoCard: PeripheralVideoCard) : ThreeArgFunction() {
override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue): LuaValue {
val str = arg1.checkjstring()
val x = arg2.checkint()
val y = arg3.checkint()
str.forEachIndexed { i, c ->
videoCard.drawChar(c, x + blockW * i, y)
}
return LuaValue.NONE
}
}
/////////////
// Sprites //
@@ -404,7 +510,7 @@ class VRAM(pxlWidth: Int, pxlHeight: Int, nSprites: Int) {
fun setForegroundPixel(x: Int, y: Int, color: Int) {
val col = CLUT[color]
background.setRGBA(x, y, col.red, col.green, col.blue, col.alpha)
foreground.setRGBA(x, y, col.red, col.green, col.blue, col.alpha)
}
}
@@ -468,3 +574,26 @@ class VSprite {
}
}
}
abstract class FourArgFunction : LibFunction() {
abstract override fun call(arg1: LuaValue, arg2: LuaValue, arg3: LuaValue, arg4: LuaValue): LuaValue
override fun call(): LuaValue {
return call(LuaValue.NIL, LuaValue.NIL, LuaValue.NIL, LuaValue.NIL)
}
override fun call(arg: LuaValue): LuaValue {
return call(arg, LuaValue.NIL, LuaValue.NIL, LuaValue.NIL)
}
override fun call(arg1: LuaValue, arg2: LuaValue): LuaValue {
return call(arg1, arg2, LuaValue.NIL, LuaValue.NIL)
}
override fun invoke(varargs: Varargs): Varargs {
return call(varargs.arg1(), varargs.arg(2), varargs.arg(3), varargs.arg(4))
}
}

View File

@@ -2,7 +2,9 @@ package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.terrarum.blendMul
import net.torvald.terrarum.gameactors.DecodeTapestry
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.gameactors.abs
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.peripheral.PeripheralVideoCard
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
@@ -15,12 +17,12 @@ import org.newdawn.slick.Image
*
* Created by SKYHi14 on 2017-02-08.
*/
class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
class GraphicsTerminal(private val host: TerrarumComputer) : Terminal {
lateinit var videoCard: PeripheralVideoCard
override val width: Int; get() = videoCard.termW
override val height: Int; get() = videoCard.termH
override val coloursCount: Int; get() = videoCard.coloursCount
override val coloursCount: Int; get() = videoCard.colorsCount
override var cursorX = 0
override var cursorY = 0
override var cursorBlink = true
@@ -78,7 +80,7 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
}
override fun keyPressed(key: Int, c: Char) {
//TODO("not implemented")
host.keyPressed(key, c)
}
override fun writeChars(s: String) {
@@ -97,7 +99,9 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
override fun emitChar(bufferChar: Int, x: Int, y: Int) {
videoCard.drawChar(
bufferChar.and(0xFF).toChar(), x, y,
bufferChar.and(0xFF).toChar(),
x * PeripheralVideoCard.blockW,
y * PeripheralVideoCard.blockH,
CLUT16_TO_64[bufferChar.ushr(8).and(0xF)],
CLUT16_TO_64[bufferChar.ushr(12).and(0xF)]
)
@@ -117,7 +121,12 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
override var lastKeyPress: Int? = null
override fun emitChar(c: Char, x: Int, y: Int) {
videoCard.drawChar(c, x, y, CLUT16_TO_64[foreColour])
videoCard.drawChar(
c,
x * PeripheralVideoCard.blockW,
y * PeripheralVideoCard.blockH,
CLUT16_TO_64[foreColour]
)
}
override fun printChar(c: Char) {
@@ -167,7 +176,7 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
}
override fun clear() {
videoCard.clearAll()
videoCard.clearForeground()
}
override fun clearLine() {
@@ -175,11 +184,28 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
}
override fun newLine() {
//TODO("not implemented")
cursorX = 0; cursorY += 1; wrap()
}
override fun scroll(amount: Int) {
//TODO("not implemented")
val rgba = videoCard.vram.foreground.rgba
val displacement = amount.abs() * PeripheralVideoCard.blockH * videoCard.vram.foreground.texWidth * 4
if (amount >= 0) {
System.arraycopy(
rgba, displacement,
rgba, 0,
rgba.size - displacement
)
(rgba.size - 1 downTo rgba.size - displacement + 1).forEach { rgba[it] = 0.toByte() }
}
else {
System.arraycopy(
rgba, 0,
rgba, displacement,
rgba.size - displacement
)
(0..displacement - 1).forEach { rgba[it] = 0.toByte() }
}
}
/**

View File

@@ -1,12 +1,11 @@
package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.aa.AAFrame
import net.torvald.aa.ColouredFastFont
import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.DecodeTapestry
import net.torvald.terrarum.gameactors.abs
import net.torvald.terrarum.gamecontroller.Key
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import org.lwjgl.BufferUtils
import org.lwjgl.openal.AL
import org.lwjgl.openal.AL10
@@ -21,7 +20,7 @@ import java.util.*
* Created by minjaesong on 16-09-07.
*/
open class SimpleTextTerminal(
phosphorColour: Color, override val width: Int, override val height: Int, private val host: BaseTerrarumComputer,
phosphorColour: Color, override val width: Int, override val height: Int, private val host: TerrarumComputer,
colour: Boolean = false, hires: Boolean = false
) : Terminal {
@@ -64,7 +63,7 @@ open class SimpleTextTerminal(
open protected val fontImg = Image(fontRef)
open val fontW = fontImg.width / 16
open val fontH = fontImg.height / 16
open protected val font = ColouredFastFont(this, fontRef, fontW, fontH)
open protected val font = SpriteSheetFont(SpriteSheet(fontRef, fontW, fontH), 0.toChar())
val borderSize = 20
override val displayW = fontW * width + 2 * borderSize

View File

@@ -1,13 +1,42 @@
package net.torvald.terrarum.virtualcomputer.terminal
import org.lwjgl.input.Keyboard
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import java.io.InputStream
/**
* Created by minjaesong on 16-09-10.
*/
class TerminalInputStream(val term: Teletype) : InputStream() {
class TerminalInputStream(val host: TerrarumComputer) : InputStream() {
private val pauseLock = java.lang.Object()
override fun read(): Int {
return -1
System.err.println("TerminalInputStream.read called")
//System.err.println(Thread.currentThread().name)
// would display "LuaJ Separated", which means this InputStream will not block main thread
host.openStdin()
synchronized(this) {
(this as java.lang.Object).wait()
}
System.err.println("TerminalInputStream.read exit")
return host.stdinInput
}
override fun read(b: ByteArray?): Int {
TODO()
}
override fun read(b: ByteArray?, off: Int, len: Int): Int {
TODO()
}
}

View File

@@ -1,15 +1,14 @@
package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import java.io.OutputStream
import java.io.PrintStream
/**
* Created by minjaesong on 16-09-10.
*/
class TerminalPrintStream(val term: Teletype) : PrintStream(TerminalOutputStream(term)) {
class TerminalPrintStream(val host: TerrarumComputer) : PrintStream(TerminalOutputStream(host))
}
class TerminalOutputStream(val term: Teletype) : OutputStream() {
override fun write(b: Int) = term.printChar(b.and(0xFF).toChar())
class TerminalOutputStream(val host: TerrarumComputer) : OutputStream() {
override fun write(b: Int) = host.term.printChar(b.and(0xFF).toChar())
}

View File

@@ -2,7 +2,7 @@ package net.torvald.terrarum.virtualcomputer.worldobject
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameactors.FixtureBase
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
import net.torvald.terrarum.virtualcomputer.worldobject.ui.UITextTerminal
@@ -14,7 +14,7 @@ import java.util.*
*/
class FixtureBasicTerminal(phosphor: Color) : FixtureBase() {
val computer = BaseTerrarumComputer(8)
val computer = TerrarumComputer(8)
val vt: Terminal = SimpleTextTerminal(phosphor, 80, 25, computer)
val ui = UITextTerminal(vt)

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.virtualcomputer.worldobject
import net.torvald.terrarum.gameactors.FixtureBase
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
import org.newdawn.slick.GameContainer
@@ -17,7 +17,7 @@ open class FixtureComputerBase() : FixtureBase() {
/** Connected terminal */
var terminal: FixtureBasicTerminal? = null
var computerInside: BaseTerrarumComputer? = null
var computerInside: TerrarumComputer? = null
init {
// UUID of the "brain"
@@ -33,7 +33,7 @@ open class FixtureComputerBase() : FixtureBase() {
fun attachTerminal(uuid: String) {
val fetchedTerminal = getTerminalByUUID(uuid)
computerInside = BaseTerrarumComputer(8)
computerInside = TerrarumComputer(8)
computerInside!!.attachTerminal(fetchedTerminal!!)
actorValue["computerid"] = computerInside!!.UUID
}

1
work_files/UI/.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.{psd,tga,ogg} filter=lfs diff=lfs merge=lfs -text