Fixed TIA partial scanline updates when stepping/tracing. Now a

step/trace will continue updating the TIA from the last position.
If we haven't entered 'scanline advance' mode yet, step/trace will
now do so.  This was accomplished by moving all CPU updates to TIA, so
that the TIA device now throttles/controls the M6502.

There's now some code bloat in TIA, since there are three methods
updateScanline(), updateScanlinebyStep(), updateScanlinebyTrace() that
are very similar.  But it works, and I'm satisfied to leave it alone
for now.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@825 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2005-10-11 19:38:10 +00:00
parent 568713ee45
commit ceec3433f4
7 changed files with 138 additions and 39 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.96 2005-10-06 17:28:54 stephena Exp $ // $Id: Debugger.cxx,v 1.97 2005-10-11 19:38:10 stephena Exp $
//============================================================================ //============================================================================
#include "bspf.hxx" #include "bspf.hxx"
@ -674,7 +674,7 @@ int Debugger::step()
int cyc = mySystem->cycles(); int cyc = mySystem->cycles();
mySystem->unlockDataBus(); mySystem->unlockDataBus();
mySystem->m6502().execute(1); myOSystem->console().mediaSource().updateScanlineByStep();
mySystem->lockDataBus(); mySystem->lockDataBus();
return mySystem->cycles() - cyc; return mySystem->cycles() - cyc;
@ -693,7 +693,6 @@ int Debugger::step()
int Debugger::trace() int Debugger::trace()
{ {
// 32 is the 6502 JSR instruction: // 32 is the 6502 JSR instruction:
if(mySystem->peek(myCpuDebug->pc()) == 32) { if(mySystem->peek(myCpuDebug->pc()) == 32) {
saveOldState(); saveOldState();
@ -702,10 +701,7 @@ int Debugger::trace()
int targetPC = myCpuDebug->pc() + 3; // return address int targetPC = myCpuDebug->pc() + 3; // return address
mySystem->unlockDataBus(); mySystem->unlockDataBus();
myOSystem->console().mediaSource().updateScanlineByTrace(targetPC);
while(myCpuDebug->pc() != targetPC)
mySystem->m6502().execute(1);
mySystem->lockDataBus(); mySystem->lockDataBus();
return mySystem->cycles() - cyc; return mySystem->cycles() - cyc;
@ -835,7 +831,8 @@ void Debugger::disassemble(IntArray& addr, StringList& addrLabel,
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::nextScanline(int lines) { void Debugger::nextScanline(int lines)
{
saveOldState(); saveOldState();
mySystem->unlockDataBus(); mySystem->unlockDataBus();
myTiaOutput->advanceScanline(lines); myTiaOutput->advanceScanline(lines);
@ -843,7 +840,8 @@ void Debugger::nextScanline(int lines) {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::nextFrame(int frames) { void Debugger::nextFrame(int frames)
{
saveOldState(); saveOldState();
mySystem->unlockDataBus(); mySystem->unlockDataBus();
myTiaOutput->advance(frames); myTiaOutput->advance(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: TiaOutputWidget.cxx,v 1.6 2005-09-23 17:38:27 stephena Exp $ // $Id: TiaOutputWidget.cxx,v 1.7 2005-10-11 19:38:10 stephena Exp $
// //
// Based on code from ScummVM - Scumm Interpreter // Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project // Copyright (C) 2002-2004 The ScummVM project
@ -101,6 +101,8 @@ void TiaOutputWidget::handleMouseDown(int x, int y, int button, int clickCount)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, int id)
{ {
int ystart = atoi(instance()->console().properties().get("Display.YStart").c_str());
switch(cmd) switch(cmd)
{ {
case kCMenuItemSelectedCmd: case kCMenuItemSelectedCmd:
@ -109,8 +111,8 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
case 0: case 0:
{ {
ostringstream command; ostringstream command;
int ystart = atoi(instance()->console().properties().get("Display.YStart").c_str()); int lines = myClickY + ystart -
int lines = myClickY + ystart - instance()->debugger().tiaDebug().scanlines(); instance()->debugger().tiaDebug().scanlines();
if(lines > 0) if(lines > 0)
{ {
command << "scanline #" << lines; command << "scanline #" << lines;
@ -122,7 +124,6 @@ void TiaOutputWidget::handleCommand(CommandSender* sender, int cmd, int data, in
case 1: case 1:
{ {
ostringstream command; ostringstream command;
int ystart = atoi(instance()->console().properties().get("Display.YStart").c_str());
int scanline = myClickY + ystart; int scanline = myClickY + ystart;
command << "breakif _scan==#" << scanline; command << "breakif _scan==#" << scanline;
instance()->debugger().parser()->run(command.str()); instance()->debugger().parser()->run(command.str());

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.12 2005-07-15 18:19:29 stephena Exp $ // $Id: MediaSrc.hxx,v 1.13 2005-10-11 19:38:10 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.12 2005-07-15 18:19:29 stephena Exp $ @version $Id: MediaSrc.hxx,v 1.13 2005-10-11 19:38:10 stephena Exp $
*/ */
class MediaSource class MediaSource
{ {
@ -54,13 +54,6 @@ 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
@ -75,6 +68,29 @@ class MediaSource
*/ */
virtual uInt8* previousFrameBuffer() const = 0; virtual uInt8* previousFrameBuffer() const = 0;
#ifdef DEVELOPER_SUPPORT
/**
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;
/**
This method should be called whenever a new partial scanline is to be
drawn by stepping one CPU instruction. Invoking this method will update the
graphics buffer and generate the corresponding audio samples.
*/
virtual void updateScanlineByStep() = 0;
/**
This method should be called whenever a new partial scanline is to be
drawn by tracing to target address. Invoking this method will update the
graphics buffer and generate the corresponding audio samples.
*/
virtual void updateScanlineByTrace(int target) = 0;
#endif
public: public:
/** /**
Get the palette which maps frame data to RGB values. Get the palette which maps frame data to RGB values.

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.63 2005-10-11 03:22:43 urchlay Exp $ // $Id: TIA.cxx,v 1.64 2005-10-11 19:38:10 stephena Exp $
//============================================================================ //============================================================================
#include <cassert> #include <cassert>
@ -527,7 +527,8 @@ void TIA::update()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void TIA::startFrame() { inline void TIA::startFrame()
{
// This stuff should only happen at the beginning of a new frame. // This stuff should only happen at the beginning of a new frame.
uInt8* tmp = myCurrentFrameBuffer; uInt8* tmp = myCurrentFrameBuffer;
myCurrentFrameBuffer = myPreviousFrameBuffer; myCurrentFrameBuffer = myPreviousFrameBuffer;
@ -576,7 +577,8 @@ inline void TIA::startFrame() {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void TIA::endFrame() { inline void TIA::endFrame()
{
// This stuff should only happen at the end of a frame // This stuff should only happen at the end of a frame
// Compute the number of scanlines in the frame // Compute the number of scanlines in the frame
myScanlineCountForLastFrame = myCurrentScanline; myScanlineCountForLastFrame = myCurrentScanline;
@ -587,6 +589,7 @@ inline void TIA::endFrame() {
myFrameGreyed = false; myFrameGreyed = false;
} }
#ifdef DEVELOPER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::updateScanline() void TIA::updateScanline()
{ {
@ -620,6 +623,67 @@ void TIA::updateScanline()
endFrame(); endFrame();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::updateScanlineByStep()
{
// Start a new frame if the old one was finished
if(!myPartialFrameFlag) {
startFrame();
}
// grey out old frame contents
if(!myFrameGreyed) greyOutFrame();
myFrameGreyed = true;
// true either way:
myPartialFrameFlag = true;
int totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
// Update frame by one CPU instruction/color clock
mySystem->m6502().execute(1);
updateFrame(mySystem->cycles() * 3);
totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
myCurrentScanline = totalClocks / 228;
// if we finished the frame, get ready for the next one
if(!myPartialFrameFlag)
endFrame();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::updateScanlineByTrace(int target)
{
// Start a new frame if the old one was finished
if(!myPartialFrameFlag) {
startFrame();
}
// grey out old frame contents
if(!myFrameGreyed) greyOutFrame();
myFrameGreyed = true;
// true either way:
myPartialFrameFlag = true;
int totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
while(mySystem->m6502().getPC() != target)
{
mySystem->m6502().execute(1);
updateFrame(mySystem->cycles() * 3);
}
totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
myCurrentScanline = totalClocks / 228;
// if we finished the frame, get ready for the next one
if(!myPartialFrameFlag)
endFrame();
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32* TIA::palette() const const uInt32* TIA::palette() const
{ {

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.32 2005-10-11 03:22:43 urchlay Exp $ // $Id: TIA.hxx,v 1.33 2005-10-11 19:38:10 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.32 2005-10-11 03:22:43 urchlay Exp $ @version $Id: TIA.hxx,v 1.33 2005-10-11 19:38:10 stephena Exp $
*/ */
class TIA : public Device , public MediaSource class TIA : public Device , public MediaSource
{ {
@ -129,12 +129,6 @@ 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
@ -221,6 +215,26 @@ class TIA : public Device , public MediaSource
*/ */
void enableBits(bool mode) { for(uInt8 i = 0; i < 6; ++i) myBitEnabled[i] = mode; } void enableBits(bool mode) { for(uInt8 i = 0; i < 6; ++i) myBitEnabled[i] = mode; }
#ifdef DEVELOPER_SUPPORT
/**
This method should be called to update the media source with
a new scanline.
*/
virtual void updateScanline();
/**
This method should be called to update the media source with
a new partial scanline by stepping one CPU instruction.
*/
virtual void updateScanlineByStep();
/**
This method should be called to update the media source with
a new partial scanline by tracing to target address.
*/
virtual void updateScanlineByTrace(int target);
#endif
private: private:
// Compute the ball mask table // Compute the ball mask table
void computeBallMaskTable(); void computeBallMaskTable();

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: M6502.hxx,v 1.14 2005-09-20 19:09:10 stephena Exp $ // $Id: M6502.hxx,v 1.15 2005-10-11 19:38:10 stephena Exp $
//============================================================================ //============================================================================
#ifndef M6502_HXX #ifndef M6502_HXX
@ -41,7 +41,7 @@ typedef GUI::Array<Expression*> ExpressionList;
has a 64K addressing space. has a 64K addressing space.
@author Bradford W. Mott @author Bradford W. Mott
@version $Id: M6502.hxx,v 1.14 2005-09-20 19:09:10 stephena Exp $ @version $Id: M6502.hxx,v 1.15 2005-10-11 19:38:10 stephena Exp $
*/ */
class M6502 class M6502
{ {
@ -164,6 +164,13 @@ class M6502
return myExecutionStatus & FatalErrorBit; return myExecutionStatus & FatalErrorBit;
} }
/**
Get the 16-bit value of the Program Counter register.
@return The program counter register
*/
uInt16 getPC() const { return PC; }
public: public:
/** /**
Overload the ostream output operator for addressing modes. Overload the ostream output operator for addressing modes.

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: M6502Hi.cxx,v 1.13 2005-09-20 19:09:10 stephena Exp $ // $Id: M6502Hi.cxx,v 1.14 2005-10-11 19:38:10 stephena Exp $
//============================================================================ //============================================================================
#include "M6502Hi.hxx" #include "M6502Hi.hxx"
@ -90,8 +90,6 @@ inline void M6502High::poke(uInt16 address, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool M6502High::execute(uInt32 number) bool M6502High::execute(uInt32 number)
{ {
int cond = -1;
// Clear all of the execution status bits except for the fatal error bit // Clear all of the execution status bits except for the fatal error bit
myExecutionStatus &= FatalErrorBit; myExecutionStatus &= FatalErrorBit;
@ -122,7 +120,8 @@ bool M6502High::execute(uInt32 number)
} }
} }
if((cond = evalCondBreaks()) > -1) int cond = evalCondBreaks();
if(cond > -1)
{ {
string buf = "CBP: " + myBreakCondNames[cond]; string buf = "CBP: " + myBreakCondNames[cond];
if(myDebugger->start(buf)) if(myDebugger->start(buf))