mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
graphics mode 5
This commit is contained in:
@@ -112,7 +112,7 @@ if (fullFilePathStr.startsWith('$:/TAPE') || fullFilePathStr.startsWith('$:\\TAP
|
||||
|
||||
con.clear()
|
||||
con.curs_set(0)
|
||||
graphics.setGraphicsMode(4) // 4096-colour mode
|
||||
graphics.setGraphicsMode(5) // 32-bit colour mode
|
||||
graphics.clearPixels(0)
|
||||
graphics.clearPixels2(0)
|
||||
|
||||
|
||||
@@ -1454,6 +1454,7 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
*/
|
||||
fun uploadRGBToFramebuffer(rgbAddr: Long, width: Int, height: Int, frameCount: Int, resizeToFull: Boolean) {
|
||||
val gpu = (vm.peripheralTable[1].peripheral as GraphicsAdapter)
|
||||
val graphicsMode = gpu.graphicsMode
|
||||
|
||||
val rgbAddrIncVec = if (rgbAddr >= 0) 1 else -1
|
||||
|
||||
@@ -1471,6 +1472,10 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val rgbBulkBuffer = ByteArray(chunkSize * 3)
|
||||
val rgChunk = ByteArray(chunkSize)
|
||||
val baChunk = ByteArray(chunkSize)
|
||||
val rChunk = ByteArray(chunkSize)
|
||||
val gChunk = ByteArray(chunkSize)
|
||||
val bChunk = ByteArray(chunkSize)
|
||||
val aChunk = ByteArray(chunkSize); aChunk.fill(-1)
|
||||
|
||||
while (pixelsProcessed < totalNativePixels) {
|
||||
val pixelsInChunk = kotlin.math.min(chunkSize, totalNativePixels - pixelsProcessed)
|
||||
@@ -1490,24 +1495,53 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val g = rgbBulkBuffer[i*3 + 1].toUint()
|
||||
val b = rgbBulkBuffer[i*3 + 2].toUint()
|
||||
|
||||
// Apply Bayer dithering and convert to 4-bit
|
||||
val r4 = ditherValue(r, videoX, videoY, frameCount)
|
||||
val g4 = ditherValue(g, videoX, videoY, frameCount)
|
||||
val b4 = ditherValue(b, videoX, videoY, frameCount)
|
||||
if (graphicsMode == 4) {
|
||||
// Apply Bayer dithering and convert to 4-bit
|
||||
val r4 = ditherValue(r, videoX, videoY, frameCount)
|
||||
val g4 = ditherValue(g, videoX, videoY, frameCount)
|
||||
val b4 = ditherValue(b, videoX, videoY, frameCount)
|
||||
|
||||
// Pack RGB values and store in chunk arrays for batch processing
|
||||
rgChunk[i] = ((r4 shl 4) or g4).toByte()
|
||||
baChunk[i] = ((b4 shl 4) or 15).toByte()
|
||||
// Pack RGB values and store in chunk arrays for batch processing
|
||||
rgChunk[i] = ((r4 shl 4) or g4).toByte()
|
||||
baChunk[i] = ((b4 shl 4) or 15).toByte()
|
||||
|
||||
// Write directly to framebuffer position
|
||||
val nativePos = videoY * nativeWidth + videoX
|
||||
}
|
||||
else if (graphicsMode == 5) {
|
||||
rChunk[i] = r.toByte()
|
||||
gChunk[i] = g.toByte()
|
||||
bChunk[i] = b.toByte()
|
||||
}
|
||||
}
|
||||
val pixelIndex = pixelsProcessed
|
||||
val videoY = pixelIndex / width
|
||||
val videoX = pixelIndex % width
|
||||
val nativePos = videoY * nativeWidth + videoX
|
||||
if (graphicsMode == 4) {
|
||||
UnsafeHelper.memcpyRaw(
|
||||
rgChunk, UnsafeHelper.getArrayOffset(rgChunk) + i,
|
||||
null, gpu.framebuffer.ptr + nativePos, 1L
|
||||
rgChunk, UnsafeHelper.getArrayOffset(rgChunk),
|
||||
null, gpu.framebuffer.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
baChunk, UnsafeHelper.getArrayOffset(baChunk) + i,
|
||||
null, gpu.framebuffer2!!.ptr + nativePos, 1L
|
||||
baChunk, UnsafeHelper.getArrayOffset(baChunk),
|
||||
null, gpu.framebuffer2!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
}
|
||||
else if (graphicsMode == 5) {
|
||||
UnsafeHelper.memcpyRaw(
|
||||
rChunk, UnsafeHelper.getArrayOffset(rChunk),
|
||||
null, gpu.framebuffer.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
gChunk, UnsafeHelper.getArrayOffset(gChunk),
|
||||
null, gpu.framebuffer2!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
bChunk, UnsafeHelper.getArrayOffset(bChunk),
|
||||
null, gpu.framebuffer3!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
aChunk, UnsafeHelper.getArrayOffset(aChunk),
|
||||
null, gpu.framebuffer4!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1520,9 +1554,13 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val scaleY = height.toFloat() / nativeHeight.toFloat()
|
||||
|
||||
// Process native pixels in 8KB chunks
|
||||
val chunkSize = 8192
|
||||
val chunkSize = 32768
|
||||
val rgChunk = ByteArray(chunkSize)
|
||||
val baChunk = ByteArray(chunkSize)
|
||||
val rChunk = ByteArray(chunkSize)
|
||||
val gChunk = ByteArray(chunkSize)
|
||||
val bChunk = ByteArray(chunkSize)
|
||||
val aChunk = ByteArray(chunkSize); aChunk.fill(-1)
|
||||
|
||||
var pixelsProcessed = 0
|
||||
|
||||
@@ -1545,23 +1583,54 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
||||
val g = rgb[1]
|
||||
val b = rgb[2]
|
||||
|
||||
// Apply Bayer dithering and convert to 4-bit using native coordinates
|
||||
val r4 = ditherValue(r, nativeX, nativeY, frameCount)
|
||||
val g4 = ditherValue(g, nativeX, nativeY, frameCount)
|
||||
val b4 = ditherValue(b, nativeX, nativeY, frameCount)
|
||||
if (graphicsMode == 4) {
|
||||
// Apply Bayer dithering and convert to 4-bit using native coordinates
|
||||
val r4 = ditherValue(r, nativeX, nativeY, frameCount)
|
||||
val g4 = ditherValue(g, nativeX, nativeY, frameCount)
|
||||
val b4 = ditherValue(b, nativeX, nativeY, frameCount)
|
||||
|
||||
// Pack and store in chunk buffers
|
||||
rgChunk[i] = ((r4 shl 4) or g4).toByte()
|
||||
baChunk[i] = ((b4 shl 4) or 15).toByte()
|
||||
// Pack and store in chunk buffers
|
||||
rgChunk[i] = ((r4 shl 4) or g4).toByte()
|
||||
baChunk[i] = ((b4 shl 4) or 15).toByte()
|
||||
}
|
||||
else if (graphicsMode == 5) {
|
||||
rChunk[i] = r.toByte()
|
||||
gChunk[i] = g.toByte()
|
||||
bChunk[i] = b.toByte()
|
||||
}
|
||||
}
|
||||
val pixelIndex = pixelsProcessed
|
||||
val videoY = pixelIndex / width
|
||||
val videoX = pixelIndex % width
|
||||
val nativePos = videoY * nativeWidth + videoX
|
||||
if (graphicsMode == 4) {
|
||||
UnsafeHelper.memcpyRaw(
|
||||
rgChunk, UnsafeHelper.getArrayOffset(rgChunk),
|
||||
null, gpu.framebuffer.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
baChunk, UnsafeHelper.getArrayOffset(baChunk),
|
||||
null, gpu.framebuffer2!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
}
|
||||
else if (graphicsMode == 5) {
|
||||
UnsafeHelper.memcpyRaw(
|
||||
rChunk, UnsafeHelper.getArrayOffset(rChunk),
|
||||
null, gpu.framebuffer.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
gChunk, UnsafeHelper.getArrayOffset(gChunk),
|
||||
null, gpu.framebuffer2!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
bChunk, UnsafeHelper.getArrayOffset(bChunk),
|
||||
null, gpu.framebuffer3!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
UnsafeHelper.memcpyRaw(
|
||||
aChunk, UnsafeHelper.getArrayOffset(aChunk),
|
||||
null, gpu.framebuffer4!!.ptr + nativePos, pixelsInChunk.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
// Write pixels to their sequential positions in framebuffer
|
||||
UnsafeHelper.memcpyRaw(
|
||||
rgChunk, UnsafeHelper.getArrayOffset(rgChunk),
|
||||
null, gpu.framebuffer.ptr + pixelsProcessed, pixelsInChunk.toLong())
|
||||
UnsafeHelper.memcpyRaw(
|
||||
baChunk, UnsafeHelper.getArrayOffset(baChunk),
|
||||
null, gpu.framebuffer2!!.ptr + pixelsProcessed, pixelsInChunk.toLong())
|
||||
|
||||
pixelsProcessed += pixelsInChunk
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ data class SuperGraphicsAddonConfig(
|
||||
val bankCount: Int = 1
|
||||
)
|
||||
|
||||
class ReferenceGraphicsAdapter(assetsRoot: String, vm: VM) : GraphicsAdapter(assetsRoot, vm, GraphicsAdapter.DEFAULT_CONFIG_COLOR_CRT, SuperGraphicsAddonConfig(2))
|
||||
class ReferenceGraphicsAdapter(assetsRoot: String, vm: VM) : GraphicsAdapter(assetsRoot, vm, GraphicsAdapter.DEFAULT_CONFIG_COLOR_CRT, SuperGraphicsAddonConfig(4))
|
||||
class ReferenceGraphicsAdapter2(assetsRoot: String, vm: VM) : RemoteGraphicsAdapter(assetsRoot, vm, GraphicsAdapter.DEFAULT_CONFIG_COLOR_CRT, SuperGraphicsAddonConfig(2))
|
||||
class ReferenceLikeLCD(assetsRoot: String, vm: VM) : GraphicsAdapter(assetsRoot, vm, GraphicsAdapter.DEFAULT_CONFIG_PMLCD)
|
||||
|
||||
@@ -76,6 +76,9 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
|
||||
internal val framebuffer = UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this)//Pixmap(WIDTH, HEIGHT, Pixmap.Format.Alpha)
|
||||
internal val framebuffer2 = if (sgr.bankCount >= 2) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this) else null
|
||||
internal val framebuffer3 = if (sgr.bankCount >= 3) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this) else null
|
||||
internal val framebuffer4 = if (sgr.bankCount >= 4) UnsafeHelper.allocate(WIDTH.toLong() * HEIGHT, this) else null
|
||||
|
||||
internal val framebufferOut = Pixmap(WIDTH, HEIGHT, Pixmap.Format.RGBA8888)
|
||||
protected var rendertex = Texture(1, 1, Pixmap.Format.RGBA8888)
|
||||
internal val paletteOfFloats = FloatArray(1024) {
|
||||
@@ -130,7 +133,7 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
private val outFBOregion = Array(2) { TextureRegion(outFBOs[it].colorBufferTexture) }
|
||||
private val outFBObatch = SpriteBatch(1000, DefaultGL32Shaders.createSpriteBatchShader())
|
||||
|
||||
private var graphicsMode = 0
|
||||
var graphicsMode = 0
|
||||
private var layerArrangement = 0
|
||||
|
||||
|
||||
@@ -227,7 +230,19 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
|
||||
override fun peek(addr: Long): Byte? {
|
||||
val adi = addr.toInt()
|
||||
if (framebuffer2 != null && addr >= 262144) {
|
||||
if (framebuffer4 != null && addr >= 524288) {
|
||||
return when (addr - 524288) {
|
||||
in 0 until 250880 -> framebuffer4[addr - 524288]
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else if (framebuffer3 != null && addr >= 393216) {
|
||||
return when (addr - 393216) {
|
||||
in 0 until 250880 -> framebuffer3[addr - 393216]
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
else if (framebuffer2 != null && addr >= 262144) {
|
||||
return when (addr - 262144) {
|
||||
in 0 until 250880 -> framebuffer2[addr - 262144]
|
||||
else -> null
|
||||
@@ -275,6 +290,24 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
override fun poke(addr: Long, byte: Byte) {
|
||||
val adi = addr.toInt()
|
||||
val bi = byte.toInt().and(255)
|
||||
if (framebuffer4 != null) {
|
||||
when (addr - 524288) {
|
||||
in 0 until 250880 -> {
|
||||
lastUsedColour = byte
|
||||
framebuffer4[addr - 524288] = byte
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (framebuffer3 != null) {
|
||||
when (addr - 393216) {
|
||||
in 0 until 250880 -> {
|
||||
lastUsedColour = byte
|
||||
framebuffer3[addr - 393216] = byte
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if (framebuffer2 != null) {
|
||||
when (addr - 262144) {
|
||||
in 0 until 250880 -> {
|
||||
@@ -899,6 +932,8 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
// textShader.tryDispose()
|
||||
framebuffer.destroy()
|
||||
framebuffer2?.destroy()
|
||||
framebuffer3?.destroy()
|
||||
framebuffer4?.destroy()
|
||||
framebufferOut.tryDispose()
|
||||
rendertex.tryDispose()
|
||||
textArea.destroy()
|
||||
@@ -942,7 +977,27 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
chrrom.pixels.position(0)
|
||||
|
||||
framebufferOut.setColor(-1);framebufferOut.fill()
|
||||
if (graphicsMode == 4 && framebuffer2 != null) {
|
||||
if (graphicsMode == 5 && framebuffer4 != null && framebuffer3 != null && framebuffer2 != null) {
|
||||
for (y in 0 until HEIGHT) {
|
||||
var xoff = scanlineOffsets[2L * y].toUint() or scanlineOffsets[2L * y + 1].toUint().shl(8)
|
||||
if (xoff.and(0x8000) != 0) xoff = xoff or 0xFFFF0000.toInt()
|
||||
val xs = (0 + xoff).coerceIn(0, WIDTH - 1)..(WIDTH - 1 + xoff).coerceIn(0, WIDTH - 1)
|
||||
|
||||
if (xoff in -(WIDTH - 1) until WIDTH) {
|
||||
for (x in xs) {
|
||||
val r = framebuffer[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
|
||||
val g = framebuffer2[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
|
||||
val b = framebuffer3[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
|
||||
val a = framebuffer4[y.toLong() * WIDTH + (x - xoff)].toUint() // coerceIn not required as (x - xoff) never escapes 0..559
|
||||
framebufferOut.setColor(
|
||||
r.shl(24) or g.shl(16) or b.shl(8) or a
|
||||
)
|
||||
framebufferOut.drawPixel(x, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (graphicsMode == 4 && framebuffer2 != null) {
|
||||
for (y in 0 until HEIGHT) {
|
||||
var xoff = scanlineOffsets[2L * y].toUint() or scanlineOffsets[2L * y + 1].toUint().shl(8)
|
||||
if (xoff.and(0x8000) != 0) xoff = xoff or 0xFFFF0000.toInt()
|
||||
@@ -968,7 +1023,7 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi
|
||||
}
|
||||
}
|
||||
else if (graphicsMode == 3 && framebuffer2 != null) {
|
||||
val layerOrder = (if (graphicsMode == 1) LAYERORDERS4 else LAYERORDERS2)[layerArrangement]
|
||||
val layerOrder = LAYERORDERS2[layerArrangement]
|
||||
|
||||
val fb1 = if (layerOrder[0] == 0) framebuffer else framebuffer2
|
||||
val fb2 = if (layerOrder[0] == 0) framebuffer2 else framebuffer
|
||||
|
||||
Reference in New Issue
Block a user