Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/gameboy/cpu/cpu.cpp
2 views
1
#include <gameboy/gameboy.hpp>
2
3
#include <snes/snes.hpp>
4
5
#define CPU_CPP
6
namespace GameBoy {
7
8
#include "core/core.cpp"
9
#include "mmio/mmio.cpp"
10
#include "timing/timing.cpp"
11
#include "serialization.cpp"
12
CPU cpu;
13
14
void CPU::Main() {
15
cpu.main();
16
}
17
18
void CPU::main() {
19
while(true) {
20
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
21
scheduler.sync = Scheduler::SynchronizeMode::All;
22
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
23
}
24
25
if(trace) print(disassemble(r[PC]), "\n");
26
interrupt_test();
27
uint8 opcode = op_read(r[PC]++);
28
(this->*opcode_table[opcode])();
29
}
30
}
31
32
void CPU::interrupt_raise(CPU::Interrupt id) {
33
if(id == Interrupt::Vblank) {
34
status.interrupt_request_vblank = 1;
35
if(status.interrupt_enable_vblank) status.halt = false;
36
}
37
38
if(id == Interrupt::Stat) {
39
status.interrupt_request_stat = 1;
40
if(status.interrupt_enable_stat) status.halt = false;
41
}
42
43
if(id == Interrupt::Timer) {
44
status.interrupt_request_timer = 1;
45
if(status.interrupt_enable_timer) status.halt = false;
46
}
47
48
if(id == Interrupt::Serial) {
49
status.interrupt_request_serial = 1;
50
if(status.interrupt_enable_serial) status.halt = false;
51
}
52
53
if(id == Interrupt::Joypad) {
54
status.interrupt_request_joypad = 1;
55
if(status.interrupt_enable_joypad) status.halt = status.stop = false;
56
}
57
}
58
59
void CPU::interrupt_test() {
60
if(status.ime) {
61
if(status.interrupt_request_vblank && status.interrupt_enable_vblank) {
62
status.interrupt_request_vblank = 0;
63
return interrupt_exec(0x0040);
64
}
65
66
if(status.interrupt_request_stat && status.interrupt_enable_stat) {
67
status.interrupt_request_stat = 0;
68
return interrupt_exec(0x0048);
69
}
70
71
if(status.interrupt_request_timer && status.interrupt_enable_timer) {
72
status.interrupt_request_timer = 0;
73
return interrupt_exec(0x0050);
74
}
75
76
if(status.interrupt_request_serial && status.interrupt_enable_serial) {
77
status.interrupt_request_serial = 0;
78
return interrupt_exec(0x0058);
79
}
80
81
if(status.interrupt_request_joypad && status.interrupt_enable_joypad) {
82
status.interrupt_request_joypad = 0;
83
return interrupt_exec(0x0060);
84
}
85
}
86
}
87
88
void CPU::interrupt_exec(uint16 pc) {
89
status.ime = 0;
90
op_write(--r[SP], r[PC] >> 8);
91
op_write(--r[SP], r[PC] >> 0);
92
r[PC] = pc;
93
op_io();
94
op_io();
95
op_io();
96
}
97
98
void CPU::power() {
99
create(Main, 4 * 1024 * 1024);
100
101
for(unsigned n = 0xc000; n <= 0xdfff; n++) bus.mmio[n] = this; //WRAM
102
for(unsigned n = 0xe000; n <= 0xfdff; n++) bus.mmio[n] = this; //WRAM (mirror)
103
for(unsigned n = 0xff80; n <= 0xfffe; n++) bus.mmio[n] = this; //HRAM
104
105
bus.mmio[0xff00] = this; //JOYP
106
bus.mmio[0xff01] = this; //SB
107
bus.mmio[0xff02] = this; //SC
108
bus.mmio[0xff04] = this; //DIV
109
bus.mmio[0xff05] = this; //TIMA
110
bus.mmio[0xff06] = this; //TMA
111
bus.mmio[0xff07] = this; //TAC
112
bus.mmio[0xff0f] = this; //IF
113
bus.mmio[0xff46] = this; //DMA
114
bus.mmio[0xffff] = this; //IE
115
116
if(system.cgb()) {
117
bus.mmio[0xff4d] = this; //KEY1
118
bus.mmio[0xff51] = this; //HDMA1
119
bus.mmio[0xff52] = this; //HDMA2
120
bus.mmio[0xff53] = this; //HDMA3
121
bus.mmio[0xff54] = this; //HDMA4
122
bus.mmio[0xff55] = this; //HDMA5
123
bus.mmio[0xff56] = this; //RP
124
bus.mmio[0xff6c] = this; //???
125
bus.mmio[0xff70] = this; //SVBK
126
bus.mmio[0xff72] = this; //???
127
bus.mmio[0xff73] = this; //???
128
bus.mmio[0xff74] = this; //???
129
bus.mmio[0xff75] = this; //???
130
bus.mmio[0xff76] = this; //???
131
bus.mmio[0xff77] = this; //???
132
}
133
134
for(unsigned n = 0; n < 32768; n++) wram[n] = 0x00;
135
for(unsigned n = 0; n < 8192; n++) hram[n] = 0x00;
136
137
r[PC] = 0x0000;
138
r[SP] = 0x0000;
139
r[AF] = 0x0000;
140
r[BC] = 0x0000;
141
r[DE] = 0x0000;
142
r[HL] = 0x0000;
143
144
status.clock = 0;
145
status.halt = false;
146
status.stop = false;
147
status.ei = false;
148
status.ime = 0;
149
150
status.p15 = 0;
151
status.p14 = 0;
152
status.joyp = 0;
153
status.mlt_req = 0;
154
155
status.serial_data = 0;
156
status.serial_bits = 0;
157
158
status.serial_transfer = 0;
159
status.serial_clock = 0;
160
161
status.div = 0;
162
163
status.tima = 0;
164
165
status.tma = 0;
166
167
status.timer_enable = 0;
168
status.timer_clock = 0;
169
170
status.interrupt_request_joypad = 0;
171
status.interrupt_request_serial = 0;
172
status.interrupt_request_timer = 0;
173
status.interrupt_request_stat = 0;
174
status.interrupt_request_vblank = 0;
175
176
status.speed_double = 0;
177
status.speed_switch = 0;
178
179
status.dma_source = 0;
180
status.dma_target = 0;
181
182
status.dma_mode = 0;
183
status.dma_length = 0;
184
185
status.ff6c = 0;
186
status.ff72 = 0;
187
status.ff73 = 0;
188
status.ff74 = 0;
189
status.ff75 = 0;
190
191
status.wram_bank = 1;
192
193
status.interrupt_enable_joypad = 0;
194
status.interrupt_enable_serial = 0;
195
status.interrupt_enable_timer = 0;
196
status.interrupt_enable_stat = 0;
197
status.interrupt_enable_vblank = 0;
198
}
199
200
CPU::CPU()
201
: trace(false)
202
, wram(nullptr)
203
, hram(nullptr)
204
{
205
initialize_opcode_table();
206
}
207
208
CPU::~CPU()
209
{
210
SNES::interface()->freeSharedMemory(wram);
211
SNES::interface()->freeSharedMemory(hram);
212
}
213
214
void CPU::initialize()
215
{
216
wram = (uint8*)SNES::interface()->allocSharedMemory("SGB_WRAM", 32768);
217
hram = (uint8*)SNES::interface()->allocSharedMemory("SGB_HRAM", 8192);
218
}
219
220
} //namespace GameBoy
221
222