From 837cccdf835ac926cbd3e3b4ce977c13e76b8a8f Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 4 Mar 2017 14:58:28 -0500 Subject: [PATCH 1/3] Switched to deferred updates for the 6532. --- Machines/Atari2600/Atari2600.cpp | 10 +++++++++- Machines/Atari2600/Atari2600.hpp | 8 ++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index e7454d630..aa6e3fdd7 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -22,6 +22,7 @@ Machine::Machine() : tia_input_value_{0xff, 0xff}, cycles_since_speaker_update_(0), cycles_since_video_update_(0), + cycles_since_6532_update_(0), frame_record_pointer_(0), is_ntsc_(true) { @@ -203,6 +204,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin // check for a PIA access if((address&0x1280) == 0x280) { + update_6532(); if(isReadOperation(operation)) { returnValue &= mos6532_.get_register(address); } else { @@ -216,7 +218,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin } if(!tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_)) set_ready_line(false); - mos6532_.run_for_cycles(cycles_run_for / 3); + cycles_since_6532_update_ += (cycles_run_for / 3); return cycles_run_for / 3; } @@ -321,6 +323,12 @@ void Machine::update_video() cycles_since_video_update_ = 0; } +void Machine::update_6532() +{ + mos6532_.run_for_cycles(cycles_since_6532_update_); + cycles_since_6532_update_ = 0; +} + void Machine::synchronise() { update_audio(); diff --git a/Machines/Atari2600/Atari2600.hpp b/Machines/Atari2600/Atari2600.hpp index 68c45e97b..ad1a076aa 100644 --- a/Machines/Atari2600/Atari2600.hpp +++ b/Machines/Atari2600/Atari2600.hpp @@ -77,11 +77,15 @@ class Machine: // speaker backlog accumlation counter unsigned int cycles_since_speaker_update_; - void update_audio(); + inline void update_audio(); // video backlog accumulation counter unsigned int cycles_since_video_update_; - void update_video(); + inline void update_video(); + + // RIOT backlog accumulation counter + unsigned int cycles_since_6532_update_; + inline void update_6532(); // output frame rate tracker struct FrameRecord From e09b76bf326f30536f53d00acc1c896719ee384e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 4 Mar 2017 15:57:54 -0500 Subject: [PATCH 2/3] Fixed 'same value, then immediate increment, then proper counting increments' behaviour and ensured it takes one cycle to commit a value. Adjusted tests to match. --- Components/6532/6532.hpp | 2 +- .../Mac/Clock SignalTests/6532Tests.swift | 76 ++++++++++++++----- 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/Components/6532/6532.hpp b/Components/6532/6532.hpp index acf57f66d..acfb7de78 100644 --- a/Components/6532/6532.hpp +++ b/Components/6532/6532.hpp @@ -51,7 +51,7 @@ template class MOS6532 { if(address & 0x10) { timer_.writtenShift = timer_.activeShift = (decodedAddress - 0x04) * 3 + (decodedAddress / 0x07); // i.e. 0, 3, 6, 10 - timer_.value = ((unsigned int)(value) << timer_.activeShift) | ((1 << timer_.activeShift)-1); + timer_.value = ((unsigned int)value << timer_.activeShift) + 2; timer_.interrupt_enabled = !!(address&0x08); interrupt_status_ &= ~InterruptFlag::Timer; evaluate_interrupts(); diff --git a/OSBindings/Mac/Clock SignalTests/6532Tests.swift b/OSBindings/Mac/Clock SignalTests/6532Tests.swift index 86150f74a..091fdfd0e 100644 --- a/OSBindings/Mac/Clock SignalTests/6532Tests.swift +++ b/OSBindings/Mac/Clock SignalTests/6532Tests.swift @@ -21,14 +21,29 @@ class MOS6532Tests: XCTestCase { with6532 { // set a count of 128 at single-clock intervals $0.setValue(128, forRegister:0x14) - - // run for one clock and the count should now be 127 $0.run(forCycles: 1) - XCTAssert($0.value(forRegister: 4) == 127, "A single tick should decrease the counter once") - // run for a further 200 clock counts; timer should reach -73 = 183 - $0.run(forCycles: 200) - XCTAssert($0.value(forRegister: 4) == 183, "Timer should underflow and keep counting") + // one cycle later the timer should still contain 128 + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 4), 128) + + // run for one more clock and the count should now be 127 + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 4), 127) + + // run for 127 clocks and the timer should be zero, but the timer flag will not yet be set + $0.run(forCycles: 127) + XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0) + XCTAssertEqual($0.value(forRegister: 4), 0) + + // after one more cycle the counter should be 255 and the timer flag will now be set + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0x80) + XCTAssertEqual($0.value(forRegister: 4), 255) + + // run for a further 55 clock counts; timer should reach -200 + $0.run(forCycles: 55) + XCTAssertEqual($0.value(forRegister: 4), 200) } } @@ -37,26 +52,44 @@ class MOS6532Tests: XCTestCase { with6532 { // set a count of 28 at eight-clock intervals $0.setValue(28, forRegister:0x15) - - // run for seven clock and the count should still be 28 - $0.run(forCycles: 7) - XCTAssert($0.value(forRegister: 4) == 28, "The timer should remain unchanged for seven clocks") - - // run for a further clock and the count should now be 27 $0.run(forCycles: 1) - XCTAssert($0.value(forRegister: 4) == 27, "The timer should have decremented once after 8 cycles") - // run for a further 7 + 27*8 + 5 = 228 clock counts; timer should reach -5 = 0xfb - $0.run(forCycles: 228) - XCTAssert($0.value(forRegister: 4) == 0xfb, "Timer should underflow and start counting at single-clock pace") + // one cycle later the timer should still contain 28 + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 4), 28) + + // one further cycle and the timer should hit 27 + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 4), 27) + + // run for seven clock and the count should still be 27 + $0.run(forCycles: 7) + XCTAssertEqual($0.value(forRegister: 4), 27) + + // run for a further clock and the count should now be 26 + $0.run(forCycles: 1) + XCTAssertEqual($0.value(forRegister: 4), 26) + + // run for another 26 * 8 = 208 cycles and the count should hit zero without setting the timer flag, and + // stay there for seven more cycles + $0.run(forCycles: 208) + for _ in 0 ..< 8 { + XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0) + XCTAssertEqual($0.value(forRegister: 4), 0) + $0.run(forCycles: 1) + } + + // run six more, and the timer should reach 249, with the interrupt flag set + $0.run(forCycles: 6) + XCTAssertEqual($0.value(forRegister: 5) & 0x80, 0x80) + XCTAssertEqual($0.value(forRegister: 4), 249) // timer should now resume dividing by eight $0.run(forCycles: 7) - XCTAssert($0.value(forRegister: 4) == 0xfb, "Timer should remain unchanged for seven cycles") + XCTAssertEqual($0.value(forRegister: 4), 249) - // timer should now resume dividing by eight $0.run(forCycles: 1) - XCTAssert($0.value(forRegister: 4) == 0xfa, "Timer should decrement after eighth cycle") + XCTAssertEqual($0.value(forRegister: 4), 248) } } @@ -64,10 +97,11 @@ class MOS6532Tests: XCTestCase { with6532 { // set a count of 1 at single-clock intervals $0.setValue(1, forRegister:0x1c) - - // run for one clock and the count should now be zero $0.run(forCycles: 1) + // run for two clocks and the count should now be zero + $0.run(forCycles: 2) + // interrupt shouldn't be signalled yet, bit should not be set XCTAssert(!$0.irqLine, "IRQ line should not be set") XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set") From d3257c345ac36a33f92b96dab7a7ed10306550c9 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 4 Mar 2017 17:00:28 -0500 Subject: [PATCH 3/3] Tested against public ROMs and corrected. Also moved the deferred adjustment into a more canonical place. --- Components/6532/6532.hpp | 4 ++-- Machines/Atari2600/Atari2600.cpp | 2 +- OSBindings/Mac/Clock SignalTests/6532Tests.swift | 11 ----------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/Components/6532/6532.hpp b/Components/6532/6532.hpp index acfb7de78..bac2a3c3d 100644 --- a/Components/6532/6532.hpp +++ b/Components/6532/6532.hpp @@ -51,7 +51,7 @@ template class MOS6532 { if(address & 0x10) { timer_.writtenShift = timer_.activeShift = (decodedAddress - 0x04) * 3 + (decodedAddress / 0x07); // i.e. 0, 3, 6, 10 - timer_.value = ((unsigned int)value << timer_.activeShift) + 2; + timer_.value = ((unsigned int)value << timer_.activeShift) ; timer_.interrupt_enabled = !!(address&0x08); interrupt_status_ &= ~InterruptFlag::Timer; evaluate_interrupts(); @@ -119,7 +119,7 @@ template class MOS6532 { timer_.value -= number_of_cycles; } else { number_of_cycles -= timer_.value; - timer_.value = 0x100 - number_of_cycles; + timer_.value = (0x100 - number_of_cycles) & 0xff; timer_.activeShift = 0; interrupt_status_ |= InterruptFlag::Timer; evaluate_interrupts(); diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index aa6e3fdd7..e779952df 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -63,6 +63,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin cycles_since_speaker_update_ += cycles_run_for; cycles_since_video_update_ += cycles_run_for; + cycles_since_6532_update_ += (cycles_run_for / 3); if(operation != CPU6502::BusOperation::Ready) { @@ -218,7 +219,6 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin } if(!tia_->get_cycles_until_horizontal_blank(cycles_since_video_update_)) set_ready_line(false); - cycles_since_6532_update_ += (cycles_run_for / 3); return cycles_run_for / 3; } diff --git a/OSBindings/Mac/Clock SignalTests/6532Tests.swift b/OSBindings/Mac/Clock SignalTests/6532Tests.swift index 091fdfd0e..fa48039f5 100644 --- a/OSBindings/Mac/Clock SignalTests/6532Tests.swift +++ b/OSBindings/Mac/Clock SignalTests/6532Tests.swift @@ -21,10 +21,6 @@ class MOS6532Tests: XCTestCase { with6532 { // set a count of 128 at single-clock intervals $0.setValue(128, forRegister:0x14) - $0.run(forCycles: 1) - - // one cycle later the timer should still contain 128 - $0.run(forCycles: 1) XCTAssertEqual($0.value(forRegister: 4), 128) // run for one more clock and the count should now be 127 @@ -52,10 +48,6 @@ class MOS6532Tests: XCTestCase { with6532 { // set a count of 28 at eight-clock intervals $0.setValue(28, forRegister:0x15) - $0.run(forCycles: 1) - - // one cycle later the timer should still contain 28 - $0.run(forCycles: 1) XCTAssertEqual($0.value(forRegister: 4), 28) // one further cycle and the timer should hit 27 @@ -99,9 +91,6 @@ class MOS6532Tests: XCTestCase { $0.setValue(1, forRegister:0x1c) $0.run(forCycles: 1) - // run for two clocks and the count should now be zero - $0.run(forCycles: 2) - // interrupt shouldn't be signalled yet, bit should not be set XCTAssert(!$0.irqLine, "IRQ line should not be set") XCTAssert($0.value(forRegister: 5) == 0x00, "Counter interrupt should not be set")