improved way of initialising vms at (re)launch

This commit is contained in:
minjaesong
2023-01-04 19:09:42 +09:00
parent f27caded9b
commit ceddf2c5b9
20 changed files with 275 additions and 177 deletions

View File

@@ -7,7 +7,11 @@ import net.torvald.tsvm.peripheral.AudioAdapter
*/
class AudioJSR223Delegate(private val vm: VM) {
private fun getFirstSnd(): AudioAdapter? = vm.findPeribyType(VM.PERITYPE_SOUND)?.peripheral as? AudioAdapter
private fun getFirstSnd(): AudioAdapter? {
val a = vm.findPeribyType(VM.PERITYPE_SOUND)?.peripheral as? AudioAdapter
println("get AudioAdapter: $a; vm: $vm")
return a
}
private fun getPlayhead(playhead: Int) = getFirstSnd()?.playheads?.get(playhead)
fun setPcmMode(playhead: Int) { getPlayhead(playhead)?.isPcmMode = true }
@@ -56,9 +60,9 @@ class AudioJSR223Delegate(private val vm: VM) {
}
fun getPcmData(index: Int) = getFirstSnd()?.pcmBin?.get(index.toLong())
fun setPcmQueueSizeIndex(playhead: Int, index: Int) { getPlayhead(playhead)?.pcmQueueSizeIndex = index }
fun getPcmQueueSizeIndex(playhead: Int, index: Int) { getPlayhead(playhead)?.pcmQueueSizeIndex }
fun getPcmQueueSize(playhead: Int, index: Int) { getPlayhead(playhead)?.getPcmQueueSize() }
fun setPcmQueueCapacityIndex(playhead: Int, index: Int) { getPlayhead(playhead)?.pcmQueueSizeIndex = index }
fun getPcmQueueCapacityIndex(playhead: Int, index: Int) { getPlayhead(playhead)?.pcmQueueSizeIndex }
fun getPcmQueueCapacity(playhead: Int, index: Int) { getPlayhead(playhead)?.getPcmQueueCapacity() }
fun resetParams(playhead: Int) {
getPlayhead(playhead)?.resetParams()

View File

@@ -465,7 +465,7 @@ class GraphicsJSR223Delegate(private val vm: VM) {
}
}
else if (1 == useDither) {
val srcimg = UnsafeHelper.allocate(width * height * 4L * channels) // array of floats!
val srcimg = UnsafeHelper.allocate(width * height * 4L * channels, this) // array of floats!
for (k in 0L until len) {
srcimg.setFloat(channels * k + 0, vm.peek(srcPtr + channels * k + 0)!!.toUint().toFloat() / 255f)

View File

@@ -24,9 +24,9 @@ internal object UnsafeHelper {
/**
* A factory method to allocate a memory of given size and return its starting address as a pointer.
*/
fun allocate(size: Long): UnsafePtr {
fun allocate(size: Long, caller: Any): UnsafePtr {
val ptr = unsafe.allocateMemory(size)
return UnsafePtr(ptr, size)
return UnsafePtr(ptr, size, caller)
}
fun memcpy(src: UnsafePtr, fromIndex: Long, dest: UnsafePtr, toIndex: Long, copyLength: Long) =
@@ -58,7 +58,7 @@ internal object UnsafeHelper {
*
* Use of hashCode() is forbidden, use the pointer instead.
*/
internal class UnsafePtr(pointer: Long, allocSize: Long) {
internal class UnsafePtr(pointer: Long, allocSize: Long, private val caller: Any) {
var destroyed = false
private set
@@ -162,7 +162,7 @@ internal class UnsafePtr(pointer: Long, allocSize: Long) {
UnsafeHelper.unsafe.setMemory(ptr, size, byte)
}
override fun toString() = "0x${ptr.toString(16)} with size $size"
override fun toString() = "0x${ptr.toString(16)} with size $size, created by $caller"
override fun equals(other: Any?) = this.ptr == (other as UnsafePtr).ptr && this.size == other.size
inline fun printStackTrace(obj: Any) = printStackTrace(obj, System.out) // because of Java

View File

@@ -0,0 +1,6 @@
package net.torvald.tsvm
/**
* Created by minjaesong on 2023-01-04.
*/
fun getHashStr(length: Int = 5) = (0 until length).map { "YBNDRFG8EJKMCPQXOTLVWIS2A345H769"[Math.random().times(32).toInt()] }.joinToString("")

View File

@@ -14,6 +14,10 @@ import kotlin.math.ceil
class ErrorIllegalAccess(vm: VM, addr: Long) : RuntimeException("Segmentation fault at 0x${addr.toString(16).padStart(8, '0')} on VM id ${vm.id}")
inline class VmId(val text: String) {
override fun toString() = text
}
/**
* A class representing an instance of a Virtual Machine
@@ -30,7 +34,9 @@ class VM(
val peripheralSlots = _peripheralSlots.coerceIn(1,8)
val id = java.util.Random().nextInt()
val id = VmId(getHashStr(6).let { it.substring(0..2) + "-" + it.substring(3..5) })
override fun toString() = "tsvm.VM!$id"
internal val contexts = ArrayList<Thread>()
@@ -38,7 +44,7 @@ class VM(
val MALLOC_UNIT = 64
private val mallocBlockSize = (memsize / MALLOC_UNIT).toInt()
internal val usermem = UnsafeHelper.allocate(memsize)
internal val usermem = UnsafeHelper.allocate(memsize, this)
val peripheralTable = Array(peripheralSlots) { PeripheralEntry() }

View File

@@ -13,6 +13,8 @@ import java.nio.charset.Charset
*/
class VMJSR223Delegate(private val vm: VM) {
fun getVmId() = vm.id.toString()
fun poke(addr: Int, value: Int) = vm.poke(addr.toLong(), value.toByte())
fun peek(addr: Int) = vm.peek(addr.toLong())!!.toInt().and(255)
fun nanoTime() = System.nanoTime()

View File

@@ -2,11 +2,15 @@ package net.torvald.tsvm
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.utils.GdxRuntimeException
import com.badlogic.gdx.utils.JsonValue
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import net.torvald.tsvm.peripheral.BlockTransferInterface
import net.torvald.tsvm.peripheral.GraphicsAdapter
import net.torvald.tsvm.peripheral.PeriBase
import net.torvald.tsvm.peripheral.VMProgramRom
/**
* Created by minjaesong on 2022-12-15.
@@ -21,7 +25,7 @@ object VMSetupBroker {
* @param vmRunners Hashmap on the host of VMs that holds the instances of the VMRunners for the given VM. Key: Int(VM's identifier), value: [net.torvald.tsvm.VMRunner]
* @param coroutineJobs Hashmap on the host of VMs that holds the coroutine-job object for the currently running VM-instance. Key: Int(VM's identifier), value: [kotlinx.coroutines.Job]
*/
fun initVMenv(vm: VM, gpu: GraphicsAdapter, vmRunners: HashMap<Int, VMRunner>, coroutineJobs: HashMap<Int, Job>, whatToDoOnVmException: (Throwable) -> Unit) {
fun initVMenv(vm: VM, profileJson: JsonValue, profileName: String, gpu: GraphicsAdapter, vmRunners: HashMap<VmId, VMRunner>, coroutineJobs: HashMap<VmId, Job>, whatToDoOnVmException: (Throwable) -> Unit) {
vm.init()
try {
@@ -29,6 +33,8 @@ object VMSetupBroker {
}
catch (_: GdxRuntimeException) {} // pixmap already disposed
installPeripherals(vm, profileJson, profileName)
vm.peripheralTable[1] = PeripheralEntry(gpu)//, GraphicsAdapter.VRAM_SIZE, 16, 0)
vm.getPrintStream = { gpu.getPrintStream() }
@@ -54,8 +60,10 @@ object VMSetupBroker {
* @param vmRunners Hashmap on the host of VMs that holds the instances of the VMRunners for the given VM. Key: Int(VM's identifier), value: [net.torvald.tsvm.VMRunner]
* @param coroutineJobs Hashmap on the host of VMs that holds the coroutine-job object for the currently running VM-instance. Key: Int(VM's identifier), value: [kotlinx.coroutines.Job]
*/
fun killVMenv(vm: VM, vmRunners: HashMap<Int, VMRunner>, coroutineJobs: HashMap<Int, Job>) {
fun killVMenv(vm: VM, vmRunners: HashMap<VmId, VMRunner>, coroutineJobs: HashMap<VmId, Job>) {
vm.park()
vm.poke(-90L, -128)
for (i in 1 until vm.peripheralTable.size) {
try {
@@ -64,13 +72,108 @@ object VMSetupBroker {
catch (_: Throwable) {}
}
coroutineJobs[vm.id]?.cancel("VM kill command received")
vmRunners[vm.id]?.close()
vm.getPrintStream = { TODO() }
vm.getErrorStream = { TODO() }
vm.getInputStream = { TODO() }
vm.poke(-90L, -128)
vmRunners[vm.id]?.close()
coroutineJobs[vm.id]?.cancel("VM kill command received")
}
/**
* You'll want to further init the things using the VM this function returns, such as:
*
* ```
* makeVMfromJson(json.get(NAME)).let{
* initVMemv(it)
* vms[VIEWPORT_INDEX] = VMRunnerInfo(it, NAME)
* }
* ```
*/
private fun installPeripherals(vm: VM, json: JsonValue, profileName: String): VM {
println("Processing profile '$profileName'")
val cardslots = json.getInt("cardslots")
// install peripherals
listOf("com1", "com2", "com3", "com4").map { json.get(it) }.forEachIndexed { index, jsonValue ->
jsonValue?.let { deviceInfo ->
val className = deviceInfo.getString("cls")
val loadedClass = Class.forName(className)
val argTypess = loadedClass.declaredConstructors
var successful = false
var k = 0
// just try out all the possible argTypes
while (!successful && k < argTypess.size) {
try {
val argTypes = argTypess[k].parameterTypes
println("loadedClass = $className")
println("trying constructor args[${k}/${argTypess.lastIndex}]: ${argTypes.joinToString { it.canonicalName }}")
val args = deviceInfo.get("args").allIntoJavaType(argTypes.tail())
val loadedClassConstructor = loadedClass.getConstructor(*argTypes)
val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args)
vm.getIO().blockTransferPorts[index].attachDevice(loadedClassInstance as BlockTransferInterface)
println("COM${index+1} = ${loadedClassInstance.javaClass.canonicalName}: ${args.joinToString()}")
successful = true
}
catch (e: IllegalArgumentException) {
// e.printStackTrace()
}
finally {
k += 1
}
}
if (!successful) {
throw RuntimeException("Invalid or insufficient arguments for $className in the profile $profileName")
}
}
}
(2..cardslots).map { it to json.get("card$it") }.forEach { (index, jsonValue) ->
jsonValue?.let { deviceInfo ->
val className = deviceInfo.getString("cls")
val loadedClass = Class.forName(className)
val argTypes = loadedClass.declaredConstructors[0].parameterTypes
val args = deviceInfo.get("args").allIntoJavaType(argTypes.tail())
val loadedClassConstructor = loadedClass.getConstructor(*argTypes)
val loadedClassInstance = loadedClassConstructor.newInstance(vm, *args)
val peri = loadedClassInstance as PeriBase
vm.peripheralTable[index] = PeripheralEntry(
peri
)
}
}
return vm
}
private fun JsonValue.allIntoJavaType(argTypes: Array<Class<*>>): Array<Any?> {
val values = this.iterator().toList()
if (values.size != argTypes.size) throw IllegalArgumentException("# of args: ${values.size}, # of arg types: ${argTypes.size}")
return argTypes.mapIndexed { index, it -> when (it.canonicalName) {
"float", "java.lang.Float" -> values[index].asFloat()
"double", "java.lang.Double" -> values[index].asDouble()
"byte", "java.lang.Byte" -> values[index].asByte()
"char", "java.lang.Character" -> values[index].asChar()
"short", "java.lang.Short" -> values[index].asShort()
"int", "java.lang.Integer" -> values[index].asInt()
"long", "java.lang.Long" -> values[index].asLong()
"boolean", "java.lang.Boolean" -> values[index].asBoolean()
"java.lang.String" -> values[index].asString()
else -> throw NotImplementedError("No conversion for ${it.canonicalName} exists")
} }.toTypedArray()
}
private fun <T> Array<T>.tail(): Array<T> = this.sliceArray(1..this.lastIndex)
}

View File

@@ -2,12 +2,14 @@ package net.torvald.tsvm.peripheral
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio
import com.badlogic.gdx.utils.GdxRuntimeException
import com.badlogic.gdx.utils.Queue
import net.torvald.UnsafeHelper
import net.torvald.UnsafePtr
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
import net.torvald.tsvm.ThreeFiveMiniUfloat
import net.torvald.tsvm.VM
import net.torvald.tsvm.getHashStr
private fun Boolean.toInt() = if (this) 1 else 0
@@ -17,14 +19,14 @@ private class RenderRunnable(val playhead: AudioAdapter.Playhead) : Runnable {
}
@Volatile private var exit = false
override fun run() {
while (!Thread.interrupted()) {
while (!exit) {
if (playhead.isPcmMode) {
val writeQueue = playhead.pcmQueue
if (playhead.isPlaying && writeQueue.notEmpty()) {
printdbg("Taking samples from queue (queue size: ${writeQueue.size})")
printdbg("Taking samples from queue (queue size: ${writeQueue.size}/${playhead.getPcmQueueCapacity()})")
val samples = writeQueue.removeFirst()
playhead.position = writeQueue.size
@@ -46,7 +48,7 @@ private class RenderRunnable(val playhead: AudioAdapter.Playhead) : Runnable {
Thread.sleep(1)
}
Thread.currentThread().interrupt()
playhead.audioDevice.dispose()
}
fun stop() {
exit = true
@@ -59,10 +61,10 @@ private class WriteQueueingRunnable(val playhead: AudioAdapter.Playhead, val pcm
}
@Volatile private var exit = false
override fun run() {
while (!Thread.interrupted()) {
while (!exit) {
playhead.let {
if (it.pcmQueue.size < it.getPcmQueueSize() && it.pcmUpload && it.pcmUploadLength > 0) {
if (it.pcmQueue.size < it.getPcmQueueCapacity() && it.pcmUpload && it.pcmUploadLength > 0) {
printdbg("Downloading samples ${it.pcmUploadLength}")
val samples = ByteArray(it.pcmUploadLength)
@@ -77,7 +79,6 @@ private class WriteQueueingRunnable(val playhead: AudioAdapter.Playhead, val pcm
Thread.sleep(4)
}
Thread.currentThread().interrupt()
}
fun stop() {
exit = true
@@ -98,12 +99,12 @@ class AudioAdapter(val vm: VM) : PeriBase {
const val SAMPLING_RATE = 30000
}
internal val sampleBin = UnsafeHelper.allocate(114687L)
internal val sampleBin = UnsafeHelper.allocate(114687L, this)
internal val instruments = Array(256) { TaudInst() }
internal val playdata = Array(256) { Array(64) { TaudPlayData(0,0,0,0,0,0,0,0) } }
internal val playheads: Array<Playhead>
internal val cueSheet = Array(2048) { PlayCue() }
internal val pcmBin = UnsafeHelper.allocate(65536L)
internal val pcmBin = UnsafeHelper.allocate(65536L, this)
private val renderRunnables: Array<RenderRunnable>
private val renderThreads: Array<Thread>
@@ -114,6 +115,9 @@ class AudioAdapter(val vm: VM) : PeriBase {
throwable.printStackTrace()
}
val hash = getHashStr()
override fun toString() = "AudioAdapter!$hash"
init {
@@ -140,13 +144,14 @@ class AudioAdapter(val vm: VM) : PeriBase {
}
Playhead(index = it, audioDevice = adev)
Playhead(this, index = it, audioDevice = adev)
}
renderRunnables = Array(4) { RenderRunnable(playheads[it]) }
renderThreads = Array(4) { Thread(renderRunnables[it], "AudioRenderHead${it+1}") }
renderThreads = Array(4) { Thread(renderRunnables[it], "AudioRenderHead${it+1}!$hash") }
writeQueueingRunnables = Array(4) { WriteQueueingRunnable(playheads[it], pcmBin) }
writeQueueingThreads = Array(4) { Thread(writeQueueingRunnables[it], "AudioQueueingHead${it+1}") }
writeQueueingThreads = Array(4) { Thread(writeQueueingRunnables[it], "AudioQueueingHead${it+1}!$hash") }
// printdbg("AudioAdapter latency: ${audioDevice.latency}")
renderThreads.forEach { it.uncaughtExceptionHandler = threadExceptionHandler; it.start() }
@@ -290,6 +295,7 @@ class AudioAdapter(val vm: VM) : PeriBase {
internal object PlayInstNop : PlayInstruction(0)
internal data class Playhead(
private val parent: AudioAdapter,
val index: Int,
var position: Int = 0,
@@ -372,10 +378,11 @@ class AudioAdapter(val vm: VM) : PeriBase {
}
}
fun getPcmQueueSize() = QUEUE_SIZE[pcmQueueSizeIndex]
fun getPcmQueueCapacity() = QUEUE_SIZE[pcmQueueSizeIndex]
fun dispose() {
audioDevice.dispose()
println("AudioDevice dispose ${parent.renderThreads[index]}")
try { audioDevice.dispose() } catch (e: GdxRuntimeException) { println(" "+ e.message) }
}
companion object {

View File

@@ -7,8 +7,10 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.math.Matrix4
import com.badlogic.gdx.utils.Disposable
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.UnsafeHelper
import net.torvald.UnsafePtr
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.toUint
import net.torvald.tsvm.FBM
import net.torvald.tsvm.LoadShader
@@ -17,6 +19,7 @@ import net.torvald.tsvm.kB
import net.torvald.tsvm.peripheral.GraphicsAdapter.Companion.DRAW_SHADER_FRAG
import java.io.InputStream
import java.io.OutputStream
import java.lang.IllegalArgumentException
import kotlin.experimental.and
data class AdapterConfig(
@@ -64,8 +67,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
protected val theme = config.theme
protected val TAB_SIZE = 8
internal val framebuffer = UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT)//Pixmap(WIDTH, HEIGHT, Pixmap.Format.Alpha)
internal val framebuffer2 = if (sgr.bankCount >= 2) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT) else null
internal val framebuffer = UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this)//Pixmap(WIDTH, HEIGHT, Pixmap.Format.Alpha)
internal val framebuffer2 = if (sgr.bankCount >= 2) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this) else null
internal val framebufferOut = Pixmap(WIDTH, HEIGHT, Pixmap.Format.RGBA8888)
protected var rendertex = Texture(1, 1, Pixmap.Format.RGBA8888)
internal val paletteOfFloats = FloatArray(1024) {
@@ -78,9 +81,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
protected var chrrom0 = Texture(1,1,Pixmap.Format.RGBA8888)
protected val faketex: Texture
internal val textArea = UnsafeHelper.allocate(7682)
internal val unusedArea = UnsafeHelper.allocate(1024)
internal val scanlineOffsets = UnsafeHelper.allocate(1024)
internal val textArea = UnsafeHelper.allocate(7682, this)
internal val unusedArea = UnsafeHelper.allocate(1024, this)
internal val scanlineOffsets = UnsafeHelper.allocate(1024, this)
protected val paletteShader = LoadShader(DRAW_SHADER_VERT, config.paletteShader)
protected val textShader = LoadShader(DRAW_SHADER_VERT, config.fragShader)
@@ -124,7 +127,7 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
// override var halfrowMode = false
private val instArea = UnsafeHelper.allocate(65536L)
private val instArea = UnsafeHelper.allocate(65536L, this)
override var rawCursorPos: Int
get() = textArea.getShortFree(memTextCursorPosOffset).toInt()
@@ -943,27 +946,31 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
}
}
fun Disposable.tryDispose() {
try { this.dispose() } catch (_: GdxRuntimeException) {} catch (_: IllegalArgumentException) {}
}
override fun dispose() {
//testTex.dispose()
try { framebuffer.destroy() } catch (_: GdxRuntimeException) {}
try { framebuffer2?.destroy() } catch (_: GdxRuntimeException) {}
try { framebufferOut.dispose() } catch (_: GdxRuntimeException) {}
rendertex.dispose()
// paletteShader.tryDispose()
// textShader.tryDispose()
framebuffer.destroy()
framebuffer2?.destroy()
framebufferOut.tryDispose()
rendertex.tryDispose()
textArea.destroy()
textForePixmap.dispose()
textBackPixmap.dispose()
textPixmap.dispose()
paletteShader.dispose()
textShader.dispose()
faketex.dispose()
outFBOs.forEach { it.dispose() }
outFBObatch.dispose()
textForePixmap.tryDispose()
textBackPixmap.tryDispose()
textPixmap.tryDispose()
faketex.tryDispose()
// outFBOs.forEach { it.tryDispose() }
outFBObatch.tryDispose()
try { textForeTex.dispose() } catch (_: GdxRuntimeException) {}
try { textBackTex.dispose() } catch (_: GdxRuntimeException) {}
textForeTex.tryDispose()
textBackTex.tryDispose()
chrrom0.dispose()
chrrom.dispose()
chrrom0.tryDispose()
chrrom.tryDispose()
unusedArea.destroy()
scanlineOffsets.destroy()
instArea.destroy()

View File

@@ -27,20 +27,20 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor {
private val keyboardBuffer = CircularArray<Byte>(32, true)
internal val blockTransferRx = arrayOf(
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096)
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this)
)
internal val blockTransferTx = arrayOf(
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096),
UnsafeHelper.allocate(4096)
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this),
UnsafeHelper.allocate(4096, this)
)
/*private*/ val blockTransferPorts = Array(4) { BlockTransferPort(vm, it) }
private val peripheralFast = UnsafeHelper.allocate(1024)
private val peripheralFast = UnsafeHelper.allocate(1024, this)
private val keyEventBuffers = ByteArray(8)

View File

@@ -1,7 +1,6 @@
package net.torvald.tsvm.peripheral
import com.badlogic.gdx.audio.AudioDevice
import com.badlogic.gdx.backends.lwjgl3.audio.OpenALAudioDevice
import com.badlogic.gdx.backends.lwjgl3.audio.OpenALLwjgl3Audio
import com.badlogic.gdx.math.MathUtils
import com.badlogic.gdx.utils.GdxRuntimeException
@@ -120,6 +119,14 @@ class OpenALBufferedAudioDevice(
freeSourceMethod.invoke(audio, sourceID)
}
private val alErrors = hashMapOf(
AL10.AL_INVALID_NAME to "AL_INVALID_NAME",
AL10.AL_INVALID_ENUM to "AL_INVALID_ENUM",
AL10.AL_INVALID_VALUE to "AL_INVALID_VALUE",
AL10.AL_INVALID_OPERATION to "AL_INVALID_OPERATION",
AL10.AL_OUT_OF_MEMORY to "AL_OUT_OF_MEMORY"
)
fun writeSamples(data: ByteArray, offset: Int, length: Int) {
var offset = offset
var length = length
@@ -129,8 +136,11 @@ class OpenALBufferedAudioDevice(
if (sourceID == -1) return
if (buffers == null) {
buffers = BufferUtils.createIntBuffer(bufferCount)
AL10.alGetError()
AL10.alGenBuffers(buffers)
if (AL10.alGetError() != AL10.AL_NO_ERROR) throw GdxRuntimeException("Unabe to allocate audio buffers.")
AL10.alGetError().let {
if (it != AL10.AL_NO_ERROR) throw GdxRuntimeException("Unabe to allocate audio buffers: ${alErrors[it]}")
}
}
AL10.alSourcei(sourceID, AL10.AL_LOOPING, AL10.AL_FALSE)
AL10.alSourcef(sourceID, AL10.AL_GAIN, volume)

View File

@@ -19,7 +19,7 @@ open class RamBank(val vm: VM, bankCount: Int) : PeriBase {
if (banks % 2 == 1) banks += 1
}
internal val mem = UnsafeHelper.allocate(bankSize * banks)
internal val mem = UnsafeHelper.allocate(bankSize * banks, this)
protected var map0 = 0
protected var map1 = 1

View File

@@ -16,7 +16,7 @@ class TTY(assetsRoot: String, val vm: VM) : GlassTty(TEXT_ROWS, TEXT_COLS), Peri
}
private val chrrom = Texture("$assetsRoot/tty.png")
private val textBuffer = UnsafeHelper.allocate(TEXT_ROWS * TEXT_COLS * 2L)
private val textBuffer = UnsafeHelper.allocate(TEXT_ROWS * TEXT_COLS * 2L, this)
override var rawCursorPos = 0
private val TEXT_AREA_SIZE = TEXT_COLS * TEXT_ROWS

View File

@@ -124,8 +124,8 @@ class Videotron2K(var gpu: GraphicsAdapter?) {
""".trimIndent()
}
internal var regs = UnsafeHelper.allocate(16 * 4)
internal var internalMem = UnsafeHelper.allocate(16384)
internal var regs = UnsafeHelper.allocate(16 * 4, this)
// internal var internalMem = UnsafeHelper.allocate(16384, this)
internal var callStack = Stack<Pair<Long, Int>>() // Pair of Scene-ID (has SCENE_PREFIX; 0 with no prefix for root scene) and ProgramCounter
/* Compile-time variables */