mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-11 06:11:50 +09:00
beeps are now processed sorely on the computer, added speaker driver (wip)
Former-commit-id: c8339104815a62db51e5bd26460a87f1f653a775 Former-commit-id: f22320a45734b141c4f02ca61fbd79772e32c7c5
This commit is contained in:
@@ -6,10 +6,30 @@
|
||||
Some codes were taken from OpenComputers, which is distributed under MIT
|
||||
--]]
|
||||
|
||||
_G.computer = {}
|
||||
computer.realTime = function() return 0 end
|
||||
|
||||
if totalMemory() == 0 then print("no RAM installed") __haltsystemexplicit__() return end
|
||||
-- global variables
|
||||
_G._VERSION = "Luaj-jse 3.0.1 (Lua 5.2.3)"
|
||||
_G.EMDASH = string.char(0xC4)
|
||||
_G.UNCHECKED = string.char(0x9C) -- box unchecked
|
||||
_G.CHECKED = string.char(0x9D) -- box checked
|
||||
_G.MONEY = string.char(0x9E) -- currency sign
|
||||
_G.MIDDOT = string.char(0xFA) -- middle dot sign
|
||||
_G.DC1 = string.char(17) -- black
|
||||
_G.DC2 = string.char(18) -- white
|
||||
_G.DC3 = string.char(19) -- dim grey
|
||||
_G.DC4 = string.char(20) -- light grey
|
||||
_G.DLE = string.char(16) -- default error colour
|
||||
|
||||
_G.bell = function(patn) term.bell(patn or ".") end
|
||||
_G.beep = _G.bell
|
||||
|
||||
if totalMemory() == 0 then
|
||||
bell "="
|
||||
print("no RAM installed")
|
||||
__haltsystemexplicit__()
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local hookInterval = 100
|
||||
@@ -949,18 +969,7 @@ sandbox._G = sandbox
|
||||
-- path for any ingame libraries
|
||||
package.path = "/net/torvald/terrarum/virtualcomputer/assets/lua/?.lua;" .. package.path
|
||||
|
||||
-- global variables
|
||||
_G._VERSION = "Luaj-jse 3.0.1 (Lua 5.2.3)"
|
||||
_G.EMDASH = string.char(0xC4)
|
||||
_G.UNCHECKED = string.char(0x9C) -- box unchecked
|
||||
_G.CHECKED = string.char(0x9D) -- box checked
|
||||
_G.MONEY = string.char(0x9E) -- currency sign
|
||||
_G.MIDDOT = string.char(0xFA) -- middle dot sign
|
||||
_G.DC1 = string.char(17) -- black
|
||||
_G.DC2 = string.char(18) -- white
|
||||
_G.DC3 = string.char(19) -- dim grey
|
||||
_G.DC4 = string.char(20) -- light grey
|
||||
_G.DLE = string.char(16) -- default error colour
|
||||
-- global functions
|
||||
_G.runscript = function(s, src, ...)
|
||||
if s:byte(1) == 27 then error("Bytecode execution is prohibited.") end
|
||||
|
||||
@@ -973,8 +982,6 @@ _G.runscript = function(s, src, ...)
|
||||
end
|
||||
end
|
||||
_G.__scanMode__ = "UNINIT" -- part of inputstream implementation
|
||||
_G.bell = function(patn) term.bell(patn or ".") end
|
||||
_G.beep = _G.bell
|
||||
|
||||
local screenbufferdim = term.width() * term.height()
|
||||
local screencolours = 4
|
||||
@@ -982,7 +989,6 @@ if term.isCol() then screencolours = 8
|
||||
elseif term.isTeletype() then screencolours = 1 end
|
||||
local screenbuffersize = screenbufferdim * screencolours / 8
|
||||
|
||||
--_G.computer = {} -- standard console colours
|
||||
computer.prompt = DC3.."> "..DC4
|
||||
computer.verbose = true -- print debug info
|
||||
computer.loadedCLayer = {} -- list of loaded compatibility layers
|
||||
@@ -990,6 +996,7 @@ computer.bootloader = "/boot/efi"
|
||||
computer.OEM = ""
|
||||
computer.beep = emittone
|
||||
computer.totalMemory = _G.totalMemory
|
||||
computer.bellpitch = 1000
|
||||
local getMemory = function()
|
||||
collectgarbage()
|
||||
return collectgarbage("count") * 1024 - 6.5*1048576 + screenbuffersize
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.newdawn.slick.GameContainer
|
||||
import org.newdawn.slick.Input
|
||||
import java.io.*
|
||||
import java.nio.ByteBuffer
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* A part that makes "computer fixture" actually work
|
||||
@@ -34,6 +35,8 @@ import java.nio.ByteBuffer
|
||||
class BaseTerrarumComputer() {
|
||||
|
||||
val DEBUG_UNLIMITED_MEM = false
|
||||
val DEBUG = false
|
||||
|
||||
|
||||
lateinit var luaJ_globals: Globals
|
||||
private set
|
||||
@@ -112,6 +115,8 @@ class BaseTerrarumComputer() {
|
||||
luaJ_globals.STDERR = termErr
|
||||
luaJ_globals.STDIN = termIn
|
||||
|
||||
luaJ_globals["bit"] = luaJ_globals["bit32"]
|
||||
|
||||
// load libraries
|
||||
Term(luaJ_globals, term)
|
||||
Security(luaJ_globals)
|
||||
@@ -119,6 +124,8 @@ class BaseTerrarumComputer() {
|
||||
HostAccessProvider(luaJ_globals, this)
|
||||
Input(luaJ_globals, this)
|
||||
Http(luaJ_globals, this)
|
||||
PcSpeakerDriver(luaJ_globals, this)
|
||||
|
||||
|
||||
// secure the sandbox
|
||||
luaJ_globals["io"] = LuaValue.NIL
|
||||
@@ -134,7 +141,7 @@ class BaseTerrarumComputer() {
|
||||
luaJ_globals["totalMemory"] = LuaFunGetTotalMem(this)
|
||||
|
||||
luaJ_globals["computer"] = LuaTable()
|
||||
luaJ_globals["emittone"] = ComputerEmitTone(this)
|
||||
if (DEBUG) luaJ_globals["emittone"] = ComputerEmitTone(this)
|
||||
}
|
||||
|
||||
var threadTimer = 0
|
||||
@@ -158,6 +165,10 @@ class BaseTerrarumComputer() {
|
||||
unsetThreadRun()
|
||||
}
|
||||
}
|
||||
|
||||
driveBeepQueueManager(delta)
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun keyPressed(key: Int, c: Char) {
|
||||
@@ -190,6 +201,8 @@ class BaseTerrarumComputer() {
|
||||
|
||||
class ThreadRunCommand : Runnable {
|
||||
|
||||
val DEBUGTHRE = true
|
||||
|
||||
val mode: Int
|
||||
val arg1: Any
|
||||
val arg2: String
|
||||
@@ -227,8 +240,6 @@ class BaseTerrarumComputer() {
|
||||
if (DEBUGTHRE) e.printStackTrace(System.err)
|
||||
}
|
||||
}
|
||||
|
||||
val DEBUGTHRE = true
|
||||
}
|
||||
|
||||
class LuaFunGetTotalMem(val computer: BaseTerrarumComputer) : ZeroArgFunction() {
|
||||
@@ -248,6 +259,58 @@ class BaseTerrarumComputer() {
|
||||
// BEEPER DRIVER //
|
||||
///////////////////
|
||||
|
||||
private val beepMaxLen = 10000
|
||||
// let's regard it as a tracker...
|
||||
private val beepQueue = ArrayList<Pair<Int, Float>>()
|
||||
private var beepCursor = -1
|
||||
private var beepQueueLineExecTimer = 0 // millisec
|
||||
private var beepQueueFired = false
|
||||
|
||||
private fun driveBeepQueueManager(delta: Int) {
|
||||
// start beep queue
|
||||
if (beepQueue.size > 0 && beepCursor == -1) {
|
||||
beepCursor = 0
|
||||
}
|
||||
|
||||
// continue beep queue
|
||||
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
|
||||
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
|
||||
beepCursor += 1
|
||||
beepQueueFired = false
|
||||
}
|
||||
|
||||
// complete beep queue
|
||||
if (beepCursor >= beepQueue.size) {
|
||||
clearBeepQueue()
|
||||
if (DEBUG) println("!! Beep queue clear")
|
||||
}
|
||||
|
||||
// actually play queue
|
||||
if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) {
|
||||
playTone(beepQueue[beepCursor].first, beepQueue[beepCursor].second)
|
||||
beepQueueFired = true
|
||||
}
|
||||
|
||||
if (beepQueueFired) beepQueueLineExecTimer += delta
|
||||
}
|
||||
|
||||
fun clearBeepQueue() {
|
||||
beepQueue.clear()
|
||||
beepCursor = -1
|
||||
beepQueueLineExecTimer = 0
|
||||
}
|
||||
|
||||
fun enqueueBeep(duration: Int, freq: Float) {
|
||||
beepQueue.add(Pair(Math.min(duration, beepMaxLen), freq))
|
||||
}
|
||||
|
||||
fun beepQueueGetLenOfPtn(ptnIndex: Int) = beepQueue[ptnIndex].first
|
||||
|
||||
|
||||
////////////////////
|
||||
// TONE GENERATOR //
|
||||
////////////////////
|
||||
|
||||
private val sampleRate = 44100
|
||||
private var beepSource: Int? = null
|
||||
private var beepBuffer: Int? = null
|
||||
@@ -311,7 +374,7 @@ class BaseTerrarumComputer() {
|
||||
return audioData
|
||||
}
|
||||
|
||||
internal fun playTone(leninmilli: Int, freq: Float) {
|
||||
private fun playTone(leninmilli: Int, freq: Float) {
|
||||
audioData = makeAudioData(leninmilli, freq)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
/**
|
||||
* Virtual driver for 4-track squarewave soundcard
|
||||
*
|
||||
* Created by minjaesong on 16-09-27.
|
||||
*/
|
||||
class Kukeiha {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import li.cil.repack.org.luaj.vm2.LuaTable
|
||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||
import li.cil.repack.org.luaj.vm2.lib.TwoArgFunction
|
||||
import li.cil.repack.org.luaj.vm2.lib.ZeroArgFunction
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
|
||||
/**
|
||||
* PC Speaker driver and arpeggiator (MONOTONE-style 4 channels)
|
||||
*
|
||||
* Created by minjaesong on 16-09-27.
|
||||
*/
|
||||
class PcSpeakerDriver(globals: Globals, host: BaseTerrarumComputer) {
|
||||
|
||||
init {
|
||||
globals["speaker"] = LuaTable()
|
||||
globals["speaker"]["enqueue"] = EnqueueTone(host)
|
||||
globals["speaker"]["clear"] = ClearQueue(host)
|
||||
}
|
||||
|
||||
class EnqueueTone(val host: BaseTerrarumComputer) : TwoArgFunction() {
|
||||
override fun call(millisec: LuaValue, freq: LuaValue): LuaValue {
|
||||
host.enqueueBeep(millisec.checkint(), freq.tofloat())
|
||||
return LuaValue.NONE
|
||||
}
|
||||
}
|
||||
|
||||
class ClearQueue(val host: BaseTerrarumComputer) : ZeroArgFunction() {
|
||||
override fun call(): LuaValue {
|
||||
host.clearBeepQueue()
|
||||
return LuaValue.NONE
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,6 +23,9 @@ open class SimpleTextTerminal(
|
||||
phosphorColour: Color, override val width: Int, override val height: Int, private val host: BaseTerrarumComputer,
|
||||
colour: Boolean = false, hires: Boolean = false
|
||||
) : Terminal {
|
||||
|
||||
private val DEBUG = false
|
||||
|
||||
/**
|
||||
* Terminals must support AT LEAST 4 colours.
|
||||
* Color index 0 must be default background, index 3 must be default foreground
|
||||
@@ -108,32 +111,6 @@ open class SimpleTextTerminal(
|
||||
}
|
||||
|
||||
wrap()
|
||||
|
||||
// start beep queue
|
||||
if (beepQueue.size > 0 && beepCursor == -1) {
|
||||
beepCursor = 0
|
||||
}
|
||||
|
||||
// continue beep queue
|
||||
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
|
||||
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
|
||||
beepCursor += 1
|
||||
beepQueueFired = false
|
||||
}
|
||||
|
||||
// complete beep queue
|
||||
if (beepCursor >= beepQueue.size) {
|
||||
clearBeepQueue()
|
||||
// println("!! Beep queue clear")
|
||||
}
|
||||
|
||||
// actually play queue
|
||||
if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) {
|
||||
beep(beepQueue[beepCursor].first, beepQueue[beepCursor].second)
|
||||
beepQueueFired = true
|
||||
}
|
||||
|
||||
if (beepQueueFired) beepQueueLineExecTimer += delta
|
||||
}
|
||||
|
||||
private fun wrap() {
|
||||
@@ -332,48 +309,38 @@ open class SimpleTextTerminal(
|
||||
foreColour = foreDefault
|
||||
}
|
||||
|
||||
private val maxDuration = 10000
|
||||
|
||||
// let's regard it as a tracker...
|
||||
private val beepQueue = ArrayList<Pair<Int, Float>>()
|
||||
private var beepCursor = -1
|
||||
private var beepQueueLineExecTimer = 0 // millisec
|
||||
private var beepQueueFired = false
|
||||
|
||||
/**
|
||||
* @param duration: milliseconds
|
||||
* @param freg: Frequency (float)
|
||||
*/
|
||||
override fun beep(duration: Int, freq: Float) {
|
||||
// println("!! Beep playing row $beepCursor, d ${Math.min(duration, maxDuration)} f $freq")
|
||||
host.playTone(Math.min(duration, maxDuration), freq)
|
||||
host.clearBeepQueue()
|
||||
host.enqueueBeep(duration, freq)
|
||||
}
|
||||
|
||||
/** for "beep code" on modern BIOS. Pattern: - . */
|
||||
/** for "beep code" on modern BIOS. */
|
||||
override fun bell(pattern: String) {
|
||||
clearBeepQueue()
|
||||
host.clearBeepQueue()
|
||||
|
||||
val freq: Float =
|
||||
if (host.luaJ_globals["computer"]["bellpitch"].isnil())
|
||||
1000f
|
||||
else
|
||||
host.luaJ_globals["computer"]["bellpitch"].checkdouble().toFloat()
|
||||
|
||||
for (c in pattern) {
|
||||
when (c) {
|
||||
'.' -> { enqueueBeep(80, 1000f); enqueueBeep(80, 0f) }
|
||||
'-' -> { enqueueBeep(250, 1000f); enqueueBeep(80, 0f) }
|
||||
' ' -> { enqueueBeep(250, 0f) }
|
||||
'.' -> { host.enqueueBeep(50, freq); host.enqueueBeep(50, 0f) }
|
||||
'-' -> { host.enqueueBeep(200, freq); host.enqueueBeep(50, 0f) }
|
||||
'=' -> { host.enqueueBeep(500, freq); host.enqueueBeep(50, 0f) }
|
||||
' ' -> { host.enqueueBeep(200, 0f) }
|
||||
',' -> { host.enqueueBeep(50, 0f) }
|
||||
else -> throw IllegalArgumentException("Unacceptable pattern: $c (from '$pattern')")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun clearBeepQueue() {
|
||||
beepQueue.clear()
|
||||
beepCursor = -1
|
||||
beepQueueLineExecTimer = 0
|
||||
}
|
||||
|
||||
fun enqueueBeep(duration: Int, freq: Float) {
|
||||
beepQueue.add(Pair(Math.min(duration, maxDuration), freq))
|
||||
}
|
||||
|
||||
fun beepQueueGetLenOfPtn(ptnIndex: Int) = beepQueue[ptnIndex].first
|
||||
|
||||
override var lastInputByte: Int = -1
|
||||
var sb: StringBuilder = StringBuilder()
|
||||
private var inputOpen = false
|
||||
@@ -466,8 +433,6 @@ open class SimpleTextTerminal(
|
||||
ASCII_DLE
|
||||
)
|
||||
}
|
||||
|
||||
private val DEBUG = true
|
||||
}
|
||||
|
||||
class ALException(errorCode: Int) : Exception("ALerror: $errorCode") {
|
||||
|
||||
Reference in New Issue
Block a user