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 void Close() {
108 rom_data_.clear();
109 size_ = 0;
110 is_loaded_ = false;
111 }
112
113 absl::StatusOr<uint8_t> ReadByte(int offset);
114 absl::StatusOr<uint16_t> ReadWord(int offset);
115 absl::StatusOr<uint32_t> ReadLong(int offset);
116 absl::StatusOr<std::vector<uint8_t>> ReadByteVector(uint32_t offset,
117 uint32_t length) const;
118 absl::StatusOr<gfx::Tile16> ReadTile16(uint32_t tile16_id);
119
120 absl::Status WriteTile16(int tile16_id, const gfx::Tile16& tile);
121 absl::Status WriteByte(int addr, uint8_t value);
122 absl::Status WriteWord(int addr, uint16_t value);
123 absl::Status WriteShort(int addr, uint16_t value);
124 absl::Status WriteLong(uint32_t addr, uint32_t value);
125 absl::Status WriteVector(int addr, std::vector<uint8_t> data);
126 absl::Status WriteColor(uint32_t address, const gfx::SnesColor& color);
127
128 template <typename... Args>
129 absl::Status WriteTransaction(Args... args) {
130 absl::Status status;
131 // Fold expression to apply the Write function on each argument
132 ((status = WriteHelper(args)), ...);
133 return status;
134 }
135
136 template <typename T, typename... Args>
137 absl::Status ReadTransaction(T& var, int address, Args&&... args) {
138 absl::Status status = ReadHelper<T>(var, address);
139 if (!status.ok()) {
140 return status;
141 }
142 if constexpr (sizeof...(args) > 0) {
143 status = ReadTransaction(std::forward<Args>(args)...);
144 }
145 return status;
146 }
147
148 uint8_t& operator[](unsigned long i) {
149 if (i >= size_) throw std::out_of_range("Rom index out of range");
150 return rom_data_[i];
151 }
152
153 bool is_loaded() const {
154 if (!absl::StrContains(filename_, ".sfc") &&
155 !absl::StrContains(filename_, ".smc")) {
156 return false;
157 }
158 return is_loaded_;
159 }
160
161 auto title() const { return title_; }
162 auto size() const { return size_; }
163 auto data() const { return rom_data_.data(); }
164 auto mutable_data() { return rom_data_.data(); }
165 auto begin() { return rom_data_.begin(); }
166 auto end() { return rom_data_.end(); }
167
168 auto vector() const { return rom_data_; }
169 auto version() const { return version_; }
170 auto filename() const { return filename_; }
171 auto set_filename(std::string name) { filename_ = name; }
172
173 std::vector<uint8_t> graphics_buffer() const { return graphics_buffer_; }
175 auto palette_group() const { return palette_groups_; }
177 auto dungeon_palette(int i) { return palette_groups_.dungeon_main[i]; }
179 return palette_groups_.dungeon_main.mutable_palette(i);
180 }
181
184 return kVersionConstantsMap.at(version_);
185 }
186
187 std::array<std::array<uint8_t, 8>, kNumMainBlocksets> main_blockset_ids;
188 std::array<std::array<uint8_t, 4>, kNumRoomBlocksets> room_blockset_ids;
189 std::array<std::array<uint8_t, 4>, kNumSpritesets> spriteset_ids;
190 std::array<std::array<uint8_t, 4>, kNumPalettesets> paletteset_ids;
191
192 struct WriteAction {
194 std::variant<int, uint8_t, uint16_t, short, std::vector<uint8_t>,
195 gfx::SnesColor, std::vector<gfx::SnesColor>>
197 };
198
199 private:
200 virtual absl::Status WriteHelper(const WriteAction& action) {
201 if (std::holds_alternative<uint8_t>(action.value)) {
202 return WriteByte(action.address, std::get<uint8_t>(action.value));
203 } else if (std::holds_alternative<uint16_t>(action.value) ||
204 std::holds_alternative<short>(action.value)) {
205 return WriteShort(action.address, std::get<uint16_t>(action.value));
206 } else if (std::holds_alternative<std::vector<uint8_t>>(action.value)) {
207 return WriteVector(action.address,
208 std::get<std::vector<uint8_t>>(action.value));
209 } else if (std::holds_alternative<gfx::SnesColor>(action.value)) {
210 return WriteColor(action.address, std::get<gfx::SnesColor>(action.value));
211 } else if (std::holds_alternative<std::vector<gfx::SnesColor>>(
212 action.value)) {
213 return absl::UnimplementedError(
214 "WriteHelper: std::vector<gfx::SnesColor>");
215 }
216 auto error_message = absl::StrFormat("Invalid write argument type: %s",
217 typeid(action.value).name());
218 return absl::InvalidArgumentError(error_message);
219 }
220
221 template <typename T>
222 absl::Status ReadHelper(T& var, int address) {
223 if constexpr (std::is_same_v<T, uint8_t>) {
224 ASSIGN_OR_RETURN(auto result, ReadByte(address));
225 var = result;
226 } else if constexpr (std::is_same_v<T, uint16_t>) {
227 ASSIGN_OR_RETURN(auto result, ReadWord(address));
228 var = result;
229 } else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
230 ASSIGN_OR_RETURN(auto result, ReadByteVector(address, var.size()));
231 var = result;
232 }
233 return absl::OkStatus();
234 }
235
236 absl::Status LoadZelda3();
237 absl::Status LoadGfxGroups();
238 absl::Status SaveGroupsToRom();
239
240 // ROM file loaded flag
241 bool is_loaded_ = false;
242
243 // Size of the ROM data.
244 unsigned long size_ = 0;
245
246 // Title of the ROM loaded from the header
247 std::string title_ = "ROM not loaded";
248
249 // Filename of the ROM
250 std::string filename_ = "";
251
252 // Full contiguous rom space
253 std::vector<uint8_t> rom_data_;
254
255 // Full contiguous graphics space
256 std::vector<uint8_t> graphics_buffer_;
257
258 // Label manager for unique resource names.
260
261 // All palette groups in the game
263
264 // Version of the game
266};
267
269 public:
271 static GraphicsSheetManager instance;
272 return instance;
273 }
275 virtual ~GraphicsSheetManager() = default;
276 std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets() { return gfx_sheets_; }
277 auto gfx_sheet(int i) { return gfx_sheets_[i]; }
278 auto mutable_gfx_sheet(int i) { return &gfx_sheets_[i]; }
279 auto mutable_gfx_sheets() { return &gfx_sheets_; }
280
281 private:
282 std::array<gfx::Bitmap, kNumGfxSheets> gfx_sheets_;
283};
284
303absl::StatusOr<std::array<gfx::Bitmap, kNumGfxSheets>> LoadAllGraphicsData(
304 Rom& rom, bool defer_render = false);
305
306absl::Status SaveAllGraphicsData(
307 Rom& rom, std::array<gfx::Bitmap, kNumGfxSheets>& gfx_sheets);
308
317absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom& rom);
318
322absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(
323 const Rom& rom);
324
325constexpr uint32_t kFastRomRegion = 0x808000;
326
327inline uint32_t SnesToPc(uint32_t addr) noexcept {
328 if (addr >= kFastRomRegion) {
329 addr -= kFastRomRegion;
330 }
331 uint32_t temp = (addr & 0x7FFF) + ((addr / 2) & 0xFF8000);
332 return (temp + 0x0);
333}
334
335inline uint32_t PcToSnes(uint32_t addr) {
336 uint8_t* b = reinterpret_cast<uint8_t*>(&addr);
337 b[2] = static_cast<uint8_t>(b[2] * 2);
338
339 if (b[1] >= 0x80) {
340 b[2] += 1;
341 } else {
342 b[1] += 0x80;
343 }
344
345 return addr;
346}
347
348inline uint32_t Get24LocalFromPC(uint8_t* data, int addr, bool pc = true) {
349 uint32_t ret =
350 (PcToSnes(addr) & 0xFF0000) | (data[addr + 1] << 8) | data[addr];
351 if (pc) {
352 return SnesToPc(ret);
353 }
354 return ret;
355}
356
357inline int AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) noexcept {
358 return (bank << 16) | (high << 8) | low;
359}
360
361inline uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr) noexcept {
362 uint32_t result = 0;
363 result = (bank << 16) | addr;
364 return result;
365}
366
371 public:
372 SharedRom() = default;
373 virtual ~SharedRom() = default;
374
375 std::shared_ptr<Rom> shared_rom() {
376 if (!shared_rom_) {
377 shared_rom_ = std::make_shared<Rom>();
378 }
379 return shared_rom_;
380 }
381
382 auto rom() {
383 if (!shared_rom_) {
384 shared_rom_ = std::make_shared<Rom>();
385 }
386 Rom* rom = shared_rom_.get();
387 return rom;
388 }
389
390 // private:
391 static std::shared_ptr<Rom> shared_rom_;
392};
393
394} // namespace yaze
395
396#endif
virtual ~GraphicsSheetManager()=default
std::array< gfx::Bitmap, kNumGfxSheets > gfx_sheets_
Definition rom.h:282
auto gfx_sheet(int i)
Definition rom.h:277
static GraphicsSheetManager & GetInstance()
Definition rom.h:270
auto mutable_gfx_sheet(int i)
Definition rom.h:278
std::array< gfx::Bitmap, kNumGfxSheets > & gfx_sheets()
Definition rom.h:276
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:258
zelda3_version version_
Definition rom.h:265
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
Definition rom.cc:172
auto mutable_graphics_buffer()
Definition rom.h:174
absl::Status ReadTransaction(T &var, int address, Args &&... args)
Definition rom.h:137
auto begin()
Definition rom.h:165
absl::Status SaveGroupsToRom()
Definition rom.cc:563
std::vector< uint8_t > rom_data_
Definition rom.h:253
std::vector< uint8_t > graphics_buffer() const
Definition rom.h:173
gfx::PaletteGroupMap palette_groups_
Definition rom.h:262
auto palette_group() const
Definition rom.h:175
absl::StatusOr< gfx::Tile16 > ReadTile16(uint32_t tile16_id)
Definition rom.cc:270
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
Definition rom.cc:362
auto filename() const
Definition rom.h:170
auto mutable_palette_group()
Definition rom.h:176
absl::Status LoadFromData(const std::vector< uint8_t > &data, bool z3_load=true)
Definition rom.cc:217
auto end()
Definition rom.h:166
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:301
auto vector() const
Definition rom.h:168
auto version() const
Definition rom.h:169
auto mutable_data()
Definition rom.h:164
absl::Status SaveToFile(bool backup, bool save_new=false, std::string filename="")
Saves the Rom data to a file.
Definition rom.cc:407
absl::Status LoadZelda3()
Definition rom.cc:371
std::array< std::array< uint8_t, 4 >, kNumSpritesets > spriteset_ids
Definition rom.h:189
ResourceLabelManager * resource_label()
Definition rom.h:182
std::array< std::array< uint8_t, 4 >, kNumPalettesets > paletteset_ids
Definition rom.h:190
auto mutable_dungeon_palette(int i)
Definition rom.h:178
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:241
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
Definition rom.cc:349
std::string title_
Definition rom.h:247
absl::Status WriteTile16(int tile16_id, const gfx::Tile16 &tile)
Definition rom.cc:288
void Expand(int size)
Definition rom.h:102
absl::Status WriteTransaction(Args... args)
Definition rom.h:129
auto set_filename(std::string name)
Definition rom.h:171
std::array< std::array< uint8_t, 4 >, kNumRoomBlocksets > room_blockset_ids
Definition rom.h:188
virtual absl::Status WriteHelper(const WriteAction &action)
Definition rom.h:200
absl::StatusOr< uint32_t > ReadLong(int offset)
Definition rom.cc:249
auto data() const
Definition rom.h:163
auto size() const
Definition rom.h:162
std::vector< uint8_t > graphics_buffer_
Definition rom.h:256
zelda3_version_pointers version_constants() const
Definition rom.h:183
ResourceLabelManager resource_label_manager_
Definition rom.h:259
absl::Status LoadGfxGroups()
Definition rom.cc:530
bool is_loaded_
Definition rom.h:241
absl::Status ReadHelper(T &var, int address)
Definition rom.h:222
std::string filename_
Definition rom.h:250
unsigned long size_
Definition rom.h:244
absl::Status SavePalette(int index, const std::string &group_name, gfx::SnesPalette &palette)
Definition rom.cc:503
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:234
absl::Status WriteShort(int addr, uint16_t value)
Definition rom.cc:324
auto dungeon_palette(int i)
Definition rom.h:177
void Close()
Definition rom.h:107
uint8_t & operator[](unsigned long i)
Definition rom.h:148
bool is_loaded() const
Definition rom.h:153
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:312
absl::Status WriteLong(uint32_t addr, uint32_t value)
Definition rom.cc:336
auto title() const
Definition rom.h:161
std::array< std::array< uint8_t, 8 >, kNumMainBlocksets > main_blockset_ids
Definition rom.h:187
absl::Status SaveAllPalettes()
Saves all palettes in the Rom.
Definition rom.cc:517
virtual ~SharedRom()=default
static std::shared_ptr< Rom > shared_rom_
Definition rom.h:391
auto rom()
Definition rom.h:382
std::shared_ptr< Rom > shared_rom()
Definition rom.h:375
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:59
Main namespace for the application.
Definition controller.cc:18
uint32_t PcToSnes(uint32_t addr)
Definition rom.h:335
uint32_t MapBankToWordAddress(uint8_t bank, uint16_t addr) noexcept
Definition rom.h:361
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:325
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:348
constexpr uint32_t kNumSpritesets
Definition rom.h:40
int AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) noexcept
Definition rom.h:357
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:77
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:136
uint32_t SnesToPc(uint32_t addr) noexcept
Definition rom.h:327
std::variant< int, uint8_t, uint16_t, short, std::vector< uint8_t >, gfx::SnesColor, std::vector< gfx::SnesColor > > value
Definition rom.h:196
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