20#include <unordered_map>
24#include "absl/container/flat_hash_map.h"
25#include "absl/status/status.h"
26#include "absl/status/statusor.h"
27#include "absl/strings/match.h"
28#include "absl/strings/str_cat.h"
29#include "absl/strings/str_format.h"
30#include "absl/strings/string_view.h"
79static const std::map<Z3_Version, VersionConstants> kVersionConstantsMap = {
202 absl::Status
SaveToFile(
bool backup,
bool save_new =
false,
212 absl::Status
SavePalette(
int index,
const std::string& group_name,
238 return absl::OkStatus();
246 return absl::FailedPreconditionError(
"ROM file not loaded");
249 return absl::FailedPreconditionError(
250 "File was loaded, but ROM data was empty.");
252 return absl::OkStatus();
258 if (offset >=
static_cast<int>(
rom_data_.size())) {
259 return absl::FailedPreconditionError(
"Offset out of range");
266 if (offset + 1 >=
static_cast<int>(
rom_data_.size())) {
267 return absl::FailedPreconditionError(
"Offset out of range");
279 if (offset + 2 >=
static_cast<int>(
rom_data_.size())) {
280 return absl::OutOfRangeError(
"Offset out of range");
290 if (offset + length >
static_cast<uint32_t
>(
rom_data_.size())) {
291 return absl::OutOfRangeError(
"Offset and length out of range");
293 std::vector<uint8_t> result;
294 for (uint32_t i = offset; i < offset + length; i++) {
328 return absl::OkStatus();
332 absl::Status
Write(
int addr,
int value) {
333 if (addr >=
static_cast<int>(
rom_data_.size())) {
334 return absl::InvalidArgumentError(absl::StrFormat(
335 "Attempt to write %d value failed, address %d out of range", value,
339 return absl::OkStatus();
344 if (addr >=
static_cast<int>(
rom_data_.size())) {
345 return absl::OutOfRangeError(absl::StrFormat(
346 "Attempt to write byte %#02x value failed, address %d out of range",
350 std::string log_str = absl::StrFormat(
"WriteByte: %#06X: %s", addr,
353 return absl::OkStatus();
358 if (addr + 1 >=
static_cast<int>(
rom_data_.size())) {
359 return absl::OutOfRangeError(absl::StrFormat(
360 "Attempt to write word %#04x value failed, address %d out of range",
363 rom_data_[addr] = (uint8_t)(value & 0xFF);
364 rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
367 return absl::OkStatus();
372 if (addr + 1 >=
static_cast<int>(
rom_data_.size())) {
373 return absl::OutOfRangeError(absl::StrFormat(
374 "Attempt to write short %#04x value failed, address %d out of range",
377 rom_data_[addr] = (uint8_t)(value & 0xFF);
378 rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
381 return absl::OkStatus();
386 if (addr + 2 >=
static_cast<uint32_t
>(
rom_data_.size())) {
387 return absl::OutOfRangeError(absl::StrFormat(
388 "Attempt to write long %#06x value failed, address %d out of range",
391 rom_data_[addr] = (uint8_t)(value & 0xFF);
392 rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
393 rom_data_[addr + 2] = (uint8_t)((value >> 16) & 0xFF);
396 return absl::OkStatus();
400 if (addr +
static_cast<int>(
data.size()) >
402 return absl::InvalidArgumentError(absl::StrFormat(
403 "Attempt to write vector value failed, address %d out of range",
406 for (
int i = 0; i < static_cast<int>(
data.size()); i++) {
411 return absl::OkStatus();
415 uint16_t bgr = ((color.
snes() >> 10) & 0x1F) |
416 ((color.
snes() & 0x1F) << 10) | (color.
snes() & 0x7C00);
424 template <
typename... Args>
432 template <
typename T,
typename... Args>
439 if constexpr (
sizeof...(args) > 0) {
448 std::cout <<
"ROM: Index " << i <<
" out of bounds, size: " <<
size_
456 if (!absl::StrContains(
filename_,
".sfc") &&
492 return kVersionConstantsMap.at(
version_);
502 std::variant<int, uint8_t, uint16_t, short, std::vector<uint8_t>,
509 if (std::holds_alternative<uint8_t>(action.
value)) {
511 }
else if (std::holds_alternative<uint16_t>(action.
value) ||
512 std::holds_alternative<short>(action.
value)) {
514 }
else if (std::holds_alternative<std::vector<uint8_t>>(action.
value)) {
516 std::get<std::vector<uint8_t>>(action.
value));
517 }
else if (std::holds_alternative<gfx::SnesColor>(action.
value)) {
519 }
else if (std::holds_alternative<std::vector<gfx::SnesColor>>(
521 return absl::UnimplementedError(
522 "WriteHelper: std::vector<gfx::SnesColor>");
524 auto error_message = absl::StrFormat(
"Invalid write argument type: %s",
525 typeid(action.
value).name());
526 return absl::InvalidArgumentError(error_message);
529 template <
typename T>
531 if constexpr (std::is_same_v<T, uint8_t>) {
534 }
else if constexpr (std::is_same_v<T, uint16_t>) {
537 }
else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
541 return absl::OkStatus();
The Rom class is used to load, save, and modify Rom data.
absl::Status WriteByte(int addr, uint8_t value)
auto mutable_palette_group()
VersionConstants version_constants() const
absl::Status WriteTransaction(Args... args)
std::vector< uint8_t > graphics_buffer() const
std::vector< uint8_t > rom_data_
absl::Status WriteLong(uint32_t addr, uint32_t value)
absl::Status LoadGfxGroups()
uint16_t toint16(int offset)
std::vector< std::vector< uint8_t > > paletteset_ids
absl::Status ReadTransaction(T &var, int address, Args &&... args)
absl::Status SaveToFile(bool backup, bool save_new=false, std::string filename="")
Saves the Rom data to a file.
absl::StatusOr< uint32_t > ReadLong(int offset)
absl::Status SaveAllPalettes()
Saves all palettes in the Rom.
absl::StatusOr< gfx::Tile16 > ReadTile16(uint32_t tile16_id)
auto mutable_gfx_sheets()
std::array< gfx::Bitmap, kNumGfxSheets > graphics_sheets_
core::ResourceLabelManager * resource_label()
absl::Status SavePalette(int index, const std::string &group_name, gfx::SnesPalette &palette)
absl::Status LoadAllGraphicsData(bool defer_render=false)
This function iterates over all graphics sheets in the Rom and loads them into memory....
virtual absl::Status WriteHelper(const WriteAction &action)
std::vector< std::vector< uint8_t > > spriteset_ids
absl::StatusOr< std::vector< uint8_t > > Load2BppGraphics()
Loads 2bpp graphics from Rom data.
void Expand(int size)
Expand the Rom data to a specified size.
absl::Status WriteTile16(int tile16_id, const gfx::Tile16 &tile)
auto set_filename(std::string name)
std::vector< std::vector< uint8_t > > room_blockset_ids
absl::Status LoadLinkGraphics()
Loads the players 4bpp graphics sheet from Rom data.
gfx::PaletteGroupMap palette_groups_
absl::Status WriteShort(int addr, uint16_t value)
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
absl::Status Write(int addr, int value)
absl::Status SaveGroupsToRom()
absl::Status Close()
Close the Rom file.
absl::StatusOr< uint16_t > ReadWord(int offset)
absl::Status ReadHelper(T &var, int address)
auto mutable_dungeon_palette(int i)
absl::Status WriteWord(int addr, uint16_t value)
auto mutable_link_graphics()
auto dungeon_palette(int i)
uint8_t & operator[](unsigned long i)
absl::Status LoadFromFile(const std::string &filename, bool z3_load=true)
std::vector< std::vector< uint8_t > > main_blockset_ids
absl::StatusOr< uint8_t > ReadByte(int offset)
absl::Status LoadFromBytes(const std::vector< uint8_t > &data)
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
absl::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length)
std::vector< uint8_t > graphics_buffer_
core::ResourceLabelManager resource_label_manager_
absl::Status LoadFromPointer(uchar *data, size_t length, bool z3_load=true)
absl::Status ReadWritePreconditions()
Precondition check for reading and writing to the Rom.
absl::Status LoadZelda3()
std::array< gfx::Bitmap, kNumLinkSheets > link_graphics_
A class to hold a shared pointer to a Rom object.
static std::shared_ptr< Rom > shared_rom_
std::shared_ptr< Rom > shared_rom()
virtual ~SharedRom()=default
A class to manage experimental feature flags.
static void log(std::string message)
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
Tile composition of four 8x8 tiles.
#define RETURN_IF_ERROR(expression)
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::string UppercaseHexWord(uint16_t word)
std::string UppercaseHexLong(uint32_t dword)
std::string UppercaseHexByte(uint8_t byte, bool leading)
TileInfo WordToTileInfo(uint16_t word)
uint16_t TileInfoToWord(TileInfo tile_info)
constexpr uint32_t kTile16Ptr
constexpr uint32_t kNumRoomBlocksets
Z3_Version
Different versions of the game supported by the Rom class.
constexpr uint32_t kNormalGfxSpaceStart
constexpr uint32_t kNormalGfxSpaceEnd
constexpr uint32_t kNumSpritesets
constexpr uint32_t kNumLinkSheets
constexpr uint32_t kMaxGraphics
constexpr uint32_t kUncompressedSheetSize
constexpr uint32_t kFontSpriteLocation
constexpr uint32_t kNumGfxSheets
constexpr uint32_t kNumMainBlocksets
constexpr uint32_t kGfxGroupsPointer
constexpr uint32_t kNumPalettesets
std::variant< int, uint8_t, uint16_t, short, std::vector< uint8_t >, gfx::SnesColor, std::vector< gfx::SnesColor > > value
Constants for each version of the game.
uint32_t overlayPointersBank
uint32_t kOverworldGfxPtr1
uint32_t kOverworldGfxGroups2
uint32_t kCompressedAllMap32PointersLow
uint32_t kGfxAnimatedPointer
uint32_t kOverworldGfxGroups1
uint32_t kCompressedAllMap32PointersHigh
uint32_t kDungeonPalettesGroups
uint32_t overworldMapPaletteGroup
uint32_t overworldTilesType
uint32_t kSpriteBlocksetPointer
uint32_t kOverworldGfxPtr3
uint32_t kOverworldGfxPtr2
Represents a mapping of palette groups.
PaletteGroup dungeon_main
auto mutable_palette(int i)