Delete old TIA core (files are only moved for now).

This commit is contained in:
Stephen Anthony 2016-12-10 12:45:00 -03:30
parent f7e712386b
commit 4b5a02903e
31 changed files with 0 additions and 3993 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,645 +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-2016 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef TIA_DEFAULT_CORE_HXX
#define TIA_DEFAULT_CORE_HXX
class Console;
class Settings;
class Sound;
#include "AbstractTIA.hxx"
#include "bspf.hxx"
#include "System.hxx"
#include "TIATables.hxx"
namespace TIADefaultCore {
/**
This class is a device that emulates the Television Interface Adaptor
found in the Atari 2600 and 7800 consoles. The Television Interface
Adaptor is an integrated circuit designed to interface between an
eight bit microprocessor and a television video modulator. It converts
eight bit parallel data into serial outputs for the color, luminosity,
and composite sync required by a video modulator.
This class outputs the serial data into a frame buffer which can then
be displayed on screen.
@author Bradford W. Mott
@version $Id$
*/
class TIA : public AbstractTIA
{
public:
/**
Create a new TIA for the specified console
@param console The console the TIA is associated with
@param sound The sound object the TIA is associated with
@param settings The settings object for this TIA device
*/
TIA(Console& console, Sound& sound, Settings& settings);
virtual ~TIA() = default;
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Reset frame to current YStart/Height properties
*/
void frameReset() override;
/**
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.
*/
void systemCyclesReset() override;
/**
Install TIA in the specified system. Invoked by the system
when the TIA is attached to it.
@param system The system the device should install itself in
*/
void install(System& system) override;
/**
Install TIA in the specified system and device. Invoked by
the system when the TIA is attached to it. All devices
which invoke this method take responsibility for chaining
requests back to *this* device.
@param system The system the device should install itself in
@param device The device responsible for this address space
*/
void installDelegate(System& system, Device& device) override;
/**
Save the current state of this device to the given Serializer.
@param out The Serializer object to use
@return False on any errors, else true
*/
bool save(Serializer& out) const override;
/**
Load the current state of this device from the given Serializer.
@param in The Serializer object to use
@return False on any errors, else true
*/
bool load(Serializer& in) override;
/**
The following are very similar to save() and load(), except they
do a 'deeper' save of the display data itself.
Normally, the internal framebuffer doesn't need to be saved to
a state file, since the file already contains all the information
needed to re-create it, starting from scanline 0. In effect, when a
state is loaded, the framebuffer is empty, and the next call to
update() generates valid framebuffer data.
However, state files saved from the debugger need more information,
such as the exact state of the internal framebuffer itself *before*
we call update(), including if the display was in partial frame mode.
Essentially, a normal state save has 'frame resolution', whereas
the debugger state save has 'cycle resolution', and hence needs
more information. The methods below save/load this extra info,
and eliminate having to save approx. 50K to normal state files.
*/
bool saveDisplay(Serializer& out) const override;
bool loadDisplay(Serializer& in) override;
/**
Get a descriptor for the device name (used in error checking).
@return The name of the object
*/
string name() const override { return "TIA"; }
/**
Get the byte at the specified address
@return The byte at the specified address
*/
uInt8 peek(uInt16 address) override;
/**
Change the byte at the specified address to the given value
@param address The address where the value should be stored
@param value The value to be stored at the address
@return True if the poke changed the device address space, else false
*/
bool poke(uInt16 address, uInt8 value) override;
/**
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.
*/
void update() override;
/**
Answers the current frame buffer
@return Pointer to the current frame buffer
*/
uInt8* currentFrameBuffer() const override
{ return myCurrentFrameBuffer.get() + myFramePointerOffset + myCurrentFrameJitter; }
/**
Answers the previous frame buffer
@return Pointer to the previous frame buffer
*/
uInt8* previousFrameBuffer() const override
{ return myPreviousFrameBuffer.get() + myFramePointerOffset; }
/**
Answers the height of the frame buffer
*/
inline uInt32 height() const override { return myFrameHeight; }
inline uInt32 ystart() const override { return myFrameYStart; }
/**
Changes the current Height/YStart properties.
Note that calls to these method(s) must be eventually followed by
::frameReset() for the changes to take effect.
*/
void setHeight(uInt32 height) override { myFrameHeight = height; }
void setYStart(uInt32 ystart) override { myFrameYStart = ystart; }
/**
Enables/disables auto-frame calculation. If enabled, the TIA
re-adjusts the framerate at regular intervals.
@param mode Whether to enable or disable all auto-frame calculation
*/
void enableAutoFrame(bool mode) override { myAutoFrameEnabled = mode; }
/**
Enables/disables color-loss for PAL modes only.
@param mode Whether to enable or disable PAL color-loss mode
*/
void enableColorLoss(bool mode) override
{ myColorLossEnabled = myFramerate <= 55 ? mode : false; }
/**
Answers whether this TIA runs at NTSC or PAL scanrates,
based on how many frames of out the total count are PAL frames.
*/
bool isPAL() const override
{ return double(myPALFrameCounter) / myFrameCounter >= (25.0/60.0); }
/**
Answers the current color clock we've gotten to on this scanline.
@return The current color clock
*/
uInt32 clocksThisLine() const override
{ 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 override
{ return ((mySystem->cycles() * 3) - myClockWhenFrameStarted) / 228; }
/**
Answers whether the TIA is currently in 'partial frame' mode
(we're in between a call of startFrame and endFrame).
@return If we're in partial frame mode
*/
bool partialFrame() const override { return myPartialFrameFlag; }
/**
Answers the first scanline at which drawing occured in the last frame.
@return The starting scanline
*/
uInt32 startScanline() const override { return myStartScanline; }
/**
Answers the current position of the virtual 'electron beam' used to
draw the TIA image. If not in partial frame mode, the position is
defined to be in the lower right corner (@ width/height of the screen).
Note that the coordinates are with respect to currentFrameBuffer(),
taking any YStart values into account.
@return The x/y coordinates of the scanline electron beam, and whether
it is in the visible/viewable area of the screen
*/
bool scanlinePos(uInt16& x, uInt16& y) const override;
/**
Enables/disable/toggle the specified (or all) TIA bit(s). Note that
disabling a graphical object also disables its collisions.
@param mode 1/0 indicates on/off, and values greater than 1 mean
flip the bit from its current state
@return Whether the bit was enabled or disabled
*/
bool toggleBit(TIABit b, uInt8 mode = 2) override;
bool toggleBits() override;
/**
Enables/disable/toggle the specified (or all) TIA bit collision(s).
@param mode 1/0 indicates on/off, and values greater than 1 mean
flip the collision from its current state
@return Whether the collision was enabled or disabled
*/
bool toggleCollision(TIABit b, uInt8 mode = 2) override;
bool toggleCollisions() override;
/**
Enables/disable/toggle 'fixed debug colors' mode.
@param mode 1/0 indicates on/off, otherwise flip from
its current state
@return Whether the mode was enabled or disabled
*/
bool toggleFixedColors(uInt8 mode = 2) override;
/**
Enable/disable/query state of 'undriven/floating TIA pins'.
@param mode 1/0 indicates on/off, otherwise return the current state
@return Whether the mode was enabled or disabled
*/
bool driveUnusedPinsRandom(uInt8 mode = 2) override;
/**
Enables/disable/toggle 'scanline jittering' mode, and set the
recovery 'factor'.
@param mode 1/0 indicates on/off, otherwise flip from
its current state
@return Whether the mode was enabled or disabled
*/
bool toggleJitter(uInt8 mode = 2) override;
void setJitterRecoveryFactor(Int32 f) override { myJitterRecoveryFactor = f; }
#ifdef DEBUGGER_SUPPORT
/**
This method should be called to update the TIA with a new scanline.
*/
void updateScanline() override;
/**
This method should be called to update the TIA with a new partial
scanline by stepping one CPU instruction.
*/
void updateScanlineByStep() override;
/**
This method should be called to update the TIA with a new partial
scanline by tracing to target address.
*/
void updateScanlineByTrace(int target) override;
#endif
private:
/**
Enables/disables all TIABit bits. Note that disabling a graphical
object also disables its collisions.
@param mode Whether to enable or disable all bits
*/
void enableBits(bool mode);
/**
Enables/disables all TIABit collisions.
@param mode Whether to enable or disable all collisions
*/
void enableCollisions(bool mode);
// Reset all instance variables to the initial state
void initialize();
// Update the current frame buffer to the specified color clock
void updateFrame(Int32 clock);
// Waste cycles until the current scanline is finished
void waitHorizontalSync();
// Reset horizontal sync counter
void waitHorizontalRSync();
// Clear both internal TIA buffers to black (palette color 0)
void clearBuffers();
// Set up bookkeeping for the next frame
void startFrame();
// Update bookkeeping at end of frame
void endFrame();
// Convert resistance from ports to dumped value
uInt8 dumpedInputPort(int resistance);
// Write the specified value to the HMOVE registers at the given clock
void pokeHMP0(uInt8 value, Int32 clock);
void pokeHMP1(uInt8 value, Int32 clock);
void pokeHMM0(uInt8 value, Int32 clock);
void pokeHMM1(uInt8 value, Int32 clock);
void pokeHMBL(uInt8 value, Int32 clock);
// Apply motion to registers when HMOVE is currently active
void applyActiveHMOVEMotion(int hpos, Int16& pos, Int32 motionClock);
// Apply motion to registers when HMOVE was previously active
void applyPreviousHMOVEMotion(int hpos, Int16& pos, uInt8 motion);
private:
// Console the TIA is associated with
Console& myConsole;
// Sound object the TIA is associated with
Sound& mySound;
// Settings object the TIA is associated with
Settings& mySettings;
// Pointer to the current frame buffer
BytePtr myCurrentFrameBuffer;
// Pointer to the previous frame buffer
BytePtr myPreviousFrameBuffer;
// Pointer to the next pixel that will be drawn in the current frame buffer
uInt8* myFramePointer;
// Indicates offset used by the exported frame buffer
// (the exported frame buffer is a vertical 'sliding window' of the actual buffer)
uInt32 myFramePointerOffset;
// Indicates the number of 'colour clocks' offset from the base
// frame buffer pointer
// (this is used when loading state files with a 'partial' frame)
uInt32 myFramePointerClocks;
// Indicated what scanline the frame should start being drawn at
uInt32 myFrameYStart;
// Indicates the height of the frame in scanlines
uInt32 myFrameHeight;
// Indicates offset in color clocks when display should stop
uInt32 myStopDisplayOffset;
// Indicates color clocks when the current frame began
Int32 myClockWhenFrameStarted;
// Indicates color clocks when frame should begin to be drawn
Int32 myClockStartDisplay;
// Indicates color clocks when frame should stop being drawn
Int32 myClockStopDisplay;
// Indicates color clocks when the frame was last updated
Int32 myClockAtLastUpdate;
// Indicates how many color clocks remain until the end of
// current scanline. This value is valid during the
// displayed portion of the frame.
Int32 myClocksToEndOfScanLine;
// Indicates the total number of scanlines generated by the last frame
uInt32 myScanlineCountForLastFrame;
// Indicates the maximum number of scanlines to be generated for a frame
uInt32 myMaximumNumberOfScanlines;
// Indicates potentially the first scanline at which drawing occurs
uInt32 myStartScanline;
// Color clock when VSYNC ending causes a new frame to be started
Int32 myVSYNCFinishClock;
uInt8 myVSYNC; // Holds the VSYNC register value
uInt8 myVBLANK; // Holds the VBLANK register value
uInt8 myNUSIZ0; // Number and size of player 0 and missle 0
uInt8 myNUSIZ1; // Number and size of player 1 and missle 1
uInt8 myPlayfieldPriorityAndScore;
uInt8 myPriorityEncoder[2][256];
uInt8 myColor[8];
uInt8 myFixedColor[8];
uInt8* myColorPtr;
uInt8 myCTRLPF; // Playfield control register
bool myREFP0; // Indicates if player 0 is being reflected
bool myREFP1; // Indicates if player 1 is being reflected
uInt32 myPF; // Playfield graphics (19-12:PF2 11-4:PF1 3-0:PF0)
uInt8 myGRP0; // Player 0 graphics register
uInt8 myGRP1; // Player 1 graphics register
uInt8 myDGRP0; // Player 0 delayed graphics register
uInt8 myDGRP1; // Player 1 delayed graphics register
bool myENAM0; // Indicates if missle 0 is enabled
bool myENAM1; // Indicates if missle 1 is enabled
bool myENABL; // Indicates if the ball is enabled
bool myDENABL; // Indicates if the vertically delayed ball is enabled
uInt8 myHMP0; // Player 0 horizontal motion register
uInt8 myHMP1; // Player 1 horizontal motion register
uInt8 myHMM0; // Missle 0 horizontal motion register
uInt8 myHMM1; // Missle 1 horizontal motion register
uInt8 myHMBL; // Ball horizontal motion register
bool myVDELP0; // Indicates if player 0 is being vertically delayed
bool myVDELP1; // Indicates if player 1 is being vertically delayed
bool myVDELBL; // Indicates if the ball is being vertically delayed
bool myRESMP0; // Indicates if missle 0 is reset to player 0
bool myRESMP1; // Indicates if missle 1 is reset to player 1
uInt16 myCollision; // Collision register
// Determines whether specified collisions are enabled or disabled
// The lower 16 bits are and'ed with the collision register to mask out
// any collisions we don't want to be processed
// The upper 16 bits are used to store which objects is currently
// enabled or disabled
// This is necessary since there are 15 collision combinations which
// are controlled by 6 objects
uInt32 myCollisionEnabledMask;
// 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
// 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;
// Index into the player mask arrays indicating whether display
// of the first copy should be suppressed
uInt8 mySuppressP0;
uInt8 mySuppressP1;
// Latches for 'more motion required' as described in A. Towers TIA
// Hardware Notes
bool myHMP0mmr;
bool myHMP1mmr;
bool myHMM0mmr;
bool myHMM1mmr;
bool myHMBLmmr;
// Graphics for Player 0 that should be displayed. This will be
// reflected if the player is being reflected.
uInt8 myCurrentGRP0;
// Graphics for Player 1 that should be displayed. This will be
// reflected if the player is being reflected.
uInt8 myCurrentGRP1;
// It's VERY important that the BL, M0, M1, P0 and P1 current
// mask pointers are always on a uInt32 boundary. Otherwise,
// the TIA code will fail on a good number of CPUs.
const uInt8* myP0Mask;
const uInt8* myM0Mask;
const uInt8* myM1Mask;
const uInt8* myP1Mask;
const uInt8* myBLMask;
const uInt32* myPFMask;
// Audio values; only used by TIADebug
uInt8 myAUDV0, myAUDV1, myAUDC0, myAUDC1, myAUDF0, myAUDF1;
// Indicates when the dump for paddles was last set
Int32 myDumpDisabledCycle;
// Indicates if the dump is current enabled for the paddles
bool myDumpEnabled;
// Latches for INPT4 and INPT5
uInt8 myINPT4, myINPT5;
// Indicates if HMOVE blanks are currently or previously enabled,
// and at which horizontal position the HMOVE was initiated
Int32 myCurrentHMOVEPos;
Int32 myPreviousHMOVEPos;
bool myHMOVEBlankEnabled;
// Indicates if unused TIA pins are randomly driven high or low
// Otherwise, they take on the value previously on the databus
bool myTIAPinsDriven;
// Bitmap of the objects that should be considered while drawing
uInt8 myEnabledObjects;
// Determines whether specified bits (from TIABit) are enabled or disabled
// This is and'ed with the enabled objects each scanline to mask out any
// objects we don't want to be processed
uInt8 myDisabledObjects;
// Indicates if color loss should be enabled or disabled. Color loss
// occurs on PAL (and maybe SECAM) systems when the previous frame
// 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;
// Automatic framerate correction based on number of scanlines
bool myAutoFrameEnabled;
// Number of total frames displayed by this TIA
uInt32 myFrameCounter;
// Number of PAL frames displayed by this TIA
uInt32 myPALFrameCounter;
// The framerate currently in use by the Console
float myFramerate;
// Whether TIA bits/collisions are currently enabled/disabled
bool myBitsEnabled, myCollisionsEnabled;
// Whether to enable jitter emulation
bool myJitterEnabled;
// Derived from the difference between the scanline counts of the
// current and prior frames. If non-zero the next frame should jitter.
Int32 myNextFrameJitter;
// Jitter amount for the current frame
Int32 myCurrentFrameJitter;
// Large jitter values will take multiple frames to recover from
Int32 myJitterRecovery, myJitterRecoveryFactor;
private:
// Following constructors and assignment operators not supported
TIA() = delete;
TIA(const TIA&) = delete;
TIA(TIA&&) = delete;
TIA& operator=(const TIA&) = delete;
TIA& operator=(TIA&&) = delete;
};
} // namespace TIADefaultCore
#endif

View File

@ -1,730 +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-2016 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#include <cassert>
#include "bspf.hxx"
#include "TIATables.hxx"
namespace TIADefaultCore {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIATables::computeAllTables()
{
memset(DisabledMask, 0, 640);
buildCollisionMaskTable();
buildPxMaskTable();
buildMxMaskTable();
buildBLMaskTable();
buildPFMaskTable();
buildGRPReflectTable();
buildPxPosResetWhenTable();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIATables::buildCollisionMaskTable()
{
for(uInt8 i = 0; i < 64; ++i)
{
CollisionMask[i] = 0;
if((i & M0Bit) && (i & P1Bit)) // M0-P1
CollisionMask[i] |= Cx_M0P1;
if((i & M0Bit) && (i & P0Bit)) // M0-P0
CollisionMask[i] |= Cx_M0P0;
if((i & M1Bit) && (i & P0Bit)) // M1-P0
CollisionMask[i] |= Cx_M1P0;
if((i & M1Bit) && (i & P1Bit)) // M1-P1
CollisionMask[i] |= Cx_M1P1;
if((i & P0Bit) && (i & PFBit)) // P0-PF
CollisionMask[i] |= Cx_P0PF;
if((i & P0Bit) && (i & BLBit)) // P0-BL
CollisionMask[i] |= Cx_P0BL;
if((i & P1Bit) && (i & PFBit)) // P1-PF
CollisionMask[i] |= Cx_P1PF;
if((i & P1Bit) && (i & BLBit)) // P1-BL
CollisionMask[i] |= Cx_P1BL;
if((i & M0Bit) && (i & PFBit)) // M0-PF
CollisionMask[i] |= Cx_M0PF;
if((i & M0Bit) && (i & BLBit)) // M0-BL
CollisionMask[i] |= Cx_M0BL;
if((i & M1Bit) && (i & PFBit)) // M1-PF
CollisionMask[i] |= Cx_M1PF;
if((i & M1Bit) && (i & BLBit)) // M1-BL
CollisionMask[i] |= Cx_M1BL;
if((i & BLBit) && (i & PFBit)) // BL-PF
CollisionMask[i] |= Cx_BLPF;
if((i & P0Bit) && (i & P1Bit)) // P0-P1
CollisionMask[i] |= Cx_P0P1;
if((i & M0Bit) && (i & M1Bit)) // M0-M1
CollisionMask[i] |= Cx_M0M1;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [suppress mode:2][nusiz:8][pixel:320]
// suppress=1: suppress on
// suppress=0: suppress off
void TIATables::buildPxMaskTable()
{
Int32 x, suppress, nusiz;
// Set the player mask table to all zeros
for(nusiz = 0; nusiz < 8; ++nusiz)
for(x = 0; x < 160; ++x)
PxMask[0][nusiz][x] = PxMask[1][nusiz][x] = 0x00;
// Now, compute the player mask table
for(suppress = 0; suppress < 2; ++suppress)
{
for(nusiz = 0; nusiz < 8; ++nusiz)
{
for(x = 0; x < 160 + 72; ++x)
{
// nusiz:
// 0: one copy
// 1: two copies-close
// 2: two copies-med
// 3: three copies-close
// 4: two copies-wide
// 5: double size player
// 6: 3 copies medium
// 7: quad sized player
switch(nusiz)
{
case 0x00:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
break;
case 0x01:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
else if(((x - 16) >= 0) && ((x - 16) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 16);
break;
case 0x02:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
else if(((x - 32) >= 0) && ((x - 32) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 32);
break;
case 0x03:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
else if(((x - 16) >= 0) && ((x - 16) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 16);
else if(((x - 32) >= 0) && ((x - 32) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 32);
break;
case 0x04:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
else if(((x - 64) >= 0) && ((x - 64) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 64);
break;
case 0x05:
// For some reason in double size nusiz the player's output
// is delayed by one pixel thus we use > instead of >=
if((suppress == 0) && (x > 0) && (x <= 16))
PxMask[suppress][nusiz][x % 160] = 0x80 >> ((x - 1)/2);
break;
case 0x06:
if((suppress == 0) && (x >= 0) && (x < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> x;
else if(((x - 32) >= 0) && ((x - 32) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 32);
else if(((x - 64) >= 0) && ((x - 64) < 8))
PxMask[suppress][nusiz][x % 160] = 0x80 >> (x - 64);
break;
case 0x07:
// For some reason in quad size nusiz the player's output
// is delayed by one pixel thus we use > instead of >=
if((suppress == 0) && (x > 0) && (x <= 32))
PxMask[suppress][nusiz][x % 160] = 0x80 >> ((x - 1)/4);
break;
}
}
// Copy data into wrap-around area
for(x = 0; x < 160; ++x)
PxMask[suppress][nusiz][x + 160] = PxMask[suppress][nusiz][x];
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [number:8][size:5][pixel:320]
void TIATables::buildMxMaskTable()
{
Int32 x, size, number;
// Clear the missle table to start with
for(number = 0; number < 8; ++number)
for(size = 0; size < 5; ++size)
for(x = 0; x < 160; ++x)
MxMask[number][size][x] = false;
for(number = 0; number < 8; ++number)
{
for(size = 0; size < 5; ++size)
{
for(x = 0; x < 160 + 72; ++x)
{
// For the following, size index = 4 is almost exactly the same as
// index = 2; that is, 1 << 2, or 4 colour clocks wide
// To simulate the weirdness in the Cosmic Ark starfield effect,
// each group of 4 pixels has its 3rd pixel blanked
switch(number)
{
// Only one copy of the missle
case 0x00:
case 0x05:
case 0x07:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
// Two copies - close
case 0x01:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 16) >= 0) && ((x - 16) < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 16) >= 0) && ((x - 16) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
// Two copies - medium
case 0x02:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 32) >= 0) && ((x - 32) < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 32) >= 0) && ((x - 32) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
// Three copies - close
case 0x03:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 16) >= 0) && ((x - 16) < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 32) >= 0) && ((x - 32) < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 16) >= 0) && ((x - 16) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 32) >= 0) && ((x - 32) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
// Two copies - wide
case 0x04:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 64) >= 0) && ((x - 64) < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 64) >= 0) && ((x - 64) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
// Three copies - medium
case 0x06:
if(size != 4)
{
if((x >= 0) && (x < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 32) >= 0) && ((x - 32) < (1 << size)))
MxMask[number][size][x % 160] = true;
else if(((x - 64) >= 0) && ((x - 64) < (1 << size)))
MxMask[number][size][x % 160] = true;
}
else
{
if((x >= 0) && (x < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 32) >= 0) && ((x - 32) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
else if(((x - 64) >= 0) && ((x - 64) < (1 << 2)))
MxMask[number][4][x % 160] = ((x - 2) % 4 == 0 ? false : true);
}
break;
}
}
// Copy data into wrap-around area
for(x = 0; x < 160; ++x)
MxMask[number][size][x + 160] =
MxMask[number][size][x];
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [size:4][pixel:320]
void TIATables::buildBLMaskTable()
{
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)
BLMask[size][x] = false;
// Set the necessary fields true
for(x = 0; x < 160 + 8; ++x)
if((x >= 0) && (x < (1 << size)))
BLMask[size][x % 160] = true;
// Copy fields into the wrap-around area of the mask
for(x = 0; x < 160; ++x)
BLMask[size][x + 160] = BLMask[size][x];
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [reflect:2][pixel:160]
// reflect=1: reflection on
// reflect=0: reflection off
void TIATables::buildPFMaskTable()
{
Int32 x;
// Compute playfield mask table for non-reflected mode
for(x = 0; x < 160; ++x)
{
if(x < 16)
PFMask[0][x] = 0x00001 << (x >> 2);
else if(x < 48)
PFMask[0][x] = 0x00800 >> ((x - 16) >> 2);
else if(x < 80)
PFMask[0][x] = 0x01000 << ((x - 48) >> 2);
else if(x < 96)
PFMask[0][x] = 0x00001 << ((x - 80) >> 2);
else if(x < 128)
PFMask[0][x] = 0x00800 >> ((x - 96) >> 2);
else if(x < 160)
PFMask[0][x] = 0x01000 << ((x - 128) >> 2);
}
// Compute playfield mask table for reflected mode
for(x = 0; x < 160; ++x)
{
if(x < 16)
PFMask[1][x] = 0x00001 << (x >> 2);
else if(x < 48)
PFMask[1][x] = 0x00800 >> ((x - 16) >> 2);
else if(x < 80)
PFMask[1][x] = 0x01000 << ((x - 48) >> 2);
else if(x < 112)
PFMask[1][x] = 0x80000 >> ((x - 80) >> 2);
else if(x < 144)
PFMask[1][x] = 0x00010 << ((x - 112) >> 2);
else if(x < 160)
PFMask[1][x] = 0x00008 >> ((x - 144) >> 2);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIATables::buildGRPReflectTable()
{
for(uInt16 i = 0; i < 256; ++i)
{
uInt8 r = 0;
for(uInt16 t = 1; t <= 128; t <<= 1)
r = (r << 1) | ((i & t) ? 0x01 : 0x00);
GRPReflect[i] = r;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// [nusiz:8][old pixel:160][new pixel:160]
void TIATables::buildPxPosResetWhenTable()
{
uInt32 nusiz, oldx, newx;
// Loop through all player nusizs, 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(nusiz = 0; nusiz < 8; ++nusiz)
{
for(oldx = 0; oldx < 160; ++oldx)
{
// Set everything to 0 for non-delay/non-display section
for(newx = 0; newx < 160; ++newx)
PxPosResetWhen[nusiz][oldx][newx] = 0;
// Now, we'll set the entries for non-delay/non-display section
for(newx = 0; newx < 160 + 72 + 5; ++newx)
{
// nusiz:
// 0: one copy
// 1: two copies-close
// 2: two copies-med
// 3: three copies-close
// 4: two copies-wide
// 5: double size player
// 6: 3 copies medium
// 7: quad sized player
switch(nusiz)
{
case 0x00:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x01:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x02:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x03:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 16)) && (newx < (oldx + 16 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 16 + 4) && (newx < (oldx + 16 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x04:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x05:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 16)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x06:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 32)) && (newx < (oldx + 32 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= (oldx + 64)) && (newx < (oldx + 64 + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 32 + 4) && (newx < (oldx + 32 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
else if((newx >= oldx + 64 + 4) && (newx < (oldx + 64 + 4 + 8)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
case 0x07:
if((newx >= oldx) && (newx < (oldx + 4)))
PxPosResetWhen[nusiz][oldx][newx % 160] = -1;
else if((newx >= oldx + 4) && (newx < (oldx + 4 + 32)))
PxPosResetWhen[nusiz][oldx][newx % 160] = 1;
break;
}
}
// Let's do a sanity check on table entries
uInt32 s1 = 0, s2 = 0;
for(newx = 0; newx < 160; ++newx)
{
if(PxPosResetWhen[nusiz][oldx][newx] == -1)
++s1;
if(PxPosResetWhen[nusiz][oldx][newx] == 1)
++s2;
}
assert((s1 % 4 == 0) && (s2 % 8 == 0));
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Int16 TIATables::PokeDelay[64] = {
0, // VSYNC
1, // VBLANK (0) / 1
0, // WSYNC
0, // RSYNC
0, // NUSIZ0
0, // NUSIZ1
0, // COLUP0
0, // COLUP1
0, // COLUPF
0, // COLUBK
0, // CTRLPF
1, // REFP0
1, // REFP1
-1, // PF0 (4) / -1
-1, // PF1 (4) / -1
-1, // PF2 (4) / -1
0, // RESP0
0, // RESP1
8, // RESM0 (0) / 8
8, // RESM1 (0) / 8
0, // RESBL
0, // AUDC0 (-1) / 0
0, // AUDC1 (-1) / 0
0, // AUDF0 (-1) / 0
0, // AUDF1 (-1) / 0
0, // AUDV0 (-1) / 0
0, // AUDV1 (-1) / 0
1, // GRP0
1, // GRP1
1, // ENAM0
1, // ENAM1
1, // ENABL
0, // HMP0
0, // HMP1
0, // HMM0
0, // HMM1
0, // HMBL
0, // VDELP0
0, // VDELP1
0, // VDELBL
0, // RESMP0
0, // RESMP1
3, // HMOVE
0, // HMCLR
0, // CXCLR
// remaining values are undefined TIA write locations
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
};
#if 0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const Int32 TIATables::CompleteMotion[76][16] = {
{ 0, -1, -2, -3, -4, -5, -6, -7, 8, 7, 6, 5, 4, 3, 2, 1}, // HBLANK
{ 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
};
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIATables::PxMask[2][8][320];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIATables::MxMask[8][5][320];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIATables::BLMask[4][320];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIATables::PFMask[2][160];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIATables::GRPReflect[256];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 TIATables::CollisionMask[64];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 TIATables::DisabledMask[640];
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int8 TIATables::PxPosResetWhen[8][160][160];
} // namespace TIADefaultCore

View File

@ -1,122 +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-2016 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id$
//============================================================================
#ifndef TIA_DEFAULT_CORE_TABLES_HXX
#define TIA_DEFAULT_CORE_TABLES_HXX
#include "bspf.hxx"
#include "TIATypes.hxx"
/**
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$
*/
namespace TIADefaultCore {
class TIATables
{
public:
/**
Compute all static tables used by the TIA
*/
static void computeAllTables();
// Player mask table
// [suppress mode][nusiz][pixel]
static uInt8 PxMask[2][8][320];
// Missle mask table (entries are true or false)
// [number][size][pixel]
// There are actually only 4 possible size combinations on a real system
// The fifth size is used for simulating the starfield effect in
// Cosmic Ark and Stay Frosty
static uInt8 MxMask[8][5][320];
// Ball mask table (entries are true or false)
// [size][pixel]
static uInt8 BLMask[4][320];
// Playfield mask table for reflected and non-reflected playfields
// [reflect, pixel]
static uInt32 PFMask[2][160];
// A mask table which can be used when an object is disabled
static uInt8 DisabledMask[640];
// Used to set the collision register to the correct value
static uInt16 CollisionMask[64];
// Indicates the update delay associated with poking at a TIA address
static const Int16 PokeDelay[64];
#if 0
// Used to convert value written in a motion register into
// its internal representation
static const Int32 CompleteMotion[76][16];
#endif
// Indicates if HMOVE blanks should occur for the corresponding cycle
static const bool HMOVEBlankEnableCycles[76];
// Used to reflect a players graphics
static uInt8 GRPReflect[256];
// Indicates if player is being reset during delay, display or other times
// [nusiz][old pixel][new pixel]
static Int8 PxPosResetWhen[8][160][160];
private:
// Compute the collision decode table
static void buildCollisionMaskTable();
// Compute the player mask table
static void buildPxMaskTable();
// Compute the missle mask table
static void buildMxMaskTable();
// Compute the ball mask table
static void buildBLMaskTable();
// Compute playfield mask table
static void buildPFMaskTable();
// Compute the player reflect table
static void buildGRPReflectTable();
// Compute the player position reset when table
static void buildPxPosResetWhenTable();
private:
// Following constructors and assignment operators not supported
TIATables() = delete;
TIATables(const TIATables&) = delete;
TIATables(TIATables&&) = delete;
TIATables& operator=(const TIATables&) = delete;
TIATables& operator=(TIATables&&) = delete;
};
} // namespace TIADefaultCore
#endif

View File

@ -1,11 +0,0 @@
MODULE := src/emucore/tia/core_default
MODULE_OBJS := \
src/emucore/tia/core_default/TIA.o \
src/emucore/tia/core_default/TIATables.o
MODULE_DIRS += \
src/emucore/tia/core_default
# Include common rules
include $(srcdir)/common.rules