diff --git a/src/memory/mos652x/cia.rs b/src/memory/mos652x/cia.rs index 9b0d922..6d961a7 100644 --- a/src/memory/mos652x/cia.rs +++ b/src/memory/mos652x/cia.rs @@ -74,10 +74,11 @@ pub struct Cia { time_clock: TimeClock, shift_register: ShiftRegister, interrupts: InterruptRegister, + interrupt_connected: bool, } impl Cia { - pub fn new(port_a: Box, port_b: Box) -> Self { + pub fn new(port_a: Box, port_b: Box, interrupt_connected: bool) -> Self { Self { a: PortRegisters::new(port_a), b: PortRegisters::new(port_b), @@ -86,6 +87,7 @@ impl Cia { time_clock: TimeClock::new(), shift_register: ShiftRegister::new(), interrupts: InterruptRegister::new(), + interrupt_connected, } } } @@ -228,7 +230,11 @@ impl Memory for Cia { // TODO: stuff based on ca1, ca2, cb1, cb2 - active_interrupt + if self.interrupt_connected { + active_interrupt + } else { + ActiveInterrupt::None + } } } @@ -240,7 +246,7 @@ mod tests { #[test] fn test_read_write() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // writes without DDR shouldn't be reflected in reads cia.write(0x00, 0b10101010); @@ -266,7 +272,7 @@ mod tests { #[test] fn test_timer_a() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer A interrupts cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_A); @@ -290,9 +296,34 @@ mod tests { } } + #[test] + fn test_interrupt_disconnected() { + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), false); + + // enable timer A interrupts + cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_A); + + // set the timer to count down from 0x10 + cia.write(0x04, 0x10); + cia.write(0x05, 0x00); + + // start the timer, and disable continuous operation + cia.write(0x0E, 0b0000_1001); + + for _ in 0..0x0F { + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); + } + + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); + + for _ in 0..0x20 { + assert_eq!(ActiveInterrupt::None, cia.poll(1, 0)); + } + } + #[test] fn test_timer_b() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer B interrupts cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_B); @@ -313,7 +344,7 @@ mod tests { #[test] fn test_timer_a_continuous() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer A interrupts cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_A); @@ -336,7 +367,7 @@ mod tests { #[test] fn test_ier_timers() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_A); @@ -363,7 +394,7 @@ mod tests { #[test] fn test_interrupt_flags() { - let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut cia = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts cia.write(0x0D, interrupt_bits::MASTER | interrupt_bits::TIMER_A); diff --git a/src/memory/mos652x/pia.rs b/src/memory/mos652x/pia.rs index 415f501..0d8ffd8 100644 --- a/src/memory/mos652x/pia.rs +++ b/src/memory/mos652x/pia.rs @@ -128,14 +128,16 @@ pub mod pia_control_bits { pub struct Pia { a: PiaPortRegisters, b: PiaPortRegisters, + interrupt_connected: bool, } impl Pia { /// Create a new PIA with the two given port implementations. - pub fn new(a: Box, b: Box) -> Self { + pub fn new(a: Box, b: Box, interrupt_connected: bool) -> Self { Self { a: PiaPortRegisters::new(a), b: PiaPortRegisters::new(b), + interrupt_connected, } } } @@ -170,7 +172,7 @@ impl Memory for Pia { let a = self.a.poll(cycles_since_poll, total_cycle_count); let b = self.b.poll(cycles_since_poll, total_cycle_count); - if a || b { + if self.interrupt_connected && (a || b) { ActiveInterrupt::IRQ } else { ActiveInterrupt::None @@ -186,7 +188,7 @@ mod tests { #[test] fn test_read() { - let mut pia = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut pia = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // deselect the DDR pia.write(0x01, pia_control_bits::DDR_SELECT); @@ -210,7 +212,7 @@ mod tests { #[test] fn test_write() { - let mut pia = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut pia = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // deselect the DDR pia.write(0x01, pia_control_bits::DDR_SELECT); diff --git a/src/memory/mos652x/via.rs b/src/memory/mos652x/via.rs index 343ffac..f422e65 100644 --- a/src/memory/mos652x/via.rs +++ b/src/memory/mos652x/via.rs @@ -46,6 +46,7 @@ pub struct Via { sr: ShiftRegister, interrupts: InterruptRegister, pcr: u8, // peripheral control register + interrupt_connected: bool, } #[allow(dead_code)] @@ -61,7 +62,7 @@ pub mod interrupt_bits { } impl Via { - pub fn new(a: Box, b: Box) -> Self { + pub fn new(a: Box, b: Box, interrupt_connected: bool) -> Self { Self { a: PortRegisters::new(a), b: PortRegisters::new(b), @@ -70,6 +71,7 @@ impl Via { sr: ShiftRegister::new(), interrupts: InterruptRegister::new(), pcr: 0, + interrupt_connected, } } } @@ -250,7 +252,11 @@ impl Memory for Via { } } - active_interrupt + if self.interrupt_connected { + active_interrupt + } else { + ActiveInterrupt::None + } } } @@ -262,7 +268,7 @@ mod tests { #[test] fn test_read_write() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // writes without DDR shouldn't be reflected in reads via.write(0x00, 0b10101010); @@ -288,7 +294,7 @@ mod tests { #[test] fn test_timer_1() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T1); @@ -311,7 +317,7 @@ mod tests { #[test] fn test_timer_2() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 2 interrupts via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T2); @@ -334,7 +340,7 @@ mod tests { #[test] fn test_t1_continuous() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T1); @@ -361,7 +367,7 @@ mod tests { #[test] fn test_ier_register() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // put something in the register via.write( @@ -389,7 +395,7 @@ mod tests { #[test] fn test_ier_timers() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T1); @@ -410,9 +416,27 @@ mod tests { assert_eq!(ActiveInterrupt::IRQ, via.poll(1, 0)); } + #[test] + fn test_interrupt_disconnected() { + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), false); + + // enable timer 1 interrupts + via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T1); + + // set timer 1 to count down from 0x10 + via.write(0x04, 0x10); + via.write(0x05, 0x00); + // timer 1 should interrupt first + for _ in 0..0x0F { + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); + } + + assert_eq!(ActiveInterrupt::None, via.poll(1, 0)); + } + #[test] fn test_ifr() { - let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let mut via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); // enable timer 1 interrupts via.write(0x0e, interrupt_bits::MASTER | interrupt_bits::T1); diff --git a/src/systems/c64/mod.rs b/src/systems/c64/mod.rs index 2eb6550..face95e 100644 --- a/src/systems/c64/mod.rs +++ b/src/systems/c64/mod.rs @@ -263,9 +263,10 @@ impl BuildableSystem for C64System { config.mapping, platform.clone(), )), + true, ); - let cia_2 = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let cia_2 = Cia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); let region6 = BankedMemory::new(selector6.clone()) .bank( diff --git a/src/systems/pet/mod.rs b/src/systems/pet/mod.rs index 6369b50..e66b171 100644 --- a/src/systems/pet/mod.rs +++ b/src/systems/pet/mod.rs @@ -180,9 +180,9 @@ impl BuildableSystem for PetSystem { let port_a = PetPia1PortA::new(); let port_b = PetPia1PortB::new(port_a.get_keyboard_row(), config.mapping, platform); - let pia1 = Pia::new(Box::new(port_a), Box::new(port_b)); - let pia2 = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new())); - let via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new())); + let pia1 = Pia::new(Box::new(port_a), Box::new(port_b), true); + let pia2 = Pia::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); + let via = Via::new(Box::new(NullPort::new()), Box::new(NullPort::new()), true); let kernel_rom = BlockMemory::from_file(0x1000, roms.kernal); diff --git a/src/systems/vic/mod.rs b/src/systems/vic/mod.rs index 9b3149a..592d7cb 100644 --- a/src/systems/vic/mod.rs +++ b/src/systems/vic/mod.rs @@ -270,8 +270,8 @@ impl BuildableSystem for Vic20System { let v2b = VicVia2PortB::new(v1a.get_joy_pin_3()); let v2a = VicVia2PortA::new(v2b.get_keyboard_col(), config.mapping, platform); - let via1 = Via::new(Box::new(v1a), Box::new(NullPort::new())); - let via2 = Via::new(Box::new(v2a), Box::new(v2b)); + let via1 = Via::new(Box::new(v1a), Box::new(NullPort::new()), true); + let via2 = Via::new(Box::new(v2a), Box::new(v2b), true); let basic_rom = BlockMemory::from_file(0x2000, roms.basic); let kernel_rom = BlockMemory::from_file(0x2000, roms.kernal);