Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/alt/ppu-compatibility/render/bg.cpp
2 views
1
#ifdef PPU_CPP
2
3
//called once at the start of every rendered scanline
4
void PPU::update_bg_info() {
5
const unsigned hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
6
const unsigned width = (!hires ? 256 : 512);
7
8
for(unsigned bg = 0; bg < 4; bg++) {
9
bg_info[bg].th = (regs.bg_tilesize[bg] ? 4 : 3);
10
bg_info[bg].tw = (hires ? 4 : bg_info[bg].th);
11
12
bg_info[bg].mx = (bg_info[bg].th == 4 ? (width << 1) : width);
13
bg_info[bg].my = bg_info[bg].mx;
14
if(regs.bg_scsize[bg] & 0x01) bg_info[bg].mx <<= 1;
15
if(regs.bg_scsize[bg] & 0x02) bg_info[bg].my <<= 1;
16
bg_info[bg].mx--;
17
bg_info[bg].my--;
18
19
bg_info[bg].scy = (regs.bg_scsize[bg] & 0x02) ? (32 << 5) : 0;
20
bg_info[bg].scx = (regs.bg_scsize[bg] & 0x01) ? (32 << 5) : 0;
21
if(regs.bg_scsize[bg] == 3) bg_info[bg].scy <<= 1;
22
}
23
}
24
25
template<unsigned bg>
26
uint16 PPU::bg_get_tile(uint16 x, uint16 y) {
27
x = (x & bg_info[bg].mx) >> bg_info[bg].tw;
28
y = (y & bg_info[bg].my) >> bg_info[bg].th;
29
30
uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f);
31
if(y & 0x20) pos += bg_info[bg].scy;
32
if(x & 0x20) pos += bg_info[bg].scx;
33
34
const uint16 addr = regs.bg_scaddr[bg] + (pos << 1);
35
return vram[addr] + (vram[addr + 1] << 8);
36
}
37
38
#define setpixel_main(x) \
39
if(pixel_cache[x].pri_main < tile_pri) { \
40
pixel_cache[x].pri_main = tile_pri; \
41
pixel_cache[x].bg_main = bg; \
42
pixel_cache[x].src_main = col; \
43
pixel_cache[x].ce_main = false; \
44
}
45
46
#define setpixel_sub(x) \
47
if(pixel_cache[x].pri_sub < tile_pri) { \
48
pixel_cache[x].pri_sub = tile_pri; \
49
pixel_cache[x].bg_sub = bg; \
50
pixel_cache[x].src_sub = col; \
51
pixel_cache[x].ce_sub = false; \
52
}
53
54
template<unsigned mode, unsigned bg, unsigned color_depth>
55
void PPU::render_line_bg(uint8 pri0_pos, uint8 pri1_pos) {
56
if(layer_enabled[bg][0] == false) pri0_pos = 0;
57
if(layer_enabled[bg][1] == false) pri1_pos = 0;
58
if(pri0_pos + pri1_pos == 0) return;
59
60
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) return;
61
62
const bool bg_enabled = regs.bg_enabled[bg];
63
const bool bgsub_enabled = regs.bgsub_enabled[bg];
64
65
const uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : (bg == BG2) ? 0x4000 : 0x0000;
66
const uint8 bgpal_index = (mode == 0 ? (bg << 5) : 0);
67
68
const uint8 pal_size = 2 << color_depth; //<<2 (*4), <<4 (*16), <<8 (*256)
69
const uint16 tile_mask = 0x0fff >> color_depth; //0x0fff, 0x07ff, 0x03ff
70
//4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile
71
//index is a tile number count to add to base tile number
72
const unsigned tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth);
73
74
const uint8 *bg_td = bg_tiledata[color_depth];
75
const uint8 *bg_td_state = bg_tiledata_state[color_depth];
76
77
const uint8 tile_width = bg_info[bg].tw;
78
const uint8 tile_height = bg_info[bg].th;
79
const uint16 mask_x = bg_info[bg].mx; //screen width mask
80
const uint16 mask_y = bg_info[bg].my; //screen height mask
81
82
uint16 y = regs.bg_y[bg];
83
uint16 hscroll = regs.bg_hofs[bg];
84
uint16 vscroll = regs.bg_vofs[bg];
85
86
const unsigned hires = (mode == 5 || mode == 6);
87
const unsigned width = (!hires ? 256 : 512);
88
89
if(hires) {
90
hscroll <<= 1;
91
if(regs.interlace) y = (y << 1) + field();
92
}
93
94
uint16 hval, vval;
95
uint16 tile_pri, tile_num;
96
uint8 pal_index, pal_num;
97
uint16 hoffset, voffset, opt_x, col;
98
bool mirror_x, mirror_y;
99
100
const uint8 *tile_ptr;
101
const uint16 *mtable = mosaic_table[regs.mosaic_enabled[bg] ? regs.mosaic_size : 0];
102
const bool is_opt_mode = (mode == 2 || mode == 4 || mode == 6);
103
const bool is_direct_color_mode = (regs.direct_color == true && bg == BG1 && (mode == 3 || mode == 4));
104
105
build_window_tables(bg);
106
const uint8 *wt_main = window[bg].main;
107
const uint8 *wt_sub = window[bg].sub;
108
109
uint16 prev_x = 0xffff, prev_y = 0xffff, prev_optx = 0xffff;
110
for(uint16 x = 0; x < width; x++) {
111
hoffset = mtable[x] + hscroll;
112
voffset = y + vscroll;
113
114
if(is_opt_mode) {
115
opt_x = (x + (hscroll & 7));
116
117
//tile 0 is unaffected by OPT mode...
118
if(opt_x >= 8) {
119
//cache tile data in hval, vval if possible
120
if((opt_x >> 3) != (prev_optx >> 3)) {
121
prev_optx = opt_x;
122
123
hval = bg_get_tile<BG3>((opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3]);
124
if(mode != 4) {
125
vval = bg_get_tile<BG3>((opt_x - 8) + (regs.bg_hofs[BG3] & ~7), regs.bg_vofs[BG3] + 8);
126
}
127
}
128
129
if(mode == 4) {
130
if(hval & opt_valid_bit) {
131
if(!(hval & 0x8000)) {
132
hoffset = opt_x + (hval & ~7);
133
} else {
134
voffset = y + hval;
135
}
136
}
137
} else {
138
if(hval & opt_valid_bit) {
139
hoffset = opt_x + (hval & ~7);
140
}
141
if(vval & opt_valid_bit) {
142
voffset = y + vval;
143
}
144
}
145
}
146
}
147
148
hoffset &= mask_x;
149
voffset &= mask_y;
150
151
if((hoffset >> 3) != prev_x || (voffset >> 3) != prev_y) {
152
prev_x = (hoffset >> 3);
153
prev_y = (voffset >> 3);
154
155
tile_num = bg_get_tile<bg>(hoffset, voffset); //format = vhopppcc cccccccc
156
mirror_y = (tile_num & 0x8000);
157
mirror_x = (tile_num & 0x4000);
158
tile_pri = (tile_num & 0x2000) ? pri1_pos : pri0_pos;
159
pal_num = ((tile_num >> 10) & 7);
160
pal_index = bgpal_index + (pal_num << pal_size);
161
162
if(tile_width == 4) { //16x16 horizontal tile mirroring
163
if((bool)(hoffset & 8) != mirror_x) tile_num++;
164
}
165
166
if(tile_height == 4) { //16x16 vertical tile mirroring
167
if((bool)(voffset & 8) != mirror_y) tile_num += 16;
168
}
169
170
tile_num &= 0x03ff;
171
tile_num += tiledata_index;
172
tile_num &= tile_mask;
173
174
if(bg_td_state[tile_num] == 1) {
175
render_bg_tile<color_depth>(tile_num);
176
}
177
178
if(mirror_y) voffset ^= 7; //invert y tile pos
179
tile_ptr = bg_td + (tile_num * 64) + ((voffset & 7) * 8);
180
}
181
182
if(mirror_x) hoffset ^= 7; //invert x tile pos
183
col = *(tile_ptr + (hoffset & 7));
184
if(col) {
185
if(is_direct_color_mode) {
186
col = get_direct_color(pal_num, col);
187
} else {
188
col = get_palette(col + pal_index);
189
}
190
191
if(!hires) {
192
if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); }
193
if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); }
194
} else {
195
int hx = x >> 1;
196
if(x & 1) {
197
if(bg_enabled == true && !wt_main[hx]) { setpixel_main(hx); }
198
} else {
199
if(bgsub_enabled == true && !wt_sub[hx]) { setpixel_sub(hx); }
200
}
201
}
202
}
203
}
204
}
205
206
#undef setpixel_main
207
#undef setpixel_sub
208
209
#endif
210
211