Path: blob/master/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp
2 views
//this should only be called by CPU::PPUcounter::tick();1//keeps track of previous counter positions in history table2void PPUcounter::tick() {3status.hcounter += 2; //increment by smallest unit of time4if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {5status.hcounter = 0;6vcounter_tick();7}89history.index = (history.index + 1) & 2047;10history.field [history.index] = status.field;11history.vcounter[history.index] = status.vcounter;12history.hcounter[history.index] = status.hcounter;13}1415//this should only be called by PPU::PPUcounter::tick(n);16//allows stepping by more than the smallest unit of time17void PPUcounter::tick(unsigned clocks) {18status.hcounter += clocks;19if(status.hcounter >= lineclocks()) {20status.hcounter -= lineclocks();21vcounter_tick();22}23}2425//internal26void PPUcounter::vcounter_tick() {27if(++status.vcounter == 128) status.interlace = ppu.interlace();2829if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)30|| (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 263)31|| (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 262 && status.field == 1)32|| (system.region() == System::Region::PAL && status.interlace == false && status.vcounter == 312)33|| (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 313)34|| (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 312 && status.field == 1)35) {36status.vcounter = 0;37status.field = !status.field;38}39if(scanline) scanline();40}4142bool PPUcounter::field () const { return status.field; }43uint16 PPUcounter::vcounter() const { return status.vcounter; }44uint16 PPUcounter::hcounter() const { return status.hcounter; }4546bool PPUcounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }47uint16 PPUcounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }48uint16 PPUcounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }4950//one PPU dot = 4 CPU clocks51//52//PPU dots 323 and 327 are 6 CPU clocks long.53//this does not apply to NTSC non-interlace scanline 240 on odd fields. this is54//because the PPU skips one dot to alter the color burst phase of the video signal.55//56//dot 323 range = { 1292, 1294, 1296 }57//dot 327 range = { 1310, 1312, 1314 }5859uint16 PPUcounter::hdot() const {60if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {61return (hcounter() >> 2);62} else {63return (hcounter() - ((hcounter() > 1292) << 1) - ((hcounter() > 1310) << 1)) >> 2;64}65}6667uint16 PPUcounter::lineclocks() const {68if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;69return 1364;70}7172void PPUcounter::reset() {73status.interlace = false;74status.field = 0;75status.vcounter = 0;76status.hcounter = 0;77history.index = 0;7879for(unsigned i = 0; i < 2048; i++) {80history.field [i] = 0;81history.vcounter[i] = 0;82history.hcounter[i] = 0;83}84}858687