diff --git a/stella/src/common/FrameBufferGL.cxx b/stella/src/common/FrameBufferGL.cxx index 8f9a6edad..ef6b921d6 100644 --- a/stella/src/common/FrameBufferGL.cxx +++ b/stella/src/common/FrameBufferGL.cxx @@ -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: FrameBufferGL.cxx,v 1.133 2009-01-10 18:42:49 stephena Exp $ +// $Id: FrameBufferGL.cxx,v 1.134 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifdef DISPLAY_OPENGL @@ -26,10 +26,10 @@ #include "Console.hxx" #include "Font.hxx" -#include "MediaSrc.hxx" #include "OSystem.hxx" #include "Settings.hxx" #include "Surface.hxx" +#include "TIA.hxx" #include "FrameBufferGL.hxx" @@ -354,15 +354,15 @@ cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferGL::drawMediaSource(bool fullRedraw) +void FrameBufferGL::drawTIA(bool fullRedraw) { - MediaSource& mediasrc = myOSystem->console().mediaSource(); + const TIA& tia = myOSystem->console().tia(); // Copy the mediasource framebuffer to the RGB texture - uInt8* currentFrame = mediasrc.currentFrameBuffer(); - uInt8* previousFrame = mediasrc.previousFrameBuffer(); - uInt32 width = mediasrc.width(); - uInt32 height = mediasrc.height(); + uInt8* currentFrame = tia.currentFrameBuffer(); + uInt8* previousFrame = tia.previousFrameBuffer(); + uInt32 width = tia.width(); + uInt32 height = tia.height(); uInt32 pitch = myTiaSurface->pitch(); uInt16* buffer = (uInt16*) myTiaSurface->pixels(); diff --git a/stella/src/common/FrameBufferGL.hxx b/stella/src/common/FrameBufferGL.hxx index c97e894d2..9714384f7 100644 --- a/stella/src/common/FrameBufferGL.hxx +++ b/stella/src/common/FrameBufferGL.hxx @@ -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: FrameBufferGL.hxx,v 1.71 2009-01-15 23:07:29 stephena Exp $ +// $Id: FrameBufferGL.hxx,v 1.72 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_GL_HXX @@ -35,7 +35,7 @@ class FBSurfaceGL; This class implements an SDL OpenGL framebuffer. @author Stephen Anthony - @version $Id: FrameBufferGL.hxx,v 1.71 2009-01-15 23:07:29 stephena Exp $ + @version $Id: FrameBufferGL.hxx,v 1.72 2009-01-19 16:52:32 stephena Exp $ */ class FrameBufferGL : public FrameBuffer { @@ -138,10 +138,10 @@ class FrameBufferGL : public FrameBuffer FBSurface* createSurface(int w, int h, bool useBase = false) const; /** - This method should be called anytime the MediaSource needs to be redrawn + This method should be called anytime the TIA needs to be redrawn to the screen (full indicating that a full redraw is required). */ - void drawMediaSource(bool full); + void drawTIA(bool full); /** This method is called to provide information about the FrameBuffer. @@ -187,7 +187,7 @@ class FrameBufferGL : public FrameBuffer A surface suitable for OpenGL rendering mode. @author Stephen Anthony - @version $Id: FrameBufferGL.hxx,v 1.71 2009-01-15 23:07:29 stephena Exp $ + @version $Id: FrameBufferGL.hxx,v 1.72 2009-01-19 16:52:32 stephena Exp $ */ class FBSurfaceGL : public FBSurface { diff --git a/stella/src/common/FrameBufferSoft.cxx b/stella/src/common/FrameBufferSoft.cxx index 6c8bcea8a..49c37a437 100644 --- a/stella/src/common/FrameBufferSoft.cxx +++ b/stella/src/common/FrameBufferSoft.cxx @@ -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: FrameBufferSoft.cxx,v 1.93 2009-01-14 20:31:07 stephena Exp $ +// $Id: FrameBufferSoft.cxx,v 1.94 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include @@ -23,11 +23,11 @@ #include "Console.hxx" #include "Font.hxx" -#include "MediaSrc.hxx" #include "OSystem.hxx" #include "RectList.hxx" #include "Settings.hxx" #include "Surface.hxx" +#include "TIA.hxx" #include "FrameBufferSoft.hxx" @@ -102,7 +102,7 @@ bool FrameBufferSoft::setVidMode(VideoMode& mode) myFormat = myScreen->format; myBytesPerPixel = myFormat->BytesPerPixel; - // Make sure drawMediaSource() knows which renderer to use + // Make sure drawTIA() knows which renderer to use switch(myBytesPerPixel) { case 2: // 16-bit @@ -136,15 +136,15 @@ bool FrameBufferSoft::setVidMode(VideoMode& mode) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSoft::drawMediaSource(bool fullRedraw) +void FrameBufferSoft::drawTIA(bool fullRedraw) { - MediaSource& mediasrc = myOSystem->console().mediaSource(); + const TIA& tia = myOSystem->console().tia(); - uInt8* currentFrame = mediasrc.currentFrameBuffer(); - uInt8* previousFrame = mediasrc.previousFrameBuffer(); + uInt8* currentFrame = tia.currentFrameBuffer(); + uInt8* previousFrame = tia.previousFrameBuffer(); - uInt32 width = mediasrc.width(); - uInt32 height = mediasrc.height(); + uInt32 width = tia.width(); + uInt32 height = tia.height(); switch(myRenderType) { diff --git a/stella/src/common/FrameBufferSoft.hxx b/stella/src/common/FrameBufferSoft.hxx index bbff05b1a..da423af00 100644 --- a/stella/src/common/FrameBufferSoft.hxx +++ b/stella/src/common/FrameBufferSoft.hxx @@ -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: FrameBufferSoft.hxx,v 1.64 2009-01-10 18:52:55 stephena Exp $ +// $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_SOFT_HXX @@ -32,7 +32,7 @@ class RectList; This class implements an SDL software framebuffer. @author Stephen Anthony - @version $Id: FrameBufferSoft.hxx,v 1.64 2009-01-10 18:52:55 stephena Exp $ + @version $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ */ class FrameBufferSoft : public FrameBuffer { @@ -126,10 +126,10 @@ class FrameBufferSoft : public FrameBuffer FBSurface* createSurface(int w, int h, bool useBase = false) const; /** - This method should be called anytime the MediaSource needs to be redrawn + This method should be called anytime the TIA needs to be redrawn to the screen (full indicating that a full redraw is required). */ - void drawMediaSource(bool full); + void drawTIA(bool full); /** This method is called after any drawing is done (per-frame). @@ -172,7 +172,7 @@ class FrameBufferSoft : public FrameBuffer A surface suitable for software rendering mode. @author Stephen Anthony - @version $Id: FrameBufferSoft.hxx,v 1.64 2009-01-10 18:52:55 stephena Exp $ + @version $Id: FrameBufferSoft.hxx,v 1.65 2009-01-19 16:52:32 stephena Exp $ */ class FBSurfaceSoft : public FBSurface { diff --git a/stella/src/common/Snapshot.cxx b/stella/src/common/Snapshot.cxx index 1fd6e7c2a..054df8457 100644 --- a/stella/src/common/Snapshot.cxx +++ b/stella/src/common/Snapshot.cxx @@ -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: Snapshot.cxx,v 1.26 2009-01-11 02:23:45 stephena Exp $ +// $Id: Snapshot.cxx,v 1.27 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include @@ -23,8 +23,8 @@ #include "bspf.hxx" #include "FrameBuffer.hxx" -#include "MediaSrc.hxx" #include "Props.hxx" +#include "TIA.hxx" #include "Version.hxx" #include "Snapshot.hxx" @@ -56,15 +56,14 @@ string Snapshot::savePNG(const FrameBuffer& framebuffer, const Properties& props } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string Snapshot::savePNG(const FrameBuffer& framebuffer, - const MediaSource& mediasrc, const Properties& props, - const string& filename) +string Snapshot::savePNG(const FrameBuffer& framebuffer, const TIA& tia, + const Properties& props, const string& filename) { ofstream out(filename.c_str(), ios_base::binary); if(!out.is_open()) return "ERROR: Couldn't create snapshot file"; - uInt32 width = mediasrc.width(), height = mediasrc.height(); + uInt32 width = tia.width(), height = tia.height(); uInt8* buffer = new uInt8[(width*3*2 + 1) * height]; // Fill the buffer with pixels from the mediasrc diff --git a/stella/src/common/Snapshot.hxx b/stella/src/common/Snapshot.hxx index ac4cbe75f..9cc63c81f 100644 --- a/stella/src/common/Snapshot.hxx +++ b/stella/src/common/Snapshot.hxx @@ -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: Snapshot.hxx,v 1.15 2009-01-03 22:57:12 stephena Exp $ +// $Id: Snapshot.hxx,v 1.16 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef SNAPSHOT_HXX @@ -21,7 +21,7 @@ class Properties; class FrameBuffer; -class MediaSource; +class TIA; #include #include "bspf.hxx" @@ -42,16 +42,15 @@ class Snapshot /** Save the current TIA image to a PNG file using data directly from - the MediaSource/TIA. No filtering or scaling will be included. + the TIA framebuffer. No filtering or scaling will be included. @param framebuffer The framebuffer containing the image data @param mediasrc Source of the raw TIA data @param props The properties object containing info about the ROM @param filename The filename of the PNG file */ - static string savePNG(const FrameBuffer& framebuffer, - const MediaSource& mediasrc, const Properties& props, - const string& filename); + static string savePNG(const FrameBuffer& framebuffer, const TIA& tia, + const Properties& props, const string& filename); private: static string saveBufferToPNG(ofstream& out, uInt8* buffer, diff --git a/stella/src/common/SoundSDL.hxx b/stella/src/common/SoundSDL.hxx index 195cff9b7..45528cbbb 100644 --- a/stella/src/common/SoundSDL.hxx +++ b/stella/src/common/SoundSDL.hxx @@ -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: SoundSDL.hxx,v 1.21 2009-01-01 18:13:35 stephena Exp $ +// $Id: SoundSDL.hxx,v 1.22 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef SOUND_SDL_HXX @@ -25,16 +25,15 @@ class OSystem; #include -#include "Sound.hxx" #include "bspf.hxx" -#include "MediaSrc.hxx" #include "TIASnd.hxx" +#include "Sound.hxx" /** This class implements the sound API for SDL. @author Stephen Anthony and Bradford W. Mott - @version $Id: SoundSDL.hxx,v 1.21 2009-01-01 18:13:35 stephena Exp $ + @version $Id: SoundSDL.hxx,v 1.22 2009-01-19 16:52:32 stephena Exp $ */ class SoundSDL : public Sound { diff --git a/stella/src/common/Version.hxx b/stella/src/common/Version.hxx index 1d1c50f7b..9611f142e 100644 --- a/stella/src/common/Version.hxx +++ b/stella/src/common/Version.hxx @@ -13,13 +13,13 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Version.hxx,v 1.45 2009-01-16 19:10:06 stephena Exp $ +// $Id: Version.hxx,v 1.46 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef VERSION_HXX #define VERSION_HXX -#define STELLA_BASE_VERSION "2.7" +#define STELLA_BASE_VERSION "2.7.1_cvs" #ifdef NIGHTLY_BUILD #define STELLA_VERSION STELLA_BASE_VERSION "pre-" NIGHTLY_BUILD diff --git a/stella/src/debugger/Debugger.cxx b/stella/src/debugger/Debugger.cxx index 4d7dfce80..d41014095 100644 --- a/stella/src/debugger/Debugger.cxx +++ b/stella/src/debugger/Debugger.cxx @@ -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.132 2009-01-15 21:04:47 stephena Exp $ +// $Id: Debugger.cxx,v 1.133 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include "bspf.hxx" @@ -466,7 +466,7 @@ int Debugger::step() int cyc = mySystem->cycles(); unlockState(); - myOSystem->console().mediaSource().updateScanlineByStep(); + myOSystem->console().tia().updateScanlineByStep(); lockState(); return mySystem->cycles() - cyc; @@ -494,7 +494,7 @@ int Debugger::trace() int targetPC = myCpuDebug->pc() + 3; // return address unlockState(); - myOSystem->console().mediaSource().updateScanlineByTrace(targetPC); + myOSystem->console().tia().updateScanlineByTrace(targetPC); lockState(); return mySystem->cycles() - cyc; diff --git a/stella/src/debugger/TIADebug.cxx b/stella/src/debugger/TIADebug.cxx index a07b20094..5d3cfc4af 100644 --- a/stella/src/debugger/TIADebug.cxx +++ b/stella/src/debugger/TIADebug.cxx @@ -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.29 2009-01-03 22:57:12 stephena Exp $ +// $Id: TIADebug.cxx,v 1.30 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include "System.hxx" @@ -24,7 +24,7 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TIADebug::TIADebug(Debugger& dbg, Console& console) : DebuggerSystem(dbg, console), - myTIA((TIA&)console.mediaSource()) + myTIA(console.tia()) { nusizStrings[0] = "size=8 copy=1"; nusizStrings[1] = "size=8 copy=2 spac=8"; diff --git a/stella/src/debugger/TIADebug.hxx b/stella/src/debugger/TIADebug.hxx index 469d206e1..f3cb71de0 100644 --- a/stella/src/debugger/TIADebug.hxx +++ b/stella/src/debugger/TIADebug.hxx @@ -13,18 +13,18 @@ // 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.25 2009-01-12 15:11:54 stephena Exp $ +// $Id: TIADebug.hxx,v 1.26 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef TIA_DEBUG_HXX #define TIA_DEBUG_HXX -class TIA; class Debugger; class TiaDebug; #include "Array.hxx" #include "DebuggerSystem.hxx" +#include "TIA.hxx" // pointer types for TIADebug instance methods // (used by TiaMethodExpression) diff --git a/stella/src/debugger/gui/TiaOutputWidget.cxx b/stella/src/debugger/gui/TiaOutputWidget.cxx index a0f3f4edc..9718046ef 100644 --- a/stella/src/debugger/gui/TiaOutputWidget.cxx +++ b/stella/src/debugger/gui/TiaOutputWidget.cxx @@ -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: TiaOutputWidget.cxx,v 1.25 2009-01-11 02:23:45 stephena Exp $ +// $Id: TiaOutputWidget.cxx,v 1.26 2009-01-19 16:52:32 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -68,7 +68,7 @@ void TiaOutputWidget::advanceScanline(int lines) { while(lines) { - instance().console().mediaSource().updateScanline(); + instance().console().tia().updateScanline(); --lines; } } @@ -78,7 +78,7 @@ void TiaOutputWidget::advance(int frames) { while(frames) { - instance().console().mediaSource().update(); + instance().console().tia().update(); --frames; } } @@ -144,7 +144,7 @@ void TiaOutputWidget::drawWidget(bool hilite) FBSurface& s = dialog().surface(); const uInt32 width = 160, // width is always 160 - height = instance().console().mediaSource().height(); + height = instance().console().tia().height(); for(uInt32 y = 0; y < height; ++y) { uInt32* line_ptr = myLineBuffer; diff --git a/stella/src/debugger/gui/TiaZoomWidget.cxx b/stella/src/debugger/gui/TiaZoomWidget.cxx index ccaede3b0..0d0d02acd 100644 --- a/stella/src/debugger/gui/TiaZoomWidget.cxx +++ b/stella/src/debugger/gui/TiaZoomWidget.cxx @@ -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: TiaZoomWidget.cxx,v 1.22 2009-01-03 22:57:12 stephena Exp $ +// $Id: TiaZoomWidget.cxx,v 1.23 2009-01-19 16:52:32 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -104,8 +104,8 @@ void TiaZoomWidget::zoom(int level) void TiaZoomWidget::recalc() { // Don't go past end of framebuffer - const int width = instance().console().mediaSource().width(), - height = instance().console().mediaSource().height(); + const int width = instance().console().tia().width(), + height = instance().console().tia().height(); // Figure out the bounding rectangle for the current center coords const int xoff = myNumCols >> 1, @@ -220,8 +220,8 @@ void TiaZoomWidget::drawWidget(bool hilite) // Draw the zoomed image // This probably isn't as efficient as it can be, but it's a small area // and I don't have time to make it faster :) - uInt8* currentFrame = instance().console().mediaSource().currentFrameBuffer(); - const int pitch = instance().console().mediaSource().width(), + uInt8* currentFrame = instance().console().tia().currentFrameBuffer(); + const int pitch = instance().console().tia().width(), width = myZoomLevel << 1, height = myZoomLevel; diff --git a/stella/src/emucore/Console.cxx b/stella/src/emucore/Console.cxx index fa37e4ddb..d4682ca22 100644 --- a/stella/src/emucore/Console.cxx +++ b/stella/src/emucore/Console.cxx @@ -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: Console.cxx,v 1.151 2009-01-01 18:13:35 stephena Exp $ +// $Id: Console.cxx,v 1.152 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include @@ -34,7 +34,6 @@ #include "M6502Hi.hxx" #include "M6502Low.hxx" #include "M6532.hxx" -#include "MediaSrc.hxx" #include "Paddles.hxx" #include "Props.hxx" #include "PropsSet.hxx" @@ -71,7 +70,7 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props) { myControllers[0] = 0; myControllers[1] = 0; - myMediaSource = 0; + myTIA = 0; mySwitches = 0; mySystem = 0; myEvent = 0; @@ -107,19 +106,15 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props) m6502->attach(myOSystem->debugger()); #endif - M6532* m6532 = new M6532(*this); - TIA *tia = new TIA(*this, myOSystem->settings()); - tia->setSound(myOSystem->sound()); + myCart = cart; + myRiot = new M6532(*this); + myTIA = new TIA(*this, myOSystem->settings()); + myTIA->setSound(myOSystem->sound()); mySystem->attach(m6502); - mySystem->attach(m6532); - mySystem->attach(tia); - mySystem->attach(cart); - - // Remember what my media source is - myMediaSource = tia; - myCart = cart; - myRiot = m6532; + mySystem->attach(myRiot); + mySystem->attach(myTIA); + mySystem->attach(myCart); // Query some info about this console ostringstream about, vidinfo; @@ -138,8 +133,8 @@ Console::Console(OSystem* osystem, Cartridge* cart, const Properties& props) int palCount = 0; for(int i = 0; i < 60; ++i) { - myMediaSource->update(); - if(i >= 30 && myMediaSource->scanlines() > 285) + myTIA->update(); + if(i >= 30 && myTIA->scanlines() > 285) ++palCount; } myDisplayFormat = (palCount >= 15) ? "PAL" : "NTSC"; @@ -429,7 +424,7 @@ bool Console::initializeVideo(bool full) string title = string("Stella ") + STELLA_VERSION + ": \"" + myProperties.get(Cartridge_Name) + "\""; if(!myOSystem->frameBuffer().initialize(title, - myMediaSource->width() << 1, myMediaSource->height())) + myTIA->width() << 1, myTIA->height())) return false; myOSystem->frameBuffer().showFrameStats( @@ -451,7 +446,7 @@ bool Console::initializeVideo(bool full) myOSystem->setFramerate(myFramerate); // Make sure auto-frame calculation is only enabled when necessary - myMediaSource->enableAutoFrame(framerate <= 0); + myTIA->enableAutoFrame(framerate <= 0); return true; } @@ -473,7 +468,7 @@ void Console::initializeAudio() myOSystem->sound().initialize(); // Make sure auto-frame calculation is only enabled when necessary - myMediaSource->enableAutoFrame(framerate <= 0); + myTIA->enableAutoFrame(framerate <= 0); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -532,7 +527,7 @@ void Console::changeYStart(int direction) strval << ystart; myProperties.set(Display_YStart, strval.str()); - ((TIA*)myMediaSource)->frameReset(); + myTIA->frameReset(); myOSystem->frameBuffer().refresh(); message = "YStart "; @@ -570,7 +565,7 @@ void Console::changeHeight(int direction) strval << height; myProperties.set(Display_Height, strval.str()); - ((TIA*)myMediaSource)->frameReset(); + myTIA->frameReset(); initializeVideo(); // takes care of refreshing the screen message = "Height "; @@ -696,7 +691,7 @@ void Console::setControllers() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::toggleTIABit(TIA::TIABit bit, const string& bitname, bool show) const { - bool result = ((TIA*)myMediaSource)->toggleBit(bit); + bool result = myTIA->toggleBit(bit); string message = bitname + (result ? " enabled" : " disabled"); myOSystem->frameBuffer().showMessage(message); } @@ -704,7 +699,7 @@ void Console::toggleTIABit(TIA::TIABit bit, const string& bitname, bool show) co // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Console::enableBits(bool enable) const { - ((TIA*)myMediaSource)->enableBits(enable); + myTIA->enableBits(enable); string message = string("TIA bits") + (enable ? " enabled" : " disabled"); myOSystem->frameBuffer().showMessage(message); } diff --git a/stella/src/emucore/Console.hxx b/stella/src/emucore/Console.hxx index 7ca5abf98..0c3fc2a75 100644 --- a/stella/src/emucore/Console.hxx +++ b/stella/src/emucore/Console.hxx @@ -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: Console.hxx,v 1.71 2009-01-01 18:13:35 stephena Exp $ +// $Id: Console.hxx,v 1.72 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef CONSOLE_HXX @@ -22,9 +22,9 @@ class Console; class Controller; class Event; -class MediaSource; class Switches; class System; +class TIA; #include "bspf.hxx" #include "Control.hxx" @@ -52,7 +52,7 @@ struct ConsoleInfo This class represents the entire game console. @author Bradford W. Mott - @version $Id: Console.hxx,v 1.71 2009-01-01 18:13:35 stephena Exp $ + @version $Id: Console.hxx,v 1.72 2009-01-19 16:52:32 stephena Exp $ */ class Console : public Serializable { @@ -91,11 +91,11 @@ class Console : public Serializable } /** - Get the MediaSource for this console + Get the TIA for this console - @return The mediasource + @return The TIA */ - MediaSource& mediaSource() const { return *myMediaSource; } + TIA& tia() const { return *myTIA; } /** Get the properties being used by the game @@ -302,8 +302,8 @@ class Console : public Serializable // Pointer to the event object to use Event* myEvent; - // Pointer to the media source object - MediaSource* myMediaSource; + // Pointer to the TIA object + TIA* myTIA; // Properties for the game Properties myProperties; diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 91b7ac53a..58f28bcf0 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -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: EventHandler.cxx,v 1.239 2009-01-16 16:38:06 stephena Exp $ +// $Id: EventHandler.cxx,v 1.240 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include @@ -1804,7 +1804,7 @@ void EventHandler::takeSnapshot() if(myOSystem->settings().getBool("ss1x")) { string msg = Snapshot::savePNG(myOSystem->frameBuffer(), - myOSystem->console().mediaSource(), + myOSystem->console().tia(), myOSystem->console().properties(), filename); myOSystem->frameBuffer().showMessage(msg); } diff --git a/stella/src/emucore/FrameBuffer.cxx b/stella/src/emucore/FrameBuffer.cxx index cab7a7490..a2e333be8 100644 --- a/stella/src/emucore/FrameBuffer.cxx +++ b/stella/src/emucore/FrameBuffer.cxx @@ -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.161 2009-01-15 01:31:26 stephena Exp $ +// $Id: FrameBuffer.cxx,v 1.162 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #include @@ -27,10 +27,10 @@ #include "Event.hxx" #include "Font.hxx" #include "Launcher.hxx" -#include "MediaSrc.hxx" #include "Menu.hxx" #include "OSystem.hxx" #include "Settings.hxx" +#include "TIA.hxx" #include "FrameBuffer.hxx" @@ -164,7 +164,7 @@ void FrameBuffer::update() // Run the console for one frame // Note that the debugger can cause a breakpoint to occur, which changes // the EventHandler state 'behind our back' - we need to check for that - myOSystem->console().mediaSource().update(); + myOSystem->console().tia().update(); #ifdef DEBUGGER_SUPPORT if(myOSystem->eventHandler().state() != EventHandler::S_EMULATE) break; #endif @@ -172,7 +172,7 @@ void FrameBuffer::update() myOSystem->console().fry(); // And update the screen - drawMediaSource(myRedrawEntireFrame); + drawTIA(myRedrawEntireFrame); // Show frame statistics if(myStatsMsg.enabled) @@ -180,7 +180,7 @@ void FrameBuffer::update() const ConsoleInfo& info = myOSystem->console().about(); char msg[30]; sprintf(msg, "%u LINES %2.2f FPS", - myOSystem->console().mediaSource().scanlines(), + myOSystem->console().tia().scanlines(), myOSystem->console().getFramerate()); myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor); myStatsMsg.surface->drawString(&myOSystem->consoleFont(), @@ -200,7 +200,7 @@ void FrameBuffer::update() { // Only update the screen if it's been invalidated if(myRedrawEntireFrame) - drawMediaSource(true); + drawTIA(true); // Show a pause message every 5 seconds if(myPausedCount++ >= 7*myOSystem->frameRate()) @@ -410,29 +410,29 @@ void FrameBuffer::refresh() { case EventHandler::S_EMULATE: case EventHandler::S_PAUSE: - drawMediaSource(true); + drawTIA(true); if(doubleBuffered) - drawMediaSource(true); + drawTIA(true); break; case EventHandler::S_MENU: - drawMediaSource(true); + drawTIA(true); myOSystem->menu().draw(true); if(doubleBuffered) { postFrameUpdate(); - drawMediaSource(true); + drawTIA(true); myOSystem->menu().draw(true); } break; case EventHandler::S_CMDMENU: - drawMediaSource(true); + drawTIA(true); myOSystem->commandMenu().draw(true); if(doubleBuffered) { postFrameUpdate(); - drawMediaSource(true); + drawTIA(true); myOSystem->commandMenu().draw(true); } break; @@ -502,8 +502,8 @@ void FrameBuffer::resetSurfaces() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 FrameBuffer::tiaPixel(uInt32 idx) const { - uInt8 c = *(myOSystem->console().mediaSource().currentFrameBuffer() + idx); - uInt8 p = *(myOSystem->console().mediaSource().previousFrameBuffer() + idx); + uInt8 c = *(myOSystem->console().tia().currentFrameBuffer() + idx); + uInt8 p = *(myOSystem->console().tia().previousFrameBuffer() + idx); return (!myUsePhosphor ? myDefPalette[c] : myAvgPalette[c][p]); } diff --git a/stella/src/emucore/FrameBuffer.hxx b/stella/src/emucore/FrameBuffer.hxx index 85759c04b..cb433dd13 100644 --- a/stella/src/emucore/FrameBuffer.hxx +++ b/stella/src/emucore/FrameBuffer.hxx @@ -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.115 2009-01-10 18:52:55 stephena Exp $ +// $Id: FrameBuffer.hxx,v 1.116 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_HXX @@ -83,15 +83,15 @@ enum { /** - This class encapsulates the MediaSource and is the basis for the video + This class encapsulates all video buffers and is the basis for the video display in Stella. All graphics ports should derive from this class for platform-specific video stuff. - All GUI elements (ala ScummVM) are drawn into FBSurfaces, which are in - turn drawn here as well. + The TIA is drawn here, and all GUI elements (ala ScummVM, which are drawn + into FBSurfaces), are in turn drawn here as well. @author Stephen Anthony - @version $Id: FrameBuffer.hxx,v 1.115 2009-01-10 18:52:55 stephena Exp $ + @version $Id: FrameBuffer.hxx,v 1.116 2009-01-19 16:52:32 stephena Exp $ */ class FrameBuffer { @@ -118,7 +118,7 @@ class FrameBuffer /** Updates the display, which depending on the current mode could mean - drawing the mediasource, any pending menus, etc. + drawing the TIA, any pending menus, etc. */ void update(); @@ -247,7 +247,7 @@ class FrameBuffer const StringMap& supportedTIAFilters(const string& type); /** - Get the TIA pixel associated with the given MediaSrc index. + Get the TIA pixel associated with the given TIA buffer index. */ uInt32 tiaPixel(uInt32 idx) const; @@ -383,10 +383,10 @@ class FrameBuffer virtual FBSurface* createSurface(int w, int h, bool useBase = false) const = 0; /** - This method should be called anytime the MediaSource needs to be redrawn + This method should be called anytime the TIA needs to be redrawn to the screen (full indicating that a full redraw is required). */ - virtual void drawMediaSource(bool full) = 0; + virtual void drawTIA(bool full) = 0; /** This method is called after any drawing is done (per-frame). @@ -563,7 +563,7 @@ class FrameBuffer FrameBuffer type. @author Stephen Anthony - @version $Id: FrameBuffer.hxx,v 1.115 2009-01-10 18:52:55 stephena Exp $ + @version $Id: FrameBuffer.hxx,v 1.116 2009-01-19 16:52:32 stephena Exp $ */ // Text alignment modes for drawString() enum TextAlignment { diff --git a/stella/src/emucore/MediaSrc.cxx b/stella/src/emucore/MediaSrc.cxx deleted file mode 100644 index be458d91c..000000000 --- a/stella/src/emucore/MediaSrc.cxx +++ /dev/null @@ -1,44 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: MediaSrc.cxx,v 1.6 2009-01-01 18:13:36 stephena Exp $ -//============================================================================ - -#include -#include "MediaSrc.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::MediaSource() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::~MediaSource() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::MediaSource(const MediaSource&) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource& MediaSource::operator = (const MediaSource&) -{ - assert(false); - - return *this; -} - diff --git a/stella/src/emucore/MediaSrc.hxx b/stella/src/emucore/MediaSrc.hxx deleted file mode 100644 index d2ba0c385..000000000 --- a/stella/src/emucore/MediaSrc.hxx +++ /dev/null @@ -1,139 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa -// SSSS tt ee ee ll ll aa -// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" -// SS SS tt ee ll ll aa aa -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team -// -// 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.20 2009-01-01 18:13:36 stephena Exp $ -//============================================================================ - -#ifndef MEDIASOURCE_HXX -#define MEDIASOURCE_HXX - -#include - -class MediaSource; -class Sound; - -#include "bspf.hxx" - -/** - This class provides an interface for accessing graphics and audio data. - - @author Bradford W. Mott - @version $Id: MediaSrc.hxx,v 1.20 2009-01-01 18:13:36 stephena Exp $ -*/ -class MediaSource -{ - public: - /** - Create a new media source - */ - MediaSource(); - - /** - Destructor - */ - virtual ~MediaSource(); - - public: - /** - This method should be called at an interval corresponding to the - desired frame rate to update the media source. Invoking this method - will update the graphics buffer and generate the corresponding audio - samples. - */ - virtual void update() = 0; - - /** - Answers the current frame buffer - - @return Pointer to the current frame buffer - */ - virtual uInt8* currentFrameBuffer() const = 0; - - /** - Answers the previous frame buffer - - @return Pointer to the previous frame buffer - */ - virtual uInt8* previousFrameBuffer() const = 0; - -#ifdef DEBUGGER_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: - /** - Answers the height of the frame buffer - - @return The frame's height - */ - virtual uInt32 height() const = 0; - - /** - Answers the width of the frame buffer - - @return The frame's width - */ - virtual uInt32 width() const = 0; - - public: - /** - Enables/disables auto-frame calculation. If enabled, the - MediaSource should re-adjust the framerate at regular intervals. - - @param mode Whether to enable or disable all auto-frame calculation - */ - virtual void enableAutoFrame(bool mode) = 0; - - /** - Answers the total number of scanlines the media source generated - in producing the current frame buffer. - - @return The total number of scanlines generated - */ - virtual uInt32 scanlines() const = 0; - - /** - Sets the sound device for the TIA. - */ - virtual void setSound(Sound& sound) = 0; - - private: - // Copy constructor isn't supported by this class so make it private - MediaSource(const MediaSource&); - - // Assignment operator isn't supported by this class so make it private - MediaSource& operator = (const MediaSource&); -}; - -#endif diff --git a/stella/src/emucore/TIA.cxx b/stella/src/emucore/TIA.cxx index ce809c378..117317dbc 100644 --- a/stella/src/emucore/TIA.cxx +++ b/stella/src/emucore/TIA.cxx @@ -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.100 2009-01-14 20:31:07 stephena Exp $ +// $Id: TIA.cxx,v 1.101 2009-01-19 16:52:32 stephena Exp $ //============================================================================ //#define DEBUG_HMOVE @@ -33,6 +33,7 @@ #include "Settings.hxx" #include "Sound.hxx" #include "System.hxx" +#include "TIATables.hxx" #include "TIA.hxx" @@ -40,28 +41,26 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TIA::TIA(Console& console, Settings& settings) - : myConsole(console), - mySettings(settings), - mySound(NULL), - myColorLossEnabled(false), - myPartialFrameFlag(false), - myMaximumNumberOfScanlines(262), - myCOLUBK(myColor[0]), - myCOLUPF(myColor[1]), - myCOLUP0(myColor[2]), - myCOLUP1(myColor[3]) + : myConsole(console), + mySettings(settings), + mySound(NULL), + myMaximumNumberOfScanlines(262), + myCOLUBK(myColor[0]), + myCOLUPF(myColor[1]), + myCOLUP0(myColor[2]), + myCOLUP1(myColor[3]), + myColorLossEnabled(false), + myPartialFrameFlag(false), + myFrameGreyed(false), + myAutoFrameEnabled(false), + myFrameCounter(0) { - uInt32 i; - // Allocate buffers for two frame buffers myCurrentFrameBuffer = new uInt8[160 * 300]; myPreviousFrameBuffer = new uInt8[160 * 300]; - myFrameGreyed = false; - myAutoFrameEnabled = false; - - for(i = 0; i < 6; ++i) - myBitEnabled[i] = true; + // Make sure all TIA bits are enabled + enableBits(true); for(uInt16 x = 0; x < 2; ++x) { @@ -71,13 +70,13 @@ TIA::TIA(Console& console, Settings& settings) { uInt8 color = 0; - if((enabled & (myP1Bit | myM1Bit)) != 0) + if((enabled & (P1Bit | M1Bit)) != 0) color = 3; - if((enabled & (myP0Bit | myM0Bit)) != 0) + if((enabled & (P0Bit | M0Bit)) != 0) color = 2; - if((enabled & myBLBit) != 0) + if((enabled & BLBit) != 0) color = 1; - if((enabled & myPFBit) != 0) + if((enabled & PFBit) != 0) color = 1; // NOTE: Playfield has priority so ScoreBit isn't used myPriorityEncoder[x][enabled] = color; @@ -86,13 +85,13 @@ TIA::TIA(Console& console, Settings& settings) { uInt8 color = 0; - if((enabled & myBLBit) != 0) + if((enabled & BLBit) != 0) color = 1; - if((enabled & myPFBit) != 0) + if((enabled & PFBit) != 0) color = (enabled & ScoreBit) ? ((x == 0) ? 2 : 3) : 1; - if((enabled & (myP1Bit | myM1Bit)) != 0) + if((enabled & (P1Bit | M1Bit)) != 0) color = (color != 2) ? 3 : 2; - if((enabled & (myP0Bit | myM0Bit)) != 0) + if((enabled & (P0Bit | M0Bit)) != 0) color = 2; myPriorityEncoder[x][enabled] = color; @@ -100,21 +99,10 @@ TIA::TIA(Console& console, Settings& settings) } } - for(i = 0; i < 640; ++i) - ourDisabledMaskTable[i] = 0; - // Compute all of the mask tables - computeBallMaskTable(); - computeCollisionTable(); - computeMissleMaskTable(); - computePlayerMaskTable(); - computePlayerPositionResetWhenTable(); - computePlayerReflectTable(); - computePlayfieldMaskTable(); - - // Init stats counters - myFrameCounter = 0; + TIATables::computeAllTables(); + // Zero audio registers myAUDV0 = myAUDV1 = myAUDF0 = myAUDF1 = myAUDC0 = myAUDC1 = 0; } @@ -135,67 +123,49 @@ void TIA::reset() myEnabledObjects = 0; // Some default values for the registers - myVSYNC = 0; - myVBLANK = 0; - myNUSIZ0 = 0; - myNUSIZ1 = 0; + myVSYNC = myVBLANK = 0; + myNUSIZ0 = myNUSIZ1 = 0; myCOLUP0 = 0; myCOLUP1 = 0; myCOLUPF = 0; myPlayfieldPriorityAndScore = 0; myCOLUBK = 0; myCTRLPF = 0; - myREFP0 = false; - myREFP1 = false; + myREFP0 = myREFP1 = false; myPF = 0; - myGRP0 = 0; - myGRP1 = 0; - myDGRP0 = 0; - myDGRP1 = 0; - myENAM0 = false; - myENAM1 = false; - myENABL = false; - myDENABL = false; - myHMP0 = 0; - myHMP1 = 0; - myHMM0 = 0; - myHMM1 = 0; - myHMBL = 0; - myVDELP0 = false; - myVDELP1 = false; - myVDELBL = false; - myRESMP0 = false; - myRESMP1 = false; + myGRP0 = myGRP1 = myDGRP0 = myDGRP1 = 0; + myENAM0 = myENAM1 = myENABL = myDENABL = false; + myHMP0 = myHMP1 = myHMM0 = myHMM1 = myHMBL = 0; + myVDELP0 = myVDELP1 = myVDELBL = myRESMP0 = myRESMP1 = false; myCollision = 0; - myPOSP0 = 0; - myPOSP1 = 0; - myPOSM0 = 0; - myPOSM1 = 0; - myPOSBL = 0; + myPOSP0 = myPOSP1 = myPOSM0 = myPOSM1 = myPOSBL = 0; // Some default values for the "current" variables myCurrentGRP0 = 0; myCurrentGRP1 = 0; - myCurrentBLMask = ourBallMaskTable[0][0]; - myCurrentM0Mask = ourMissleMaskTable[0][0][0]; - myCurrentM1Mask = ourMissleMaskTable[0][0][0]; - myCurrentP0Mask = ourPlayerMaskTable[0][0][0]; - myCurrentP1Mask = ourPlayerMaskTable[0][0][0]; - myCurrentPFMask = ourPlayfieldTable[0]; + myCurrentBLMask = TIATables::BallMaskTable[0][0]; + myCurrentM0Mask = TIATables::MissleMaskTable[0][0][0]; + myCurrentM1Mask = TIATables::MissleMaskTable[0][0][0]; + myCurrentP0Mask = TIATables::PlayerMaskTable[0][0][0]; + myCurrentP1Mask = TIATables::PlayerMaskTable[0][0][0]; + myCurrentPFMask = TIATables::PlayfieldTable[0]; + + myMotionClockP0 = 0; + myMotionClockP1 = 0; + myMotionClockM0 = 0; + myMotionClockM1 = 0; + myMotionClockBL = 0; myLastHMOVEClock = 0; myHMOVEBlankEnabled = false; - myM0CosmicArkMotionEnabled = false; - myM0CosmicArkCounter = 0; + myM0CosmicArkMotionEnabled = false; // FIXME - remove this + myM0CosmicArkCounter = 0; // FIXME - remove this enableBits(true); myDumpEnabled = false; myDumpDisabledCycle = 0; - myAllowHMOVEBlanks = - (myConsole.properties().get(Emulation_HmoveBlanks) == "YES"); - myFloatTIAOutputPins = mySettings.getBool("tiafloat"); myAutoFrameEnabled = (mySettings.getInt("framerate") <= 0); @@ -228,8 +198,7 @@ void TIA::frameReset() myFramePointer = myCurrentFrameBuffer; // Make sure all these are within bounds - myFrameXStart = 0; // Hardcoded in preparation for new TIA class - myFrameWidth = 160; // Hardcoded in preparation for new TIA class + myFrameWidth = 160; myFrameYStart = atoi(myConsole.properties().get(Display_YStart).c_str()); if(myFrameYStart < 0) myFrameYStart = 0; if(myFrameYStart > 64) myFrameYStart = 64; @@ -372,17 +341,17 @@ bool TIA::save(Serializer& out) const out.putByte((char)myCurrentGRP1); // pointers -// myCurrentBLMask = ourBallMaskTable[0][0]; -// myCurrentM0Mask = ourMissleMaskTable[0][0][0]; -// myCurrentM1Mask = ourMissleMaskTable[0][0][0]; -// myCurrentP0Mask = ourPlayerMaskTable[0][0][0]; -// myCurrentP1Mask = ourPlayerMaskTable[0][0][0]; -// myCurrentPFMask = ourPlayfieldTable[0]; +// myCurrentBLMask = TIATables::BallMaskTable[0][0]; +// myCurrentM0Mask = TIATables::MissleMaskTable[0][0][0]; +// myCurrentM1Mask = TIATables::MissleMaskTable[0][0][0]; +// myCurrentP0Mask = TIATables::PlayerMaskTable[0][0][0]; +// myCurrentP1Mask = TIATables::PlayerMaskTable[0][0][0]; +// myCurrentPFMask = TIATables::PlayfieldTable[0]; out.putInt(myLastHMOVEClock); out.putBool(myHMOVEBlankEnabled); - out.putBool(myM0CosmicArkMotionEnabled); - out.putInt(myM0CosmicArkCounter); + out.putBool(myM0CosmicArkMotionEnabled); // FIXME - remove this + out.putInt(myM0CosmicArkCounter); // FIXME - remove this out.putBool(myDumpEnabled); out.putInt(myDumpDisabledCycle); @@ -469,17 +438,17 @@ bool TIA::load(Deserializer& in) myCurrentGRP1 = (uInt8) in.getByte(); // pointers -// myCurrentBLMask = ourBallMaskTable[0][0]; -// myCurrentM0Mask = ourMissleMaskTable[0][0][0]; -// myCurrentM1Mask = ourMissleMaskTable[0][0][0]; -// myCurrentP0Mask = ourPlayerMaskTable[0][0][0]; -// myCurrentP1Mask = ourPlayerMaskTable[0][0][0]; -// myCurrentPFMask = ourPlayfieldTable[0]; +// myCurrentBLMask = TIATables::BallMaskTable[0][0]; +// myCurrentM0Mask = TIATables::MissleMaskTable[0][0][0]; +// myCurrentM1Mask = TIATables::MissleMaskTable[0][0][0]; +// myCurrentP0Mask = TIATables::PlayerMaskTable[0][0][0]; +// myCurrentP1Mask = TIATables::PlayerMaskTable[0][0][0]; +// myCurrentPFMask = TIATables::PlayfieldTable[0]; myLastHMOVEClock = (Int32) in.getInt(); myHMOVEBlankEnabled = in.getBool(); - myM0CosmicArkMotionEnabled = in.getBool(); - myM0CosmicArkCounter = (uInt32) in.getInt(); + myM0CosmicArkMotionEnabled = in.getBool(); // FIXME - remove this + myM0CosmicArkCounter = (uInt32) in.getInt(); // FIXME - remove this myDumpEnabled = in.getBool(); myDumpDisabledCycle = (Int32) in.getInt(); @@ -701,524 +670,12 @@ void TIA::updateScanlineByTrace(int target) } #endif -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIA::width() const -{ - return myFrameWidth; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIA::height() const -{ - return myFrameHeight; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIA::scanlines() const -{ - // calculate the current scanline - uInt32 totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted; - return totalClocks/228; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIA::clocksThisLine() const -{ - // calculate the current scanline - uInt32 totalClocks = (mySystem->cycles() * 3) - myClockWhenFrameStarted; - return totalClocks%228; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void TIA::setSound(Sound& sound) { mySound = &sound; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computeBallMaskTable() -{ - // First, calculate masks for alignment 0 - for(Int32 size = 0; size < 4; ++size) - { - Int32 x; - - // Set all of the masks to false to start with - for(x = 0; x < 160; ++x) - { - ourBallMaskTable[0][size][x] = false; - } - - // Set the necessary fields true - for(x = 0; x < 160 + 8; ++x) - { - if((x >= 0) && (x < (1 << size))) - { - ourBallMaskTable[0][size][x % 160] = true; - } - } - - // Copy fields into the wrap-around area of the mask - for(x = 0; x < 160; ++x) - { - ourBallMaskTable[0][size][x + 160] = ourBallMaskTable[0][size][x]; - } - } - - // Now, copy data for alignments of 1, 2 and 3 - for(uInt32 align = 1; align < 4; ++align) - { - for(uInt32 size = 0; size < 4; ++size) - { - for(uInt32 x = 0; x < 320; ++x) - { - ourBallMaskTable[align][size][x] = - ourBallMaskTable[0][size][(x + 320 - align) % 320]; - } - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computeCollisionTable() -{ - for(uInt8 i = 0; i < 64; ++i) - { - ourCollisionTable[i] = 0; - - if((i & myM0Bit) && (i & myP1Bit)) // M0-P1 - ourCollisionTable[i] |= 0x0001; - - if((i & myM0Bit) && (i & myP0Bit)) // M0-P0 - ourCollisionTable[i] |= 0x0002; - - if((i & myM1Bit) && (i & myP0Bit)) // M1-P0 - ourCollisionTable[i] |= 0x0004; - - if((i & myM1Bit) && (i & myP1Bit)) // M1-P1 - ourCollisionTable[i] |= 0x0008; - - if((i & myP0Bit) && (i & myPFBit)) // P0-PF - ourCollisionTable[i] |= 0x0010; - - if((i & myP0Bit) && (i & myBLBit)) // P0-BL - ourCollisionTable[i] |= 0x0020; - - if((i & myP1Bit) && (i & myPFBit)) // P1-PF - ourCollisionTable[i] |= 0x0040; - - if((i & myP1Bit) && (i & myBLBit)) // P1-BL - ourCollisionTable[i] |= 0x0080; - - if((i & myM0Bit) && (i & myPFBit)) // M0-PF - ourCollisionTable[i] |= 0x0100; - - if((i & myM0Bit) && (i & myBLBit)) // M0-BL - ourCollisionTable[i] |= 0x0200; - - if((i & myM1Bit) && (i & myPFBit)) // M1-PF - ourCollisionTable[i] |= 0x0400; - - if((i & myM1Bit) && (i & myBLBit)) // M1-BL - ourCollisionTable[i] |= 0x0800; - - if((i & myBLBit) && (i & myPFBit)) // BL-PF - ourCollisionTable[i] |= 0x1000; - - if((i & myP0Bit) && (i & myP1Bit)) // P0-P1 - ourCollisionTable[i] |= 0x2000; - - if((i & myM0Bit) && (i & myM1Bit)) // M0-M1 - ourCollisionTable[i] |= 0x4000; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computeMissleMaskTable() -{ - // First, calculate masks for alignment 0 - Int32 x, size, number; - - // Clear the missle table to start with - for(number = 0; number < 8; ++number) - for(size = 0; size < 4; ++size) - for(x = 0; x < 160; ++x) - ourMissleMaskTable[0][number][size][x] = false; - - for(number = 0; number < 8; ++number) - { - for(size = 0; size < 4; ++size) - { - for(x = 0; x < 160 + 72; ++x) - { - // Only one copy of the missle - if((number == 0x00) || (number == 0x05) || (number == 0x07)) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - // Two copies - close - else if(number == 0x01) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 16) >= 0) && ((x - 16) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - // Two copies - medium - else if(number == 0x02) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - // Three copies - close - else if(number == 0x03) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 16) >= 0) && ((x - 16) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - // Two copies - wide - else if(number == 0x04) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 64) >= 0) && ((x - 64) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - // Three copies - medium - else if(number == 0x06) - { - if((x >= 0) && (x < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - else if(((x - 64) >= 0) && ((x - 64) < (1 << size))) - ourMissleMaskTable[0][number][size][x % 160] = true; - } - } - - // Copy data into wrap-around area - for(x = 0; x < 160; ++x) - ourMissleMaskTable[0][number][size][x + 160] = - ourMissleMaskTable[0][number][size][x]; - } - } - - // Now, copy data for alignments of 1, 2 and 3 - for(uInt32 align = 1; align < 4; ++align) - { - for(number = 0; number < 8; ++number) - { - for(size = 0; size < 4; ++size) - { - for(x = 0; x < 320; ++x) - { - ourMissleMaskTable[align][number][size][x] = - ourMissleMaskTable[0][number][size][(x + 320 - align) % 320]; - } - } - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computePlayerMaskTable() -{ - // First, calculate masks for alignment 0 - Int32 x, enable, mode; - - // Set the player mask table to all zeros - for(enable = 0; enable < 2; ++enable) - for(mode = 0; mode < 8; ++mode) - for(x = 0; x < 160; ++x) - ourPlayerMaskTable[0][enable][mode][x] = 0x00; - - // Now, compute the player mask table - for(enable = 0; enable < 2; ++enable) - { - for(mode = 0; mode < 8; ++mode) - { - for(x = 0; x < 160 + 72; ++x) - { - if(mode == 0x00) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - } - else if(mode == 0x01) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - else if(((x - 16) >= 0) && ((x - 16) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 16); - } - else if(mode == 0x02) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - else if(((x - 32) >= 0) && ((x - 32) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); - } - else if(mode == 0x03) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - else if(((x - 16) >= 0) && ((x - 16) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 16); - else if(((x - 32) >= 0) && ((x - 32) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); - } - else if(mode == 0x04) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - else if(((x - 64) >= 0) && ((x - 64) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 64); - } - else if(mode == 0x05) - { - // For some reason in double size mode the player's output - // is delayed by one pixel thus we use > instead of >= - if((enable == 0) && (x > 0) && (x <= 16)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> ((x - 1)/2); - } - else if(mode == 0x06) - { - if((enable == 0) && (x >= 0) && (x < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; - else if(((x - 32) >= 0) && ((x - 32) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); - else if(((x - 64) >= 0) && ((x - 64) < 8)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 64); - } - else if(mode == 0x07) - { - // For some reason in quad size mode the player's output - // is delayed by one pixel thus we use > instead of >= - if((enable == 0) && (x > 0) && (x <= 32)) - ourPlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> ((x - 1)/4); - } - } - - // Copy data into wrap-around area - for(x = 0; x < 160; ++x) - { - ourPlayerMaskTable[0][enable][mode][x + 160] = - ourPlayerMaskTable[0][enable][mode][x]; - } - } - } - - // Now, copy data for alignments of 1, 2 and 3 - for(uInt32 align = 1; align < 4; ++align) - { - for(enable = 0; enable < 2; ++enable) - { - for(mode = 0; mode < 8; ++mode) - { - for(x = 0; x < 320; ++x) - { - ourPlayerMaskTable[align][enable][mode][x] = - ourPlayerMaskTable[0][enable][mode][(x + 320 - align) % 320]; - } - } - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computePlayerPositionResetWhenTable() -{ - uInt32 mode, oldx, newx; - - // Loop through all player modes, all old player positions, and all new - // player positions and determine where the new position is located: - // 1 means the new position is within the display of an old copy of the - // player, -1 means the new position is within the delay portion of an - // old copy of the player, and 0 means it's neither of these two - for(mode = 0; mode < 8; ++mode) - { - for(oldx = 0; oldx < 160; ++oldx) - { - // Set everything to 0 for non-delay/non-display section - for(newx = 0; newx < 160; ++newx) - { - ourPlayerPositionResetWhenTable[mode][oldx][newx] = 0; - } - - // Now, we'll set the entries for non-delay/non-display section - for(newx = 0; newx < 160 + 72 + 5; ++newx) - { - if(mode == 0x00) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x01) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x02) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x03) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x04) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x05) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 16))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x06) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - else if(mode == 0x07) - { - if((newx >= oldx) && (newx < (oldx + 4))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; - - if((newx >= oldx + 4) && (newx < (oldx + 4 + 32))) - ourPlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; - } - } - - // Let's do a sanity check on our table entries - uInt32 s1 = 0, s2 = 0; - for(newx = 0; newx < 160; ++newx) - { - if(ourPlayerPositionResetWhenTable[mode][oldx][newx] == -1) - ++s1; - if(ourPlayerPositionResetWhenTable[mode][oldx][newx] == 1) - ++s2; - } - assert((s1 % 4 == 0) && (s2 % 8 == 0)); - } - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computePlayerReflectTable() -{ - for(uInt16 i = 0; i < 256; ++i) - { - uInt8 r = 0; - - for(uInt16 t = 1; t <= 128; t *= 2) - { - r = (r << 1) | ((i & t) ? 0x01 : 0x00); - } - - ourPlayerReflectTable[i] = r; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void TIA::computePlayfieldMaskTable() -{ - Int32 x; - - // Compute playfield mask table for non-reflected mode - for(x = 0; x < 160; ++x) - { - if(x < 16) - ourPlayfieldTable[0][x] = 0x00001 << (x / 4); - else if(x < 48) - ourPlayfieldTable[0][x] = 0x00800 >> ((x - 16) / 4); - else if(x < 80) - ourPlayfieldTable[0][x] = 0x01000 << ((x - 48) / 4); - else if(x < 96) - ourPlayfieldTable[0][x] = 0x00001 << ((x - 80) / 4); - else if(x < 128) - ourPlayfieldTable[0][x] = 0x00800 >> ((x - 96) / 4); - else if(x < 160) - ourPlayfieldTable[0][x] = 0x01000 << ((x - 128) / 4); - } - - // Compute playfield mask table for reflected mode - for(x = 0; x < 160; ++x) - { - if(x < 16) - ourPlayfieldTable[1][x] = 0x00001 << (x / 4); - else if(x < 48) - ourPlayfieldTable[1][x] = 0x00800 >> ((x - 16) / 4); - else if(x < 80) - ourPlayfieldTable[1][x] = 0x01000 << ((x - 48) / 4); - else if(x < 112) - ourPlayfieldTable[1][x] = 0x80000 >> ((x - 80) / 4); - else if(x < 144) - ourPlayfieldTable[1][x] = 0x00010 << ((x - 112) / 4); - else if(x < 160) - ourPlayfieldTable[1][x] = 0x00008 >> ((x - 144) / 4); - } -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) { @@ -1246,8 +703,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield is enabled and the score bit is not set - case myPFBit: - case myPFBit | PriorityBit: + case PFBit: + case PFBit | PriorityBit: { uInt32* mask = &myCurrentPFMask[hpos]; @@ -1267,8 +724,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield is enabled and the score bit is set - case myPFBit | ScoreBit: - case myPFBit | ScoreBit | PriorityBit: + case PFBit | ScoreBit: + case PFBit | ScoreBit | PriorityBit: { uInt32* mask = &myCurrentPFMask[hpos]; @@ -1291,10 +748,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Player 0 is enabled - case myP0Bit: - case myP0Bit | ScoreBit: - case myP0Bit | PriorityBit: - case myP0Bit | ScoreBit | PriorityBit: + case P0Bit: + case P0Bit | ScoreBit: + case P0Bit | PriorityBit: + case P0Bit | ScoreBit | PriorityBit: { uInt8* mP0 = &myCurrentP0Mask[hpos]; @@ -1315,10 +772,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Player 1 is enabled - case myP1Bit: - case myP1Bit | ScoreBit: - case myP1Bit | PriorityBit: - case myP1Bit | ScoreBit | PriorityBit: + case P1Bit: + case P1Bit | ScoreBit: + case P1Bit | PriorityBit: + case P1Bit | ScoreBit | PriorityBit: { uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1339,10 +796,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Player 0 and 1 are enabled - case myP0Bit | myP1Bit: - case myP0Bit | myP1Bit | ScoreBit: - case myP0Bit | myP1Bit | PriorityBit: - case myP0Bit | myP1Bit | ScoreBit | PriorityBit: + case P0Bit | P1Bit: + case P0Bit | P1Bit | ScoreBit: + case P0Bit | P1Bit | PriorityBit: + case P0Bit | P1Bit | ScoreBit | PriorityBit: { uInt8* mP0 = &myCurrentP0Mask[hpos]; uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1361,7 +818,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) myCOLUP0 : ((myCurrentGRP1 & *mP1) ? myCOLUP1 : myCOLUBK); if((myCurrentGRP0 & *mP0) && (myCurrentGRP1 & *mP1)) - myCollision |= ourCollisionTable[myP0Bit | myP1Bit]; + myCollision |= TIATables::CollisionTable[P0Bit | P1Bit]; ++mP0; ++mP1; ++myFramePointer; } @@ -1370,10 +827,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Missle 0 is enabled - case myM0Bit: - case myM0Bit | ScoreBit: - case myM0Bit | PriorityBit: - case myM0Bit | ScoreBit | PriorityBit: + case M0Bit: + case M0Bit | ScoreBit: + case M0Bit | PriorityBit: + case M0Bit | ScoreBit | PriorityBit: { uInt8* mM0 = &myCurrentM0Mask[hpos]; @@ -1394,10 +851,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Missle 1 is enabled - case myM1Bit: - case myM1Bit | ScoreBit: - case myM1Bit | PriorityBit: - case myM1Bit | ScoreBit | PriorityBit: + case M1Bit: + case M1Bit | ScoreBit: + case M1Bit | PriorityBit: + case M1Bit | ScoreBit | PriorityBit: { uInt8* mM1 = &myCurrentM1Mask[hpos]; @@ -1418,10 +875,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball is enabled - case myBLBit: - case myBLBit | ScoreBit: - case myBLBit | PriorityBit: - case myBLBit | ScoreBit | PriorityBit: + case BLBit: + case BLBit | ScoreBit: + case BLBit | PriorityBit: + case BLBit | ScoreBit | PriorityBit: { uInt8* mBL = &myCurrentBLMask[hpos]; @@ -1442,10 +899,10 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Missle 0 and 1 are enabled - case myM0Bit | myM1Bit: - case myM0Bit | myM1Bit | ScoreBit: - case myM0Bit | myM1Bit | PriorityBit: - case myM0Bit | myM1Bit | ScoreBit | PriorityBit: + case M0Bit | M1Bit: + case M0Bit | M1Bit | ScoreBit: + case M0Bit | M1Bit | PriorityBit: + case M0Bit | M1Bit | ScoreBit | PriorityBit: { uInt8* mM0 = &myCurrentM0Mask[hpos]; uInt8* mM1 = &myCurrentM1Mask[hpos]; @@ -1462,7 +919,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = *mM0 ? myCOLUP0 : (*mM1 ? myCOLUP1 : myCOLUBK); if(*mM0 && *mM1) - myCollision |= ourCollisionTable[myM0Bit | myM1Bit]; + myCollision |= TIATables::CollisionTable[M0Bit | M1Bit]; ++mM0; ++mM1; ++myFramePointer; } @@ -1471,8 +928,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Missle 0 are enabled and playfield priority is not set - case myBLBit | myM0Bit: - case myBLBit | myM0Bit | ScoreBit: + case BLBit | M0Bit: + case BLBit | M0Bit | ScoreBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mM0 = &myCurrentM0Mask[hpos]; @@ -1489,7 +946,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = (*mM0 ? myCOLUP0 : (*mBL ? myCOLUPF : myCOLUBK)); if(*mBL && *mM0) - myCollision |= ourCollisionTable[myBLBit | myM0Bit]; + myCollision |= TIATables::CollisionTable[BLBit | M0Bit]; ++mBL; ++mM0; ++myFramePointer; } @@ -1498,8 +955,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Missle 0 are enabled and playfield priority is set - case myBLBit | myM0Bit | PriorityBit: - case myBLBit | myM0Bit | ScoreBit | PriorityBit: + case BLBit | M0Bit | PriorityBit: + case BLBit | M0Bit | ScoreBit | PriorityBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mM0 = &myCurrentM0Mask[hpos]; @@ -1516,7 +973,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = (*mBL ? myCOLUPF : (*mM0 ? myCOLUP0 : myCOLUBK)); if(*mBL && *mM0) - myCollision |= ourCollisionTable[myBLBit | myM0Bit]; + myCollision |= TIATables::CollisionTable[BLBit | M0Bit]; ++mBL; ++mM0; ++myFramePointer; } @@ -1525,8 +982,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Missle 1 are enabled and playfield priority is not set - case myBLBit | myM1Bit: - case myBLBit | myM1Bit | ScoreBit: + case BLBit | M1Bit: + case BLBit | M1Bit | ScoreBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mM1 = &myCurrentM1Mask[hpos]; @@ -1544,7 +1001,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = (*mM1 ? myCOLUP1 : (*mBL ? myCOLUPF : myCOLUBK)); if(*mBL && *mM1) - myCollision |= ourCollisionTable[myBLBit | myM1Bit]; + myCollision |= TIATables::CollisionTable[BLBit | M1Bit]; ++mBL; ++mM1; ++myFramePointer; } @@ -1553,8 +1010,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Missle 1 are enabled and playfield priority is set - case myBLBit | myM1Bit | PriorityBit: - case myBLBit | myM1Bit | ScoreBit | PriorityBit: + case BLBit | M1Bit | PriorityBit: + case BLBit | M1Bit | ScoreBit | PriorityBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mM1 = &myCurrentM1Mask[hpos]; @@ -1572,7 +1029,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = (*mBL ? myCOLUPF : (*mM1 ? myCOLUP1 : myCOLUBK)); if(*mBL && *mM1) - myCollision |= ourCollisionTable[myBLBit | myM1Bit]; + myCollision |= TIATables::CollisionTable[BLBit | M1Bit]; ++mBL; ++mM1; ++myFramePointer; } @@ -1581,8 +1038,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Player 1 are enabled and playfield priority is not set - case myBLBit | myP1Bit: - case myBLBit | myP1Bit | ScoreBit: + case BLBit | P1Bit: + case BLBit | P1Bit | ScoreBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1600,7 +1057,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) (*mBL ? myCOLUPF : myCOLUBK); if(*mBL && (myCurrentGRP1 & *mP1)) - myCollision |= ourCollisionTable[myBLBit | myP1Bit]; + myCollision |= TIATables::CollisionTable[BLBit | P1Bit]; ++mBL; ++mP1; ++myFramePointer; } @@ -1609,8 +1066,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Ball and Player 1 are enabled and playfield priority is set - case myBLBit | myP1Bit | PriorityBit: - case myBLBit | myP1Bit | PriorityBit | ScoreBit: + case BLBit | P1Bit | PriorityBit: + case BLBit | P1Bit | PriorityBit | ScoreBit: { uInt8* mBL = &myCurrentBLMask[hpos]; uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1628,7 +1085,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) ((myCurrentGRP1 & *mP1) ? myCOLUP1 : myCOLUBK); if(*mBL && (myCurrentGRP1 & *mP1)) - myCollision |= ourCollisionTable[myBLBit | myP1Bit]; + myCollision |= TIATables::CollisionTable[BLBit | P1Bit]; ++mBL; ++mP1; ++myFramePointer; } @@ -1637,7 +1094,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield and Player 0 are enabled and playfield priority is not set - case myPFBit | myP0Bit: + case PFBit | P0Bit: { uInt32* mPF = &myCurrentPFMask[hpos]; uInt8* mP0 = &myCurrentP0Mask[hpos]; @@ -1655,7 +1112,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) myCOLUP0 : ((myPF & *mPF) ? myCOLUPF : myCOLUBK); if((myPF & *mPF) && (myCurrentGRP0 & *mP0)) - myCollision |= ourCollisionTable[myPFBit | myP0Bit]; + myCollision |= TIATables::CollisionTable[PFBit | P0Bit]; ++mPF; ++mP0; ++myFramePointer; } @@ -1665,7 +1122,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield and Player 0 are enabled and playfield priority is set - case myPFBit | myP0Bit | PriorityBit: + case PFBit | P0Bit | PriorityBit: { uInt32* mPF = &myCurrentPFMask[hpos]; uInt8* mP0 = &myCurrentP0Mask[hpos]; @@ -1683,7 +1140,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) ((myCurrentGRP0 & *mP0) ? myCOLUP0 : myCOLUBK); if((myPF & *mPF) && (myCurrentGRP0 & *mP0)) - myCollision |= ourCollisionTable[myPFBit | myP0Bit]; + myCollision |= TIATables::CollisionTable[PFBit | P0Bit]; ++mPF; ++mP0; ++myFramePointer; } @@ -1693,7 +1150,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield and Player 1 are enabled and playfield priority is not set - case myPFBit | myP1Bit: + case PFBit | P1Bit: { uInt32* mPF = &myCurrentPFMask[hpos]; uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1711,7 +1168,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) myCOLUP1 : ((myPF & *mPF) ? myCOLUPF : myCOLUBK); if((myPF & *mPF) && (myCurrentGRP1 & *mP1)) - myCollision |= ourCollisionTable[myPFBit | myP1Bit]; + myCollision |= TIATables::CollisionTable[PFBit | P1Bit]; ++mPF; ++mP1; ++myFramePointer; } @@ -1721,7 +1178,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield and Player 1 are enabled and playfield priority is set - case myPFBit | myP1Bit | PriorityBit: + case PFBit | P1Bit | PriorityBit: { uInt32* mPF = &myCurrentPFMask[hpos]; uInt8* mP1 = &myCurrentP1Mask[hpos]; @@ -1739,7 +1196,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) ((myCurrentGRP1 & *mP1) ? myCOLUP1 : myCOLUBK); if((myPF & *mPF) && (myCurrentGRP1 & *mP1)) - myCollision |= ourCollisionTable[myPFBit | myP1Bit]; + myCollision |= TIATables::CollisionTable[PFBit | P1Bit]; ++mPF; ++mP1; ++myFramePointer; } @@ -1749,8 +1206,8 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // Playfield and Ball are enabled - case myPFBit | myBLBit: - case myPFBit | myBLBit | PriorityBit: + case PFBit | BLBit: + case PFBit | BLBit | PriorityBit: { uInt32* mPF = &myCurrentPFMask[hpos]; uInt8* mBL = &myCurrentBLMask[hpos]; @@ -1767,7 +1224,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) *myFramePointer = ((myPF & *mPF) || *mBL) ? myCOLUPF : myCOLUBK; if((myPF & *mPF) && *mBL) - myCollision |= ourCollisionTable[myPFBit | myBLBit]; + myCollision |= TIATables::CollisionTable[PFBit | BLBit]; ++mPF; ++mBL; ++myFramePointer; } @@ -1780,24 +1237,24 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) { for(; myFramePointer < ending; ++myFramePointer, ++hpos) { - uInt8 enabled = (myPF & myCurrentPFMask[hpos]) ? myPFBit : 0; + uInt8 enabled = (myPF & myCurrentPFMask[hpos]) ? PFBit : 0; - if((myEnabledObjects & myBLBit) && myCurrentBLMask[hpos]) - enabled |= myBLBit; + if((myEnabledObjects & BLBit) && myCurrentBLMask[hpos]) + enabled |= BLBit; if(myCurrentGRP1 & myCurrentP1Mask[hpos]) - enabled |= myP1Bit; + enabled |= P1Bit; - if((myEnabledObjects & myM1Bit) && myCurrentM1Mask[hpos]) - enabled |= myM1Bit; + if((myEnabledObjects & M1Bit) && myCurrentM1Mask[hpos]) + enabled |= M1Bit; if(myCurrentGRP0 & myCurrentP0Mask[hpos]) - enabled |= myP0Bit; + enabled |= P0Bit; - if((myEnabledObjects & myM0Bit) && myCurrentM0Mask[hpos]) - enabled |= myM0Bit; + if((myEnabledObjects & M0Bit) && myCurrentM0Mask[hpos]) + enabled |= M0Bit; - myCollision |= ourCollisionTable[enabled]; + myCollision |= TIATables::CollisionTable[enabled]; *myFramePointer = myColor[myPriorityEncoder[hpos < 80 ? 0 : 1] [enabled | myPlayfieldPriorityAndScore]]; } @@ -1809,7 +1266,7 @@ inline void TIA::updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -inline void TIA::updateFrame(Int32 clock) +void TIA::updateFrame(Int32 clock) { // See if we're in the nondisplayable portion of the screen or if // we've already updated this portion of the screen @@ -1851,7 +1308,7 @@ inline void TIA::updateFrame(Int32 clock) myClockAtLastUpdate = clock; } - Int32 startOfScanLine = HBLANK + myFrameXStart; + Int32 startOfScanLine = HBLANK; // Skip over as many horizontal blank clocks as we can if(clocksFromStartOfScanLine < startOfScanLine) @@ -1892,19 +1349,18 @@ inline void TIA::updateFrame(Int32 clock) // 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]; + myCurrentPFMask = TIATables::PlayfieldTable[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] + myCurrentP0Mask = &TIATables::PlayerMaskTable[myPOSP0 & 0x03] [0][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)]; - myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03] + myCurrentP1Mask = &TIATables::PlayerMaskTable[myPOSP1 & 0x03] [0][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)]; +#ifndef NO_HMOVE_FIXES // Handle the "Cosmic Ark" TIA bug if it's enabled if(myM0CosmicArkMotionEnabled) { @@ -1922,21 +1378,22 @@ inline void TIA::updateFrame(Int32 clock) if(myM0CosmicArkCounter == 1) { // Stretch this missle so it's at least 2 pixels wide - myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03] + myCurrentM0Mask = &TIATables::MissleMaskTable[myPOSM0 & 0x03] [myNUSIZ0 & 0x07][((myNUSIZ0 & 0x30) >> 4) | 0x01] [160 - (myPOSM0 & 0xFC)]; } else if(myM0CosmicArkCounter == 2) { // Missle is disabled on this line - myCurrentM0Mask = &ourDisabledMaskTable[0]; + myCurrentM0Mask = &TIATables::DisabledMaskTable[0]; } else { - myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03] + myCurrentM0Mask = &TIATables::MissleMaskTable[myPOSM0 & 0x03] [myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)]; } - } + } +#endif } } while(myClockAtLastUpdate < clock); @@ -1991,16 +1448,13 @@ inline uInt8 TIA::dumpedInputPort(int resistance) } else { - uInt32 needed = (uInt32) (1.6 * resistance * 0.01e-6 * - myScanlineCountForLastFrame * 228 * myFramerate / 3); + // Constant here is derived from '1.6 * 0.01e-6 * 228 / 3' + uInt32 needed = (uInt32) + (1.216e-6 * resistance * myScanlineCountForLastFrame * myFramerate); if((mySystem->cycles() - myDumpDisabledCycle) > needed) - { return 0x80; - } else - { return 0x00; - } } return 0x00; } @@ -2013,71 +1467,71 @@ uInt8 TIA::peek(uInt16 addr) // Update frame to current color clock before we look at anything! updateFrame(mySystem->cycles() * 3); - uInt8 data = 0x00; + uInt8 value = 0x00; switch(addr & 0x000f) { case CXM0P: - data = ((myCollision & 0x0001) ? 0x80 : 0x00) | - ((myCollision & 0x0002) ? 0x40 : 0x00); + value = ((myCollision & 0x0001) ? 0x80 : 0x00) | + ((myCollision & 0x0002) ? 0x40 : 0x00); break; case CXM1P: - data = ((myCollision & 0x0004) ? 0x80 : 0x00) | - ((myCollision & 0x0008) ? 0x40 : 0x00); + value = ((myCollision & 0x0004) ? 0x80 : 0x00) | + ((myCollision & 0x0008) ? 0x40 : 0x00); break; case CXP0FB: - data = ((myCollision & 0x0010) ? 0x80 : 0x00) | - ((myCollision & 0x0020) ? 0x40 : 0x00); + value = ((myCollision & 0x0010) ? 0x80 : 0x00) | + ((myCollision & 0x0020) ? 0x40 : 0x00); break; case CXP1FB: - data = ((myCollision & 0x0040) ? 0x80 : 0x00) | - ((myCollision & 0x0080) ? 0x40 : 0x00); + value = ((myCollision & 0x0040) ? 0x80 : 0x00) | + ((myCollision & 0x0080) ? 0x40 : 0x00); break; case CXM0FB: - data = ((myCollision & 0x0100) ? 0x80 : 0x00) | - ((myCollision & 0x0200) ? 0x40 : 0x00); + value = ((myCollision & 0x0100) ? 0x80 : 0x00) | + ((myCollision & 0x0200) ? 0x40 : 0x00); break; case CXM1FB: - data = ((myCollision & 0x0400) ? 0x80 : 0x00) | - ((myCollision & 0x0800) ? 0x40 : 0x00); + value = ((myCollision & 0x0400) ? 0x80 : 0x00) | + ((myCollision & 0x0800) ? 0x40 : 0x00); break; case CXBLPF: - data = (myCollision & 0x1000) ? 0x80 : 0x00; + value = (myCollision & 0x1000) ? 0x80 : 0x00; break; case CXPPMM: - data = ((myCollision & 0x2000) ? 0x80 : 0x00) | - ((myCollision & 0x4000) ? 0x40 : 0x00); + value = ((myCollision & 0x2000) ? 0x80 : 0x00) | + ((myCollision & 0x4000) ? 0x40 : 0x00); break; case INPT0: - data = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Nine)); + value = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Nine)); break; case INPT1: - data = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Five)); + value = dumpedInputPort(myConsole.controller(Controller::Left).read(Controller::Five)); break; case INPT2: - data = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Nine)); + value = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Nine)); break; case INPT3: - data = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Five)); + value = dumpedInputPort(myConsole.controller(Controller::Right).read(Controller::Five)); break; case INPT4: - data = myConsole.controller(Controller::Left).read(Controller::Six) ? 0x80 : 0x00; + value = myConsole.controller(Controller::Left).read(Controller::Six) ? 0x80 : 0x00; break; case INPT5: - data = myConsole.controller(Controller::Right).read(Controller::Six) ? 0x80 : 0x00; + value = myConsole.controller(Controller::Right).read(Controller::Six) ? 0x80 : 0x00; break; case 0x0e: // TODO - document this address @@ -2088,9 +1542,9 @@ uInt8 TIA::peek(uInt16 addr) // On certain CMOS EPROM chips the unused TIA pins on a read are not // floating but pulled high. Programmers might want to check their // games for compatibility, so we make this optional. - data |= myFloatTIAOutputPins ? (mySystem->getDataBusState() & 0x3F) : 0x3F; + value |= myFloatTIAOutputPins ? (mySystem->getDataBusState() & 0x3F) : 0x3F; - return data; + return value; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -2099,7 +1553,7 @@ void TIA::poke(uInt16 addr, uInt8 value) addr = addr & 0x003f; Int32 clock = mySystem->cycles() * 3; - Int16 delay = ourPokeDelayTable[addr]; + Int16 delay = TIATables::PokeDelayTable[addr]; // See if this is a poke to a PF register if(delay == -1) @@ -2193,10 +1647,10 @@ void TIA::poke(uInt16 addr, uInt8 value) // TODO: Technically the "enable" part, [0], should depend on the current // enabled or disabled state. This mean we probably need a data member // to maintain that state (01/21/99). - myCurrentP0Mask = &ourPlayerMaskTable[myPOSP0 & 0x03] + myCurrentP0Mask = &TIATables::PlayerMaskTable[myPOSP0 & 0x03] [0][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)]; - myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03] + myCurrentM0Mask = &TIATables::MissleMaskTable[myPOSM0 & 0x03] [myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)]; break; @@ -2209,10 +1663,10 @@ void TIA::poke(uInt16 addr, uInt8 value) // TODO: Technically the "enable" part, [0], should depend on the current // enabled or disabled state. This mean we probably need a data member // to maintain that state (01/21/99). - myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03] + myCurrentP1Mask = &TIATables::PlayerMaskTable[myPOSP1 & 0x03] [0][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)]; - myCurrentM1Mask = &ourMissleMaskTable[myPOSM1 & 0x03] + myCurrentM1Mask = &TIATables::MissleMaskTable[myPOSM1 & 0x03] [myNUSIZ1 & 0x07][(myNUSIZ1 & 0x30) >> 4][160 - (myPOSM1 & 0xFC)]; break; @@ -2275,10 +1729,10 @@ void TIA::poke(uInt16 addr, uInt8 value) // we're still on the left hand side of the playfield if(((clock - myClockWhenFrameStarted) % 228) < (68 + 79)) { - myCurrentPFMask = ourPlayfieldTable[myCTRLPF & 0x01]; + myCurrentPFMask = TIATables::PlayfieldTable[myCTRLPF & 0x01]; } - myCurrentBLMask = &ourBallMaskTable[myPOSBL & 0x03] + myCurrentBLMask = &TIATables::BallMaskTable[myPOSBL & 0x03] [(myCTRLPF & 0x30) >> 4][160 - (myPOSBL & 0xFC)]; break; @@ -2290,7 +1744,7 @@ void TIA::poke(uInt16 addr, uInt8 value) if(((value & 0x08) && !myREFP0) || (!(value & 0x08) && myREFP0)) { myREFP0 = (value & 0x08); - myCurrentGRP0 = ourPlayerReflectTable[myCurrentGRP0]; + myCurrentGRP0 = TIATables::PlayerReflectTable[myCurrentGRP0]; } break; } @@ -2301,7 +1755,7 @@ void TIA::poke(uInt16 addr, uInt8 value) if(((value & 0x08) && !myREFP1) || (!(value & 0x08) && myREFP1)) { myREFP1 = (value & 0x08); - myCurrentGRP1 = ourPlayerReflectTable[myCurrentGRP1]; + myCurrentGRP1 = TIATables::PlayerReflectTable[myCurrentGRP1]; } break; } @@ -2310,10 +1764,10 @@ void TIA::poke(uInt16 addr, uInt8 value) { myPF = (myPF & 0x000FFFF0) | ((value >> 4) & 0x0F); - if(!myBitEnabled[TIA::PF] || myPF == 0) - myEnabledObjects &= ~myPFBit; + if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0) + myEnabledObjects &= ~PFBit; else - myEnabledObjects |= myPFBit; + myEnabledObjects |= PFBit; break; } @@ -2322,10 +1776,10 @@ void TIA::poke(uInt16 addr, uInt8 value) { myPF = (myPF & 0x000FF00F) | ((uInt32)value << 4); - if(!myBitEnabled[TIA::PF] || myPF == 0) - myEnabledObjects &= ~myPFBit; + if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0) + myEnabledObjects &= ~PFBit; else - myEnabledObjects |= myPFBit; + myEnabledObjects |= PFBit; break; } @@ -2334,10 +1788,10 @@ void TIA::poke(uInt16 addr, uInt8 value) { myPF = (myPF & 0x00000FFF) | ((uInt32)value << 12); - if(!myBitEnabled[TIA::PF] || myPF == 0) - myEnabledObjects &= ~myPFBit; + if(myBitEnabled[TIA::PF] == 0x00 || myPF == 0) + myEnabledObjects &= ~PFBit; else - myEnabledObjects |= myPFBit; + myEnabledObjects |= PFBit; break; } @@ -2348,7 +1802,7 @@ void TIA::poke(uInt16 addr, uInt8 value) Int32 newx = hpos < HBLANK ? 3 : (((hpos - HBLANK) + 5) % 160); // Find out under what condition the player is being reset - Int8 when = ourPlayerPositionResetWhenTable[myNUSIZ0 & 7][myPOSP0][newx]; + Int8 when = TIATables::PlayerPositionResetWhenTable[myNUSIZ0 & 7][myPOSP0][newx]; #ifdef DEBUG_HMOVE if((clock - myLastHMOVEClock) < (24 * 3)) @@ -2369,7 +1823,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP0 = newx; // Setup the mask to skip the first copy of the player - myCurrentP0Mask = &ourPlayerMaskTable[myPOSP0 & 0x03] + myCurrentP0Mask = &TIATables::PlayerMaskTable[myPOSP0 & 0x03] [1][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)]; } // Player is being reset in neither the delay nor display section @@ -2378,7 +1832,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP0 = newx; // So we setup the mask to skip the first copy of the player - myCurrentP0Mask = &ourPlayerMaskTable[myPOSP0 & 0x03] + myCurrentP0Mask = &TIATables::PlayerMaskTable[myPOSP0 & 0x03] [1][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)]; } // Player is being reset during the delay section of one of its copies @@ -2387,7 +1841,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP0 = newx; // So we setup the mask to display all copies of the player - myCurrentP0Mask = &ourPlayerMaskTable[myPOSP0 & 0x03] + myCurrentP0Mask = &TIATables::PlayerMaskTable[myPOSP0 & 0x03] [0][myNUSIZ0 & 0x07][160 - (myPOSP0 & 0xFC)]; } break; @@ -2399,7 +1853,7 @@ void TIA::poke(uInt16 addr, uInt8 value) Int32 newx = hpos < HBLANK ? 3 : (((hpos - HBLANK) + 5) % 160); // Find out under what condition the player is being reset - Int8 when = ourPlayerPositionResetWhenTable[myNUSIZ1 & 7][myPOSP1][newx]; + Int8 when = TIATables::PlayerPositionResetWhenTable[myNUSIZ1 & 7][myPOSP1][newx]; #ifdef DEBUG_HMOVE if((clock - myLastHMOVEClock) < (24 * 3)) @@ -2420,7 +1874,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP1 = newx; // Setup the mask to skip the first copy of the player - myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03] + myCurrentP1Mask = &TIATables::PlayerMaskTable[myPOSP1 & 0x03] [1][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)]; } // Player is being reset in neither the delay nor display section @@ -2429,7 +1883,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP1 = newx; // So we setup the mask to skip the first copy of the player - myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03] + myCurrentP1Mask = &TIATables::PlayerMaskTable[myPOSP1 & 0x03] [1][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)]; } // Player is being reset during the delay section of one of its copies @@ -2438,7 +1892,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSP1 = newx; // So we setup the mask to display all copies of the player - myCurrentP1Mask = &ourPlayerMaskTable[myPOSP1 & 0x03] + myCurrentP1Mask = &TIATables::PlayerMaskTable[myPOSP1 & 0x03] [0][myNUSIZ1 & 0x07][160 - (myPOSP1 & 0xFC)]; } break; @@ -2472,7 +1926,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSM0 = 8; } #endif - myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03] + myCurrentM0Mask = &TIATables::MissleMaskTable[myPOSM0 & 0x03] [myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)]; break; } @@ -2498,7 +1952,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSM1 = 3; } #endif - myCurrentM1Mask = &ourMissleMaskTable[myPOSM1 & 0x03] + myCurrentM1Mask = &TIATables::MissleMaskTable[myPOSM1 & 0x03] [myNUSIZ1 & 0x07][(myNUSIZ1 & 0x30) >> 4][160 - (myPOSM1 & 0xFC)]; break; } @@ -2570,7 +2024,7 @@ void TIA::poke(uInt16 addr, uInt8 value) myPOSBL = 8; } #endif - myCurrentBLMask = &ourBallMaskTable[myPOSBL & 0x03] + myCurrentBLMask = &TIATables::BallMaskTable[myPOSBL & 0x03] [(myCTRLPF & 0x30) >> 4][160 - (myPOSBL & 0xFC)]; break; } @@ -2620,29 +2074,29 @@ void TIA::poke(uInt16 addr, uInt8 value) case GRP0: // Graphics Player 0 { // Set player 0 graphics - myGRP0 = (myBitEnabled[TIA::P0] ? value : 0); + myGRP0 = value & myBitEnabled[TIA::P0]; // Copy player 1 graphics into its delayed register myDGRP1 = myGRP1; // Get the "current" data for GRP0 base on delay register and reflect uInt8 grp0 = myVDELP0 ? myDGRP0 : myGRP0; - myCurrentGRP0 = myREFP0 ? ourPlayerReflectTable[grp0] : grp0; + myCurrentGRP0 = myREFP0 ? TIATables::PlayerReflectTable[grp0] : grp0; // Get the "current" data for GRP1 base on delay register and reflect uInt8 grp1 = myVDELP1 ? myDGRP1 : myGRP1; - myCurrentGRP1 = myREFP1 ? ourPlayerReflectTable[grp1] : grp1; + myCurrentGRP1 = myREFP1 ? TIATables::PlayerReflectTable[grp1] : grp1; // Set enabled object bits if(myCurrentGRP0 != 0) - myEnabledObjects |= myP0Bit; + myEnabledObjects |= P0Bit; else - myEnabledObjects &= ~myP0Bit; + myEnabledObjects &= ~P0Bit; if(myCurrentGRP1 != 0) - myEnabledObjects |= myP1Bit; + myEnabledObjects |= P1Bit; else - myEnabledObjects &= ~myP1Bit; + myEnabledObjects &= ~P1Bit; break; } @@ -2650,7 +2104,7 @@ void TIA::poke(uInt16 addr, uInt8 value) case GRP1: // Graphics Player 1 { // Set player 1 graphics - myGRP1 = (myBitEnabled[TIA::P1] ? value : 0); + myGRP1 = value & myBitEnabled[TIA::P1]; // Copy player 0 graphics into its delayed register myDGRP0 = myGRP0; @@ -2660,61 +2114,61 @@ void TIA::poke(uInt16 addr, uInt8 value) // Get the "current" data for GRP0 base on delay register uInt8 grp0 = myVDELP0 ? myDGRP0 : myGRP0; - myCurrentGRP0 = myREFP0 ? ourPlayerReflectTable[grp0] : grp0; + myCurrentGRP0 = myREFP0 ? TIATables::PlayerReflectTable[grp0] : grp0; // Get the "current" data for GRP1 base on delay register uInt8 grp1 = myVDELP1 ? myDGRP1 : myGRP1; - myCurrentGRP1 = myREFP1 ? ourPlayerReflectTable[grp1] : grp1; + myCurrentGRP1 = myREFP1 ? TIATables::PlayerReflectTable[grp1] : grp1; // Set enabled object bits if(myCurrentGRP0 != 0) - myEnabledObjects |= myP0Bit; + myEnabledObjects |= P0Bit; else - myEnabledObjects &= ~myP0Bit; + myEnabledObjects &= ~P0Bit; if(myCurrentGRP1 != 0) - myEnabledObjects |= myP1Bit; + myEnabledObjects |= P1Bit; else - myEnabledObjects &= ~myP1Bit; + myEnabledObjects &= ~P1Bit; if(myVDELBL ? myDENABL : myENABL) - myEnabledObjects |= myBLBit; + myEnabledObjects |= BLBit; else - myEnabledObjects &= ~myBLBit; + myEnabledObjects &= ~BLBit; break; } case ENAM0: // Enable Missile 0 graphics { - myENAM0 = (myBitEnabled[TIA::M0] ? value & 0x02 : 0); + myENAM0 = (value & 0x02) & myBitEnabled[TIA::M0]; if(myENAM0 && !myRESMP0) - myEnabledObjects |= myM0Bit; + myEnabledObjects |= M0Bit; else - myEnabledObjects &= ~myM0Bit; + myEnabledObjects &= ~M0Bit; break; } case ENAM1: // Enable Missile 1 graphics { - myENAM1 = (myBitEnabled[TIA::M1] ? value & 0x02 : 0); + myENAM1 = (value & 0x02) & myBitEnabled[TIA::M1]; if(myENAM1 && !myRESMP1) - myEnabledObjects |= myM1Bit; + myEnabledObjects |= M1Bit; else - myEnabledObjects &= ~myM1Bit; + myEnabledObjects &= ~M1Bit; break; } case ENABL: // Enable Ball graphics { - myENABL = (myBitEnabled[TIA::BL] ? value & 0x02 : 0); + myENABL = (value & 0x02) & myBitEnabled[TIA::BL]; if(myVDELBL ? myDENABL : myENABL) - myEnabledObjects |= myBLBit; + myEnabledObjects |= BLBit; else - myEnabledObjects &= ~myBLBit; + myEnabledObjects &= ~BLBit; break; } @@ -2735,13 +2189,14 @@ void TIA::poke(uInt16 addr, uInt8 value) { Int8 tmp = value >> 4; +#ifndef NO_HMOVE_FIXES // Should we enabled TIA M0 "bug" used for stars in Cosmic Ark? if((clock == (myLastHMOVEClock + 21 * 3)) && (myHMM0 == 7) && (tmp == 6)) { myM0CosmicArkMotionEnabled = true; myM0CosmicArkCounter = 0; } - +#endif myHMM0 = tmp; break; } @@ -2763,12 +2218,12 @@ void TIA::poke(uInt16 addr, uInt8 value) myVDELP0 = value & 0x01; uInt8 grp0 = myVDELP0 ? myDGRP0 : myGRP0; - myCurrentGRP0 = myREFP0 ? ourPlayerReflectTable[grp0] : grp0; + myCurrentGRP0 = myREFP0 ? TIATables::PlayerReflectTable[grp0] : grp0; if(myCurrentGRP0 != 0) - myEnabledObjects |= myP0Bit; + myEnabledObjects |= P0Bit; else - myEnabledObjects &= ~myP0Bit; + myEnabledObjects &= ~P0Bit; break; } @@ -2777,12 +2232,12 @@ void TIA::poke(uInt16 addr, uInt8 value) myVDELP1 = value & 0x01; uInt8 grp1 = myVDELP1 ? myDGRP1 : myGRP1; - myCurrentGRP1 = myREFP1 ? ourPlayerReflectTable[grp1] : grp1; + myCurrentGRP1 = myREFP1 ? TIATables::PlayerReflectTable[grp1] : grp1; if(myCurrentGRP1 != 0) - myEnabledObjects |= myP1Bit; + myEnabledObjects |= P1Bit; else - myEnabledObjects &= ~myP1Bit; + myEnabledObjects &= ~P1Bit; break; } @@ -2791,9 +2246,9 @@ void TIA::poke(uInt16 addr, uInt8 value) myVDELBL = value & 0x01; if(myVDELBL ? myDENABL : myENABL) - myEnabledObjects |= myBLBit; + myEnabledObjects |= BLBit; else - myEnabledObjects &= ~myBLBit; + myEnabledObjects &= ~BLBit; break; } @@ -2811,16 +2266,16 @@ void TIA::poke(uInt16 addr, uInt8 value) middle = 4; myPOSM0 = (myPOSP0 + middle) % 160; - myCurrentM0Mask = &ourMissleMaskTable[myPOSM0 & 0x03] + myCurrentM0Mask = &TIATables::MissleMaskTable[myPOSM0 & 0x03] [myNUSIZ0 & 0x07][(myNUSIZ0 & 0x30) >> 4][160 - (myPOSM0 & 0xFC)]; } myRESMP0 = value & 0x02; if(myENAM0 && !myRESMP0) - myEnabledObjects |= myM0Bit; + myEnabledObjects |= M0Bit; else - myEnabledObjects &= ~myM0Bit; + myEnabledObjects &= ~M0Bit; break; } @@ -2839,16 +2294,16 @@ void TIA::poke(uInt16 addr, uInt8 value) middle = 4; myPOSM1 = (myPOSP1 + middle) % 160; - myCurrentM1Mask = &ourMissleMaskTable[myPOSM1 & 0x03] + myCurrentM1Mask = &TIATables::MissleMaskTable[myPOSM1 & 0x03] [myNUSIZ1 & 0x07][(myNUSIZ1 & 0x30) >> 4][160 - (myPOSM1 & 0xFC)]; } myRESMP1 = value & 0x02; if(myENAM1 && !myRESMP1) - myEnabledObjects |= myM1Bit; + myEnabledObjects |= M1Bit; else - myEnabledObjects &= ~myM1Bit; + myEnabledObjects &= ~M1Bit; break; } @@ -2942,139 +2397,15 @@ void TIA::poke(uInt16 addr, uInt8 value) } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::ourBallMaskTable[4][4][320]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 TIA::ourCollisionTable[64]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::ourDisabledMaskTable[640]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const Int16 TIA::ourPokeDelayTable[64] = { - 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, 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, 0, 0, 0, 0, 0, -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::ourMissleMaskTable[4][8][4][320]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const bool TIA::ourHMOVEBlankEnableCycles[76] = { - true, true, true, true, true, true, true, true, true, true, // 00 - true, true, true, true, true, true, true, true, true, true, // 10 - true, false, false, false, false, false, false, false, false, false, // 20 - false, false, false, false, false, false, false, false, false, false, // 30 - false, false, false, false, false, false, false, false, false, false, // 40 - false, false, false, false, false, false, false, false, false, false, // 50 - false, false, false, false, false, false, false, false, false, false, // 60 - false, false, false, false, false, true // 70 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const Int32 TIA::ourCompleteMotionTable[76][16] = { - { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -6, -6, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -5, -5, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -5, -5, -5, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -4, -4, -4, -4, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -3, -3, -3, -3, -3, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -2, -2, -2, -2, -2, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -2, -2, -2, -2, -2, -2, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, -1, -1, -1, -1, -1, -1, -1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 1, 1, 1, 1, 1, 1, 1, 1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 1, 1, 1, 1, 1, 1, 1, 1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK - { 2, 2, 2, 2, 2, 2, 2, 2, 8, 7, 6, 5, 4, 3, 2, 2}, // HBLANK - { 3, 3, 3, 3, 3, 3, 3, 3, 8, 7, 6, 5, 4, 3, 3, 3}, // HBLANK - { 4, 4, 4, 4, 4, 4, 4, 4, 8, 7, 6, 5, 4, 4, 4, 4}, // HBLANK - { 4, 4, 4, 4, 4, 4, 4, 4, 8, 7, 6, 5, 4, 4, 4, 4}, // HBLANK - { 5, 5, 5, 5, 5, 5, 5, 5, 8, 7, 6, 5, 5, 5, 5, 5}, // HBLANK - { 6, 6, 6, 6, 6, 6, 6, 6, 8, 7, 6, 6, 6, 6, 6, 6}, // HBLANK - { 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, 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, 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, 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, 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, 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, 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, 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}, - { 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, 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, 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, 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, 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, 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, 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, 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}, - { 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, 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, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, 0, -1, -2, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, -1, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, 0, -1, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, 0, -1, -2, -3, -4, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, 0, -1, -2, -3, -4, -5, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, -1, -2, -3, -4, -5, -6, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, 0, -1, -2, -3, -4, -5, -6, 0, 0, 0, 0, 0, 0, 0, 0}, - { 0, -1, -2, -3, -4, -5, -6, -7, 0, 0, 0, 0, 0, 0, 0, 0}, - {-1, -2, -3, -4, -5, -6, -7, -8, 0, 0, 0, 0, 0, 0, 0, 0}, - {-2, -3, -4, -5, -6, -7, -8, -9, 0, 0, 0, 0, 0, 0, 0, -1}, - {-2, -3, -4, -5, -6, -7, -8, -9, 0, 0, 0, 0, 0, 0, 0, -1}, - {-3, -4, -5, -6, -7, -8, -9,-10, 0, 0, 0, 0, 0, 0, -1, -2}, - {-4, -5, -6, -7, -8, -9,-10,-11, 0, 0, 0, 0, 0, -1, -2, -3}, - {-5, -6, -7, -8, -9,-10,-11,-12, 0, 0, 0, 0, -1, -2, -3, -4}, - {-5, -6, -7, -8, -9,-10,-11,-12, 0, 0, 0, 0, -1, -2, -3, -4}, - {-6, -7, -8, -9,-10,-11,-12,-13, 0, 0, 0, -1, -2, -3, -4, -5}, - {-7, -8, -9,-10,-11,-12,-13,-14, 0, 0, -1, -2, -3, -4, -5, -6}, - {-8, -9,-10,-11,-12,-13,-14,-15, 0, -1, -2, -3, -4, -5, -6, -7}, - {-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 -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::ourPlayerMaskTable[4][2][8][320]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Int8 TIA::ourPlayerPositionResetWhenTable[8][160][160]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 TIA::ourPlayerReflectTable[256]; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 TIA::ourPlayfieldTable[2][160]; - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TIA::TIA(const TIA& c) - : myConsole(c.myConsole), - mySettings(c.mySettings), - mySound(c.mySound), - myCOLUBK(myColor[0]), - myCOLUPF(myColor[1]), - myCOLUP0(myColor[2]), - myCOLUP1(myColor[3]) + : myConsole(c.myConsole), + mySettings(c.mySettings), + mySound(c.mySound), + myCOLUBK(myColor[0]), + myCOLUPF(myColor[1]), + myCOLUP0(myColor[2]), + myCOLUP1(myColor[3]) { assert(false); } @@ -3083,6 +2414,5 @@ TIA::TIA(const TIA& c) TIA& TIA::operator = (const TIA&) { assert(false); - return *this; } diff --git a/stella/src/emucore/TIA.hxx b/stella/src/emucore/TIA.hxx index d29fc30b6..2b5490f73 100644 --- a/stella/src/emucore/TIA.hxx +++ b/stella/src/emucore/TIA.hxx @@ -13,20 +13,19 @@ // 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.50 2009-01-13 01:18:25 stephena Exp $ +// $Id: TIA.hxx,v 1.51 2009-01-19 16:52:32 stephena Exp $ //============================================================================ #ifndef TIA_HXX #define TIA_HXX class Console; -class System; class Settings; #include "bspf.hxx" #include "Sound.hxx" #include "Device.hxx" -#include "MediaSrc.hxx" +#include "System.hxx" /** This class is a device that emulates the Television Interface Adapator @@ -40,9 +39,9 @@ class Settings; be displayed on screen. @author Bradford W. Mott - @version $Id: TIA.hxx,v 1.50 2009-01-13 01:18:25 stephena Exp $ + @version $Id: TIA.hxx,v 1.51 2009-01-19 16:52:32 stephena Exp $ */ -class TIA : public Device , public MediaSource +class TIA : public Device { public: friend class TIADebug; @@ -64,19 +63,19 @@ class TIA : public Device , public MediaSource /** Reset device to its power-on state */ - virtual void reset(); + void reset(); /** Reset frame to change XStart/YStart/Width/Height properties */ - virtual void frameReset(); + void frameReset(); /** Notification method invoked by the system right before the system resets its cycle counter to zero. It may be necessary to override this method for devices that remember cycle counts. */ - virtual void systemCyclesReset(); + void systemCyclesReset(); /** Install TIA in the specified system. Invoked by the system @@ -84,7 +83,7 @@ class TIA : public Device , public MediaSource @param system The system the device should install itself in */ - virtual void install(System& system); + void install(System& system); /** Install TIA in the specified system and device. Invoked by @@ -95,7 +94,7 @@ class TIA : public Device , public MediaSource @param system The system the device should install itself in @param device The device responsible for this address space */ - virtual void install(System& system, Device& device); + void install(System& system, Device& device); /** Save the current state of this device to the given Serializer. @@ -103,7 +102,7 @@ class TIA : public Device , public MediaSource @param out The Serializer object to use @return False on any errors, else true */ - virtual bool save(Serializer& out) const; + bool save(Serializer& out) const; /** Load the current state of this device from the given Deserializer. @@ -111,22 +110,21 @@ class TIA : public Device , public MediaSource @param in The Deserializer object to use @return False on any errors, else true */ - virtual bool load(Deserializer& in); + bool load(Deserializer& in); /** Get a descriptor for the device name (used in error checking). @return The name of the object */ - virtual string name() const { return "TIA"; } + string name() const { return "TIA"; } - public: /** Get the byte at the specified address @return The byte at the specified address */ - virtual uInt8 peek(uInt16 address); + uInt8 peek(uInt16 address); /** Change the byte at the specified address to the given value @@ -134,14 +132,14 @@ class TIA : public Device , public MediaSource @param address The address where the value should be stored @param value The value to be stored at the address */ - virtual void poke(uInt16 address, uInt8 value); + void poke(uInt16 address, uInt8 value); - public: /** - This method should be called at an interval corresponding to - the desired frame rate to update the media source. + This method should be called at an interval corresponding to the + desired frame rate to update the TIA. Invoking this method will update + the graphics buffer and generate the corresponding audio samples. */ - virtual void update(); + void update(); /** Answers the current frame buffer @@ -158,18 +156,10 @@ class TIA : public Device , public MediaSource uInt8* previousFrameBuffer() const { return myPreviousFrameBuffer; } /** - Answers the height of the frame buffer - - @return The frame's height + Answers the width and height of the frame buffer */ - uInt32 height() const; - - /** - Answers the width of the frame buffer - - @return The frame's width - */ - uInt32 width() const; + inline uInt32 width() const { return myFrameWidth; } + inline uInt32 height() const { return myFrameHeight; } /** Enables/disables auto-frame calculation. If enabled, the TIA @@ -180,26 +170,28 @@ class TIA : public Device , public MediaSource void enableAutoFrame(bool mode) { myAutoFrameEnabled = mode; } /** - Answers the total number of scanlines the media source generated - in producing the current frame buffer. For partial frames, this - will be the current scanline. + Answers the current color clock we've gotten to on this scanline. + + @return The current color clock + */ + inline uInt32 clocksThisLine() const + { return ((mySystem->cycles() * 3) - myClockWhenFrameStarted) % 228; } + + /** + Answers the total number of scanlines the TIA generated in producing + the current frame buffer. For partial frames, this will be the + current scanline. @return The total number of scanlines generated */ - uInt32 scanlines() const; + inline uInt32 scanlines() const + { return ((mySystem->cycles() * 3) - myClockWhenFrameStarted) / 228; } /** Sets the sound device for the TIA. */ void setSound(Sound& sound); - /** - Answers the current color clock we've gotten to on this scanline. - - @return The current color clock - */ - uInt32 clocksThisLine() const; - enum TIABit { P0, // Descriptor for Player 0 Bit P1, // Descriptor for Player 1 Bit @@ -214,64 +206,43 @@ class TIA : public Device , public MediaSource @return Whether the bit was enabled or disabled */ - bool enableBit(TIABit b, bool mode) { myBitEnabled[b] = mode; return mode; } + void enableBit(TIABit b, bool mode) { myBitEnabled[b] = mode ? 0xff : 0x00; } /** Toggles the specified TIA bit. @return Whether the bit was enabled or disabled */ - bool toggleBit(TIABit b) { myBitEnabled[b] = !myBitEnabled[b]; return myBitEnabled[b]; } + bool toggleBit(TIABit b) + { myBitEnabled[b] = myBitEnabled[b] == 0xff ? 0x00 : 0xff; return myBitEnabled[b]; } /** 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; } + void enableBits(bool mode) + { for(uInt8 i = 0; i < 6; ++i) myBitEnabled[i] = mode ? 0xff : 0x00; } #ifdef DEBUGGER_SUPPORT /** - This method should be called to update the media source with - a new scanline. + This method should be called to update the TIA with a new scanline. */ - virtual void updateScanline(); + void updateScanline(); /** - This method should be called to update the media source with - a new partial scanline by stepping one CPU instruction. + This method should be called to update the TIA with a new partial + scanline by stepping one CPU instruction. */ - virtual void updateScanlineByStep(); + void updateScanlineByStep(); /** - This method should be called to update the media source with - a new partial scanline by tracing to target address. + This method should be called to update the TIA with a new partial + scanline by tracing to target address. */ - virtual void updateScanlineByTrace(int target); + void updateScanlineByTrace(int target); #endif - private: - // Compute the ball mask table - void computeBallMaskTable(); - - // Compute the collision decode table - void computeCollisionTable(); - - // Compute the missle mask table - void computeMissleMaskTable(); - - // Compute the player mask table - void computePlayerMaskTable(); - - // Compute the player position reset when table - void computePlayerPositionResetWhenTable(); - - // Compute the player reflect table - void computePlayerReflectTable(); - - // Compute playfield mask table - void computePlayfieldMaskTable(); - private: // Update the current frame buffer up to one scanline void updateFrameScanline(uInt32 clocksToUpdate, uInt32 hpos); @@ -307,20 +278,6 @@ class TIA : public Device , public MediaSource // Sound object the TIA is associated with Sound* mySound; - private: - // Indicates if color loss should be enabled or disabled. Color loss - // occurs on PAL (and maybe SECAM) systems when the previous frame - // 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; - // Pointer to the current frame buffer uInt8* myCurrentFrameBuffer; @@ -330,10 +287,7 @@ class TIA : public Device , public MediaSource // Pointer to the next pixel that will be drawn in the current frame buffer uInt8* myFramePointer; - // Indicates where the scanline should start being displayed - uInt32 myFrameXStart; - - // Indicates the width of the scanline + // Indicates the width of the visible scanline uInt32 myFrameWidth; // Indicated what scanline the frame should start being drawn at @@ -348,7 +302,6 @@ class TIA : public Device , public MediaSource // Indicates offset in color clocks when display should stop uInt32 myStopDisplayOffset; - private: // Indicates color clocks when the current frame began Int32 myClockWhenFrameStarted; @@ -366,6 +319,21 @@ class TIA : public Device , public MediaSource // 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; @@ -378,7 +346,6 @@ class TIA : public Device , public MediaSource // Color clock when VSYNC ending causes a new frame to be started Int32 myVSYNCFinishClock; - private: uInt8 myVSYNC; // Holds the VSYNC register value uInt8 myVBLANK; // Holds the VBLANK register value @@ -389,10 +356,10 @@ class TIA : public Device , public MediaSource uInt32 myColor[4]; uInt8 myPriorityEncoder[2][256]; - uInt32& myCOLUBK; // Background color register (replicated 4 times) - uInt32& myCOLUPF; // Playfield color register (replicated 4 times) - uInt32& myCOLUP0; // Player 0 color register (replicated 4 times) - uInt32& myCOLUP1; // Player 1 color register (replicated 4 times) + uInt32& myCOLUBK; // Background color register (replicated 4 times) + uInt32& myCOLUPF; // Playfield color register (replicated 4 times) + uInt32& myCOLUP0; // Player 0 color register (replicated 4 times) + uInt32& myCOLUP1; // Player 1 color register (replicated 4 times) uInt8 myCTRLPF; // Playfield control register @@ -426,17 +393,16 @@ class TIA : public Device , public MediaSource 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) - Int16 myPOSP0; // Player 0 position register - Int16 myPOSP1; // Player 1 position register - Int16 myPOSM0; // Missle 0 position register - Int16 myPOSM1; // Missle 1 position register - Int16 myPOSBL; // Ball position register + Int16 myPOSP0; // Player 0 position register + Int16 myPOSP1; // Player 1 position register + Int16 myPOSM0; // Missle 0 position register + Int16 myPOSM1; // Missle 1 position register + Int16 myPOSBL; // Ball position register - private: // Graphics for Player 0 that should be displayed. This will be // reflected if the player is being reflected. uInt8 myCurrentGRP0; @@ -475,23 +441,18 @@ class TIA : public Device , public MediaSource uInt8 myAUDF0; uInt8 myAUDF1; - private: // Indicates when the dump for paddles was last set Int32 myDumpDisabledCycle; // Indicates if the dump is current enabled for the paddles bool myDumpEnabled; - private: // Color clock when last HMOVE occured Int32 myLastHMOVEClock; // Indicates if HMOVE blanks are currently enabled bool myHMOVEBlankEnabled; - // Indicates if we're allowing HMOVE blanks to be enabled - bool myAllowHMOVEBlanks; - // Indicates if unused TIA pins are floating on a peek bool myFloatTIAOutputPins; @@ -504,8 +465,19 @@ class TIA : public Device , public MediaSource // Bitmap of the objects that should be considered while drawing uInt8 myEnabledObjects; - // Answers whether specified bits (from TIABit) are enabled or disabled - bool myBitEnabled[6]; + // 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]; + + // Indicates if color loss should be enabled or disabled. Color loss + // occurs on PAL (and maybe SECAM) systems when the previous frame + // 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; // Has current frame been "greyed out" (has updateScanline() been run?) bool myFrameGreyed; @@ -513,119 +485,12 @@ class TIA : public Device , public MediaSource // Automatic framerate correction based on number of scanlines bool myAutoFrameEnabled; + // Number of frames displayed by this TIA + int myFrameCounter; + // The framerate currently in use by the Console float myFramerate; - private: - enum { // TODO - convert these to match TIA.cs - myP0Bit = 0x01, // Bit for Player 0 - myM0Bit = 0x02, // Bit for Missle 0 - myP1Bit = 0x04, // Bit for Player 1 - myM1Bit = 0x08, // Bit for Missle 1 - myBLBit = 0x10, // Bit for Ball - myPFBit = 0x20, // Bit for Playfield - ScoreBit = 0x40, // Bit for Playfield score mode - PriorityBit = 0x80 // Bit for Playfield priority - }; - - // TIA Write/Read register names - enum { - 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) - RSYNC = 0x03, // Write: reset hrz. sync counter (strobe) - NUSIZ0 = 0x04, // Write: number-size player-missle 0 (D5-0) - NUSIZ1 = 0x05, // Write: number-size player-missle 1 (D5-0) - COLUP0 = 0x06, // Write: color-lum player 0 (D7-1) - COLUP1 = 0x07, // Write: color-lum player 1 (D7-1) - COLUPF = 0x08, // Write: color-lum playfield (D7-1) - COLUBK = 0x09, // Write: color-lum background (D7-1) - CTRLPF = 0x0a, // Write: cntrl playfield ballsize & coll. (D5-4,D2-0) - REFP0 = 0x0b, // Write: reflect player 0 (D3) - REFP1 = 0x0c, // Write: reflect player 1 (D3) - PF0 = 0x0d, // Write: playfield register byte 0 (D7-4) - PF1 = 0x0e, // Write: playfield register byte 1 (D7-0) - PF2 = 0x0f, // Write: playfield register byte 2 (D7-0) - RESP0 = 0x10, // Write: reset player 0 (strobe) - RESP1 = 0x11, // Write: reset player 1 (strobe) - RESM0 = 0x12, // Write: reset missle 0 (strobe) - RESM1 = 0x13, // Write: reset missle 1 (strobe) - RESBL = 0x14, // Write: reset ball (strobe) - AUDC0 = 0x15, // Write: audio control 0 (D3-0) - AUDC1 = 0x16, // Write: audio control 1 (D4-0) - AUDF0 = 0x17, // Write: audio frequency 0 (D4-0) - AUDF1 = 0x18, // Write: audio frequency 1 (D3-0) - AUDV0 = 0x19, // Write: audio volume 0 (D3-0) - AUDV1 = 0x1a, // Write: audio volume 1 (D3-0) - GRP0 = 0x1b, // Write: graphics player 0 (D7-0) - GRP1 = 0x1c, // Write: graphics player 1 (D7-0) - ENAM0 = 0x1d, // Write: graphics (enable) missle 0 (D1) - ENAM1 = 0x1e, // Write: graphics (enable) missle 1 (D1) - ENABL = 0x1f, // Write: graphics (enable) ball (D1) - HMP0 = 0x20, // Write: horizontal motion player 0 (D7-4) - HMP1 = 0x21, // Write: horizontal motion player 1 (D7-4) - HMM0 = 0x22, // Write: horizontal motion missle 0 (D7-4) - HMM1 = 0x23, // Write: horizontal motion missle 1 (D7-4) - HMBL = 0x24, // Write: horizontal motion ball (D7-4) - VDELP0 = 0x25, // Write: vertical delay player 0 (D0) - VDELP1 = 0x26, // Write: vertical delay player 1 (D0) - VDELBL = 0x27, // Write: vertical delay ball (D0) - RESMP0 = 0x28, // Write: reset missle 0 to player 0 (D1) - RESMP1 = 0x29, // Write: reset missle 1 to player 1 (D1) - HMOVE = 0x2a, // Write: apply horizontal motion (strobe) - HMCLR = 0x2b, // Write: clear horizontal motion registers (strobe) - CXCLR = 0x2c, // Write: clear collision latches (strobe) - - CXM0P = 0x00, // Read collision: D7=(M0,P1); D6=(M0,P0) - CXM1P = 0x01, // Read collision: D7=(M1,P0); D6=(M1,P1) - CXP0FB = 0x02, // Read collision: D7=(P0,PF); D6=(P0,BL) - CXP1FB = 0x03, // Read collision: D7=(P1,PF); D6=(P1,BL) - CXM0FB = 0x04, // Read collision: D7=(M0,PF); D6=(M0,BL) - CXM1FB = 0x05, // Read collision: D7=(M1,PF); D6=(M1,BL) - CXBLPF = 0x06, // Read collision: D7=(BL,PF); D6=(unused) - CXPPMM = 0x07, // Read collision: D7=(P0,P1); D6=(M0,M1) - INPT0 = 0x08, // Read pot port: D7 - INPT1 = 0x09, // Read pot port: D7 - INPT2 = 0x0a, // Read pot port: D7 - INPT3 = 0x0b, // Read pot port: D7 - INPT4 = 0x0c, // Read P1 joystick trigger: D7 - INPT5 = 0x0d // Read P2 joystick trigger: D7 - }; - - // Ball mask table (entries are true or false) - static uInt8 ourBallMaskTable[4][4][320]; - - // Used to set the collision register to the correct value - static uInt16 ourCollisionTable[64]; - - // A mask table which can be used when an object is disabled - static uInt8 ourDisabledMaskTable[640]; - - // Indicates the update delay associated with poking at a TIA address - static const Int16 ourPokeDelayTable[64]; - - // Missle mask table (entries are true or false) - static uInt8 ourMissleMaskTable[4][8][4][320]; - - // Used to convert value written in a motion register into - // its internal representation - static const Int32 ourCompleteMotionTable[76][16]; - - // Indicates if HMOVE blanks should occur for the corresponding cycle - static const bool ourHMOVEBlankEnableCycles[76]; - - // Player mask table - static uInt8 ourPlayerMaskTable[4][2][8][320]; - - // Indicates if player is being reset during delay, display or other times - static Int8 ourPlayerPositionResetWhenTable[8][160][160]; - - // Used to reflect a players graphics - static uInt8 ourPlayerReflectTable[256]; - - // Playfield mask table for reflected and non-reflected playfields - static uInt32 ourPlayfieldTable[2][160]; - private: // Copy constructor isn't supported by this class so make it private TIA(const TIA&); diff --git a/stella/src/emucore/TIATables.cxx b/stella/src/emucore/TIATables.cxx new file mode 100644 index 000000000..0eb531c1a --- /dev/null +++ b/stella/src/emucore/TIATables.cxx @@ -0,0 +1,644 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: TIATables.cxx,v 1.1 2009-01-19 16:52:32 stephena Exp $ +//============================================================================ + +#include + +#include "bspf.hxx" +#include "TIATables.hxx" + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computeAllTables() +{ + for(uInt32 i = 0; i < 640; ++i) + DisabledMaskTable[i] = 0; + + computeBallMaskTable(); + computeCollisionTable(); + computeMissleMaskTable(); + computePlayerMaskTable(); + computePlayerPositionResetWhenTable(); + computePlayerReflectTable(); + computePlayfieldMaskTable(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computeBallMaskTable() +{ + // First, calculate masks for alignment 0 + for(Int32 size = 0; size < 4; ++size) + { + Int32 x; + + // Set all of the masks to false to start with + for(x = 0; x < 160; ++x) + { + BallMaskTable[0][size][x] = false; + } + + // Set the necessary fields true + for(x = 0; x < 160 + 8; ++x) + { + if((x >= 0) && (x < (1 << size))) + { + BallMaskTable[0][size][x % 160] = true; + } + } + + // Copy fields into the wrap-around area of the mask + for(x = 0; x < 160; ++x) + { + BallMaskTable[0][size][x + 160] = BallMaskTable[0][size][x]; + } + } + + // Now, copy data for alignments of 1, 2 and 3 + for(uInt32 align = 1; align < 4; ++align) + { + for(uInt32 size = 0; size < 4; ++size) + { + for(uInt32 x = 0; x < 320; ++x) + { + BallMaskTable[align][size][x] = BallMaskTable[0][size][(x + 320 - align) % 320]; + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computeCollisionTable() +{ + for(uInt8 i = 0; i < 64; ++i) + { + CollisionTable[i] = 0; + + if((i & M0Bit) && (i & P1Bit)) // M0-P1 + CollisionTable[i] |= 0x0001; + + if((i & M0Bit) && (i & P0Bit)) // M0-P0 + CollisionTable[i] |= 0x0002; + + if((i & M1Bit) && (i & P0Bit)) // M1-P0 + CollisionTable[i] |= 0x0004; + + if((i & M1Bit) && (i & P1Bit)) // M1-P1 + CollisionTable[i] |= 0x0008; + + if((i & P0Bit) && (i & PFBit)) // P0-PF + CollisionTable[i] |= 0x0010; + + if((i & P0Bit) && (i & BLBit)) // P0-BL + CollisionTable[i] |= 0x0020; + + if((i & P1Bit) && (i & PFBit)) // P1-PF + CollisionTable[i] |= 0x0040; + + if((i & P1Bit) && (i & BLBit)) // P1-BL + CollisionTable[i] |= 0x0080; + + if((i & M0Bit) && (i & PFBit)) // M0-PF + CollisionTable[i] |= 0x0100; + + if((i & M0Bit) && (i & BLBit)) // M0-BL + CollisionTable[i] |= 0x0200; + + if((i & M1Bit) && (i & PFBit)) // M1-PF + CollisionTable[i] |= 0x0400; + + if((i & M1Bit) && (i & BLBit)) // M1-BL + CollisionTable[i] |= 0x0800; + + if((i & BLBit) && (i & PFBit)) // BL-PF + CollisionTable[i] |= 0x1000; + + if((i & P0Bit) && (i & P1Bit)) // P0-P1 + CollisionTable[i] |= 0x2000; + + if((i & M0Bit) && (i & M1Bit)) // M0-M1 + CollisionTable[i] |= 0x4000; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computeMissleMaskTable() +{ + // First, calculate masks for alignment 0 + Int32 x, size, number; + + // Clear the missle table to start with + for(number = 0; number < 8; ++number) + for(size = 0; size < 4; ++size) + for(x = 0; x < 160; ++x) + MissleMaskTable[0][number][size][x] = false; + + for(number = 0; number < 8; ++number) + { + for(size = 0; size < 4; ++size) + { + for(x = 0; x < 160 + 72; ++x) + { + // Only one copy of the missle + if((number == 0x00) || (number == 0x05) || (number == 0x07)) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + // Two copies - close + else if(number == 0x01) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 16) >= 0) && ((x - 16) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + // Two copies - medium + else if(number == 0x02) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + // Three copies - close + else if(number == 0x03) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 16) >= 0) && ((x - 16) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + // Two copies - wide + else if(number == 0x04) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 64) >= 0) && ((x - 64) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + // Three copies - medium + else if(number == 0x06) + { + if((x >= 0) && (x < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 32) >= 0) && ((x - 32) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + else if(((x - 64) >= 0) && ((x - 64) < (1 << size))) + MissleMaskTable[0][number][size][x % 160] = true; + } + } + + // Copy data into wrap-around area + for(x = 0; x < 160; ++x) + MissleMaskTable[0][number][size][x + 160] = + MissleMaskTable[0][number][size][x]; + } + } + + // Now, copy data for alignments of 1, 2 and 3 + for(uInt32 align = 1; align < 4; ++align) + { + for(number = 0; number < 8; ++number) + { + for(size = 0; size < 4; ++size) + { + for(x = 0; x < 320; ++x) + { + MissleMaskTable[align][number][size][x] = + MissleMaskTable[0][number][size][(x + 320 - align) % 320]; + } + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computePlayerMaskTable() +{ + // First, calculate masks for alignment 0 + Int32 x, enable, mode; + + // Set the player mask table to all zeros + for(enable = 0; enable < 2; ++enable) + for(mode = 0; mode < 8; ++mode) + for(x = 0; x < 160; ++x) + PlayerMaskTable[0][enable][mode][x] = 0x00; + + // Now, compute the player mask table + for(enable = 0; enable < 2; ++enable) + { + for(mode = 0; mode < 8; ++mode) + { + for(x = 0; x < 160 + 72; ++x) + { + if(mode == 0x00) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + } + else if(mode == 0x01) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + else if(((x - 16) >= 0) && ((x - 16) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 16); + } + else if(mode == 0x02) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + else if(((x - 32) >= 0) && ((x - 32) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); + } + else if(mode == 0x03) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + else if(((x - 16) >= 0) && ((x - 16) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 16); + else if(((x - 32) >= 0) && ((x - 32) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); + } + else if(mode == 0x04) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + else if(((x - 64) >= 0) && ((x - 64) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 64); + } + else if(mode == 0x05) + { + // For some reason in double size mode the player's output + // is delayed by one pixel thus we use > instead of >= + if((enable == 0) && (x > 0) && (x <= 16)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> ((x - 1)/2); + } + else if(mode == 0x06) + { + if((enable == 0) && (x >= 0) && (x < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> x; + else if(((x - 32) >= 0) && ((x - 32) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 32); + else if(((x - 64) >= 0) && ((x - 64) < 8)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> (x - 64); + } + else if(mode == 0x07) + { + // For some reason in quad size mode the player's output + // is delayed by one pixel thus we use > instead of >= + if((enable == 0) && (x > 0) && (x <= 32)) + PlayerMaskTable[0][enable][mode][x % 160] = 0x80 >> ((x - 1)/4); + } + } + + // Copy data into wrap-around area + for(x = 0; x < 160; ++x) + { + PlayerMaskTable[0][enable][mode][x + 160] = + PlayerMaskTable[0][enable][mode][x]; + } + } + } + + // Now, copy data for alignments of 1, 2 and 3 + for(uInt32 align = 1; align < 4; ++align) + { + for(enable = 0; enable < 2; ++enable) + { + for(mode = 0; mode < 8; ++mode) + { + for(x = 0; x < 320; ++x) + { + PlayerMaskTable[align][enable][mode][x] = + PlayerMaskTable[0][enable][mode][(x + 320 - align) % 320]; + } + } + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computePlayerPositionResetWhenTable() +{ + uInt32 mode, oldx, newx; + + // Loop through all player modes, all old player positions, and all new + // player positions and determine where the new position is located: + // 1 means the new position is within the display of an old copy of the + // player, -1 means the new position is within the delay portion of an + // old copy of the player, and 0 means it's neither of these two + for(mode = 0; mode < 8; ++mode) + { + for(oldx = 0; oldx < 160; ++oldx) + { + // Set everything to 0 for non-delay/non-display section + for(newx = 0; newx < 160; ++newx) + { + PlayerPositionResetWhenTable[mode][oldx][newx] = 0; + } + + // Now, we'll set the entries for non-delay/non-display section + for(newx = 0; newx < 160 + 72 + 5; ++newx) + { + if(mode == 0x00) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x01) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x02) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x03) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x04) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x05) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 16))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x06) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + else if(mode == 0x07) + { + if((newx >= oldx) && (newx < (oldx + 4))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = -1; + + if((newx >= oldx + 4) && (newx < (oldx + 4 + 32))) + PlayerPositionResetWhenTable[mode][oldx][newx % 160] = 1; + } + } + + // Let's do a sanity check on table entries + uInt32 s1 = 0, s2 = 0; + for(newx = 0; newx < 160; ++newx) + { + if(PlayerPositionResetWhenTable[mode][oldx][newx] == -1) + ++s1; + if(PlayerPositionResetWhenTable[mode][oldx][newx] == 1) + ++s2; + } + assert((s1 % 4 == 0) && (s2 % 8 == 0)); + } + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computePlayerReflectTable() +{ + for(uInt16 i = 0; i < 256; ++i) + { + uInt8 r = 0; + + for(uInt16 t = 1; t <= 128; t *= 2) + { + r = (r << 1) | ((i & t) ? 0x01 : 0x00); + } + + PlayerReflectTable[i] = r; + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void TIATables::computePlayfieldMaskTable() +{ + Int32 x; + + // Compute playfield mask table for non-reflected mode + for(x = 0; x < 160; ++x) + { + if(x < 16) + PlayfieldTable[0][x] = 0x00001 << (x / 4); + else if(x < 48) + PlayfieldTable[0][x] = 0x00800 >> ((x - 16) / 4); + else if(x < 80) + PlayfieldTable[0][x] = 0x01000 << ((x - 48) / 4); + else if(x < 96) + PlayfieldTable[0][x] = 0x00001 << ((x - 80) / 4); + else if(x < 128) + PlayfieldTable[0][x] = 0x00800 >> ((x - 96) / 4); + else if(x < 160) + PlayfieldTable[0][x] = 0x01000 << ((x - 128) / 4); + } + + // Compute playfield mask table for reflected mode + for(x = 0; x < 160; ++x) + { + if(x < 16) + PlayfieldTable[1][x] = 0x00001 << (x / 4); + else if(x < 48) + PlayfieldTable[1][x] = 0x00800 >> ((x - 16) / 4); + else if(x < 80) + PlayfieldTable[1][x] = 0x01000 << ((x - 48) / 4); + else if(x < 112) + PlayfieldTable[1][x] = 0x80000 >> ((x - 80) / 4); + else if(x < 144) + PlayfieldTable[1][x] = 0x00010 << ((x - 112) / 4); + else if(x < 160) + PlayfieldTable[1][x] = 0x00008 >> ((x - 144) / 4); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 TIATables::BallMaskTable[4][4][320]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt16 TIATables::CollisionTable[64]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 TIATables::DisabledMaskTable[640]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const Int16 TIATables::PokeDelayTable[64] = { + 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, 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, 0, 0, 0, 0, 0, +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 TIATables::MissleMaskTable[4][8][4][320]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const bool TIATables::HMOVEBlankEnableCycles[76] = { + true, true, true, true, true, true, true, true, true, true, // 00 + true, true, true, true, true, true, true, true, true, true, // 10 + true, false, false, false, false, false, false, false, false, false, // 20 + false, false, false, false, false, false, false, false, false, false, // 30 + false, false, false, false, false, false, false, false, false, false, // 40 + false, false, false, false, false, false, false, false, false, false, // 50 + false, false, false, false, false, false, false, false, false, false, // 60 + false, false, false, false, false, true // 70 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const Int32 TIATables::CompleteMotionTable[76][16] = { + { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -6, -6, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -5, -5, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -5, -5, -5, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -4, -4, -4, -4, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -3, -3, -3, -3, -3, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -2, -2, -2, -2, -2, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -2, -2, -2, -2, -2, -2, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, -1, -1, -1, -1, -1, -1, -1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 0, 0, 0, 0, 0, 0, 0, 0, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 1, 1, 1, 1, 1, 1, 1, 1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 1, 1, 1, 1, 1, 1, 1, 1, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK + { 2, 2, 2, 2, 2, 2, 2, 2, 8, 7, 6, 5, 4, 3, 2, 2}, // HBLANK + { 3, 3, 3, 3, 3, 3, 3, 3, 8, 7, 6, 5, 4, 3, 3, 3}, // HBLANK + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 7, 6, 5, 4, 4, 4, 4}, // HBLANK + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 7, 6, 5, 4, 4, 4, 4}, // HBLANK + { 5, 5, 5, 5, 5, 5, 5, 5, 8, 7, 6, 5, 5, 5, 5, 5}, // HBLANK + { 6, 6, 6, 6, 6, 6, 6, 6, 8, 7, 6, 6, 6, 6, 6, 6}, // HBLANK + { 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, 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, 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, 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, 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, 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, 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, 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}, + { 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, 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, 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, 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, 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, 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, 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, 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}, + { 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, 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, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, 0, -1, -2, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, -1, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, 0, -1, -2, -3, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, 0, -1, -2, -3, -4, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, 0, -1, -2, -3, -4, -5, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, -1, -2, -3, -4, -5, -6, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, 0, -1, -2, -3, -4, -5, -6, 0, 0, 0, 0, 0, 0, 0, 0}, + { 0, -1, -2, -3, -4, -5, -6, -7, 0, 0, 0, 0, 0, 0, 0, 0}, + {-1, -2, -3, -4, -5, -6, -7, -8, 0, 0, 0, 0, 0, 0, 0, 0}, + {-2, -3, -4, -5, -6, -7, -8, -9, 0, 0, 0, 0, 0, 0, 0, -1}, + {-2, -3, -4, -5, -6, -7, -8, -9, 0, 0, 0, 0, 0, 0, 0, -1}, + {-3, -4, -5, -6, -7, -8, -9,-10, 0, 0, 0, 0, 0, 0, -1, -2}, + {-4, -5, -6, -7, -8, -9,-10,-11, 0, 0, 0, 0, 0, -1, -2, -3}, + {-5, -6, -7, -8, -9,-10,-11,-12, 0, 0, 0, 0, -1, -2, -3, -4}, + {-5, -6, -7, -8, -9,-10,-11,-12, 0, 0, 0, 0, -1, -2, -3, -4}, + {-6, -7, -8, -9,-10,-11,-12,-13, 0, 0, 0, -1, -2, -3, -4, -5}, + {-7, -8, -9,-10,-11,-12,-13,-14, 0, 0, -1, -2, -3, -4, -5, -6}, + {-8, -9,-10,-11,-12,-13,-14,-15, 0, -1, -2, -3, -4, -5, -6, -7}, + {-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 +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 TIATables::PlayerMaskTable[4][2][8][320]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Int8 TIATables::PlayerPositionResetWhenTable[8][160][160]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt8 TIATables::PlayerReflectTable[256]; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +uInt32 TIATables::PlayfieldTable[2][160]; diff --git a/stella/src/emucore/TIATables.hxx b/stella/src/emucore/TIATables.hxx new file mode 100644 index 000000000..77134cb6e --- /dev/null +++ b/stella/src/emucore/TIATables.hxx @@ -0,0 +1,172 @@ +//============================================================================ +// +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa +// SSSS tt ee ee ll ll aa +// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" +// SS SS tt ee ll ll aa aa +// SSSS ttt eeeee llll llll aaaaa +// +// Copyright (c) 1995-2009 by Bradford W. Mott and the Stella team +// +// See the file "license" for information on usage and redistribution of +// this file, and for a DISCLAIMER OF ALL WARRANTIES. +// +// $Id: TIATables.hxx,v 1.1 2009-01-19 16:52:32 stephena Exp $ +//============================================================================ + +#ifndef TIA_TABLES_HXX +#define TIA_TABLES_HXX + +#include "bspf.hxx" + +enum { + P0Bit = 0x01, // Bit for Player 0 + M0Bit = 0x02, // Bit for Missle 0 + P1Bit = 0x04, // Bit for Player 1 + M1Bit = 0x08, // Bit for Missle 1 + BLBit = 0x10, // Bit for Ball + PFBit = 0x20, // Bit for Playfield + ScoreBit = 0x40, // Bit for Playfield score mode + PriorityBit = 0x80 // Bit for Playfield priority +}; + +// TIA Write/Read register names +enum { + 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) + RSYNC = 0x03, // Write: reset hrz. sync counter (strobe) + NUSIZ0 = 0x04, // Write: number-size player-missle 0 (D5-0) + NUSIZ1 = 0x05, // Write: number-size player-missle 1 (D5-0) + COLUP0 = 0x06, // Write: color-lum player 0 (D7-1) + COLUP1 = 0x07, // Write: color-lum player 1 (D7-1) + COLUPF = 0x08, // Write: color-lum playfield (D7-1) + COLUBK = 0x09, // Write: color-lum background (D7-1) + CTRLPF = 0x0a, // Write: cntrl playfield ballsize & coll. (D5-4,D2-0) + REFP0 = 0x0b, // Write: reflect player 0 (D3) + REFP1 = 0x0c, // Write: reflect player 1 (D3) + PF0 = 0x0d, // Write: playfield register byte 0 (D7-4) + PF1 = 0x0e, // Write: playfield register byte 1 (D7-0) + PF2 = 0x0f, // Write: playfield register byte 2 (D7-0) + RESP0 = 0x10, // Write: reset player 0 (strobe) + RESP1 = 0x11, // Write: reset player 1 (strobe) + RESM0 = 0x12, // Write: reset missle 0 (strobe) + RESM1 = 0x13, // Write: reset missle 1 (strobe) + RESBL = 0x14, // Write: reset ball (strobe) + AUDC0 = 0x15, // Write: audio control 0 (D3-0) + AUDC1 = 0x16, // Write: audio control 1 (D4-0) + AUDF0 = 0x17, // Write: audio frequency 0 (D4-0) + AUDF1 = 0x18, // Write: audio frequency 1 (D3-0) + AUDV0 = 0x19, // Write: audio volume 0 (D3-0) + AUDV1 = 0x1a, // Write: audio volume 1 (D3-0) + GRP0 = 0x1b, // Write: graphics player 0 (D7-0) + GRP1 = 0x1c, // Write: graphics player 1 (D7-0) + ENAM0 = 0x1d, // Write: graphics (enable) missle 0 (D1) + ENAM1 = 0x1e, // Write: graphics (enable) missle 1 (D1) + ENABL = 0x1f, // Write: graphics (enable) ball (D1) + HMP0 = 0x20, // Write: horizontal motion player 0 (D7-4) + HMP1 = 0x21, // Write: horizontal motion player 1 (D7-4) + HMM0 = 0x22, // Write: horizontal motion missle 0 (D7-4) + HMM1 = 0x23, // Write: horizontal motion missle 1 (D7-4) + HMBL = 0x24, // Write: horizontal motion ball (D7-4) + VDELP0 = 0x25, // Write: vertical delay player 0 (D0) + VDELP1 = 0x26, // Write: vertical delay player 1 (D0) + VDELBL = 0x27, // Write: vertical delay ball (D0) + RESMP0 = 0x28, // Write: reset missle 0 to player 0 (D1) + RESMP1 = 0x29, // Write: reset missle 1 to player 1 (D1) + HMOVE = 0x2a, // Write: apply horizontal motion (strobe) + HMCLR = 0x2b, // Write: clear horizontal motion registers (strobe) + CXCLR = 0x2c, // Write: clear collision latches (strobe) + + CXM0P = 0x00, // Read collision: D7=(M0,P1); D6=(M0,P0) + CXM1P = 0x01, // Read collision: D7=(M1,P0); D6=(M1,P1) + CXP0FB = 0x02, // Read collision: D7=(P0,PF); D6=(P0,BL) + CXP1FB = 0x03, // Read collision: D7=(P1,PF); D6=(P1,BL) + CXM0FB = 0x04, // Read collision: D7=(M0,PF); D6=(M0,BL) + CXM1FB = 0x05, // Read collision: D7=(M1,PF); D6=(M1,BL) + CXBLPF = 0x06, // Read collision: D7=(BL,PF); D6=(unused) + CXPPMM = 0x07, // Read collision: D7=(P0,P1); D6=(M0,M1) + INPT0 = 0x08, // Read pot port: D7 + INPT1 = 0x09, // Read pot port: D7 + INPT2 = 0x0a, // Read pot port: D7 + INPT3 = 0x0b, // Read pot port: D7 + INPT4 = 0x0c, // Read P1 joystick trigger: D7 + INPT5 = 0x0d // Read P2 joystick trigger: D7 +}; + +/** + The TIA class uses some static tables that aren't dependent on the actual + TIA state. For code organization, it's better to place that functionality + here. + + @author Stephen Anthony + @version $Id: TIATables.hxx,v 1.1 2009-01-19 16:52:32 stephena Exp $ +*/ +class TIATables +{ + public: + /** + Compute all static tables used by the TIA + */ + static void computeAllTables(); + + // Ball mask table (entries are true or false) + static uInt8 BallMaskTable[4][4][320]; + + // Used to set the collision register to the correct value + static uInt16 CollisionTable[64]; + + // A mask table which can be used when an object is disabled + static uInt8 DisabledMaskTable[640]; + + // Indicates the update delay associated with poking at a TIA address + static const Int16 PokeDelayTable[64]; + + // Missle mask table (entries are true or false) + static uInt8 MissleMaskTable[4][8][4][320]; + + // Used to convert value written in a motion register into + // its internal representation + static const Int32 CompleteMotionTable[76][16]; + + // Indicates if HMOVE blanks should occur for the corresponding cycle + static const bool HMOVEBlankEnableCycles[76]; + + // Player mask table + static uInt8 PlayerMaskTable[4][2][8][320]; + + // Indicates if player is being reset during delay, display or other times + static Int8 PlayerPositionResetWhenTable[8][160][160]; + + // Used to reflect a players graphics + static uInt8 PlayerReflectTable[256]; + + // Playfield mask table for reflected and non-reflected playfields + static uInt32 PlayfieldTable[2][160]; + + private: + // Compute the ball mask table + static void computeBallMaskTable(); + + // Compute the collision decode table + static void computeCollisionTable(); + + // Compute the missle mask table + static void computeMissleMaskTable(); + + // Compute the player mask table + static void computePlayerMaskTable(); + + // Compute the player position reset when table + static void computePlayerPositionResetWhenTable(); + + // Compute the player reflect table + static void computePlayerReflectTable(); + + // Compute playfield mask table + static void computePlayfieldMaskTable(); +}; + +#endif diff --git a/stella/src/emucore/module.mk b/stella/src/emucore/module.mk index dcbf4524a..a7a8a7139 100644 --- a/stella/src/emucore/module.mk +++ b/stella/src/emucore/module.mk @@ -41,7 +41,6 @@ MODULE_OBJS := \ src/emucore/M6532.o \ src/emucore/MT24LC256.o \ src/emucore/MD5.o \ - src/emucore/MediaSrc.o \ src/emucore/OSystem.o \ src/emucore/Paddles.o \ src/emucore/Props.o \ @@ -55,6 +54,7 @@ MODULE_OBJS := \ src/emucore/StateManager.o \ src/emucore/TIA.o \ src/emucore/TIASnd.o \ + src/emucore/TIATables.o \ src/emucore/TrackBall.o \ src/emucore/unzip.o \ src/emucore/MediaFactory.o diff --git a/stella/src/gui/CommandDialog.cxx b/stella/src/gui/CommandDialog.cxx index 9507399db..20b55df0f 100644 --- a/stella/src/gui/CommandDialog.cxx +++ b/stella/src/gui/CommandDialog.cxx @@ -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: CommandDialog.cxx,v 1.24 2009-01-15 18:45:23 stephena Exp $ +// $Id: CommandDialog.cxx,v 1.25 2009-01-19 16:52:32 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -192,7 +192,7 @@ void CommandDialog::handleCommand(CommandSender* sender, int cmd, instance().eventHandler().leaveMenuMode(); instance().eventHandler().handleEvent(event, 1); instance().console().switches().update(); - instance().console().mediaSource().update(); + instance().console().tia().update(); instance().eventHandler().handleEvent(event, 0); instance().frameBuffer().refresh(); } diff --git a/stella/src/gui/VideoDialog.cxx b/stella/src/gui/VideoDialog.cxx index b9281b61d..8d84d5858 100644 --- a/stella/src/gui/VideoDialog.cxx +++ b/stella/src/gui/VideoDialog.cxx @@ -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: VideoDialog.cxx,v 1.63 2009-01-14 20:31:07 stephena Exp $ +// $Id: VideoDialog.cxx,v 1.64 2009-01-19 16:52:32 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -310,7 +310,7 @@ void VideoDialog::saveConfig() if(&instance().console()) { // Make sure auto-frame calculation is only enabled when necessary - instance().console().mediaSource().enableAutoFrame(i <= 0); + instance().console().tia().enableAutoFrame(i <= 0); instance().console().setFramerate(float(i)); }