Simplified TIA class by removing 'greying' functionality to the debugger,

where it more properly belongs.  The greyed values are now from PAL
color-loss, which is also calculated for NTSC (though it's never actually
used in NTSC mode for regular rendering).  This also fixes problems with
debugger state files being saved with greyed values, and sometimes having
the frame greyed twice (hence making it impossible to see).  It should
also result in a slight speed increase, since some code has been taken
out of the TIA rendering fast path.

Added electron beam indicator the the TIA output in the debugger.
Basically, it's just a small square indicating where drawing will
start for the next instruction.

Fixed TIA output in the debugger so that right-clicking and selecting
'fill to scanline' actually works without first having to manually
enter partial frame mode.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1868 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-09-01 11:54:59 +00:00
parent 33130a78f0
commit a7da944b36
9 changed files with 124 additions and 107 deletions

View File

@ -546,6 +546,7 @@ uInt8 TIADebug::posP0(int newVal)
{
if(newVal > -1)
myTIA.myPOSP0 = newVal;
return myTIA.myPOSP0;
}
@ -554,36 +555,34 @@ uInt8 TIADebug::posP1(int newVal)
{
if(newVal > -1)
myTIA.myPOSP1 = newVal;
return myTIA.myPOSP1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIADebug::posM0(int newVal)
{
/* FIXME
if(newVal > -1)
mySystem.poke(???, newVal);
*/
myTIA.myPOSM0 = newVal;
return myTIA.myPOSM0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIADebug::posM1(int newVal)
{
/* FIXME
if(newVal > -1)
mySystem.poke(???, newVal);
*/
myTIA.myPOSM1 = newVal;
return myTIA.myPOSM1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIADebug::posBL(int newVal)
{
/* FIXME
if(newVal > -1)
mySystem.poke(???, newVal);
*/
myTIA.myPOSBL = newVal;
return myTIA.myPOSBL;
}

View File

@ -91,8 +91,9 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
if(rmb == "scanline")
{
ostringstream command;
int lines = myClickY + ystart -
instance().debugger().tiaDebug().scanlines();
int lines = myClickY + ystart;
if(instance().console().tia().partialFrame())
lines -= instance().console().tia().scanlines();
if(lines > 0)
{
command << "scanline #" << lines;
@ -120,20 +121,34 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
void TiaOutputWidget::drawWidget(bool hilite)
{
//cerr << "TiaOutputWidget::drawWidget\n";
// FIXME - maybe 'greyed out mode' should be done here, not in the TIA class
FBSurface& s = dialog().surface();
const uInt32 width = 160, // width is always 160
const uInt32 width = instance().console().tia().width(),
height = instance().console().tia().height();
for(uInt32 y = 0; y < height; ++y)
// Get current scanline position
// This determines where the frame greying should start, and where a
// scanline 'pointer' should be drawn
uInt16 scanx, scany, scanoffset;
bool visible = instance().console().tia().scanlinePos(scanx, scany);
scanoffset = width * scany + scanx;
for(uInt32 y = 0, i = 0; y < height; ++y)
{
uInt32* line_ptr = myLineBuffer;
for(uInt32 x = 0; x < width; ++x)
for(uInt32 x = 0; x < width; ++x, ++i)
{
uInt32 pixel = instance().frameBuffer().tiaPixel(y*width+x);
uInt8 shift = i > scanoffset ? 1 : 0;
uInt32 pixel = instance().frameBuffer().tiaPixel(i, shift);
*line_ptr++ = pixel;
*line_ptr++ = pixel;
}
s.drawPixels(myLineBuffer, _x, _y+y, width << 1);
}
// Show electron beam position
if(visible && scanx < width && scany+2u < height)
{
s.fillRect(_x+scanx<<1, _y+scany, 3, 3, kBtnTextColor);
}
}

View File

@ -220,18 +220,25 @@ void TiaZoomWidget::drawWidget(bool hilite)
// Draw the zoomed image
// 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 :)
uInt8* currentFrame = instance().console().tia().currentFrameBuffer();
const int pitch = instance().console().tia().width(),
width = myZoomLevel << 1,
height = myZoomLevel;
const uInt8* currentFrame = instance().console().tia().currentFrameBuffer();
const int width = instance().console().tia().width(),
wzoom = myZoomLevel << 1,
hzoom = myZoomLevel;
// Get current scanline position
// This determines where the frame greying should start
uInt16 scanx, scany, scanoffset;
instance().console().tia().scanlinePos(scanx, scany);
scanoffset = width * scany + scanx;
int x, y, col, row;
for(y = myYoff, row = 0; y < myNumRows+myYoff; ++y, row += height)
for(y = myYoff, row = 0; y < myNumRows+myYoff; ++y, row += hzoom)
{
for(x = myXoff, col = 0; x < myNumCols+myXoff; ++x, col += width)
for(x = myXoff, col = 0; x < myNumCols+myXoff; ++x, col += wzoom)
{
s.fillRect(_x + col + 2, _y + row + 2, width, height,
currentFrame[y*pitch + x]);
uInt32 idx = y*width + x;
uInt32 color = currentFrame[idx] | (idx > scanoffset ? 1 : 0);
s.fillRect(_x + col + 2, _y + row + 2, wzoom, hzoom, color);
}
}
}

View File

@ -293,8 +293,7 @@ void Console::toggleColorLoss()
{
bool colorloss = !myOSystem->settings().getBool("colorloss");
myOSystem->settings().setBool("colorloss", colorloss);
setColorLossPalette(colorloss);
setPalette(myOSystem->settings().getString("palette"));
myTIA->enableColorLoss(colorloss);
string message = string("PAL color-loss ") +
(colorloss ? "enabled" : "disabled");
@ -420,12 +419,13 @@ bool Console::initializeVideo(bool full)
myOSystem->frameBuffer().showFrameStats(
myOSystem->settings().getBool("stats"));
setColorLossPalette();
}
bool enable = myProperties.get(Display_Phosphor) == "YES";
int blend = atoi(myProperties.get(Display_PPBlend).c_str());
myOSystem->frameBuffer().enablePhosphor(enable, blend);
setColorLossPalette(myOSystem->settings().getBool("colorloss"));
setPalette(myOSystem->settings().getString("palette"));
// Set the correct framerate based on the format of the ROM
@ -741,7 +741,7 @@ void Console::loadUserPalette()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setColorLossPalette(bool loss)
void Console::setColorLossPalette()
{
// Look at all the palettes, since we don't know which one is
// currently active
@ -762,23 +762,18 @@ void Console::setColorLossPalette(bool loss)
if(palette[i] == 0)
continue;
// If color-loss is enabled, fill the odd numbered palette entries
// with gray values (calculated using the standard RGB -> grayscale
// conversion formula)
// Fill the odd numbered palette entries with gray values (calculated
// using the standard RGB -> grayscale conversion formula)
for(int j = 0; j < 128; ++j)
{
uInt32 pixel = palette[i][(j<<1)];
if(loss)
{
uInt8 r = (pixel >> 16) & 0xff;
uInt8 g = (pixel >> 8) & 0xff;
uInt8 b = (pixel >> 0) & 0xff;
uInt8 sum = (uInt8) (((float)r * 0.2989) +
((float)g * 0.5870) +
((float)b * 0.1140));
pixel = (sum << 16) + (sum << 8) + sum;
}
palette[i][(j<<1)+1] = pixel;
uInt8 r = (pixel >> 16) & 0xff;
uInt8 g = (pixel >> 8) & 0xff;
uInt8 b = (pixel >> 0) & 0xff;
uInt8 sum = (uInt8) (((float)r * 0.2989) +
((float)g * 0.5870) +
((float)b * 0.1140));
palette[i][(j<<1)+1] = (sum << 16) + (sum << 8) + sum;
}
}
}

View File

@ -282,10 +282,11 @@ class Console : public Serializable
void loadUserPalette();
/**
Loads all defined palettes with PAL color-loss data depending
on 'state'.
Loads all defined palettes with PAL color-loss data, even those that
normally can't have it enabled (NTSC), since it's also used for
'greying out' the frame in the debugger.
*/
void setColorLossPalette(bool state);
void setColorLossPalette();
/**
Returns a pointer to the palette data for the palette currently defined

View File

@ -508,10 +508,10 @@ void FrameBuffer::resetSurfaces()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::tiaPixel(uInt32 idx) const
uInt32 FrameBuffer::tiaPixel(uInt32 idx, uInt8 shift) const
{
uInt8 c = *(myOSystem->console().tia().currentFrameBuffer() + idx);
uInt8 p = *(myOSystem->console().tia().previousFrameBuffer() + idx);
uInt8 c = *(myOSystem->console().tia().currentFrameBuffer() + idx) | shift;
uInt8 p = *(myOSystem->console().tia().previousFrameBuffer() + idx) | shift;
return (!myUsePhosphor ? myDefPalette[c] : myAvgPalette[c][p]);
}

View File

@ -247,9 +247,10 @@ class FrameBuffer
const StringMap& supportedTIAFilters(const string& type);
/**
Get the TIA pixel associated with the given TIA buffer index.
Get the TIA pixel associated with the given TIA buffer index,
shifting by the given offset (for greyscale values).
*/
uInt32 tiaPixel(uInt32 idx) const;
uInt32 tiaPixel(uInt32 idx, uInt8 shift = 0) const;
/**
Set up the TIA/emulation palette for a screen of any depth > 8.

View File

@ -44,7 +44,6 @@ TIA::TIA(Console& console, Sound& sound, Settings& settings)
myMaximumNumberOfScanlines(262),
myColorLossEnabled(false),
myPartialFrameFlag(false),
myFrameGreyed(false),
myAutoFrameEnabled(false),
myFrameCounter(0)
{
@ -181,7 +180,7 @@ void TIA::reset()
myFixedColor[_PF] = 0xd8d8d8d8;
myFixedColor[_BK] = 0x1c1c1c1c;
myFixedColor[_HBLANK] = 0x0e0e0e0e;
myColorLossEnabled = true;
myColorLossEnabled = mySettings.getBool("colorloss");
myMaximumNumberOfScanlines = 342;
}
@ -543,10 +542,7 @@ bool TIA::loadDisplay(Serializer& in)
// If we're in partial frame mode, make sure to re-create the screen
// as it existed when the state was saved
if(myPartialFrameFlag)
{
myFramePointer += myFramePointerClocks;
myFrameGreyed = true;
}
}
catch(const char* msg)
{
@ -574,15 +570,7 @@ void TIA::update()
// TODO: have code here that handles errors....
if(myPartialFrameFlag)
{
// Grey out old frame contents
if(!myFrameGreyed)
greyOutFrame();
myFrameGreyed = true;
}
else
endFrame();
endFrame();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -633,8 +621,6 @@ inline void TIA::startFrame()
}
}
myStartScanline = 0x7FFFFFFF;
myFrameGreyed = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -678,8 +664,33 @@ inline void TIA::endFrame()
memset(myCurrentFrameBuffer, 0, 160 * 320);
memset(myPreviousFrameBuffer, 1, 160 * 320);
}
}
myFrameGreyed = false;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIA::scanlinePos(uInt16& x, uInt16& y) const
{
if(myPartialFrameFlag)
{
// We only care about the scanline position when it's in the viewable area
if(myFramePointerClocks >= myFramePointerOffset)
{
x = (myFramePointerClocks - myFramePointerOffset) % 160;
y = (myFramePointerClocks - myFramePointerOffset) / 160;
return true;
}
else
{
x = 0;
y = 0;
return false;
}
}
else
{
x = width();
y = height();
return false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -726,11 +737,6 @@ void TIA::updateScanline()
if(!myPartialFrameFlag)
startFrame();
// grey out old frame contents
if(!myFrameGreyed)
greyOutFrame();
myFrameGreyed = true;
// true either way:
myPartialFrameFlag = true;
@ -756,10 +762,6 @@ void TIA::updateScanlineByStep()
if(!myPartialFrameFlag)
startFrame();
// grey out old frame contents
if(!myFrameGreyed) greyOutFrame();
myFrameGreyed = true;
// true either way:
myPartialFrameFlag = true;
@ -779,10 +781,6 @@ void TIA::updateScanlineByTrace(int target)
if(!myPartialFrameFlag)
startFrame();
// grey out old frame contents
if(!myFrameGreyed) greyOutFrame();
myFrameGreyed = true;
// true either way:
myPartialFrameFlag = true;
@ -1575,27 +1573,6 @@ inline void TIA::waitHorizontalSync()
mySystem->incrementCycles(cyclesToEndOfLine);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::greyOutFrame()
{
uInt32 c = scanlines();
if(c < myFrameYStart) c = myFrameYStart;
if(c > (myFrameHeight + myFrameYStart))
return;
//cerr << "greying frame from scanline " << c << endl;
uInt8* buffer = myCurrentFrameBuffer + myFramePointerOffset;
for(uInt32 s = c; s < (myFrameHeight + myFrameYStart); ++s)
{
for(uInt32 i = 0; i < 160; ++i)
{
uInt32 idx = (s - myFrameYStart) * 160 + i;
buffer[idx] = ((buffer[idx] & 0x0f) >> 1);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::clearBuffers()
{

View File

@ -195,6 +195,14 @@ class TIA : public Device
*/
void enableAutoFrame(bool mode) { myAutoFrameEnabled = mode; }
/**
Enables/disables color-loss for PAL modes only.
@param mode Whether to enable or disable PAL color-loss mode
*/
void enableColorLoss(bool mode)
{ myColorLossEnabled = myFramerate <= 55 ? mode : false; }
/**
Answers the current color clock we've gotten to on this scanline.
@ -213,6 +221,14 @@ class TIA : public Device
inline uInt32 scanlines() const
{ return ((mySystem->cycles() * 3) - myClockWhenFrameStarted) / 228; }
/**
Answers whether the TIA is currently in 'partial frame' mode
(we're in between a call of startFrame and endFrame).
@return If we're in partial frame mode
*/
inline bool partialFrame() const { return myPartialFrameFlag; }
/**
Answers the first scanline at which drawing occured in the last frame.
@ -220,6 +236,18 @@ class TIA : public Device
*/
inline uInt32 startScanline() const { return myStartScanline; }
/**
Answers the current position of the virtual 'electron beam' used to
draw the TIA image. If not in partial frame mode, the position is
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
it is in the visible/viewable area of the screen
*/
bool scanlinePos(uInt16& x, uInt16& y) const;
/**
Enables/disables all TIABit bits.
@ -276,9 +304,6 @@ class TIA : public Device
// Waste cycles until the current scanline is finished
void waitHorizontalSync();
// Grey out current framebuffer from current scanline to bottom
void greyOutFrame();
// Clear both internal TIA buffers to black (palette color 0)
void clearBuffers();
@ -524,9 +549,6 @@ class TIA : public Device
// when VSYNC is strobed or the max scanlines/frame limit is hit.
bool myPartialFrameFlag;
// Has current frame been "greyed out" (has updateScanline() been run?)
bool myFrameGreyed;
// Automatic framerate correction based on number of scanlines
bool myAutoFrameEnabled;