tweak 6510 io port and fix overflow bug in TOD

This commit is contained in:
Irmen de Jong 2020-02-20 00:01:54 +01:00
parent 99d8f5cd97
commit 35cbe4e3ca
5 changed files with 144 additions and 32 deletions

View File

@ -52,6 +52,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
if (updatedAt != latchedTime) {
updatedAt = latchedTime
var elapsedSeconds = (latchedTime.toDouble()-startedAt)/1000.0+userStartTime
if(elapsedSeconds>60*3600)
elapsedSeconds=0.0 // TOD counds max 60 hours
hours = (elapsedSeconds/3600).toInt()
elapsedSeconds -= hours*3600
minutes = (elapsedSeconds/60).toInt()

View File

@ -1,6 +1,5 @@
package razorvine.c64emu
import razorvine.ksim65.Cpu6502
import razorvine.ksim65.components.MemMappedComponent
import razorvine.ksim65.components.UByte
@ -9,10 +8,11 @@ import razorvine.ksim65.components.UByte
* Controlling the memory layout, and cassette port (not processed at all).
*
*/
class CpuIoPort(val cpu: Cpu6502) : MemMappedComponent(0x0000, 0x0001) {
class CpuIoPort : MemMappedComponent(0x0000, 0x0001) {
private var dataDirections: Int = 0
private var ioPort: Int = 0xff
private var ioPort: Int = 0
var loram: Boolean = false // Bit 0: LORAM signal. Selects ROM or RAM at 40960 ($A000). 1=BASIC, 0=RAM
private set
var hiram: Boolean = false // Bit 1: HIRAM signal. Selects ROM or RAM at 57344 ($E000). 1=Kernal, 0=RAM
@ -28,8 +28,13 @@ class CpuIoPort(val cpu: Cpu6502) : MemMappedComponent(0x0000, 0x0001) {
}
override operator fun get(offset: Int): UByte {
return if(offset==0) dataDirections.toShort() else {
(ioPort or dataDirections.inv() and 0b00111111).toShort()
return if(offset==0) {
dataDirections.toShort()
} else {
if(dataDirections and 0b00100000 == 0)
(ioPort and 0b11011111).toShort() // bit 5 is low when input
else
ioPort.toShort()
}
}
@ -38,14 +43,14 @@ class CpuIoPort(val cpu: Cpu6502) : MemMappedComponent(0x0000, 0x0001) {
dataDirections = data.toInt()
determineRoms()
} else {
ioPort = data.toInt()
ioPort = (ioPort and dataDirections.inv()) or (data.toInt() and dataDirections)
determineRoms()
}
}
private fun determineRoms() {
if (dataDirections and 0b00000001 != 0) loram = ioPort and 0b00000001 != 0
if (dataDirections and 0b00000010 != 0) hiram = ioPort and 0b00000010 != 0
if (dataDirections and 0b00000100 != 0) charen = ioPort and 0b00000100 != 0
loram = ioPort and 0b00000001 != 0
hiram = ioPort and 0b00000010 != 0
charen = ioPort and 0b00000100 != 0
}
}

View File

@ -39,12 +39,12 @@ class C64Machine(title: String) : IVirtualMachine {
it.load(kernalData)
}
override val cpu = Cpu6502()
val cpuIoPort = CpuIoPort(cpu)
val cpuIoPort = CpuIoPort()
// This bus contains "mmu" logic to control the memory bank switching controlled by the 6510's io port in $00/$01.
// Therefore we provide it the various roms directly and not "connect" these to the bus in the default way.
override val bus = Bus6510(cpuIoPort, chargenRom, basicRom, kernalRom)
override val cpu = Cpu6502()
// the C64 has 64KB of RAM. Some of it may be banked out and replaced by ROM.
val ram = Ram(0x0000, 0xffff)

View File

@ -9,14 +9,11 @@ import razorvine.ksim65.components.Ram
import razorvine.ksim65.components.Rom
import kotlin.test.*
// TODO: run these tests by using the C64 machine emulation components
@Execution(ExecutionMode.CONCURRENT)
@Disabled("need to fix more c64 specific stuff here")
class Test6502TestSuiteC64Specific {
val cpu: Cpu6502 = Cpu6502()
val ioPort = CpuIoPort(cpu)
val ioPort = CpuIoPort()
val ram = Ram(0, 0xffff)
val bus: Bus
val kernalStubs = C64KernalStubs(ram)
@ -108,106 +105,136 @@ class Test6502TestSuiteC64Specific {
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1pb6() {
runTest("cia1pb6")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1pb7() {
runTest("cia1pb7")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1ta() {
runTest("cia1ta")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1tab() {
runTest("cia1tab")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1tb() {
runTest("cia1tb")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia1tb123() {
runTest("cia1tb123")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia2pb6() {
runTest("cia2pb6")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia2pb7() {
runTest("cia2pb7")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia2ta() {
runTest("cia2ta")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia2tb() {
runTest("cia2tb")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCia2tb123() {
runTest("cia2tb123")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCntdef() {
runTest("cntdef")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCnto2() {
// todo fix: When the timer input is switched from o2 to CNT or from CNT back to o2, there must be a two clock delay until the switch is recognized.
runTest("cnto2")
}
@Test
fun testCpuport() {
runTest("cpuport")
}
@Test
@Disabled("tests c64 specific hardware")
fun testCputiming() {
runTest("cputiming")
runTest("cputiming") // TODO fix this test once the cycle times are correct?
}
@Test
@Disabled("tests c64 specific hardware")
fun testFlipos() {
runTest("flipos")
}
@Test
@Disabled("tests c64 specific hardware")
fun testIcr01() {
runTest("icr01")
}
@Test
@Disabled("tests c64 specific hardware")
fun testImr() {
runTest("imr")
}
@Test
@Disabled("tests c64 specific hardware")
fun testIrq() {
runTest("irq")
}
@Test
@Disabled("tests c64 specific hardware")
fun testLoadth() {
runTest("loadth")
}
@Test
@Disabled("tests c64 specific hardware")
fun testNmi() {
runTest("nmi")
}
@Test
@Disabled("tests c64 specific hardware")
fun testOneshot() {
runTest("oneshot")
}
@Test
fun testCpuport() {
runTest("cpuport")
}
@Test
fun testMmu() {
runTest("mmu")
@ -217,14 +244,4 @@ class Test6502TestSuiteC64Specific {
fun testMmufetch() {
runTest("mmufetch")
}
@Test
fun testNmi() {
runTest("nmi")
}
@Test
fun testOneshot() {
runTest("oneshot")
}
}

View File

@ -0,0 +1,88 @@
import razorvine.c64emu.CpuIoPort
import kotlin.test.*
class TestC64Components {
@Test
fun testCpuIoPort() {
val io = CpuIoPort()
io.reset()
assertEquals(0xef, io[0])
assertEquals(0x37, io[1])
io[0] = 0b11111111
io[1] = 0b11111111
assertEquals(0b11111111,io[0])
assertEquals(0b11111111,io[1])
io[0] = 0
assertEquals(0b11011111,io[1], "bit 5 (cassette motor) is drawn low if input")
io[0] = 0b11111111
assertEquals(0b11111111,io[1], "bit 5 (cassette motor) is high if output")
io[1] = 0x37
io[0] = 0b00100000
assertEquals(0b00100000, io[0])
assertEquals(0x37, io[1])
io[0] = 0xff
assertEquals(0xff, io[0])
assertEquals(0x37, io[1])
io[1] = 0b11110000
assertEquals(0b11110000, io[1])
io[0] = 0b00100000
io[1] = 0b01010101
assertEquals(0b11010000, io[1])
io[0] = 0b00100001
assertEquals(0b11010000, io[1])
io[1] = 0b01010101
assertEquals(0b11010001, io[1])
io[0] = 0b11000011
assertEquals(0b11010001, io[1])
io[1] = 0b00100000
assertEquals(0b00010000, io[1])
io[1] = 0b11111111
assertEquals(0b11010011, io[1])
}
@Test
fun testRoms() {
val io = CpuIoPort()
io.reset()
assertTrue(io.loram)
assertTrue(io.hiram)
assertTrue(io.charen)
io[0] = 0
io[1] = 0
assertTrue(io.loram)
assertTrue(io.hiram)
assertTrue(io.charen)
io[0] = 255
assertTrue(io.loram)
assertTrue(io.hiram)
assertTrue(io.charen)
io[1] = 0b1111110
assertFalse(io.loram)
assertTrue(io.hiram)
assertTrue(io.charen)
io[1] = 0b1111101
assertTrue(io.loram)
assertFalse(io.hiram)
assertTrue(io.charen)
io[1] = 0b1111011
assertTrue(io.loram)
assertTrue(io.hiram)
assertFalse(io.charen)
}
}