yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
game_data.cc
Go to the documentation of this file.
1#include "zelda3/game_data.h"
2
3#include "absl/strings/str_format.h"
5#include "util/log.h"
6#include "util/macro.h"
8
9#include <algorithm>
10
11#ifdef __EMSCRIPTEN__
13#endif
14
15namespace yaze {
16namespace zelda3 {
17
18namespace {
19
20constexpr uint32_t kUncompressedSheetSize = 0x0800;
21// constexpr uint32_t kTile16Ptr = 0x78000;
22
23// Helper to get address from bytes
24uint32_t AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) {
25 return (bank << 16) | (high << 8) | low;
26}
27
28// Helper to convert SNES to PC address
29uint32_t SnesToPc(uint32_t snes_addr) {
30 return (snes_addr & 0x7FFF) | ((snes_addr & 0x7F0000) >> 1);
31}
32
34 size_t offset = 0;
35 int length = 0;
36 bool valid = false;
37};
38
40 const int palette_size = static_cast<int>(palette.size());
41 if (palette_size <= 0) {
42 return {};
43 }
44
45 const bool has_explicit_transparent =
46 palette_size >= 16 && (palette_size % 16 == 0);
47 PaletteSlice slice;
48 slice.offset = has_explicit_transparent ? 1 : 0;
49 slice.length = has_explicit_transparent ? 15 : std::min(palette_size, 15);
50 slice.valid =
51 slice.length > 0 &&
52 (slice.offset + static_cast<size_t>(slice.length) <= palette.size());
53
54 if (!slice.valid) {
55 slice.offset = 0;
56 slice.length = std::min(palette_size, 15);
57 slice.valid =
58 slice.length > 0 &&
59 (slice.offset + static_cast<size_t>(slice.length) <= palette.size());
60 }
61
62 return slice;
63}
64
65void ApplyDefaultPalette(gfx::Bitmap& bitmap, const gfx::SnesPalette& palette) {
66 auto slice = GetDefaultPaletteSlice(palette);
67 if (!slice.valid) {
68 return;
69 }
70 bitmap.SetPaletteWithTransparent(palette, slice.offset, slice.length);
71}
72
73// Helper to convert PC to SNES address
74// uint32_t PcToSnes(uint32_t pc_addr) {
75// return ((pc_addr & 0x7FFF) | 0x8000) | ((pc_addr & 0x3F8000) << 1);
76// }
77
78// ============================================================================
79// Graphics Address Resolution
80// ============================================================================
81
107} // namespace
108
111uint32_t GetGraphicsAddress(const uint8_t* data, uint8_t addr, uint32_t ptr1,
112 uint32_t ptr2, uint32_t ptr3, size_t rom_size) {
113 if (ptr1 > UINT32_MAX - addr || ptr1 + addr >= rom_size ||
114 ptr2 > UINT32_MAX - addr || ptr2 + addr >= rom_size ||
115 ptr3 > UINT32_MAX - addr || ptr3 + addr >= rom_size) {
116 return static_cast<uint32_t>(rom_size);
117 }
118 return SnesToPc(AddressFromBytes(data[ptr1 + addr], data[ptr2 + addr],
119 data[ptr3 + addr]));
120}
121
122absl::Status LoadGameData(Rom& rom, GameData& data,
123 const LoadOptions& options) {
124 data.Clear();
125 data.set_rom(&rom);
126
127 if (options.populate_metadata) {
128 RETURN_IF_ERROR(LoadMetadata(rom, data));
129 }
130
131 if (options.load_palettes) {
132 RETURN_IF_ERROR(LoadPalettes(rom, data));
133 }
134
135 if (options.load_gfx_groups) {
136 RETURN_IF_ERROR(LoadGfxGroups(rom, data));
137 }
138
139 if (options.load_graphics) {
140 RETURN_IF_ERROR(LoadGraphics(rom, data));
141 }
142
143 if (options.expand_rom) {
144 if (rom.size() < 1048576 * 2) {
145 rom.Expand(1048576 * 2);
146 }
147 }
148
149 return absl::OkStatus();
150}
151
152absl::Status SaveGameData(Rom& rom, GameData& data) {
153 if (core::FeatureFlags::get().kSaveAllPalettes) {
154 // TODO: Implement SaveAllPalettes logic using Rom::WriteColor
155 // This was previously in Rom::SaveAllPalettes
156 return data.palette_groups.for_each(
157 [&](gfx::PaletteGroup& group) -> absl::Status {
158 for (size_t i = 0; i < group.size(); ++i) {
159 auto* palette = group.mutable_palette(i);
160 for (size_t j = 0; j < palette->size(); ++j) {
161 gfx::SnesColor color = (*palette)[j];
162 if (color.is_modified()) {
163 RETURN_IF_ERROR(rom.WriteColor(
164 gfx::GetPaletteAddress(group.name(), i, j), color));
165 color.set_modified(false);
166 }
167 }
168 }
169 return absl::OkStatus();
170 });
171 }
172
174 RETURN_IF_ERROR(SaveGfxGroups(rom, data));
175 }
176
177 // TODO: Implement SaveAllGraphicsData logic
178 return absl::OkStatus();
179}
180
181absl::Status LoadMetadata(const Rom& rom, GameData& data) {
182 constexpr uint32_t kTitleStringOffset = 0x7FC0;
183 constexpr uint32_t kTitleStringLength = 20;
184
185 if (rom.size() < kTitleStringOffset + kTitleStringLength) {
186 return absl::OutOfRangeError("ROM too small for metadata");
187 }
188
189 // Check version byte at offset + 0x19 (0x7FD9)
190 if (kTitleStringOffset + 0x19 < rom.size()) {
191 // Access directly via data() since ReadByte is non-const
192 uint8_t version_byte = rom.data()[kTitleStringOffset + 0x19];
193 data.version =
194 (version_byte == 0) ? zelda3_version::JP : zelda3_version::US;
195 }
196
197 auto title_bytes = rom.ReadByteVector(kTitleStringOffset, kTitleStringLength);
198 if (title_bytes.ok()) {
199 data.title.assign(title_bytes->begin(), title_bytes->end());
200 }
201
202 return absl::OkStatus();
203}
204
205absl::Status LoadPalettes(const Rom& rom, GameData& data) {
206 // Create a vector from rom data for palette loading
207 const std::vector<uint8_t>& rom_vec = rom.vector();
208 return gfx::LoadAllPalettes(rom_vec, data.palette_groups);
209}
210
211absl::Status LoadGfxGroups(Rom& rom, GameData& data) {
212 if (kVersionConstantsMap.find(data.version) == kVersionConstantsMap.end()) {
213 return absl::FailedPreconditionError("Unsupported ROM version");
214 }
215
216 auto version_constants = kVersionConstantsMap.at(data.version);
217
218 // Load Main Blocksets
219 auto main_ptr_res = rom.ReadWord(kGfxGroupsPointer);
220 if (main_ptr_res.ok()) {
221 uint32_t main_ptr = SnesToPc(*main_ptr_res);
222 for (uint32_t i = 0; i < kNumMainBlocksets; i++) {
223 for (int j = 0; j < 8; j++) {
224 auto val = rom.ReadByte(main_ptr + (i * 8) + j);
225 if (val.ok())
226 data.main_blockset_ids[i][j] = *val;
227 }
228 }
229 }
230
231 // Load Room Blocksets
232 for (uint32_t i = 0; i < kNumRoomBlocksets; i++) {
233 for (int j = 0; j < 4; j++) {
234 auto val = rom.ReadByte(kEntranceGfxGroup + (i * 4) + j);
235 if (val.ok())
236 data.room_blockset_ids[i][j] = *val;
237 }
238 }
239
240 // Load Sprite Blocksets
241 for (uint32_t i = 0; i < kNumSpritesets; i++) {
242 for (int j = 0; j < 4; j++) {
243 auto val =
244 rom.ReadByte(version_constants.kSpriteBlocksetPointer + (i * 4) + j);
245 if (val.ok())
246 data.spriteset_ids[i][j] = *val;
247 }
248 }
249
250 // Load Palette Sets
251 for (uint32_t i = 0; i < kNumPalettesets; i++) {
252 for (int j = 0; j < 4; j++) {
253 auto val =
254 rom.ReadByte(version_constants.kDungeonPalettesGroups + (i * 4) + j);
255 if (val.ok())
256 data.paletteset_ids[i][j] = *val;
257 }
258 }
259
260 return absl::OkStatus();
261}
262
263absl::Status SaveGfxGroups(Rom& rom, const GameData& data) {
264 auto version_constants = kVersionConstantsMap.at(data.version);
265
266 ASSIGN_OR_RETURN(auto main_ptr, rom.ReadWord(kGfxGroupsPointer));
267 main_ptr = SnesToPc(main_ptr);
268
269 // Save Main Blocksets
270 for (uint32_t i = 0; i < kNumMainBlocksets; i++) {
271 for (int j = 0; j < 8; j++) {
273 rom.WriteByte(main_ptr + (i * 8) + j, data.main_blockset_ids[i][j]));
274 }
275 }
276
277 // Save Room Blocksets
278 for (uint32_t i = 0; i < kNumRoomBlocksets; i++) {
279 for (int j = 0; j < 4; j++) {
281 data.room_blockset_ids[i][j]));
282 }
283 }
284
285 // Save Sprite Blocksets
286 for (uint32_t i = 0; i < kNumSpritesets; i++) {
287 for (int j = 0; j < 4; j++) {
289 rom.WriteByte(version_constants.kSpriteBlocksetPointer + (i * 4) + j,
290 data.spriteset_ids[i][j]));
291 }
292 }
293
294 // Save Palette Sets
295 for (uint32_t i = 0; i < kNumPalettesets; i++) {
296 for (int j = 0; j < 4; j++) {
298 rom.WriteByte(version_constants.kDungeonPalettesGroups + (i * 4) + j,
299 data.paletteset_ids[i][j]));
300 }
301 }
302
303 return absl::OkStatus();
304}
305
306// ============================================================================
307// Main Graphics Loading
308// ============================================================================
309
339absl::Status LoadGraphics(Rom& rom, GameData& data) {
340 if (kVersionConstantsMap.find(data.version) == kVersionConstantsMap.end()) {
341 return absl::FailedPreconditionError(
342 "Unsupported ROM version for graphics");
343 }
344 auto version_constants = kVersionConstantsMap.at(data.version);
345
346 data.graphics_buffer.clear();
347
348#ifdef __EMSCRIPTEN__
349 auto loading_handle =
350 app::platform::WasmLoadingManager::BeginLoading("Loading Graphics");
351#endif
352
353 // Initialize Diagnostics
354 auto& diag = data.diagnostics;
355 diag.rom_size = rom.size();
356 diag.ptr1_loc = version_constants.kOverworldGfxPtr1;
357 diag.ptr2_loc = version_constants.kOverworldGfxPtr2;
358 diag.ptr3_loc = version_constants.kOverworldGfxPtr3;
359
360 for (uint32_t i = 0; i < kNumGfxSheets; i++) {
361#ifdef __EMSCRIPTEN__
362 app::platform::WasmLoadingManager::UpdateProgress(
363 loading_handle, static_cast<float>(i) / kNumGfxSheets);
364#endif
365
366 diag.sheets[i].index = i;
367 std::vector<uint8_t> sheet;
368 bool bpp3 = false;
369 uint32_t offset = 0;
370
371 // Uncompressed 3BPP (115-126)
372 if (i >= 115 && i <= 126) {
373 diag.sheets[i].is_compressed = false;
374 offset =
375 GetGraphicsAddress(rom.data(), i, version_constants.kOverworldGfxPtr1,
376 version_constants.kOverworldGfxPtr2,
377 version_constants.kOverworldGfxPtr3, rom.size());
378 diag.sheets[i].pc_offset = offset;
379
380 auto read_res =
382 if (read_res.ok()) {
383 sheet = *read_res;
384 diag.sheets[i].decompression_succeeded = true;
385 bpp3 = true;
386 } else {
387 sheet.assign(zelda3::kUncompressedSheetSize, 0);
388 diag.sheets[i].decompression_succeeded = false;
389 }
390 }
391 // 2BPP (113-114, 218+) - Skipped in main loop
392 else if (i == 113 || i == 114 || i >= 218) {
393 diag.sheets[i].is_compressed = true;
394 bpp3 = false;
395 }
396 // Compressed 3BPP (Standard)
397 else {
398 diag.sheets[i].is_compressed = true;
399 offset =
400 GetGraphicsAddress(rom.data(), i, version_constants.kOverworldGfxPtr1,
401 version_constants.kOverworldGfxPtr2,
402 version_constants.kOverworldGfxPtr3, rom.size());
403 diag.sheets[i].pc_offset = offset;
404
405 if (offset < rom.size()) {
406 // Decompress using LC-LZ2 algorithm with 0x800 byte output buffer.
407 // IMPORTANT: The size parameter (0x800) must NOT be 0, or DecompressV2
408 // returns an empty vector immediately. This was a regression bug.
409 // See: docs/internal/graphics-loading-regression-2024.md
410 auto decomp_res =
411 gfx::lc_lz2::DecompressV2(rom.data(), offset, 0x800, 1, rom.size());
412 if (decomp_res.ok()) {
413 sheet = *decomp_res;
414 diag.sheets[i].decompression_succeeded = true;
415 bpp3 = true;
416 } else {
417 diag.sheets[i].decompression_succeeded = false;
418 }
419 }
420 }
421
422 // Post-process
423 if (bpp3) {
424 auto converted_sheet = gfx::SnesTo8bppSheet(sheet, 3);
425 if (converted_sheet.size() != 4096)
426 converted_sheet.resize(4096, 0);
427
428 data.raw_gfx_sheets[i] = converted_sheet;
430 gfx::kTilesheetDepth, converted_sheet);
431
432 // Apply default palettes
433 if (!data.palette_groups.empty()) {
434 gfx::SnesPalette default_palette;
435 if (i < 113 && data.palette_groups.dungeon_main.size() > 0) {
436 default_palette = data.palette_groups.dungeon_main[0];
437 } else if (i < 128 && data.palette_groups.sprites_aux1.size() > 0) {
438 default_palette = data.palette_groups.sprites_aux1[0];
439 } else if (data.palette_groups.hud.size() > 0) {
440 default_palette = data.palette_groups.hud.palette(0);
441 }
442
443 if (!default_palette.empty()) {
444 ApplyDefaultPalette(data.gfx_bitmaps[i], default_palette);
445 } else {
446 // Fallback to grayscale if no palette found
447 std::vector<gfx::SnesColor> grayscale;
448 for (int color_idx = 0; color_idx < 16; ++color_idx) {
449 float val = color_idx / 15.0f;
450 grayscale.emplace_back(ImVec4(val, val, val, 1.0f));
451 }
452 // Ensure index 0 is transparent for SNES compatibility
453 if (!grayscale.empty()) {
454 grayscale[0].set_transparent(true);
455 }
456 data.gfx_bitmaps[i].SetPalette(gfx::SnesPalette(grayscale));
457 }
458 } else {
459 // Fallback to grayscale if no palette groups loaded
460 std::vector<gfx::SnesColor> grayscale;
461 for (int color_idx = 0; color_idx < 16; ++color_idx) {
462 float val = color_idx / 15.0f;
463 grayscale.emplace_back(ImVec4(val, val, val, 1.0f));
464 }
465 // Ensure index 0 is transparent for SNES compatibility
466 if (!grayscale.empty()) {
467 grayscale[0].set_transparent(true);
468 }
469 data.gfx_bitmaps[i].SetPalette(gfx::SnesPalette(grayscale));
470 }
471
472 data.graphics_buffer.insert(
473 data.graphics_buffer.end(), data.gfx_bitmaps[i].data(),
474 data.gfx_bitmaps[i].data() + data.gfx_bitmaps[i].size());
475 } else {
476 // Placeholder - Fill with 0 (transparent) instead of 0xFF (white)
477 std::vector<uint8_t> placeholder(4096, 0);
478 data.raw_gfx_sheets[i] = placeholder;
480 gfx::kTilesheetDepth, placeholder);
481 data.graphics_buffer.resize(data.graphics_buffer.size() + 4096, 0);
482 }
483 }
484
485 diag.Analyze();
486
487#ifdef __EMSCRIPTEN__
488 app::platform::WasmLoadingManager::EndLoading(loading_handle);
489#endif
490
491 return absl::OkStatus();
492}
493
494// ============================================================================
495// Link Graphics Loading
496// ============================================================================
497
498absl::StatusOr<std::array<gfx::Bitmap, kNumLinkSheets>> LoadLinkGraphics(
499 const Rom& rom) {
500 std::array<gfx::Bitmap, kNumLinkSheets> link_graphics;
501 for (uint32_t i = 0; i < kNumLinkSheets; i++) {
502 auto link_sheet_data_result =
503 rom.ReadByteVector(/*offset=*/kLinkGfxOffset + (i * kLinkGfxLength),
504 /*length=*/kLinkGfxLength);
505 if (!link_sheet_data_result.ok()) {
506 return link_sheet_data_result.status();
507 }
508 auto link_sheet_8bpp =
509 gfx::SnesTo8bppSheet(*link_sheet_data_result, /*bpp=*/4);
510 if (link_sheet_8bpp.size() != 4096)
511 link_sheet_8bpp.resize(4096, 0);
512
513 link_graphics[i].Create(gfx::kTilesheetWidth, gfx::kTilesheetHeight,
514 gfx::kTilesheetDepth, link_sheet_8bpp);
515 // Palette is applied by the caller since GameData may not be available here
516 }
517 return link_graphics;
518}
519
520// ============================================================================
521// 2BPP Graphics Loading
522// ============================================================================
523
524absl::StatusOr<std::vector<uint8_t>> Load2BppGraphics(const Rom& rom) {
525 std::vector<uint8_t> sheet;
526 const uint8_t sheets[] = {0x71, 0x72, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE};
527
528 // Get version constants - default to US if we don't know
529 auto version_constants = kVersionConstantsMap.at(zelda3_version::US);
530
531 for (const auto& sheet_id : sheets) {
532 auto offset = GetGraphicsAddress(
533 rom.data(), sheet_id, version_constants.kOverworldGfxPtr1,
534 version_constants.kOverworldGfxPtr2,
535 version_constants.kOverworldGfxPtr3, rom.size());
536
537 if (offset >= rom.size()) {
538 return absl::OutOfRangeError(absl::StrFormat(
539 "2BPP graphics sheet %u offset %u exceeds ROM size %zu", sheet_id,
540 offset, rom.size()));
541 }
542
543 // Decompress using LC-LZ2 algorithm with 0x800 byte output buffer.
544 auto decomp_result =
545 gfx::lc_lz2::DecompressV2(rom.data(), offset, 0x800, 1, rom.size());
546 if (!decomp_result.ok()) {
547 return decomp_result.status();
548 }
549 auto converted_sheet = gfx::SnesTo8bppSheet(*decomp_result, 2);
550 for (const auto& each_pixel : converted_sheet) {
551 sheet.push_back(each_pixel);
552 }
553 }
554 return sheet;
555}
556
557// ============================================================================
558// Font Graphics Loading
559// ============================================================================
560
561absl::StatusOr<gfx::Bitmap> LoadFontGraphics(const Rom& rom) {
562 // Font sprites are located at 0x70000, 2BPP format
563 constexpr uint32_t kFontDataSize = 0x4000; // 16KB of font data
564
565 auto font_data_result =
566 rom.ReadByteVector(kFontSpriteLocation, kFontDataSize);
567 if (!font_data_result.ok()) {
568 return font_data_result.status();
569 }
570
571 // Convert from 2BPP SNES format to 8BPP
572 auto font_8bpp = gfx::SnesTo8bppSheet(*font_data_result, /*bpp=*/2);
573
574 gfx::Bitmap font_bitmap;
576 gfx::kTilesheetDepth, font_8bpp);
577
578 return font_bitmap;
579}
580
581// ============================================================================
582// Graphics Saving
583// ============================================================================
584
586 [[maybe_unused]] Rom& rom,
587 [[maybe_unused]] const std::array<gfx::Bitmap, kNumGfxSheets>& sheets) {
588 // For now, return OK status - full implementation would write sheets back
589 // to ROM at their respective addresses with proper compression
590 LOG_INFO("SaveAllGraphicsData", "Graphics save not yet fully implemented");
591 return absl::OkStatus();
592}
593
594} // namespace zelda3
595} // namespace yaze
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length) const
Definition rom.cc:245
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:290
const auto & vector() const
Definition rom.h:139
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:230
void Expand(int size)
Definition rom.h:49
auto data() const
Definition rom.h:135
auto size() const
Definition rom.h:134
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:222
static Flags & get()
Definition features.h:92
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:67
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
Definition bitmap.cc:201
void SetPaletteWithTransparent(const SnesPalette &palette, size_t index, int length=7)
Set the palette with a transparent color.
Definition bitmap.cc:456
SNES Color container.
Definition snes_color.h:110
constexpr bool is_modified() const
Definition snes_color.h:195
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
#define LOG_INFO(category, format,...)
Definition log.h:105
#define ASSIGN_OR_RETURN(type_variable_name, expression)
Definition macro.h:62
absl::StatusOr< std::vector< uint8_t > > DecompressV2(const uint8_t *data, int offset, int size, int mode, size_t rom_size)
Decompresses a buffer of data using the LC_LZ2 algorithm.
constexpr int kTilesheetHeight
Definition snes_tile.h:17
constexpr int kTilesheetWidth
Definition snes_tile.h:16
constexpr int kTilesheetDepth
Definition snes_tile.h:18
std::vector< uint8_t > SnesTo8bppSheet(std::span< uint8_t > sheet, int bpp, int num_sheets)
Definition snes_tile.cc:132
absl::Status LoadAllPalettes(const std::vector< uint8_t > &rom_data, PaletteGroupMap &groups)
Loads all the palettes for the game.
void ApplyDefaultPalette(gfx::Bitmap &bitmap, const gfx::SnesPalette &palette)
Definition game_data.cc:65
PaletteSlice GetDefaultPaletteSlice(const gfx::SnesPalette &palette)
Definition game_data.cc:39
absl::Status SaveGfxGroups(Rom &rom, const GameData &data)
Definition game_data.cc:263
absl::StatusOr< std::vector< uint8_t > > Load2BppGraphics(const Rom &rom)
Loads 2BPP graphics sheets from ROM.
Definition game_data.cc:524
constexpr uint16_t kLinkGfxLength
Definition game_data.h:48
constexpr uint32_t kFontSpriteLocation
Definition game_data.h:51
absl::StatusOr< std::array< gfx::Bitmap, kNumLinkSheets > > LoadLinkGraphics(const Rom &rom)
Loads Link's graphics sheets from ROM.
Definition game_data.cc:498
absl::StatusOr< gfx::Bitmap > LoadFontGraphics(const Rom &rom)
Loads font graphics from ROM.
Definition game_data.cc:561
constexpr uint32_t kNumRoomBlocksets
Definition game_data.h:30
constexpr uint32_t kUncompressedSheetSize
Definition game_data.h:54
absl::Status LoadGameData(Rom &rom, GameData &data, const LoadOptions &options)
Loads all Zelda3-specific game data from a generic ROM.
Definition game_data.cc:122
absl::Status LoadMetadata(const Rom &rom, GameData &data)
Definition game_data.cc:181
constexpr uint32_t kNumPalettesets
Definition game_data.h:32
absl::Status SaveAllGraphicsData(Rom &rom, const std::array< gfx::Bitmap, kNumGfxSheets > &sheets)
Saves all graphics sheets back to ROM.
Definition game_data.cc:585
constexpr uint32_t kLinkGfxOffset
Definition game_data.h:47
constexpr uint32_t kNumMainBlocksets
Definition game_data.h:29
constexpr uint32_t kNumGfxSheets
Definition game_data.h:25
constexpr uint32_t kEntranceGfxGroup
Definition game_data.h:35
constexpr uint32_t kNumSpritesets
Definition game_data.h:31
constexpr uint32_t kNumLinkSheets
Definition game_data.h:26
absl::Status LoadPalettes(const Rom &rom, GameData &data)
Definition game_data.cc:205
absl::Status SaveGameData(Rom &rom, GameData &data)
Saves modified game data back to the ROM.
Definition game_data.cc:152
absl::Status LoadGraphics(Rom &rom, GameData &data)
Definition game_data.cc:339
uint32_t GetGraphicsAddress(const uint8_t *data, uint8_t addr, uint32_t ptr1, uint32_t ptr2, uint32_t ptr3, size_t rom_size)
Gets the graphics address for a sheet index.
Definition game_data.cc:111
absl::Status LoadGfxGroups(Rom &rom, GameData &data)
Definition game_data.cc:211
constexpr int kGfxGroupsPointer
int AddressFromBytes(uint8_t bank, uint8_t high, uint8_t low) noexcept
Definition snes.h:39
uint32_t SnesToPc(uint32_t addr) noexcept
Definition snes.h:8
#define RETURN_IF_ERROR(expr)
Definition snes.cc:22
absl::Status for_each(Func &&func)
Represents a group of palettes.
auto palette(int i) const
std::array< std::array< uint8_t, 4 >, kNumSpritesets > spriteset_ids
Definition game_data.h:93
void set_rom(Rom *rom)
Definition game_data.h:75
std::array< std::array< uint8_t, 4 >, kNumRoomBlocksets > room_blockset_ids
Definition game_data.h:92
std::array< std::array< uint8_t, 4 >, kNumPalettesets > paletteset_ids
Definition game_data.h:99
gfx::PaletteGroupMap palette_groups
Definition game_data.h:89
GraphicsLoadDiagnostics diagnostics
Definition game_data.h:102
zelda3_version version
Definition game_data.h:78
std::array< gfx::Bitmap, kNumGfxSheets > gfx_bitmaps
Definition game_data.h:84
std::array< std::array< uint8_t, 8 >, kNumMainBlocksets > main_blockset_ids
Definition game_data.h:91
std::array< std::vector< uint8_t >, kNumGfxSheets > raw_gfx_sheets
Definition game_data.h:83
std::vector< uint8_t > graphics_buffer
Definition game_data.h:82