yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
memory.h
Go to the documentation of this file.
1#ifndef MEM_H
2#define MEM_H
3
4#include <cstdint>
5#include <functional>
6#include <iostream>
7#include <string>
8#include <vector>
9
11
12// LoROM (Mode 20):
13
14// Banks Offset Purpose
15// 00-3F 0000-1FFF LowRAM (shadowed from 7E)
16// 2000-2FFF PPU1, APU
17// 3000-3FFF SFX, DSP, etc.
18// 4000-41FF Controller
19// 4200-5FFF PPU2, DMA, etc.
20// 6000-7FFF Expansion RAM (reserved)
21// 8000-FFFF 32k ROM Chunk
22// 40-7C 0000-7FFF 32k ROM Chunk
23// 8000-FFFF 32k ROM Chunk
24// 7D 0000-FFFF SRAM
25// 7E 0000-1FFF LowRAM
26// 2000-FFFF System RAM
27// 7F 0000-FFFF System RAM
28
29namespace yaze {
30namespace app {
31namespace emu {
32namespace memory {
33
34typedef struct CpuCallbacks {
35 std::function<uint8_t(uint32_t)> read_byte;
36 std::function<void(uint32_t, uint8_t)> write_byte;
37 std::function<void(bool waiting)> idle;
39
40constexpr uint32_t kROMStart = 0x008000;
41constexpr uint32_t kROMSize = 0x200000;
42constexpr uint32_t kRAMStart = 0x7E0000;
43constexpr uint32_t kRAMSize = 0x20000;
44
48class Memory {
49 public:
50 virtual ~Memory() = default;
51 virtual uint8_t ReadByte(uint32_t address) const = 0;
52 virtual uint16_t ReadWord(uint32_t address) const = 0;
53 virtual uint32_t ReadWordLong(uint32_t address) const = 0;
54 virtual std::vector<uint8_t> ReadByteVector(uint32_t address,
55 uint16_t length) const = 0;
56
57 virtual void WriteByte(uint32_t address, uint8_t value) = 0;
58 virtual void WriteWord(uint32_t address, uint16_t value) = 0;
59 virtual void WriteLong(uint32_t address, uint32_t value) = 0;
60
61 virtual void PushByte(uint8_t value) = 0;
62 virtual uint8_t PopByte() = 0;
63 virtual void PushWord(uint16_t value) = 0;
64 virtual uint16_t PopWord() = 0;
65 virtual void PushLong(uint32_t value) = 0;
66 virtual uint32_t PopLong() = 0;
67
68 virtual uint16_t SP() const = 0;
69 virtual void SetSP(uint16_t value) = 0;
70
71 virtual void ClearMemory() = 0;
72
73 virtual uint8_t operator[](int i) const = 0;
74 virtual uint8_t at(int i) const = 0;
75
76 virtual uint8_t open_bus() const = 0;
77 virtual void set_open_bus(uint8_t value) = 0;
78
79 virtual bool hdma_init_requested() const = 0;
80 virtual bool hdma_run_requested() const = 0;
81 virtual void init_hdma_request() = 0;
82 virtual void run_hdma_request() = 0;
83 virtual void set_hdma_run_requested(bool value) = 0;
84 virtual void set_hdma_init_requested(bool value) = 0;
85 virtual void set_pal_timing(bool value) = 0;
86 virtual void set_h_pos(uint16_t value) = 0;
87 virtual void set_v_pos(uint16_t value) = 0;
88
89 // get h_pos and v_pos
90 virtual auto h_pos() const -> uint16_t = 0;
91 virtual auto v_pos() const -> uint16_t = 0;
92 // get pal timing
93 virtual auto pal_timing() const -> bool = 0;
94};
95
102class MemoryImpl : public Memory {
103 public:
104 void Initialize(const std::vector<uint8_t>& romData, bool verbose = false);
105
106 uint16_t GetHeaderOffset() {
107 uint16_t offset;
108 switch (memory_[(0x00 << 16) + 0xFFD5] & 0x07) {
109 case 0: // LoROM
110 offset = 0x7FC0;
111 break;
112 case 1: // HiROM
113 offset = 0xFFC0;
114 break;
115 case 5: // ExHiROM
116 offset = 0x40;
117 break;
118 default:
119 throw std::invalid_argument(
120 "Unable to locate supported ROM mapping mode in the provided ROM "
121 "file. Please try another ROM file.");
122 }
123
124 return offset;
125 }
126
127 uint8_t cart_read(uint8_t bank, uint16_t adr);
128 void cart_write(uint8_t bank, uint16_t adr, uint8_t val);
129
130 uint8_t cart_readLorom(uint8_t bank, uint16_t adr);
131 void cart_writeLorom(uint8_t bank, uint16_t adr, uint8_t val);
132
133 uint8_t cart_readHirom(uint8_t bank, uint16_t adr);
134 uint8_t cart_readExHirom(uint8_t bank, uint16_t adr);
135
136 void cart_writeHirom(uint8_t bank, uint16_t adr, uint8_t val);
137
138 uint8_t ReadByte(uint32_t address) const override {
139 uint32_t mapped_address = GetMappedAddress(address);
140 return memory_.at(mapped_address);
141 }
142 uint16_t ReadWord(uint32_t address) const override {
143 uint32_t mapped_address = GetMappedAddress(address);
144 return static_cast<uint16_t>(memory_.at(mapped_address)) |
145 (static_cast<uint16_t>(memory_.at(mapped_address + 1)) << 8);
146 }
147 uint32_t ReadWordLong(uint32_t address) const override {
148 uint32_t mapped_address = GetMappedAddress(address);
149 return static_cast<uint32_t>(memory_.at(mapped_address)) |
150 (static_cast<uint32_t>(memory_.at(mapped_address + 1)) << 8) |
151 (static_cast<uint32_t>(memory_.at(mapped_address + 2)) << 16);
152 }
153 std::vector<uint8_t> ReadByteVector(uint32_t address,
154 uint16_t length) const override {
155 uint32_t mapped_address = GetMappedAddress(address);
156 return std::vector<uint8_t>(memory_.begin() + mapped_address,
157 memory_.begin() + mapped_address + length);
158 }
159
160 void WriteByte(uint32_t address, uint8_t value) override {
161 uint32_t mapped_address = GetMappedAddress(address);
162 memory_[mapped_address] = value;
163 }
164 void WriteWord(uint32_t address, uint16_t value) override {
165 uint32_t mapped_address = GetMappedAddress(address);
166 memory_.at(mapped_address) = value & 0xFF;
167 memory_.at(mapped_address + 1) = (value >> 8) & 0xFF;
168 }
169 void WriteLong(uint32_t address, uint32_t value) override {
170 uint32_t mapped_address = GetMappedAddress(address);
171 memory_.at(mapped_address) = value & 0xFF;
172 memory_.at(mapped_address + 1) = (value >> 8) & 0xFF;
173 memory_.at(mapped_address + 2) = (value >> 16) & 0xFF;
174 }
175
176 // Stack operations
177 void PushByte(uint8_t value) override {
178 if (SP_ > 0x0100) {
179 memory_.at(SP_--) = value;
180 } else {
181 // Handle stack underflow
182 std::cout << "Stack underflow!" << std::endl;
183 throw std::runtime_error("Stack underflow!");
184 }
185 }
186
187 uint8_t PopByte() override {
188 if (SP_ < 0x1FF) {
189 return memory_.at(++SP_);
190 } else {
191 // Handle stack overflow
192 std::cout << "Stack overflow!" << std::endl;
193 throw std::runtime_error("Stack overflow!");
194 }
195 }
196
197 void PushWord(uint16_t value) override {
198 PushByte(value >> 8);
199 PushByte(value & 0xFF);
200 }
201
202 uint16_t PopWord() override {
203 uint8_t low = PopByte();
204 uint8_t high = PopByte();
205 return (static_cast<uint16_t>(high) << 8) | low;
206 }
207
208 void PushLong(uint32_t value) override {
209 PushByte(value >> 16);
210 PushByte(value >> 8);
211 PushByte(value & 0xFF);
212 }
213
214 uint32_t PopLong() override {
215 uint8_t low = PopByte();
216 uint8_t mid = PopByte();
217 uint8_t high = PopByte();
218 return (static_cast<uint32_t>(high) << 16) |
219 (static_cast<uint32_t>(mid) << 8) | low;
220 }
221
222 // Stack Pointer access.
223 uint16_t SP() const override { return SP_; }
224 auto mutable_sp() -> uint16_t& { return SP_; }
225 void SetSP(uint16_t value) override { SP_ = value; }
226 void ClearMemory() override { std::fill(memory_.begin(), memory_.end(), 0); }
227
228 uint8_t at(int i) const override { return memory_[i]; }
229 uint8_t operator[](int i) const override {
230 if (i > memory_.size()) {
231 std::cout << i << " out of bounds \n";
232 return memory_[0];
233 }
234 return memory_[i];
235 }
236
237 auto size() const { return memory_.size(); }
238 auto begin() const { return memory_.begin(); }
239 auto end() const { return memory_.end(); }
240 auto data() const { return memory_.data(); }
241 void set_open_bus(uint8_t value) override { open_bus_ = value; }
242 auto open_bus() const -> uint8_t override { return open_bus_; }
243 auto hdma_init_requested() const -> bool override {
244 return hdma_init_requested_;
245 }
246 auto hdma_run_requested() const -> bool override {
247 return hdma_run_requested_;
248 }
249 void init_hdma_request() override { hdma_init_requested_ = true; }
250 void run_hdma_request() override { hdma_run_requested_ = true; }
251 void set_hdma_run_requested(bool value) override {
252 hdma_run_requested_ = value;
253 }
254 void set_hdma_init_requested(bool value) override {
255 hdma_init_requested_ = value;
256 }
257 void set_pal_timing(bool value) override { pal_timing_ = value; }
258 void set_h_pos(uint16_t value) override { h_pos_ = value; }
259 void set_v_pos(uint16_t value) override { v_pos_ = value; }
260 auto h_pos() const -> uint16_t override { return h_pos_; }
261 auto v_pos() const -> uint16_t override { return v_pos_; }
262 auto pal_timing() const -> bool override { return pal_timing_; }
263
264 auto dma_state() -> uint8_t& { return dma_state_; }
265 void set_dma_state(uint8_t value) { dma_state_ = value; }
266 auto dma_channels() -> DmaChannel* { return channel; }
267
268 // Define memory regions
269 std::vector<uint8_t> rom_;
270 std::vector<uint8_t> ram_;
271
272 private:
273 uint32_t GetMappedAddress(uint32_t address) const;
274
275 bool verbose_ = false;
276
277 // DMA requests
278 bool hdma_run_requested_ = false;
279 bool hdma_init_requested_ = false;
280
281 bool pal_timing_ = false;
282
283 // Memory regions
284 uint32_t rom_size_;
285 uint32_t sram_size_;
286
287 // Frame timing
288 uint16_t h_pos_ = 0;
289 uint16_t v_pos_ = 0;
290
291 // Dma State
292 uint8_t dma_state_ = 0;
293
294 // Open bus
295 uint8_t open_bus_ = 0;
296
297 // Stack Pointer
298 uint16_t SP_ = 0;
299
300 // Cart Type
301 uint8_t type_ = 1;
302
303 // Dma Channels
304 DmaChannel channel[8];
305
306 // Memory (64KB)
307 std::vector<uint8_t> memory_;
308};
309
310} // namespace memory
311} // namespace emu
312} // namespace app
313} // namespace yaze
314
315#endif // MEM_H
Implementation of the Memory interface for emulating memory in a SNES system.
Definition memory.h:102
uint32_t ReadWordLong(uint32_t address) const override
Definition memory.h:147
std::vector< uint8_t > memory_
Definition memory.h:307
auto mutable_sp() -> uint16_t &
Definition memory.h:224
void WriteWord(uint32_t address, uint16_t value) override
Definition memory.h:164
void WriteLong(uint32_t address, uint32_t value) override
Definition memory.h:169
uint16_t PopWord() override
Definition memory.h:202
auto v_pos() const -> uint16_t override
Definition memory.h:261
void set_dma_state(uint8_t value)
Definition memory.h:265
auto dma_channels() -> DmaChannel *
Definition memory.h:266
void set_h_pos(uint16_t value) override
Definition memory.h:258
void PushWord(uint16_t value) override
Definition memory.h:197
std::vector< uint8_t > ReadByteVector(uint32_t address, uint16_t length) const override
Definition memory.h:153
void set_open_bus(uint8_t value) override
Definition memory.h:241
auto h_pos() const -> uint16_t override
Definition memory.h:260
void init_hdma_request() override
Definition memory.h:249
uint8_t at(int i) const override
Definition memory.h:228
void run_hdma_request() override
Definition memory.h:250
uint8_t ReadByte(uint32_t address) const override
Definition memory.h:138
std::vector< uint8_t > rom_
Definition memory.h:269
auto hdma_run_requested() const -> bool override
Definition memory.h:246
uint16_t SP() const override
Definition memory.h:223
void set_hdma_run_requested(bool value) override
Definition memory.h:251
void PushLong(uint32_t value) override
Definition memory.h:208
void SetSP(uint16_t value) override
Definition memory.h:225
void set_pal_timing(bool value) override
Definition memory.h:257
auto dma_state() -> uint8_t &
Definition memory.h:264
void WriteByte(uint32_t address, uint8_t value) override
Definition memory.h:160
auto open_bus() const -> uint8_t override
Definition memory.h:242
void set_v_pos(uint16_t value) override
Definition memory.h:259
std::vector< uint8_t > ram_
Definition memory.h:270
uint8_t PopByte() override
Definition memory.h:187
uint32_t PopLong() override
Definition memory.h:214
void set_hdma_init_requested(bool value) override
Definition memory.h:254
uint16_t ReadWord(uint32_t address) const override
Definition memory.h:142
auto pal_timing() const -> bool override
Definition memory.h:262
void PushByte(uint8_t value) override
Definition memory.h:177
auto hdma_init_requested() const -> bool override
Definition memory.h:243
uint8_t operator[](int i) const override
Definition memory.h:229
Memory interface.
Definition memory.h:48
virtual std::vector< uint8_t > ReadByteVector(uint32_t address, uint16_t length) const =0
virtual void PushLong(uint32_t value)=0
virtual void WriteLong(uint32_t address, uint32_t value)=0
virtual void set_pal_timing(bool value)=0
virtual void PushByte(uint8_t value)=0
virtual uint16_t SP() const =0
virtual void set_v_pos(uint16_t value)=0
virtual void SetSP(uint16_t value)=0
virtual void PushWord(uint16_t value)=0
virtual auto v_pos() const -> uint16_t=0
virtual void WriteByte(uint32_t address, uint8_t value)=0
virtual uint8_t operator[](int i) const =0
virtual void set_hdma_run_requested(bool value)=0
virtual uint8_t at(int i) const =0
virtual uint8_t open_bus() const =0
virtual void WriteWord(uint32_t address, uint16_t value)=0
virtual void set_h_pos(uint16_t value)=0
virtual void run_hdma_request()=0
virtual bool hdma_run_requested() const =0
virtual uint8_t ReadByte(uint32_t address) const =0
virtual auto h_pos() const -> uint16_t=0
virtual void set_hdma_init_requested(bool value)=0
virtual uint32_t PopLong()=0
virtual uint16_t ReadWord(uint32_t address) const =0
virtual uint32_t ReadWordLong(uint32_t address) const =0
virtual void init_hdma_request()=0
virtual uint8_t PopByte()=0
virtual uint16_t PopWord()=0
virtual auto pal_timing() const -> bool=0
virtual void set_open_bus(uint8_t value)=0
virtual bool hdma_init_requested() const =0
constexpr uint32_t kROMSize
Definition memory.h:41
constexpr uint32_t kRAMSize
Definition memory.h:43
struct yaze::app::emu::memory::CpuCallbacks CpuCallbacks
constexpr uint32_t kROMStart
Definition memory.h:40
constexpr uint32_t kRAMStart
Definition memory.h:42
Definition common.cc:22
std::function< uint8_t(uint32_t)> read_byte
Definition memory.h:35
std::function< void(bool waiting)> idle
Definition memory.h:37
std::function< void(uint32_t, uint8_t)> write_byte
Definition memory.h:36