Partial TIA updates are, well, partially supported :)

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@658 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
urchlay 2005-07-16 16:09:38 +00:00
parent 453c7fff22
commit 55d57ed1ea
4 changed files with 111 additions and 110 deletions

View File

@ -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.48 2005-07-15 18:19:29 stephena Exp $
// $Id: TIA.cxx,v 1.49 2005-07-16 16:09:37 urchlay Exp $
//============================================================================
#include <cassert>
@ -148,6 +148,7 @@ void TIA::reset()
myClocksToEndOfScanLine = 228;
myVSYNCFinishClock = 0x7FFFFFFF;
myScanlineCountForLastFrame = 0;
myCurrentScanline = 0;
// Currently no objects are enabled
myEnabledObjects = 0;
@ -307,6 +308,7 @@ bool TIA::save(Serializer& out)
out.putLong(myClockAtLastUpdate);
out.putLong(myClocksToEndOfScanLine);
out.putLong(myScanlineCountForLastFrame);
out.putLong(myCurrentScanline);
out.putLong(myVSYNCFinishClock);
out.putLong(myEnabledObjects);
@ -403,6 +405,7 @@ bool TIA::load(Deserializer& in)
myClockAtLastUpdate = (Int32) in.getLong();
myClocksToEndOfScanLine = (Int32) in.getLong();
myScanlineCountForLastFrame = (Int32) in.getLong();
myCurrentScanline = (Int32) in.getLong();
myVSYNCFinishClock = (Int32) in.getLong();
myEnabledObjects = (uInt8) in.getLong();
@ -487,62 +490,82 @@ bool TIA::load(Deserializer& in)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::update()
void TIA::update(int cpuCycles)
{
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)
if(!myPartialFrameFlag) {
// This stuff should only happen at the beginning of a new frame.
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)
{
myCOLUP0 |= 0x01010101;
myCOLUP1 |= 0x01010101;
myCOLUPF |= 0x01010101;
myCOLUBK |= 0x01010101;
}
else
{
myCOLUP0 &= 0xfefefefe;
myCOLUP1 &= 0xfefefefe;
myCOLUPF &= 0xfefefefe;
myCOLUBK &= 0xfefefefe;
}
}
if(myScanlineCountForLastFrame & 0x01)
{
myCOLUP0 |= 0x01010101;
myCOLUP1 |= 0x01010101;
myCOLUPF |= 0x01010101;
myCOLUBK |= 0x01010101;
}
else
{
myCOLUP0 &= 0xfefefefe;
myCOLUP1 &= 0xfefefefe;
myCOLUPF &= 0xfefefefe;
myCOLUBK &= 0xfefefefe;
}
}
}
// Execute instructions until frame is finished
mySystem->m6502().execute(25000);
// Partial frame flag starts out true here. When then 6502 strobes VSYNC,
// TIA::poke() will set this flag to false, so we'll know whether the
// frame got finished or interrupted by the debugger hitting a break/trap.
myPartialFrameFlag = true;
// Execute instructions until frame is finished, or a breakpoint/trap hits
mySystem->m6502().execute(cpuCycles);
cerr << "myPartialFrameFlag==" << myPartialFrameFlag << endl;
// TODO: have code here that handles errors....
// Compute the number of scanlines in the frame
uInt32 totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted;
myScanlineCountForLastFrame = totalClocks / 228;
myCurrentScanline = totalClocks / 228;
// Stats counters
myFrameCounter++;
// This stuff should only happen at the end of a frame
if(!myPartialFrameFlag) {
// Compute the number of scanlines in the frame
myScanlineCountForLastFrame = myCurrentScanline;
// Stats counters
myFrameCounter++;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIA::update()
{
update(25000);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -551,62 +574,7 @@ 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++;
update(76);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -641,7 +609,7 @@ uInt32 TIA::height() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIA::scanlines() const
{
return (uInt32)myScanlineCountForLastFrame;
return (uInt32)myCurrentScanline;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -2062,6 +2030,7 @@ void TIA::poke(uInt16 addr, uInt8 value)
if(((clock - myClockWhenFrameStarted) / 228) > myMaximumNumberOfScanlines)
{
mySystem->m6502().stop();
myPartialFrameFlag = false;
}
switch(addr)
@ -2084,6 +2053,7 @@ void TIA::poke(uInt16 addr, uInt8 value)
// Since we're finished with the frame tell the processor to halt
mySystem->m6502().stop();
myPartialFrameFlag = false;
}
break;
}

View File

@ -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.26 2005-07-15 18:19:29 stephena Exp $
// $Id: TIA.hxx,v 1.27 2005-07-16 16:09:37 urchlay Exp $
//============================================================================
#ifndef TIA_HXX
@ -42,7 +42,7 @@ class Settings;
be displayed on screen.
@author Bradford W. Mott
@version $Id: TIA.hxx,v 1.26 2005-07-15 18:19:29 stephena Exp $
@version $Id: TIA.hxx,v 1.27 2005-07-16 16:09:37 urchlay Exp $
*/
class TIA : public Device , public MediaSource
{
@ -129,6 +129,11 @@ class TIA : public Device , public MediaSource
*/
virtual void update();
/* The backend update method. Currently pointless to make this public, as
we don't support partial scanline updates, but give it time :)
*/
void update(int cpuCycles);
/**
This method should be called to update the media source with
a new scanline.
@ -264,6 +269,10 @@ class TIA : public Device , public MediaSource
// contains an odd number of scanlines.
bool myColorLossEnabled;
// Indicates whether we're done with the current frame. poke() clears this
// when VSYNC is strobed or the max scanlines/frame limit is hit.
bool myPartialFrameFlag;
private:
// Number of frames displayed by this TIA
int myFrameCounter;
@ -317,6 +326,9 @@ class TIA : public Device , public MediaSource
// Indicates the total number of scanlines generated by the last frame
Int32 myScanlineCountForLastFrame;
// Indicates the current scanline during a partial frame.
Int32 myCurrentScanline;
// Indicates the maximum number of scanlines to be generated for a frame
Int32 myMaximumNumberOfScanlines;

View File

@ -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: PromptWidget.cxx,v 1.26 2005-07-08 14:36:18 stephena Exp $
// $Id: PromptWidget.cxx,v 1.27 2005-07-16 16:09:38 urchlay Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -610,6 +610,11 @@ void PromptWidget::addToHistory(const char *str)
_historySize++;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int PromptWidget::compareHistory(const char *histLine) {
return 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PromptWidget::historyScroll(int direction)
{
@ -629,6 +634,18 @@ void PromptWidget::historyScroll(int direction)
int line = _historyLine + direction;
if ((direction < 0 && line < 0) || (direction > 0 && line > _historySize))
return;
// If they press arrow-up with anything in the buffer, search backwards
// in the history.
/*
if(direction < 0 && _currentPos > _promptStartPos) {
for(;line > 0; line--) {
if(compareHistory(_history[line]) == 0)
break;
}
}
*/
_historyLine = line;
// Remove the current user text

View File

@ -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: PromptWidget.hxx,v 1.7 2005-07-05 15:25:44 stephena Exp $
// $Id: PromptWidget.hxx,v 1.8 2005-07-16 16:09:38 urchlay Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -108,6 +108,8 @@ class PromptWidget : public Widget, public CommandSender
OverlayColor textColor;
OverlayColor bgColor;
bool _inverse;
int compareHistory(const char *histLine);
};
#endif