Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/ppu/ppu.cpp
2 views
1
#include <snes/snes.hpp>
2
3
#define PPU_CPP
4
namespace SNES {
5
6
PPU ppu;
7
8
#include "background/background.cpp"
9
#include "mmio/mmio.cpp"
10
#include "screen/screen.cpp"
11
#include "sprite/sprite.cpp"
12
#include "window/window.cpp"
13
#include "serialization.cpp"
14
15
void PPU::step(unsigned clocks) {
16
clock += clocks;
17
}
18
19
void PPU::synchronize_cpu() {
20
if(CPU::Threaded == true) {
21
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) co_switch(cpu.thread);
22
} else {
23
while(clock >= 0) cpu.enter();
24
}
25
}
26
27
void PPU::Enter() { ppu.enter(); }
28
29
void PPU::enter() {
30
while(true) {
31
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
32
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
33
}
34
35
scanline();
36
add_clocks(68);
37
bg1.begin();
38
bg2.begin();
39
bg3.begin();
40
bg4.begin();
41
42
if(vcounter() <= 239) {
43
for(signed pixel = -7; pixel <= 255; pixel++) {
44
bg1.run(1);
45
bg2.run(1);
46
bg3.run(1);
47
bg4.run(1);
48
add_clocks(2);
49
50
bg1.run(0);
51
bg2.run(0);
52
bg3.run(0);
53
bg4.run(0);
54
if(pixel >= 0) {
55
sprite.run();
56
window.run();
57
screen.run();
58
}
59
add_clocks(2);
60
}
61
62
add_clocks(14);
63
sprite.tilefetch();
64
} else {
65
add_clocks(1052 + 14 + 136);
66
}
67
68
add_clocks(lineclocks() - 68 - 1052 - 14 - 136);
69
}
70
}
71
72
void PPU::add_clocks(unsigned clocks) {
73
clocks >>= 1;
74
while(clocks--) {
75
tick(2);
76
step(2);
77
synchronize_cpu();
78
}
79
}
80
81
void PPU::enable() {
82
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
83
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
84
85
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
86
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
87
}
88
89
void PPU::power() {
90
ppu1_version = config.ppu1.version;
91
ppu2_version = config.ppu2.version;
92
93
for(int i=0;i<128*1024;i++) vram[i] = 0;
94
for(int i=0;i<544;i++) oam[i] = 0;
95
for(int i=0;i<512;i++) cgram[i] = 0;
96
97
//not sure about this
98
reset();
99
100
}
101
102
void PPU::reset() {
103
create(Enter, system.cpu_frequency());
104
PPUcounter::reset();
105
memset(surface, 0, 512 * 512 * sizeof(uint32));
106
107
mmio_reset();
108
bg1.reset();
109
bg2.reset();
110
bg3.reset();
111
bg4.reset();
112
sprite.reset();
113
window.reset();
114
screen.reset();
115
116
frame();
117
}
118
119
void PPU::scanline() {
120
if(vcounter() == 0) {
121
frame();
122
bg1.frame();
123
bg2.frame();
124
bg3.frame();
125
bg4.frame();
126
}
127
128
bg1.scanline();
129
bg2.scanline();
130
bg3.scanline();
131
bg4.scanline();
132
sprite.scanline();
133
window.scanline();
134
screen.scanline();
135
}
136
137
void PPU::frame() {
138
system.frame();
139
sprite.frame();
140
141
display.interlace = regs.interlace;
142
display.overscan = regs.overscan;
143
}
144
145
void PPU::layer_enable(unsigned layer, unsigned priority, bool enable)
146
{
147
//TODO
148
}
149
150
void PPU::initialize()
151
{
152
vram = (uint8*)interface()->allocSharedMemory("VRAM",128 * 1024);
153
oam = (uint8*)interface()->allocSharedMemory("OAM",544);
154
cgram = (uint8*)interface()->allocSharedMemory("CGRAM",512);
155
surface = new uint32[512 * 512];
156
output = surface + 16 * 512;
157
}
158
159
PPU::PPU() :
160
bg1(*this, Background::ID::BG1),
161
bg2(*this, Background::ID::BG2),
162
bg3(*this, Background::ID::BG3),
163
bg4(*this, Background::ID::BG4),
164
sprite(*this),
165
window(*this),
166
screen(*this) {
167
168
}
169
170
PPU::~PPU() {
171
delete[] surface;
172
interface()->freeSharedMemory(vram);
173
interface()->freeSharedMemory(oam);
174
interface()->freeSharedMemory(cgram);
175
}
176
177
}
178
179