1
0
mirror of https://github.com/irmen/ksim65.git synced 2024-11-15 09:05:52 +00:00

tweak charset logic

This commit is contained in:
Irmen de Jong 2019-10-14 20:48:48 +02:00
parent 009b0c5c15
commit e40456d7e4
2 changed files with 17 additions and 21 deletions

View File

@ -12,7 +12,7 @@ import javax.swing.JPanel
* The rendering logic of the screen of the C64. * The rendering logic of the screen of the C64.
* It supports: Character mode, * It supports: Character mode,
* High res bitmap mode (320*200), Multicolor bitmap mode (160*200). * High res bitmap mode (320*200), Multicolor bitmap mode (160*200).
* TODO: Multicolor character mode. Extended background color mode. Custom charsets. * TODO: Custom charsets from RAM. Multicolor character mode. Extended background color mode.
*/ */
internal class Screen(private val chargenData: ByteArray, val ram: MemoryComponent) : JPanel() { internal class Screen(private val chargenData: ByteArray, val ram: MemoryComponent) : JPanel() {
@ -26,7 +26,6 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
val gd = ge.defaultScreenDevice.defaultConfiguration val gd = ge.defaultScreenDevice.defaultConfiguration
fullscreenImage = gd.createCompatibleImage(ScreenDefs.SCREEN_WIDTH+2*ScreenDefs.BORDER_SIZE, fullscreenImage = gd.createCompatibleImage(ScreenDefs.SCREEN_WIDTH+2*ScreenDefs.BORDER_SIZE,
ScreenDefs.SCREEN_HEIGHT+2*ScreenDefs.BORDER_SIZE, Transparency.OPAQUE) ScreenDefs.SCREEN_HEIGHT+2*ScreenDefs.BORDER_SIZE, Transparency.OPAQUE)
fullscreenImage.accelerationPriority = 1.0f
fullscreenG2d = fullscreenImage.graphics as Graphics2D fullscreenG2d = fullscreenImage.graphics as Graphics2D
val size = Dimension(fullscreenImage.width*ScreenDefs.DISPLAY_PIXEL_SCALING.toInt(), val size = Dimension(fullscreenImage.width*ScreenDefs.DISPLAY_PIXEL_SCALING.toInt(),
@ -40,9 +39,7 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
} }
private fun loadCharacters(shifted: Boolean): Array<BufferedImage> { private fun loadCharacters(shifted: Boolean): Array<BufferedImage> {
val chars = Array(256) { val chars = Array(256) { BufferedImage(8, 8, BufferedImage.TYPE_BYTE_BINARY) }
BufferedImage(8, 8, BufferedImage.TYPE_BYTE_BINARY).also { it.accelerationPriority = 1.0f }
}
val offset = if (shifted) 256*8 else 0 val offset = if (shifted) 256*8 else 0
for (char in 0..255) { for (char in 0..255) {
for (line in 0..7) { for (line in 0..7) {
@ -164,20 +161,14 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
// normal character mode // normal character mode
val screenAddress = vicBank+(vicVMCSB ushr 4) shl 10 val screenAddress = vicBank+(vicVMCSB ushr 4) shl 10
val charsetAddress = (vicVMCSB and 0b00001110) shl 10 val charsetAddress = (vicVMCSB and 0b00001110) shl 10
if (charsetAddress == 0x1000 || charsetAddress == 0x1800) {
// use built-in character ROM
for (y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) { for (y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) {
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, charsetAddress == 0x1800) drawColoredChar(x, y, char, color, vicBank + charsetAddress)
} }
} }
} }
/* else {
// TODO: custom charsets from RAM. Currently the charset ROM is just loaded externally.
} */
}
} }
private fun renderBitmapMode(vicBank: Address, vicVMCSB: Int, multiColorMode: Boolean) { private fun renderBitmapMode(vicBank: Address, vicVMCSB: Int, multiColorMode: Boolean) {
@ -239,10 +230,15 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
pixels[offset+7] = fourColors[colors[3]] pixels[offset+7] = fourColors[colors[3]]
} }
private val coloredCharacters = mutableMapOf<Triple<Int, Int, Boolean>, BufferedImage>() private val coloredCharacterImageCache = mutableMapOf<Triple<Int, Int, Boolean>, BufferedImage>()
private fun drawColoredChar(x: Int, y: Int, char: Int, color: Int, shifted: Boolean) { private fun drawColoredChar(x: Int, y: Int, char: Int, color: Int, charsetAddr: Address) {
var cached = coloredCharacters[Triple(char, color, shifted)] // The vic 'sees' the charset rom at these addresses: $1000 + $1800, $9000 + $9800
// so we can use pre-loaded images to efficiently draw the characters.
// If the address is different, the vic takes charset data from RAM instead.
// TODO: currently custom charsets taken from RAM are not yet supported
val shifted = charsetAddr and 0x0800 != 0
var cached = coloredCharacterImageCache[Triple(char, color, shifted)]
if (cached == null) { if (cached == null) {
cached = if (shifted) shiftedCharacters[char] else normalCharacters[char] cached = if (shifted) shiftedCharacters[char] else normalCharacters[char]
val colored = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK) val colored = fullscreenG2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
@ -259,7 +255,7 @@ internal class Screen(private val chargenData: ByteArray, val ram: MemoryCompone
} }
} }
} }
coloredCharacters[Triple(char, color, shifted)] = colored coloredCharacterImageCache[Triple(char, color, shifted)] = colored
cached = colored cached = colored
} }
fullscreenG2d.drawImage(cached, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null) fullscreenG2d.drawImage(cached, x*8+ScreenDefs.BORDER_SIZE, y*8+ScreenDefs.BORDER_SIZE, null)

View File

@ -31,7 +31,7 @@ object ScreenDefs {
private fun loadCharacters(): Array<BufferedImage> { private fun loadCharacters(): Array<BufferedImage> {
val img = ImageIO.read(javaClass.getResourceAsStream("/charset/unscii8x16.png")) val img = ImageIO.read(javaClass.getResourceAsStream("/charset/unscii8x16.png"))
val charactersImage = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB).also { it.accelerationPriority = 1.0f } val charactersImage = BufferedImage(img.width, img.height, BufferedImage.TYPE_INT_ARGB)
charactersImage.createGraphics().drawImage(img, 0, 0, null) charactersImage.createGraphics().drawImage(img, 0, 0, null)
val black = Color(0, 0, 0).rgb val black = Color(0, 0, 0).rgb