Well, it's finally here. First pass at the new TIA code, which improves

emulation when performing 'illegal' HMOVEs (aka, when modifying the HMxx
registers within 24 CPU cycles of HMOVE).

All tweaks for illegal HMOVEs have been removed; and all ROMs that
previously needed those tweaks are now working correctly.  Several other
ROMs are fixed as well, including Bumper Bash and Pole Position.

As this is WIP, there is also some breakage:

1)  Cosmic Ark 'TIA confusion mode' effects aren't complete; the
movement is correct, but the missile widths aren't corrected yet.

2)  Performing a write to NUSIZx while a player is still drawing
isn't complete.  This breaks several ROMs that worked before, such
as Galaxian and Space Instigators.

3)  Writes to RESPx aren't complete yet, especially if they're
combined with an immediate write to NUSIZx.

Most of the ideas (and some code) for these changes comes from
contributions to MESS and EMU7800.  Where applicable, permission
was obtained from the original author to use the code/ideas.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1845 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-08-02 15:34:43 +00:00
parent c457cea658
commit 5e4b690d8d
8 changed files with 687 additions and 502 deletions

View File

@ -473,9 +473,9 @@ int Debugger::step()
int cyc = mySystem->cycles();
unlockState();
unlockBankswitchState();
myOSystem->console().tia().updateScanlineByStep();
lockState();
lockBankswitchState();
return mySystem->cycles() - cyc;
}
@ -501,9 +501,9 @@ int Debugger::trace()
int cyc = mySystem->cycles();
int targetPC = myCpuDebug->pc() + 3; // return address
unlockState();
unlockBankswitchState();
myOSystem->console().tia().updateScanlineByTrace(targetPC);
lockState();
lockBankswitchState();
return mySystem->cycles() - cyc;
}
@ -633,9 +633,13 @@ void Debugger::nextScanline(int lines)
{
saveOldState();
unlockState();
myTiaOutput->advanceScanline(lines);
lockState();
unlockBankswitchState();
while(lines)
{
myOSystem->console().tia().updateScanline();
--lines;
}
lockBankswitchState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -643,9 +647,13 @@ void Debugger::nextFrame(int frames)
{
saveOldState();
unlockState();
myTiaOutput->advance(frames);
lockState();
unlockBankswitchState();
while(frames)
{
myOSystem->console().tia().update();
--frames;
}
lockBankswitchState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -746,14 +754,14 @@ void Debugger::saveOldState()
void Debugger::setStartState()
{
// Lock the bus each time the debugger is entered, so we don't disturb anything
lockState();
lockBankswitchState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setQuitState()
{
// Bus must be unlocked for normal operation when leaving debugger mode
unlockState();
unlockBankswitchState();
// execute one instruction on quit. If we're
// sitting at a breakpoint/trap, this will get us past it.
@ -911,14 +919,14 @@ bool Debugger::saveROM(const string& filename) const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::lockState()
void Debugger::lockBankswitchState()
{
mySystem->lockDataBus();
myConsole->cartridge().lockBank();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::unlockState()
void Debugger::unlockBankswitchState()
{
mySystem->unlockDataBus();
myConsole->cartridge().unlockBank();

View File

@ -306,8 +306,16 @@ class Debugger : public DialogContainer
bool setBank(int bank);
bool patchROM(int addr, int value);
void lockState();
void unlockState();
/**
Normally, accessing RAM or ROM during emulation can possibly trigger
bankswitching. However, when we're in the debugger, we'd like to
inspect values without actually triggering bankswitches. The
read/write state must therefore be locked before accessing values,
and unlocked for normal emulation to occur.
(takes mediasource into account)
*/
void lockBankswitchState();
void unlockBankswitchState();
private:
/**

View File

@ -16,8 +16,6 @@
// $Id$
//============================================================================
//#define NEWTIA
#include "System.hxx"
#include "Debugger.hxx"
@ -617,11 +615,7 @@ uInt8 TIADebug::hmP0(int newVal)
if(newVal > -1)
mySystem.poke(HMP0, newVal << 4);
#ifdef NEWTIA
return myTIA.myHMP0 >> 4;
#else
return myTIA.myHMP0;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -630,11 +624,7 @@ uInt8 TIADebug::hmP1(int newVal)
if(newVal > -1)
mySystem.poke(HMP1, newVal << 4);
#ifdef NEWTIA
return myTIA.myHMP1 >> 4;
#else
return myTIA.myHMP1;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -643,11 +633,7 @@ uInt8 TIADebug::hmM0(int newVal)
if(newVal > -1)
mySystem.poke(HMM0, newVal << 4);
#ifdef NEWTIA
return myTIA.myHMM0 >> 4;
#else
return myTIA.myHMM0;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -656,11 +642,7 @@ uInt8 TIADebug::hmM1(int newVal)
if(newVal > -1)
mySystem.poke(HMM1, newVal << 4);
#ifdef NEWTIA
return myTIA.myHMM1 >> 4;
#else
return myTIA.myHMM1;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -669,11 +651,7 @@ uInt8 TIADebug::hmBL(int newVal)
if(newVal > -1)
mySystem.poke(HMBL, newVal << 4);
#ifdef NEWTIA
return myTIA.myHMBL >> 4;
#else
return myTIA.myHMBL;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -63,26 +63,6 @@ void TiaOutputWidget::loadConfig()
setDirty(); draw();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaOutputWidget::advanceScanline(int lines)
{
while(lines)
{
instance().console().tia().updateScanline();
--lines;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaOutputWidget::advance(int frames)
{
while(frames)
{
instance().console().tia().update();
--frames;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TiaOutputWidget::handleMouseDown(int x, int y, int button, int clickCount)
{

View File

@ -49,8 +49,6 @@ class TiaOutputWidget : public Widget, public CommandSender
virtual bool handleKeyDown(int ascii, int keycode, int modifiers);
virtual bool handleKeyUp(int ascii, int keycode, int modifiers);
*/
void advanceScanline(int lines);
void advance(int frames);
protected:
void handleMouseDown(int x, int y, int button, int clickCount);

File diff suppressed because it is too large Load Diff

View File

@ -266,6 +266,19 @@ class TIA : public Device
// Convert resistance from ports to dumped value
uInt8 dumpedInputPort(int resistance);
// Write the specified value to the HMOVE registers at the given clock
void pokeHMP0(uInt8 value, Int32 clock);
void pokeHMP1(uInt8 value, Int32 clock);
void pokeHMM0(uInt8 value, Int32 clock);
void pokeHMM1(uInt8 value, Int32 clock);
void pokeHMBL(uInt8 value, Int32 clock);
// Apply motion to registers when HMOVE is currently active
inline void applyActiveHMOVEMotion(int hpos, Int16& pos, Int32 motionClock);
// Apply motion to registers when HMOVE was previously active
inline void applyPreviousHMOVEMotion(int hpos, Int16& pos, uInt8 motion);
private:
// Console the TIA is associated with
Console& myConsole;
@ -321,29 +334,11 @@ class TIA : public Device
// displayed portion of the frame.
Int32 myClocksToEndOfScanLine;
// The color clocks elapsed so far for each of the graphical objects,
// as denoted by 'MOTCK' line described in A. Towers TIA Hardware Notes
Int32 myMotionClockP0;
Int32 myMotionClockP1;
Int32 myMotionClockM0;
Int32 myMotionClockM1;
Int32 myMotionClockBL;
// Indicates 'start' signal for each of the graphical objects as
// described in A. Towers TIA Hardware Notes
Int32 myStartP0;
Int32 myStartP1;
Int32 myStartM0;
Int32 myStartM1;
// Indicates the total number of scanlines generated by the last frame
Int32 myScanlineCountForLastFrame;
// Indicates the current scanline during a partial frame.
Int32 myCurrentScanline;
uInt32 myScanlineCountForLastFrame;
// Indicates the maximum number of scanlines to be generated for a frame
Int32 myMaximumNumberOfScanlines;
uInt32 myMaximumNumberOfScanlines;
// Color clock when VSYNC ending causes a new frame to be started
Int32 myVSYNCFinishClock;
@ -377,25 +372,25 @@ class TIA : public Device
uInt8 myDGRP1; // Player 1 delayed graphics register
bool myENAM0; // Indicates if missle 0 is enabled
bool myENAM1; // Indicates if missle 0 is enabled
bool myENAM1; // Indicates if missle 1 is enabled
bool myENABL; // Indicates if the ball is enabled
bool myDENABL; // Indicates if the virtically delayed ball is enabled
bool myDENABL; // Indicates if the vertically delayed ball is enabled
Int8 myHMP0; // Player 0 horizontal motion register
Int8 myHMP1; // Player 1 horizontal motion register
Int8 myHMM0; // Missle 0 horizontal motion register
Int8 myHMM1; // Missle 1 horizontal motion register
Int8 myHMBL; // Ball horizontal motion register
uInt8 myHMP0; // Player 0 horizontal motion register
uInt8 myHMP1; // Player 1 horizontal motion register
uInt8 myHMM0; // Missle 0 horizontal motion register
uInt8 myHMM1; // Missle 1 horizontal motion register
uInt8 myHMBL; // Ball horizontal motion register
bool myVDELP0; // Indicates if player 0 is being virtically delayed
bool myVDELP1; // Indicates if player 1 is being virtically delayed
bool myVDELBL; // Indicates if the ball is being virtically delayed
bool myVDELP0; // Indicates if player 0 is being vertically delayed
bool myVDELP1; // Indicates if player 1 is being vertically delayed
bool myVDELBL; // Indicates if the ball is being vertically delayed
bool myRESMP0; // Indicates if missle 0 is reset to player 0
bool myRESMP1; // Indicates if missle 1 is reset to player 1
uInt16 myCollision; // Collision register
uInt16 myCollision; // Collision register
// Note that these position registers contain the color clock
// on which the object's serial output should begin (0 to 159)
@ -405,6 +400,29 @@ class TIA : public Device
Int16 myPOSM1; // Missle 1 position register
Int16 myPOSBL; // Ball position register
// The color clocks elapsed so far for each of the graphical objects,
// as denoted by 'MOTCK' line described in A. Towers TIA Hardware Notes
Int32 myMotionClockP0;
Int32 myMotionClockP1;
Int32 myMotionClockM0;
Int32 myMotionClockM1;
Int32 myMotionClockBL;
// Indicates 'start' signal for each of the graphical objects as
// described in A. Towers TIA Hardware Notes
Int32 myStartP0;
Int32 myStartP1;
Int32 myStartM0;
Int32 myStartM1;
// Latches for 'more motion required' as described in A. Towers TIA
// Hardware Notes
bool myHMP0mmr;
bool myHMP1mmr;
bool myHMM0mmr;
bool myHMM1mmr;
bool myHMBLmmr;
// Graphics for Player 0 that should be displayed. This will be
// reflected if the player is being reflected.
uInt8 myCurrentGRP0;
@ -435,13 +453,8 @@ class TIA : public Device
// Pointer to the currently active mask array for the playfield
uInt32* myCurrentPFMask;
// Audio values. Only used by TIADebug.
uInt8 myAUDV0;
uInt8 myAUDV1;
uInt8 myAUDC0;
uInt8 myAUDC1;
uInt8 myAUDF0;
uInt8 myAUDF1;
// Audio values; only used by TIADebug
uInt8 myAUDV0, myAUDV1, myAUDC0, myAUDC1, myAUDF0, myAUDF1;
// Indicates when the dump for paddles was last set
Int32 myDumpDisabledCycle;
@ -449,21 +462,15 @@ class TIA : public Device
// Indicates if the dump is current enabled for the paddles
bool myDumpEnabled;
// Color clock when last HMOVE occured
Int32 myLastHMOVEClock;
// Indicates if HMOVE blanks are currently enabled
// Indicates if HMOVE blanks are currently or previously enabled,
// and at which horizontal position the HMOVE was initiated
Int32 myCurrentHMOVEPos;
Int32 myPreviousHMOVEPos;
bool myHMOVEBlankEnabled;
// Indicates if unused TIA pins are floating on a peek
bool myFloatTIAOutputPins;
// TIA M0 "bug" used for stars in Cosmic Ark flag
bool myM0CosmicArkMotionEnabled;
// Counter used for TIA M0 "bug"
uInt32 myM0CosmicArkCounter;
// Bitmap of the objects that should be considered while drawing
uInt8 myEnabledObjects;

View File

@ -550,8 +550,8 @@ uInt8 TIATables::DisabledMask[640];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Int16 TIATables::PokeDelay[64] = {
0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, -1, -1,
0, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};