Second pass at scanline advance. It's still not working, but it's

getting closer.  I can change a color in the TiwWidget, advance a few
scanlines, then do a frame advance.  The color changes show up only
after advancing the frame, so obviously TIA::update() is doing
something that TIA::updateScanline() isn't.  Brian, any advice on
this one; it seems I don't know as much about the TIA as I
thought :(


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@657 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-07-15 18:19:29 +00:00
parent dd5fa1d773
commit 453c7fff22
8 changed files with 129 additions and 155 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: Debugger.cxx,v 1.65 2005-07-15 15:27:29 stephena Exp $ // $Id: Debugger.cxx,v 1.66 2005-07-15 18:19:28 stephena Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -636,8 +636,12 @@ const string& Debugger::disassemble(int start, int lines) {
void Debugger::nextScanline(int lines) { void Debugger::nextScanline(int lines) {
saveOldState(); saveOldState();
mySystem->unlockDataBus(); mySystem->unlockDataBus();
myTiaDebug->advanceScanline(lines); // FIXME - add code to 'darken' the current TIA framebuffer, so we can
myOSystem->frameBuffer().refreshTIA(); // differentiate between old content and newly drawn scanlines
// myTiaDebug->clearTIA();
myOSystem->frameBuffer().advanceScanline(lines);
mySystem->lockDataBus(); mySystem->lockDataBus();
} }

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: TIADebug.cxx,v 1.12 2005-07-15 15:27:29 stephena Exp $ // $Id: TIADebug.cxx,v 1.13 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#include "System.hxx" #include "System.hxx"
@ -68,9 +68,9 @@ void TIADebug::saveOldState()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::advanceScanline(int lines) void TIADebug::clearTIA()
{ {
myTIA->advanceFrameScanline(lines); myTIA->clearBuffers();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: TIADebug.hxx,v 1.8 2005-07-15 15:27:29 stephena Exp $ // $Id: TIADebug.hxx,v 1.9 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#ifndef TIA_DEBUG_HXX #ifndef TIA_DEBUG_HXX
@ -42,7 +42,7 @@ class TIADebug : public DebuggerSystem
void saveOldState(); void saveOldState();
void advanceScanline(int lines); void clearTIA();
// FIXME - add whole slew of setXXX() methods // FIXME - add whole slew of setXXX() methods
uInt8 coluP0(int newVal = -1); uInt8 coluP0(int newVal = -1);

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBuffer.cxx,v 1.51 2005-07-03 00:53:59 stephena Exp $ // $Id: FrameBuffer.cxx,v 1.52 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#include <sstream> #include <sstream>
@ -45,6 +45,7 @@ FrameBuffer::FrameBuffer(OSystem* osystem)
myPauseStatus(false), myPauseStatus(false),
theRedrawOverlayIndicator(false), theRedrawOverlayIndicator(false),
myOverlayRedraws(2), myOverlayRedraws(2),
theScanlineAdvanceIndicator(0),
theFrameAdvanceIndicator(0), theFrameAdvanceIndicator(0),
myMessageTime(0), myMessageTime(0),
myMessageText(""), myMessageText(""),
@ -238,6 +239,12 @@ void FrameBuffer::update()
advance = true; advance = true;
--theFrameAdvanceIndicator; --theFrameAdvanceIndicator;
} }
else if(theScanlineAdvanceIndicator > 0)
{
myOSystem->console().mediaSource().updateScanline();
advance = true;
--theScanlineAdvanceIndicator;
}
// Only update the screen if it's been invalidated or we're in // Only update the screen if it's been invalidated or we're in
// frame advance mode // frame advance mode
@ -294,6 +301,17 @@ void FrameBuffer::refreshOverlay(bool now)
if(now) update(); if(now) update();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::advanceScanline(int lines)
{
if(myOSystem->eventHandler().state() != EventHandler::S_DEBUGGER)
return;
theScanlineAdvanceIndicator = lines;
while(theScanlineAdvanceIndicator)
update();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::advance(int frames) void FrameBuffer::advance(int frames)
{ {

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: FrameBuffer.hxx,v 1.46 2005-07-15 15:27:29 stephena Exp $ // $Id: FrameBuffer.hxx,v 1.47 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#ifndef FRAMEBUFFER_HXX #ifndef FRAMEBUFFER_HXX
@ -52,7 +52,7 @@ enum FrameStyle {
All GUI elements (ala ScummVM) are drawn here as well. All GUI elements (ala ScummVM) are drawn here as well.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.46 2005-07-15 15:27:29 stephena Exp $ @version $Id: FrameBuffer.hxx,v 1.47 2005-07-15 18:19:29 stephena Exp $
*/ */
class FrameBuffer class FrameBuffer
{ {
@ -145,6 +145,11 @@ class FrameBuffer
*/ */
void refreshOverlay(bool now = false); void refreshOverlay(bool now = false);
/**
Indicates that the emulation should advance given number of scanlines.
*/
void advanceScanline(int lines);
/** /**
Indicates that the emulation should advance given number of frames. Indicates that the emulation should advance given number of frames.
*/ */
@ -459,6 +464,9 @@ class FrameBuffer
// Number of times menu have been drawn // Number of times menu have been drawn
int myOverlayRedraws; int myOverlayRedraws;
// Indicates how many scanlines the emulation should advance
int theScanlineAdvanceIndicator;
// Indicates how many frames the emulation should advance // Indicates how many frames the emulation should advance
int theFrameAdvanceIndicator; int theFrameAdvanceIndicator;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: MediaSrc.hxx,v 1.11 2005-06-29 13:11:03 stephena Exp $ // $Id: MediaSrc.hxx,v 1.12 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#ifndef MEDIASOURCE_HXX #ifndef MEDIASOURCE_HXX
@ -30,7 +30,7 @@ class Sound;
This class provides an interface for accessing graphics and audio data. This class provides an interface for accessing graphics and audio data.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: MediaSrc.hxx,v 1.11 2005-06-29 13:11:03 stephena Exp $ @version $Id: MediaSrc.hxx,v 1.12 2005-07-15 18:19:29 stephena Exp $
*/ */
class MediaSource class MediaSource
{ {
@ -54,6 +54,13 @@ class MediaSource
*/ */
virtual void update() = 0; virtual void update() = 0;
/**
This method should be called whenever a new scanline is to be drawn.
Invoking this method will update the graphics buffer and generate
the corresponding audio samples.
*/
virtual void updateScanline() = 0;
/** /**
Answers the current frame buffer Answers the current frame buffer

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: TIA.cxx,v 1.47 2005-07-15 15:27:29 stephena Exp $ // $Id: TIA.cxx,v 1.48 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#include <cassert> #include <cassert>
@ -129,10 +129,7 @@ void TIA::reset()
mySound->reset(); mySound->reset();
// Clear frame buffers // Clear frame buffers
for(uInt32 i = 0; i < 160 * 300; ++i) clearBuffers();
{
myCurrentFrameBuffer[i] = myPreviousFrameBuffer[i] = 0;
}
// Reset pixel pointer and drawing flag // Reset pixel pointer and drawing flag
myFramePointer = myCurrentFrameBuffer; myFramePointer = myCurrentFrameBuffer;
@ -548,6 +545,70 @@ void TIA::update()
myFrameCounter++; myFrameCounter++;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::updateScanline()
{
// FIXME - extend this method to draw partial scanlines
// ie, when step/trace is called from the debugger
uInt8* tmp = myCurrentFrameBuffer;
myCurrentFrameBuffer = myPreviousFrameBuffer;
myPreviousFrameBuffer = tmp;
// Remember the number of clocks which have passed on the current scanline
// so that we can adjust the frame's starting clock by this amount. This
// is necessary since some games position objects during VSYNC and the
// TIA's internal counters are not reset by VSYNC.
uInt32 clocks = ((mySystem->cycles() * 3) - myClockWhenFrameStarted) % 228;
// Ask the system to reset the cycle count so it doesn't overflow
mySystem->resetCycles();
// Setup clocks that'll be used for drawing this frame
myClockWhenFrameStarted = -1 * clocks;
myClockStartDisplay = myClockWhenFrameStarted + myStartDisplayOffset;
myClockStopDisplay = myClockWhenFrameStarted + myStopDisplayOffset;
myClockAtLastUpdate = myClockStartDisplay;
myClocksToEndOfScanLine = 228;
// Reset frame buffer pointer
myFramePointer = myCurrentFrameBuffer;
// If color loss is enabled then update the color registers based on
// the number of scanlines in the last frame that was generated
if(myColorLossEnabled)
{
if(myScanlineCountForLastFrame & 0x01)
{
myCOLUP0 |= 0x01010101;
myCOLUP1 |= 0x01010101;
myCOLUPF |= 0x01010101;
myCOLUBK |= 0x01010101;
}
else
{
myCOLUP0 &= 0xfefefefe;
myCOLUP1 &= 0xfefefefe;
myCOLUPF &= 0xfefefefe;
myCOLUBK &= 0xfefefefe;
}
}
// Execute instructions until scanline is finished
mySystem->m6502().execute(76);
// TODO: have code here that handles errors....
// Compute the number of scanlines in the frame
uInt32 totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
myScanlineCountForLastFrame = totalClocks / 228;
cerr << "myScanlineCountForLastFrame = " << myScanlineCountForLastFrame << endl;
// Stats counters
myFrameCounter++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32* TIA::palette() const const uInt32* TIA::palette() const
{ {
@ -1809,142 +1870,12 @@ inline void TIA::waitHorizontalSync()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::advanceFrameScanline(int lines) void TIA::clearBuffers()
{ {
// Ignore # of lines for now for(uInt32 i = 0; i < 160 * 300; ++i)
cerr << "TIA::advanceFrameScanline\n";
Int32 clock = mySystem->cycles() * 3;
// See if we're in the nondisplayable portion of the screen or if
// we've already updated this portion of the screen
if((clock < myClockStartDisplay) ||
(myClockAtLastUpdate >= myClockStopDisplay) ||
(myClockAtLastUpdate >= clock))
{ {
return; myCurrentFrameBuffer[i] = myPreviousFrameBuffer[i] = 0;
} }
// Truncate the number of cycles to update to the stop display point
if(clock > myClockStopDisplay)
{
clock = myClockStopDisplay;
}
// Update frame one scanline at a time
// do
{
// Compute the number of clocks we're going to update
Int32 clocksToUpdate = 0;
// Remember how many clocks we are from the left side of the screen
Int32 clocksFromStartOfScanLine = 228 - myClocksToEndOfScanLine;
// See if we're updating more than the current scanline
if(clock > (myClockAtLastUpdate + myClocksToEndOfScanLine))
{
// Yes, we have more than one scanline to update so finish current one
clocksToUpdate = myClocksToEndOfScanLine;
myClocksToEndOfScanLine = 228;
myClockAtLastUpdate += clocksToUpdate;
}
else
{
// No, so do as much of the current scanline as possible
clocksToUpdate = clock - myClockAtLastUpdate;
myClocksToEndOfScanLine -= clocksToUpdate;
myClockAtLastUpdate = clock;
}
Int32 startOfScanLine = HBLANK + myFrameXStart;
// Skip over as many horizontal blank clocks as we can
if(clocksFromStartOfScanLine < startOfScanLine)
{
uInt32 tmp;
if((startOfScanLine - clocksFromStartOfScanLine) < clocksToUpdate)
tmp = startOfScanLine - clocksFromStartOfScanLine;
else
tmp = clocksToUpdate;
clocksFromStartOfScanLine += tmp;
clocksToUpdate -= tmp;
}
// Remember frame pointer in case HMOVE blanks need to be handled
uInt8* oldFramePointer = myFramePointer;
// Update as much of the scanline as we can
if(clocksToUpdate != 0)
{
updateFrameScanline(clocksToUpdate, clocksFromStartOfScanLine - HBLANK);
}
// Handle HMOVE blanks if they are enabled
if(myHMOVEBlankEnabled && (startOfScanLine < HBLANK + 8) &&
(clocksFromStartOfScanLine < (HBLANK + 8)))
{
Int32 blanks = (HBLANK + 8) - clocksFromStartOfScanLine;
memset(oldFramePointer, 0, blanks);
if((clocksToUpdate + clocksFromStartOfScanLine) >= (HBLANK + 8))
{
myHMOVEBlankEnabled = false;
}
}
// See if we're at the end of a scanline
if(myClocksToEndOfScanLine == 228)
{
myFramePointer -= (160 - myFrameWidth - myFrameXStart);
// Yes, so set PF mask based on current CTRLPF reflection state
myCurrentPFMask = ourPlayfieldTable[myCTRLPF & 0x01];
// TODO: These should be reset right after the first copy of the player
// has passed. However, for now we'll just reset at the end of the
// scanline since the other way would be to slow (01/21/99).
myCurrentP0Mask = &ourPlayerMaskTable[myPOSP0 & 0x03]
[0][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)];
myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03]
[0][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)];
// Handle the "Cosmic Ark" TIA bug if it's enabled
if(myM0CosmicArkMotionEnabled)
{
// Movement table associated with the bug
static uInt32 m[4] = {18, 33, 0, 17};
myM0CosmicArkCounter = (myM0CosmicArkCounter + 1) & 3;
myPOSM0 -= m[myM0CosmicArkCounter];
if(myPOSM0 >= 160)
myPOSM0 -= 160;
else if(myPOSM0 < 0)
myPOSM0 += 160;
if(myM0CosmicArkCounter == 1)
{
// Stretch this missle so it's at least 2 pixels wide
myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03]
[myNUSIZ0 & 0x07][((myNUSIZ0 & 0x30) >> 4) | 0x01]
[160 - (myPOSM0 & 0xFC)];
}
else if(myM0CosmicArkCounter == 2)
{
// Missle is disabled on this line
myCurrentM0Mask = &ourDisabledMaskTable[0];
}
else
{
myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03]
[myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)];
}
}
}
}
// while(myClockAtLastUpdate < clock);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of // See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
// //
// $Id: TIA.hxx,v 1.25 2005-07-15 15:27:29 stephena Exp $ // $Id: TIA.hxx,v 1.26 2005-07-15 18:19:29 stephena Exp $
//============================================================================ //============================================================================
#ifndef TIA_HXX #ifndef TIA_HXX
@ -42,7 +42,7 @@ class Settings;
be displayed on screen. be displayed on screen.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: TIA.hxx,v 1.25 2005-07-15 15:27:29 stephena Exp $ @version $Id: TIA.hxx,v 1.26 2005-07-15 18:19:29 stephena Exp $
*/ */
class TIA : public Device , public MediaSource class TIA : public Device , public MediaSource
{ {
@ -129,6 +129,12 @@ class TIA : public Device , public MediaSource
*/ */
virtual void update(); virtual void update();
/**
This method should be called to update the media source with
a new scanline.
*/
virtual void updateScanline();
/** /**
Answers the current frame buffer Answers the current frame buffer
@ -239,8 +245,8 @@ class TIA : public Device , public MediaSource
// Waste cycles until the current scanline is finished // Waste cycles until the current scanline is finished
void waitHorizontalSync(); void waitHorizontalSync();
// Draw the specified number of scanlines (for debugger use only) // Clear both internal TIA buffers to black (palette color 0)
void advanceFrameScanline(int lines); void clearBuffers();
private: private:
// Console the TIA is associated with // Console the TIA is associated with