mirror of https://github.com/stella-emu/stella.git
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:
parent
33130a78f0
commit
a7da944b36
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue