mirror of
https://github.com/irmen/ksim65.git
synced 2024-06-09 11:29:30 +00:00
tweak 6510 io port and fix overflow bug in TOD
This commit is contained in:
parent
99d8f5cd97
commit
35cbe4e3ca
|
@ -52,6 +52,8 @@ class Cia(val number: Int, startAddress: Address, endAddress: Address, val cpu:
|
||||||
if (updatedAt != latchedTime) {
|
if (updatedAt != latchedTime) {
|
||||||
updatedAt = latchedTime
|
updatedAt = latchedTime
|
||||||
var elapsedSeconds = (latchedTime.toDouble()-startedAt)/1000.0+userStartTime
|
var elapsedSeconds = (latchedTime.toDouble()-startedAt)/1000.0+userStartTime
|
||||||
|
if(elapsedSeconds>60*3600)
|
||||||
|
elapsedSeconds=0.0 // TOD counds max 60 hours
|
||||||
hours = (elapsedSeconds/3600).toInt()
|
hours = (elapsedSeconds/3600).toInt()
|
||||||
elapsedSeconds -= hours*3600
|
elapsedSeconds -= hours*3600
|
||||||
minutes = (elapsedSeconds/60).toInt()
|
minutes = (elapsedSeconds/60).toInt()
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package razorvine.c64emu
|
package razorvine.c64emu
|
||||||
|
|
||||||
import razorvine.ksim65.Cpu6502
|
|
||||||
import razorvine.ksim65.components.MemMappedComponent
|
import razorvine.ksim65.components.MemMappedComponent
|
||||||
import razorvine.ksim65.components.UByte
|
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).
|
* 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 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
|
var loram: Boolean = false // Bit 0: LORAM signal. Selects ROM or RAM at 40960 ($A000). 1=BASIC, 0=RAM
|
||||||
private set
|
private set
|
||||||
var hiram: Boolean = false // Bit 1: HIRAM signal. Selects ROM or RAM at 57344 ($E000). 1=Kernal, 0=RAM
|
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 {
|
override operator fun get(offset: Int): UByte {
|
||||||
return if(offset==0) dataDirections.toShort() else {
|
return if(offset==0) {
|
||||||
(ioPort or dataDirections.inv() and 0b00111111).toShort()
|
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()
|
dataDirections = data.toInt()
|
||||||
determineRoms()
|
determineRoms()
|
||||||
} else {
|
} else {
|
||||||
ioPort = data.toInt()
|
ioPort = (ioPort and dataDirections.inv()) or (data.toInt() and dataDirections)
|
||||||
determineRoms()
|
determineRoms()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun determineRoms() {
|
private fun determineRoms() {
|
||||||
if (dataDirections and 0b00000001 != 0) loram = ioPort and 0b00000001 != 0
|
loram = ioPort and 0b00000001 != 0
|
||||||
if (dataDirections and 0b00000010 != 0) hiram = ioPort and 0b00000010 != 0
|
hiram = ioPort and 0b00000010 != 0
|
||||||
if (dataDirections and 0b00000100 != 0) charen = ioPort and 0b00000100 != 0
|
charen = ioPort and 0b00000100 != 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,12 +39,12 @@ class C64Machine(title: String) : IVirtualMachine {
|
||||||
it.load(kernalData)
|
it.load(kernalData)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val cpu = Cpu6502()
|
val cpuIoPort = CpuIoPort()
|
||||||
val cpuIoPort = CpuIoPort(cpu)
|
|
||||||
|
|
||||||
// This bus contains "mmu" logic to control the memory bank switching controlled by the 6510's io port in $00/$01.
|
// 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.
|
// 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 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.
|
// the C64 has 64KB of RAM. Some of it may be banked out and replaced by ROM.
|
||||||
val ram = Ram(0x0000, 0xffff)
|
val ram = Ram(0x0000, 0xffff)
|
||||||
|
|
|
@ -9,14 +9,11 @@ import razorvine.ksim65.components.Ram
|
||||||
import razorvine.ksim65.components.Rom
|
import razorvine.ksim65.components.Rom
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
// TODO: run these tests by using the C64 machine emulation components
|
|
||||||
|
|
||||||
@Execution(ExecutionMode.CONCURRENT)
|
@Execution(ExecutionMode.CONCURRENT)
|
||||||
@Disabled("need to fix more c64 specific stuff here")
|
|
||||||
class Test6502TestSuiteC64Specific {
|
class Test6502TestSuiteC64Specific {
|
||||||
|
|
||||||
val cpu: Cpu6502 = Cpu6502()
|
val cpu: Cpu6502 = Cpu6502()
|
||||||
val ioPort = CpuIoPort(cpu)
|
val ioPort = CpuIoPort()
|
||||||
val ram = Ram(0, 0xffff)
|
val ram = Ram(0, 0xffff)
|
||||||
val bus: Bus
|
val bus: Bus
|
||||||
val kernalStubs = C64KernalStubs(ram)
|
val kernalStubs = C64KernalStubs(ram)
|
||||||
|
@ -108,106 +105,136 @@ class Test6502TestSuiteC64Specific {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1pb6() {
|
fun testCia1pb6() {
|
||||||
runTest("cia1pb6")
|
runTest("cia1pb6")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1pb7() {
|
fun testCia1pb7() {
|
||||||
runTest("cia1pb7")
|
runTest("cia1pb7")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1ta() {
|
fun testCia1ta() {
|
||||||
runTest("cia1ta")
|
runTest("cia1ta")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1tab() {
|
fun testCia1tab() {
|
||||||
runTest("cia1tab")
|
runTest("cia1tab")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1tb() {
|
fun testCia1tb() {
|
||||||
runTest("cia1tb")
|
runTest("cia1tb")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia1tb123() {
|
fun testCia1tb123() {
|
||||||
runTest("cia1tb123")
|
runTest("cia1tb123")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia2pb6() {
|
fun testCia2pb6() {
|
||||||
runTest("cia2pb6")
|
runTest("cia2pb6")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia2pb7() {
|
fun testCia2pb7() {
|
||||||
runTest("cia2pb7")
|
runTest("cia2pb7")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia2ta() {
|
fun testCia2ta() {
|
||||||
runTest("cia2ta")
|
runTest("cia2ta")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia2tb() {
|
fun testCia2tb() {
|
||||||
runTest("cia2tb")
|
runTest("cia2tb")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCia2tb123() {
|
fun testCia2tb123() {
|
||||||
runTest("cia2tb123")
|
runTest("cia2tb123")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCntdef() {
|
fun testCntdef() {
|
||||||
runTest("cntdef")
|
runTest("cntdef")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testCnto2() {
|
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")
|
runTest("cnto2")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCpuport() {
|
@Disabled("tests c64 specific hardware")
|
||||||
runTest("cpuport")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testCputiming() {
|
fun testCputiming() {
|
||||||
runTest("cputiming")
|
runTest("cputiming") // TODO fix this test once the cycle times are correct?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testFlipos() {
|
fun testFlipos() {
|
||||||
runTest("flipos")
|
runTest("flipos")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testIcr01() {
|
fun testIcr01() {
|
||||||
runTest("icr01")
|
runTest("icr01")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testImr() {
|
fun testImr() {
|
||||||
runTest("imr")
|
runTest("imr")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testIrq() {
|
fun testIrq() {
|
||||||
runTest("irq")
|
runTest("irq")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Disabled("tests c64 specific hardware")
|
||||||
fun testLoadth() {
|
fun testLoadth() {
|
||||||
runTest("loadth")
|
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
|
@Test
|
||||||
fun testMmu() {
|
fun testMmu() {
|
||||||
runTest("mmu")
|
runTest("mmu")
|
||||||
|
@ -217,14 +244,4 @@ class Test6502TestSuiteC64Specific {
|
||||||
fun testMmufetch() {
|
fun testMmufetch() {
|
||||||
runTest("mmufetch")
|
runTest("mmufetch")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testNmi() {
|
|
||||||
runTest("nmi")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testOneshot() {
|
|
||||||
runTest("oneshot")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
88
src/test/kotlin/TestC64Components.kt
Normal file
88
src/test/kotlin/TestC64Components.kt
Normal 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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user