yaze 0.2.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
rom.h
Go to the documentation of this file.
1#ifndef YAZE_APP_ROM_H
2#define YAZE_APP_ROM_H
3
4#include <SDL.h>
5#include <zelda.h>
6
7#include <cstddef>
8#include <cstdint>
9#include <cstring>
10#include <ctime>
11#include <map>
12#include <memory>
13#include <string>
14#include <variant>
15#include <vector>
16
17#include "absl/status/status.h"
18#include "absl/status/statusor.h"
19#include "absl/strings/match.h"
20#include "absl/strings/str_format.h"
21#include "absl/strings/string_view.h"
22#include "app/core/project.h"
23#include "app/gfx/bitmap.h"
25#include "app/gfx/snes_tile.h"
26#include "util/macro.h"
27
28namespace yaze {
29
30constexpr uint32_t kNumGfxSheets = 223;
31constexpr uint32_t kNumLinkSheets = 14;
32constexpr uint32_t kTile16Ptr = 0x78000;
33constexpr uint32_t kNormalGfxSpaceStart = 0x87000;
34constexpr uint32_t kNormalGfxSpaceEnd = 0xC4200;
35constexpr uint32_t kFontSpriteLocation = 0x70000;
36constexpr uint32_t kGfxGroupsPointer = 0x6237;
37constexpr uint32_t kUncompressedSheetSize = 0x0800;
38constexpr uint32_t kNumMainBlocksets = 37;
39constexpr uint32_t kNumRoomBlocksets = 82;
40constexpr uint32_t kNumSpritesets = 144;
41constexpr uint32_t kNumPalettesets = 72;
42constexpr uint32_t kEntranceGfxGroup = 0x5D97;
43constexpr uint32_t kMaxGraphics = 0x0C3FFF; // 0xC3FB5
44
48static const std::map<zelda3_version, zelda3_version_pointers>
49 kVersionConstantsMap = {
50 {zelda3_version::US, zelda3_us_pointers},
51 {zelda3_version::JP, zelda3_jp_pointers},
54};
55
59class Rom {
60 public:
68 absl::Status LoadFromFile(const std::string& filename, bool z3_load = true);
69 absl::Status LoadFromData(const std::vector<uint8_t>& data,
70 bool z3_load = true);
71
81 absl::Status SaveToFile(bool backup, bool save_new = false,
82 std::string filename = "");
83
91 absl::Status SavePalette(int index, const std::string& group_name,
92 gfx::SnesPalette& palette);
93
100 absl::Status SaveAllPalettes();
101
102 void Expand(int size) {
103 rom_data_.resize(size);
104 size_ = size;
105 }
106
107 absl::Status Close() {
108 rom_data_.clear();
109 size_ = 0;
110 is_loaded_ = false;
111 return absl::OkStatus();
112 }
113
114 absl::StatusOr<uint8_t> ReadByte(int offset);
115 absl::StatusOr<uint16_t> ReadWord(int offset);
116 absl::StatusOr<uint32_t> ReadLong(int offset);
117 absl::StatusOr<std::vector<uint8_t>> ReadByteVector(uint32_t offset,
118 uint32_t length) const;
119 absl::StatusOr<gfx::Tile16> ReadTile16(uint32_t tile16_id);
120
121 absl::Status WriteTile16(int tile16_id, const gfx::Tile16& tile);
122 absl::Status WriteByte(int addr, uint8_t value);
123 absl::Status WriteWord(int addr, uint16_t value);
124 absl::Status WriteShort(int addr, uint16_t value);
125 absl::Status WriteLong(uint32_t addr, uint32_t value);
126 absl::Status WriteVector(int addr, std::vector<uint8_t> data);
127 absl::Status WriteColor(uint32_t address, const gfx::SnesColor& color);
128
129 template <typename... Args>
130 absl::Status WriteTransaction(Args... args) {
131 absl::Status status;
132 // Fold expression to apply the Write function on each argument
133 ((status = WriteHelper(args)), ...);
134 return status;
135 }
136
137 template <typename T, typename... Args>
138 absl::Status ReadTransaction(T& var, int address, Args&&... args) {
139 absl::Status status = ReadHelper<T>(var, address);
140 if (!status.ok()) {
141 return status;
142 }
143 if constexpr (sizeof...(args) > 0) {
144 status = ReadTransaction(std::forward<Args>(args)...);
145 }
146 return status;
147 }
148
149 uint8_t& operator[](unsigned long i) {
150 if (i >= size_) throw std::out_of_range("Rom index out of range");
151 return rom_data_[i];
152 }
153
154 bool is_loaded() const {
155 if (!absl::StrContains(filename_, ".sfc") &&
156 !absl::StrContains(filename_, ".smc")) {
157 return false;
158 }
159 return is_loaded_;
160 }
161
162 auto title() const { return title_; }
163 auto size() const { return size_; }
164 auto data() const { return rom_data_.data(); }
165 auto mutable_data() { return rom_data_.data(); }
166 auto begin() { return rom_data_.begin(); }
167 auto end() { return rom_data_.end(); }
168
169 auto vector() const { return rom_data_; }
170 auto version() const { return version_; }
171 auto filename() const { return filename_; }
172 auto set_filename(std::string name) { filename_ = name; }
173
174 std::vector<uint8_t> graphics_buffer() const { return graphics_buffer_; }
176 auto palette_group() const { return palette_groups_; }
178 auto dungeon_palette(int i) { return palette_groups_.dungeon_main[i]; }
180 return palette_groups_.dungeon_main.mutable_palette(i);
181 }
182
185 return kVersionConstantsMap.at(version_);
186 }
187
188 std::array<std::array<uint8_t, 8>, kNumMainBlocksets> main_blockset_ids;
189 std::array<std::array<uint8_t, 4>, kNumRoomBlocksets> room_blockset_ids;
190 std::array<std::array<uint8_t, 4>, kNumSpritesets> spriteset_ids;
191 std::array<std::array<uint8_t, 4>, kNumPalettesets> paletteset_ids;
192
193 struct WriteAction {
195 std::variant<int, uint8_t, uint16_t, short, std::vector<uint8_t>,
196 gfx::SnesColor, std::vector<gfx::SnesColor>>
198 };
199
200 private:
201 virtual absl::Status WriteHelper(const WriteAction& action) {
202 if (std::holds_alternative<uint8_t>(action.value)) {
203 return WriteByte(action.address, std::get<uint8_t>(action.value));
204 } else if (std::holds_alternative<uint16_t>(action.value) ||
205 std::holds_alternative<short>(action.value)) {
206 return WriteShort(action.address, std::get<uint16_t>(action.value));
207 } else if (std::holds_alternative<std::vector<uint8_t>>(action.value)) {
208 return WriteVector(action.address,
209 std::get<std::vector<uint8_t>>(action.value));
210 } else if (std::holds_alternative<gfx::SnesColor>(action.value)) {
211 return WriteColor(action.address, std::get<gfx::SnesColor>(action.value));
212 } else if (std::holds_alternative<std::vector<gfx::SnesColor>>(
213 action.value)) {
214 return absl::UnimplementedError(
215 "WriteHelper: std::vector<gfx::SnesColor>");
216 }
217 auto error_message = absl::StrFormat("Invalid write argument type: %s",
218 typeid(action.value).name());
219 return absl::InvalidArgumentError(error_message);
220 }
221
222 template <typename T>
223 absl::Status ReadHelper(T& var, int address) {
224 if constexpr (std::is_same_v<T, uint8_t>) {
225 ASSIGN_OR_RETURN(auto result, ReadByte(address));
226 var = result;
227 } else if constexpr (std::is_same_v<T, uint16_t>) {
228 ASSIGN_OR_RETURN(auto result, ReadWord(address));
229 var = result;
230 } else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
231 ASSIGN_OR_RETURN(auto result, ReadByteVector(address, var.size()));
232 var = result;
233 }
234 return absl::OkStatus();
235 }
236
237 absl::Status LoadZelda3();
238 absl::Status LoadGfxGroups();
239 absl::Status SaveGroupsToRom();
240
241 // ROM file loaded flag
242 bool is_loaded_ = false;
243
244 // Size of the ROM data.
245 unsigned long size_ = 0;
246
247 // Title of the ROM loaded from the header
248 std::string title_ = "ROM not loaded";
249
250 // Filename of the ROM
251 std::string filename_ = "";
252
253 // Full contiguous rom space
254 std::vector<uint8_t> rom_data_;
255
256 // Full contiguous graphics space
257 std::vector<uint8_t> graphics_buffer_;
258
259 // Label manager for unique resource names.
261
262 // All palette groups in the game
264
265 // Version of the game
267};
268
270 public:
272 static GraphicsSheetManager instance;
273 return instance;
274 }
276 virtual ~GraphicsSheetManager() = default;
277 std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets() { return gfx_sheets_; }
278 auto gfx_sheet(int i) { return gfx_sheets_[i]; }
279 auto mutable_gfx_sheet(int i) { return &gfx_sheets_[i]; }
280 auto mutable_gfx_sheets() { return &gfx_sheets_; }
281
282 private:
283 std::array<gfx::Bitmap, kNumGfxSheets> gfx_sheets_;
284};
285
304absl::StatusOr<std::array<gfx::Bitmap, kNumGfxSheets>> LoadAllGraphicsData(
305 Rom& rom, bool defer_render = false);
306
307absl::Status SaveAllGraphicsData(
308 Rom& rom, std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets);
309
318absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom& rom);
319
323absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(
324 const Rom& rom);
325
326constexpr uint32_t kFastRomRegion = 0x808000;
327
328inline uint32_t SnesToPc(uint32_t addr) noexcept {
329 if (addr >= kFastRomRegion) {
330 addr -= kFastRomRegion;
331 }
332 uint32_t temp = (addr & 0x7FFF) + ((addr / 2) & 0xFF8000);
333 return (temp + 0x0);
334}
335
336inline uint32_t PcToSnes(uint32_t addr) {
337 uint8_t* b = reinterpret_cast<uint8_t*>(&addr);
338 b[2] = static_cast<uint8_t>(b[2] * 2);
339
340 if (b[1] >= 0x80) {
341 b[2] += 1;
342 } else {
343 b[1] += 0x80;
344 }
345
346 return addr;
347}
348
349inline uint32_t Get24LocalFromPC(uint8_t* data, int addr, bool pc = true) {
350 uint32_t ret =
351 (PcToSnes(addr) & 0xFF0000) | (data[addr + 1] << 8) | data[addr];
352 if (pc) {
353 return SnesToPc(ret);
354 }
355 return ret;
356}
357
358inline int AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) noexcept {
359 return (bank << 16) | (high << 8) | low;
360}
361
362inline uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr) noexcept {
363 uint32_t result = 0;
364 result = (bank << 16) | addr;
365 return result;
366}
367
372 public:
373 SharedRom() = default;
374 virtual ~SharedRom() = default;
375
376 std::shared_ptr<Rom> shared_rom() {
377 if (!shared_rom_) {
378 shared_rom_ = std::make_shared<Rom>();
379 }
380 return shared_rom_;
381 }
382
383 auto rom() {
384 if (!shared_rom_) {
385 shared_rom_ = std::make_shared<Rom>();
386 }
387 Rom* rom = shared_rom_.get();
388 return rom;
389 }
390
391 // private:
392 static std::shared_ptr<Rom> shared_rom_;
393};
394
395} // namespace yaze
396
397#endif
virtual ~GraphicsSheetManager()=default
std::array< gfx::Bitmap, kNumGfxSheets > gfx_sheets_
Definition rom.h:283
auto gfx_sheet(int i)
Definition rom.h:278
static GraphicsSheetManager & GetInstance()
Definition rom.h:271
auto mutable_gfx_sheet(int i)
Definition rom.h:279
std::array< gfx::Bitmap, kNumGfxSheets > & gfx_sheets()
Definition rom.h:277
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:59
absl::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length) const
Definition rom.cc:259
zelda3_version version_
Definition rom.h:266
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:173
auto mutable_graphics_buffer()
Definition rom.h:175
absl::Status ReadTransaction(T &var, int address, Args &&... args)
Definition rom.h:138
auto begin()
Definition rom.h:166
absl::Status SaveGroupsToRom()
Definition rom.cc:564
std::vector< uint8_t > rom_data_
Definition rom.h:254
std::vector< uint8_t > graphics_buffer() const
Definition rom.h:174
gfx::PaletteGroupMap palette_groups_
Definition rom.h:263
auto palette_group() const
Definition rom.h:176
absl::StatusOr< gfx::Tile16 > ReadTile16(uint32_t tile16_id)
Definition rom.cc:271
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
Definition rom.cc:363
auto filename() const
Definition rom.h:171
auto mutable_palette_group()
Definition rom.h:177
absl::Status LoadFromData(const std::vector< uint8_t > &data, bool z3_load=true)
Definition rom.cc:218
auto end()
Definition rom.h:167
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:302
auto vector() const
Definition rom.h:169
auto version() const
Definition rom.h:170
auto mutable_data()
Definition rom.h:165
absl::Status SaveToFile(bool backup, bool save_new=false, std::string filename="")
Saves the Rom data to a file.
Definition rom.cc:408
absl::Status LoadZelda3()
Definition rom.cc:372
std::array< std::array< uint8_t, 4 >, kNumSpritesets > spriteset_ids
Definition rom.h:190
ResourceLabelManager * resource_label()
Definition rom.h:183
std::array< std::array< uint8_t, 4 >, kNumPalettesets > paletteset_ids
Definition rom.h:191
auto mutable_dungeon_palette(int i)
Definition rom.h:179
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:242
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
Definition rom.cc:350
std::string title_
Definition rom.h:248
absl::Status WriteTile16(int tile16_id, const gfx::Tile16 &tile)
Definition rom.cc:289
void Expand(int size)
Definition rom.h:102
absl::Status WriteTransaction(Args... args)
Definition rom.h:130
auto set_filename(std::string name)
Definition rom.h:172
std::array< std::array< uint8_t, 4 >, kNumRoomBlocksets > room_blockset_ids
Definition rom.h:189
virtual absl::Status WriteHelper(const WriteAction &action)
Definition rom.h:201
absl::StatusOr< uint32_t > ReadLong(int offset)
Definition rom.cc:250
auto data() const
Definition rom.h:164
auto size() const
Definition rom.h:163
std::vector< uint8_t > graphics_buffer_
Definition rom.h:257
zelda3_version_pointers version_constants() const
Definition rom.h:184
ResourceLabelManager resource_label_manager_
Definition rom.h:260
absl::Status LoadGfxGroups()
Definition rom.cc:531
bool is_loaded_
Definition rom.h:242
absl::Status ReadHelper(T &var, int address)
Definition rom.h:223
std::string filename_
Definition rom.h:251
unsigned long size_
Definition rom.h:245
absl::Status SavePalette(int index, const std::string &group_name, gfx::SnesPalette &palette)
Definition rom.cc:504
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:235
absl::Status WriteShort(int addr, uint16_t value)
Definition rom.cc:325
auto dungeon_palette(int i)
Definition rom.h:178
uint8_t & operator[](unsigned long i)
Definition rom.h:149
bool is_loaded() const
Definition rom.h:154
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:313
absl::Status WriteLong(uint32_t addr, uint32_t value)
Definition rom.cc:337
auto title() const
Definition rom.h:162
absl::Status Close()
Definition rom.h:107
std::array< std::array< uint8_t, 8 >, kNumMainBlocksets > main_blockset_ids
Definition rom.h:188
absl::Status SaveAllPalettes()
Saves all palettes in the Rom.
Definition rom.cc:518
virtual ~SharedRom()=default
static std::shared_ptr< Rom > shared_rom_
Definition rom.h:392
auto rom()
Definition rom.h:383
std::shared_ptr< Rom > shared_rom()
Definition rom.h:376
SharedRom()=default
SNES Color container.
Definition snes_color.h:38
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Tile composition of four 8x8 tiles.
Definition snes_tile.h:129
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Definition macro.h:70
Main namespace for the application.
Definition controller.cc:18
uint32_t PcToSnes(uint32_t addr)
Definition rom.h:336
uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr) noexcept
Definition rom.h:362
constexpr uint32_t kMaxGraphics
Definition rom.h:43
constexpr uint32_t kGfxGroupsPointer
Definition rom.h:36
constexpr uint32_t kUncompressedSheetSize
Definition rom.h:37
absl::StatusOr< std::vector< uint8_t > > Load2BppGraphics(const Rom &rom)
Loads 2bpp graphics from Rom data.
Definition rom.cc:39
constexpr uint32_t kFastRomRegion
Definition rom.h:326
absl::StatusOr< std::array< gfx::Bitmap, kNumLinkSheets > > LoadLinkGraphics(const Rom &rom)
Loads the players 4bpp graphics sheet from Rom data.
Definition rom.cc:58
constexpr uint32_t kNumLinkSheets
Definition rom.h:31
constexpr uint32_t kNormalGfxSpaceStart
Definition rom.h:33
constexpr uint32_t kEntranceGfxGroup
Definition rom.h:42
constexpr uint32_t kFontSpriteLocation
Definition rom.h:35
uint32_t Get24LocalFromPC(uint8_t *data, int addr, bool pc=true)
Definition rom.h:349
constexpr uint32_t kNumSpritesets
Definition rom.h:40
int AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) noexcept
Definition rom.h:358
constexpr uint32_t kTile16Ptr
Definition rom.h:32
constexpr uint32_t kNumMainBlocksets
Definition rom.h:38
constexpr uint32_t kNumRoomBlocksets
Definition rom.h:39
constexpr uint32_t kNumGfxSheets
Definition rom.h:30
absl::StatusOr< std::array< gfx::Bitmap, kNumGfxSheets > > LoadAllGraphicsData(Rom &rom, bool defer_render)
This function iterates over all graphics sheets in the Rom and loads them into memory....
Definition rom.cc:78
constexpr uint32_t kNumPalettesets
Definition rom.h:41
constexpr uint32_t kNormalGfxSpaceEnd
Definition rom.h:34
absl::Status SaveAllGraphicsData(Rom &rom, std::array< gfx::Bitmap, kNumGfxSheets > &gfx_sheets)
Definition rom.cc:137
uint32_t SnesToPc(uint32_t addr) noexcept
Definition rom.h:328
std::variant< int, uint8_t, uint16_t, short, std::vector< uint8_t >, gfx::SnesColor, std::vector< gfx::SnesColor > > value
Definition rom.h:197
Represents a mapping of palette groups.
Pointers for each version of the game.
Definition zelda.h:23
zelda3_version
Different versions of the game supported by yaze.
Definition zelda.h:13
@ US
Definition zelda.h:14
@ SD
Definition zelda.h:16
@ RANDO
Definition zelda.h:17
@ JP
Definition zelda.h:15