diff --git a/Changes.txt b/Changes.txt index 5751c6d4a..ea15437f2 100644 --- a/Changes.txt +++ b/Changes.txt @@ -23,6 +23,15 @@ now, this applies mainly to the various decimal and binary fields. More widgets will be made editable in future releases. + * The TIA now emulates the jitter that occurs when scanline counts + are not consistent frame-over-frame. Also, the DPC+ scheme now + emulates jitter that can occur when using its Fractional Datafetchers + if the DFxFRACINC registers are not re-initialized every frame. + Special thanks to SpiceWare for this implementation. + + * Tweaked 'MDM' scheme autodetection to detect that the identification + string can be in either bank 0 or bank 1. + * Changed 'hidecursor' commandline argument (and associated UI item) to 'cursor'. The new argument allows to set mouse cursor visibility separately for both UI and emulation modes. diff --git a/src/emucore/Cart.cxx b/src/emucore/Cart.cxx index 12206f057..4923a77b4 100644 --- a/src/emucore/Cart.cxx +++ b/src/emucore/Cart.cxx @@ -894,9 +894,9 @@ bool Cartridge::isProbablyFE(const uInt8* image, uInt32 size) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool Cartridge::isProbablyMDM(const uInt8* image, uInt32 size) { - // MDM cart is identified key 'MDMC' in the first 4K of ROM + // MDM cart is identified key 'MDMC' in the first 8K of ROM uInt8 signature[] = { 'M', 'D', 'M', 'C' }; - return searchForBytes(image, 4096, signature, 4, 1); + return searchForBytes(image, 8192, signature, 4, 1); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartDPCPlus.cxx b/src/emucore/CartDPCPlus.cxx index 9809d01ba..d6d24650d 100644 --- a/src/emucore/CartDPCPlus.cxx +++ b/src/emucore/CartDPCPlus.cxx @@ -412,7 +412,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value) { //DFxFRACLOW - fractional data pointer low byte case 0x00: - myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F0000) | ((uInt16)value << 8); + myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F00FF) | ((uInt16)value << 8); break; // DFxFRACHI - fractional data pointer high byte diff --git a/src/emucore/TIA.cxx b/src/emucore/TIA.cxx index a33611cd1..dda032dd7 100644 --- a/src/emucore/TIA.cxx +++ b/src/emucore/TIA.cxx @@ -57,8 +57,10 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings) myFrameCounter(0), myPALFrameCounter(0), myBitsEnabled(true), - myCollisionsEnabled(true) - + myCollisionsEnabled(true), + myNextFrameJitter(0), + myCurrentFrameJitter(0) + { // Allocate buffers for two frame buffers myCurrentFrameBuffer = new uInt8[160 * 320]; @@ -141,6 +143,7 @@ void TIA::reset() myFrameCounter = myPALFrameCounter = 0; myScanlineCountForLastFrame = 0; + myNextFrameJitter = myCurrentFrameJitter = 0; myP0Mask = &TIATables::PxMask[0][0][0]; myP1Mask = &TIATables::PxMask[0][0][0]; @@ -653,6 +656,39 @@ inline void TIA::endFrame() memset(myPreviousFrameBuffer + offset, 1, stride); } + // Account for frame jitter, skipping the first few frames + if(myFrameCounter > 3) + { + // Set the jitter amount for the current frame + myCurrentFrameJitter = myNextFrameJitter * 160; + + // Calculate the jitter amount for the next frame. + // Jitter amount of a frame depends upon the difference + // between the scanline counts of the prior two frames. + myNextFrameJitter = myScanlineCountForLastFrame - previousCount; + + if(myNextFrameJitter < 0) + { + myNextFrameJitter = --myNextFrameJitter >> 1; + + // Make sure currentFrameBuffer() doesn't return a pointer that + // results in memory being accessed outside of the 160*320 bytes + // allocated for the frame buffer + if(myNextFrameJitter < -myFrameYStart) + myNextFrameJitter = myFrameYStart; + } + else if(myNextFrameJitter > 0) + { + myNextFrameJitter = ++myNextFrameJitter >> 1; + + // Make sure currentFrameBuffer() doesn't return a pointer that + // results in memory being accessed outside of the 160*320 bytes + // allocated for the frame buffer + if(myNextFrameJitter > 320 - myFrameYStart - myFrameHeight) + myNextFrameJitter = 320 - myFrameYStart - myFrameHeight; + } + } + // Recalculate framerate. attempting to auto-correct for scanline 'jumps' if(myAutoFrameEnabled) { diff --git a/src/emucore/TIA.hxx b/src/emucore/TIA.hxx index 832d67947..76dbe0c37 100644 --- a/src/emucore/TIA.hxx +++ b/src/emucore/TIA.hxx @@ -175,7 +175,7 @@ class TIA : public Device @return Pointer to the current frame buffer */ uInt8* currentFrameBuffer() const - { return myCurrentFrameBuffer + myFramePointerOffset; } + { return myCurrentFrameBuffer + myFramePointerOffset + myCurrentFrameJitter; } /** Answers the previous frame buffer @@ -615,7 +615,14 @@ class TIA : public Device // Whether TIA bits/collisions are currently enabled/disabled bool myBitsEnabled, myCollisionsEnabled; - + + // Derived from the difference between the scanline counts of the + // current and prior frames. If non-zero the next frame should jitter. + Int32 myNextFrameJitter; + + // Jitter amount for the current frame + Int32 myCurrentFrameJitter; + private: // Following constructors and assignment operators not supported TIA() = delete; diff --git a/src/macosx/stella.xcodeproj/project.pbxproj b/src/macosx/stella.xcodeproj/project.pbxproj index 30f7723c0..cbdca0637 100644 --- a/src/macosx/stella.xcodeproj/project.pbxproj +++ b/src/macosx/stella.xcodeproj/project.pbxproj @@ -1032,8 +1032,8 @@ DCD6FC9211C28C6F005DA767 /* PNGLibrary.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = PNGLibrary.hxx; path = ../common/PNGLibrary.hxx; sourceTree = SOURCE_ROOT; }; DCDA03AE1A2009BA00711920 /* CartWD.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CartWD.cxx; path = ../emucore/CartWD.cxx; sourceTree = ""; }; DCDA03AF1A2009BB00711920 /* CartWD.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CartWD.hxx; path = ../emucore/CartWD.hxx; sourceTree = ""; }; - DCDAF4D818CA9AAB00D3865D /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../../../Library/Frameworks/SDL2.framework; sourceTree = ""; }; - DCDAF4DA18CA9AF000D3865D /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = ../../../../../../Library/Frameworks/SDL2.framework; sourceTree = ""; }; + DCDAF4D818CA9AAB00D3865D /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = ""; }; + DCDAF4DA18CA9AF000D3865D /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = ""; }; DCDE17F617724E5D00EB1AC6 /* ConfigPathDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConfigPathDialog.cxx; path = ../gui/ConfigPathDialog.cxx; sourceTree = SOURCE_ROOT; }; DCDE17F717724E5D00EB1AC6 /* ConfigPathDialog.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ConfigPathDialog.hxx; path = ../gui/ConfigPathDialog.hxx; sourceTree = SOURCE_ROOT; }; DCDE17F817724E5D00EB1AC6 /* SnapshotDialog.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SnapshotDialog.cxx; path = ../gui/SnapshotDialog.cxx; sourceTree = SOURCE_ROOT; };