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