diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/DrawCall.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/DrawCall.kt index eb6bc58..21042d1 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/DrawCall.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/DrawCall.kt @@ -31,21 +31,31 @@ internal class GotoScanline(val line: Int) : DrawCall { } } +internal class ChangeGraphicsMode(val mode: Int) : DrawCall { + override fun execute(gpu: GraphicsAdapter) { + gpu.mmio_write(12L, mode.toByte()) + } +} + internal class JumpIfScanline( + val reg: Int, val compare: Int, val whenLessThan: Int, val whenEqualTo: Int, val whenGreaterThan: Int ) : DrawCall { override fun execute(gpu: GraphicsAdapter) { - if (gpu.rScanline < compare) { - if (whenLessThan != 65535) gpu.rScanline = whenLessThan - 1 + // TODO regValue = when ... + val regValue = gpu.rScanline + + if (regValue < compare) { + if (whenLessThan != 65535) gpu.drawCallProgramCounter = whenLessThan - 1 } - else if (gpu.rScanline == compare) { - if (whenEqualTo != 65535) gpu.rScanline = whenEqualTo - 1 + else if (regValue == compare) { + if (whenEqualTo != 65535) gpu.drawCallProgramCounter = whenEqualTo - 1 } else { - if (whenGreaterThan != 65535) gpu.rScanline = whenGreaterThan - 1 + if (whenGreaterThan != 65535) gpu.drawCallProgramCounter = whenGreaterThan - 1 } } } @@ -69,17 +79,20 @@ internal class DrawCallDrawLines( internal class DrawCallCopyPixels( - val opCount: Int, - val addrFrom: Int, - val xPos: Int, - val lineLength: Int, - val stride1: Int, - val stride2: Int, - val stride3: Int, - val stride4: Int, - val stride5: Int + val useTransparency: Boolean, + val width: Int, + val height: Int, + val transparencyKey: Int, + val xpos: Int, + val baseAddr: Int, + val stride: Int, + val colourMath1: Int, + val colourMath2: Int ) : DrawCall { override fun execute(gpu: GraphicsAdapter) { - TODO("Not yet implemented") + if (useTransparency) + gpu.blockCopyTransparency(width, height, xpos, gpu.rScanline, transparencyKey.toByte(), baseAddr, stride) + else + gpu.blockCopy(width, height, xpos, gpu.rScanline, baseAddr, stride) } -} \ No newline at end of file +} diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt index 633fe73..494df18 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/GraphicsAdapter.kt @@ -430,17 +430,13 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi ) ) } - in 0x20..0x25 -> { - return DrawCallCopyPixels( - (head and 0xF).toInt() + 1, - bytes[1].toUint().shl(16) or bytes[2].toUint().shl(8) or bytes[3].toUint(), - bytes[4].toUint().shl(8) or bytes[5].toUint(), - bytes[6].toUint().shl(8) or bytes[7].toUint(), - bytes[8].toUint().shl(8) or bytes[9].toUint(), - bytes[10].toUint().shl(8) or bytes[11].toUint(), - bytes[12].toUint().shl(8) or bytes[13].toUint(), - bytes[14].toUint().shl(8) or bytes[15].toUint(), - bytes[16].toUint().shl(8) or bytes[17].toUint() + 0x60.toByte() -> { + return JumpIfScanline( + bytes[1].toUint(), + toBigInt(bytes[2], bytes[3]), + toBigInt(bytes[4], bytes[5]), + toBigInt(bytes[6], bytes[7]), + toBigInt(bytes[8], bytes[9]) ) } else -> throw UnsupportedOperationException("Unknown Head byte 0x${head.toString(16).padStart(2,'0').toUpperCase()}") @@ -448,20 +444,81 @@ open class GraphicsAdapter(private val assetsRoot: String, val vm: VM, val confi } in -16..-1 -> { // C-type - when (head) { - else -> throw UnsupportedOperationException("Unknown Head byte 0x${head.toString(16).padStart(2,'0').toUpperCase()}") - } + val call1 = bytesToControlCalls(bytes.sliceArray(0..5)) + val call2 = bytesToControlCalls(bytes.sliceArray(6..11)) + val call3 = bytesToControlCalls(bytes.sliceArray(12..17)) + return DrawCallCompound(call1, call2, call3) } else -> { // T-type when (head) { + in 0xA0..0xA1 -> { + return DrawCallCopyPixels( + (head and 2) == 1.toByte(), + bytes[1].toUint().unzero(256), bytes[2].toUint().unzero(256), + bytes[3].toUint(), + toBigInt(bytes[4], bytes[5]), + toBigInt(bytes[6], bytes[7], bytes[8]), + toBigInt(bytes[9], bytes[10], bytes[11]), + toBigInt(bytes[12], bytes[13], bytes[14]), + toBigInt(bytes[15], bytes[16], bytes[17]) + ) + } else -> throw UnsupportedOperationException("Unknown Head byte 0x${head.toString(16).padStart(2,'0').toUpperCase()}") } } } } + private fun bytesToControlCalls(bytes: ByteArray): DrawCall { + return when (toBigInt(bytes[0], bytes[1])) { + 0xF00F -> DrawCallEnd + 0xF100 -> GotoScanline(toBigInt(bytes[2], bytes[3])) + 0xF101 -> ChangeGraphicsMode(toBigInt(bytes[2], bytes[3])) + 0xFFFF -> DrawCallNop + else -> throw UnsupportedOperationException("Unknown Opcode 0x${toBigInt(bytes[0], bytes[1]).toString(16).padStart(4, '0').toUpperCase()}") + } + } + private fun Int.unzero(n: Int) = if (this == 0) n else this + private fun toBigInt(byte1: Byte, byte2: Byte, byte3: Byte? = null): Int { + if (byte3 != null) + return byte1.toUint().shl(16) or byte2.toUint().shl(8) or byte3.toUint() + else + return byte1.toUint().shl(8) or byte2.toUint() + } + + open fun blockCopy(width: Int, height: Int, x: Int, y: Int, baseAddr: Int, stride: Int) { + var line = y + var srcPtr = vm.usermem.ptr + baseAddr + while (line < y + height) { + val destPtr = framebuffer.ptr + line * WIDTH + x + + UnsafeHelper.memcpy(srcPtr, destPtr, width.toLong()) + + srcPtr += stride + line += 1 + } + } + + open fun blockCopyTransparency(width: Int, height: Int, x: Int, y: Int, transparencyKey: Byte, baseAddr: Int, stride: Int) { + var line = y + var srcPtr = baseAddr * 1L + while (line < y + height) { + val destPtr = line * WIDTH + x * 1L + +// UnsafeHelper.memcpy(srcPtr, destPtr, width.toLong()) + for (col in x until x + width) { + val pixel = vm.usermem[srcPtr + col] + if (pixel != transparencyKey) { + framebuffer[destPtr + col] = pixel + } + } + + srcPtr += stride + line += 1 + } + } /** * @param mode 0-Low, 1-High