mirror of https://github.com/stella-emu/stella.git
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:
parent
dd5fa1d773
commit
453c7fff22
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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"
|
||||
|
@ -636,8 +636,12 @@ const string& Debugger::disassemble(int start, int lines) {
|
|||
void Debugger::nextScanline(int lines) {
|
||||
saveOldState();
|
||||
mySystem->unlockDataBus();
|
||||
myTiaDebug->advanceScanline(lines);
|
||||
myOSystem->frameBuffer().refreshTIA();
|
||||
// FIXME - add code to 'darken' the current TIA framebuffer, so we can
|
||||
// differentiate between old content and newly drawn scanlines
|
||||
// myTiaDebug->clearTIA();
|
||||
|
||||
myOSystem->frameBuffer().advanceScanline(lines);
|
||||
|
||||
mySystem->lockDataBus();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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"
|
||||
|
@ -68,9 +68,9 @@ void TIADebug::saveOldState()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIADebug::advanceScanline(int lines)
|
||||
void TIADebug::clearTIA()
|
||||
{
|
||||
myTIA->advanceFrameScanline(lines);
|
||||
myTIA->clearBuffers();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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
|
||||
|
@ -42,7 +42,7 @@ class TIADebug : public DebuggerSystem
|
|||
|
||||
void saveOldState();
|
||||
|
||||
void advanceScanline(int lines);
|
||||
void clearTIA();
|
||||
|
||||
// FIXME - add whole slew of setXXX() methods
|
||||
uInt8 coluP0(int newVal = -1);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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>
|
||||
|
@ -45,6 +45,7 @@ FrameBuffer::FrameBuffer(OSystem* osystem)
|
|||
myPauseStatus(false),
|
||||
theRedrawOverlayIndicator(false),
|
||||
myOverlayRedraws(2),
|
||||
theScanlineAdvanceIndicator(0),
|
||||
theFrameAdvanceIndicator(0),
|
||||
myMessageTime(0),
|
||||
myMessageText(""),
|
||||
|
@ -238,6 +239,12 @@ void FrameBuffer::update()
|
|||
advance = true;
|
||||
--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
|
||||
// frame advance mode
|
||||
|
@ -294,6 +301,17 @@ void FrameBuffer::refreshOverlay(bool now)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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
|
||||
|
@ -52,7 +52,7 @@ enum FrameStyle {
|
|||
All GUI elements (ala ScummVM) are drawn here as well.
|
||||
|
||||
@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
|
||||
{
|
||||
|
@ -145,6 +145,11 @@ class FrameBuffer
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -459,6 +464,9 @@ class FrameBuffer
|
|||
// Number of times menu have been drawn
|
||||
int myOverlayRedraws;
|
||||
|
||||
// Indicates how many scanlines the emulation should advance
|
||||
int theScanlineAdvanceIndicator;
|
||||
|
||||
// Indicates how many frames the emulation should advance
|
||||
int theFrameAdvanceIndicator;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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
|
||||
|
@ -30,7 +30,7 @@ class Sound;
|
|||
This class provides an interface for accessing graphics and audio data.
|
||||
|
||||
@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
|
||||
{
|
||||
|
@ -54,6 +54,13 @@ class MediaSource
|
|||
*/
|
||||
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
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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>
|
||||
|
@ -129,10 +129,7 @@ void TIA::reset()
|
|||
mySound->reset();
|
||||
|
||||
// Clear frame buffers
|
||||
for(uInt32 i = 0; i < 160 * 300; ++i)
|
||||
{
|
||||
myCurrentFrameBuffer[i] = myPreviousFrameBuffer[i] = 0;
|
||||
}
|
||||
clearBuffers();
|
||||
|
||||
// Reset pixel pointer and drawing flag
|
||||
myFramePointer = myCurrentFrameBuffer;
|
||||
|
@ -548,6 +545,70 @@ void TIA::update()
|
|||
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
|
||||
{
|
||||
|
@ -1809,142 +1870,12 @@ inline void TIA::waitHorizontalSync()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::advanceFrameScanline(int lines)
|
||||
void TIA::clearBuffers()
|
||||
{
|
||||
// Ignore # of lines for now
|
||||
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))
|
||||
for(uInt32 i = 0; i < 160 * 300; ++i)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// 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
|
||||
|
@ -42,7 +42,7 @@ class Settings;
|
|||
be displayed on screen.
|
||||
|
||||
@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
|
||||
{
|
||||
|
@ -129,6 +129,12 @@ class TIA : public Device , public MediaSource
|
|||
*/
|
||||
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
|
||||
|
||||
|
@ -239,8 +245,8 @@ class TIA : public Device , public MediaSource
|
|||
// Waste cycles until the current scanline is finished
|
||||
void waitHorizontalSync();
|
||||
|
||||
// Draw the specified number of scanlines (for debugger use only)
|
||||
void advanceFrameScanline(int lines);
|
||||
// Clear both internal TIA buffers to black (palette color 0)
|
||||
void clearBuffers();
|
||||
|
||||
private:
|
||||
// Console the TIA is associated with
|
||||
|
|
Loading…
Reference in New Issue