Add platform-specific requestAnimationFrame, refactor redundant string accessor methods, and introduce BufferedImage and Color classes for emulator graphics rendering.

This commit is contained in:
2025-08-14 16:49:39 +02:00
parent c7552c2a95
commit 9f295b2fb9
16 changed files with 215 additions and 175 deletions

View File

@@ -1,22 +1,13 @@
package mtmc.emulator
import java.awt.Color
import java.awt.Dimension
import java.awt.RenderingHints
import java.awt.image.BufferedImage
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.util.*
import javax.imageio.ImageIO
import kotlin.math.min
class MTMCDisplay(private val computer: MonTanaMiniComputer) {
private val buffer = BufferedImage(
COLS,
ROWS,
BufferedImage.TYPE_INT_ARGB
)
1
) // BufferedImage.TYPE_INT_ARGB
private var currentColor: DisplayColor? = null
private var graphics: Array<BufferedImage> = arrayOf()
private var byteArray: ByteArray = ByteArray(0)
@@ -69,24 +60,25 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
}
private fun loadSplashScreen() {
try {
val bytes: ByteArray = Base64.getDecoder().decode(SPLASH_SCREEN)
val bais = ByteArrayInputStream(bytes)
var img: BufferedImage? = null
img = ImageIO.read(bais)
loadScaledImage(img)
} catch (e: IOException) {
e.printStackTrace()
}
/* try {
val bytes: ByteArray = Base64.getDecoder().decode(SPLASH_SCREEN)
val bais = ByteArrayInputStream(bytes)
var img: BufferedImage? = null
img = ImageIO.read(bais)
loadScaledImage(img)
} catch (e: IOException) {
e.printStackTrace()
}*/
}
private fun loadImage(data: ByteArray): BufferedImage? {
try {
return ImageIO.read(ByteArrayInputStream(data))
} catch (e: IOException) {
e.printStackTrace()
throw IllegalStateException(e)
}
/* try {
return ImageIO.read(ByteArrayInputStream(data))
} catch (e: IOException) {
e.printStackTrace()
throw IllegalStateException(e)
}*/
return null
}
fun loadGraphics(data: Array<ByteArray>) {
@@ -96,7 +88,7 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
}
graphics = Array(data.size) { index ->
loadImage(data[index]) ?: BufferedImage(160, 144, BufferedImage.TYPE_INT_RGB)
loadImage(data[index]) ?: BufferedImage(160, 144, 1) //BufferedImage.TYPE_INT_RGB)
}
}
@@ -128,31 +120,31 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
}
fun drawLine(startCol: Short, startRow: Short, endCol: Short, endRow: Short) {
val graphics = buffer.getGraphics()
graphics.setColor(currentColor!!.javaColor)
graphics.drawLine(startCol.toInt(), startRow.toInt(), endCol.toInt(), endRow.toInt())
graphics.dispose()
// val graphics = buffer.getGraphics()
// graphics.setColor(currentColor!!.javaColor)
// graphics.drawLine(startCol.toInt(), startRow.toInt(), endCol.toInt(), endRow.toInt())
// graphics.dispose()
}
fun drawRectangle(startCol: Short, startRow: Short, width: Short, height: Short) {
val graphics = buffer.getGraphics()
graphics.setColor(currentColor!!.javaColor)
graphics.fillRect(startCol.toInt(), startRow.toInt(), width.toInt(), height.toInt())
graphics.dispose()
// val graphics = buffer.getGraphics()
// graphics.setColor(currentColor!!.javaColor)
// graphics.fillRect(startCol.toInt(), startRow.toInt(), width.toInt(), height.toInt())
// graphics.dispose()
}
fun drawImage(image: Int, x: Int, y: Int) {
val graphic = graphics!![image]
val graphics = buffer.getGraphics()
graphics.drawImage(graphic, x, y, null)
graphics.dispose()
// val graphics = buffer.getGraphics()
// graphics.drawImage(graphic, x, y, null)
// graphics.dispose()
}
fun drawImage(image: Int, x: Int, y: Int, width: Int, height: Int) {
val graphic = graphics!![image]
val graphics = buffer.getGraphics()
graphics.drawImage(graphic, x, y, width, height, null)
graphics.dispose()
// val graphics = buffer.getGraphics()
// graphics.drawImage(graphic, x, y, width, height, null)
// graphics.dispose()
}
fun drawImage(
@@ -167,20 +159,20 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
dh: Int
) {
val graphic = graphics!![image]
val graphics = buffer.getGraphics()
graphics.drawImage(graphic, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, null)
graphics.dispose()
// val graphics = buffer.getGraphics()
// graphics.drawImage(graphic, dx, dy, dx + dw, dy + dh, sx, sy, sx + sw, sy + sh, null)
// graphics.dispose()
}
fun sync() {
val baos = ByteArrayOutputStream()
try {
buffer.flush()
ImageIO.write(buffer, "png", baos)
byteArray = baos.toByteArray()
} catch (e: IOException) {
throw RuntimeException(e)
}
/* val baos = ByteArrayOutputStream()
try {
buffer.flush()
ImageIO.write(buffer, "png", baos)
byteArray = baos.toByteArray()
} catch (e: IOException) {
throw RuntimeException(e)
}*/
computer.notifyOfDisplayUpdate()
}
@@ -240,21 +232,24 @@ class MTMCDisplay(private val computer: MonTanaMiniComputer) {
fun scaleImage(original: BufferedImage, scaleDimensions: Dimension): BufferedImage {
val resized = BufferedImage(scaleDimensions.width, scaleDimensions.height, original.getType())
val g = resized.createGraphics()
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR
)
g.drawImage(
original, 0, 0, scaleDimensions.width, scaleDimensions.height, 0, 0, original.getWidth(),
original.getHeight(), null
)
g.dispose()
/*
val g = resized.createGraphics()
g.setRenderingHint(
RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR
)
g.drawImage(
original, 0, 0, scaleDimensions.width, scaleDimensions.height, 0, 0, original.getWidth(),
original.getHeight(), null
)
g.dispose()
*/
return resized
}
fun convertImage(image: BufferedImage): BufferedImage {
val arbg = BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR)
val arbg =
BufferedImage(image.getWidth(), image.getHeight(), 2) //BufferedImage.TYPE_4BYTE_ABGR)
for (x in 0..<image.getWidth()) {
for (y in 0..<image.getHeight()) {
val rgb = image.getRGB(x, y)