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:
parent
009b0c5c15
commit
e40456d7e4
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user