Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/gameboy/lcd/lcd.cpp
2 views
1
#include <gameboy/gameboy.hpp>
2
3
//LY = 0-153
4
//Raster = 0-143
5
//Vblank = 144-153
6
7
//LX = 0-455
8
9
#define LCD_CPP
10
namespace GameBoy {
11
12
#include "dmg.cpp"
13
#include "cgb.cpp"
14
#include "mmio/mmio.cpp"
15
#include "serialization.cpp"
16
LCD lcd;
17
18
void LCD::Main() {
19
lcd.main();
20
}
21
22
void LCD::main() {
23
while(true) {
24
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
25
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
26
}
27
28
add_clocks(4);
29
status.lx += 4;
30
if(status.lx >= 456) scanline();
31
32
if(status.display_enable && status.lx == 0) {
33
if(status.interrupt_oam) cpu.interrupt_raise(CPU::Interrupt::Stat);
34
}
35
36
if(status.display_enable && status.lx == 252) {
37
if(status.interrupt_hblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
38
cpu.hblank();
39
}
40
}
41
}
42
43
void LCD::add_clocks(unsigned clocks) {
44
clock += clocks * cpu.frequency;
45
if(clock >= 0 && scheduler.sync != Scheduler::SynchronizeMode::All) {
46
co_switch(scheduler.active_thread = cpu.thread);
47
}
48
}
49
50
void LCD::scanline() {
51
status.lx -= 456;
52
if(++status.ly == 154) frame();
53
54
if(status.display_enable && status.interrupt_lyc == true) {
55
if(status.ly == status.lyc) cpu.interrupt_raise(CPU::Interrupt::Stat);
56
}
57
58
if(status.ly < 144) {
59
system.cgb() == false ? dmg_render() : cgb_render();
60
}
61
62
if(status.display_enable && status.ly == 144) {
63
cpu.interrupt_raise(CPU::Interrupt::Vblank);
64
if(status.interrupt_vblank) cpu.interrupt_raise(CPU::Interrupt::Stat);
65
}
66
}
67
68
void LCD::frame() {
69
interface->videoRefresh(screen);
70
cpu.mmio_joyp_poll();
71
72
status.ly = 0;
73
status.wyc = 0;
74
scheduler.exit(Scheduler::ExitReason::FrameEvent);
75
}
76
77
unsigned LCD::hflip(unsigned data) const {
78
return ((data & 0x8080) >> 7) | ((data & 0x4040) >> 5)
79
| ((data & 0x2020) >> 3) | ((data & 0x1010) >> 1)
80
| ((data & 0x0808) << 1) | ((data & 0x0404) << 3)
81
| ((data & 0x0202) << 5) | ((data & 0x0101) << 7);
82
}
83
84
void LCD::power() {
85
create(Main, 4 * 1024 * 1024);
86
87
for(unsigned n = 0x8000; n <= 0x9fff; n++) bus.mmio[n] = this; //VRAM
88
for(unsigned n = 0xfe00; n <= 0xfe9f; n++) bus.mmio[n] = this; //OAM
89
90
bus.mmio[0xff40] = this; //LCDC
91
bus.mmio[0xff41] = this; //STAT
92
bus.mmio[0xff42] = this; //SCY
93
bus.mmio[0xff43] = this; //SCX
94
bus.mmio[0xff44] = this; //LY
95
bus.mmio[0xff45] = this; //LYC
96
bus.mmio[0xff47] = this; //BGP
97
bus.mmio[0xff48] = this; //OBP0
98
bus.mmio[0xff49] = this; //OBP1
99
bus.mmio[0xff4a] = this; //WY
100
bus.mmio[0xff4b] = this; //WX
101
102
if(system.cgb()) {
103
bus.mmio[0xff4f] = this; //VBK
104
bus.mmio[0xff68] = this; //BGPI
105
bus.mmio[0xff69] = this; //BGPD
106
bus.mmio[0xff6a] = this; //OBPI
107
bus.mmio[0xff6b] = this; //OBPD
108
}
109
110
for(auto &n : screen) n = 0x0000;
111
for(auto &n : line) n = 0x0000;
112
for(auto &n : origin) n = Origin::None;
113
114
for(auto &n : vram) n = 0x00;
115
for(auto &n : oam) n = 0x00;
116
for(auto &n : bgp) n = 0x00;
117
for(auto &n : obp[0]) n = 0x00;
118
for(auto &n : obp[1]) n = 0x00;
119
for(auto &n : bgpd) n = 0x0000;
120
for(auto &n : obpd) n = 0x0000;
121
122
status.lx = 0;
123
status.wyc = 0;
124
125
status.display_enable = 0;
126
status.window_tilemap_select = 0;
127
status.window_display_enable = 0;
128
status.bg_tiledata_select = 0;
129
status.bg_tilemap_select = 0;
130
status.ob_size = 0;
131
status.ob_enable = 0;
132
status.bg_enable = 0;
133
134
status.interrupt_lyc = 0;
135
status.interrupt_oam = 0;
136
status.interrupt_vblank = 0;
137
status.interrupt_hblank = 0;
138
139
status.scy = 0;
140
status.scx = 0;
141
status.ly = 0;
142
status.lyc = 0;
143
status.wy = 0;
144
status.wx = 0;
145
146
status.vram_bank = 0;
147
148
status.bgpi_increment = 0;
149
status.bgpi = 0;
150
151
status.obpi_increment = 0;
152
status.obpi = 0;
153
}
154
155
LCD::LCD() {
156
}
157
158
}
159
160