mirror of
https://github.com/irmen/ksim65.git
synced 2024-09-27 07:54:29 +00:00
optimized ram access when drawing sprites
This commit is contained in:
parent
d7b443a677
commit
88645266fa
@ -123,15 +123,11 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||||||
val mx = ram[0xd010].toInt() and (1 shl sprite) != 0
|
val mx = ram[0xd010].toInt() and (1 shl sprite) != 0
|
||||||
val xpos = ram[0xd000+sprite*2].toInt()+if (mx) 256 else 0
|
val xpos = ram[0xd000+sprite*2].toInt()+if (mx) 256 else 0
|
||||||
val ypos = ram[0xd001+sprite*2].toInt()
|
val ypos = ram[0xd001+sprite*2].toInt()
|
||||||
if(xpos in 1..343 && ypos in 30..249) {
|
if (xpos in 1..343 && ypos in 30..249) {
|
||||||
spriteGfx.fillRect(0, 0, 24, 21)
|
spriteGfx.fillRect(0, 0, 24, 21)
|
||||||
renderSprite(sprite, spritePixels, vicBank)
|
renderSprite(sprite, spritePixels, vicBank)
|
||||||
fullscreenG2d.drawImage(spriteImage,
|
fullscreenG2d.drawImage(spriteImage, xpos+ScreenDefs.BORDER_SIZE-24, ypos+ScreenDefs.BORDER_SIZE-50,
|
||||||
xpos+ScreenDefs.BORDER_SIZE-24,
|
if (vicXXPAND and bit == 0) 24 else 48, if (vicYXPAND and bit == 0) 21 else 42, null)
|
||||||
ypos+ScreenDefs.BORDER_SIZE-50,
|
|
||||||
if(vicXXPAND and bit == 0) 24 else 48,
|
|
||||||
if(vicYXPAND and bit == 0) 21 else 42,
|
|
||||||
null)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,9 +136,10 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||||||
private fun renderSprite(sprite: Int, spritePixels: IntArray, vicBank: Address) {
|
private fun renderSprite(sprite: Int, spritePixels: IntArray, vicBank: Address) {
|
||||||
// note: the sprite pixels must all have been cleared to transparency already
|
// note: the sprite pixels must all have been cleared to transparency already
|
||||||
val sprptr = ram[vicBank+2040+sprite]*64
|
val sprptr = ram[vicBank+2040+sprite]*64
|
||||||
|
val sprdata = ram.getBlock(sprptr, 21*3)
|
||||||
val color = ScreenDefs.colorPalette[ram[0xd027+sprite]].rgb
|
val color = ScreenDefs.colorPalette[ram[0xd027+sprite]].rgb
|
||||||
for (i in spritePixels.indices step 8) {
|
for (i in spritePixels.indices step 8) {
|
||||||
val bits = ram[sprptr+i/8].toInt()
|
val bits = sprdata[i/8].toInt()
|
||||||
if (bits and 0b10000000 != 0) spritePixels[i] = color
|
if (bits and 0b10000000 != 0) spritePixels[i] = color
|
||||||
if (bits and 0b01000000 != 0) spritePixels[i+1] = color
|
if (bits and 0b01000000 != 0) spritePixels[i+1] = color
|
||||||
if (bits and 0b00100000 != 0) spritePixels[i+2] = color
|
if (bits and 0b00100000 != 0) spritePixels[i+2] = color
|
||||||
@ -165,15 +162,15 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||||||
for (x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
for (x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
||||||
val char = ram[screenAddress+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
val char = ram[screenAddress+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||||
val color = ram[0xd800+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt() // colors always at $d800
|
val color = ram[0xd800+x+y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt() // colors always at $d800
|
||||||
drawColoredChar(x, y, char, color, vicBank + charsetAddress)
|
drawColoredChar(x, y, char, color, vicBank+charsetAddress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderBitmapMode(vicBank: Address, vicVMCSB: Int, multiColorMode: Boolean) {
|
private fun renderBitmapMode(vicBank: Address, vicVMCSB: Int, multiColorMode: Boolean) {
|
||||||
val bitmap = ram.getPages((vicBank ushr 8)+if (vicVMCSB and 0b00001000 != 0) 32 else 0, 32)
|
val bitmap = ram.getBlock(vicBank+if (vicVMCSB and 0b00001000 != 0) 32*256 else 0, 32*256)
|
||||||
val colorBytes = ram.getPages((vicBank ushr 8)+((vicVMCSB ushr 4) shl 2), 4)
|
val colorBytes = ram.getBlock(vicBank+((vicVMCSB ushr 4) shl 2)*256, 4*256)
|
||||||
val pixels: IntArray = (fullscreenImage.raster.dataBuffer as DataBufferInt).data
|
val pixels: IntArray = (fullscreenImage.raster.dataBuffer as DataBufferInt).data
|
||||||
val screenColor = ScreenDefs.colorPalette[ram[0xd021]].rgb
|
val screenColor = ScreenDefs.colorPalette[ram[0xd021]].rgb
|
||||||
if (multiColorMode) {
|
if (multiColorMode) {
|
||||||
@ -238,16 +235,36 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
|
|||||||
// If the address is different, the vic takes charset data from RAM instead (thus allowing user defined charsets)
|
// If the address is different, the vic takes charset data from RAM instead (thus allowing user defined charsets)
|
||||||
// A user-supplied character set in RAM must begin at an address that is 2048 byte aligned,
|
// A user-supplied character set in RAM must begin at an address that is 2048 byte aligned,
|
||||||
// and lies within the same 16K VIC bank as the screen character memory.
|
// and lies within the same 16K VIC bank as the screen character memory.
|
||||||
// TODO: currently custom charsets taken from RAM aren't supported
|
when (charsetAddr) {
|
||||||
val shifted = charsetAddr and 0x0800 != 0
|
0x1000, 0x1800, 0x9000, 0x9800 -> {
|
||||||
val charImage = getCharImage(char, color, shifted)
|
val charImage = getCharImage(char, color, charsetAddr and 0x0800 != 0)
|
||||||
fullscreenG2d.drawImage(charImage, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
fullscreenG2d.drawImage(charImage, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// TODO: currently custom charsets taken from RAM aren't supported yet (need to read the char pixels)
|
||||||
|
fullscreenG2d.drawImage(placeholderUserCharacter, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: temporary placeholder for user-defined charset
|
||||||
|
private val placeholderUserCharacter: BufferedImage by lazy {
|
||||||
|
val img = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
||||||
|
with(img.graphics) {
|
||||||
|
color = Color.DARK_GRAY
|
||||||
|
fillRect(0, 0, 8, 8)
|
||||||
|
}
|
||||||
|
for (x in 0..7) {
|
||||||
|
img.setRGB(x, x, Color.RED.rgb)
|
||||||
|
img.setRGB(7-x, x, Color.RED.rgb)
|
||||||
|
}
|
||||||
|
img
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCharImage(char: Int, color: Int, shifted: Boolean): BufferedImage {
|
private fun getCharImage(char: Int, color: Int, shifted: Boolean): BufferedImage {
|
||||||
val key = Triple(char, color, shifted)
|
val key = Triple(char, color, shifted)
|
||||||
|
|
||||||
fun makeCachedImage(): BufferedImage {
|
fun makeCachedImage(): BufferedImage {
|
||||||
val monoImg = if (shifted) shiftedCharacters[char] else normalCharacters[char]
|
val monoImg = if (shifted) shiftedCharacters[char] else normalCharacters[char]
|
||||||
val coloredImg = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
val coloredImg = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
||||||
val srcPixel = IntArray(4)
|
val srcPixel = IntArray(4)
|
||||||
|
@ -209,7 +209,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
|||||||
else ram.load(file.readBytes(), loadAddress!!)
|
else ram.load(file.readBytes(), loadAddress!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getZeroAndStackPages(): Array<UByte> = ram.getPages(0, 2)
|
override fun getZeroAndStackPages(): Array<UByte> = ram.getBlock(0, 512)
|
||||||
|
|
||||||
override fun pause(paused: Boolean) {
|
override fun pause(paused: Boolean) {
|
||||||
this.paused = paused
|
this.paused = paused
|
||||||
|
@ -47,7 +47,7 @@ class VirtualMachine(title: String) : IVirtualMachine {
|
|||||||
hostDisplay.start(30)
|
hostDisplay.start(30)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getZeroAndStackPages(): Array<UByte> = ram.getPages(0, 2)
|
override fun getZeroAndStackPages(): Array<UByte> = ram.getBlock(0, 512)
|
||||||
|
|
||||||
override fun loadFileInRam(file: File, loadAddress: Address?) {
|
override fun loadFileInRam(file: File, loadAddress: Address?) {
|
||||||
if (file.extension == "prg" && loadAddress == null) ram.loadPrg(file.inputStream(), null)
|
if (file.extension == "prg" && loadAddress == null) ram.loadPrg(file.inputStream(), null)
|
||||||
|
@ -62,5 +62,5 @@ abstract class MemoryComponent(startAddress: Address, endAddress: Address) : Mem
|
|||||||
require(startAddress and 0xff == 0 && endAddress and 0xff == 0xff) { "address range must span complete page(s)" }
|
require(startAddress and 0xff == 0 && endAddress and 0xff == 0xff) { "address range must span complete page(s)" }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPages(page: Int, numPages: Int): Array<UByte> = data.copyOfRange(page*256, (page+numPages)*256)
|
fun getBlock(start: Int, length: Int): Array<UByte> = data.copyOfRange(start, start+length)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user