mirror of
https://github.com/irmen/ksim65.git
synced 2025-02-07 18:30:48 +00:00
Custom c64 key mapping to make typing on a modern keyboard tolerable. Connected Restore key (backslash) to NMI.
This commit is contained in:
parent
bfdd9aa656
commit
88c1688a41
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@ -15,6 +15,7 @@
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="useAutoImport" value="true" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
|
@ -9,11 +9,13 @@ import java.awt.event.KeyEvent
|
||||
* Minimal simulation of the MOS 6526 CIA chip.
|
||||
* Depending on what CIA it is (1 or 2), some registers do different things on the C64.
|
||||
*/
|
||||
class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappedComponent(startAddress, endAddress) {
|
||||
class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMappedComponent(startAddress, endAddress) {
|
||||
private var ramBuffer = Array<UByte>(endAddress - startAddress + 1) { 0x00 }
|
||||
private var pra = 0xff
|
||||
|
||||
private val hostKeyPresses = mutableSetOf<Int>()
|
||||
private data class HostKeyPress(val code: Int, val rightSide: Boolean, val numpad: Boolean)
|
||||
|
||||
private val hostKeyPresses = mutableSetOf<HostKeyPress>()
|
||||
|
||||
init {
|
||||
require(endAddress - startAddress + 1 == 256) { "cia requires exactly 256 memory bytes (16*16 mirrored)" }
|
||||
@ -24,134 +26,165 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
hostKeyPresses.clear()
|
||||
// TODO: reset TOD timer, timer A and B
|
||||
}
|
||||
|
||||
override fun get(address: Address): UByte {
|
||||
fun scanColumn(keys: List<HostKeyPress>): UByte {
|
||||
var bits = 0b10000000
|
||||
var presses = 0
|
||||
for (key in keys) {
|
||||
if (key in hostKeyPresses) presses = presses or bits
|
||||
bits = bits ushr 1
|
||||
}
|
||||
return (presses.inv() and 255).toShort()
|
||||
}
|
||||
|
||||
val register = (address - startAddress) and 15
|
||||
if(number==1) {
|
||||
if (number == 1) {
|
||||
return if (register == 0x01) {
|
||||
// register 1 on CIA#1 is the keyboard data port
|
||||
// if bit is cleared in PRA, contains keys pressed in that column of the matrix
|
||||
// TODO tweak the keyboard mapping so that keys like '=' can be pressed,
|
||||
// RESTORE works (this is not a normal key but connected to the cpu's NMI line),
|
||||
// Cursor up/down/left/right all work and left/right shift are different.
|
||||
when(pra) {
|
||||
when (pra) {
|
||||
0b00000000 -> {
|
||||
// check if any keys are pressed at all (by checking all columns at once)
|
||||
if(hostKeyPresses.isEmpty()) 0xff.toShort() else 0x00.toShort()
|
||||
if (hostKeyPresses.isEmpty()) 0xff.toShort() else 0x00.toShort()
|
||||
}
|
||||
0b11111110 -> {
|
||||
// read column 0
|
||||
val presses =
|
||||
(if (KeyEvent.VK_DOWN in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_F5 in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if (KeyEvent.VK_F3 in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if (KeyEvent.VK_F1 in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_F7 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_RIGHT in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_ENTER in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if (KeyEvent.VK_BACK_SPACE in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_DOWN, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_F5, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_F3, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_F1, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_F7, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_RIGHT, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_ENTER, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_BACK_SPACE, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b11111101 -> {
|
||||
// read column 1
|
||||
val presses =
|
||||
(if(KeyEvent.VK_SHIFT in hostKeyPresses) 0b10000000 else 0) or // TODO make it LEFT shift only
|
||||
(if(KeyEvent.VK_E in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if(KeyEvent.VK_S in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if(KeyEvent.VK_Z in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if(KeyEvent.VK_4 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if(KeyEvent.VK_A in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if(KeyEvent.VK_W in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if(KeyEvent.VK_3 in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_SHIFT, rightSide = false, numpad = false), // left shift
|
||||
HostKeyPress(KeyEvent.VK_E, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_S, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_Z, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_4, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_A, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_W, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_3, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b11111011 -> {
|
||||
// read column 2
|
||||
val presses =
|
||||
(if (KeyEvent.VK_X in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_T in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if (KeyEvent.VK_F in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if (KeyEvent.VK_C in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_6 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_D in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_R in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if (KeyEvent.VK_5 in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_X, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_T, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_F, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_C, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_6, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_D, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_R, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_5, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b11110111 -> {
|
||||
// read column 3
|
||||
val presses =
|
||||
(if (KeyEvent.VK_V in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_U in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if (KeyEvent.VK_H in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if (KeyEvent.VK_B in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_8 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_G in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_Y in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if (KeyEvent.VK_7 in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_V, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_U, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_H, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_B, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_8, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_G, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_Y, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_7, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b11101111 -> {
|
||||
// read column 4
|
||||
val presses =
|
||||
(if (KeyEvent.VK_N in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_O in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if (KeyEvent.VK_K in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if (KeyEvent.VK_M in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_0 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_J in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_I in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if (KeyEvent.VK_9 in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_N, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_O, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_K, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_M, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_0, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_J, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_I, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_9, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b11011111 -> {
|
||||
// read column 5
|
||||
val presses =
|
||||
(if (KeyEvent.VK_COMMA in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_OPEN_BRACKET in hostKeyPresses) 0b01000000 else 0) or // '[' = @
|
||||
(if (KeyEvent.VK_SEMICOLON in hostKeyPresses) 0b00100000 else 0) or // ';' -> :
|
||||
(if (KeyEvent.VK_PERIOD in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_MINUS in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_L in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_P in hostKeyPresses) 0b00000010 else 0) or
|
||||
(if (KeyEvent.VK_PLUS in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_COMMA, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_AT, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_COLON, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_PERIOD, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_MINUS, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_L, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_P, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_PLUS, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
0b10111111 -> {
|
||||
// read column 6
|
||||
val presses =
|
||||
(if (KeyEvent.VK_SLASH in hostKeyPresses) 0b10000000 else 0) or
|
||||
(if (KeyEvent.VK_BACK_SLASH in hostKeyPresses) 0b01000000 else 0) or // '\' -> up arrow
|
||||
(if (KeyEvent.VK_EQUALS in hostKeyPresses) 0b00100000 else 0) or
|
||||
(if (KeyEvent.VK_SHIFT in hostKeyPresses) 0b00010000 else 0) or // TODO RIGHT shift only
|
||||
(if (KeyEvent.VK_HOME in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_QUOTE in hostKeyPresses) 0b00000100 else 0) or // ' -> ;
|
||||
(if (KeyEvent.VK_CLOSE_BRACKET in hostKeyPresses) 0b00000010 else 0) or // ']' = *
|
||||
(if (KeyEvent.VK_END in hostKeyPresses) 0b00000001 else 0) // END -> pound key
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_SLASH, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_CIRCUMFLEX, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_EQUALS, rightSide = false, numpad = false),
|
||||
HostKeyPress(
|
||||
KeyEvent.VK_SHIFT,
|
||||
rightSide = true,
|
||||
numpad = false
|
||||
), // right shift
|
||||
HostKeyPress(KeyEvent.VK_HOME, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_SEMICOLON, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_ASTERISK, rightSide = false, numpad = false),
|
||||
HostKeyPress(
|
||||
KeyEvent.VK_DEAD_TILDE,
|
||||
rightSide = false,
|
||||
numpad = false
|
||||
) // pound sign
|
||||
)
|
||||
)
|
||||
}
|
||||
0b01111111 -> {
|
||||
// read column 7
|
||||
val presses =
|
||||
(if (KeyEvent.VK_ESCAPE in hostKeyPresses) 0b10000000 else 0) or // esc -> STOP
|
||||
(if (KeyEvent.VK_Q in hostKeyPresses) 0b01000000 else 0) or
|
||||
(if (KeyEvent.VK_ALT in hostKeyPresses) 0b00100000 else 0) or // alt -> Commodore
|
||||
(if (KeyEvent.VK_SPACE in hostKeyPresses) 0b00010000 else 0) or
|
||||
(if (KeyEvent.VK_2 in hostKeyPresses) 0b00001000 else 0) or
|
||||
(if (KeyEvent.VK_CONTROL in hostKeyPresses) 0b00000100 else 0) or
|
||||
(if (KeyEvent.VK_BACK_QUOTE in hostKeyPresses) 0b00000010 else 0) or // '`' -> left arrow
|
||||
(if (KeyEvent.VK_1 in hostKeyPresses) 0b00000001 else 0)
|
||||
(presses.inv() and 255).toShort()
|
||||
scanColumn(
|
||||
listOf(
|
||||
HostKeyPress(KeyEvent.VK_ESCAPE, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_Q, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_ALT, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_SPACE, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_2, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_CONTROL, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_BACK_QUOTE, rightSide = false, numpad = false),
|
||||
HostKeyPress(KeyEvent.VK_1, rightSide = false, numpad = false)
|
||||
)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
else -> {
|
||||
// invalid column selection
|
||||
0xff
|
||||
}
|
||||
}
|
||||
}
|
||||
else ramBuffer[register]
|
||||
} else ramBuffer[register]
|
||||
}
|
||||
|
||||
// CIA #2 is not emulated yet
|
||||
@ -161,7 +194,7 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe
|
||||
override fun set(address: Address, data: UByte) {
|
||||
val register = (address - startAddress) and 15
|
||||
ramBuffer[register] = data
|
||||
if(number==1) {
|
||||
if (number == 1) {
|
||||
when (register) {
|
||||
0x00 -> {
|
||||
// PRA data port A (select keyboard matrix column)
|
||||
@ -173,9 +206,127 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address): MemMappe
|
||||
}
|
||||
|
||||
fun hostKeyPressed(event: KeyEvent) {
|
||||
if(event.id==KeyEvent.KEY_PRESSED)
|
||||
hostKeyPresses.add(event.keyCode)
|
||||
else if(event.id==KeyEvent.KEY_RELEASED)
|
||||
hostKeyPresses.remove(event.keyCode)
|
||||
val rightSide = event.keyLocation == KeyEvent.KEY_LOCATION_RIGHT
|
||||
val numpad = event.keyLocation == KeyEvent.KEY_LOCATION_NUMPAD
|
||||
val shift = HostKeyPress(KeyEvent.VK_SHIFT, rightSide = true, numpad = false)
|
||||
|
||||
fun register(eventId: Int, vararg keys: HostKeyPress) {
|
||||
if (eventId == KeyEvent.KEY_PRESSED) keys.forEach { hostKeyPresses.add(it) }
|
||||
else keys.forEach { hostKeyPresses.remove(it) }
|
||||
}
|
||||
|
||||
fun unregister(keyCode: Int) {
|
||||
hostKeyPresses.removeAll { it.code == keyCode }
|
||||
}
|
||||
|
||||
// to avoid some 'stuck' keys, if we receive a shift/control/alt RELEASE, we wipe the keyboard buffer
|
||||
// (this can happen becase we're changing the keycode for some pressed keys below,
|
||||
// and a released key doesn't always match the pressed keycode anymore then)
|
||||
if (event.id == KeyEvent.KEY_RELEASED && event.keyCode in listOf(
|
||||
KeyEvent.VK_SHIFT,
|
||||
KeyEvent.VK_CONTROL,
|
||||
KeyEvent.VK_ALT,
|
||||
KeyEvent.VK_ALT_GRAPH
|
||||
)
|
||||
) hostKeyPresses.clear()
|
||||
|
||||
// try to remap the keys a bit so a modern PC keyboard maps better to the keys of the C64
|
||||
when {
|
||||
event.keyChar == '@' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_AT, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '^' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_CIRCUMFLEX, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '&' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_6, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '*' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_ASTERISK, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '(' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_8, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == ')' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_9, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '[' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_COLON, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == ']' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_SEMICOLON, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '+' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_PLUS, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '"' -> {
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_2, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == ':' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_COLON, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '~' -> {
|
||||
unregister(KeyEvent.VK_SHIFT)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_DEAD_TILDE, rightSide = false, numpad = false))
|
||||
}
|
||||
event.keyChar == '\'' -> {
|
||||
register(event.id, shift, HostKeyPress(KeyEvent.VK_7, rightSide = false, numpad = false))
|
||||
}
|
||||
else -> when (event.keyCode) {
|
||||
KeyEvent.VK_CONTROL, KeyEvent.VK_TAB -> {
|
||||
// both controls and the tab key map to the 'single left control'
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_CONTROL, rightSide = false, numpad = false))
|
||||
}
|
||||
KeyEvent.VK_ALT, KeyEvent.VK_ALT_GRAPH -> {
|
||||
// both alts map to the 'commodore key' (same left alt)
|
||||
register(event.id, HostKeyPress(KeyEvent.VK_ALT, rightSide = false, numpad = false))
|
||||
}
|
||||
KeyEvent.VK_F2 -> {
|
||||
// F2 = shift+F1
|
||||
val func = HostKeyPress(KeyEvent.VK_F1, rightSide = false, numpad = false)
|
||||
register(event.id, shift, func)
|
||||
}
|
||||
KeyEvent.VK_F4 -> {
|
||||
// F4 = shift+F3
|
||||
val func = HostKeyPress(KeyEvent.VK_F3, rightSide = false, numpad = false)
|
||||
register(event.id, shift, func)
|
||||
}
|
||||
KeyEvent.VK_F6 -> {
|
||||
// F6 = shift+F5
|
||||
val func = HostKeyPress(KeyEvent.VK_F5, rightSide = false, numpad = false)
|
||||
register(event.id, shift, func)
|
||||
}
|
||||
KeyEvent.VK_F8 -> {
|
||||
// F8 = shift+F7
|
||||
val func = HostKeyPress(KeyEvent.VK_F7, rightSide = false, numpad = false)
|
||||
register(event.id, shift, func)
|
||||
}
|
||||
KeyEvent.VK_INSERT -> {
|
||||
// insert = shift+backspace(del)
|
||||
val backspace = HostKeyPress(KeyEvent.VK_BACK_SPACE, rightSide = false, numpad = false)
|
||||
register(event.id, shift, backspace)
|
||||
}
|
||||
KeyEvent.VK_UP -> {
|
||||
// up = shift+down
|
||||
val cursor = HostKeyPress(KeyEvent.VK_DOWN, rightSide = false, numpad = false)
|
||||
register(event.id, shift, cursor)
|
||||
}
|
||||
KeyEvent.VK_LEFT -> {
|
||||
// left = shift+right
|
||||
val cursor = HostKeyPress(KeyEvent.VK_RIGHT, rightSide = false, numpad = false)
|
||||
register(event.id, shift, cursor)
|
||||
}
|
||||
else -> {
|
||||
// just map the key as usual
|
||||
val hostkey = HostKeyPress(event.keyCode, rightSide, numpad)
|
||||
register(event.id, hostkey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package razorvine.c64emu
|
||||
|
||||
import razorvine.ksim65.Cpu6502
|
||||
import razorvine.ksim65.components.MemoryComponent
|
||||
import java.awt.*
|
||||
import java.awt.image.BufferedImage
|
||||
@ -60,13 +61,13 @@ private class BitmapScreenPanel(val chargenData: ByteArray, val ram: MemoryCompo
|
||||
|
||||
private fun loadCharacters(shifted: Boolean): Array<BufferedImage> {
|
||||
val chars = Array(256) { BufferedImage(8, 8, BufferedImage.TYPE_BYTE_BINARY) }
|
||||
val offset = if(shifted) 256*8 else 0
|
||||
val offset = if (shifted) 256 * 8 else 0
|
||||
// val color = ScreenDefs.colorPalette[14].rgb
|
||||
for(char in 0..255) {
|
||||
for(line in 0..7) {
|
||||
val charbyte = chargenData[offset + char*8 + line].toInt()
|
||||
for(x in 0..7) {
|
||||
if(charbyte and (0b10000000 ushr x) !=0 )
|
||||
for (char in 0..255) {
|
||||
for (line in 0..7) {
|
||||
val charbyte = chargenData[offset + char * 8 + line].toInt()
|
||||
for (x in 0..7) {
|
||||
if (charbyte and (0b10000000 ushr x) != 0)
|
||||
chars[char].setRGB(x, line, 0xffffff)
|
||||
}
|
||||
}
|
||||
@ -92,10 +93,10 @@ private class BitmapScreenPanel(val chargenData: ByteArray, val ram: MemoryCompo
|
||||
val shifted = (ram[0xd018].toInt() and 0b00000010) != 0
|
||||
g2d.background = ScreenDefs.colorPalette[ram[0xd021].toInt() and 15]
|
||||
g2d.clearRect(0, 0, ScreenDefs.SCREEN_WIDTH, ScreenDefs.SCREEN_HEIGHT)
|
||||
for(y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) {
|
||||
for(x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
||||
val char = ram[screen + x + y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
val color = ram[colors + x + y*ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
for (y in 0 until ScreenDefs.SCREEN_HEIGHT_CHARS) {
|
||||
for (x in 0 until ScreenDefs.SCREEN_WIDTH_CHARS) {
|
||||
val char = ram[screen + x + y * ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
val color = ram[colors + x + y * ScreenDefs.SCREEN_WIDTH_CHARS].toInt()
|
||||
drawColoredChar(x, y, char, color and 15, shifted)
|
||||
}
|
||||
}
|
||||
@ -105,18 +106,18 @@ private class BitmapScreenPanel(val chargenData: ByteArray, val ram: MemoryCompo
|
||||
|
||||
private fun drawColoredChar(x: Int, y: Int, char: Int, color: Int, shifted: Boolean) {
|
||||
var cached = coloredCharacters[Triple(char, color, shifted)]
|
||||
if(cached==null) {
|
||||
cached = if(shifted) shiftedCharacters[char] else normalCharacters[char]
|
||||
if (cached == null) {
|
||||
cached = if (shifted) shiftedCharacters[char] else normalCharacters[char]
|
||||
val colored = g2d.deviceConfiguration.createCompatibleImage(8, 8, BufferedImage.BITMASK)
|
||||
val sourceRaster = cached.raster
|
||||
val coloredRaster = colored.raster
|
||||
val pixelArray = IntArray(4)
|
||||
val javaColor = ScreenDefs.colorPalette[color]
|
||||
val coloredPixel = listOf(javaColor.red, javaColor.green, javaColor.blue, javaColor.alpha).toIntArray()
|
||||
for(pixelY in 0..7) {
|
||||
for(pixelX in 0..7) {
|
||||
for (pixelY in 0..7) {
|
||||
for (pixelX in 0..7) {
|
||||
val source = sourceRaster.getPixel(pixelX, pixelY, pixelArray)
|
||||
if(source[0]!=0) {
|
||||
if (source[0] != 0) {
|
||||
coloredRaster.setPixel(pixelX, pixelY, coloredPixel)
|
||||
}
|
||||
}
|
||||
@ -132,6 +133,7 @@ class MainC64Window(
|
||||
title: String,
|
||||
chargenData: ByteArray,
|
||||
val ram: MemoryComponent,
|
||||
val cpu: Cpu6502,
|
||||
val keypressCia: Cia
|
||||
) : JFrame(title), KeyListener {
|
||||
private val canvas = BitmapScreenPanel(chargenData, ram)
|
||||
@ -195,7 +197,7 @@ class MainC64Window(
|
||||
addKeyListener(this)
|
||||
pack()
|
||||
setLocationRelativeTo(null)
|
||||
location = Point(location.x/2, location.y)
|
||||
location = Point(location.x / 2, location.y)
|
||||
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, mutableSetOf())
|
||||
setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, mutableSetOf())
|
||||
requestFocusInWindow()
|
||||
@ -218,8 +220,14 @@ class MainC64Window(
|
||||
override fun keyTyped(event: KeyEvent) {}
|
||||
|
||||
override fun keyPressed(event: KeyEvent) {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
// '\' is mapped as RESTORE, this causes a NMI on the cpu
|
||||
if (event.keyChar == '\\') {
|
||||
cpu.nmi()
|
||||
} else {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
}
|
||||
}
|
||||
|
||||
override fun keyReleased(event: KeyEvent) {
|
||||
keypressCia.hostKeyPressed(event)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class C64Machine(title: String) : IVirtualMachine {
|
||||
// TODO: implement something so that RND(0) actually works in basic. (cia timer?)
|
||||
|
||||
private val debugWindow = DebugWindow(this)
|
||||
private val hostDisplay = MainC64Window(title, chargenData, ram, cia1)
|
||||
private val hostDisplay = MainC64Window(title, chargenData, ram, cpu, cia1)
|
||||
private var paused = false
|
||||
|
||||
init {
|
||||
|
Loading…
x
Reference in New Issue
Block a user