1
0
mirror of https://github.com/irmen/ksim65.git synced 2025-02-09 01:30:44 +00:00

added CIA timers, this fixes basic's RND()

This commit is contained in:
Irmen de Jong 2019-09-26 22:59:14 +02:00
parent 02dca20f8d
commit 022d15d622

View File

@ -8,10 +8,11 @@ import java.awt.event.KeyEvent
/** /**
* Minimal simulation of the MOS 6526 CIA chip. * 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. * Depending on what CIA it is (1 or 2), some registers do different things on the C64.
* TODO implement at least Timer A, so that RND(0) starts working. * This implementation provides a working keyboard matrix, TOD clock, and the essentials of the timer A and B.
* TODO: timer IRQ triggering, more timer control bits.
*/ */
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 ramBuffer = Array<UByte>(endAddress - startAddress + 1) { 0 }
private var pra = 0xff private var pra = 0xff
class TimeOfDay { class TimeOfDay {
@ -54,6 +55,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
} }
private var tod = TimeOfDay() private var tod = TimeOfDay()
private var timerAset = 0
private var timerBset = 0
private var timerAactual = 0
private var timerBactual = 0
private data class HostKeyPress(val code: Int, val rightSide: Boolean=false, val numpad: Boolean=false) private data class HostKeyPress(val code: Int, val rightSide: Boolean=false, val numpad: Boolean=false)
@ -64,18 +69,31 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
} }
override fun clock() { override fun clock() {
// TODO: timer A and B countdowns, IRQ triggering.
tod.update() tod.update()
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
}
} }
override fun reset() { override fun reset() {
hostKeyPresses.clear() hostKeyPresses.clear()
tod.stop() tod.stop()
// TODO: reset timer A and B ramBuffer.fill(0)
timerAactual = 0
timerAset = 0
timerBactual = 0
timerBset = 0
} }
override fun get(address: Address): UByte { override fun get(address: Address): UByte {
fun scanColumn(keys: List<HostKeyPress>): UByte { fun scanColumn(vararg keys: HostKeyPress): UByte {
var bits = 0b10000000 var bits = 0b10000000
var presses = 0 var presses = 0
for (key in keys) { for (key in keys) {
@ -86,8 +104,7 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
} }
val register = (address - startAddress) and 15 val register = (address - startAddress) and 15
if (number == 1) { if (number == 1 && register == 0x01) {
if (register == 0x01) {
// register 1 on CIA#1 is the keyboard data port // 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 // if bit is cleared in PRA, contains keys pressed in that column of the matrix
return when (pra) { return when (pra) {
@ -98,7 +115,6 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
0b11111110 -> { 0b11111110 -> {
// read column 0 // read column 0
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_DOWN), HostKeyPress(KeyEvent.VK_DOWN),
HostKeyPress(KeyEvent.VK_F5), HostKeyPress(KeyEvent.VK_F5),
HostKeyPress(KeyEvent.VK_F3), HostKeyPress(KeyEvent.VK_F3),
@ -108,12 +124,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_ENTER), HostKeyPress(KeyEvent.VK_ENTER),
HostKeyPress(KeyEvent.VK_BACK_SPACE) HostKeyPress(KeyEvent.VK_BACK_SPACE)
) )
)
} }
0b11111101 -> { 0b11111101 -> {
// read column 1 // read column 1
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_SHIFT), // left shift HostKeyPress(KeyEvent.VK_SHIFT), // left shift
HostKeyPress(KeyEvent.VK_E), HostKeyPress(KeyEvent.VK_E),
HostKeyPress(KeyEvent.VK_S), HostKeyPress(KeyEvent.VK_S),
@ -123,12 +137,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_W), HostKeyPress(KeyEvent.VK_W),
HostKeyPress(KeyEvent.VK_3) HostKeyPress(KeyEvent.VK_3)
) )
)
} }
0b11111011 -> { 0b11111011 -> {
// read column 2 // read column 2
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_X), HostKeyPress(KeyEvent.VK_X),
HostKeyPress(KeyEvent.VK_T), HostKeyPress(KeyEvent.VK_T),
HostKeyPress(KeyEvent.VK_F), HostKeyPress(KeyEvent.VK_F),
@ -138,12 +150,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_R), HostKeyPress(KeyEvent.VK_R),
HostKeyPress(KeyEvent.VK_5) HostKeyPress(KeyEvent.VK_5)
) )
)
} }
0b11110111 -> { 0b11110111 -> {
// read column 3 // read column 3
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_V), HostKeyPress(KeyEvent.VK_V),
HostKeyPress(KeyEvent.VK_U), HostKeyPress(KeyEvent.VK_U),
HostKeyPress(KeyEvent.VK_H), HostKeyPress(KeyEvent.VK_H),
@ -153,12 +163,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_Y), HostKeyPress(KeyEvent.VK_Y),
HostKeyPress(KeyEvent.VK_7) HostKeyPress(KeyEvent.VK_7)
) )
)
} }
0b11101111 -> { 0b11101111 -> {
// read column 4 // read column 4
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_N), HostKeyPress(KeyEvent.VK_N),
HostKeyPress(KeyEvent.VK_O), HostKeyPress(KeyEvent.VK_O),
HostKeyPress(KeyEvent.VK_K), HostKeyPress(KeyEvent.VK_K),
@ -168,12 +176,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_I), HostKeyPress(KeyEvent.VK_I),
HostKeyPress(KeyEvent.VK_9) HostKeyPress(KeyEvent.VK_9)
) )
)
} }
0b11011111 -> { 0b11011111 -> {
// read column 5 // read column 5
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_COMMA), HostKeyPress(KeyEvent.VK_COMMA),
HostKeyPress(KeyEvent.VK_AT), HostKeyPress(KeyEvent.VK_AT),
HostKeyPress(KeyEvent.VK_COLON), HostKeyPress(KeyEvent.VK_COLON),
@ -183,12 +189,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_P), HostKeyPress(KeyEvent.VK_P),
HostKeyPress(KeyEvent.VK_PLUS) HostKeyPress(KeyEvent.VK_PLUS)
) )
)
} }
0b10111111 -> { 0b10111111 -> {
// read column 6 // read column 6
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_SLASH), HostKeyPress(KeyEvent.VK_SLASH),
HostKeyPress(KeyEvent.VK_CIRCUMFLEX), HostKeyPress(KeyEvent.VK_CIRCUMFLEX),
HostKeyPress(KeyEvent.VK_EQUALS), HostKeyPress(KeyEvent.VK_EQUALS),
@ -198,12 +202,10 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_ASTERISK), HostKeyPress(KeyEvent.VK_ASTERISK),
HostKeyPress(KeyEvent.VK_DEAD_TILDE) // pound sign HostKeyPress(KeyEvent.VK_DEAD_TILDE) // pound sign
) )
)
} }
0b01111111 -> { 0b01111111 -> {
// read column 7 // read column 7
scanColumn( scanColumn(
listOf(
HostKeyPress(KeyEvent.VK_ESCAPE), HostKeyPress(KeyEvent.VK_ESCAPE),
HostKeyPress(KeyEvent.VK_Q), HostKeyPress(KeyEvent.VK_Q),
HostKeyPress(KeyEvent.VK_ALT), HostKeyPress(KeyEvent.VK_ALT),
@ -213,7 +215,6 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
HostKeyPress(KeyEvent.VK_BACK_QUOTE), HostKeyPress(KeyEvent.VK_BACK_QUOTE),
HostKeyPress(KeyEvent.VK_1) HostKeyPress(KeyEvent.VK_1)
) )
)
} }
else -> { else -> {
// invalid column selection // invalid column selection
@ -221,10 +222,12 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
} }
} }
} else ramBuffer[register] } else ramBuffer[register]
}
return when (register) { return when (register) {
0x04 -> (timerAactual and 0xff).toShort()
0x05 -> (timerAactual ushr 8).toShort()
0x06 -> (timerBactual and 0xff).toShort()
0x07 -> (timerBactual ushr 8).toShort()
0x08 -> { 0x08 -> {
tod.start() tod.start()
(tod.tenths and 0x0f).toShort() (tod.tenths and 0x0f).toShort()
@ -262,31 +265,46 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address) : MemMapp
override fun set(address: Address, data: UByte) { override fun set(address: Address, data: UByte) {
val register = (address - startAddress) and 15 val register = (address - startAddress) and 15
ramBuffer[register] = data ramBuffer[register] = data
if (number == 1) { if (number == 1 && register == 0x00) {
when (register) {
0x00 -> {
// PRA data port A (select keyboard matrix column) // PRA data port A (select keyboard matrix column)
pra = data.toInt() pra = data.toInt()
} }
}
}
when (register) { when (register) {
0x08 -> { 0x04 -> {
tod.tenths = data.toInt() and 0x0f if(ramBuffer[0x0e].toInt() and 0b10000000 == 0) {
timerAset = (timerAset and 0xff00) or data.toInt()
timerAactual = timerAset
} }
0x09 -> {
tod.seconds = fromBCD(data)
} }
0x0a -> { 0x05 -> {
tod.minutes = fromBCD(data) if(ramBuffer[0x0e].toInt() and 0b10000000 == 0) {
timerAset = (timerAset and 0x00ff) or (data.toInt() shl 8)
timerAactual = timerAset
} }
}
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
}
}
0x08 -> tod.tenths = data.toInt() and 0x0f
0x09 -> tod.seconds = fromBCD(data)
0x0a -> tod.minutes = fromBCD(data)
0x0b -> { 0x0b -> {
tod.stop() tod.stop()
tod.hours = fromBCD(data) tod.hours = fromBCD(data)
if (data >= 12) if (data >= 12)
tod.hours = tod.hours or 0b10000000 tod.hours = tod.hours or 0b10000000
} }
// the timer A and B control registers are simply provided by the rambuffer for now.
} }
} }