2019-09-23 23:22:54 +00:00
|
|
|
package razorvine.c64emu
|
|
|
|
|
|
|
|
import razorvine.ksim65.components.Address
|
|
|
|
import razorvine.ksim65.components.MemMappedComponent
|
|
|
|
import razorvine.ksim65.components.UByte
|
2019-09-24 19:14:24 +00:00
|
|
|
import java.awt.event.KeyEvent
|
2019-09-23 23:22:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2019-09-26 20:59:14 +00:00
|
|
|
* This implementation provides a working keyboard matrix, TOD clock, and the essentials of the timer A and B.
|
2019-10-05 13:14:26 +00:00
|
|
|
* TODO: timer IRQ triggering, more timer control bits. Validate that the timerA/B timing is cycle correct.
|
2019-09-23 23:22:54 +00:00
|
|
|
*/
|
2019-09-25 20:58:58 +00:00
|
|
|
class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMappedComponent(startAddress, endAddress) {
|
2019-09-26 20:59:14 +00:00
|
|
|
private var ramBuffer = Array<UByte>(endAddress - startAddress + 1) { 0 }
|
2019-09-23 23:22:54 +00:00
|
|
|
private var pra = 0xff
|
|
|
|
|
2019-09-25 23:31:39 +00:00
|
|
|
class TimeOfDay {
|
|
|
|
private var updatedAt = 0L
|
|
|
|
private var startedAt = 0L
|
|
|
|
private var userStartTime = 0.0
|
|
|
|
private var running = false
|
|
|
|
var hours = 0
|
|
|
|
var minutes = 0
|
|
|
|
var seconds = 0
|
|
|
|
var tenths = 0
|
2019-10-05 20:22:06 +00:00
|
|
|
private var latchedTime = 0L
|
|
|
|
private var latched = false
|
2019-09-25 23:31:39 +00:00
|
|
|
|
|
|
|
fun start() {
|
2019-09-26 18:56:13 +00:00
|
|
|
if (!running) {
|
2019-09-25 23:31:39 +00:00
|
|
|
updatedAt = System.currentTimeMillis()
|
|
|
|
startedAt = updatedAt
|
|
|
|
userStartTime = hours * 3600 + minutes * 60 + seconds + tenths / 10.0
|
|
|
|
running = true
|
|
|
|
}
|
2019-10-05 20:22:06 +00:00
|
|
|
latch(false)
|
2019-09-25 23:31:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fun stop() {
|
|
|
|
running = false
|
|
|
|
}
|
|
|
|
|
2019-10-05 20:22:06 +00:00
|
|
|
fun latch(latched: Boolean) {
|
|
|
|
this.latched = latched
|
|
|
|
update()
|
|
|
|
}
|
|
|
|
|
2019-09-25 23:31:39 +00:00
|
|
|
fun update() {
|
2019-10-05 20:22:06 +00:00
|
|
|
if(!running || latched)
|
|
|
|
return
|
|
|
|
latchedTime = System.currentTimeMillis()
|
|
|
|
if (updatedAt != latchedTime) {
|
|
|
|
updatedAt = latchedTime
|
|
|
|
var elapsedSeconds = (latchedTime.toDouble() - startedAt) / 1000.0 + userStartTime
|
2019-09-25 23:31:39 +00:00
|
|
|
hours = (elapsedSeconds / 3600).toInt()
|
|
|
|
elapsedSeconds -= hours * 3600
|
|
|
|
minutes = (elapsedSeconds / 60).toInt()
|
|
|
|
elapsedSeconds -= minutes * 60
|
|
|
|
seconds = (elapsedSeconds).toInt()
|
|
|
|
elapsedSeconds -= seconds
|
|
|
|
tenths = (elapsedSeconds * 10).toInt()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-04 18:39:57 +00:00
|
|
|
private var totalCycles = 0
|
2019-09-25 23:31:39 +00:00
|
|
|
private var tod = TimeOfDay()
|
2019-09-26 20:59:14 +00:00
|
|
|
private var timerAset = 0
|
|
|
|
private var timerBset = 0
|
|
|
|
private var timerAactual = 0
|
|
|
|
private var timerBactual = 0
|
2019-09-25 23:31:39 +00:00
|
|
|
|
2019-09-26 18:56:13 +00:00
|
|
|
private data class HostKeyPress(val code: Int, val rightSide: Boolean=false, val numpad: Boolean=false)
|
2019-09-25 20:58:58 +00:00
|
|
|
|
|
|
|
private val hostKeyPresses = mutableSetOf<HostKeyPress>()
|
2019-09-24 19:14:24 +00:00
|
|
|
|
2019-09-23 23:22:54 +00:00
|
|
|
init {
|
|
|
|
require(endAddress - startAddress + 1 == 256) { "cia requires exactly 256 memory bytes (16*16 mirrored)" }
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun clock() {
|
2019-10-04 18:39:57 +00:00
|
|
|
totalCycles++
|
|
|
|
|
|
|
|
if(totalCycles % 20000 == 0) {
|
|
|
|
// TOD resolution is 0.1 second, no need to update it in every cycle
|
|
|
|
tod.update()
|
|
|
|
}
|
|
|
|
|
2019-09-26 20:59:14 +00:00
|
|
|
if(ramBuffer[0x0e].toInt() and 1 != 0) {
|
|
|
|
timerAactual--
|
|
|
|
if(timerAactual<0)
|
|
|
|
timerAactual = if(ramBuffer[0x0e].toInt() and 0b1000 != 0) 0 else timerAset
|
|
|
|
}
|
|
|
|
if(ramBuffer[0x0f].toInt() and 1 != 0) {
|
|
|
|
timerBactual--
|
|
|
|
if(timerBactual<0)
|
|
|
|
timerBactual = if(ramBuffer[0x0f].toInt() and 0b1000 != 0) 0 else timerBset
|
|
|
|
}
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun reset() {
|
2019-09-25 20:58:58 +00:00
|
|
|
hostKeyPresses.clear()
|
2019-09-25 23:31:39 +00:00
|
|
|
tod.stop()
|
2019-09-26 20:59:14 +00:00
|
|
|
ramBuffer.fill(0)
|
|
|
|
timerAactual = 0
|
|
|
|
timerAset = 0
|
|
|
|
timerBactual = 0
|
|
|
|
timerBset = 0
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun get(address: Address): UByte {
|
2019-09-26 20:59:14 +00:00
|
|
|
fun scanColumn(vararg keys: HostKeyPress): UByte {
|
2019-09-25 20:58:58 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2019-09-23 23:22:54 +00:00
|
|
|
val register = (address - startAddress) and 15
|
2019-09-26 20:59:14 +00:00
|
|
|
if (number == 1 && 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
|
|
|
|
return 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()
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
2019-09-26 20:59:14 +00:00
|
|
|
0b11111110 -> {
|
|
|
|
// read column 0
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_DOWN),
|
|
|
|
HostKeyPress(KeyEvent.VK_F5),
|
|
|
|
HostKeyPress(KeyEvent.VK_F3),
|
|
|
|
HostKeyPress(KeyEvent.VK_F1),
|
|
|
|
HostKeyPress(KeyEvent.VK_F7),
|
|
|
|
HostKeyPress(KeyEvent.VK_RIGHT),
|
|
|
|
HostKeyPress(KeyEvent.VK_ENTER),
|
|
|
|
HostKeyPress(KeyEvent.VK_BACK_SPACE)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b11111101 -> {
|
|
|
|
// read column 1
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_SHIFT), // left shift
|
|
|
|
HostKeyPress(KeyEvent.VK_E),
|
|
|
|
HostKeyPress(KeyEvent.VK_S),
|
|
|
|
HostKeyPress(KeyEvent.VK_Z),
|
|
|
|
HostKeyPress(KeyEvent.VK_4),
|
|
|
|
HostKeyPress(KeyEvent.VK_A),
|
|
|
|
HostKeyPress(KeyEvent.VK_W),
|
|
|
|
HostKeyPress(KeyEvent.VK_3)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b11111011 -> {
|
|
|
|
// read column 2
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_X),
|
|
|
|
HostKeyPress(KeyEvent.VK_T),
|
|
|
|
HostKeyPress(KeyEvent.VK_F),
|
|
|
|
HostKeyPress(KeyEvent.VK_C),
|
|
|
|
HostKeyPress(KeyEvent.VK_6),
|
|
|
|
HostKeyPress(KeyEvent.VK_D),
|
|
|
|
HostKeyPress(KeyEvent.VK_R),
|
|
|
|
HostKeyPress(KeyEvent.VK_5)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b11110111 -> {
|
|
|
|
// read column 3
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_V),
|
|
|
|
HostKeyPress(KeyEvent.VK_U),
|
|
|
|
HostKeyPress(KeyEvent.VK_H),
|
|
|
|
HostKeyPress(KeyEvent.VK_B),
|
|
|
|
HostKeyPress(KeyEvent.VK_8),
|
|
|
|
HostKeyPress(KeyEvent.VK_G),
|
|
|
|
HostKeyPress(KeyEvent.VK_Y),
|
|
|
|
HostKeyPress(KeyEvent.VK_7)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b11101111 -> {
|
|
|
|
// read column 4
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_N),
|
|
|
|
HostKeyPress(KeyEvent.VK_O),
|
|
|
|
HostKeyPress(KeyEvent.VK_K),
|
|
|
|
HostKeyPress(KeyEvent.VK_M),
|
|
|
|
HostKeyPress(KeyEvent.VK_0),
|
|
|
|
HostKeyPress(KeyEvent.VK_J),
|
|
|
|
HostKeyPress(KeyEvent.VK_I),
|
|
|
|
HostKeyPress(KeyEvent.VK_9)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b11011111 -> {
|
|
|
|
// read column 5
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_COMMA),
|
|
|
|
HostKeyPress(KeyEvent.VK_AT),
|
|
|
|
HostKeyPress(KeyEvent.VK_COLON),
|
|
|
|
HostKeyPress(KeyEvent.VK_PERIOD),
|
|
|
|
HostKeyPress(KeyEvent.VK_MINUS),
|
|
|
|
HostKeyPress(KeyEvent.VK_L),
|
|
|
|
HostKeyPress(KeyEvent.VK_P),
|
|
|
|
HostKeyPress(KeyEvent.VK_PLUS)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b10111111 -> {
|
|
|
|
// read column 6
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_SLASH),
|
|
|
|
HostKeyPress(KeyEvent.VK_CIRCUMFLEX),
|
|
|
|
HostKeyPress(KeyEvent.VK_EQUALS),
|
|
|
|
HostKeyPress(KeyEvent.VK_SHIFT, rightSide = true), // right shift
|
|
|
|
HostKeyPress(KeyEvent.VK_HOME),
|
|
|
|
HostKeyPress(KeyEvent.VK_SEMICOLON),
|
|
|
|
HostKeyPress(KeyEvent.VK_ASTERISK),
|
|
|
|
HostKeyPress(KeyEvent.VK_DEAD_TILDE) // pound sign
|
|
|
|
)
|
|
|
|
}
|
|
|
|
0b01111111 -> {
|
|
|
|
// read column 7
|
|
|
|
scanColumn(
|
|
|
|
HostKeyPress(KeyEvent.VK_ESCAPE),
|
|
|
|
HostKeyPress(KeyEvent.VK_Q),
|
|
|
|
HostKeyPress(KeyEvent.VK_ALT),
|
|
|
|
HostKeyPress(KeyEvent.VK_SPACE),
|
|
|
|
HostKeyPress(KeyEvent.VK_2),
|
|
|
|
HostKeyPress(KeyEvent.VK_CONTROL),
|
|
|
|
HostKeyPress(KeyEvent.VK_BACK_QUOTE),
|
|
|
|
HostKeyPress(KeyEvent.VK_1)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
else -> {
|
|
|
|
// invalid column selection
|
|
|
|
0xff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else ramBuffer[register]
|
2019-09-25 23:31:39 +00:00
|
|
|
|
|
|
|
return when (register) {
|
2019-09-26 20:59:14 +00:00
|
|
|
0x04 -> (timerAactual and 0xff).toShort()
|
|
|
|
0x05 -> (timerAactual ushr 8).toShort()
|
|
|
|
0x06 -> (timerBactual and 0xff).toShort()
|
|
|
|
0x07 -> (timerBactual ushr 8).toShort()
|
2019-09-25 23:31:39 +00:00
|
|
|
0x08 -> {
|
|
|
|
tod.start()
|
|
|
|
(tod.tenths and 0x0f).toShort()
|
|
|
|
}
|
2019-10-04 18:39:57 +00:00
|
|
|
0x09 -> toBCD(tod.seconds)
|
|
|
|
0x0a -> toBCD(tod.minutes)
|
2019-10-05 20:22:06 +00:00
|
|
|
0x0b -> {
|
|
|
|
tod.latch(true)
|
|
|
|
toBCD(tod.hours)
|
|
|
|
}
|
2019-09-25 23:31:39 +00:00
|
|
|
else -> ramBuffer[register]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun toBCD(data: Int): UByte {
|
|
|
|
val tens = data / 10
|
2019-09-26 18:56:13 +00:00
|
|
|
val ones = data - tens * 10
|
2019-09-25 23:31:39 +00:00
|
|
|
return ((tens shl 4) or ones).toShort()
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun fromBCD(bcd: UByte): Int {
|
|
|
|
val ibcd = bcd.toInt()
|
|
|
|
val tens = ibcd ushr 4
|
|
|
|
val ones = ibcd and 0x0f
|
2019-09-26 18:56:13 +00:00
|
|
|
return tens * 10 + ones
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun set(address: Address, data: UByte) {
|
|
|
|
val register = (address - startAddress) and 15
|
|
|
|
ramBuffer[register] = data
|
2019-09-26 20:59:14 +00:00
|
|
|
if (number == 1 && register == 0x00) {
|
|
|
|
// PRA data port A (select keyboard matrix column)
|
|
|
|
pra = data.toInt()
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
2019-09-25 23:31:39 +00:00
|
|
|
|
|
|
|
when (register) {
|
2019-09-26 20:59:14 +00:00
|
|
|
0x04 -> {
|
|
|
|
if(ramBuffer[0x0e].toInt() and 0b10000000 == 0) {
|
|
|
|
timerAset = (timerAset and 0xff00) or data.toInt()
|
|
|
|
timerAactual = timerAset
|
|
|
|
}
|
2019-09-26 18:56:13 +00:00
|
|
|
}
|
2019-09-26 20:59:14 +00:00
|
|
|
0x05 -> {
|
|
|
|
if(ramBuffer[0x0e].toInt() and 0b10000000 == 0) {
|
|
|
|
timerAset = (timerAset and 0x00ff) or (data.toInt() shl 8)
|
|
|
|
timerAactual = timerAset
|
|
|
|
}
|
2019-09-26 18:56:13 +00:00
|
|
|
}
|
2019-09-26 20:59:14 +00:00
|
|
|
0x06 -> {
|
|
|
|
if(ramBuffer[0x0f].toInt() and 0b10000000 == 0) {
|
|
|
|
timerBset = (timerBset and 0xff00) or data.toInt()
|
|
|
|
timerBactual = timerBset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
0x07 -> {
|
|
|
|
if(ramBuffer[0x0f].toInt() and 0b10000000 == 0) {
|
|
|
|
timerBset = (timerBset and 0x00ff) or (data.toInt() shl 8)
|
|
|
|
timerBactual = timerBset
|
|
|
|
}
|
2019-09-26 18:56:13 +00:00
|
|
|
}
|
2019-09-26 20:59:14 +00:00
|
|
|
0x08 -> tod.tenths = data.toInt() and 0x0f
|
|
|
|
0x09 -> tod.seconds = fromBCD(data)
|
|
|
|
0x0a -> tod.minutes = fromBCD(data)
|
2019-09-25 23:31:39 +00:00
|
|
|
0x0b -> {
|
|
|
|
tod.stop()
|
|
|
|
tod.hours = fromBCD(data)
|
|
|
|
}
|
2019-09-26 20:59:14 +00:00
|
|
|
// the timer A and B control registers are simply provided by the rambuffer for now.
|
2019-09-25 23:31:39 +00:00
|
|
|
}
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|
2019-09-24 19:14:24 +00:00
|
|
|
|
|
|
|
fun hostKeyPressed(event: KeyEvent) {
|
2019-09-25 20:58:58 +00:00
|
|
|
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
|
2019-10-04 18:39:57 +00:00
|
|
|
// (this can happen because we're changing the keycode for some pressed keys below,
|
2019-09-25 20:58:58 +00:00
|
|
|
// 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)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_AT))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
event.keyChar == '^' -> {
|
|
|
|
unregister(KeyEvent.VK_SHIFT)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_CIRCUMFLEX))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
event.keyChar == '*' -> {
|
|
|
|
unregister(KeyEvent.VK_SHIFT)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_ASTERISK))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
event.keyChar == '+' -> {
|
|
|
|
unregister(KeyEvent.VK_SHIFT)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_PLUS))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
event.keyChar == ':' -> {
|
|
|
|
unregister(KeyEvent.VK_SHIFT)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_COLON))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
event.keyChar == '~' -> {
|
|
|
|
unregister(KeyEvent.VK_SHIFT)
|
2019-09-26 18:56:13 +00:00
|
|
|
register(event.id, HostKeyPress(KeyEvent.VK_DEAD_TILDE))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
2019-09-26 18:56:13 +00:00
|
|
|
event.keyChar == '&' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_6))
|
|
|
|
event.keyChar == '(' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_8))
|
|
|
|
event.keyChar == ')' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_9))
|
|
|
|
event.keyChar == '[' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_COLON))
|
|
|
|
event.keyChar == ']' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_SEMICOLON))
|
|
|
|
event.keyChar == '"' -> register(event.id, HostKeyPress(KeyEvent.VK_2))
|
|
|
|
event.keyChar == '\'' -> register(event.id, shift, HostKeyPress(KeyEvent.VK_7))
|
|
|
|
else ->
|
|
|
|
// F2 = shift+F1
|
|
|
|
// F4 = shift+F3
|
|
|
|
// F6 = shift+F5
|
|
|
|
// F8 = shift+F7
|
|
|
|
// insert = shift+backspace(del)
|
|
|
|
// up = shift+down
|
|
|
|
// left = shift+right
|
|
|
|
// just map the key as usual
|
|
|
|
// both alts map to the 'commodore key' (same left alt)
|
|
|
|
// both controls and the tab key map to the 'single left control'
|
|
|
|
when (event.keyCode) {
|
|
|
|
KeyEvent.VK_CONTROL, KeyEvent.VK_TAB -> register(event.id, HostKeyPress(KeyEvent.VK_CONTROL))
|
|
|
|
KeyEvent.VK_ALT, KeyEvent.VK_ALT_GRAPH -> register(event.id, HostKeyPress(KeyEvent.VK_ALT))
|
|
|
|
KeyEvent.VK_F2 -> register(event.id, shift, HostKeyPress(KeyEvent.VK_F1))
|
|
|
|
KeyEvent.VK_F4 -> register(event.id, shift, HostKeyPress(KeyEvent.VK_F3))
|
|
|
|
KeyEvent.VK_F6 -> register(event.id, shift, HostKeyPress(KeyEvent.VK_F5))
|
|
|
|
KeyEvent.VK_F8 -> register(event.id, shift, HostKeyPress(KeyEvent.VK_F7))
|
|
|
|
KeyEvent.VK_INSERT -> register(event.id, shift, HostKeyPress(KeyEvent.VK_BACK_SPACE))
|
|
|
|
KeyEvent.VK_UP -> register(event.id, shift, HostKeyPress(KeyEvent.VK_DOWN))
|
|
|
|
KeyEvent.VK_LEFT -> register(event.id, shift, HostKeyPress(KeyEvent.VK_RIGHT))
|
|
|
|
else -> register(event.id, HostKeyPress(event.keyCode, rightSide, numpad))
|
2019-09-25 20:58:58 +00:00
|
|
|
}
|
|
|
|
}
|
2019-09-24 19:14:24 +00:00
|
|
|
}
|
2019-09-23 23:22:54 +00:00
|
|
|
}
|