mirror of
https://github.com/DerKoun/bsnes-hd.git
synced 2025-04-02 10:52:49 -04:00
84 lines
2.7 KiB
C++
84 lines
2.7 KiB
C++
auto PPUcounter::tick() -> void {
|
|
time.hcounter += 2; //increment by smallest unit of time.
|
|
if(time.hcounter == hperiod()) {
|
|
last.hperiod = hperiod();
|
|
time.hcounter = 0;
|
|
tickScanline();
|
|
}
|
|
}
|
|
|
|
auto PPUcounter::tick(uint clocks) -> void {
|
|
time.hcounter += clocks;
|
|
if(time.hcounter >= hperiod()) {
|
|
last.hperiod = hperiod();
|
|
time.hcounter -= hperiod();
|
|
tickScanline();
|
|
}
|
|
}
|
|
|
|
auto PPUcounter::tickScanline() -> void {
|
|
if(++time.vcounter == 128) {
|
|
//it's not important when this is captured: it is only needed at V=240 or V=311.
|
|
time.interlace = ppu.interlace();
|
|
time.vperiod += interlace() && !field();
|
|
}
|
|
|
|
if(vcounter() == vperiod()) {
|
|
last.vperiod = vperiod();
|
|
//this may be off by one until V=128, hence why vperiod() is a private function.
|
|
time.vperiod = Region::NTSC() ? 262 : 312;
|
|
time.vcounter = 0;
|
|
time.field ^= 1;
|
|
}
|
|
|
|
time.hperiod = 1364;
|
|
//NTSC and PAL scanline rates would not match up with color clocks if every scanline were 1364 clocks.
|
|
//to offset for this error, NTSC has one short scanline, and PAL has one long scanline.
|
|
if(Region::NTSC() && interlace() == 0 && field() == 1 && vcounter() == 240) time.hperiod -= 4;
|
|
if(Region::PAL() && interlace() == 1 && field() == 1 && vcounter() == 311) time.hperiod += 4;
|
|
if(scanline) scanline();
|
|
}
|
|
|
|
auto PPUcounter::interlace() const -> bool { return time.interlace; }
|
|
auto PPUcounter::field() const -> bool { return time.field; }
|
|
auto PPUcounter::vcounter() const -> uint { return time.vcounter; }
|
|
auto PPUcounter::hcounter() const -> uint { return time.hcounter; }
|
|
auto PPUcounter::vperiod() const -> uint { return time.vperiod; }
|
|
auto PPUcounter::hperiod() const -> uint { return time.hperiod; }
|
|
|
|
auto PPUcounter::vcounter(uint offset) const -> uint {
|
|
if(offset <= hcounter()) return vcounter();
|
|
if(vcounter() > 0) return vcounter() - 1;
|
|
return last.vperiod - 1;
|
|
}
|
|
|
|
auto PPUcounter::hcounter(uint offset) const -> uint {
|
|
if(offset <= hcounter()) return hcounter() - offset;
|
|
return hcounter() + last.hperiod - offset;
|
|
}
|
|
|
|
//one PPU dot = 4 CPU clocks.
|
|
//
|
|
//PPU dots 323 and 327 are 6 CPU clocks long.
|
|
//this does not apply to NTSC non-interlace scanline 240 on odd fields. this is
|
|
//because the PPU skips one dot to alter the color burst phase of the video signal.
|
|
//it is not known what happens for PAL 1368 clock scanlines.
|
|
//
|
|
//dot 323 range = {1292, 1294, 1296}
|
|
//dot 327 range = {1310, 1312, 1314}
|
|
|
|
auto PPUcounter::hdot() const -> uint {
|
|
if(hperiod() == 1360) {
|
|
return hcounter() >> 2;
|
|
} else {
|
|
return hcounter() - ((hcounter() > 1292) << 1) - ((hcounter() > 1310) << 1) >> 2;
|
|
}
|
|
}
|
|
|
|
auto PPUcounter::reset() -> void {
|
|
time = {};
|
|
last = {};
|
|
|
|
time.vperiod = last.vperiod = Region::NTSC() ? 262 : 312;
|
|
time.hperiod = last.hperiod = 1364;
|
|
}
|