The TIA image in the debugger is now correctly rendered in greyscale

below the current electron beam position.

Fix long-standing bug whereby entering the debugger for the first time
and tracing/scanline advancing, the TIA image was blanked, and didn't
work correctly until you exited and re-entered the debugger.

Minor refactoring optimizations, and renaming of methods.
This commit is contained in:
Stephen Anthony 2017-02-20 19:51:59 -03:30
parent 39f756f821
commit c99cb33cda
8 changed files with 63 additions and 142 deletions

View File

@ -111,7 +111,7 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
{ {
ostringstream command; ostringstream command;
int lines = myClickY + ystart; int lines = myClickY + ystart;
if(instance().console().tia().partialFrame()) if(instance().console().tia().isRendering())
lines -= instance().console().tia().scanlines(); lines -= instance().console().tia().scanlines();
if(lines > 0) if(lines > 0)
{ {
@ -156,7 +156,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
// This determines where the frame greying should start, and where a // This determines where the frame greying should start, and where a
// scanline 'pointer' should be drawn // scanline 'pointer' should be drawn
uInt16 scanx, scany, scanoffset; uInt16 scanx, scany, scanoffset;
bool visible = instance().console().tia().scanlinePos(scanx, scany); bool visible = instance().console().tia().electronBeamPos(scanx, scany);
scanoffset = width * scany + scanx; scanoffset = width * scany + scanx;
for(uInt32 y = 0, i = 0; y < height; ++y) for(uInt32 y = 0, i = 0; y < height; ++y)
@ -164,7 +164,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
uInt32* line_ptr = myLineBuffer; uInt32* line_ptr = myLineBuffer;
for(uInt32 x = 0; x < width; ++x, ++i) for(uInt32 x = 0; x < width; ++x, ++i)
{ {
uInt8 shift = i > scanoffset ? 1 : 0; uInt8 shift = i >= scanoffset ? 1 : 0;
uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift); uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift);
*line_ptr++ = pixel; *line_ptr++ = pixel;
*line_ptr++ = pixel; *line_ptr++ = pixel;

View File

@ -254,7 +254,7 @@ void TiaZoomWidget::drawWidget(bool hilite)
// Get current scanline position // Get current scanline position
// This determines where the frame greying should start // This determines where the frame greying should start
uInt16 scanx, scany, scanoffset; uInt16 scanx, scany, scanoffset;
instance().console().tia().scanlinePos(scanx, scany); instance().console().tia().electronBeamPos(scanx, scany);
scanoffset = width * scany + scanx; scanoffset = width * scany + scanx;
int x, y, col, row; int x, y, col, row;

View File

@ -405,8 +405,6 @@ void Console::setProperties(const Properties& props)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBInitStatus Console::initializeVideo(bool full) FBInitStatus Console::initializeVideo(bool full)
{ {
setPalette(myOSystem.settings().getString("palette"));
FBInitStatus fbstatus = kSuccess; FBInitStatus fbstatus = kSuccess;
if(full) if(full)
@ -421,6 +419,7 @@ FBInitStatus Console::initializeVideo(bool full)
myOSystem.frameBuffer().showFrameStats(myOSystem.settings().getBool("stats")); myOSystem.frameBuffer().showFrameStats(myOSystem.settings().getBool("stats"));
generateColorLossPalette(); generateColorLossPalette();
} }
setPalette(myOSystem.settings().getString("palette"));
// Set the correct framerate based on the format of the ROM // Set the correct framerate based on the format of the ROM
// This can be overridden by changing the framerate in the // This can be overridden by changing the framerate in the

View File

@ -274,7 +274,7 @@ void FrameBuffer::update()
const ConsoleInfo& info = myOSystem.console().about(); const ConsoleInfo& info = myOSystem.console().about();
char msg[30]; char msg[30];
std::snprintf(msg, 30, "%3u @ %3.2ffps => %s", std::snprintf(msg, 30, "%3u @ %3.2ffps => %s",
myOSystem.console().tia().scanlines(), myOSystem.console().tia().scanlinesLastFrame(),
myOSystem.console().getFramerate(), info.DisplayFormat.c_str()); myOSystem.console().getFramerate(), info.DisplayFormat.c_str());
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor); myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
myStatsMsg.surface->drawString(infoFont(), myStatsMsg.surface->drawString(infoFont(),

View File

@ -230,7 +230,7 @@ void FrameManager::updateAutodetectedTvMode()
updateTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal); updateTvMode(deltaNTSC <= deltaPAL ? TvMode::ntsc : TvMode::pal);
else if (!myModeConfirmed) { else if (!myModeConfirmed) {
if ( if (
(myCurrentFrameFinalLines < frameLinesPAL) && (myCurrentFrameFinalLines < frameLinesPAL) &&
(myCurrentFrameFinalLines > frameLinesNTSC) && (myCurrentFrameFinalLines > frameLinesNTSC) &&
(myCurrentFrameFinalLines % 2) (myCurrentFrameFinalLines % 2)
) )
@ -289,7 +289,8 @@ void FrameManager::setYstart(uInt32 ystart)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameManager::ystart() const { uInt32 FrameManager::ystart() const
{
return myVblankManager.ystart(); return myVblankManager.ystart();
} }
@ -329,6 +330,12 @@ uInt32 FrameManager::scanlines() const
return myCurrentFrameTotalLines; return myCurrentFrameTotalLines;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameManager::scanlinesLastFrame() const
{
return myCurrentFrameFinalLines;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameManager::setTvMode(TvMode mode) void FrameManager::setTvMode(TvMode mode)
{ {

View File

@ -61,13 +61,12 @@ class FrameManager : public Serializable
void setFixedHeight(uInt32 height); void setFixedHeight(uInt32 height);
uInt32 getY() const uInt32 getY() const { return myY; }
{
return myY;
}
uInt32 scanlines() const; uInt32 scanlines() const;
uInt32 scanlinesLastFrame() const;
uInt32 frameCount() const { return myTotalFrames; } uInt32 frameCount() const { return myTotalFrames; }
float frameRate() const { return myFrameRate; } float frameRate() const { return myFrameRate; }

View File

@ -199,12 +199,13 @@ bool TIA::save(Serializer& out) const
// TODO - save instance variables // TODO - save instance variables
// Save the state of each graphics object // Save the state of each graphics object
if(!myPlayfield.save(out)) return false; if(!myBackground.save(out)) return false;
if(!myMissile0.save(out)) return false; if(!myPlayfield.save(out)) return false;
if(!myMissile1.save(out)) return false; if(!myMissile0.save(out)) return false;
if(!myPlayer0.save(out)) return false; if(!myMissile1.save(out)) return false;
if(!myPlayer1.save(out)) return false; if(!myPlayer0.save(out)) return false;
if(!myBall.save(out)) return false; if(!myPlayer1.save(out)) return false;
if(!myBall.save(out)) return false;
// Save the sound sample stuff ... // Save the sound sample stuff ...
mySound.save(out); mySound.save(out);
@ -229,12 +230,13 @@ bool TIA::load(Serializer& in)
// TODO - load instance variables // TODO - load instance variables
// Load the state of each graphics object // Load the state of each graphics object
if(!myPlayfield.load(in)) return false; if(!myBackground.load(in)) return false;
if(!myMissile0.load(in)) return false; if(!myPlayfield.load(in)) return false;
if(!myMissile1.load(in)) return false; if(!myMissile0.load(in)) return false;
if(!myPlayer0.load(in)) return false; if(!myMissile1.load(in)) return false;
if(!myPlayer1.load(in)) return false; if(!myPlayer0.load(in)) return false;
if(!myBall.load(in)) return false; if(!myPlayer1.load(in)) return false;
if(!myBall.load(in)) return false;
} }
catch(...) catch(...)
{ {
@ -344,6 +346,7 @@ bool TIA::poke(uInt16 address, uInt8 value)
// It appears that the 6507 only halts during a read cycle so // It appears that the 6507 only halts during a read cycle so
// we test here for follow-on writes which should be ignored as // we test here for follow-on writes which should be ignored as
// far as halting the processor is concerned. // far as halting the processor is concerned.
// See issue #42 for more information.
if (mySystem->m6502().lastAccessWasRead()) if (mySystem->m6502().lastAccessWasRead())
{ {
mySubClock += (228 - myHctr) % 228; mySubClock += (228 - myHctr) % 228;
@ -614,54 +617,6 @@ void TIA::update()
mySystem->m6502().execute(25000); mySystem->m6502().execute(25000);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIA::height() const
{
return myFrameManager.height();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIA::ystart() const
{
return myFrameManager.ystart();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setHeight(uInt32 height)
{
myFrameManager.setFixedHeight(height);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setYStart(uInt32 ystart)
{
myFrameManager.setYstart(ystart);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::autodetectTvMode(bool toggle)
{
myFrameManager.autodetectTvMode(toggle);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::setTvMode(TvMode mode)
{
myFrameManager.setTvMode(mode);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TvMode TIA::tvMode() const
{
return myFrameManager.tvMode();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::enableAutoFrame(bool enabled)
{
myAutoFrameEnabled = enabled;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// TODO: stub // TODO: stub
void TIA::enableColorLoss(bool enabled) void TIA::enableColorLoss(bool enabled)
@ -669,48 +624,12 @@ void TIA::enableColorLoss(bool enabled)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIA::clocksThisLine() const bool TIA::electronBeamPos(uInt16& x, uInt16& y) const
{ {
return myHctr + myXDelta; x = clocksThisLine();
} y = myFrameManager.getY();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return isRendering();
uInt32 TIA::scanlines() const
{
return myFrameManager.scanlines();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIA::partialFrame() const
{
return myFrameManager.isRendering();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIA::scanlinePos(uInt16& x, uInt16& y) const
{
if(partialFrame())
{
// We only care about the scanline position when it's in the viewable area
if(1)//myFramePointerClocks >= myFramePointerOffset)
{
x = clocksThisLine();//(myFramePointerClocks - myFramePointerOffset) % 160;
y = myFrameManager.getY();//(myFramePointerClocks - myFramePointerOffset) / 160;
return true;
}
else
{
x = 0;
y = 0;
return false;
}
}
else
{
x = width();
y = height();
return false;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -850,12 +769,8 @@ void TIA::updateScanline()
{ {
// Update frame by one scanline at a time // Update frame by one scanline at a time
uInt32 line = scanlines(); uInt32 line = scanlines();
cerr << "-> " << line << endl;
while (line == scanlines()) while (line == scanlines())
{
updateScanlineByStep(); updateScanlineByStep();
cerr << line << endl;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -151,31 +151,27 @@ class TIA : public Device
/** /**
Answers the current and previous frame buffer pointers Answers the current and previous frame buffer pointers
*/ */
uInt8* currentFrameBuffer() const { uInt8* currentFrameBuffer() const { return myCurrentFrameBuffer.get(); }
return myCurrentFrameBuffer.get(); uInt8* previousFrameBuffer() const { return myPreviousFrameBuffer.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; uInt32 height() const { return myFrameManager.height(); }
uInt32 ystart() const; uInt32 ystart() const { return myFrameManager.ystart(); }
/** /**
Changes the current Height/YStart properties. Changes the current Height/YStart properties.
Note that calls to these method(s) must be eventually followed by Note that calls to these method(s) must be eventually followed by
::frameReset() for the changes to take effect. ::frameReset() for the changes to take effect.
*/ */
void setHeight(uInt32 height); void setHeight(uInt32 height) { myFrameManager.setFixedHeight(height); }
void setYStart(uInt32 ystart); void setYStart(uInt32 ystart) { myFrameManager.setYstart(ystart); }
void autodetectTvMode(bool toggle); void autodetectTvMode(bool toggle) { myFrameManager.autodetectTvMode(toggle); }
void setTvMode(TvMode mode); void setTvMode(TvMode mode) { myFrameManager.setTvMode(mode); }
TvMode tvMode() const; TvMode tvMode() const { return myFrameManager.tvMode(); }
/** /**
Enables/disables auto-frame calculation. If enabled, the TIA Enables/disables auto-frame calculation. If enabled, the TIA
@ -183,7 +179,7 @@ class TIA : public Device
@param enabled Whether to enable or disable all auto-frame calculation @param enabled Whether to enable or disable all auto-frame calculation
*/ */
void enableAutoFrame(bool enabled); void enableAutoFrame(bool enabled) { myAutoFrameEnabled = enabled; }
/** /**
Enables/disables color-loss for PAL modes only. Enables/disables color-loss for PAL modes only.
@ -197,7 +193,7 @@ class TIA : public Device
@return The current color clock @return The current color clock
*/ */
uInt32 clocksThisLine() const; uInt32 clocksThisLine() const { return myHctr + myXDelta; }
/** /**
Answers the total number of scanlines the TIA generated in producing Answers the total number of scanlines the TIA generated in producing
@ -206,27 +202,32 @@ class TIA : public Device
@return The total number of scanlines generated @return The total number of scanlines generated
*/ */
uInt32 scanlines() const; uInt32 scanlines() const { return myFrameManager.scanlines(); }
/** /**
Answers whether the TIA is currently in 'partial frame' mode Answers the total number of scanlines the TIA generated in the
previous frame.
@return The total number of scanlines generated in the last frame.
*/
uInt32 scanlinesLastFrame() const { return myFrameManager.scanlinesLastFrame(); }
/**
Answers whether the TIA is currently in being rendered
(we're in between the start and end of drawing a frame). (we're in between the start and end of drawing a frame).
@return If we're in partial frame mode @return If the frame is in rendering mode
*/ */
bool partialFrame() const; bool isRendering() const { return myFrameManager.isRendering(); }
/** /**
Answers the current position of the virtual 'electron beam' used to Answers the current position of the virtual 'electron beam' used to
draw the TIA image. If not in partial frame mode, the position is draw the TIA image.
defined to be in the lower right corner (@ width/height of the screen).
Note that the coordinates are with respect to currentFrameBuffer(),
taking any YStart values into account.
@return The x/y coordinates of the scanline electron beam, and whether @return The x/y coordinates of the scanline electron beam, and whether
it is in the visible/viewable area of the screen it is in the visible/viewable area of the screen
*/ */
bool scanlinePos(uInt16& x, uInt16& y) const; bool electronBeamPos(uInt16& x, uInt16& y) const;
/** /**
Enables/disable/toggle the specified (or all) TIA bit(s). Note that Enables/disable/toggle the specified (or all) TIA bit(s). Note that