Fixed TIA image in debugger being two frames behind.

This commit is contained in:
Stephen Anthony 2017-05-28 13:55:23 -02:30
parent 25e96c3164
commit 79d8ed0010
7 changed files with 40 additions and 65 deletions

View File

@ -70,7 +70,8 @@
* Fixed bug in debugger tracing and displaying the partial TIA image; * Fixed bug in debugger tracing and displaying the partial TIA image;
the first time entering the debugger and starting to trace, the image the first time entering the debugger and starting to trace, the image
was blanked out (black) instead of being drawn in greyscale. was blanked out (black) instead of being drawn in greyscale. Also, the
image is now synchronized, instead of being two frames behind.
* Fixed crash with zipped ROMs that are less than 4K in size; so far * Fixed crash with zipped ROMs that are less than 4K in size; so far
this bug has only ever occurred in Windows XP, but it's been there this bug has only ever occurred in Windows XP, but it's been there
@ -124,7 +125,8 @@
This fixes issues with a newer ZLIB not working with an older PNG, etc. This fixes issues with a newer ZLIB not working with an older PNG, etc.
* Updated build scripts for Visual Studio 2017 (Windows) and MacOS * Updated build scripts for Visual Studio 2017 (Windows) and MacOS
Sierra (latest version of Xcode). Sierra (latest version of Xcode), and make these the minimum supported
versions.
* Updated UNIX configure script to work with the clang 5+ and gcc 7+ * Updated UNIX configure script to work with the clang 5+ and gcc 7+
compiler versions, and fixed compile issues on AArch64 and ppc64le compiler versions, and fixed compile issues on AArch64 and ppc64le

View File

@ -169,7 +169,5 @@ void TiaOutputWidget::drawWidget(bool hilite)
// Show electron beam position // Show electron beam position
if(visible && scanx < width && scany+2u < height) if(visible && scanx < width && scany+2u < height)
{
s.fillRect(_x+(scanx<<1), _y+scany, 3, 3, kBtnTextColor); s.fillRect(_x+(scanx<<1), _y+scany, 3, 3, kBtnTextColor);
}
} }

View File

@ -246,7 +246,7 @@ void TiaZoomWidget::drawWidget(bool hilite)
// Draw the zoomed image // Draw the zoomed image
// This probably isn't as efficient as it can be, but it's a small area // This probably isn't as efficient as it can be, but it's a small area
// and I don't have time to make it faster :) // and I don't have time to make it faster :)
const uInt8* currentFrame = instance().console().tia().currentFrameBuffer(); const uInt8* currentFrame = instance().console().tia().frameBuffer();
const int width = instance().console().tia().width(), const int width = instance().console().tia().width(),
wzoom = myZoomLevel << 1, wzoom = myZoomLevel << 1,
hzoom = myZoomLevel; hzoom = myZoomLevel;

View File

