mirror of https://github.com/stella-emu/stella.git
TIA documentation.
This commit is contained in:
parent
4440aabc56
commit
cd390bcc5a
|
@ -55,12 +55,19 @@
|
||||||
class TIA : public Device
|
class TIA : public Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* These dummy register addresses are used to represent the delayed
|
||||||
|
* old / new register swap on writing GRPx and ENABL in the DelayQueue (see below).
|
||||||
|
*/
|
||||||
enum DummyRegisters: uInt8 {
|
enum DummyRegisters: uInt8 {
|
||||||
shuffleP0 = 0xF0,
|
shuffleP0 = 0xF0,
|
||||||
shuffleP1 = 0xF1,
|
shuffleP1 = 0xF1,
|
||||||
shuffleBL = 0xF2
|
shuffleBL = 0xF2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible palette entries for objects in "fixed debug color mode".
|
||||||
|
*/
|
||||||
enum FixedColor {
|
enum FixedColor {
|
||||||
NTSC_RED = 0x30,
|
NTSC_RED = 0x30,
|
||||||
NTSC_ORANGE = 0x38,
|
NTSC_ORANGE = 0x38,
|
||||||
|
@ -408,48 +415,116 @@ class TIA : public Device
|
||||||
string name() const override { return "TIA"; }
|
string name() const override { return "TIA"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* During each line, the TIA cycles through these two states
|
||||||
|
*/
|
||||||
enum HState {blank, frame};
|
enum HState {blank, frame};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The three different modes of the priority encoder. Check TIA::renderPixel
|
||||||
|
* for a precise definition.
|
||||||
|
*/
|
||||||
enum Priority {pfp, score, normal};
|
enum Priority {pfp, score, normal};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Palette and indices for fixed debug colors.
|
||||||
|
*/
|
||||||
enum FixedObject { P0, M0, P1, M1, PF, BL };
|
enum FixedObject { P0, M0, P1, M1, PF, BL };
|
||||||
FixedColor myFixedColorPalette[2][6];
|
FixedColor myFixedColorPalette[2][6];
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is invoked by FrameManager when a new frame starts
|
||||||
|
*/
|
||||||
void onFrameStart();
|
void onFrameStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is invoked by FrameManager when the visible range of the
|
||||||
|
* current frame starts
|
||||||
|
*/
|
||||||
void onRenderingStart();
|
void onRenderingStart();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This callback is invoked by FrameManager when the current frame completes.
|
||||||
|
*/
|
||||||
void onFrameComplete();
|
void onFrameComplete();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the CPU enters halt state (RDY pulled low). Execution continues
|
||||||
|
* immediatelly afterwards, so we have to adjust the system clock to account
|
||||||
|
* for the cycles the 6502 spent in halt state.
|
||||||
|
*/
|
||||||
void onHalt();
|
void onHalt();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run and forward TIA emulation to the current system clock.
|
||||||
|
*/
|
||||||
void updateEmulation();
|
void updateEmulation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute colorClocks cycles of TIA simulation
|
||||||
|
*/
|
||||||
void cycle(uInt32 colorClocks);
|
void cycle(uInt32 colorClocks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advance the movement logic by a single clock.
|
||||||
|
*/
|
||||||
void tickMovement();
|
void tickMovement();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advance a single clock during hblank.
|
||||||
|
*/
|
||||||
void tickHblank();
|
void tickHblank();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advance a single clock duing the visible part of the scanline.
|
||||||
|
*/
|
||||||
void tickHframe();
|
void tickHframe();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a RSYNC
|
||||||
|
*/
|
||||||
void applyRsync();
|
void applyRsync();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the collision bitfield.
|
||||||
|
*/
|
||||||
void updateCollision();
|
void updateCollision();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the current pixel into the framebuffer
|
||||||
|
*/
|
||||||
void renderPixel(uInt32 x, uInt32 y);
|
void renderPixel(uInt32 x, uInt32 y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the first 8 pixels of a scanline with black if we are in hblank (called during HMOVE)
|
||||||
|
*/
|
||||||
void clearHmoveComb();
|
void clearHmoveComb();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Advance a line and update our state accordingly.
|
||||||
|
*/
|
||||||
void nextLine();
|
void nextLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the last line. Called in nextLine if TIA state was unchanged.
|
||||||
|
*/
|
||||||
void cloneLastLine();
|
void cloneLastLine();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute a delayed write. Called when the DelayQueue is pumped.
|
||||||
|
*/
|
||||||
void delayedWrite(uInt8 address, uInt8 value);
|
void delayedWrite(uInt8 address, uInt8 value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update all paddle readout circuits to the current controller state.
|
||||||
|
*/
|
||||||
void updatePaddle(uInt8 idx);
|
void updatePaddle(uInt8 idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the target counter value during a RESx. This exentially depends on the position
|
||||||
|
* in the current scanline.
|
||||||
uInt8 resxCounter();
|
uInt8 resxCounter();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -470,12 +545,32 @@ class TIA : public Device
|
||||||
Sound& mySound;
|
Sound& mySound;
|
||||||
Settings& mySettings;
|
Settings& mySettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The length of the delay queue (maximum number of clocks delay)
|
||||||
|
*/
|
||||||
static constexpr unsigned delayQueueLength = 16;
|
static constexpr unsigned delayQueueLength = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the delay queue (maximum number of writes scheduled in a single slot).
|
||||||
|
*/
|
||||||
static constexpr unsigned delayQueueSize = 16;
|
static constexpr unsigned delayQueueSize = 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of delayed writes that are queued up for future execution. Delayed
|
||||||
|
* writes can be both actual writes whose effect is delayed by one or more clocs
|
||||||
|
* on real hardware and delayed side effects of certain operations (GRPx!).
|
||||||
|
*/
|
||||||
DelayQueue<delayQueueLength, delayQueueSize> myDelayQueue;
|
DelayQueue<delayQueueLength, delayQueueSize> myDelayQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The frame manager is responsible for detecting frame boundaries and the visible
|
||||||
|
* region of each frame.
|
||||||
|
*/
|
||||||
FrameManager myFrameManager;
|
FrameManager myFrameManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The various TIA objects.
|
||||||
|
*/
|
||||||
Background myBackground;
|
Background myBackground;
|
||||||
Playfield myPlayfield;
|
Playfield myPlayfield;
|
||||||
Missile myMissile0;
|
Missile myMissile0;
|
||||||
|
@ -483,8 +578,15 @@ class TIA : public Device
|
||||||
Player myPlayer0;
|
Player myPlayer0;
|
||||||
Player myPlayer1;
|
Player myPlayer1;
|
||||||
Ball myBall;
|
Ball myBall;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The paddle readout circuits.
|
||||||
|
*/
|
||||||
PaddleReader myPaddleReaders[4];
|
PaddleReader myPaddleReaders[4];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Circuits for the "latched inputs".
|
||||||
|
*/
|
||||||
LatchedInput myInput0;
|
LatchedInput myInput0;
|
||||||
LatchedInput myInput1;
|
LatchedInput myInput1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue