Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/ppu/counter/counter-inline.hpp
2 views
1
//this should only be called by CPU::PPUcounter::tick();
2
//keeps track of previous counter positions in history table
3
void PPUcounter::tick() {
4
status.hcounter += 2; //increment by smallest unit of time
5
if(status.hcounter >= 1360 && status.hcounter == lineclocks()) {
6
status.hcounter = 0;
7
vcounter_tick();
8
}
9
10
history.index = (history.index + 1) & 2047;
11
history.field [history.index] = status.field;
12
history.vcounter[history.index] = status.vcounter;
13
history.hcounter[history.index] = status.hcounter;
14
}
15
16
//this should only be called by PPU::PPUcounter::tick(n);
17
//allows stepping by more than the smallest unit of time
18
void PPUcounter::tick(unsigned clocks) {
19
status.hcounter += clocks;
20
if(status.hcounter >= lineclocks()) {
21
status.hcounter -= lineclocks();
22
vcounter_tick();
23
}
24
}
25
26
//internal
27
void PPUcounter::vcounter_tick() {
28
if(++status.vcounter == 128) status.interlace = ppu.interlace();
29
30
if((system.region() == System::Region::NTSC && status.interlace == false && status.vcounter == 262)
31
|| (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 263)
32
|| (system.region() == System::Region::NTSC && status.interlace == true && status.vcounter == 262 && status.field == 1)
33
|| (system.region() == System::Region::PAL && status.interlace == false && status.vcounter == 312)
34
|| (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 313)
35
|| (system.region() == System::Region::PAL && status.interlace == true && status.vcounter == 312 && status.field == 1)
36
) {
37
status.vcounter = 0;
38
status.field = !status.field;
39
}
40
if(scanline) scanline();
41
}
42
43
bool PPUcounter::field () const { return status.field; }
44
uint16 PPUcounter::vcounter() const { return status.vcounter; }
45
uint16 PPUcounter::hcounter() const { return status.hcounter; }
46
47
bool PPUcounter::field (unsigned offset) const { return history.field [(history.index - (offset >> 1)) & 2047]; }
48
uint16 PPUcounter::vcounter(unsigned offset) const { return history.vcounter[(history.index - (offset >> 1)) & 2047]; }
49
uint16 PPUcounter::hcounter(unsigned offset) const { return history.hcounter[(history.index - (offset >> 1)) & 2047]; }
50
51
//one PPU dot = 4 CPU clocks
52
//
53
//PPU dots 323 and 327 are 6 CPU clocks long.
54
//this does not apply to NTSC non-interlace scanline 240 on odd fields. this is
55
//because the PPU skips one dot to alter the color burst phase of the video signal.
56
//
57
//dot 323 range = { 1292, 1294, 1296 }
58
//dot 327 range = { 1310, 1312, 1314 }
59
60
uint16 PPUcounter::hdot() const {
61
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) {
62
return (hcounter() >> 2);
63
} else {
64
return (hcounter() - ((hcounter() > 1292) << 1) - ((hcounter() > 1310) << 1)) >> 2;
65
}
66
}
67
68
uint16 PPUcounter::lineclocks() const {
69
if(system.region() == System::Region::NTSC && status.interlace == false && vcounter() == 240 && field() == 1) return 1360;
70
return 1364;
71
}
72
73
void PPUcounter::reset() {
74
status.interlace = false;
75
status.field = 0;
76
status.vcounter = 0;
77
status.hcounter = 0;
78
history.index = 0;
79
80
for(unsigned i = 0; i < 2048; i++) {
81
history.field [i] = 0;
82
history.vcounter[i] = 0;
83
history.hcounter[i] = 0;
84
}
85
}
86
87