generated from rnentjes/kotlin-server-web-undertow
Refactor PlatformSpecific functions with time and setTimeout, optimize RewindStep substeps handling, update MTMCClock timing logic, enhance frame processing, and integrate updateJsDisplay for dynamic updates in Main.
This commit is contained in:
@@ -3,6 +3,8 @@ package mtmc.emulator
|
||||
import mtmc.emulator.MonTanaMiniComputer.ComputerStatus
|
||||
import mtmc.util.currentTimeMillis
|
||||
import mtmc.util.requestAnimationFrame
|
||||
import mtmc.util.setTimeout
|
||||
import mtmc.util.time
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -27,21 +29,22 @@ class MTMCClock(
|
||||
var frame = 0
|
||||
|
||||
fun run() {
|
||||
requestAnimationFrame { handleFrame(it) }
|
||||
requestAnimationFrame { handleFrame() }
|
||||
}
|
||||
|
||||
fun handleFrame(time: Double) {
|
||||
fun handleFrame() {
|
||||
// figure out how many instructions to execute this 'time' duration
|
||||
// maximize time so we don't hang if the emulator is too slow
|
||||
val time = time()
|
||||
if (lastFrame == 0.0) {
|
||||
lastFrame = time
|
||||
requestAnimationFrame { handleFrame(it) }
|
||||
requestAnimationFrame { handleFrame() }
|
||||
return
|
||||
}
|
||||
val delta = time - lastFrame
|
||||
lastFrame = time
|
||||
|
||||
val actualTime = min(delta / 1000.0, 0.0166)
|
||||
val timeToProcess = min(delta, 16.0)
|
||||
|
||||
// assume 1Hz = 1 instruction/second
|
||||
if (computer.getStatus() == ComputerStatus.EXECUTING) {
|
||||
@@ -50,23 +53,28 @@ class MTMCClock(
|
||||
speed = 1L
|
||||
}
|
||||
|
||||
instructionsToRun += actualTime * speed
|
||||
val pulse: Long = instructionsToRun.toLong()
|
||||
instructionsToRun += timeToProcess * speed / 1000.0
|
||||
val pulse: Long = instructionsToRun.toLong() + 1
|
||||
instructionsToRun -= pulse
|
||||
|
||||
val time = currentTimeMillis()
|
||||
val start = time()
|
||||
val ir = computer.pulse(pulse)
|
||||
instructions += ir
|
||||
val duration = (time() - start)
|
||||
val actual = ir / (delta / 1000.0)
|
||||
if (frame % 100 == 0) {
|
||||
val duration = currentTimeMillis() - time
|
||||
println("Instructions ran: $ir (delta = ${delta.toFloat()}, actualTime = ${actualTime.toFloat()}, speed = $speed (actual=${(ir / delta * 1000).toLong()}), duration = $duration)")
|
||||
println("Instructions ran: $ir (delta = ${delta.toFloat()}, timeToProcess = ${timeToProcess.toFloat()}, speed = $speed (actual=${actual.toLong()}), duration = $duration)")
|
||||
}
|
||||
|
||||
virtual += instructions
|
||||
ips = (instructions / actualTime).toLong()
|
||||
ips = (instructions / timeToProcess).toLong()
|
||||
frame++
|
||||
|
||||
requestAnimationFrame { handleFrame(it) }
|
||||
if (duration > timeToProcess) {
|
||||
setTimeout({ handleFrame() })
|
||||
} else {
|
||||
requestAnimationFrame { handleFrame() }
|
||||
}
|
||||
}
|
||||
|
||||
//println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")")
|
||||
|
||||
@@ -32,7 +32,7 @@ class MonTanaMiniComputer {
|
||||
var clock: MTMCClock = MTMCClock(this)
|
||||
var fileSystem: FileSystem = FileSystem(this)
|
||||
|
||||
var rewindSteps = Array<RewindStep?>(MAX_REWIND_STEPS) { null }
|
||||
var rewindSteps = Array(MAX_REWIND_STEPS) { RewindStep() }
|
||||
var rewindIndex = -1
|
||||
|
||||
// listeners
|
||||
@@ -133,11 +133,9 @@ class MonTanaMiniComputer {
|
||||
}
|
||||
|
||||
fun fetchAndExecute() {
|
||||
currentRewindStep = RewindStep()
|
||||
currentRewindStep?.let {
|
||||
rewindIndex = (rewindIndex + 1) % rewindSteps.size
|
||||
rewindSteps.set(rewindIndex, it)
|
||||
}
|
||||
rewindIndex = (rewindIndex + 1) % rewindSteps.size
|
||||
rewindSteps[rewindIndex].index = 0
|
||||
|
||||
fetchCurrentInstruction()
|
||||
val instruction = getRegisterValue(Register.IR)
|
||||
if (isDoubleWordInstruction(instruction)) {
|
||||
|
||||
@@ -3,13 +3,16 @@ package mtmc.emulator
|
||||
import mtmc.util.Runnable
|
||||
|
||||
class RewindStep {
|
||||
var subSteps: MutableList<Runnable?> = mutableListOf()
|
||||
var subSteps: Array<Runnable> = Array(10) { {} }
|
||||
var index = 0
|
||||
|
||||
fun rewind() {
|
||||
subSteps.reversed().forEach({ obj: Runnable? -> obj!!.invoke() })
|
||||
}
|
||||
|
||||
fun addSubStep(subStep: Runnable?) {
|
||||
subSteps.add(subStep)
|
||||
if (subStep != null && index < subSteps.size) {
|
||||
subSteps[index++] = subStep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package mtmc.util
|
||||
|
||||
expect fun currentTimeMillis(): Double
|
||||
|
||||
expect fun time(): Double
|
||||
|
||||
expect fun requestAnimationFrame(action: (Double) -> Unit)
|
||||
|
||||
expect fun setTimeout(action: () -> Unit)
|
||||
|
||||
expect fun immediateTimeout(action: (Double) -> Unit): Int
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package mtmc
|
||||
|
||||
import kotlinx.browser.document
|
||||
import kotlinx.browser.window
|
||||
import mtmc.emulator.MonTanaMiniComputer
|
||||
import mtmc.util.currentTimeMillis
|
||||
import mtmc.view.DisplayView
|
||||
import mtmc.view.MTMCView
|
||||
import nl.astraeus.komp.Komponent
|
||||
@@ -21,4 +23,21 @@ fun main() {
|
||||
|
||||
mainView.requestUpdate()
|
||||
display.requestUpdate()
|
||||
|
||||
window.requestAnimationFrame { updateJsDisplay() }
|
||||
}
|
||||
|
||||
var lastMemoryUpdate = currentTimeMillis()
|
||||
var updateState = true
|
||||
|
||||
fun updateJsDisplay() {
|
||||
display.requestUpdate()
|
||||
if (currentTimeMillis() - lastMemoryUpdate > 125) {
|
||||
if (updateState) {
|
||||
mainView.registerView.requestUpdate()
|
||||
mainView.memoryView.requestUpdate()
|
||||
}
|
||||
lastMemoryUpdate = currentTimeMillis()
|
||||
}
|
||||
window.requestAnimationFrame { updateJsDisplay() }
|
||||
}
|
||||
|
||||
@@ -1,27 +1,19 @@
|
||||
package mtmc.util
|
||||
|
||||
import kotlinx.browser.window
|
||||
import mtmc.display
|
||||
import mtmc.mainView
|
||||
import kotlin.js.Date
|
||||
|
||||
var lastMemoryUpdate = currentTimeMillis()
|
||||
var updateState = true
|
||||
|
||||
actual fun currentTimeMillis(): Double = Date().getTime()
|
||||
actual fun requestAnimationFrame(action: (Double) -> Unit) {
|
||||
window.requestAnimationFrame {
|
||||
action(it)
|
||||
|
||||
display.requestUpdate()
|
||||
if (currentTimeMillis() - lastMemoryUpdate > 125) {
|
||||
if (updateState) {
|
||||
mainView.registerView.requestUpdate()
|
||||
mainView.memoryView.requestUpdate()
|
||||
}
|
||||
lastMemoryUpdate = currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
actual fun immediateTimeout(action: (Double) -> Unit): Int = window.setTimeout(action, 0)
|
||||
|
||||
actual fun time(): Double = window.performance.now()
|
||||
|
||||
actual fun setTimeout(action: () -> Unit) {
|
||||
window.setTimeout(action)
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import kotlinx.html.span
|
||||
import mtmc.display
|
||||
import mtmc.emulator.MonTanaMiniComputer
|
||||
import mtmc.mainView
|
||||
import mtmc.util.updateState
|
||||
import mtmc.updateState
|
||||
import nl.astraeus.komp.HtmlBuilder
|
||||
import nl.astraeus.komp.Komponent
|
||||
import org.w3c.dom.HTMLSelectElement
|
||||
|
||||
@@ -5,4 +5,8 @@ actual fun requestAnimationFrame(action: (Double) -> Unit) {
|
||||
error("requestAnimationFrame is not supported on JVM")
|
||||
}
|
||||
|
||||
actual fun immediateTimeout(action: (Double) -> Unit): Int = 0
|
||||
actual fun immediateTimeout(action: (Double) -> Unit): Int = 0
|
||||
|
||||
actual fun time(): Double = System.nanoTime() * 1000.0
|
||||
|
||||
actual fun setTimeout(action: () -> Unit) {}
|
||||
Reference in New Issue
Block a user