Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/alt/ppu-performance/background/background.cpp
2 views
1
#ifdef PPU_CPP
2
3
#include "mode7.cpp"
4
5
unsigned PPU::Background::get_tile(unsigned hoffset, unsigned voffset) {
6
unsigned tile_x = (hoffset & mask_x) >> tile_width;
7
unsigned tile_y = (voffset & mask_y) >> tile_height;
8
9
unsigned tile_pos = ((tile_y & 0x1f) << 5) + (tile_x & 0x1f);
10
if(tile_y & 0x20) tile_pos += scy;
11
if(tile_x & 0x20) tile_pos += scx;
12
13
const uint16 tiledata_addr = regs.screen_addr + (tile_pos << 1);
14
return (ppu.vram[tiledata_addr + 0] << 0) + (ppu.vram[tiledata_addr + 1] << 8);
15
}
16
17
void PPU::Background::offset_per_tile(unsigned x, unsigned y, unsigned &hoffset, unsigned &voffset) {
18
unsigned opt_x = (x + (hscroll & 7)), hval, vval;
19
if(opt_x >= 8) {
20
hval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 0);
21
if(self.regs.bgmode != 4)
22
vval = self.bg3.get_tile((opt_x - 8) + (self.bg3.regs.hoffset & ~7), self.bg3.regs.voffset + 8);
23
24
if(self.regs.bgmode == 4) {
25
if(hval & opt_valid_bit) {
26
if(!(hval & 0x8000)) {
27
hoffset = opt_x + (hval & ~7);
28
} else {
29
voffset = y + hval;
30
}
31
}
32
} else {
33
if(hval & opt_valid_bit) {
34
hoffset = opt_x + (hval & ~7);
35
}
36
if(vval & opt_valid_bit) {
37
voffset = y + vval;
38
}
39
}
40
}
41
}
42
43
void PPU::Background::scanline() {
44
if(self.vcounter() == 1) {
45
mosaic_vcounter = regs.mosaic + 1;
46
mosaic_voffset = 1;
47
} else if(--mosaic_vcounter == 0) {
48
mosaic_vcounter = regs.mosaic + 1;
49
mosaic_voffset += regs.mosaic + 1;
50
}
51
if(self.regs.display_disable) return;
52
53
hires = (self.regs.bgmode == 5 || self.regs.bgmode == 6);
54
width = !hires ? 256 : 512;
55
56
tile_height = regs.tile_size ? 4 : 3;
57
tile_width = hires ? 4 : tile_height;
58
59
mask_x = (tile_height == 4 ? width << 1 : width);
60
mask_y = mask_x;
61
if(regs.screen_size & 1) mask_x <<= 1;
62
if(regs.screen_size & 2) mask_y <<= 1;
63
mask_x--;
64
mask_y--;
65
66
scx = (regs.screen_size & 1 ? 32 << 5 : 0);
67
scy = (regs.screen_size & 2 ? 32 << 5 : 0);
68
if(regs.screen_size == 3) scy <<= 1;
69
}
70
71
void PPU::Background::render() {
72
if(regs.mode == Mode::Inactive) return;
73
if(regs.main_enable == false && regs.sub_enable == false) return;
74
75
if(regs.main_enable) window.render(0);
76
if(regs.sub_enable) window.render(1);
77
if(regs.mode == Mode::Mode7) return render_mode7();
78
79
unsigned priority0 = (priority0_enable ? regs.priority0 : 0);
80
unsigned priority1 = (priority1_enable ? regs.priority1 : 0);
81
if(priority0 + priority1 == 0) return;
82
83
unsigned mosaic_hcounter = 1;
84
unsigned mosaic_palette = 0;
85
unsigned mosaic_priority = 0;
86
unsigned mosaic_color = 0;
87
88
const unsigned bgpal_index = (self.regs.bgmode == 0 ? id << 5 : 0);
89
const unsigned pal_size = 2 << regs.mode;
90
const unsigned tile_mask = 0x0fff >> regs.mode;
91
const unsigned tiledata_index = regs.tiledata_addr >> (4 + regs.mode);
92
93
hscroll = regs.hoffset;
94
vscroll = regs.voffset;
95
96
unsigned y = (regs.mosaic == 0 ? self.vcounter() : mosaic_voffset);
97
if(hires) {
98
hscroll <<= 1;
99
if(self.regs.interlace) y = (y << 1) + self.field();
100
}
101
102
unsigned tile_pri, tile_num;
103
unsigned pal_index, pal_num;
104
unsigned hoffset, voffset, col;
105
bool mirror_x, mirror_y;
106
107
const bool is_opt_mode = (self.regs.bgmode == 2 || self.regs.bgmode == 4 || self.regs.bgmode == 6);
108
const bool is_direct_color_mode = (self.screen.regs.direct_color == true && id == ID::BG1 && (self.regs.bgmode == 3 || self.regs.bgmode == 4));
109
110
signed x = 0 - (hscroll & 7);
111
while(x < width) {
112
hoffset = x + hscroll;
113
voffset = y + vscroll;
114
if(is_opt_mode) offset_per_tile(x, y, hoffset, voffset);
115
hoffset &= mask_x;
116
voffset &= mask_y;
117
118
tile_num = get_tile(hoffset, voffset);
119
mirror_y = tile_num & 0x8000;
120
mirror_x = tile_num & 0x4000;
121
tile_pri = tile_num & 0x2000 ? priority1 : priority0;
122
pal_num = (tile_num >> 10) & 7;
123
pal_index = (bgpal_index + (pal_num << pal_size)) & 0xff;
124
125
if(tile_width == 4 && (bool)(hoffset & 8) != mirror_x) tile_num += 1;
126
if(tile_height == 4 && (bool)(voffset & 8) != mirror_y) tile_num += 16;
127
tile_num = ((tile_num & 0x03ff) + tiledata_index) & tile_mask;
128
129
if(mirror_y) voffset ^= 7;
130
unsigned mirror_xmask = !mirror_x ? 0 : 7;
131
132
uint8 *tiledata = self.cache.tile(regs.mode, tile_num);
133
tiledata += ((voffset & 7) * 8);
134
135
for(unsigned n = 0; n < 8; n++, x++) {
136
if(x & width) continue;
137
if(--mosaic_hcounter == 0) {
138
mosaic_hcounter = regs.mosaic + 1;
139
mosaic_palette = tiledata[n ^ mirror_xmask];
140
mosaic_priority = tile_pri;
141
if(is_direct_color_mode) {
142
mosaic_color = self.screen.get_direct_color(pal_num, mosaic_palette);
143
} else {
144
mosaic_color = self.screen.get_palette(pal_index + mosaic_palette);
145
}
146
}
147
if(mosaic_palette == 0) continue;
148
149
if(hires == false) {
150
if(regs.main_enable && !window.main[x]) self.screen.output.plot_main(x, mosaic_color, mosaic_priority, id);
151
if(regs.sub_enable && !window.sub[x]) self.screen.output.plot_sub(x, mosaic_color, mosaic_priority, id);
152
} else {
153
signed half_x = x >> 1;
154
if(x & 1) {
155
if(regs.main_enable && !window.main[half_x]) self.screen.output.plot_main(half_x, mosaic_color, mosaic_priority, id);
156
} else {
157
if(regs.sub_enable && !window.sub[half_x]) self.screen.output.plot_sub(half_x, mosaic_color, mosaic_priority, id);
158
}
159
}
160
}
161
}
162
}
163
164
PPU::Background::Background(PPU &self, unsigned id) : self(self), id(id) {
165
priority0_enable = true;
166
priority1_enable = true;
167
168
opt_valid_bit = (id == ID::BG1 ? 0x2000 : id == ID::BG2 ? 0x4000 : 0x0000);
169
170
mosaic_table = new uint16*[16];
171
for(unsigned m = 0; m < 16; m++) {
172
mosaic_table[m] = new uint16[4096];
173
for(unsigned x = 0; x < 4096; x++) {
174
mosaic_table[m][x] = (x / (m + 1)) * (m + 1);
175
}
176
}
177
}
178
179
PPU::Background::~Background() {
180
for(unsigned m = 0; m < 16; m++) delete[] mosaic_table[m];
181
delete[] mosaic_table;
182
}
183
184
#endif
185
186