Refactor PlatformSpecific, update MonTanaMiniComputer and MTMCDisplay logic, add splash screen rendering with SplashData, and optimize observer calls and color initialization.

This commit is contained in:
2025-08-18 11:36:42 +02:00
parent 37691dc7fa
commit 8457d3a854
7 changed files with 1829 additions and 25 deletions

View File

@@ -18,13 +18,8 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
LIGHT(87, 124, 68), LIGHT(87, 124, 68),
LIGHTEST(127, 134, 15); LIGHTEST(127, 134, 15);
val intVal: Int val intVal: Int = 0xFF shl 24 or (r shl 16) or (g shl 8) or b
val javaColor: Color val javaColor: Color = Color(r, g, b)
init {
this.intVal = 0xFF shl 24 or (r shl 16) or (g shl 8) or b
javaColor = Color(r, g, b)
}
fun distance(r: Int, g: Int, b: Int): Int { fun distance(r: Int, g: Int, b: Int): Int {
val dr = this.r - r val dr = this.r - r
@@ -56,15 +51,20 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
} }
private fun loadSplashScreen() { private fun loadSplashScreen() {
/* try { currentColor = DisplayColor.DARK
val bytes: ByteArray = Base64.getDecoder().decode(SPLASH_SCREEN) var currentColorCount = 0
val bais = ByteArrayInputStream(bytes) var currentColor = 0
var img: BufferedImage? = null var colorIndex = 0
img = ImageIO.read(bais) for (col in 0..<COLS) {
loadScaledImage(img) for (row in 0..<ROWS) {
} catch (e: IOException) { if (currentColorCount == 0) {
e.printStackTrace() currentColorCount = SPLASH_SCREEN_COLORS[colorIndex++]
}*/ currentColor = SPLASH_SCREEN_COLORS[colorIndex++]
}
setPixel(col, row, DisplayColor.entries[currentColor])
currentColorCount--
}
}
} }
private fun loadImage(data: ByteArray): BufferedImage? { private fun loadImage(data: ByteArray): BufferedImage? {
@@ -107,7 +107,11 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
} }
fun setPixel(col: Int, row: Int, color: DisplayColor) { fun setPixel(col: Int, row: Int, color: DisplayColor) {
buffer.setRGB(col, row, color.intVal) try {
buffer.setRGB(col, row, color.intVal)
} catch (e: Throwable) {
throw e
}
} }
fun getPixel(col: Int, row: Int): Short { fun getPixel(col: Int, row: Int): Short {
@@ -173,7 +177,7 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
//computer.notifyOfDisplayUpdate() //computer.notifyOfDisplayUpdate()
} }
fun toPng(): ByteArray? { fun toPng(): ByteArray {
return byteArray return byteArray
} }

View File

