1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-12-24 12:30:17 +00:00

Introduced a separate queue for pixels, which may or may not be correct.

This commit is contained in:
Thomas Harte 2016-05-24 21:39:57 -04:00
parent 0b081831a9
commit 758806f924
2 changed files with 38 additions and 34 deletions

View File

@ -23,7 +23,8 @@ Machine::Machine() :
_rom(nullptr),
_piaDataValue{0xff, 0xff},
_tiaInputValue{0xff, 0xff},
_upcomingEventsPointer(0)
_upcomingEventsPointer(0),
_upcomingPixelsPointer(0)
{
memset(_collisions, 0xff, sizeof(_collisions));
set_reset_line(true);
@ -83,6 +84,8 @@ void Machine::update_timers(int mask)
unsigned int upcomingEventsPointerPlus1 = (_upcomingEventsPointer + 1)%number_of_upcoming_events;
unsigned int upcomingEventsPointerPlus2 = (_upcomingEventsPointer + 2)%number_of_upcoming_events;
unsigned int upcomingPixelsPointerPlus4 = (_upcomingPixelsPointer + 4)%number_of_upcoming_events;
// grab the background now, for display in four clocks
if(mask & (1 << 5))
{
@ -90,7 +93,7 @@ void Machine::update_timers(int mask)
{
unsigned int offset = 4 + _horizontalTimer - (horizontalTimerPeriod - 160);
_upcomingEvents[upcomingEventsPointerPlus4].updates |= Event::Action::Playfield;
_upcomingEvents[upcomingEventsPointerPlus4].pixels |= _playfield[(offset >> 2)%40] << 5;
_upcomingEvents[upcomingEventsPointerPlus4].playfieldPixel = _playfield[(offset >> 2)%40];
}
}
@ -102,7 +105,7 @@ void Machine::update_timers(int mask)
if(_pixelCounter[4] < 8 && _ballGraphicsEnable[_ballGraphicsSelector]&2) {
int ballSize = 1 << ((_playfieldControl >> 4)&3);
_upcomingEvents[upcomingEventsPointerPlus4].pixels |= (_pixelCounter[4] < ballSize) ? (1 << 4) : 0;
_upcomingPixels[upcomingPixelsPointerPlus4] |= (_pixelCounter[4] < ballSize) ? (1 << 4) : 0;
}
_objectCounter[4] = (_objectCounter[4] + 1)%160;
@ -146,12 +149,15 @@ void Machine::update_timers(int mask)
{
if(mask & (1 << c))
{
int lastSpriteCounter = _spriteCounter[c];
_spriteCounter[c]++;
uint8_t repeatMask = _playerAndMissileSize[c] & 7;
switch(repeatMask)
{
default: _pixelCounter[c] += 4; break;
case 5: _pixelCounter[c] += 2; break;
case 7: _pixelCounter[c] += 1; break;
default: _pixelCounter[c] ++; break;
case 5: _pixelCounter[c] += ((lastSpriteCounter ^ _spriteCounter[c]) >> 1)&1; break;
case 7: _pixelCounter[c] += ((lastSpriteCounter ^ _spriteCounter[c]) >> 2)&1; break;
}
_objectCounter[c] = (_objectCounter[c] + 1)%160;
}
@ -174,19 +180,23 @@ void Machine::update_timers(int mask)
_upcomingEvents[_upcomingEventsPointer].pixelCounterMask = 0;
}
// reload the playfield pixel if appropriate
if(_upcomingEvents[_upcomingEventsPointer].updates & Event::Action::Playfield)
{
_playfieldOutput = _upcomingEvents[_upcomingEventsPointer].playfieldPixel;
}
// determine the pixel masks
for(int c = 0; c < 2; c++)
{
if(_playerGraphics[c]) {
// figure out player colour
if(_playerGraphics[c] && _pixelCounter[c] < 32) {
int flipMask = (_playerReflection[c]&0x8) ? 0 : 7;
if(_pixelCounter[c] < 32)
_upcomingEvents[upcomingEventsPointerPlus4].pixels |= ((_playerGraphics[_playerGraphicsSelector[c]][c] >> ((_pixelCounter[c] >> 2) ^ flipMask)) & 1) << c;
_upcomingPixels[upcomingPixelsPointerPlus4] |= ((_playerGraphics[_playerGraphicsSelector[c]][c] >> (_pixelCounter[c] ^ flipMask)) & 1) << c;
}
if(_pixelCounter[c+2] < 8 && (_missileGraphicsEnable[c]&2) && !_missileGraphicsReset[c]) {
int missileSize = 1 << ((_playerAndMissileSize[c] >> 4)&3);
_upcomingEvents[upcomingEventsPointerPlus4].pixels |= ((_pixelCounter[c+2] < missileSize) ? 1 : 0) << (c + 2);
_upcomingPixels[upcomingPixelsPointerPlus4] |= ((_pixelCounter[c+2] < missileSize) ? 1 : 0) << (c + 2);
}
}
}
@ -199,18 +209,18 @@ uint8_t Machine::get_output_pixel()
uint8_t playfieldColour = ((_playfieldControl&6) == 2) ? _playerColour[offset / 80] : _playfieldColour;
// get the ball proposed state
uint8_t ballPixel = (_upcomingEvents[_upcomingEventsPointer].pixels >> 4) & 1;
uint8_t ballPixel = (_upcomingPixels[_upcomingPixelsPointer] >> 4) & 1;
// deal with the sprites
uint8_t playerPixels[2] =
{
static_cast<uint8_t>((_upcomingEvents[_upcomingEventsPointer].pixels >> 0) & 1),
static_cast<uint8_t>((_upcomingEvents[_upcomingEventsPointer].pixels >> 1) & 1)
static_cast<uint8_t>((_upcomingPixels[_upcomingPixelsPointer] >> 0) & 1),
static_cast<uint8_t>((_upcomingPixels[_upcomingPixelsPointer] >> 1) & 1)
};
uint8_t missilePixels[2] =
{
static_cast<uint8_t>((_upcomingEvents[_upcomingEventsPointer].pixels >> 2) & 1),
static_cast<uint8_t>((_upcomingEvents[_upcomingEventsPointer].pixels >> 3) & 1),
static_cast<uint8_t>((_upcomingPixels[_upcomingPixelsPointer] >> 2) & 1),
static_cast<uint8_t>((_upcomingPixels[_upcomingPixelsPointer] >> 3) & 1),
};
// accumulate collisions
@ -243,6 +253,10 @@ uint8_t Machine::get_output_pixel()
if(playerPixels[0] || missilePixels[0]) outputColour = _playerColour[0];
}
// update pixel chain
_upcomingPixels[_upcomingPixelsPointer] = 0;
_upcomingPixelsPointer = (_upcomingPixelsPointer + 1)%number_of_upcoming_events;
// return colour
return outputColour;
}
@ -269,12 +283,7 @@ void Machine::output_pixels(unsigned int count)
case 16: case 17: state = _vBlankExtend ? OutputState::Blank : OutputState::Pixel; break;
default: state = OutputState::Pixel; break;
}
// if(!(_horizontalTimer&3) && _vBlankExtend)
// {
// printf("%c", 'a' + state);
// }
// grab background colour and schedule pixel counter resets
// update pixel timers
if(state == OutputState::Pixel)
update_timers(~0);
@ -287,9 +296,6 @@ void Machine::output_pixels(unsigned int count)
_upcomingEvents[(_upcomingEventsPointer+4)%number_of_upcoming_events].state = state;
// apply any queued changes and flush the record
if(_upcomingEvents[_upcomingEventsPointer].updates & Event::Action::Playfield)
_playfieldOutput = (_upcomingEvents[_upcomingEventsPointer].pixels >> 5)&1;
if(_upcomingEvents[_upcomingEventsPointer].updates & Event::Action::HMoveSetup)
{
_upcomingEvents[_upcomingEventsPointer].updates |= Event::Action::HMoveCompare;
@ -329,12 +335,8 @@ void Machine::output_pixels(unsigned int count)
if(_upcomingEvents[_upcomingEventsPointer].updates & Event::Action::HMoveDecrement)
{
update_timers(_hMoveFlags);
// for(int c = 0; c < 5; c++)
// {
// printf("%c", _hMoveFlags & (1 << c) ? 'X' : '-');
// }
// printf(" ");
}
// read that state
state = _upcomingEvents[_upcomingEventsPointer].state;
OutputState actingState = state;
@ -376,7 +378,6 @@ void Machine::output_pixels(unsigned int count)
// advance
_upcomingEvents[_upcomingEventsPointer].updates = 0;
_upcomingEvents[_upcomingEventsPointer].pixels = 0;
_upcomingEventsPointer = (_upcomingEventsPointer + 1)%number_of_upcoming_events;
// advance horizontal timer, perform reset actions if requested

View File

@ -72,12 +72,15 @@ class Machine: public CPU6502::Processor<Machine> {
int pixelCounterMask;
OutputState state;
uint8_t pixels;
uint8_t playfieldPixel;
Event() : updates(0), pixelCounterMask(0), pixels(0) {}
Event() : updates(0), pixelCounterMask(0), playfieldPixel(0) {}
} _upcomingEvents[number_of_upcoming_events];
unsigned int _upcomingEventsPointer;
uint8_t _upcomingPixels[number_of_upcoming_events];
unsigned int _upcomingPixelsPointer;
uint8_t _playfieldOutput;
// player registers
@ -109,7 +112,7 @@ class Machine: public CPU6502::Processor<Machine> {
// object counters
uint8_t _objectCounter[5];
int _pixelCounter[5];
int _pixelCounter[5], _spriteCounter[2];
// joystick state
uint8_t _piaDataDirection[2];