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 bdba27d776
commit 96c6cb2cc6
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"> <module type="JAVA_MODULE" version="4">
<component name="FacetManager"> <component name="FacetManager">
<facet type="Lua" name="Lua"> <facet type="Lua" name="Lua">
<configuration SdkName="Kahlua" /> <configuration SdkName="LuaJ" />
</facet> </facet>
<facet type="kotlin-language" name="Kotlin"> <facet type="kotlin-language" name="Kotlin">
<configuration version="1"> <configuration version="1">
<option name="compilerInfo"> <option name="compilerInfo">
<KotlinCompilerInfo> <KotlinCompilerInfo>
<option name="compilerSettings"> <option name="compilerSettings">
<CompilerSettings> <CompilerSettings />
<option name="additionalArguments" value="-version" />
<option name="copyJsLibraryFiles" value="true" />
<option name="outputDirectoryForJsLibraryFiles" value="lib" />
</CompilerSettings>
</option> </option>
<option name="k2jsCompilerArguments"> <option name="k2jsCompilerArguments">
<K2JSCompilerArguments> <K2JSCompilerArguments>
<option name="outputFile" /> <option name="moduleKind" value="plain" />
<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>
</K2JSCompilerArguments> </K2JSCompilerArguments>
</option> </option>
<option name="k2jvmCompilerArguments">
<K2JVMCompilerArguments>
<option name="jvmTarget" value="1.6" />
</K2JVMCompilerArguments>
</option>
<option name="_commonCompilerArguments"> <option name="_commonCompilerArguments">
<DummyImpl> <DummyImpl>
<option name="languageVersion" /> <option name="languageVersion" value="1.1" />
<option name="apiVersion" /> <option name="apiVersion" value="1.1" />
<option name="suppressWarnings" value="false" /> <option name="coroutinesEnable" value="true" />
<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>
</DummyImpl> </DummyImpl>
</option> </option>
</KotlinCompilerInfo> </KotlinCompilerInfo>
</option> </option>
<option name="useProjectSettings" value="false" />
<option name="versionInfo"> <option name="versionInfo">
<KotlinVersionInfo> <KotlinVersionInfo>
<option name="apiLevel" value="1.0" /> <option name="apiLevel" value="1.1" />
<option name="languageLevel" value="1.0" /> <option name="languageLevel" value="1.1" />
<option name="targetPlatformName" value="JVM 1.6" /> <option name="targetPlatformName" value="JVM 1.8" />
</KotlinVersionInfo> </KotlinVersionInfo>
</option> </option>
</configuration> </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.*
import java.util.function.Consumer import java.util.function.Consumer
typealias ActorValue = KVHashMap
typealias GameConfig = KVHashMap
/** /**
* Created by minjaesong on 15-12-30. * Created by minjaesong on 15-12-30.
*/ */
open class KVHashMap { class KVHashMap {
private val hashMap: HashMap<String, Any> private val hashMap = HashMap<String, Any>()
init {
hashMap = HashMap<String, Any>()
}
/** /**
* Add key-value pair to the configuration table. * Add key-value pair to the configuration table.
@@ -104,7 +103,8 @@ open class KVHashMap {
get() = hashMap.keys get() = hashMap.keys
fun remove(key: String) { 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.random.HQRNG
import net.torvald.terrarum.gameactors.roundInt 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.peripheral.PeripheralVideoCard
import net.torvald.terrarum.virtualcomputer.terminal.GraphicsTerminal import net.torvald.terrarum.virtualcomputer.terminal.GraphicsTerminal
import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11
@@ -16,7 +16,7 @@ import java.util.*
* Created by SKYHi14 on 2017-02-23. * Created by SKYHi14 on 2017-02-23.
*/ */
class StateGraphicComputerTest : BasicGameState() { class StateGraphicComputerTest : BasicGameState() {
val computer = BaseTerrarumComputer(8) val computer = TerrarumComputer(8)
val monitor = GraphicsTerminal(computer) val monitor = GraphicsTerminal(computer)
init { init {
@@ -30,7 +30,8 @@ class StateGraphicComputerTest : BasicGameState() {
override fun init(container: GameContainer?, game: StateBasedGame?) { override fun init(container: GameContainer?, game: StateBasedGame?) {
val vcard = (computer.getPeripheral("ppu") as PeripheralVideoCard).vram 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( vcard.sprites[0].setAll(intArrayOf(
0,0,0,0,0,1,1,1, 0,0,0,0,0,1,1,1,
@@ -71,46 +72,18 @@ class StateGraphicComputerTest : BasicGameState() {
0,1,1,1,0,0,0,0, 0,1,1,1,0,0,0,0,
0,0,2,2,2,0,0,0, 0,0,2,2,2,0,0,0,
0,0,2,2,2,2,0,0 0,0,2,2,2,2,0,0
)) ))*/
} }
var angle = 0.0
override fun update(container: GameContainer, game: StateBasedGame?, delta: Int) { override fun update(container: GameContainer, game: StateBasedGame?, delta: Int) {
Terrarum.appgc.setTitle("VT — F: ${container.fps}" + 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) monitor.update(container, delta)
computer.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 override fun getID() = Terrarum.STATE_ID_TEST_TTY
@@ -118,4 +91,8 @@ class StateGraphicComputerTest : BasicGameState() {
override fun render(container: GameContainer, game: StateBasedGame?, g: Graphics) { override fun render(container: GameContainer, game: StateBasedGame?, g: Graphics) {
monitor.render(container, g) 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 package net.torvald.terrarum
import net.torvald.terrarum.gamecontroller.Key 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.SimpleTextTerminal
import net.torvald.terrarum.virtualcomputer.terminal.Teletype import net.torvald.terrarum.virtualcomputer.terminal.Teletype
import net.torvald.terrarum.virtualcomputer.terminal.TeletypeTerminal import net.torvald.terrarum.virtualcomputer.terminal.TeletypeTerminal
@@ -20,7 +20,7 @@ import org.newdawn.slick.state.StateBasedGame
class StateVTTest : BasicGameState() { class StateVTTest : BasicGameState() {
// HiRes: 100x64, LoRes: 80x25 // HiRes: 100x64, LoRes: 80x25
val computerInside = BaseTerrarumComputer(8) val computerInside = TerrarumComputer(8)
val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25, val vt = SimpleTextTerminal(SimpleTextTerminal.AMETHYST_NOVELTY, 80, 25,
computerInside, colour = false, hires = false) 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 gc.graphics.clear() // clean up any 'dust' in the buffer
//addState(StateVTTest()) //addState(StateVTTest())
//addState(StateGraphicComputerTest()) addState(StateGraphicComputerTest())
//addState(StateTestingLightning()) //addState(StateTestingLightning())
//addState(StateSplash()) //addState(StateSplash())
//addState(StateMonitorCheck()) //addState(StateMonitorCheck())

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.gameactors package net.torvald.terrarum.gameactors
import net.torvald.random.HQRNG import net.torvald.random.HQRNG
import net.torvald.terrarum.ActorValue
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.itemproperties.ItemCodex import net.torvald.terrarum.itemproperties.ItemCodex
import org.newdawn.slick.GameContainer 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 isNoSubjectToFluidResistance = isPlayerNoClip
} }
/** ////////////////////////////////////////////////////////////////
* Actual physics thing (altering velocity) starts from here // Codes that modifies velocity (moveDelta and externalForce) //
*/ ////////////////////////////////////////////////////////////////
// Combine velo and walk // Combine velo and walk
applyMovementVelocity() applyMovementVelocity()
@@ -376,6 +376,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
// Set 'next' position (hitbox) from canonical and walking velocity // Set 'next' position (hitbox) from canonical and walking velocity
setNewNextHitbox() setNewNextHitbox()
///////////////////////////////////////////////////////
// Codes that (SHOULD) displaces nextHitbox directly //
///////////////////////////////////////////////////////
/** /**
* solveCollision()? * solveCollision()?
* If and only if: * If and only if:
@@ -386,6 +390,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
applyNormalForce() applyNormalForce()
} }
//////////////////////////////////////////////////////////////
// Codes that modifies velocity (after hitbox displacement) //
//////////////////////////////////////////////////////////////
if (!immobileBody) { // TODO test no friction on immobileBody if (!immobileBody) { // TODO test no friction on immobileBody
setHorizontalFriction() setHorizontalFriction()
} }
@@ -395,6 +403,10 @@ open class ActorWithSprite(renderOrder: ActorOrder, val immobileBody: Boolean =
setVerticalFriction() setVerticalFriction()
} }
// some spacing //
// apply our compensation to actual hitbox // apply our compensation to actual hitbox
updateHitbox() updateHitbox()

View File

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

View File

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

View File

@@ -47,10 +47,10 @@ class LuaAIWrapper(private val scriptPath: String) : ActorAI {
override fun update(delta: Int) { override fun update(delta: Int) {
// run "update()" function in the script // 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 var threadRun = false
fun runCommand(reader: Reader, filename: String) { 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 speaker.enqueue(80, computer.bellpitch) -- term.bell sometimes get squelched
-- load bios, if any -- 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. -- halt/run luaprompt upon the termination of bios.
-- Valid BIOS should load OS and modify 'shell.status' to 'shell.halt' before terminating itself. -- Valid BIOS should load OS and modify 'shell.status' to 'shell.halt' before terminating itself.

View File

@@ -6,7 +6,7 @@
-- ALIASES -- -- ALIASES --
------------- -------------
_G.io = {} -- we make our own sandbox'd system --_G.io = {} -- we make our own sandbox'd system
--[[fs.dofile = function(p, ...) --[[fs.dofile = function(p, ...)
local f = fs.open(p, "r") 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" _G.__scanMode__ = "line"
local s local s
repeat -- we can do this ONLY IF lua execution process is SEPARATE THREAD repeat -- we can do this ONLY IF lua execution process is SEPARATE THREAD
s = machine.getLastStreamInput() s = machine.__readFromStdin()
until s until s
-- input is closed when RETURN is hit. See above comments. -- input is closed when RETURN is hit. See above comments.
return s 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.stdin = "stdin"
io.stdout = "stdout" io.stdout = "stdout"
io.stderr = "stderr" io.stderr = "stderr"
io.open = fs.open io.open = fs.open]]
io.input = function(luafile) --[[io.input = function(luafile)
io.__openfile__ = luafile io.__openfile__ = luafile
end end
@@ -105,13 +105,18 @@ io.read = function(option)
options["*n"] = function() error("Read number is not supported, yet!") end--_readNumber options["*n"] = function() error("Read number is not supported, yet!") end--_readNumber
options["*a"] = _readAll options["*a"] = _readAll
options["*l"] = _readLine options["*l"] = _readLine
end]]
io.read = function()
return string.char(machine.__readFromStdin())
end end
----------------- -----------------
-- PRINTSTREAM -- -- PRINTSTREAM --
----------------- -----------------
io.write = function(...) -- only useful when IO is "opening" stdin
--[[io.write = function(...)
local args = {...} local args = {...}
for _, v in ipairs(args) do for _, v in ipairs(args) do
local s local s
@@ -122,10 +127,10 @@ io.write = function(...)
end end
term.write(s) term.write(s)
end end
end end]]
-- for some reason, inputstream above kills 'print' function. -- for some reason, inputstream above kills 'print' function.
-- So we rewrite it. -- So we rewrite it.
_G.print = function(...) --[[_G.print = function(...) -- dependent on above io.write reimpl
local args = {...} local args = {...}
io.write(args[1]) io.write(args[1])
@@ -138,7 +143,7 @@ _G.print = function(...)
end end
io.write("\n") 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. * @param term : terminal that is connected to the computer fixtures, null if not connected any.
* Created by minjaesong on 16-09-10. * Created by minjaesong on 16-09-10.
*/ */
class BaseTerrarumComputer(peripheralSlots: Int) { class TerrarumComputer(peripheralSlots: Int) {
var maxPeripherals: Int = peripheralSlots var maxPeripherals: Int = peripheralSlots
private set private set
@@ -42,11 +42,11 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
lateinit var luaJ_globals: Globals lateinit var luaJ_globals: Globals
private set private set
var termOut: PrintStream? = null var stdout: PrintStream? = null
private set private set
var termErr: PrintStream? = null var stderr: PrintStream? = null
private set private set
var termIn: InputStream? = null var stdin: InputStream? = null
private set private set
val processorCycle: Int // number of Lua statement to process per tick (1/100 s) 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>() val peripheralTable = ArrayList<Peripheral>()
var stdinInput: Int = -1
private set
// os-related functions. These are called "machine" library-wise. // os-related functions. These are called "machine" library-wise.
private val startupTimestamp: Long = System.currentTimeMillis() private val startupTimestamp: Long = System.currentTimeMillis()
/** Time elapsed since the power is on. */ /** Time elapsed since the power is on. */
@@ -119,7 +123,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
if (peripheralTable.size < maxPeripherals) { if (peripheralTable.size < maxPeripherals) {
peripheralTable.add(peri) peripheralTable.add(peri)
peri.loadLib(luaJ_globals) peri.loadLib(luaJ_globals)
println("[BaseTerrarumComputer] loading peripheral $peri") println("[TerrarumComputer] loading peripheral $peri")
} }
else { else {
throw Error("No vacant peripheral slot") throw Error("No vacant peripheral slot")
@@ -129,7 +133,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
fun detachPeripheral(peri: Peripheral) { fun detachPeripheral(peri: Peripheral) {
if (peripheralTable.contains(peri)) { if (peripheralTable.contains(peri)) {
peripheralTable.remove(peri) peripheralTable.remove(peri)
println("[BaseTerrarumComputer] unloading peripheral $peri") println("[TerrarumComputer] unloading peripheral $peri")
} }
else { else {
throw IllegalArgumentException("Peripheral not exists: $peri") throw IllegalArgumentException("Peripheral not exists: $peri")
@@ -144,13 +148,13 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
fun initSandbox(term: Teletype) { fun initSandbox(term: Teletype) {
luaJ_globals = JsePlatform.debugGlobals() luaJ_globals = JsePlatform.debugGlobals()
termOut = TerminalPrintStream(term) stdout = TerminalPrintStream(this)
termErr = TerminalPrintStream(term) stderr = TerminalPrintStream(this)
termIn = TerminalInputStream(term) stdin = TerminalInputStream(this)
luaJ_globals.STDOUT = termOut luaJ_globals.STDOUT = stdout
luaJ_globals.STDERR = termErr luaJ_globals.STDERR = stderr
luaJ_globals.STDIN = termIn luaJ_globals.STDIN = stdin
luaJ_globals["bit"] = luaJ_globals["bit32"] 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) { fun update(gc: GameContainer, delta: Int) {
input = gc.input input = gc.input
if (currentExecutionThread.state == Thread.State.TERMINATED) if (currentExecutionThread.state == Thread.State.TERMINATED) {
unsetThreadRun() threadRun = false
// 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 (!isHalted) { if (!isHalted) {
driveBeepQueueManager(delta) driveBeepQueueManager(delta)
} }
else {
currentExecutionThread.interrupt()
}
} }
fun keyPressed(key: Int, c: Char) { 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() fun openStdin() {
var threadRun = false 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) { fun runCommand(line: String, env: String) {
if (!threadRun && !isHalted) { if (!threadRun) {
currentExecutionThread = Thread(ThreadRunCommand(luaJ_globals, line, env)) runnableRunCommand = ThreadRunCommand(luaJ_globals, line, env)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start() currentExecutionThread.start()
threadRun = true threadRun = true
} }
} }
fun runCommand(reader: Reader, filename: String) { fun runCommand(reader: Reader, filename: String) {
if (!threadRun && !isHalted) { if (!threadRun) {
currentExecutionThread = Thread(ThreadRunCommand(luaJ_globals, reader, filename)) runnableRunCommand = ThreadRunCommand(luaJ_globals, reader, filename)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start() currentExecutionThread.start()
threadRun = true threadRun = true
} }
} }
private fun unsetThreadRun() {
threadRun = false
threadTimer = 0
}
class ThreadRunCommand : Runnable { class ThreadRunCommand : Runnable {
val mode: Int private val mode: Int
val arg1: Any private val arg1: Any
val arg2: String private val arg2: String
val lua: Globals 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) { constructor(luaInstance: Globals, line: String, env: String) {
mode = 0 mode = 0
@@ -274,6 +285,32 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
} }
override fun run() { 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 { try {
val chunk: LuaValue val chunk: LuaValue
if (mode == 0) if (mode == 0)
@@ -291,15 +328,35 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
lua.STDERR.println("${SimpleTextTerminal.ASCII_DLE}${e.message}${SimpleTextTerminal.ASCII_DC4}") 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 { override fun call(): LuaValue {
return LuaValue.valueOf(computer.memSize) 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 { override fun call(millisec: LuaValue, freq: LuaValue): LuaValue {
computer.playTone(millisec.checkint(), freq.checkdouble()) computer.playTone(millisec.checkint(), freq.checkdouble())
return LuaValue.NONE return LuaValue.NONE
@@ -357,7 +414,7 @@ class BaseTerrarumComputer(peripheralSlots: Int) {
//AL.destroy() //AL.destroy()
if (DEBUG) println("[BaseTerrarumComputer] !! Beep queue clear") if (DEBUG) println("[TerrarumComputer] !! Beep queue clear")
} }
fun enqueueBeep(duration: Int, freq: Double) { 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.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction import org.luaj.vm2.lib.ZeroArgFunction
import net.torvald.terrarum.Terrarum 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 net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
import java.io.* import java.io.*
import java.nio.file.Files 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! * 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) * 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 { init {
// load things. WARNING: THIS IS MANUAL! // load things. WARNING: THIS IS MANUAL!
@@ -101,7 +101,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/ /** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
* directs media/ directory to /<uuid> directory * directs media/ directory to /<uuid> directory
*/ */
fun BaseTerrarumComputer.getRealPath(luapath: LuaValue) : String { fun TerrarumComputer.getRealPath(luapath: LuaValue) : String {
// direct mounted paths to real path // direct mounted paths to real path
val computerDir = Terrarum.currentSaveDir.absolutePath + "/computers/" val computerDir = Terrarum.currentSaveDir.absolutePath + "/computers/"
/* if not begins with "(/?)media/", direct to boot /* 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>/ * 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
@@ -155,7 +155,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
} }
/** Don't use this. Use isFile */ /** Don't use this. Use isFile */
class FileExists(val computer: BaseTerrarumComputer) : OneArgFunction() { class FileExists(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
@@ -207,7 +207,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
} }
/** we have 4GB file size limit */ /** we have 4GB file size limit */
class GetSize(val computer: BaseTerrarumComputer) : OneArgFunction() { class GetSize(val computer: TerrarumComputer) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
@@ -220,7 +220,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/** /**
* difference with ComputerCraft: it returns boolean, true on successful. * 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)
@@ -231,7 +231,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/** /**
* moves a directory, overwrites the target * 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 { override fun call(from: LuaValue, to: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(from) Filesystem.ensurePathSanity(from)
Filesystem.ensurePathSanity(to) Filesystem.ensurePathSanity(to)
@@ -250,7 +250,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
* copies a directory, overwrites the target * copies a directory, overwrites the target
* difference with ComputerCraft: it returns boolean, true on successful. * 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 { override fun call(from: LuaValue, to: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(from) Filesystem.ensurePathSanity(from)
Filesystem.ensurePathSanity(to) Filesystem.ensurePathSanity(to)
@@ -266,7 +266,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
/** /**
* difference with ComputerCraft: it returns boolean, true on successful. * 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) 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 { override fun call(base: LuaValue, local: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(base) Filesystem.ensurePathSanity(base)
Filesystem.ensurePathSanity(local) Filesystem.ensurePathSanity(local)
@@ -312,7 +312,7 @@ internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
* writeBytes = function(string as bytearray) * 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 { override fun call(path: LuaValue, mode: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) 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 { override fun call(path: LuaValue) : LuaValue {
Filesystem.ensurePathSanity(path) Filesystem.ensurePathSanity(path)

View File

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

View File

@@ -5,12 +5,12 @@ import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction import org.luaj.vm2.lib.OneArgFunction
import net.torvald.terrarum.gamecontroller.Key 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. * Created by minjaesong on 16-09-25.
*/ */
class Input(globals: Globals, computer: BaseTerrarumComputer) { class Input(globals: Globals, computer: TerrarumComputer) {
init { init {
globals["input"] = LuaTable() 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) 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 { override fun call(keyCode: LuaValue): LuaValue {
val key = keyCode.checkint() val key = keyCode.checkint()

View File

@@ -5,7 +5,7 @@ import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.TwoArgFunction import org.luaj.vm2.lib.TwoArgFunction
import org.luaj.vm2.lib.ZeroArgFunction 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.LuaFunction
import org.luaj.vm2.lib.OneArgFunction import org.luaj.vm2.lib.OneArgFunction
@@ -16,7 +16,7 @@ import org.luaj.vm2.lib.OneArgFunction
* *
* Created by minjaesong on 16-09-27. * Created by minjaesong on 16-09-27.
*/ */
class PcSpeakerDriver(val globals: Globals, host: BaseTerrarumComputer) { class PcSpeakerDriver(val globals: Globals, host: TerrarumComputer) {
init { init {
globals["speaker"] = LuaTable() 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, ...) * @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 { override fun call(): LuaValue {
host.clearBeepQueue() host.clearBeepQueue()
return LuaValue.NONE return LuaValue.NONE

View File

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

View File

@@ -1,6 +1,6 @@
package net.torvald.terrarum.virtualcomputer.peripheral 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.Globals
import org.luaj.vm2.LuaTable import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue import org.luaj.vm2.LuaValue
@@ -11,7 +11,7 @@ import org.luaj.vm2.LuaValue
* *
* Created by minjaesong on 16-09-27. * Created by minjaesong on 16-09-27.
*/ */
internal class PeripheralPSG(val host: BaseTerrarumComputer) internal class PeripheralPSG(val host: TerrarumComputer)
: Peripheral("psg") { : Peripheral("psg") {
override fun loadLib(globals: Globals) { 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.DecodeTapestry
import net.torvald.terrarum.gameactors.ai.toLua import net.torvald.terrarum.gameactors.ai.toLua
import net.torvald.terrarum.getPixel import org.luaj.vm2.*
import org.luaj.vm2.Globals import org.luaj.vm2.lib.*
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.ThreeArgFunction 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 org.newdawn.slick.*
import java.util.*
/** /**
* Created by SKYHi14 on 2017-02-08. * Created by SKYHi14 on 2017-02-08.
@@ -20,8 +13,8 @@ import java.util.*
class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) : class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
Peripheral("ppu") { Peripheral("ppu") {
companion object { companion object {
val blockW = 8 val blockW = 8 // MUST BE 8
val blockH = 8 val blockH = 8 // MUST BE 8
/** /**
* Converts consecutive lua table indexed from 1 as IntArray. * 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 val frameBufferImage = frameBuffer.image
// hard-coded 8x8 // hard-coded 8x8
var fontRom = Array<IntArray>(256, { Array<Int>(blockH, { 0 }).toIntArray() }) var fontRom = Array<IntArray>(256, { IntArray(blockH) })
init { init {
// build it for first time // build it for first time
@@ -61,10 +54,20 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
} }
val CLUT = VRAM.CLUT val CLUT = VRAM.CLUT
val coloursCount = CLUT.size val colorsCount = CLUT.size
val luaSpriteTable = LuaTable() val luaSpriteTable = LuaTable()
var color = 15 // black
set(value) {
if (value >= colorsCount || value < 0) {
throw IllegalArgumentException("Unknown colour: $value")
}
else {
field = value
}
}
init { init {
fun composeSpriteObject(spriteIndex: Int) : LuaValue { fun composeSpriteObject(spriteIndex: Int) : LuaValue {
val sprite = vram.sprites[spriteIndex] val sprite = vram.sprites[spriteIndex]
@@ -109,16 +112,29 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
override fun loadLib(globals: Globals) { override fun loadLib(globals: Globals) {
globals["ppu"] = LuaTable() globals["ppu"] = LuaTable()
globals["ppu"]["setForeColor"] = SetForeColor(this) globals["ppu"]["setTextForeColor"] = SetTextForeColor(this)
globals["ppu"]["getForeColor"] = GetForeColor(this) globals["ppu"]["getTextForeColor"] = GetTextForeColor(this)
globals["ppu"]["setBackColor"] = SetBackColor(this) globals["ppu"]["setTextBackColor"] = SetTextBackColor(this)
globals["ppu"]["getBackColor"] = GetBackColor(this) globals["ppu"]["getTextBackColor"] = GetTextBackColor(this)
globals["ppu"]["setColor"] = SetDrawColor(this)
globals["ppu"]["getColor"] = GetDrawColor(this)
globals["ppu"]["emitChar"] = EmitChar(this) globals["ppu"]["emitChar"] = EmitChar(this)
globals["ppu"]["clearAll"] = ClearAll(this) globals["ppu"]["clearAll"] = ClearAll(this)
globals["ppu"]["clearBack"] = ClearBackground(this) globals["ppu"]["clearBack"] = ClearBackground(this)
globals["ppu"]["clearFore"] = ClearForeground(this) globals["ppu"]["clearFore"] = ClearForeground(this)
globals["ppu"]["getSpritesCount"] = GetSpritesCount(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) private val spriteBuffer = ImageBuffer(VSprite.width, VSprite.height)
@@ -171,44 +187,23 @@ class PeripheralVideoCard(val termW: Int = 40, val termH: Int = 25) :
img.destroy() img.destroy()
} }
fun ImageBuffer.softwareRender(other: ImageBuffer, posX: Int, posY: Int) { private var textColorFore = 49 // white
for (y in 0..other.height - 1) { private var textColorBack = 64 // transparent
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 foreColor = 49 // white fun drawChar(c: Char, x: Int, y: Int, colFore: Int = textColorFore, colBack: Int = textColorBack) {
private var backColor = 64 // transparent
fun drawChar(c: Char, x: Int, y: Int, colFore: Int = foreColor, colBack: Int = backColor) {
val glyph = fontRom[c.toInt()] val glyph = fontRom[c.toInt()]
val fore = CLUT[colFore]
val back = CLUT[colBack]
// software render // software render
for (gy in 0..blockH - 1) { for (gy in 0..blockH - 1) { for (gx in 0..blockW - 1) {
for (gx in 0..blockW - 1) { val glyAlpha = glyph[gy] and (1 shl gx)
val glyAlpha = glyph[gy].ushr(gx).and(1)
if (glyAlpha != 0) { if (glyAlpha != 0) {
vram.foreground.setRGBA(x * blockW + gx, y * blockH + gy, fore.red, fore.green, fore.blue, fore.alpha) vram.setForegroundPixel(x + gx, y + gy, colFore)
}
else {
vram.foreground.setRGBA(x * blockW + gx, y * blockH + gy, back.red, back.green, back.blue, back.alpha)
}
} }
} 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] 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: * 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") 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 { override fun call(arg: LuaValue): LuaValue {
videoCard.foreColor = arg.checkint() videoCard.textColorFore = arg.checkint()
return LuaValue.NONE return LuaValue.NONE
} }
} }
class GetForeColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() { class GetTextForeColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue { 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 { override fun call(arg: LuaValue): LuaValue {
videoCard.backColor = arg.checkint() videoCard.textColorBack = arg.checkint()
return LuaValue.NONE return LuaValue.NONE
} }
} }
class GetBackColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() { class GetTextBackColor(val videoCard: PeripheralVideoCard) : ZeroArgFunction() {
override fun call(): LuaValue { 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() { 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] 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 // // Sprites //
@@ -404,7 +510,7 @@ class VRAM(pxlWidth: Int, pxlHeight: Int, nSprites: Int) {
fun setForegroundPixel(x: Int, y: Int, color: Int) { fun setForegroundPixel(x: Int, y: Int, color: Int) {
val col = CLUT[color] 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)
} }
} }
@@ -467,4 +573,27 @@ class VSprite {
setPixel(i % width, i / width, data[i]) setPixel(i % width, i / width, data[i])
} }
} }
} }
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.blendMul
import net.torvald.terrarum.gameactors.DecodeTapestry 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 net.torvald.terrarum.virtualcomputer.peripheral.PeripheralVideoCard
import org.newdawn.slick.Color import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer import org.newdawn.slick.GameContainer
@@ -15,12 +17,12 @@ import org.newdawn.slick.Image
* *
* Created by SKYHi14 on 2017-02-08. * 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 lateinit var videoCard: PeripheralVideoCard
override val width: Int; get() = videoCard.termW override val width: Int; get() = videoCard.termW
override val height: Int; get() = videoCard.termH 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 cursorX = 0
override var cursorY = 0 override var cursorY = 0
override var cursorBlink = true override var cursorBlink = true
@@ -78,7 +80,7 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
} }
override fun keyPressed(key: Int, c: Char) { override fun keyPressed(key: Int, c: Char) {
//TODO("not implemented") host.keyPressed(key, c)
} }
override fun writeChars(s: String) { 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) { override fun emitChar(bufferChar: Int, x: Int, y: Int) {
videoCard.drawChar( 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(8).and(0xF)],
CLUT16_TO_64[bufferChar.ushr(12).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 var lastKeyPress: Int? = null
override fun emitChar(c: Char, x: Int, y: Int) { 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) { override fun printChar(c: Char) {
@@ -167,7 +176,7 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
} }
override fun clear() { override fun clear() {
videoCard.clearAll() videoCard.clearForeground()
} }
override fun clearLine() { override fun clearLine() {
@@ -175,11 +184,28 @@ class GraphicsTerminal(private val host: BaseTerrarumComputer) : Terminal {
} }
override fun newLine() { override fun newLine() {
//TODO("not implemented") cursorX = 0; cursorY += 1; wrap()
} }
override fun scroll(amount: Int) { 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 package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.aa.AAFrame import net.torvald.aa.AAFrame
import net.torvald.aa.ColouredFastFont
import net.torvald.terrarum.* import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.DecodeTapestry import net.torvald.terrarum.gameactors.DecodeTapestry
import net.torvald.terrarum.gameactors.abs import net.torvald.terrarum.gameactors.abs
import net.torvald.terrarum.gamecontroller.Key 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.BufferUtils
import org.lwjgl.openal.AL import org.lwjgl.openal.AL
import org.lwjgl.openal.AL10 import org.lwjgl.openal.AL10
@@ -21,7 +20,7 @@ import java.util.*
* Created by minjaesong on 16-09-07. * Created by minjaesong on 16-09-07.
*/ */
open class SimpleTextTerminal( 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 colour: Boolean = false, hires: Boolean = false
) : Terminal { ) : Terminal {
@@ -64,7 +63,7 @@ open class SimpleTextTerminal(
open protected val fontImg = Image(fontRef) open protected val fontImg = Image(fontRef)
open val fontW = fontImg.width / 16 open val fontW = fontImg.width / 16
open val fontH = fontImg.height / 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 val borderSize = 20
override val displayW = fontW * width + 2 * borderSize override val displayW = fontW * width + 2 * borderSize

View File

@@ -1,13 +1,42 @@
package net.torvald.terrarum.virtualcomputer.terminal package net.torvald.terrarum.virtualcomputer.terminal
import org.lwjgl.input.Keyboard import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import java.io.InputStream import java.io.InputStream
/** /**
* Created by minjaesong on 16-09-10. * 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 { 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 package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.terrarum.virtualcomputer.computer.TerrarumComputer
import java.io.OutputStream import java.io.OutputStream
import java.io.PrintStream import java.io.PrintStream
/** /**
* Created by minjaesong on 16-09-10. * 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 host: TerrarumComputer) : OutputStream() {
override fun write(b: Int) = host.term.printChar(b.and(0xFF).toChar())
class TerminalOutputStream(val term: Teletype) : OutputStream() {
override fun write(b: Int) = 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.AVKey
import net.torvald.terrarum.gameactors.FixtureBase 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.SimpleTextTerminal
import net.torvald.terrarum.virtualcomputer.terminal.Terminal import net.torvald.terrarum.virtualcomputer.terminal.Terminal
import net.torvald.terrarum.virtualcomputer.worldobject.ui.UITextTerminal import net.torvald.terrarum.virtualcomputer.worldobject.ui.UITextTerminal
@@ -14,7 +14,7 @@ import java.util.*
*/ */
class FixtureBasicTerminal(phosphor: Color) : FixtureBase() { class FixtureBasicTerminal(phosphor: Color) : FixtureBase() {
val computer = BaseTerrarumComputer(8) val computer = TerrarumComputer(8)
val vt: Terminal = SimpleTextTerminal(phosphor, 80, 25, computer) val vt: Terminal = SimpleTextTerminal(phosphor, 80, 25, computer)
val ui = UITextTerminal(vt) val ui = UITextTerminal(vt)

View File

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