@@ -48,7 +48,6 @@ class MonTanaMiniComputer {
registerFile = ShortArray(Register.entries.size) registerFile = ShortArray(Register.entries.size)
memory = ByteArray(MEMORY_SIZE) memory = ByteArray(MEMORY_SIZE)
breakpoints = ByteArray(MEMORY_SIZE) breakpoints = ByteArray(MEMORY_SIZE)
rewindIndex = -1
setRegisterValue( setRegisterValue(
Register.SP, Register.SP,
MEMORY_SIZE.toShort().toInt() MEMORY_SIZE.toShort().toInt()
@@ -792,7 +791,7 @@ class MonTanaMiniComputer {
val currentValue = memory[address] val currentValue = memory[address]
addRewindStep { memory[address] = currentValue } addRewindStep { memory[address] = currentValue }
memory[address] = value memory[address] = value
observers!!.forEach { o: MTMCObserver? -> observers.forEach { o: MTMCObserver? ->
o!!.memoryUpdated(address, value) o!!.memoryUpdated(address, value)
} }
} }
@@ -816,7 +815,7 @@ class MonTanaMiniComputer {
registerFile[register] = currentValue registerFile[register] = currentValue
} }
registerFile[register] = value.toShort() registerFile[register] = value.toShort()
observers!!.forEach { o: MTMCObserver? -> observers.forEach { o: MTMCObserver? ->
o!!.registerUpdated(register, value) o!!.registerUpdated(register, value)
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -11,12 +11,14 @@ val mainView = MTMCView(computer)
val display = DisplayView(computer) val display = DisplayView(computer)
fun main() { fun main() {
computer.speed = 2000000 // default to 1hz computer.speed = 1000000
computer.load(lifeCode, lifeData) computer.load(lifeCode, lifeData)
//computer.load(snakeCode, snakeData)
Komponent.create(document.body!!, mainView) Komponent.create(document.body!!, mainView)
computer.start() computer.start()
mainView.requestUpdate() mainView.requestUpdate()
display.requestUpdate()
} }

View File

@@ -13,7 +13,7 @@ actual fun requestAnimationFrame(action: (Double) -> Unit) {
action(it) action(it)
display.requestUpdate() display.requestUpdate()
if (currentTimeMillis() - lastMemoryUpdate > 100) { if (currentTimeMillis() - lastMemoryUpdate > 125) {
mainView.registerView.requestUpdate() mainView.registerView.requestUpdate()
mainView.memoryView.requestUpdate() mainView.memoryView.requestUpdate()
lastMemoryUpdate = currentTimeMillis() lastMemoryUpdate = currentTimeMillis()

View File

@@ -1,18 +1,69 @@
package mtmc.view package mtmc.view
import kotlinx.html.div import kotlinx.html.div
import kotlinx.html.i
import kotlinx.html.span
import mtmc.emulator.MonTanaMiniComputer import mtmc.emulator.MonTanaMiniComputer
import nl.astraeus.komp.HtmlBuilder import nl.astraeus.komp.HtmlBuilder
import nl.astraeus.komp.Komponent import nl.astraeus.komp.Komponent
import kotlin.text.Typography.nbsp
class ControlView( class ControlView(
val computer: MonTanaMiniComputer val computer: MonTanaMiniComputer
) : Komponent() { ) : Komponent() {
override fun HtmlBuilder.render() { override fun HtmlBuilder.render() {
div { /*
+"Controls view" <div id="control-secondary">
MonTana Mini-Computer
</div>
<div id="control-buttons">
<label>
<select style="font-family: monospace;background-color: black;color: #ffcc00" name="speed" fx-action="/speed" fx-method="post" fx-swap="outerHTML" fx-target="#controls">
<option value="1">1 Hz</option>
<option value="10">10 Hz</option>
<option value="100">100 Hz</option>
<option value="1000">1 Khz</option>
<option value="1000000" selected="">1 Mhz</option>
</select>
</label>
<button fx-action="/control/run" fx-method="post" fx-swap="none">
run
</button>
<button fx-action="/control/back" fx-method="post" fx-swap="outerHTML" fx-target="#controls" disabled="disabled">
back
</button>
<button fx-action="/control/step" fx-method="post" fx-swap="outerHTML" fx-target="#controls">
step
</button>
<button fx-action="/control/reset" fx-method="post" fx-swap="outerHTML" fx-target="#controls">
reset
</button>
</div>
*/
div("control-panel") {
div("control-header") {
span {
+"m"
}
span {
+"s"
}
span {
+"u"
}
nbsp
i {
+"MTMC-16"
}
}
div("control-secondary") {
}
div("control-buttons") {
}
} }
} }

View File

@@ -1,3 +1,12 @@
root {
--pdp-blue: #243571;
--pdp-light-blue: #3286ce;
--pdp-beige: #fdfddc;
--pdp-white: #f1f1f6;
--pdp-off-white: #F0EBCD;
--filetree-gray: #666;
}
html, body { html, body {
padding: 0; padding: 0;
margin: 0; margin: 0;
@@ -52,6 +61,18 @@ body {
text-align: right; text-align: right;
} }
/* control */
.control-header {
background-color: var(--pdp-blue);
color: var(--pdp-white);
font-family: monospace;
font-size: 32px;
padding: 4px 24px;
margin-left: 0;
margin-right: 0;
}
/* registers */ /* registers */
table.register-table { table.register-table {