Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/ppu/screen/screen.cpp
2 views
1
#ifdef PPU_CPP
2
3
void PPU::Screen::scanline() {
4
output = self.output + self.vcounter() * 1024;
5
if(self.display.interlace && self.field()) output += 512;
6
}
7
8
void PPU::Screen::run() {
9
if(ppu.vcounter() == 0) return;
10
11
uint32 color;
12
if(self.regs.pseudo_hires == false && self.regs.bgmode != 5 && self.regs.bgmode != 6) {
13
color = get_pixel(0);
14
*output++ = color;
15
*output++ = color;
16
} else {
17
color = get_pixel(1);
18
*output++ = color;
19
color = get_pixel(0);
20
*output++ = color;
21
}
22
}
23
24
uint32 PPU::Screen::get_pixel(bool swap) {
25
if(ppu.regs.overscan == false && ppu.vcounter() >= 225) return 0x0000;
26
27
enum source_t { BG1, BG2, BG3, BG4, OAM, BACK };
28
bool color_enable[] = { regs.bg1_color_enable, regs.bg2_color_enable, regs.bg3_color_enable, regs.bg4_color_enable, regs.oam_color_enable, regs.back_color_enable };
29
30
//===========
31
//main screen
32
//===========
33
34
unsigned priority_main = 0;
35
unsigned color_main;
36
unsigned source_main;
37
38
if(self.bg1.output.main.priority) {
39
priority_main = self.bg1.output.main.priority;
40
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
41
color_main = get_direct_color(self.bg1.output.main.palette, self.bg1.output.main.tile);
42
} else {
43
color_main = get_color(self.bg1.output.main.palette);
44
}
45
source_main = BG1;
46
}
47
if(self.bg2.output.main.priority > priority_main) {
48
priority_main = self.bg2.output.main.priority;
49
color_main = get_color(self.bg2.output.main.palette);
50
source_main = BG2;
51
}
52
if(self.bg3.output.main.priority > priority_main) {
53
priority_main = self.bg3.output.main.priority;
54
color_main = get_color(self.bg3.output.main.palette);
55
source_main = BG3;
56
}
57
if(self.bg4.output.main.priority > priority_main) {
58
priority_main = self.bg4.output.main.priority;
59
color_main = get_color(self.bg4.output.main.palette);
60
source_main = BG4;
61
}
62
if(self.sprite.output.main.priority > priority_main) {
63
priority_main = self.sprite.output.main.priority;
64
color_main = get_color(self.sprite.output.main.palette);
65
source_main = OAM;
66
}
67
if(priority_main == 0) {
68
color_main = get_color(0);
69
source_main = BACK;
70
}
71
72
//==========
73
//sub screen
74
//==========
75
76
unsigned priority_sub = 0;
77
unsigned color_sub;
78
unsigned source_sub;
79
80
if(self.bg1.output.sub.priority) {
81
priority_sub = self.bg1.output.sub.priority;
82
if(regs.direct_color && (self.regs.bgmode == 3 || self.regs.bgmode == 4 || self.regs.bgmode == 7)) {
83
color_sub = get_direct_color(self.bg1.output.sub.palette, self.bg1.output.sub.tile);
84
} else {
85
color_sub = get_color(self.bg1.output.sub.palette);
86
}
87
source_sub = BG1;
88
}
89
if(self.bg2.output.sub.priority > priority_sub) {
90
priority_sub = self.bg2.output.sub.priority;
91
color_sub = get_color(self.bg2.output.sub.palette);
92
source_sub = BG2;
93
}
94
if(self.bg3.output.sub.priority > priority_sub) {
95
priority_sub = self.bg3.output.sub.priority;
96
color_sub = get_color(self.bg3.output.sub.palette);
97
source_sub = BG3;
98
}
99
if(self.bg4.output.sub.priority > priority_sub) {
100
priority_sub = self.bg4.output.sub.priority;
101
color_sub = get_color(self.bg4.output.sub.palette);
102
source_sub = BG4;
103
}
104
if(self.sprite.output.sub.priority > priority_sub) {
105
priority_sub = self.sprite.output.sub.priority;
106
color_sub = get_color(self.sprite.output.sub.palette);
107
source_sub = OAM;
108
}
109
if(priority_sub == 0) {
110
if(self.regs.pseudo_hires == true || self.regs.bgmode == 5 || self.regs.bgmode == 6) {
111
color_sub = get_color(0);
112
} else {
113
color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);
114
}
115
source_sub = BACK;
116
}
117
118
if(swap == true) {
119
std::swap(priority_main, priority_sub);
120
std::swap(color_main, color_sub);
121
std::swap(source_main, source_sub);
122
}
123
124
uint16 output;
125
if(!regs.addsub_mode) {
126
source_sub = BACK;
127
color_sub = (regs.color_b << 10) + (regs.color_g << 5) + (regs.color_r << 0);
128
}
129
130
if(self.window.output.main.color_enable == false) {
131
if(self.window.output.sub.color_enable == false) {
132
return 0x0000;
133
}
134
color_main = 0x0000;
135
}
136
137
bool color_exempt = (source_main == OAM && self.sprite.output.main.palette < 192);
138
if(!color_exempt && color_enable[source_main] && self.window.output.sub.color_enable) {
139
bool halve = false;
140
if(regs.color_halve && self.window.output.main.color_enable) {
141
if(!regs.addsub_mode || source_sub != BACK) halve = true;
142
}
143
output = addsub(color_main, color_sub, halve);
144
} else {
145
output = color_main;
146
}
147
148
//========
149
//lighting
150
//========
151
152
if(self.regs.display_disable) return 0;
153
return (self.regs.display_brightness << 15) | output;
154
}
155
156
uint16 PPU::Screen::addsub(unsigned x, unsigned y, bool halve) {
157
if(!regs.color_mode) {
158
if(!halve) {
159
unsigned sum = x + y;
160
unsigned carry = (sum - ((x ^ y) & 0x0421)) & 0x8420;
161
return (sum - carry) | (carry - (carry >> 5));
162
} else {
163
return (x + y - ((x ^ y) & 0x0421)) >> 1;
164
}
165
} else {
166
unsigned diff = x - y + 0x8420;
167
unsigned borrow = (diff - ((x ^ y) & 0x8420)) & 0x8420;
168
if(!halve) {
169
return (diff - borrow) & (borrow - (borrow >> 5));
170
} else {
171
return (((diff - borrow) & (borrow - (borrow >> 5))) & 0x7bde) >> 1;
172
}
173
}
174
}
175
176
uint16 PPU::Screen::get_color(unsigned palette) {
177
palette <<= 1;
178
self.regs.cgram_iaddr = palette;
179
return ppu.cgram[palette + 0] + (ppu.cgram[palette + 1] << 8);
180
}
181
182
uint16 PPU::Screen::get_direct_color(unsigned palette, unsigned tile) {
183
//palette = -------- BBGGGRRR
184
//tile = ---bgr-- --------
185
//output = 0BBb00GG Gg0RRRr0
186
return ((palette << 7) & 0x6000) + ((tile >> 0) & 0x1000)
187
+ ((palette << 4) & 0x0380) + ((tile >> 5) & 0x0040)
188
+ ((palette << 2) & 0x001c) + ((tile >> 9) & 0x0002);
189
}
190
191
void PPU::Screen::reset() {
192
regs.addsub_mode = random(false);
193
regs.direct_color = random(false);
194
regs.color_mode = random(false);
195
regs.color_halve = random(false);
196
regs.bg1_color_enable = random(false);
197
regs.bg2_color_enable = random(false);
198
regs.bg3_color_enable = random(false);
199
regs.bg4_color_enable = random(false);
200
regs.oam_color_enable = random(false);
201
regs.back_color_enable = random(false);
202
regs.color_r = random(0);
203
regs.color_g = random(0);
204
regs.color_b = random(0);
205
}
206
207
PPU::Screen::Screen(PPU &self) : self(self) {
208
}
209
210
#endif
211
212