-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnes-system.hpp
140 lines (127 loc) · 4.43 KB
/
nes-system.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#pragma once
#include <functional>
#include "byte.hpp"
#include "counter.hpp"
#include "ines.hpp"
#include "2A03.hpp"
#include "2C02.hpp"
class Nes {
private:
Cpu cpu;
Apu apu{cpu};
Ppu ppu{cpu};
Cartridge cart{cpu.memory, ppu.memory};
u8_fast controller1Button {0}, controller2Button {0};
bool controllerStrobe {false};
public:
std::function<void(u8 sample)>& audioOutputFunction {
apu.outputFunction};
std::function<void(
u8_fast x,
u8_fast y,
u32 pixel)>& videoOutputFunction {
ppu.outputFunction};
u32_fast& frame {ppu.frame};
u8_fast controller1 {0}, controller2 {0};
Nes() {
cpu.memory.readFunctions[0x4016] = [&] (
MappedMemory<>* const memory,
const u16 address) {
//TODO: open bus bits
bool result = controller1 >> controller1Button & 0x01;
controller1Button +=
!controllerStrobe
&& controller1Button < 8;
return result;
};
cpu.memory.writeFunctions[0x4016] = [&] (
MappedMemory<>* const memory,
const u16 address,
const u8 data) {
if ((controllerStrobe = data & 0x01)) {
controller1Button = 0;
controller2Button = 0;
}
};
cpu.memory.readFunctions[0x4017] = [&] (
MappedMemory<>* const memory,
const u16 address) {
//TODO: open bus bits
bool result = controller2 >> controller2Button & 0x01;
controller2Button +=
!controllerStrobe
&& controller2Button < 8;
return result;
};
cpu.timer.reload = 11;
apu.timer.reload = 11;
ppu.timer.reload = 3;
}
template <typename RomType, typename SramType>
void load(RomType rom, SramType sram) {
cart.load(rom, sram);
}
void reset() {
cpu.reset();
apu.reset();
ppu.reset();
}
void tick(const u8_fast ticks = 1) {
cpu.tick(ticks);
apu.tick(ticks);
ppu.tick(ticks);
cart.tick(ticks);
}
void writeMemory(
const bool toPpu,
const u16 address,
const u8 data) {
if (!toPpu || address <= 0x3FFF) {
MappedMemory<>& memory = toPpu ? ppu.memory : cpu.memory;
memory[address] = data;
}
}
int readMemory(
const bool fromPpu,
const u16 address) {
int value {-1};
if (!fromPpu || address <= 0x3FFF) {
MappedMemory<>& memory = fromPpu ? ppu.memory : cpu.memory;
value = memory[address];
}
return value;
}
template <typename StateType>
void dumpState(StateType& state) {
cpu.dumpState(state);
apu.dumpState(state);
ppu.dumpState(state);
std::vector<u8> cartState(cart.stateSize);
cart.dumpState(cartState);
state.write(cartState.data(), cart.stateSize);
}
template <typename StateType>
void loadState(StateType& state) {
cpu.loadState(state);
apu.loadState(state);
ppu.loadState(state);
std::vector<u8> cartState(cart.stateSize);
state.read(cartState.data(), cart.stateSize);
cart.loadState(cartState);
}
void ramdump(const char* const filename) {
std::ofstream ramdumpFile {filename,
std::ofstream::binary | std::ofstream::trunc};
auto ptr {ppu.memory.begin()};
for (u32_fast i {0}; i <= 0x3FFF; ++i, ++ptr) {
u8 byte {*ptr};
ramdumpFile.write(reinterpret_cast<char*>(&byte), 1);
}
ptr = cpu.memory.begin();
for (u32_fast i {0}; i <= 0xFFFF; ++i, ++ptr) {
u8 byte {*ptr};
ramdumpFile.write(reinterpret_cast<char*>(&byte), 1);
}
ramdumpFile.close();
}
};