mirror of https://github.com/stella-emu/stella.git
Scaled back some TIA changes from the previous alpha release. The changes
are too invasive to fix right now, and I haven't researched what the correct route should be. Basically, Stella doesn't properly emulate the behaviour of writes to RESxx and NUSIZx while graphics are currently being drawn. The tweaks currently present restore functionality to the 2.8.4 release, but are still incorrect in some ROMs (Bumper Bash and Pole Position). Reworked 'object disable' mode in the TIA class. It should now be slightly faster, and correctly disable objects in all cases (previously, it was possible for some objects to be enabled depending on the state of other objects, even when they were specifically disabled). Changed NUSIZx descriptors in the debugger to more clearly indicate what's going on. Cleaned up TIATable enum's, and eliminated duplication enumerations in different parts of the codebase. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1855 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
339956b144
commit
3006419014
11
Todo.txt
11
Todo.txt
|
@ -16,8 +16,15 @@ If you would like to contribute to Stella's development then find something
|
|||
on the list below and send email to Bradford Mott at bwmott@acm.org or
|
||||
Stephen Anthony at stephena@users.sourceforge.net.
|
||||
|
||||
* Add new TIA infrastructure with improved HMOVE emulation, including
|
||||
fixes for (possibly) incorrect VSYNC handling in Q-Bert.
|
||||
* TIA infrastructure: further improve 'illegal' HMOVE emulation to fix
|
||||
problems in several homebrew ROMs.
|
||||
|
||||
* TIA infrastructure: improve emulation of writes to NUSIZx while graphics
|
||||
are currently being drawn.
|
||||
|
||||
* TIA infrastructure: fix incorrect VSYNC handling in Q-Bert.
|
||||
|
||||
* TIA infrastructure: add emulation of RSYNC instruction.
|
||||
|
||||
* Look into adding Blargg NTSC filtering (perhaps as a GLSL program).
|
||||
|
||||
|
|
|
@ -26,14 +26,14 @@ TIADebug::TIADebug(Debugger& dbg, Console& console)
|
|||
: DebuggerSystem(dbg, console),
|
||||
myTIA(console.tia())
|
||||
{
|
||||
nusizStrings[0] = "size=8 copy=1";
|
||||
nusizStrings[1] = "size=8 copy=2 spac=8";
|
||||
nusizStrings[2] = "size=8 copy=2 spac=$18";
|
||||
nusizStrings[3] = "size=8 copy=3 spac=8";
|
||||
nusizStrings[4] = "size=8 copy=2 spac=$38";
|
||||
nusizStrings[5] = "size=$10 copy=1";
|
||||
nusizStrings[6] = "size=8 copy=3 spac=$18";
|
||||
nusizStrings[7] = "size=$20 copy=1";
|
||||
nusizStrings[0] = "1 copy";
|
||||
nusizStrings[1] = "2 copies - close (8)";
|
||||
nusizStrings[2] = "2 copies - med (24)";
|
||||
nusizStrings[3] = "3 copies - close (8)";
|
||||
nusizStrings[4] = "2 copies - wide (56)";
|
||||
nusizStrings[5] = "2x (16) sized player";
|
||||
nusizStrings[6] = "3 copies - med (24)";
|
||||
nusizStrings[7] = "4x (32) sized player";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -33,54 +33,6 @@ typedef int (TIADebug::*TIADEBUG_INT_METHOD)();
|
|||
// call the pointed-to method on the (global) debugger object.
|
||||
#define CALL_TIADEBUG_METHOD(method) ( ( Debugger::debugger().tiaDebug().*method)() )
|
||||
|
||||
enum TIALabel {
|
||||
VSYNC = 0,
|
||||
VBLANK,
|
||||
WSYNC,
|
||||
RSYNC,
|
||||
NUSIZ0,
|
||||
NUSIZ1,
|
||||
COLUP0,
|
||||
COLUP1,
|
||||
COLUPF, // $08
|
||||
COLUBK,
|
||||
CTRLPF,
|
||||
REFP0,
|
||||
REFP1,
|
||||
PF0,
|
||||
PF1,
|
||||
PF2,
|
||||
RESP0, // $10
|
||||
RESP1,
|
||||
RESM0,
|
||||
RESM1,
|
||||
RESBL,
|
||||
AUDC0,
|
||||
AUDC1,
|
||||
AUDF0,
|
||||
AUDF1, // $18
|
||||
AUDV0,
|
||||
AUDV1,
|
||||
GRP0,
|
||||
GRP1,
|
||||
ENAM0,
|
||||
ENAM1,
|
||||
ENABL,
|
||||
HMP0, // $20
|
||||
HMP1,
|
||||
HMM0,
|
||||
HMM1,
|
||||
HMBL,
|
||||
VDELP0,
|
||||
VDELP1,
|
||||
VDELBL,
|
||||
RESMP0, // $28
|
||||
RESMP1,
|
||||
HMOVE,
|
||||
HMCLR,
|
||||
CXCLR // $2C
|
||||
};
|
||||
|
||||
// Indices for various IntArray in TiaState
|
||||
enum {
|
||||
P0, P1, M0, M1, BL
|
||||
|
|
|
@ -694,7 +694,7 @@ void Console::setControllers(const string& rommd5)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::toggleTIABit(TIA::TIABit bit, const string& bitname, bool show) const
|
||||
void Console::toggleTIABit(TIABit bit, const string& bitname, bool show) const
|
||||
{
|
||||
bool result = myTIA->toggleBit(bit);
|
||||
string message = bitname + (result ? " enabled" : " disabled");
|
||||
|
|
|
@ -256,12 +256,12 @@ class Console : public Serializable
|
|||
/**
|
||||
Toggles the TIA bit specified in the method name.
|
||||
*/
|
||||
void toggleP0Bit() const { toggleTIABit(TIA::P0, "P0"); }
|
||||
void toggleP1Bit() const { toggleTIABit(TIA::P1, "P1"); }
|
||||
void toggleM0Bit() const { toggleTIABit(TIA::M0, "M0"); }
|
||||
void toggleM1Bit() const { toggleTIABit(TIA::M1, "M1"); }
|
||||
void toggleBLBit() const { toggleTIABit(TIA::BL, "BL"); }
|
||||
void togglePFBit() const { toggleTIABit(TIA::PF, "PF"); }
|
||||
void toggleP0Bit() const { toggleTIABit(P0Bit, "P0"); }
|
||||
void toggleP1Bit() const { toggleTIABit(P1Bit, "P1"); }
|
||||
void toggleM0Bit() const { toggleTIABit(M0Bit, "M0"); }
|
||||
void toggleM1Bit() const { toggleTIABit(M1Bit, "M1"); }
|
||||
void toggleBLBit() const { toggleTIABit(BLBit, "BL"); }
|
||||
void togglePFBit() const { toggleTIABit(PFBit, "PF"); }
|
||||
void enableBits(bool enable) const;
|
||||
|
||||
private:
|
||||
|
@ -270,7 +270,7 @@ class Console : public Serializable
|
|||
*/
|
||||
void setControllers(const string& rommd5);
|
||||
|
||||
void toggleTIABit(TIA::TIABit bit, const string& bitname, bool show = true) const;
|
||||
void toggleTIABit(TIABit bit, const string& bitname, bool show = true) const;
|
||||
|
||||
/**
|
||||
Loads a user-defined palette file (from OSystem::paletteFile), filling the
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
regenerated and the application recompiled.
|
||||
*/
|
||||
|
||||
#define DEF_PROPS_SIZE 3245
|
||||
#define DEF_PROPS_SIZE 3246
|
||||
|
||||
static const char* DefProps[DEF_PROPS_SIZE][20] = {
|
||||
{ "000509d1ed2b8d30a9d94be1b3b5febb", "Greg Zumwalt", "", "Jungle Jane (2003) (Greg Zumwalt) (Hack)", "Hack of Pitfall!", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
|
@ -925,6 +925,7 @@ static const char* DefProps[DEF_PROPS_SIZE][20] = {
|
|||
{ "45a095645696a217e416e4bd2baea723", "Digivision", "", "Snoopy (Digivision)", "AKA Snoopy and the Red Baron", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "45a4f55bb9a5083d470ad479afd8bca2", "CommaVid, Joseph Biel", "", "Frog Demo (1983) (CommaVid)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "45beef9da1a7e45f37f3f445f769a0b3", "Atari, Suki Lee", "CX2658", "Math Gran Prix (1982) (Atari) (PAL)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "45c4413dd703b9cfea49a13709d560eb", "Jone Yuan Telephonic Enterprise Co", "", "Challenge of.... Nexar, The (Jone Yuan) (Hack)", "Hack", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "45cb0f41774b78def53331e4c3bf3362", "Carrere Video, Roger Booth, Sylvia Day, Todd Marshall, Wes Trager, Henry Will - Teldec", "USC1007", "Octopus (1983) (Carrere Video) (PAL)", "AKA Name This Game", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "4605a00f5b44a9cbd5803a7a55de150e", "Coleco, Ed Temple", "", "Cabbage Patch Kids (07-03-1984) (Coleco) (Prototype)", "Adventures in the Park", "Prototype", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
{ "461029ab23800833e9645be3e472d470", "", "", "Combat TC (v0.1)", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },
|
||||
|
|
|
@ -35,8 +35,6 @@
|
|||
|
||||
#define HBLANK 68
|
||||
#define USE_MMR_LATCHES
|
||||
static int P0suppress = 0;
|
||||
static int P1suppress = 0;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
TIA::TIA(Console& console, Sound& sound, Settings& settings)
|
||||
|
@ -118,8 +116,9 @@ void TIA::reset()
|
|||
// Reset the sound device
|
||||
mySound.reset();
|
||||
|
||||
// Currently no objects are enabled
|
||||
// Currently no objects are enabled or selectively disabled
|
||||
myEnabledObjects = 0;
|
||||
myDisabledObjects = 0;
|
||||
|
||||
// Some default values for the registers
|
||||
myVSYNC = myVBLANK = 0;
|
||||
|
@ -155,6 +154,8 @@ void TIA::reset()
|
|||
myMotionClockM1 = 0;
|
||||
myMotionClockBL = 0;
|
||||
|
||||
mySuppressP0 = mySuppressP1 = 0;
|
||||
|
||||
myHMP0mmr = myHMP1mmr = myHMM0mmr = myHMM1mmr = myHMBLmmr = false;
|
||||
|
||||
myCurrentHMOVEPos = myPreviousHMOVEPos = 0x7FFFFFFF;
|
||||
|
@ -302,6 +303,7 @@ bool TIA::save(Serializer& out) const
|
|||
out.putInt(myVSYNCFinishClock);
|
||||
|
||||
out.putByte((char)myEnabledObjects);
|
||||
out.putByte((char)myDisabledObjects);
|
||||
|
||||
out.putByte((char)myVSYNC);
|
||||
out.putByte((char)myVBLANK);
|
||||
|
@ -340,14 +342,6 @@ bool TIA::save(Serializer& out) const
|
|||
out.putByte((char)myCurrentGRP0);
|
||||
out.putByte((char)myCurrentGRP1);
|
||||
|
||||
// pointers
|
||||
// myCurrentBLMask = TIATables::BLMask[0][0];
|
||||
// myCurrentM0Mask = TIATables::MxMask[0][0][0];
|
||||
// myCurrentM1Mask = TIATables::MxMask[0][0][0];
|
||||
// myCurrentP0Mask = TIATables::PxMask[0][0][0];
|
||||
// myCurrentP1Mask = TIATables::PxMask[0][0][0];
|
||||
// myCurrentPFMask = TIATables::PFMask[0];
|
||||
|
||||
out.putBool(myDumpEnabled);
|
||||
out.putInt(myDumpDisabledCycle);
|
||||
|
||||
|
@ -363,6 +357,14 @@ bool TIA::save(Serializer& out) const
|
|||
out.putInt(myMotionClockM1);
|
||||
out.putInt(myMotionClockBL);
|
||||
|
||||
out.putInt(myStartP0);
|
||||
out.putInt(myStartP1);
|
||||
out.putInt(myStartM0);
|
||||
out.putInt(myStartM1);
|
||||
|
||||
out.putByte(mySuppressP0);
|
||||
out.putByte(mySuppressP1);
|
||||
|
||||
out.putBool(myHMP0mmr);
|
||||
out.putBool(myHMP1mmr);
|
||||
out.putBool(myHMM0mmr);
|
||||
|
@ -411,6 +413,7 @@ bool TIA::load(Serializer& in)
|
|||
myVSYNCFinishClock = (Int32) in.getInt();
|
||||
|
||||
myEnabledObjects = (uInt8) in.getByte();
|
||||
myDisabledObjects = (uInt8) in.getByte();
|
||||
|
||||
myVSYNC = (uInt8) in.getByte();
|
||||
myVBLANK = (uInt8) in.getByte();
|
||||
|
@ -449,14 +452,6 @@ bool TIA::load(Serializer& in)
|
|||
myCurrentGRP0 = (uInt8) in.getByte();
|
||||
myCurrentGRP1 = (uInt8) in.getByte();
|
||||
|
||||
// pointers
|
||||
// myCurrentBLMask = TIATables::BLMask[0][0];
|
||||
// myCurrentM0Mask = TIATables::MxMask[0][0][0];
|
||||
// myCurrentM1Mask = TIATables::MxMask[0][0][0];
|
||||
// myCurrentP0Mask = TIATables::PxMask[0][0][0];
|
||||
// myCurrentP1Mask = TIATables::PxMask[0][0][0];
|
||||
// myCurrentPFMask = TIATables::PFMask[0];
|
||||
|
||||
myDumpEnabled = in.getBool();
|
||||
myDumpDisabledCycle = (Int32) in.getInt();
|
||||
|
||||
|
@ -472,6 +467,14 @@ bool TIA::load(Serializer& in)
|
|||
myMotionClockM1 = (Int32) in.getInt();
|
||||
myMotionClockBL = (Int32) in.getInt();
|
||||
|
||||
myStartP0 = (Int32) in.getInt();
|
||||
myStartP1 = (Int32) in.getInt();
|
||||
myStartM0 = (Int32) in.getInt();
|
||||
myStartM1 = (Int32) in.getInt();
|
||||
|
||||
mySuppressP0 = (uInt8) in.getByte();
|
||||
mySuppressP1 = (uInt8) in.getByte();
|
||||
|
||||
myHMP0mmr = in.getBool();
|
||||
myHMP1mmr = in.getBool();
|
||||
myHMM0mmr = in.getBool();
|
||||
|
@ -488,7 +491,8 @@ bool TIA::load(Serializer& in)
|
|||
mySound.load(in);
|
||||
|
||||
// Reset TIA bits to be on
|
||||
enableBits(true);
|
||||
// TODO - should we enable this, or leave it to the user?
|
||||
// enableBits(true);
|
||||
}
|
||||
catch(char *msg)
|
||||
{
|
||||
|
@ -672,6 +676,29 @@ inline void TIA::endFrame()
|
|||
myFrameGreyed = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool TIA::enableBit(TIABit b, bool mode, bool flip)
|
||||
{
|
||||
// If flip is enabled, we ignore mode and calculate our own
|
||||
if(flip) mode = !(myDisabledObjects & b);
|
||||
|
||||
if(mode) myDisabledObjects |= b;
|
||||
else myDisabledObjects &= ~b;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::enableBits(bool mode)
|
||||
{
|
||||
enableBit(P0Bit, mode);
|
||||
enableBit(P1Bit, mode);
|
||||
enableBit(M0Bit, mode);
|
||||
enableBit(M1Bit, mode);
|
||||
enableBit(BLBit, mode);
|
||||
enableBit(PFBit, mode);
|
||||
}
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::updateScanline()
|
||||
|
@ -771,9 +798,9 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos)
|
|||
myCurrentBLMask = &TIATables::BLMask[myPOSBL & 0x03]
|
||||
[(myCTRLPF & 0x30) >> 4][160 - (myPOSBL & 0xFC)];
|
||||
myCurrentP0Mask = &TIATables::PxMask[myPOSP0 & 0x03]
|
||||
[P0suppress][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)];
|
||||
[mySuppressP0][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)];
|
||||
myCurrentP1Mask = &TIATables::PxMask[myPOSP1 & 0x03]
|
||||
[P1suppress][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)];
|
||||
[mySuppressP1][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)];
|
||||
myCurrentM0Mask = &TIATables::MxMask[myPOSM0 & 0x03]
|
||||
[myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)];
|
||||
myCurrentM1Mask = &TIATables::MxMask[myPOSM1 & 0x03]
|
||||
|
@ -1322,18 +1349,19 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos)
|
|||
{
|
||||
for(; myFramePointer < ending; ++myFramePointer, ++hpos)
|
||||
{
|
||||
uInt8 enabled = (myPF & myCurrentPFMask[hpos]) ? PFBit : 0;
|
||||
uInt8 enabled = ((myEnabledObjects & PFBit) &&
|
||||
(myPF & myCurrentPFMask[hpos])) ? PFBit : 0;
|
||||
|
||||
if((myEnabledObjects & BLBit) && myCurrentBLMask[hpos])
|
||||
enabled |= BLBit;
|
||||
|
||||
if(myCurrentGRP1 & myCurrentP1Mask[hpos])
|
||||
if((myEnabledObjects & P1Bit) && (myCurrentGRP1 & myCurrentP1Mask[hpos]))
|
||||
enabled |= P1Bit;
|
||||
|
||||
if((myEnabledObjects & M1Bit) && myCurrentM1Mask[hpos])
|
||||
enabled |= M1Bit;
|
||||
|
||||
if(myCurrentGRP0 & myCurrentP0Mask[hpos])
|
||||
if((myEnabledObjects & P0Bit) && (myCurrentGRP0 & myCurrentP0Mask[hpos]))
|
||||
enabled |= P0Bit;
|
||||
|
||||
if((myEnabledObjects & M0Bit) && myCurrentM0Mask[hpos])
|
||||
|
@ -1363,6 +1391,8 @@ void TIA::updateFrame(Int32 clock)
|
|||
if(clock > myClockStopDisplay)
|
||||
clock = myClockStopDisplay;
|
||||
|
||||
//cerr << "updateFrame: " << clock << endl;
|
||||
|
||||
// Determine how many scanlines to process
|
||||
// It's easier to think about this in scanlines rather than color clocks
|
||||
uInt32 startLine = (myClockAtLastUpdate - myClockWhenFrameStarted) / 228;
|
||||
|
@ -1458,8 +1488,16 @@ void TIA::updateFrame(Int32 clock)
|
|||
|
||||
// Update as much of the scanline as we can
|
||||
if(clocksToUpdate != 0)
|
||||
{
|
||||
// Selectively disable all bits we don't wish to draw
|
||||
uInt8 oldEnabled = myEnabledObjects;
|
||||
myEnabledObjects &= myDisabledObjects;
|
||||
|
||||
updateFrameScanline(clocksToUpdate, clocksFromStartOfScanLine - HBLANK);
|
||||
|
||||
myEnabledObjects = oldEnabled;
|
||||
}
|
||||
|
||||
// Handle HMOVE blanks if they are enabled
|
||||
if(myHMOVEBlankEnabled && (startOfScanLine < HBLANK + 8) &&
|
||||
(clocksFromStartOfScanLine < (HBLANK + 8)))
|
||||
|
@ -1480,8 +1518,7 @@ void TIA::updateFrame(Int32 clock)
|
|||
// 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).
|
||||
P0suppress = 0;
|
||||
P1suppress = 0;
|
||||
mySuppressP0 = mySuppressP1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1499,7 +1536,6 @@ inline void TIA::waitHorizontalSync()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::greyOutFrame()
|
||||
{
|
||||
cerr << "greyOutFrame(): scanlines = " << scanlines() << endl;
|
||||
uInt32 c = scanlines();
|
||||
if(c < myFrameYStart) c = myFrameYStart;
|
||||
if(c > (myFrameHeight + myFrameYStart))
|
||||
|
@ -1729,17 +1765,19 @@ void TIA::poke(uInt16 addr, uInt8 value)
|
|||
|
||||
case NUSIZ0: // Number-size of player-missle 0
|
||||
{
|
||||
//cerr << "NUSIZ0 set: " << (int)myNUSIZ0 << " => " << (int)value << " @ " << (clock + delay) << ", p0 pos = " << myPOSP0 << endl;
|
||||
// TODO - 08-11-2009: determine correct delay instead of always
|
||||
// using '8'.
|
||||
myNUSIZ0 = value;
|
||||
P0suppress = 0;
|
||||
mySuppressP0 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case NUSIZ1: // Number-size of player-missle 1
|
||||
{
|
||||
//cerr << "NUSIZ1 set: " << (int)myNUSIZ1 << " => " << (int)value << " @ " << (clock + delay) << endl;
|
||||
// TODO - 08-11-2009: determine correct delay instead of always
|
||||
// using '8'.
|
||||
myNUSIZ1 = value;
|
||||
P1suppress = 0;
|
||||
mySuppressP1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1833,7 +1871,7 @@ P1suppress = 0;
|
|||
{
|
||||
myPF = (myPF & 0x000FFFF0) | ((value >> 4) & 0x0F);
|
||||
|
||||
if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0)
|
||||
if(myPF == 0)
|
||||
myEnabledObjects &= ~PFBit;
|
||||
else
|
||||
myEnabledObjects |= PFBit;
|
||||
|
@ -1845,7 +1883,7 @@ P1suppress = 0;
|
|||
{
|
||||
myPF = (myPF & 0x000FF00F) | ((uInt32)value << 4);
|
||||
|
||||
if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0)
|
||||
if(myPF == 0)
|
||||
myEnabledObjects &= ~PFBit;
|
||||
else
|
||||
myEnabledObjects |= PFBit;
|
||||
|
@ -1857,7 +1895,7 @@ P1suppress = 0;
|
|||
{
|
||||
myPF = (myPF & 0x00000FFF) | ((uInt32)value << 12);
|
||||
|
||||
if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0)
|
||||
if(myPF == 0)
|
||||
myEnabledObjects &= ~PFBit;
|
||||
else
|
||||
myEnabledObjects |= PFBit;
|
||||
|
@ -1882,38 +1920,33 @@ P1suppress = 0;
|
|||
newx = hpos < -2 ? 3 : ((hpos + 5) % 160);
|
||||
applyPreviousHMOVEMotion(hpos, newx, myHMP0);
|
||||
}
|
||||
if(newx != myPOSP0)
|
||||
if(myPOSP0 != newx)
|
||||
{
|
||||
// myPOSP0 = newx;
|
||||
// myStartP0 = 0;
|
||||
}
|
||||
// Find out under what condition the player is being reset
|
||||
delay = TIATables::PxPosResetWhen[myNUSIZ0 & 7][myPOSP0][newx];
|
||||
|
||||
// Find out under what condition the player is being reset
|
||||
Int8 when = TIATables::PxPosResetWhen[myNUSIZ0 & 7][myPOSP0][newx];
|
||||
switch(delay)
|
||||
{
|
||||
// Player is being reset during the display of one of its copies
|
||||
case 1:
|
||||
// TODO - 08-20-2009: determine whether we really need to update
|
||||
// the frame here, and also come up with a way to eliminate the
|
||||
// 200KB PxPosResetWhen table.
|
||||
updateFrame(clock + 11);
|
||||
mySuppressP0 = 1;
|
||||
break;
|
||||
|
||||
// Player is being reset during the display of one of its copies
|
||||
if(when == 1)
|
||||
{
|
||||
// So we go ahead and update the display before moving the player
|
||||
// TODO: The 11 should depend on how much of the player has already
|
||||
// been displayed. Probably change table to return the amount to
|
||||
// delay by instead of just 1 (01/21/99).
|
||||
// updateFrame(clock + 11);
|
||||
// Player is being reset in neither the delay nor display section
|
||||
case 0:
|
||||
mySuppressP0 = 1;
|
||||
break;
|
||||
|
||||
// Player is being reset during the delay section of one of its copies
|
||||
case -1:
|
||||
mySuppressP0 = 0;
|
||||
break;
|
||||
}
|
||||
myPOSP0 = newx;
|
||||
P0suppress = 1;
|
||||
}
|
||||
// Player is being reset in neither the delay nor display section
|
||||
else if(when == 0)
|
||||
{
|
||||
myPOSP0 = newx;
|
||||
P0suppress = 1;
|
||||
}
|
||||
// Player is being reset during the delay section of one of its copies
|
||||
else if(when == -1)
|
||||
{
|
||||
myPOSP0 = newx;
|
||||
P0suppress = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1935,38 +1968,33 @@ P0suppress = 0;
|
|||
newx = hpos < -2 ? 3 : ((hpos + 5) % 160);
|
||||
applyPreviousHMOVEMotion(hpos, newx, myHMP1);
|
||||
}
|
||||
if(newx != myPOSP1)
|
||||
if(myPOSP1 != newx)
|
||||
{
|
||||
// myPOSP1 = newx;
|
||||
// myStartP1 = 0;
|
||||
}
|
||||
// Find out under what condition the player is being reset
|
||||
delay = TIATables::PxPosResetWhen[myNUSIZ1 & 7][myPOSP1][newx];
|
||||
|
||||
// Find out under what condition the player is being reset
|
||||
Int8 when = TIATables::PxPosResetWhen[myNUSIZ1 & 7][myPOSP1][newx];
|
||||
switch(delay)
|
||||
{
|
||||
// Player is being reset during the display of one of its copies
|
||||
case 1:
|
||||
// TODO - 08-20-2009: determine whether we really need to update
|
||||
// the frame here, and also come up with a way to eliminate the
|
||||
// 200KB PxPosResetWhen table.
|
||||
updateFrame(clock + 11);
|
||||
mySuppressP1 = 1;
|
||||
break;
|
||||
|
||||
// Player is being reset during the display of one of its copies
|
||||
if(when == 1)
|
||||
{
|
||||
// So we go ahead and update the display before moving the player
|
||||
// TODO: The 11 should depend on how much of the player has already
|
||||
// been displayed. Probably change table to return the amount to
|
||||
// delay by instead of just 1 (01/21/99).
|
||||
// updateFrame(clock + 11);
|
||||
// Player is being reset in neither the delay nor display section
|
||||
case 0:
|
||||
mySuppressP1 = 1;
|
||||
break;
|
||||
|
||||
// Player is being reset during the delay section of one of its copies
|
||||
case -1:
|
||||
mySuppressP1 = 0;
|
||||
break;
|
||||
}
|
||||
myPOSP1 = newx;
|
||||
P1suppress = 1;
|
||||
}
|
||||
// Player is being reset in neither the delay nor display section
|
||||
else if(when == 0)
|
||||
{
|
||||
myPOSP1 = newx;
|
||||
P1suppress = 1;
|
||||
}
|
||||
// Player is being reset during the delay section of one of its copies
|
||||
else if(when == -1)
|
||||
{
|
||||
myPOSP1 = newx;
|
||||
P1suppress = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1990,7 +2018,6 @@ P1suppress = 0;
|
|||
}
|
||||
if(newx != myPOSM0)
|
||||
{
|
||||
// myStartM0 = skipM0delay ? 1 : 0;
|
||||
myPOSM0 = newx;
|
||||
}
|
||||
break;
|
||||
|
@ -2015,7 +2042,6 @@ P1suppress = 0;
|
|||
}
|
||||
if(newx != myPOSM1)
|
||||
{
|
||||
// myStartM1 = skipM1delay ? 1 : 0;
|
||||
myPOSM1 = newx;
|
||||
}
|
||||
break;
|
||||
|
@ -2085,7 +2111,7 @@ P1suppress = 0;
|
|||
case GRP0: // Graphics Player 0
|
||||
{
|
||||
// Set player 0 graphics
|
||||
myGRP0 = value & myBitEnabled[TIA::P0];
|
||||
myGRP0 = value;
|
||||
|
||||
// Copy player 1 graphics into its delayed register
|
||||
myDGRP1 = myGRP1;
|
||||
|
@ -2115,7 +2141,7 @@ P1suppress = 0;
|
|||
case GRP1: // Graphics Player 1
|
||||
{
|
||||
// Set player 1 graphics
|
||||
myGRP1 = value & myBitEnabled[TIA::P1];
|
||||
myGRP1 = value;
|
||||
|
||||
// Copy player 0 graphics into its delayed register
|
||||
myDGRP0 = myGRP0;
|
||||
|
@ -2152,7 +2178,7 @@ P1suppress = 0;
|
|||
|
||||
case ENAM0: // Enable Missile 0 graphics
|
||||
{
|
||||
myENAM0 = (value & 0x02) & myBitEnabled[TIA::M0];
|
||||
myENAM0 = value & 0x02;
|
||||
|
||||
if(myENAM0 && !myRESMP0)
|
||||
myEnabledObjects |= M0Bit;
|
||||
|
@ -2163,7 +2189,7 @@ P1suppress = 0;
|
|||
|
||||
case ENAM1: // Enable Missile 1 graphics
|
||||
{
|
||||
myENAM1 = (value & 0x02) & myBitEnabled[TIA::M1];
|
||||
myENAM1 = value & 0x02;
|
||||
|
||||
if(myENAM1 && !myRESMP1)
|
||||
myEnabledObjects |= M1Bit;
|
||||
|
@ -2174,7 +2200,7 @@ P1suppress = 0;
|
|||
|
||||
case ENABL: // Enable Ball graphics
|
||||
{
|
||||
myENABL = (value & 0x02) & myBitEnabled[TIA::BL];
|
||||
myENABL = value & 0x02;
|
||||
|
||||
if(myVDELBL ? myDENABL : myENABL)
|
||||
myEnabledObjects |= BLBit;
|
||||
|
@ -2397,8 +2423,7 @@ P1suppress = 0;
|
|||
if(myPOSM1 < 0) { myPOSM1 += 160; } myPOSM1 %= 160;
|
||||
if(myPOSBL < 0) { myPOSBL += 160; } myPOSBL %= 160;
|
||||
|
||||
P0suppress = 0;
|
||||
P1suppress = 0;
|
||||
mySuppressP0 = mySuppressP1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ class Settings;
|
|||
#include "Sound.hxx"
|
||||
#include "Device.hxx"
|
||||
#include "System.hxx"
|
||||
#include "TIATables.hxx"
|
||||
|
||||
/**
|
||||
This class is a device that emulates the Television Interface Adapator
|
||||
|
@ -212,37 +213,28 @@ class TIA : public Device
|
|||
inline uInt32 scanlines() const
|
||||
{ return ((mySystem->cycles() * 3) - myClockWhenFrameStarted) / 228; }
|
||||
|
||||
enum TIABit {
|
||||
P0, // Descriptor for Player 0 Bit
|
||||
P1, // Descriptor for Player 1 Bit
|
||||
M0, // Descriptor for Missle 0 Bit
|
||||
M1, // Descriptor for Missle 1 Bit
|
||||
BL, // Descriptor for Ball Bit
|
||||
PF // Descriptor for Playfield Bit
|
||||
};
|
||||
|
||||
/**
|
||||
Enables/disables the specified TIA bit.
|
||||
Enables/disables the specified TIA bit. If flip is true, ignore the
|
||||
given mode and instead toggle/flip the specified TIA bit.
|
||||
|
||||
@return Whether the bit was enabled or disabled
|
||||
*/
|
||||
void enableBit(TIABit b, bool mode) { myBitEnabled[b] = mode ? 0xff : 0x00; }
|
||||
bool enableBit(TIABit b, bool mode, bool flip = false);
|
||||
|
||||
/**
|
||||
Toggles the specified TIA bit.
|
||||
Toggles the specified TIA bit. This is a convenience wrapper
|
||||
around enableBit when flipping a bit.
|
||||
|
||||
@return Whether the bit was enabled or disabled
|
||||
*/
|
||||
bool toggleBit(TIABit b)
|
||||
{ myBitEnabled[b] = myBitEnabled[b] == 0xff ? 0x00 : 0xff; return myBitEnabled[b]; }
|
||||
bool toggleBit(TIABit b) { return enableBit(b, true, true); }
|
||||
|
||||
/**
|
||||
Enables/disables all TIABit bits.
|
||||
|
||||
@param mode Whether to enable or disable all bits
|
||||
*/
|
||||
void enableBits(bool mode)
|
||||
{ for(uInt8 i = 0; i < 6; ++i) myBitEnabled[i] = mode ? 0xff : 0x00; }
|
||||
void enableBits(bool mode);
|
||||
|
||||
#ifdef DEBUGGER_SUPPORT
|
||||
/**
|
||||
|
@ -442,6 +434,11 @@ class TIA : public Device
|
|||
Int32 myStartM0;
|
||||
Int32 myStartM1;
|
||||
|
||||
// Index into the player mask arrays indicating whether display
|
||||
// of the first copy should be suppressed
|
||||
uInt8 mySuppressP0;
|
||||
uInt8 mySuppressP1;
|
||||
|
||||
// Latches for 'more motion required' as described in A. Towers TIA
|
||||
// Hardware Notes
|
||||
bool myHMP0mmr;
|
||||
|
@ -502,9 +499,9 @@ class TIA : public Device
|
|||
uInt8 myEnabledObjects;
|
||||
|
||||
// Determines whether specified bits (from TIABit) are enabled or disabled
|
||||
// Each value is and'ed with the appropriate register, so the valid values
|
||||
// are 0x00 or 0xff;
|
||||
uInt8 myBitEnabled[6];
|
||||
// This is and'ed with the enabled objects each scanline to mask out any
|
||||
// objects we don't want to be processed
|
||||
uInt8 myDisabledObjects;
|
||||
|
||||
// Indicates if color loss should be enabled or disabled. Color loss
|
||||
// occurs on PAL (and maybe SECAM) systems when the previous frame
|
||||
|
|
|
@ -434,7 +434,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
if((newx >= oldx) && (newx < (oldx + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
break;
|
||||
|
||||
|
@ -444,7 +444,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
|
@ -456,7 +456,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
|
@ -470,7 +470,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
|
@ -484,7 +484,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
|
@ -494,7 +494,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
if((newx >= oldx) && (newx < (oldx + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 16)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 16)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
break;
|
||||
|
||||
|
@ -506,7 +506,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
|
@ -518,7 +518,7 @@ void TIATables::buildPxPosResetWhenTable()
|
|||
if((newx >= oldx) && (newx < (oldx + 4)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
|
||||
|
||||
if((newx >= oldx + 4) && (newx < (oldx + 4 + 32)))
|
||||
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 32)))
|
||||
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -549,8 +549,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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
|
||||
0, 1, 0, 0, 8, 8, 0, 0, 0, 0, 0, 1, 1, -1, -1, -1,
|
||||
0, 0, 8, 8, 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,
|
||||
};
|
||||
|
@ -570,6 +570,7 @@ const bool TIATables::HMOVEBlankEnableCycles[76] = {
|
|||
false, false, false, false, false, true // 70
|
||||
};
|
||||
|
||||
#if 0
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const Int32 TIATables::CompleteMotion[76][16] = {
|
||||
{ 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK
|
||||
|
@ -649,6 +650,7 @@ const Int32 TIATables::CompleteMotion[76][16] = {
|
|||
{-8, -9,-10,-11,-12,-13,-14,-15, 0, -1, -2, -3, -4, -5, -6, -7},
|
||||
{ 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1} // HBLANK
|
||||
};
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt8 TIATables::PxMask[4][2][8][320];
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "bspf.hxx"
|
||||
|
||||
enum {
|
||||
enum TIABit {
|
||||
P0Bit = 0x01, // Bit for Player 0
|
||||
M0Bit = 0x02, // Bit for Missle 0
|
||||
P1Bit = 0x04, // Bit for Player 1
|
||||
|
@ -32,7 +32,7 @@ enum {
|
|||
PriorityBit = 0x80 // Bit for Playfield priority
|
||||
};
|
||||
|
||||
enum
|
||||
enum CollisionBit
|
||||
{
|
||||
Cx_M0P1 = 1 << 0, // Missle0 - Player1 collision
|
||||
Cx_M0P0 = 1 << 1, // Missle0 - Player0 collision
|
||||
|
@ -52,7 +52,7 @@ enum
|
|||
};
|
||||
|
||||
// TIA Write/Read register names
|
||||
enum {
|
||||
enum TIARegister {
|
||||
VSYNC = 0x00, // Write: vertical sync set-clear (D1)
|
||||
VBLANK = 0x01, // Write: vertical blank set-clear (D7-6,D1)
|
||||
WSYNC = 0x02, // Write: wait for leading edge of hrz. blank (strobe)
|
||||
|
@ -140,9 +140,11 @@ class TIATables
|
|||
// Indicates the update delay associated with poking at a TIA address
|
||||
static const Int16 PokeDelay[64];
|
||||
|
||||
#if 0
|
||||
// Used to convert value written in a motion register into
|
||||
// its internal representation
|
||||
static const Int32 CompleteMotion[76][16];
|
||||
#endif
|
||||
|
||||
// Indicates if HMOVE blanks should occur for the corresponding cycle
|
||||
static const bool HMOVEBlankEnableCycles[76];
|
||||
|
|
|
@ -19637,3 +19637,9 @@
|
|||
"Cartridge.Rarity" "Hack"
|
||||
"Controller.Left" "PADDLES"
|
||||
""
|
||||
|
||||
"Cartridge.MD5" "45c4413dd703b9cfea49a13709d560eb"
|
||||
"Cartridge.Manufacturer" "Jone Yuan Telephonic Enterprise Co"
|
||||
"Cartridge.Name" "Challenge of.... Nexar, The (Jone Yuan) (Hack)"
|
||||
"Cartridge.Note" "Hack"
|
||||
""
|
||||
|
|
Loading…
Reference in New Issue