diff --git a/Changes.txt b/Changes.txt index 22eda9028..70c27806c 100644 --- a/Changes.txt +++ b/Changes.txt @@ -14,9 +14,16 @@ 3.7.2 to 3.8: (xxx xx, 2012) + * Note: because of TIA/RIOT changes, the state file format has changed + again, and old state files will not work with this release. + * Improved handling of 'illegal' VSYNC signals, which sometimes created 'short' frames that caused massive flickering. + * Improved emulation of RIOT chip, in particular the behaviour of + reading from TIMINT. Also, D6 of the Interrupt Flag register is now + properly set on active transition of the PA7 pin. + * The ROM properties database now uses 'Auto' instead of 'Auto-select' everywhere. This makes for less typing when running from the commandline. diff --git a/src/emucore/Control.hxx b/src/emucore/Control.hxx index 63463058f..a79efd3fb 100644 --- a/src/emucore/Control.hxx +++ b/src/emucore/Control.hxx @@ -65,6 +65,7 @@ class Controller : public Serializable /** Riot debug class needs special access to the underlying controller state */ + friend class M6532; friend class RiotDebug; friend class CompuMate; diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index 698f24119..246732c83 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -42,7 +42,7 @@ #include "Snapshot.hxx" #include "Sound.hxx" #include "StateManager.hxx" -#include "Switches.hxx" +#include "M6532.hxx" #include "MouseControl.hxx" #include "EventHandler.hxx" @@ -955,9 +955,7 @@ void EventHandler::poll(uInt64 time) // related to emulation if(myState == S_EMULATE) { - myOSystem->console().controller(Controller::Left).update(); - myOSystem->console().controller(Controller::Right).update(); - myOSystem->console().switches().update(); + myOSystem->console().riot().update(); #if 0 // Now check if the StateManager should be saving or loading state diff --git a/src/emucore/M6532.cxx b/src/emucore/M6532.cxx index 7d2aeb6fb..e53bbc875 100644 --- a/src/emucore/M6532.cxx +++ b/src/emucore/M6532.cxx @@ -64,6 +64,9 @@ void M6532::reset() // Zero the interrupt flag register and mark D7 as invalid myInterruptFlag = 0x00; myTimerFlagValid = false; + + // Edge-detect set to negative (high to low) + myEdgeDetectPositive = false; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -78,6 +81,29 @@ void M6532::systemCyclesReset() myConsole.controller(Controller::Right).systemCyclesReset(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void M6532::update() +{ + Controller& port0 = myConsole.controller(Controller::Left); + Controller& port1 = myConsole.controller(Controller::Right); + + // Get current PA7 state + bool prevPA7 = port0.myDigitalPinState[Controller::Four]; + + // Update entire port state + port0.update(); + port1.update(); + myConsole.switches().update(); + + // Get new PA7 state + bool currPA7 = port0.myDigitalPinState[Controller::Four]; + + // PA7 Flag is set on active transition in appropriate direction + if((!myEdgeDetectPositive && prevPA7 && !currPA7) || + (myEdgeDetectPositive && !prevPA7 && currPA7)) + myInterruptFlag |= PA7Bit; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void M6532::install(System& system) { @@ -181,7 +207,10 @@ uInt8 M6532::peek(uInt16 addr) myInterruptFlag |= TimerBit; myTimerFlagValid = true; } - return myInterruptFlag; + // PA7 Flag is always cleared after accessing TIMINT + uInt8 result = myInterruptFlag; + myInterruptFlag &= ~PA7Bit; + return result; } default: @@ -208,10 +237,17 @@ bool M6532::poke(uInt16 addr, uInt8 value) } // A2 distinguishes I/O registers from the timer + // A2 = 1 is write to timer + // A2 = 0 is write to I/O if((addr & 0x04) != 0) { - if((addr & 0x10) != 0) // TIMxT (x = 1, 8, 64, 1024) - setTimerRegister(value, addr & 0x03); + // A4 = 1 is write to TIMxT (x = 1, 8, 64, 1024) + // A4 = 0 is write to edge detect control + if((addr & 0x10) != 0) + setTimerRegister(value, addr & 0x03); // A1A0 determines interval + else { + myEdgeDetectPositive = addr & 0x01; // A0 determines direction +cerr << "myEdgeDetectPositive: " << myEdgeDetectPositive << endl; } } else { @@ -303,7 +339,6 @@ bool M6532::save(Serializer& out) const { out.putString(name()); - // Output the RAM out.putByteArray(myRAM, 128); out.putInt(myTimer); @@ -314,8 +349,10 @@ bool M6532::save(Serializer& out) const out.putByte(myDDRB); out.putByte(myOutA); out.putByte(myOutB); + out.putByte(myInterruptFlag); out.putBool(myTimerFlagValid); + out.putBool(myEdgeDetectPositive); out.putByteArray(myOutTimer, 4); } catch(...) @@ -335,7 +372,6 @@ bool M6532::load(Serializer& in) if(in.getString() != name()) return false; - // Input the RAM in.getByteArray(myRAM, 128); myTimer = in.getInt(); @@ -346,8 +382,10 @@ bool M6532::load(Serializer& in) myDDRB = in.getByte(); myOutA = in.getByte(); myOutB = in.getByte(); + myInterruptFlag = in.getByte(); myTimerFlagValid = in.getBool(); + myEdgeDetectPositive = in.getBool(); in.getByteArray(myOutTimer, 4); } catch(...) diff --git a/src/emucore/M6532.hxx b/src/emucore/M6532.hxx index cb98ea1d0..0f4bc865e 100644 --- a/src/emucore/M6532.hxx +++ b/src/emucore/M6532.hxx @@ -30,16 +30,13 @@ class Settings; /** This class models the M6532 RAM-I/O-Timer (aka RIOT) chip in the 2600 - console. Note that only the functionality used by the console is - emulated here; several aspects of the chip are completely ignored: + console. Note that since the M6507 CPU doesn't contain an interrupt line, + the following functionality relating to the RIOT IRQ line is not emulated: - - Pin 25 (IRQ) is not connected at all, therefore all related - items are ignored (A3 determining IRQ enable/disable, etc). + - A3 to enable/disable interrupt from timer to IRQ + - A1 to enable/disable interrupt from PA7 to IRQ - - D6 of the Interrupt Flag is ignored, including PA7 interrupt flag (A1) - and negative/positive edge-detection (A0) - - @author Bradford W. Mott + @author Bradford W. Mott and Stephen Anthony @version $Id$ */ class M6532 : public Device @@ -77,6 +74,11 @@ class M6532 : public Device */ void systemCyclesReset(); + /** + Update the entire digital and analog pin state of ports A and B. + */ + void update(); + /** Install 6532 in the specified system. Invoked by the system when the 6532 is attached to it. @@ -189,6 +191,10 @@ class M6532 : public Device // If it isn't valid, it will be updated as required bool myTimerFlagValid; + // Used to determine whether an active transition on PA7 has occurred + // True is positive edge-detect, false is negative edge-detect + bool myEdgeDetectPositive; + // Last value written to the timer registers uInt8 myOutTimer[4]; diff --git a/src/emucore/StateManager.cxx b/src/emucore/StateManager.cxx index 405cc1bd6..a8e8df579 100644 --- a/src/emucore/StateManager.cxx +++ b/src/emucore/StateManager.cxx @@ -30,7 +30,7 @@ #include "StateManager.hxx" -#define STATE_HEADER "03070102state" +#define STATE_HEADER "03070103state" #define MOVIE_HEADER "03030000movie" // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -