mirror of https://github.com/stella-emu/stella.git
TIA emulation is now more accurate wrt irregular scanline counts.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2524 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
2145c38087
commit
02ebafaf7d
|
@ -14,8 +14,13 @@
|
|||
|
||||
3.7 to 3.7.1: (xxxx xx, 2012)
|
||||
|
||||
* Improved TIA emulation with ROMs that have too few or too many
|
||||
scanlines; the output is now blanked as on a real TV. Special thanks
|
||||
to Omegamatrix of AtariAge for test ROMs in this area.
|
||||
|
||||
* Fixed several bugs in DPC+ bankswitching scheme, including ability to
|
||||
load and save state files.
|
||||
load and save state files. As well, ROMs now work correctly after
|
||||
console format autodetection.
|
||||
|
||||
-Have fun!
|
||||
|
||||
|
|
|
@ -199,6 +199,12 @@ void FBSurfaceTIA::update()
|
|||
myFB.myDirtyFlag = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceTIA::invalidate()
|
||||
{
|
||||
SDL_FillRect(myTexture, NULL, 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceTIA::free()
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ class FBSurfaceTIA : public FBSurface
|
|||
uInt32 getHeight() const { return myImageH; }
|
||||
void translateCoords(Int32& x, Int32& y) const;
|
||||
void update();
|
||||
void invalidate();
|
||||
void free();
|
||||
void reload();
|
||||
|
||||
|
|
|
@ -332,6 +332,8 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
|
|||
void FrameBufferGL::invalidate()
|
||||
{
|
||||
p_gl.Clear(GL_COLOR_BUFFER_BIT);
|
||||
if(myTiaSurface)
|
||||
myTiaSurface->invalidate();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -812,6 +812,12 @@ class FBSurface
|
|||
*/
|
||||
virtual void update() { }
|
||||
|
||||
/**
|
||||
This method should be called to reset the surface to empty
|
||||
pixels / colour black.
|
||||
*/
|
||||
virtual void invalidate() { }
|
||||
|
||||
/**
|
||||
This method should be called to free any resources being used by
|
||||
the surface.
|
||||
|
|
|
@ -46,7 +46,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
|||
: myConsole(console),
|
||||
mySound(sound),
|
||||
mySettings(settings),
|
||||
myFrameWidth(160),
|
||||
myFrameYStart(34),
|
||||
myFrameHeight(210),
|
||||
myMaximumNumberOfScanlines(262),
|
||||
|
@ -194,8 +193,7 @@ void TIA::frameReset()
|
|||
// Calculate color clock offsets for starting and stopping frame drawing
|
||||
// Note that although we always start drawing at scanline zero, the
|
||||
// framebuffer that is exposed outside the class actually starts at 'ystart'
|
||||
myFramePointerOffset = myFrameWidth * myFrameYStart;
|
||||
myStartDisplayOffset = 0;
|
||||
myFramePointerOffset = 160 * myFrameYStart;
|
||||
|
||||
// NTSC screens will process at least 262 scanlines,
|
||||
// while PAL will have at least 312
|
||||
|
@ -209,7 +207,7 @@ void TIA::frameReset()
|
|||
|
||||
// Reasonable values to start and stop the current frame drawing
|
||||
myClockWhenFrameStarted = mySystem->cycles() * 3;
|
||||
myClockStartDisplay = myClockWhenFrameStarted + myStartDisplayOffset;
|
||||
myClockStartDisplay = myClockWhenFrameStarted;
|
||||
myClockStopDisplay = myClockWhenFrameStarted + myStopDisplayOffset;
|
||||
myClockAtLastUpdate = myClockWhenFrameStarted;
|
||||
myClocksToEndOfScanLine = 228;
|
||||
|
@ -558,7 +556,7 @@ inline void TIA::startFrame()
|
|||
|
||||
// Setup clocks that'll be used for drawing this frame
|
||||
myClockWhenFrameStarted = -1 * clocks;
|
||||
myClockStartDisplay = myClockWhenFrameStarted + myStartDisplayOffset;
|
||||
myClockStartDisplay = myClockWhenFrameStarted;
|
||||
myClockStopDisplay = myClockWhenFrameStarted + myStopDisplayOffset;
|
||||
myClockAtLastUpdate = myClockStartDisplay;
|
||||
myClocksToEndOfScanLine = 228;
|
||||
|
@ -622,22 +620,32 @@ inline void TIA::endFrame()
|
|||
myStopDisplayOffset = offset;
|
||||
}
|
||||
|
||||
// This is a bit of a hack for those ROMs which generate too many
|
||||
// scanlines each frame, usually caused by VBLANK taking too long
|
||||
// When this happens, the frame pointers sometimes get 'confused',
|
||||
// and the framebuffer class doesn't properly overwrite data from
|
||||
// the previous frame, causing graphical garbage
|
||||
//
|
||||
// We basically erase the entire contents of both buffers, making
|
||||
// sure that they're also different from one another
|
||||
// This will force the framebuffer class to completely re-render
|
||||
// the screen
|
||||
if(previousCount > myMaximumNumberOfScanlines &&
|
||||
myScanlineCountForLastFrame <= myMaximumNumberOfScanlines)
|
||||
// The following handle cases where scanlines either go too high or too
|
||||
// low compared to the previous frame, in which case certain portions
|
||||
// of the framebuffer are cleared to zero (black pixels)
|
||||
// Due to the FrameBuffer class (potentially) doing dirty-rectangle
|
||||
// updates, each internal buffer must be set slightly differently,
|
||||
// otherwise they won't know anything has changed
|
||||
// Hence, the front buffer is set to pixel 0, and the back to pixel 1
|
||||
|
||||
// Did we generate too many scanlines?
|
||||
// (usually caused by VBLANK taking too long)
|
||||
// If so, blank entire viewable area
|
||||
if(myScanlineCountForLastFrame > 342 && previousCount <= 342)
|
||||
{
|
||||
memset(myCurrentFrameBuffer, 0, 160 * 320);
|
||||
memset(myPreviousFrameBuffer, 1, 160 * 320);
|
||||
}
|
||||
// Did the number of scanlines decrease?
|
||||
// If so, blank scanlines that weren't rendered this frame
|
||||
else if(myScanlineCountForLastFrame < previousCount &&
|
||||
myScanlineCountForLastFrame < 320 && previousCount < 320)
|
||||
{
|
||||
uInt32 offset = myScanlineCountForLastFrame * 160,
|
||||
stride = (previousCount - myScanlineCountForLastFrame) * 160;
|
||||
memset(myCurrentFrameBuffer + offset, 0, stride);
|
||||
memset(myPreviousFrameBuffer + offset, 1, stride);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -188,9 +188,9 @@ class TIA : public Device
|
|||
/**
|
||||
Answers the width and height of the frame buffer
|
||||
*/
|
||||
uInt32 width() const { return myFrameWidth; }
|
||||
uInt32 height() const { return myFrameHeight; }
|
||||
uInt32 ystart() const { return myFrameYStart; }
|
||||
inline uInt32 width() const { return 160; }
|
||||
inline uInt32 height() const { return myFrameHeight; }
|
||||
inline uInt32 ystart() const { return myFrameYStart; }
|
||||
|
||||
/**
|
||||
Changes the current Height/YStart properties.
|
||||
|
@ -403,18 +403,12 @@ class TIA : public Device
|
|||
// (this is used when loading state files with a 'partial' frame)
|
||||
uInt32 myFramePointerClocks;
|
||||
|
||||
// Indicates the width of the visible scanline
|
||||
uInt32 myFrameWidth;
|
||||
|
||||
// Indicated what scanline the frame should start being drawn at
|
||||
uInt32 myFrameYStart;
|
||||
|
||||
// Indicates the height of the frame in scanlines
|
||||
uInt32 myFrameHeight;
|
||||
|
||||
// Indicates offset in color clocks when display should begin
|
||||
uInt32 myStartDisplayOffset;
|
||||
|
||||
// Indicates offset in color clocks when display should stop
|
||||
uInt32 myStopDisplayOffset;
|
||||
|
||||
|
|
Loading…
Reference in New Issue