generated from rnentjes/kotlin-server-web-undertow
Add MemoryView component for memory rendering, refactor BufferedImage for RGB manipulation, and cleanup unused methods and comments in several classes.
This commit is contained in:
@@ -1,28 +1,26 @@
|
|||||||
package mtmc.emulator
|
package mtmc.emulator
|
||||||
|
|
||||||
class BufferedImage(width: Int, height: Int, type: Int) {
|
class BufferedImage(
|
||||||
fun getWidth(): Int {
|
val width: Int,
|
||||||
TODO("Not yet implemented")
|
val height: Int,
|
||||||
}
|
val type: Int
|
||||||
|
) {
|
||||||
fun getHeight(): Int {
|
val display = ByteArray(width * height * 4)
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getRGB(x: Int, y: Int): Int {
|
fun getRGB(x: Int, y: Int): Int {
|
||||||
TODO("Not yet implemented")
|
return display[x * 4 + y * width * 4 + 0].toInt() +
|
||||||
}
|
display[x * 4 + y * width * 4 + 1].toInt() shl 8 +
|
||||||
|
display[x * 4 + y * width * 4 + 2].toInt() shl 16
|
||||||
fun getType(): Int {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setRGB(x: Int, y: Int, intVal: Int) {
|
fun setRGB(x: Int, y: Int, intVal: Int) {
|
||||||
TODO("Not yet implemented")
|
display[x * 4 + y * width * 4 + 0] = intVal.toByte()
|
||||||
|
display[x * 4 + y * width * 4 + 1] = (intVal shr 8).toByte()
|
||||||
|
display[x * 4 + y * width * 4 + 2] = (intVal shr 16).toByte()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Dimension(
|
class Dimension(
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int
|
val height: Int
|
||||||
)
|
)
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -67,7 +67,6 @@ class MonTanaMiniComputer {
|
|||||||
// reset memory
|
// reset memory
|
||||||
initMemory()
|
initMemory()
|
||||||
|
|
||||||
|
|
||||||
val codeBoundary = code.size
|
val codeBoundary = code.size
|
||||||
code.copyInto(memory, 0, 0, codeBoundary)
|
code.copyInto(memory, 0, 0, codeBoundary)
|
||||||
setRegisterValue(Register.CB, codeBoundary - 1)
|
setRegisterValue(Register.CB, codeBoundary - 1)
|
||||||
@@ -843,7 +842,7 @@ class MonTanaMiniComputer {
|
|||||||
breakpoints[address] = (if (active) 1.toByte() else 0.toByte())
|
breakpoints[address] = (if (active) 1.toByte() else 0.toByte())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun start() {
|
fun start() {
|
||||||
console.start() // start the interactive console
|
console.start() // start the interactive console
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,16 +1010,8 @@ class MonTanaMiniComputer {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
val isMcp = getBits(16, 8, instruction) == 5.toShort()
|
val isMcp = getBits(16, 8, instruction) == 5.toShort()
|
||||||
if (isMcp) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
return isMcp
|
||||||
val computer = MonTanaMiniComputer()
|
|
||||||
computer.speed = 1 // default to 1hz
|
|
||||||
computer.start()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,17 +2,28 @@ package mtmc
|
|||||||
|
|
||||||
import kotlinx.browser.document
|
import kotlinx.browser.document
|
||||||
import kotlinx.html.div
|
import kotlinx.html.div
|
||||||
|
import kotlinx.html.style
|
||||||
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import mtmc.view.MTMCView
|
||||||
import nl.astraeus.komp.HtmlBuilder
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
import nl.astraeus.komp.Komponent
|
import nl.astraeus.komp.Komponent
|
||||||
|
|
||||||
class HelloKomponent : Komponent() {
|
class HelloKomponent : Komponent() {
|
||||||
override fun HtmlBuilder.render() {
|
override fun HtmlBuilder.render() {
|
||||||
div {
|
div {
|
||||||
|
style = "color: red;"
|
||||||
+ "Hello, world!"
|
+ "Hello, world!"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
Komponent.create(document.body!!, HelloKomponent())
|
val computer = MonTanaMiniComputer()
|
||||||
|
computer.speed = 1 // default to 1hz
|
||||||
|
|
||||||
|
val view = MTMCView(computer)
|
||||||
|
Komponent.create(document.body!!, view)
|
||||||
|
|
||||||
|
computer.start()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/jsMain/kotlin/mtmc/view/ControlView.kt
Normal file
19
src/jsMain/kotlin/mtmc/view/ControlView.kt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package mtmc.view
|
||||||
|
|
||||||
|
import kotlinx.html.div
|
||||||
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
|
import nl.astraeus.komp.Komponent
|
||||||
|
|
||||||
|
class ControlView(
|
||||||
|
val computer: MonTanaMiniComputer
|
||||||
|
) : Komponent() {
|
||||||
|
|
||||||
|
override fun HtmlBuilder.render() {
|
||||||
|
div {
|
||||||
|
+"Controls view"
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
36
src/jsMain/kotlin/mtmc/view/MTMCView.kt
Normal file
36
src/jsMain/kotlin/mtmc/view/MTMCView.kt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package mtmc.view
|
||||||
|
|
||||||
|
import kotlinx.html.div
|
||||||
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
|
import nl.astraeus.komp.Komponent
|
||||||
|
|
||||||
|
class MTMCView(
|
||||||
|
val computer: MonTanaMiniComputer
|
||||||
|
) : Komponent() {
|
||||||
|
val controlView = ControlView(computer)
|
||||||
|
val registerView = RegisterView(computer)
|
||||||
|
val memoryView = MemoryView(computer)
|
||||||
|
|
||||||
|
override fun HtmlBuilder.render() {
|
||||||
|
div("container") {
|
||||||
|
div("left-column") {
|
||||||
|
include(controlView)
|
||||||
|
include(registerView)
|
||||||
|
include(memoryView)
|
||||||
|
}
|
||||||
|
div("middle-column") {
|
||||||
|
div {
|
||||||
|
+"Console"
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
+"Shell"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div("right-column") {
|
||||||
|
+"Files"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
40
src/jsMain/kotlin/mtmc/view/MemoryView.kt
Normal file
40
src/jsMain/kotlin/mtmc/view/MemoryView.kt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package mtmc.view
|
||||||
|
|
||||||
|
import kotlinx.html.div
|
||||||
|
import kotlinx.html.table
|
||||||
|
import kotlinx.html.td
|
||||||
|
import kotlinx.html.tr
|
||||||
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
|
import nl.astraeus.komp.Komponent
|
||||||
|
|
||||||
|
fun ByteArray.asHex(address: Int): String {
|
||||||
|
val value = this[address].toInt() + this[address + 1].toInt() * 256
|
||||||
|
return value.toShort().toHexString()
|
||||||
|
}
|
||||||
|
|
||||||
|
class MemoryView(
|
||||||
|
val computer: MonTanaMiniComputer
|
||||||
|
) : Komponent() {
|
||||||
|
|
||||||
|
override fun HtmlBuilder.render() {
|
||||||
|
div("memory-panel") {
|
||||||
|
div("memory-header") {
|
||||||
|
+"Memory"
|
||||||
|
}
|
||||||
|
div("memory") {
|
||||||
|
table {
|
||||||
|
for (address in 0..<computer.memory.size step 16) {
|
||||||
|
tr {
|
||||||
|
for (offset in 0..<8) {
|
||||||
|
td {
|
||||||
|
+computer.memory.asHex(address + offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/jsMain/kotlin/mtmc/view/RegisterView.kt
Normal file
70
src/jsMain/kotlin/mtmc/view/RegisterView.kt
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package mtmc.view
|
||||||
|
|
||||||
|
import kotlinx.html.TABLE
|
||||||
|
import kotlinx.html.classes
|
||||||
|
import kotlinx.html.div
|
||||||
|
import kotlinx.html.hr
|
||||||
|
import kotlinx.html.table
|
||||||
|
import kotlinx.html.td
|
||||||
|
import kotlinx.html.tr
|
||||||
|
import mtmc.emulator.MonTanaMiniComputer
|
||||||
|
import mtmc.emulator.Register
|
||||||
|
import nl.astraeus.komp.HtmlBuilder
|
||||||
|
import nl.astraeus.komp.Komponent
|
||||||
|
|
||||||
|
class RegisterView(
|
||||||
|
val computer: MonTanaMiniComputer
|
||||||
|
) : Komponent() {
|
||||||
|
|
||||||
|
override fun HtmlBuilder.render() {
|
||||||
|
div {
|
||||||
|
+"Register view"
|
||||||
|
|
||||||
|
table("register-table") {
|
||||||
|
for (index in 0..<16) {
|
||||||
|
showRegister(index)
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
td {
|
||||||
|
colSpan = "3"
|
||||||
|
hr {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
showRegister(16)
|
||||||
|
showRegister(17)
|
||||||
|
tr {
|
||||||
|
td {
|
||||||
|
colSpan = "3"
|
||||||
|
+"Flags"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TABLE.showRegister(register: Int) {
|
||||||
|
val name = Register.fromInteger(register)
|
||||||
|
val value = computer.registerFile[register]
|
||||||
|
tr {
|
||||||
|
td {
|
||||||
|
+name
|
||||||
|
}
|
||||||
|
td("register-lights") {
|
||||||
|
for (bit in 15 downTo 0) {
|
||||||
|
div("blinken") {
|
||||||
|
if (value.toInt() and (1 shl bit) == 0) {
|
||||||
|
classes += "off"
|
||||||
|
}
|
||||||
|
if (bit % 4 == 0) {
|
||||||
|
classes += "space"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
td("align-right") {
|
||||||
|
+"$value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
124
src/jsMain/resources/mtmc.css
Normal file
124
src/jsMain/resources/mtmc.css
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overscroll-behavior: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 450px 450px 1fr;
|
||||||
|
grid-template-rows: 1fr;
|
||||||
|
overflow-y: auto;
|
||||||
|
gap: 5px;
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-column {
|
||||||
|
grid-template-rows: auto auto minmax(0, 1fr);
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 4px;
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
min-width: 450px;
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.middle-column {
|
||||||
|
background-color: #eee;
|
||||||
|
grid-template-rows: auto minmax(0, 1fr);
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 4px;
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
min-width: 450px;
|
||||||
|
max-width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-column {
|
||||||
|
background-color: #eee;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 4px;
|
||||||
|
height: 100dvh;
|
||||||
|
max-height: 100dvh;
|
||||||
|
min-width: 450px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* registers */
|
||||||
|
|
||||||
|
table.register-table {
|
||||||
|
font-family: monospace;
|
||||||
|
width: 100%;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.register-table tr td .align-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.register-table tr td.register-lights {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blinken {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 2px;
|
||||||
|
height: 6px;
|
||||||
|
width: 6px;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 3px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blinken.off {
|
||||||
|
background-color: #5c0119;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blinken.space {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* memory */
|
||||||
|
|
||||||
|
.memory-panel {
|
||||||
|
background-color: #eee;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory-header {
|
||||||
|
font-family: monospace;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
/* overflow: auto; */
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.memory {
|
||||||
|
font-family: monospace;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* console */
|
||||||
|
|
||||||
|
.small-button {
|
||||||
|
transform: rotate(-25deg) translateY(20px) translateX(-20px);
|
||||||
|
margin: 2px;
|
||||||
|
width: 50px;
|
||||||
|
background-color: #7e777b;
|
||||||
|
border: 1px solid dimgray;
|
||||||
|
border-radius: 8px;
|
||||||
|
color: whitesmoke;
|
||||||
|
box-shadow: rgb(0, 0, 0, .2) 2px 2px 1px 1px;
|
||||||
|
}
|
||||||
@@ -7,9 +7,9 @@ import io.undertow.predicate.Predicates
|
|||||||
import io.undertow.server.handlers.encoding.ContentEncodingRepository
|
import io.undertow.server.handlers.encoding.ContentEncodingRepository
|
||||||
import io.undertow.server.handlers.encoding.EncodingHandler
|
import io.undertow.server.handlers.encoding.EncodingHandler
|
||||||
import io.undertow.server.handlers.encoding.GzipEncodingProvider
|
import io.undertow.server.handlers.encoding.GzipEncodingProvider
|
||||||
import nl.astraeus.logger.Logger
|
|
||||||
import mtmc.db.Database
|
import mtmc.db.Database
|
||||||
import mtmc.web.RequestHandler
|
import mtmc.web.RequestHandler
|
||||||
|
import nl.astraeus.logger.Logger
|
||||||
|
|
||||||
val log = Logger()
|
val log = Logger()
|
||||||
|
|
||||||
@@ -58,7 +58,6 @@ fun main() {
|
|||||||
.setServerOption(UndertowOptions.SHUTDOWN_TIMEOUT, 1000)
|
.setServerOption(UndertowOptions.SHUTDOWN_TIMEOUT, 1000)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
println("Starting undertow server at port 6007...")
|
println("Starting undertow server at port $SERVER_PORT...")
|
||||||
server?.start()
|
server?.start()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mtmc.web
|
|||||||
import kotlinx.html.body
|
import kotlinx.html.body
|
||||||
import kotlinx.html.head
|
import kotlinx.html.head
|
||||||
import kotlinx.html.html
|
import kotlinx.html.html
|
||||||
|
import kotlinx.html.link
|
||||||
import kotlinx.html.meta
|
import kotlinx.html.meta
|
||||||
import kotlinx.html.script
|
import kotlinx.html.script
|
||||||
import kotlinx.html.stream.appendHTML
|
import kotlinx.html.stream.appendHTML
|
||||||
@@ -18,7 +19,7 @@ fun generateIndex(patch: String?): String {
|
|||||||
result.appendHTML(true).html {
|
result.appendHTML(true).html {
|
||||||
head {
|
head {
|
||||||
title(pageTitle)
|
title(pageTitle)
|
||||||
//link("/css/all.min.css", "stylesheet")
|
link("/mtmc.css", "stylesheet")
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
script(src = "/$repoName.js") {}
|
script(src = "/$repoName.js") {}
|
||||||
|
|||||||
Reference in New Issue
Block a user