@ -121,7 +121,7 @@ void TIASurface::setPalette(const uInt32* tia_palette, const uInt32* rgb_palette
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FBSurface& TIASurface::baseSurface(GUI::Rect& rect) const FBSurface& TIASurface::baseSurface(GUI::Rect& rect) const
{ {
uInt32 tiaw = myTIA->width(), width = tiaw*2, height = myTIA->height(); uInt32 tiaw = myTIA->width(), width = tiaw*2, height = myTIA->height();
rect.setBounds(0, 0, width, height); rect.setBounds(0, 0, width, height);
@ -146,10 +146,8 @@ const FBSurface& TIASurface::baseSurface(GUI::Rect& rect)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) const uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift) const
{ {
uInt8 c = *(myTIA->currentFrameBuffer() + idx) | shift; // FIXME - use TJ phosphor code
uInt8 p = *(myTIA->previousFrameBuffer() + idx) | shift; return myPalette[*(myTIA->frameBuffer() + idx) | shift];
return (!myUsePhosphor ? myPalette[c] : myPhosphorPalette[c][p]);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -303,10 +301,9 @@ void TIASurface::render()
// In hardware rendering mode, it's faster to just assume that the screen // In hardware rendering mode, it's faster to just assume that the screen
// is dirty and always do an update // is dirty and always do an update
uInt8* currentFrame = myTIA->currentFrameBuffer(); uInt8* fbuffer = myTIA->frameBuffer();
uInt8* previousFrame = myTIA->previousFrameBuffer(); uInt32 width = myTIA->width();
uInt32 width = myTIA->width(); uInt32 height = myTIA->height();
uInt32 height = myTIA->height();
uInt32 *buffer, pitch; uInt32 *buffer, pitch;
myTiaSurface->basePtr(buffer, pitch); myTiaSurface->basePtr(buffer, pitch);
@ -323,7 +320,7 @@ void TIASurface::render()
{ {
uInt32 pos = screenofsY; uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x) for(uInt32 x = 0; x < width; ++x)
buffer[pos++] = myPalette[currentFrame[bufofsY + x]]; buffer[pos++] = myPalette[fbuffer[bufofsY + x]];
bufofsY += width; bufofsY += width;
screenofsY += pitch; screenofsY += pitch;
@ -332,6 +329,7 @@ void TIASurface::render()
} }
case kPhosphor: case kPhosphor:
{ {
#if 0 // FIXME
uInt32 bufofsY = 0; uInt32 bufofsY = 0;
uInt32 screenofsY = 0; uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y) for(uInt32 y = 0; y < height; ++y)
@ -345,18 +343,20 @@ void TIASurface::render()
bufofsY += width; bufofsY += width;
screenofsY += pitch; screenofsY += pitch;
} }
#endif
break; break;
} }
case kBlarggNormal: case kBlarggNormal:
{ {
myNTSCFilter.blit_single(currentFrame, width, height, myNTSCFilter.blit_single(fbuffer, width, height, buffer, pitch << 2);
buffer, pitch << 2);
break; break;
} }
case kBlarggPhosphor: case kBlarggPhosphor:
{ {
#if 0 // FIXME
myNTSCFilter.blit_double(currentFrame, previousFrame, width, height, myNTSCFilter.blit_double(currentFrame, previousFrame, width, height,
buffer, pitch << 2); buffer, pitch << 2);
#endif
break; break;
} }
} }

View File

