From 50c9223a53377710225aeefec9beea96b5bf1438 Mon Sep 17 00:00:00 2001 From: scawful Date: Wed, 22 Jan 2025 13:28:21 -0500 Subject: [PATCH] Add hex utility functions and refactor usage in editors --- src/CMakeLists.txt | 1 + src/app/core/common.cc | 69 ---------------- src/app/core/common.h | 10 --- src/app/editor/dungeon/dungeon_editor.cc | 9 +- src/app/editor/editor_manager.cc | 3 +- src/app/editor/graphics/screen_editor.cc | 5 +- src/app/editor/graphics/tile16_editor.cc | 3 +- src/app/editor/message/message_data.cc | 5 +- src/app/editor/message/message_editor.cc | 15 ++-- src/app/editor/overworld/entity.cc | 12 ++- src/app/editor/overworld/overworld_editor.cc | 8 +- src/app/editor/sprite/sprite_editor.cc | 7 +- src/app/rom.cc | 13 +-- src/app/zelda3/overworld/overworld.cc | 19 +++-- src/app/zelda3/overworld/overworld_map.cc | 23 +++--- src/util/hex.cc | 86 ++++++++++++++++++++ src/util/hex.h | 20 +++++ 17 files changed, 174 insertions(+), 134 deletions(-) create mode 100644 src/util/hex.cc create mode 100644 src/util/hex.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 05141abc..fbbfcfcb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,7 @@ set( set( YAZE_UTIL_SRC util/bps.cc + util/hex.cc ) set(YAZE_RESOURCE_FILES diff --git a/src/app/core/common.cc b/src/app/core/common.cc index cce19536..a2001dda 100644 --- a/src/app/core/common.cc +++ b/src/app/core/common.cc @@ -54,77 +54,8 @@ uint32_t ldle2(uint8_t const *const p_arr) { return ldle(p_arr, 2); } // Helper function to get the third byte in a little endian number uint32_t ldle3(uint8_t const *const p_arr) { return ldle(p_arr, 3); } -void HandleHexStringParams(const std::string &hex, - const HexStringParams ¶ms) { - std::string result = hex; - switch (params.prefix) { - case HexStringParams::Prefix::kDollar: - result = absl::StrCat("$", result); - break; - case HexStringParams::Prefix::kHash: - result = absl::StrCat("#", result); - break; - case HexStringParams::Prefix::k0x: - result = absl::StrCat("0x", result); - case HexStringParams::Prefix::kNone: - default: - break; - } -} - } // namespace -std::string HexByte(uint8_t byte, HexStringParams params) { - std::string result; - const static std::string kLowerFormat = "%02x"; - const static std::string kUpperFormat = "%02X"; - if (params.uppercase) { - result = absl::StrFormat(kUpperFormat.c_str(), byte); - } else { - result = absl::StrFormat(kLowerFormat.c_str(), byte); - } - HandleHexStringParams(result, params); - return result; -} - -std::string HexWord(uint16_t word, HexStringParams params) { - std::string result; - const static std::string kLowerFormat = "%04x"; - const static std::string kUpperFormat = "%04X"; - if (params.uppercase) { - result = absl::StrFormat(kUpperFormat.c_str(), word); - } else { - result = absl::StrFormat(kLowerFormat.c_str(), word); - } - HandleHexStringParams(result, params); - return result; -} - -std::string HexLong(uint32_t dword, HexStringParams params) { - std::string result; - const static std::string kLowerFormat = "%06x"; - const static std::string kUpperFormat = "%06X"; - if (params.uppercase) { - result = absl::StrFormat(kUpperFormat.c_str(), dword); - } else { - result = absl::StrFormat(kLowerFormat.c_str(), dword); - } - HandleHexStringParams(result, params); - return result; -} - -std::string HexLongLong(uint64_t qword, HexStringParams params) { - std::string result; - const static std::string kLowerFormat = "%08x"; - const static std::string kUpperFormat = "%08X"; - if (params.uppercase) { - result = absl::StrFormat(kUpperFormat.c_str(), qword); - } else { - result = absl::StrFormat(kLowerFormat.c_str(), qword); - } - HandleHexStringParams(result, params); - return result; -} bool StringReplace(std::string &str, const std::string &from, const std::string &to) { diff --git a/src/app/core/common.h b/src/app/core/common.h index 9e8f4a0f..ed1c3d7b 100644 --- a/src/app/core/common.h +++ b/src/app/core/common.h @@ -18,16 +18,6 @@ namespace yaze { */ namespace core { -struct HexStringParams { - enum class Prefix { kNone, kDollar, kHash, k0x } prefix = Prefix::kDollar; - bool uppercase = true; -}; - -std::string HexByte(uint8_t byte, HexStringParams params = {}); -std::string HexWord(uint16_t word, HexStringParams params = {}); -std::string HexLong(uint32_t dword, HexStringParams params = {}); -std::string HexLongLong(uint64_t qword, HexStringParams params = {}); - bool StringReplace(std::string &str, const std::string &from, const std::string &to); diff --git a/src/app/editor/dungeon/dungeon_editor.cc b/src/app/editor/dungeon/dungeon_editor.cc index 3719859a..34b6ee5b 100644 --- a/src/app/editor/dungeon/dungeon_editor.cc +++ b/src/app/editor/dungeon/dungeon_editor.cc @@ -9,9 +9,10 @@ #include "app/gui/input.h" #include "app/rom.h" #include "app/zelda3/dungeon/object_names.h" +#include "app/zelda3/dungeon/room.h" #include "imgui/imgui.h" #include "imgui_memory_editor.h" -#include "zelda3/dungeon/room.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -109,7 +110,7 @@ absl::Status DungeonEditor::Initialize() { ASSIGN_OR_RETURN(current_palette_group_, gfx::CreatePaletteGroupFromLargePalette(full_palette_)); - graphics_bin_ = GraphicsSheetManager::GetInstance().gfx_sheets(); + graphics_bin_ = GraphicsSheetManager::GetInstance().gfx_sheets(); // Create a vector of pointers to the current block bitmaps for (int block : rooms_[current_room_id_].blocks()) { room_gfx_sheets_.emplace_back(&graphics_bin_[block]); @@ -327,7 +328,7 @@ void DungeonEditor::DrawRoomSelector() { int i = 0; for (const auto each_room_name : zelda3::kRoomNames) { rom()->resource_label()->SelectableLabelWithNameEdit( - current_room_id_ == i, "Dungeon Room Names", core::HexByte(i), + current_room_id_ == i, "Dungeon Room Names", util::HexByte(i), each_room_name.data()); if (ImGui::IsItemClicked()) { // TODO: Jump to tab if room is already open @@ -402,7 +403,7 @@ void DungeonEditor::DrawEntranceSelector() { for (int i = 0; i < 0x85 + 7; i++) { rom()->resource_label()->SelectableLabelWithNameEdit( current_entrance_id_ == i, "Dungeon Entrance Names", - core::HexByte(i), zelda3::kEntranceNames[i].data()); + util::HexByte(i), zelda3::kEntranceNames[i].data()); if (ImGui::IsItemClicked()) { current_entrance_id_ = i; diff --git a/src/app/editor/editor_manager.cc b/src/app/editor/editor_manager.cc index 249132ab..1796b095 100644 --- a/src/app/editor/editor_manager.cc +++ b/src/app/editor/editor_manager.cc @@ -21,6 +21,7 @@ #include "editor/editor.h" #include "imgui/imgui.h" #include "imgui/misc/cpp/imgui_stdlib.h" +#include "util/hex.h" #include "util/macro.h" namespace yaze { @@ -345,7 +346,7 @@ void EditorManager::DrawPopups() { if (BeginPopupModal("ROM Information", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { Text("Title: %s", rom()->title().c_str()); - Text("ROM Size: %s", core::HexLongLong(rom()->size()).c_str()); + Text("ROM Size: %s", util::HexLongLong(rom()->size()).c_str()); if (Button("Close", gui::kDefaultModalSize) || IsKeyPressed(ImGuiKey_Escape)) { diff --git a/src/app/editor/graphics/screen_editor.cc b/src/app/editor/graphics/screen_editor.cc index 2811a3ae..ad738fea 100644 --- a/src/app/editor/graphics/screen_editor.cc +++ b/src/app/editor/graphics/screen_editor.cc @@ -16,6 +16,7 @@ #include "app/gui/icons.h" #include "app/gui/input.h" #include "imgui/imgui.h" +#include "util/hex.h" #include "util/macro.h" namespace yaze { @@ -162,7 +163,7 @@ absl::Status ScreenEditor::LoadDungeonMaps() { gdata[j] = rom()->data()[pc_ptr_gfx++]; } - std::string label = core::HexByte(rdata[j]); + std::string label = util::HexByte(rdata[j]); dungeon_map_labels_[d][i][j] = label; } @@ -313,7 +314,7 @@ void ScreenEditor::DrawDungeonMapsTabs() { std::string label = dungeon_map_labels_[selected_dungeon][floor_number][j]; screen_canvas_.DrawText(label, (posX * 2), (posY * 2)); - std::string gfx_id = core::HexByte(tile16_id); + std::string gfx_id = util::HexByte(tile16_id); screen_canvas_.DrawText(gfx_id, (posX * 2), (posY * 2) + 16); } } diff --git a/src/app/editor/graphics/tile16_editor.cc b/src/app/editor/graphics/tile16_editor.cc index 6efc6fc6..76cb90e1 100644 --- a/src/app/editor/graphics/tile16_editor.cc +++ b/src/app/editor/graphics/tile16_editor.cc @@ -13,6 +13,7 @@ #include "app/rom.h" #include "app/zelda3/overworld/overworld.h" #include "imgui/imgui.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -58,7 +59,7 @@ absl::Status Tile16Editor::InitBlockset( RETURN_IF_ERROR(LoadTile8()); ImVector tile16_names; for (int i = 0; i < 0x200; ++i) { - std::string str = core::HexByte(all_tiles_types_[i]); + std::string str = util::HexByte(all_tiles_types_[i]); tile16_names.push_back(str); } *tile8_source_canvas_.mutable_labels(0) = tile16_names; diff --git a/src/app/editor/message/message_data.cc b/src/app/editor/message/message_data.cc index 89c72732..82f81415 100644 --- a/src/app/editor/message/message_data.cc +++ b/src/app/editor/message/message_data.cc @@ -3,6 +3,7 @@ #include #include "app/core/common.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -227,7 +228,7 @@ absl::StatusOr ParseSingleMessage( current_message_raw.append("["); current_message_raw.append(DICTIONARYTOKEN); current_message_raw.append(":"); - current_message_raw.append(core::HexWord(dictionary)); + current_message_raw.append(util::HexWord(dictionary)); current_message_raw.append("]"); auto mutable_rom_data = const_cast(rom_data.data()); @@ -265,7 +266,7 @@ std::vector ParseMessageData( for (auto &message : message_data) { std::cout << "Message #" << message.ID << " at address " - << core::HexLong(message.Address) << std::endl; + << util::HexLong(message.Address) << std::endl; std::cout << " " << message.RawString << std::endl; std::string parsed_message = ""; diff --git a/src/app/editor/message/message_editor.cc b/src/app/editor/message/message_editor.cc index e4ab5fa1..d38a266d 100644 --- a/src/app/editor/message/message_editor.cc +++ b/src/app/editor/message/message_editor.cc @@ -16,6 +16,7 @@ #include "app/rom.h" #include "imgui.h" #include "imgui/misc/cpp/imgui_stdlib.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -131,7 +132,7 @@ void MessageEditor::DrawMessageList() { for (const auto &message : list_of_texts_) { TableNextColumn(); - if (Button(core::HexWord(message.ID).c_str())) { + if (Button(util::HexWord(message.ID).c_str())) { current_message_ = message; DrawMessagePreview(); } @@ -139,7 +140,7 @@ void MessageEditor::DrawMessageList() { TextWrapped("%s", parsed_messages_[message.ID].c_str()); TableNextColumn(); TextWrapped("%s", - core::HexLong(list_of_texts_[message.ID].Address).c_str()); + util::HexLong(list_of_texts_[message.ID].Address).c_str()); } EndTable(); @@ -209,7 +210,7 @@ void MessageEditor::DrawDictionary() { for (const auto &dictionary : all_dictionaries_) { TableNextColumn(); - Text("%s", core::HexWord(dictionary.ID).c_str()); + Text("%s", util::HexWord(dictionary.ID).c_str()); TableNextColumn(); Text("%s", dictionary.Contents.c_str()); } @@ -244,12 +245,12 @@ void MessageEditor::ReadAllTextDataV2() { std::cout << "Parsed: " << current_parsed_message << std::endl; std::cout << "Raw Bytes: "; for (const auto &byte : raw_message) { - std::cout << core::HexByte(byte) << " "; + std::cout << util::HexByte(byte) << " "; } std::cout << std::endl; std::cout << "Parsed Bytes: "; for (const auto &byte : parsed_message) { - std::cout << core::HexByte(byte) << " "; + std::cout << util::HexByte(byte) << " "; } std::cout << std::endl; raw_message.clear(); @@ -295,7 +296,7 @@ void MessageEditor::ReadAllTextDataV2() { current_raw_message.append("["); current_raw_message.append(DICTIONARYTOKEN); current_raw_message.append(":"); - current_raw_message.append(core::HexWord(dictionary)); + current_raw_message.append(util::HexWord(dictionary)); current_raw_message.append("]"); uint32_t address = core::Get24LocalFromPC( @@ -393,7 +394,7 @@ void MessageEditor::ReadAllTextData() { current_message_raw.append("["); current_message_raw.append(DICTIONARYTOKEN); current_message_raw.append(":"); - current_message_raw.append(core::HexWord(dictionary)); + current_message_raw.append(util::HexWord(dictionary)); current_message_raw.append("]"); uint32_t address = core::Get24LocalFromPC( diff --git a/src/app/editor/overworld/entity.cc b/src/app/editor/overworld/entity.cc index 4f0cd998..843be091 100644 --- a/src/app/editor/overworld/entity.cc +++ b/src/app/editor/overworld/entity.cc @@ -3,6 +3,7 @@ #include "app/gui/icons.h" #include "app/gui/input.h" #include "app/gui/style.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -91,7 +92,7 @@ void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0, ImGui::SetDragDropPayload("ENTITY_PAYLOAD", &entity, sizeof(zelda3::GameEntity)); Text("Moving %s ID: %s", entity_type.c_str(), - core::HexByte(entity->entity_id_).c_str()); + util::HexByte(entity->entity_id_).c_str()); ImGui::EndDragDropSource(); } MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement); @@ -126,8 +127,7 @@ bool DrawEntranceInserterPopup() { } // TODO: Implement deleting OverworldEntrance objects, currently only hides them -bool DrawOverworldEntrancePopup( - zelda3::OverworldEntrance &entrance) { +bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance) { static bool set_done = false; if (set_done) { set_done = false; @@ -317,8 +317,7 @@ void DrawItemInsertPopup() { BeginChild("ScrollRegion", ImVec2(150, 150), true, ImGuiWindowFlags_AlwaysVerticalScrollbar); for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) { - if (Selectable(zelda3::kSecretItemNames[i].c_str(), - i == new_item_id)) { + if (Selectable(zelda3::kSecretItemNames[i].c_str(), i == new_item_id)) { new_item_id = i; } } @@ -351,8 +350,7 @@ bool DrawItemEditorPopup(zelda3::OverworldItem &item) { ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGui::BeginGroup(); for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) { - if (Selectable(zelda3::kSecretItemNames[i].c_str(), - item.id_ == i)) { + if (Selectable(zelda3::kSecretItemNames[i].c_str(), item.id_ == i)) { item.id_ = i; } } diff --git a/src/app/editor/overworld/overworld_editor.cc b/src/app/editor/overworld/overworld_editor.cc index 841d3a0f..f6db8968 100644 --- a/src/app/editor/overworld/overworld_editor.cc +++ b/src/app/editor/overworld/overworld_editor.cc @@ -23,8 +23,10 @@ #include "app/zelda3/overworld/overworld.h" #include "imgui/imgui.h" #include "imgui_memory_editor.h" +#include "util/hex.h" #include "util/macro.h" + namespace yaze { namespace editor { @@ -789,7 +791,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling, color = ImVec4(255, 255, 255, 200); } ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color); - std::string str = core::HexByte(each.entrance_id_); + std::string str = util::HexByte(each.entrance_id_); if (current_mode == EditingMode::ENTRANCES) { HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_, @@ -872,7 +874,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) { } } - std::string str = core::HexByte(i); + std::string str = util::HexByte(i); ow_map_canvas_.DrawText(str, each.x_, each.y_); } i++; @@ -1367,7 +1369,7 @@ absl::Status OverworldEditor::UpdateUsageStats() { ImGuiWindowFlags_HorizontalScrollbar)) { for (int i = 0; i < 0x81; i++) { auto entrance_name = rom_.resource_label()->CreateOrGetLabel( - "Dungeon Entrance Names", core::HexByte(i), + "Dungeon Entrance Names", util::HexByte(i), zelda3::kEntranceNames[i].data()); std::string str = absl::StrFormat("%#x - %s", i, entrance_name); if (Selectable(str.c_str(), selected_entrance_ == i, diff --git a/src/app/editor/sprite/sprite_editor.cc b/src/app/editor/sprite/sprite_editor.cc index b42ea0e1..364c3cdb 100644 --- a/src/app/editor/sprite/sprite_editor.cc +++ b/src/app/editor/sprite/sprite_editor.cc @@ -5,6 +5,7 @@ #include "app/gui/icons.h" #include "app/gui/input.h" #include "app/zelda3/sprite/sprite.h" +#include "util/hex.h" namespace yaze { namespace editor { @@ -175,7 +176,9 @@ void SpriteEditor::DrawCurrentSheets() { graphics_sheet_canvas_.DrawTileSelector(32); for (int i = 0; i < 8; i++) { graphics_sheet_canvas_.DrawBitmap( - GraphicsSheetManager::GetInstance().gfx_sheets().at(current_sheets_[i]), 1, (i * 0x40) + 1, 2); + GraphicsSheetManager::GetInstance().gfx_sheets().at( + current_sheets_[i]), + 1, (i * 0x40) + 1, 2); } graphics_sheet_canvas_.DrawGrid(); graphics_sheet_canvas_.DrawOverlay(); @@ -190,7 +193,7 @@ void SpriteEditor::DrawSpritesList() { int i = 0; for (const auto each_sprite_name : zelda3::kSpriteDefaultNames) { rom()->resource_label()->SelectableLabelWithNameEdit( - current_sprite_id_ == i, "Sprite Names", core::HexByte(i), + current_sprite_id_ == i, "Sprite Names", util::HexByte(i), zelda3::kSpriteDefaultNames[i].data()); if (ImGui::IsItemClicked()) { current_sprite_id_ = i; diff --git a/src/app/rom.cc b/src/app/rom.cc index afb66f36..c4e0f26a 100644 --- a/src/app/rom.cc +++ b/src/app/rom.cc @@ -21,6 +21,7 @@ #include "app/gfx/snes_color.h" #include "app/gfx/snes_palette.h" #include "app/gfx/snes_tile.h" +#include "util/hex.h" #include "util/macro.h" namespace yaze { @@ -303,7 +304,7 @@ absl::Status Rom::WriteByte(int addr, uint8_t value) { value, addr)); } rom_data_[addr] = value; - core::logf("WriteByte: %#06X: %s", addr, core::HexByte(value).data()); + core::logf("WriteByte: %#06X: %s", addr, util::HexByte(value).data()); return absl::OkStatus(); } @@ -315,7 +316,7 @@ absl::Status Rom::WriteWord(int addr, uint16_t value) { } rom_data_[addr] = (uint8_t)(value & 0xFF); rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF); - core::logf("WriteWord: %#06X: %s", addr, core::HexWord(value).data()); + core::logf("WriteWord: %#06X: %s", addr, util::HexWord(value).data()); return absl::OkStatus(); } @@ -327,7 +328,7 @@ absl::Status Rom::WriteShort(int addr, uint16_t value) { } rom_data_[addr] = (uint8_t)(value & 0xFF); rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF); - core::logf("WriteShort: %#06X: %s", addr, core::HexWord(value).data()); + core::logf("WriteShort: %#06X: %s", addr, util::HexWord(value).data()); return absl::OkStatus(); } @@ -340,7 +341,7 @@ absl::Status Rom::WriteLong(uint32_t addr, uint32_t value) { rom_data_[addr] = (uint8_t)(value & 0xFF); rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF); rom_data_[addr + 2] = (uint8_t)((value >> 16) & 0xFF); - core::logf("WriteLong: %#06X: %s", addr, core::HexLong(value).data()); + core::logf("WriteLong: %#06X: %s", addr, util::HexLong(value).data()); return absl::OkStatus(); } @@ -353,7 +354,7 @@ absl::Status Rom::WriteVector(int addr, std::vector data) { for (int i = 0; i < static_cast(data.size()); i++) { rom_data_[addr + i] = data[i]; } - core::logf("WriteVector: %#06X: %s", addr, core::HexByte(data[0]).data()); + core::logf("WriteVector: %#06X: %s", addr, util::HexByte(data[0]).data()); return absl::OkStatus(); } @@ -362,7 +363,7 @@ absl::Status Rom::WriteColor(uint32_t address, const gfx::SnesColor &color) { (color.snes() & 0x7C00); // Write the 16-bit color value to the ROM at the specified address - core::logf("WriteColor: %#06X: %s", address, core::HexWord(bgr).data()); + core::logf("WriteColor: %#06X: %s", address, util::HexWord(bgr).data()); return WriteShort(address, bgr); } diff --git a/src/app/zelda3/overworld/overworld.cc b/src/app/zelda3/overworld/overworld.cc index 4a7c6502..41c6647b 100644 --- a/src/app/zelda3/overworld/overworld.cc +++ b/src/app/zelda3/overworld/overworld.cc @@ -9,6 +9,7 @@ #include "app/gfx/compression.h" #include "app/gfx/snes_tile.h" #include "app/rom.h" +#include "util/hex.h" #include "util/macro.h" namespace yaze { @@ -572,7 +573,7 @@ absl::Status Overworld::SaveOverworldMaps() { if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) { core::logf("Pos set to overflow region for map %s at %s", - std::to_string(i), core::HexLong(pos)); + std::to_string(i), util::HexLong(pos)); pos = kOverworldMapDataOverflow; // 0x0F8780; } @@ -609,7 +610,7 @@ absl::Status Overworld::SaveOverworldMaps() { int snes_pos = core::PcToSnes(pos); map_pointers1[i] = snes_pos; core::logf("Saving map pointers1 and compressed data for map %s at %s", - core::HexByte(i), core::HexLong(snes_pos)); + util::HexByte(i), util::HexLong(snes_pos)); RETURN_IF_ERROR(rom()->WriteLong( rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i), snes_pos)); @@ -618,8 +619,8 @@ absl::Status Overworld::SaveOverworldMaps() { } else { // Save pointer for map1 int snes_pos = map_pointers1[map_pointers1_id[i]]; - core::logf("Saving map pointers1 for map %s at %s", core::HexByte(i), - core::HexLong(snes_pos)); + core::logf("Saving map pointers1 for map %s at %s", util::HexByte(i), + util::HexLong(snes_pos)); RETURN_IF_ERROR(rom()->WriteLong( rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i), snes_pos)); @@ -631,7 +632,7 @@ absl::Status Overworld::SaveOverworldMaps() { if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) { core::logf("Pos set to overflow region for map %s at %s", - core::HexByte(i), core::HexLong(pos)); + util::HexByte(i), util::HexLong(pos)); pos = kOverworldMapDataOverflow; } @@ -641,7 +642,7 @@ absl::Status Overworld::SaveOverworldMaps() { int snes_pos = core::PcToSnes(pos); map_pointers2[i] = snes_pos; core::logf("Saving map pointers2 and compressed data for map %s at %s", - core::HexByte(i), core::HexLong(snes_pos)); + util::HexByte(i), util::HexLong(snes_pos)); RETURN_IF_ERROR(rom()->WriteLong( rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i), snes_pos)); @@ -650,8 +651,8 @@ absl::Status Overworld::SaveOverworldMaps() { } else { // Save pointer for map2 int snes_pos = map_pointers2[map_pointers2_id[i]]; - core::logf("Saving map pointers2 for map %s at %s", core::HexByte(i), - core::HexLong(snes_pos)); + core::logf("Saving map pointers2 for map %s at %s", util::HexByte(i), + util::HexLong(snes_pos)); RETURN_IF_ERROR(rom()->WriteLong( rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i), snes_pos)); @@ -660,7 +661,7 @@ absl::Status Overworld::SaveOverworldMaps() { // Check if too many maps data if (pos > kOverworldCompressedOverflowPos) { - core::logf("Too many maps data %s", core::HexLong(pos)); + core::logf("Too many maps data %s", util::HexLong(pos)); return absl::AbortedError("Too many maps data " + std::to_string(pos)); } diff --git a/src/app/zelda3/overworld/overworld_map.cc b/src/app/zelda3/overworld/overworld_map.cc index be203123..0e3453fb 100644 --- a/src/app/zelda3/overworld/overworld_map.cc +++ b/src/app/zelda3/overworld/overworld_map.cc @@ -8,6 +8,7 @@ #include "app/gfx/snes_tile.h" #include "app/rom.h" #include "app/zelda3/overworld/overworld.h" +#include "util/hex.h" namespace yaze { namespace zelda3 { @@ -71,12 +72,12 @@ void OverworldMap::LoadAreaInfo() { } } - auto message_id = rom_.ReadWord(kOverworldMessageIds + (parent_ * 2)); + auto message_id = rom_.ReadWord(kOverworldMessageIds + (parent_ * 2)); if (message_id.ok()) { message_id_ = message_id.value(); } else { - message_id_ = 0; - core::logf("Error reading message id for map %d", parent_); + message_id_ = 0; + core::logf("Error reading message id for map %d", parent_); } if (index_ < kDarkWorldMapIdStart) { @@ -405,11 +406,11 @@ void OverworldMap::LoadMainBlocksets() { // of the 5A sheet, so this will need some special manipulation to make work // during the BuildBitmap step (or a new one specifically for animating). void OverworldMap::DrawAnimatedTiles() { - std::cout << "static_graphics_[6] = " << core::HexByte(static_graphics_[6]) + std::cout << "static_graphics_[6] = " << util::HexByte(static_graphics_[6]) << std::endl; - std::cout << "static_graphics_[7] = " << core::HexByte(static_graphics_[7]) + std::cout << "static_graphics_[7] = " << util::HexByte(static_graphics_[7]) << std::endl; - std::cout << "static_graphics_[8] = " << core::HexByte(static_graphics_[8]) + std::cout << "static_graphics_[8] = " << util::HexByte(static_graphics_[8]) << std::endl; if (static_graphics_[7] == 0x5B) { static_graphics_[7] = 0x5A; @@ -424,7 +425,7 @@ void OverworldMap::DrawAnimatedTiles() { void OverworldMap::LoadAreaGraphicsBlocksets() { for (int i = 0; i < 4; i++) { uint8_t value = rom_[rom_.version_constants().kOverworldGfxGroups1 + - (area_graphics_ * 4) + i]; + (area_graphics_ * 4) + i]; if (value != 0) { static_graphics_[3 + i] = value; } @@ -597,15 +598,15 @@ absl::Status OverworldMap::LoadPalette() { uint8_t pal0 = 0; uint8_t pal1 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + - (area_palette_ * 4)]; + (area_palette_ * 4)]; uint8_t pal2 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + - (area_palette_ * 4) + 1]; + (area_palette_ * 4) + 1]; uint8_t pal3 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + - (area_palette_ * 4) + 2]; + (area_palette_ * 4) + 2]; uint8_t pal4 = rom_[kOverworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2)]; uint8_t pal5 = rom_[kOverworldSpritePaletteGroup + - (sprite_palette_[game_state_] * 2) + 1]; + (sprite_palette_[game_state_] * 2) + 1]; auto grass_pal_group = rom_.palette_group().grass; ASSIGN_OR_RETURN(gfx::SnesColor bgr, grass_pal_group[0].GetColor(0)); diff --git a/src/util/hex.cc b/src/util/hex.cc new file mode 100644 index 00000000..e86361e2 --- /dev/null +++ b/src/util/hex.cc @@ -0,0 +1,86 @@ +#include "hex.h" + +#include + +#include "absl/strings/str_cat" +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" + +namespace yaze { +namespace util { + +namespace { + +void HandleHexStringParams(const std::string &hex, + const HexStringParams ¶ms) { + std::string result = hex; + switch (params.prefix) { + case HexStringParams::Prefix::kDollar: + result = absl::StrCat("$", result); + break; + case HexStringParams::Prefix::kHash: + result = absl::StrCat("#", result); + break; + case HexStringParams::Prefix::k0x: + result = absl::StrCat("0x", result); + case HexStringParams::Prefix::kNone: + default: + break; + } +} +} // namespace + +std::string HexByte(uint8_t byte, HexStringParams params) { + std::string result; + const static std::string kLowerFormat = "%02x"; + const static std::string kUpperFormat = "%02X"; + if (params.uppercase) { + result = absl::StrFormat(kUpperFormat.c_str(), byte); + } else { + result = absl::StrFormat(kLowerFormat.c_str(), byte); + } + HandleHexStringParams(result, params); + return result; +} + +std::string HexWord(uint16_t word, HexStringParams params) { + std::string result; + const static std::string kLowerFormat = "%04x"; + const static std::string kUpperFormat = "%04X"; + if (params.uppercase) { + result = absl::StrFormat(kUpperFormat.c_str(), word); + } else { + result = absl::StrFormat(kLowerFormat.c_str(), word); + } + HandleHexStringParams(result, params); + return result; +} + +std::string HexLong(uint32_t dword, HexStringParams params) { + std::string result; + const static std::string kLowerFormat = "%06x"; + const static std::string kUpperFormat = "%06X"; + if (params.uppercase) { + result = absl::StrFormat(kUpperFormat.c_str(), dword); + } else { + result = absl::StrFormat(kLowerFormat.c_str(), dword); + } + HandleHexStringParams(result, params); + return result; +} + +std::string HexLongLong(uint64_t qword, HexStringParams params) { + std::string result; + const static std::string kLowerFormat = "%08x"; + const static std::string kUpperFormat = "%08X"; + if (params.uppercase) { + result = absl::StrFormat(kUpperFormat.c_str(), qword); + } else { + result = absl::StrFormat(kLowerFormat.c_str(), qword); + } + HandleHexStringParams(result, params); + return result; +} + +} // namespace util +} // namespace yaze \ No newline at end of file diff --git a/src/util/hex.h b/src/util/hex.h new file mode 100644 index 00000000..ff86ca68 --- /dev/null +++ b/src/util/hex.h @@ -0,0 +1,20 @@ +#ifndef YAZE_UTIL_HEX_H +#define YAZE_UTIL_HEX_H + +#include + +namespace yaze { +namespace util { + +struct HexStringParams { + enum class Prefix { kNone, kDollar, kHash, k0x } prefix = Prefix::kDollar; + bool uppercase = true; +}; + +std::string HexByte(uint8_t byte, HexStringParams params = {}); +std::string HexWord(uint16_t word, HexStringParams params = {}); +std::string HexLong(uint32_t dword, HexStringParams params = {}); +std::string HexLongLong(uint64_t qword, HexStringParams params = {}); + +} // namespace util +} // namespace yaze \ No newline at end of file