Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libsnes/bsnes/snes/alt/cpu/cpu.cpp
2 views
1
#include <snes/snes.hpp>
2
3
#define CPU_CPP
4
namespace SNES {
5
6
CPU cpu;
7
8
#include "serialization.cpp"
9
#include "dma.cpp"
10
#include "memory.cpp"
11
#include "mmio.cpp"
12
#include "timing.cpp"
13
14
void CPU::step(unsigned clocks) {
15
smp.clock -= clocks * (uint64)smp.frequency;
16
ppu.clock -= clocks;
17
for(unsigned i = 0; i < coprocessors.size(); i++) {
18
Processor &chip = *coprocessors[i];
19
chip.clock -= clocks * (uint64)chip.frequency;
20
}
21
input.port1->clock -= clocks * (uint64)input.port1->frequency;
22
input.port2->clock -= clocks * (uint64)input.port2->frequency;
23
synchronize_controllers();
24
}
25
26
void CPU::synchronize_smp() {
27
if(SMP::Threaded == true) {
28
if(smp.clock < 0) co_switch(smp.thread);
29
} else {
30
while(smp.clock < 0) smp.enter();
31
}
32
}
33
34
void CPU::synchronize_ppu() {
35
if(PPU::Threaded == true) {
36
if(ppu.clock < 0) co_switch(ppu.thread);
37
} else {
38
while(ppu.clock < 0) ppu.enter();
39
}
40
}
41
42
void CPU::synchronize_coprocessors() {
43
for(unsigned i = 0; i < coprocessors.size(); i++) {
44
Processor &chip = *coprocessors[i];
45
if(chip.clock < 0) co_switch(chip.thread);
46
}
47
}
48
49
void CPU::synchronize_controllers() {
50
if(input.port1->clock < 0) co_switch(input.port1->thread);
51
if(input.port2->clock < 0) co_switch(input.port2->thread);
52
}
53
54
void CPU::Enter() { cpu.enter(); }
55
56
void CPU::enter() {
57
while(true) {
58
if(scheduler.sync == Scheduler::SynchronizeMode::CPU) {
59
scheduler.sync = Scheduler::SynchronizeMode::All;
60
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
61
}
62
63
if(status.nmi_pending) {
64
status.nmi_pending = false;
65
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
66
op_irq();
67
}
68
69
if(status.irq_pending) {
70
status.irq_pending = false;
71
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
72
op_irq();
73
}
74
75
op_step();
76
}
77
}
78
79
alwaysinline void CPU::op_step() {
80
(this->*opcode_table[op_readpcfirst()])();
81
}
82
83
void CPU::enable() {
84
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
85
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
86
87
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
88
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
89
90
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
91
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
92
93
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
94
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
95
96
bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
97
bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
98
99
read = [](unsigned addr) { cdlInfo.set(eCDLog_AddrType_WRAM, addr); return cpu.wram[addr]; };
100
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
101
102
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
103
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
104
bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
105
}
106
107
void CPU::power() {
108
regs.a = 0x0000;
109
regs.x = 0x0000;
110
regs.y = 0x0000;
111
regs.s = 0x01ff;
112
113
reset();
114
}
115
116
void CPU::reset() {
117
create(Enter, system.cpu_frequency());
118
coprocessors.reset();
119
PPUcounter::reset();
120
121
regs.pc = 0x000000;
122
regs.x.h = 0x00;
123
regs.y.h = 0x00;
124
regs.s.h = 0x01;
125
regs.d = 0x0000;
126
regs.db = 0x00;
127
regs.p = 0x34;
128
regs.e = 1;
129
regs.mdr = 0x00;
130
regs.wai = false;
131
update_table();
132
133
regs.pc.l = bus.read(0xfffc);
134
regs.pc.h = bus.read(0xfffd);
135
regs.pc.b = 0x00;
136
137
status.nmi_valid = false;
138
status.nmi_line = false;
139
status.nmi_transition = false;
140
status.nmi_pending = false;
141
142
status.irq_valid = false;
143
status.irq_line = false;
144
status.irq_transition = false;
145
status.irq_pending = false;
146
147
status.irq_lock = false;
148
status.hdma_pending = false;
149
150
status.wram_addr = 0x000000;
151
152
status.joypad_strobe_latch = 0;
153
154
status.nmi_enabled = false;
155
status.virq_enabled = false;
156
status.hirq_enabled = false;
157
status.auto_joypad_poll_enabled = false;
158
159
status.pio = 0xff;
160
161
status.htime = 0x0000;
162
status.vtime = 0x0000;
163
164
status.rom_speed = 8;
165
166
status.joy1l = status.joy1h = 0x00;
167
status.joy2l = status.joy2h = 0x00;
168
status.joy3l = status.joy3h = 0x00;
169
status.joy4l = status.joy4h = 0x00;
170
171
dma_reset();
172
}
173
174
CPU::CPU()
175
: queue(512, { &CPU::queue_event, this })
176
, wram(nullptr)
177
{
178
PPUcounter::scanline = { &CPU::scanline, this };
179
}
180
181
CPU::~CPU() {
182
interface()->freeSharedMemory(wram);
183
}
184
185
void CPU::initialize()
186
{
187
wram = (uint8*)interface()->allocSharedMemory("WRAM", 128 * 1024);
188
}
189
190
}
191
192