@ -67,7 +67,7 @@ class TIASurface
/** /**
Get the TIA base surface for use in saving to a PNG image. Get the TIA base surface for use in saving to a PNG image.
*/ */
const FBSurface& baseSurface(GUI::Rect& rect); const FBSurface& baseSurface(GUI::Rect& rect) const;
/** /**
Get the TIA pixel associated with the given TIA buffer index, Get the TIA pixel associated with the given TIA buffer index,

View File

@ -85,8 +85,7 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
} }
); );
myCurrentFrameBuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight); myFramebuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight);
myPreviousFrameBuffer = make_ptr<uInt8[]>(160 * FrameManager::frameBufferHeight);
myTIAPinsDriven = mySettings.getBool("tiadriven"); myTIAPinsDriven = mySettings.getBool("tiadriven");
@ -152,7 +151,7 @@ void TIA::reset()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::frameReset() void TIA::frameReset()
{ {
clearBuffers(); memset(myFramebuffer.get(), 0, 160 * FrameManager::frameBufferHeight);
myAutoFrameEnabled = mySettings.getInt("framerate") <= 0; myAutoFrameEnabled = mySettings.getInt("framerate") <= 0;
enableColorLoss(mySettings.getBool("colorloss")); enableColorLoss(mySettings.getBool("colorloss"));
} }
@ -194,13 +193,6 @@ void TIA::installDelegate(System& system, Device& device)
); );
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::clearBuffers()
{
memset(myCurrentFrameBuffer.get(), 0, 160 * FrameManager::frameBufferHeight);
memset(myPreviousFrameBuffer.get(), 0, 160 * FrameManager::frameBufferHeight);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIA::save(Serializer& out) const bool TIA::save(Serializer& out) const
{ {
@ -715,7 +707,7 @@ bool TIA::saveDisplay(Serializer& out) const
{ {
try try
{ {
out.putByteArray(myCurrentFrameBuffer.get(), 160*320); out.putByteArray(myFramebuffer.get(), 160*FrameManager::frameBufferHeight);
} }
catch(...) catch(...)
{ {
@ -732,9 +724,7 @@ bool TIA::loadDisplay(Serializer& in)
try try
{ {
// Reset frame buffer pointer and data // Reset frame buffer pointer and data
clearBuffers(); in.getByteArray(myFramebuffer.get(), 160*FrameManager::frameBufferHeight);
in.getByteArray(myCurrentFrameBuffer.get(), 160*320);
memcpy(myPreviousFrameBuffer.get(), myCurrentFrameBuffer.get(), 160*320);
} }
catch(...) catch(...)
{ {
@ -991,21 +981,13 @@ void TIA::updateEmulation()
cycle(cyclesToRun); cycle(cyclesToRun);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::swapBuffers()
{
myCurrentFrameBuffer.swap(myPreviousFrameBuffer);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::onFrameStart() void TIA::onFrameStart()
{ {
swapBuffers();
const Int32 x = myHctr - 68; const Int32 x = myHctr - 68;
if (x > 0) if (x > 0)
memset(myCurrentFrameBuffer.get(), 0, x); memset(myFramebuffer.get(), 0, x);
for (uInt8 i = 0; i < 4; i++) for (uInt8 i = 0; i < 4; i++)
updatePaddle(i); updatePaddle(i);
@ -1039,7 +1021,7 @@ void TIA::onFrameComplete()
// Blank out any extra lines not drawn this frame // Blank out any extra lines not drawn this frame
const uInt32 missingScanlines = myFrameManager.missingScanlines(); const uInt32 missingScanlines = myFrameManager.missingScanlines();
if (missingScanlines > 0) if (missingScanlines > 0)
memset(myCurrentFrameBuffer.get() + 160 * myFrameManager.getY(), 0, missingScanlines * 160); memset(myFramebuffer.get() + 160 * myFrameManager.getY(), 0, missingScanlines * 160);
// Recalculate framerate, attempting to auto-correct for scanline 'jumps' // Recalculate framerate, attempting to auto-correct for scanline 'jumps'
if(myAutoFrameEnabled) if(myAutoFrameEnabled)
@ -1142,7 +1124,7 @@ void TIA::applyRsync()
myXDelta = 157 - x; myXDelta = 157 - x;
if (myFrameManager.isRendering()) if (myFrameManager.isRendering())
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x); memset(myFramebuffer.get() + myFrameManager.getY() * 160 + x, 0, 160 - x);
myHctr = 225; myHctr = 225;
} }
@ -1176,7 +1158,7 @@ void TIA::cloneLastLine()
if (!myFrameManager.isRendering() || y == 0) return; if (!myFrameManager.isRendering() || y == 0) return;
uInt8* buffer = myCurrentFrameBuffer.get(); uInt8* buffer = myFramebuffer.get();
memcpy(buffer + y * 160, buffer + (y-1) * 160, 160); memcpy(buffer + y * 160, buffer + (y-1) * 160, 160);
} }
@ -1243,7 +1225,7 @@ void TIA::renderPixel(uInt32 x, uInt32 y)
break; break;
} }
myCurrentFrameBuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color; myFramebuffer.get()[y * 160 + x] = myFrameManager.vblank() ? 0 : color;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1269,7 +1251,7 @@ void TIA::flushLineCache()
void TIA::clearHmoveComb() void TIA::clearHmoveComb()
{ {
if (myFrameManager.isRendering() && myHstate == HState::blank) if (myFrameManager.isRendering() && myHstate == HState::blank)
memset(myCurrentFrameBuffer.get() + myFrameManager.getY() * 160, memset(myFramebuffer.get() + myFrameManager.getY() * 160,
myColorHBlank, 8); myColorHBlank, 8);
} }

View File

@ -76,12 +76,12 @@ class TIA : public Device
public: public:
/** /**
Reset device to its power-on state Reset device to its power-on state.
*/ */
void reset() override; void reset() override;
/** /**
Reset frame to current YStart/Height properties Reset frame to current YStart/Height properties.
*/ */
void frameReset(); void frameReset();
@ -100,14 +100,14 @@ class TIA : public Device
void install(System& system) override; void install(System& system) override;
/** /**
Get the byte at the specified address Get the byte at the specified address.
@return The byte at the specified address @return The byte at the specified address
*/ */
uInt8 peek(uInt16 address) override; uInt8 peek(uInt16 address) override;
/** /**
Change the byte at the specified address to the given value Change the byte at the specified address to the given value.
@param address The address where the value should be stored @param address The address where the value should be stored
@param value The value to be stored at the address @param value The value to be stored at the address
@ -157,13 +157,12 @@ class TIA : public Device
void update(); void update();
/** /**
Answers the current and previous frame buffer pointers Returns pointer to the internal frame buffer.
*/ */
uInt8* currentFrameBuffer() const { return myCurrentFrameBuffer.get(); } uInt8* frameBuffer() const { return myFramebuffer.get(); }
uInt8* previousFrameBuffer() const { return myPreviousFrameBuffer.get(); }
/** /**
Answers dimensional info about the framebuffer Answers dimensional info about the framebuffer.
*/ */
uInt32 width() const { return 160; } uInt32 width() const { return 160; }
uInt32 height() const { return myFrameManager.height(); } uInt32 height() const { return myFrameManager.height(); }
@ -305,9 +304,6 @@ class TIA : public Device
bool toggleJitter(uInt8 mode = 2); bool toggleJitter(uInt8 mode = 2);
void setJitterRecoveryFactor(Int32 factor) { myFrameManager.setJitterFactor(factor); } void setJitterRecoveryFactor(Int32 factor) { myFrameManager.setJitterFactor(factor); }
// Clear both internal TIA buffers to black (palette color 0)
void clearBuffers();
/** /**
This method should be called to update the TIA with a new scanline. This method should be called to update the TIA with a new scanline.
*/ */
@ -326,12 +322,12 @@ class TIA : public Device
TIA& updateScanlineByTrace(int target); TIA& updateScanlineByTrace(int target);
/** /**
Retrieve the last value written to a certain register Retrieve the last value written to a certain register.
*/ */
uInt8 registerValue(uInt8 reg) const; uInt8 registerValue(uInt8 reg) const;
/** /**
Get the current x value Get the current x value.
*/ */
uInt8 getPosition() const { uInt8 getPosition() const {
return (myHctr < 68) ? 0 : (myHctr - 68 - myXDelta); return (myHctr < 68) ? 0 : (myHctr - 68 - myXDelta);
@ -339,7 +335,7 @@ class TIA : public Device
/** /**
Flush the line cache after an externally triggered state change Flush the line cache after an externally triggered state change
(e.g. a register write) (e.g. a register write).
*/ */
void flushLineCache(); void flushLineCache();
@ -431,8 +427,6 @@ class TIA : public Device
uInt8 resxCounter(); uInt8 resxCounter();
void swapBuffers();
/** /**
Get the result of the specified collision register. Get the result of the specified collision register.
*/ */
@ -469,9 +463,8 @@ class TIA : public Device
LatchedInput myInput0; LatchedInput myInput0;
LatchedInput myInput1; LatchedInput myInput1;
// Pointer to the current and previous frame buffers // Pointer to the internal frame buffer
BytePtr myCurrentFrameBuffer; BytePtr myFramebuffer;
BytePtr myPreviousFrameBuffer;
bool myTIAPinsDriven; bool myTIAPinsDriven;