Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/gameboy/lcd/dmg.cpp
2 views
1
#ifdef LCD_CPP
2
3
void LCD::dmg_render() {
4
for(unsigned n = 0; n < 160; n++) {
5
line[n] = 0x00;
6
origin[n] = Origin::None;
7
}
8
9
if(status.display_enable) {
10
if(status.bg_enable) dmg_render_bg();
11
if(status.window_display_enable) dmg_render_window();
12
if(status.ob_enable) dmg_render_ob();
13
}
14
15
uint16 *output = screen + status.ly * 160;
16
for(unsigned n = 0; n < 160; n++) output[n] = line[n];
17
interface->lcdScanline();
18
}
19
20
uint16 LCD::dmg_read_tile(bool select, unsigned x, unsigned y) {
21
unsigned tmaddr = 0x1800 + (select << 10), tdaddr;
22
tmaddr += (((y >> 3) << 5) + (x >> 3)) & 0x03ff;
23
if(status.bg_tiledata_select == 0) {
24
tdaddr = 0x1000 + ((int8)vram[tmaddr] << 4);
25
} else {
26
tdaddr = 0x0000 + (vram[tmaddr] << 4);
27
}
28
tdaddr += (y & 7) << 1;
29
return (vram[tdaddr + 0] << 0) | (vram[tdaddr + 1] << 8);
30
}
31
32
void LCD::dmg_render_bg() {
33
unsigned iy = (status.ly + status.scy) & 255;
34
unsigned ix = status.scx, tx = ix & 7;
35
unsigned data = dmg_read_tile(status.bg_tilemap_select, ix, iy);
36
37
for(unsigned ox = 0; ox < 160; ox++) {
38
uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0)
39
| ((data & (0x8000 >> tx)) ? 2 : 0);
40
41
line[ox] = bgp[palette];
42
origin[ox] = Origin::BG;
43
44
ix = (ix + 1) & 255;
45
tx = (tx + 1) & 7;
46
47
if(tx == 0) data = dmg_read_tile(status.bg_tilemap_select, ix, iy);
48
}
49
}
50
51
void LCD::dmg_render_window() {
52
if(status.ly - status.wy >= 144u) return;
53
if(status.wx >= 167u) return;
54
unsigned iy = status.wyc++;
55
unsigned ix = (7 - status.wx) & 255, tx = ix & 7;
56
unsigned data = dmg_read_tile(status.window_tilemap_select, ix, iy);
57
58
for(unsigned ox = 0; ox < 160; ox++) {
59
uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0)
60
| ((data & (0x8000 >> tx)) ? 2 : 0);
61
if(ox - (status.wx - 7) < 160u) {
62
line[ox] = bgp[palette];
63
origin[ox] = Origin::BG;
64
}
65
66
ix = (ix + 1) & 255;
67
tx = (tx + 1) & 7;
68
69
if(tx == 0) data = dmg_read_tile(status.window_tilemap_select, ix, iy);
70
}
71
}
72
73
//Attributes:
74
//0x80: 0 = OBJ above BG, 1 = BG above OBJ
75
//0x40: vertical flip
76
//0x20: horizontal flip
77
//0x10: palette#
78
void LCD::dmg_render_ob() {
79
const unsigned Height = (status.ob_size == 0 ? 8 : 16);
80
unsigned sprite[10], sprites = 0;
81
82
//find first ten sprites on this scanline
83
for(unsigned s = 0; s < 40; s++) {
84
unsigned sy = oam[(s << 2) + 0] - 16;
85
unsigned sx = oam[(s << 2) + 1] - 8;
86
87
sy = status.ly - sy;
88
if(sy >= Height) continue;
89
90
sprite[sprites++] = s;
91
if(sprites == 10) break;
92
}
93
94
//sort by X-coordinate, when equal, lower address comes first
95
for(unsigned x = 0; x < sprites; x++) {
96
for(unsigned y = x + 1; y < sprites; y++) {
97
signed sx = oam[(sprite[x] << 2) + 1] - 8;
98
signed sy = oam[(sprite[y] << 2) + 1] - 8;
99
if(sy < sx) {
100
sprite[x] ^= sprite[y];
101
sprite[y] ^= sprite[x];
102
sprite[x] ^= sprite[y];
103
}
104
}
105
}
106
107
//render backwards, so that first sprite has highest priority
108
for(signed s = sprites - 1; s >= 0; s--) {
109
unsigned n = sprite[s] << 2;
110
unsigned sy = oam[n + 0] - 16;
111
unsigned sx = oam[n + 1] - 8;
112
unsigned tile = oam[n + 2] & ~status.ob_size;
113
unsigned attr = oam[n + 3];
114
115
sy = status.ly - sy;
116
if(sy >= Height) continue;
117
if(attr & 0x40) sy ^= (Height - 1);
118
119
unsigned tdaddr = (tile << 4) + (sy << 1), data = 0;
120
data |= vram[tdaddr++] << 0;
121
data |= vram[tdaddr++] << 8;
122
if(attr & 0x20) data = hflip(data);
123
124
for(unsigned tx = 0; tx < 8; tx++) {
125
uint8 palette = ((data & (0x0080 >> tx)) ? 1 : 0)
126
| ((data & (0x8000 >> tx)) ? 2 : 0);
127
if(palette == 0) continue;
128
129
palette = obp[(bool)(attr & 0x10)][palette];
130
unsigned ox = sx + tx;
131
132
if(ox < 160) {
133
if(attr & 0x80) {
134
if(origin[ox] == Origin::BG) {
135
if(line[ox] > 0) continue;
136
}
137
}
138
line[ox] = palette;
139
origin[ox] = Origin::OB;
140
}
141
}
142
}
143
}
144
145
#endif
146
147