yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
memory.cc
Go to the documentation of this file.
2
3#include "imgui/imgui.h"
4
5#include <cstdint>
6#include <iostream>
7#include <string>
8#include <vector>
9
10#include "app/emu/debug/log.h"
11
12namespace yaze {
13namespace app {
14namespace emu {
15namespace memory {
16
17void MemoryImpl::Initialize(const std::vector<uint8_t>& romData, bool verbose) {
18 verbose_ = verbose;
19 type_ = 1;
20
21 auto location = 0x7FC0; // GetHeaderOffset();
22 romSize = 0x400 << romData[location + 0x17];
23 sramSize = 0x400 << romData[location + 0x18];
24 rom_.resize(romSize);
25
26 // Copy memory into rom_
27 for (size_t i = 0; i < romSize; i++) {
28 rom_[i] = romData[i];
29 }
30 ram_.resize(sramSize);
31 for (size_t i = 0; i < sramSize; i++) {
32 ram_[i] = 0;
33 }
34
35 // Clear memory
36 memory_.resize(0x1000000); // 16 MB
37 std::fill(memory_.begin(), memory_.end(), 0);
38
39 // Load ROM data into memory based on LoROM mapping
40 size_t romSize = romData.size();
41 size_t romAddress = 0;
42 const size_t ROM_CHUNK_SIZE = 0x8000; // 32 KB
43 for (size_t bank = 0x00; bank <= 0x3F; ++bank) {
44 for (size_t offset = 0x8000; offset <= 0xFFFF; offset += ROM_CHUNK_SIZE) {
45 if (romAddress < romSize) {
46 std::copy(romData.begin() + romAddress,
47 romData.begin() + romAddress + ROM_CHUNK_SIZE,
48 memory_.begin() + (bank << 16) + offset);
49 romAddress += ROM_CHUNK_SIZE;
50 }
51 }
52 }
53
54}
55
57 memory::RomInfo romInfo;
58
59 uint32_t offset = GetHeaderOffset();
60
61 // Read cartridge title
62 char title[22];
63 for (int i = 0; i < 21; ++i) {
64 title[i] = ReadByte(offset + i);
65 }
66 title[21] = '\0'; // Null-terminate the string
67 romInfo.title = std::string(title);
68
69 // Read ROM speed and memory map mode
70 uint8_t romSpeedAndMapMode = ReadByte(offset + 0x15);
71 romInfo.romSpeed = (memory::RomSpeed)(romSpeedAndMapMode & 0x07);
72 romInfo.bankSize = (memory::BankSize)((romSpeedAndMapMode >> 5) & 0x01);
73
74 // Read ROM type
75 romInfo.romType = (memory::RomType)ReadByte(offset + 0x16);
76
77 // Read ROM size
78 romInfo.romSize = (memory::RomSize)ReadByte(offset + 0x17);
79
80 // Read RAM size
81 romInfo.sramSize = (memory::SramSize)ReadByte(offset + 0x18);
82
83 // Read country code
84 romInfo.countryCode = (memory::CountryCode)ReadByte(offset + 0x19);
85
86 // Read license
87 romInfo.license = (memory::License)ReadByte(offset + 0x1A);
88
89 // Read ROM version
90 romInfo.version = ReadByte(offset + 0x1B);
91
92 // Read checksum complement
93 romInfo.checksumComplement = ReadWord(offset + 0x1E);
94
95 // Read checksum
96 romInfo.checksum = ReadWord(offset + 0x1C);
97
98 // Read NMI VBL vector
99 romInfo.nmiVblVector = ReadWord(offset + 0x3E);
100
101 // Read reset vector
102 romInfo.resetVector = ReadWord(offset + 0x3C);
103
104 return romInfo;
105}
106
107uint8_t MemoryImpl::cart_read(uint8_t bank, uint16_t adr) {
108 switch (type_) {
109 case 0:
110 return open_bus_;
111 case 1:
112 return cart_readLorom(bank, adr);
113 case 2:
114 return cart_readHirom(bank, adr);
115 case 3:
116 return cart_readExHirom(bank, adr);
117 }
118 return open_bus_;
119}
120
121void MemoryImpl::cart_write(uint8_t bank, uint16_t adr, uint8_t val) {
122 switch (type_) {
123 case 0:
124 break;
125 case 1:
126 cart_writeLorom(bank, adr, val);
127 break;
128 case 2:
129 cart_writeHirom(bank, adr, val);
130 break;
131 case 3:
132 cart_writeHirom(bank, adr, val);
133 break;
134 }
135}
136
137uint8_t MemoryImpl::cart_readLorom(uint8_t bank, uint16_t adr) {
138 if (((bank >= 0x70 && bank < 0x7e) || bank >= 0xf0) && adr < 0x8000 &&
139 sramSize > 0) {
140 // banks 70-7e and f0-ff, adr 0000-7fff
141 return ram_[(((bank & 0xf) << 15) | adr) & (sramSize - 1)];
142 }
143 bank &= 0x7f;
144 if (adr >= 0x8000 || bank >= 0x40) {
145 // adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
146 return rom_[((bank << 15) | (adr & 0x7fff)) & (romSize - 1)];
147 }
148 return open_bus_;
149}
150
151void MemoryImpl::cart_writeLorom(uint8_t bank, uint16_t adr, uint8_t val) {
152 if (((bank >= 0x70 && bank < 0x7e) || bank > 0xf0) && adr < 0x8000 &&
153 sramSize > 0) {
154 // banks 70-7e and f0-ff, adr 0000-7fff
155 ram_[(((bank & 0xf) << 15) | adr) & (sramSize - 1)] = val;
156 }
157}
158
159uint8_t MemoryImpl::cart_readHirom(uint8_t bank, uint16_t adr) {
160 bank &= 0x7f;
161 if (bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && sramSize > 0) {
162 // banks 00-3f and 80-bf, adr 6000-7fff
163 return ram_[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (sramSize - 1)];
164 }
165 if (adr >= 0x8000 || bank >= 0x40) {
166 // adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
167 return rom_[(((bank & 0x3f) << 16) | adr) & (romSize - 1)];
168 }
169 return open_bus_;
170}
171
172uint8_t MemoryImpl::cart_readExHirom(uint8_t bank, uint16_t adr) {
173 if ((bank & 0x7f) < 0x40 && adr >= 0x6000 && adr < 0x8000 && sramSize > 0) {
174 // banks 00-3f and 80-bf, adr 6000-7fff
175 return ram_[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (sramSize - 1)];
176 }
177 bool secondHalf = bank < 0x80;
178 bank &= 0x7f;
179 if (adr >= 0x8000 || bank >= 0x40) {
180 // adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
181 return rom_[(((bank & 0x3f) << 16) | (secondHalf ? 0x400000 : 0) | adr) &
182 (romSize - 1)];
183 }
184 return open_bus_;
185}
186
187void MemoryImpl::cart_writeHirom(uint8_t bank, uint16_t adr, uint8_t val) {
188 bank &= 0x7f;
189 if (bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && sramSize > 0) {
190 // banks 00-3f and 80-bf, adr 6000-7fff
191 ram_[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (sramSize - 1)] = val;
192 }
193}
194
195uint32_t MemoryImpl::GetMappedAddress(uint32_t address) const {
196 uint8_t bank = address >> 16;
197 uint32_t offset = address & 0xFFFF;
198
199 if (bank <= 0x3F) {
200 if (address <= 0x1FFF) {
201 return (0x7E << 16) + offset; // Shadow RAM
202 } else if (address <= 0x5FFF) {
203 return (bank << 16) + (offset - 0x2000) + 0x2000; // Hardware Registers
204 } else if (address <= 0x7FFF) {
205 return offset - 0x6000 + 0x6000; // Expansion RAM
206 } else {
207 // Return lorom mapping
208 return (bank << 16) + (offset - 0x8000) + 0x8000; // ROM
209 }
210 } else if (bank == 0x7D) {
211 return offset + 0x7D0000; // SRAM
212 } else if (bank == 0x7E || bank == 0x7F) {
213 return offset + 0x7E0000; // System RAM
214 } else if (bank >= 0x80) {
215 // Handle HiROM and mirrored areas
216 }
217
218 return address; // Return the original address if no mapping is defined
219}
220
222 // Using those as a base value to create width/height that are factor of the
223 // size of our font
224 const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
225 const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
226 const char* column_names[] = {
227 "Offset", "0x00", "0x01", "0x02", "0x03", "0x04", "0x05", "0x06", "0x07",
228 "0x08", "0x09", "0x0A", "0x0B", "0x0C", "0x0D", "0x0E", "0x0F", "0x10",
229 "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19",
230 "0x1A", "0x1B", "0x1C", "0x1D", "0x1E", "0x1F"};
231 const int columns_count = IM_ARRAYSIZE(column_names);
232 const int rows_count = 16;
233
234 static ImGuiTableFlags table_flags =
235 ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX |
236 ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter |
237 ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable |
238 ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
239 ImGuiTableFlags_HighlightHoveredColumn;
240 static bool bools[columns_count * rows_count] = {};
241 static int frozen_cols = 1;
242 static int frozen_rows = 2;
243 ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX);
244 ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY);
245 ImGui::CheckboxFlags("_NoBordersInBody", &table_flags,
246 ImGuiTableFlags_NoBordersInBody);
247 ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags,
248 ImGuiTableFlags_HighlightHoveredColumn);
249 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
250 ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2);
251 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
252 ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
253
254 if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags,
255 ImVec2(0.0f, TEXT_BASE_HEIGHT * 12))) {
256 ImGui::TableSetupColumn(
257 column_names[0],
258 ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
259 for (int n = 1; n < columns_count; n++)
260 ImGui::TableSetupColumn(column_names[n],
261 ImGuiTableColumnFlags_AngledHeader |
262 ImGuiTableColumnFlags_WidthFixed);
263 ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows);
264
265 ImGui::TableAngledHeadersRow();
266 ImGui::TableHeadersRow();
267 for (int row = 0; row < rows_count; row++) {
268 ImGui::PushID(row);
269 ImGui::TableNextRow();
270 ImGui::TableSetColumnIndex(0);
271 ImGui::AlignTextToFramePadding();
272 ImGui::Text("Offset 0x%04X", row);
273 for (int column = 1; column < columns_count; column++)
274 if (ImGui::TableSetColumnIndex(column)) {
275 ImGui::PushID(column);
276 ImGui::Checkbox("", &bools[row * columns_count + column]);
277 ImGui::PopID();
278 }
279 ImGui::PopID();
280 }
281 ImGui::EndTable();
282 }
283}
284
285} // namespace memory
286} // namespace emu
287} // namespace app
288} // namespace yaze
Implementation of the Memory interface for emulating memory in a SNES system.
Definition memory.h:164
std::vector< uint8_t > memory_
Definition memory.h:371
uint8_t cart_readExHirom(uint8_t bank, uint16_t adr)
Definition memory.cc:172
void cart_writeLorom(uint8_t bank, uint16_t adr, uint8_t val)
Definition memory.cc:151
uint8_t cart_readLorom(uint8_t bank, uint16_t adr)
Definition memory.cc:137
uint32_t GetMappedAddress(uint32_t address) const
Definition memory.cc:195
uint8_t ReadByte(uint32_t address) const override
Definition memory.h:206
std::vector< uint8_t > rom_
Definition memory.h:337
memory::RomInfo ReadRomHeader()
Definition memory.cc:56
uint8_t cart_read(uint8_t bank, uint16_t adr)
Definition memory.cc:107
std::vector< uint8_t > ram_
Definition memory.h:338
uint16_t ReadWord(uint32_t address) const override
Definition memory.h:210
void cart_writeHirom(uint8_t bank, uint16_t adr, uint8_t val)
Definition memory.cc:187
void Initialize(const std::vector< uint8_t > &romData, bool verbose=false)
Definition memory.cc:17
void cart_write(uint8_t bank, uint16_t adr, uint8_t val)
Definition memory.cc:121
uint8_t cart_readHirom(uint8_t bank, uint16_t adr)
Definition memory.cc:159
void DrawSnesMemoryMapping(const MemoryImpl &memory)
Definition memory.cc:221
Definition common.cc:21