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.emulator.MonTanaMiniComputer.ComputerStatus
|
||||||
import mtmc.util.currentTimeMillis
|
import mtmc.util.currentTimeMillis
|
||||||
import mtmc.util.requestAnimationFrame
|
import mtmc.util.requestAnimationFrame
|
||||||
|
import mtmc.util.setTimeout
|
||||||
|
import mtmc.util.time
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
@@ -27,21 +29,22 @@ class MTMCClock(
|
|||||||
var frame = 0
|
var frame = 0
|
||||||
|
|
||||||
fun run() {
|
fun run() {
|
||||||
requestAnimationFrame { handleFrame(it) }
|
requestAnimationFrame { handleFrame() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun handleFrame(time: Double) {
|
fun handleFrame() {
|
||||||
// figure out how many instructions to execute this 'time' duration
|
// figure out how many instructions to execute this 'time' duration
|
||||||
// maximize time so we don't hang if the emulator is too slow
|
// maximize time so we don't hang if the emulator is too slow
|
||||||
|
val time = time()
|
||||||
if (lastFrame == 0.0) {
|
if (lastFrame == 0.0) {
|
||||||
lastFrame = time
|
lastFrame = time
|
||||||
requestAnimationFrame { handleFrame(it) }
|
requestAnimationFrame { handleFrame() }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val delta = time - lastFrame
|
val delta = time - lastFrame
|
||||||
lastFrame = time
|
lastFrame = time
|
||||||
|
|
||||||
val actualTime = min(delta / 1000.0, 0.0166)
|
val timeToProcess = min(delta, 16.0)
|
||||||
|
|
||||||
// assume 1Hz = 1 instruction/second
|
// assume 1Hz = 1 instruction/second
|
||||||
if (computer.getStatus() == ComputerStatus.EXECUTING) {
|
if (computer.getStatus() == ComputerStatus.EXECUTING) {
|
||||||
@@ -50,23 +53,28 @@ class MTMCClock(
|
|||||||
speed = 1L
|
speed = 1L
|
||||||
}
|
}
|
||||||
|
|
||||||
instructionsToRun += actualTime * speed
|
instructionsToRun += timeToProcess * speed / 1000.0
|
||||||
val pulse: Long = instructionsToRun.toLong()
|
val pulse: Long = instructionsToRun.toLong() + 1
|
||||||
instructionsToRun -= pulse
|
instructionsToRun -= pulse
|
||||||
|
|
||||||
val time = currentTimeMillis()
|
val start = time()
|
||||||
val ir = computer.pulse(pulse)
|
val ir = computer.pulse(pulse)
|
||||||
instructions += ir
|
instructions += ir
|
||||||
|
val duration = (time() - start)
|
||||||
|
val actual = ir / (delta / 1000.0)
|
||||||
if (frame % 100 == 0) {
|
if (frame % 100 == 0) {
|
||||||
val duration = currentTimeMillis() - time
|
println("Instructions ran: $ir (delta = ${delta.toFloat()}, timeToProcess = ${timeToProcess.toFloat()}, speed = $speed (actual=${actual.toLong()}), duration = $duration)")
|
||||||
println("Instructions ran: $ir (delta = ${delta.toFloat()}, actualTime = ${actualTime.toFloat()}, speed = $speed (actual=${(ir / delta * 1000).toLong()}), duration = $duration)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual += instructions
|
virtual += instructions
|
||||||
ips = (instructions / actualTime).toLong()
|
ips = (instructions / timeToProcess).toLong()
|
||||||
frame++
|
frame++
|
||||||
|
|
||||||
requestAnimationFrame { handleFrame(it) }
|
if (duration > timeToProcess) {
|
||||||
|
setTimeout({ handleFrame() })
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame { handleFrame() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")")
|
//println("Executed " + instructions + " instructions at a rate of " + ips + " ips (speed = " + speed + ")")
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class MonTanaMiniComputer {
|
|||||||
var clock: MTMCClock = MTMCClock(this)
|
var clock: MTMCClock = MTMCClock(this)
|
||||||
var fileSystem: FileSystem = FileSystem(this)
|
var fileSystem: FileSystem = FileSystem(this)
|
||||||
|
|
||||||
var rewindSteps = Array<RewindStep?>(MAX_REWIND_STEPS) { null }
|
var rewindSteps = Array(MAX_REWIND_STEPS) { RewindStep() }
|
||||||
var rewindIndex = -1
|
var rewindIndex = -1
|
||||||
|
|
||||||
// listeners
|
// listeners
|
||||||
@@ -133,11 +133,9 @@ class MonTanaMiniComputer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun fetchAndExecute() {
|
fun fetchAndExecute() {
|
||||||
currentRewindStep = RewindStep()
|
rewindIndex = (rewindIndex + 1) % rewindSteps.size
|
||||||
currentRewindStep?.let {
|
rewindSteps[rewindIndex].index = 0
|
||||||
rewindIndex = (rewindIndex + 1) % rewindSteps.size
|
|
||||||
rewindSteps.set(rewindIndex, it)
|
|
||||||
}
|
|
||||||
fetchCurrentInstruction()
|
fetchCurrentInstruction()
|
||||||
val instruction = getRegisterValue(Register.IR)
|
val instruction = getRegisterValue(Register.IR)
|
||||||
if (isDoubleWordInstruction(instruction)) {
|
if (isDoubleWordInstruction(instruction)) {
|
||||||
|
|||||||
@@ -3,13 +3,16 @@ package mtmc.emulator
|
|||||||
import mtmc.util.Runnable
|
import mtmc.util.Runnable
|
||||||
|
|
||||||
class RewindStep {
|
class RewindStep {
|
||||||
var subSteps: MutableList<Runnable?> = mutableListOf()
|
var subSteps: Array<Runnable> = Array(10) { {} }
|
||||||
|
var index = 0
|
||||||
|
|
||||||
fun rewind() {
|
fun rewind() {
|
||||||
subSteps.reversed().forEach({ obj: Runnable? -> obj!!.invoke() })
|
subSteps.reversed().forEach({ obj: Runnable? -> obj!!.invoke() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addSubStep(subStep: Runnable?) {
|
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 currentTimeMillis(): Double
|
||||||
|
|
||||||
|
expect fun time(): Double
|
||||||
|
|
||||||
expect fun requestAnimationFrame(action: (Double) -> Unit)
|
expect fun requestAnimationFrame(action: (Double) -> Unit)
|
||||||
|
|
||||||
|
expect fun setTimeout(action: () -> Unit)
|
||||||
|
|
||||||
expect fun immediateTimeout(action: (Double) -> Unit): Int
|
expect fun immediateTimeout(action: (Double) -> Unit): Int
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package mtmc
|
package mtmc
|
||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
|
import kotlinx.browser.window
|
||||||
import mtmc.emulator.MonTanaMiniComputer
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import mtmc.util.currentTimeMillis
|
||||||
import mtmc.view.DisplayView
|
import mtmc.view.DisplayView
|
||||||
import mtmc.view.MTMCView
|
import mtmc.view.MTMCView
|
||||||
import nl.astraeus.komp.Komponent
|
import nl.astraeus.komp.Komponent
|
||||||
@@ -21,4 +23,21 @@ fun main() {
|
|||||||
|
|
||||||
mainView.requestUpdate()
|
mainView.requestUpdate()
|
||||||
display.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
|
package mtmc.util
|
||||||
|
|
||||||
import kotlinx.browser.window
|
import kotlinx.browser.window
|
||||||
import mtmc.display
|
|
||||||
import mtmc.mainView
|
|
||||||
import kotlin.js.Date
|
import kotlin.js.Date
|
||||||
|
|
||||||
var lastMemoryUpdate = currentTimeMillis()
|
|
||||||
var updateState = true
|
|
||||||
|
|
||||||
actual fun currentTimeMillis(): Double = Date().getTime()
|
actual fun currentTimeMillis(): Double = Date().getTime()
|
||||||
actual fun requestAnimationFrame(action: (Double) -> Unit) {
|
actual fun requestAnimationFrame(action: (Double) -> Unit) {
|
||||||
window.requestAnimationFrame {
|
window.requestAnimationFrame {
|
||||||
action(it)
|
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 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.display
|
||||||
import mtmc.emulator.MonTanaMiniComputer
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
import mtmc.mainView
|
import mtmc.mainView
|
||||||
import mtmc.util.updateState
|
import mtmc.updateState
|
||||||
import nl.astraeus.komp.HtmlBuilder
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
import nl.astraeus.komp.Komponent
|
import nl.astraeus.komp.Komponent
|
||||||
import org.w3c.dom.HTMLSelectElement
|
import org.w3c.dom.HTMLSelectElement
|
||||||
|
|||||||
@@ -5,4 +5,8 @@ actual fun requestAnimationFrame(action: (Double) -> Unit) {
|
|||||||
error("requestAnimationFrame is not supported on JVM")
|
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