"However, bit 14 of the internal t register that holds the data written to PPUADDR is forced to 0 when writing the PPUADDR high byte"
The result of my not doing so was that fine scroll Y in the temporary VRAM address was not being properly managed, and was off by four by the time the HUD was drawn (and about when PPUADDR was being updated by the game). The fix was to introduce a new bitmask, .bit14 in AddressBitMask and set the relevant bit to 0 when updating the high byte.
In the midst of this investigation, I also discovered a slew of other tiny but potentially significant bugs, including:
A fix for when we increment Y scroll and copy X scroll; the PPU cycles at which we should be doing so were off by one.
A fix for making sure we cache background tile for the next line. The Y value in the OAM byte for a background tile is one less than where it actually is, and so we can don't need to add one to it as long as we cache the tile data on the previous scanline and in horizontal blank. And so we do so on cycle 257 on each line for the next.
A fix which addresses a very subtle potential boolean short-circuit error in the main loop in the PPU tick() function: previously if redrawScreen was already true, we'd neglect to call handleVerticalBlank().
Another fix ensuring that when sprites or background tiles are turned off, that we immediately return a nil color when fetching a color for a sprite or background tile, respectively.
A fix in Register where previously we were not necessarily overwriting bits in setBits().
Two other changes that were made that were more cosmetic than bug fixes:
A volume adjustment for the APU mixer; the volume is now set to 1.0 instead of 0.5.
Improve clarity by explicitly toggling namespace X or namespace Y bits when incrementing X and Y, respectively. This was done by using the more specific bitmasks in AddressBitMask, namely .namespaceX and .namespaceY.
So, the main purpose of this PR was to address the problem of a jumpy HUD in Sky Shark. The problem was due to my overlooking the following subtle statement in the NESDev wiki (https://www.nesdev.org/wiki/PPU_registers#PPUADDR_-_VRAM_address_($2006_write)):
"However, bit 14 of the internal t register that holds the data written to PPUADDR is forced to 0 when writing the PPUADDR high byte"
The result of my not doing so was that fine scroll Y in the temporary VRAM address was not being properly managed, and was off by four by the time the HUD was drawn (and about when PPUADDR was being updated by the game). The fix was to introduce a new bitmask,
.bit14
inAddressBitMask
and set the relevant bit to 0 when updating the high byte.In the midst of this investigation, I also discovered a slew of other tiny but potentially significant bugs, including:
tick()
function: previously ifredrawScreen
was already true, we'd neglect to callhandleVerticalBlank()
.Register
where previously we were not necessarily overwriting bits insetBits()
.Two other changes that were made that were more cosmetic than bug fixes:
AddressBitMask
, namely .namespaceX
and.namespaceY
.