Add hex utility functions and refactor usage in editors

This commit is contained in:
scawful
2025-01-22 13:28:21 -05:00
parent 62e6157864
commit 50c9223a53
17 changed files with 174 additions and 134 deletions

View File

@@ -17,6 +17,7 @@ set(
set( set(
YAZE_UTIL_SRC YAZE_UTIL_SRC
util/bps.cc util/bps.cc
util/hex.cc
) )
set(YAZE_RESOURCE_FILES set(YAZE_RESOURCE_FILES

View File

@@ -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 // 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); } uint32_t ldle3(uint8_t const *const p_arr) { return ldle(p_arr, 3); }
void HandleHexStringParams(const std::string &hex,
const HexStringParams &params) {
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 } // 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, bool StringReplace(std::string &str, const std::string &from,
const std::string &to) { const std::string &to) {

View File

@@ -18,16 +18,6 @@ namespace yaze {
*/ */
namespace core { 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, bool StringReplace(std::string &str, const std::string &from,
const std::string &to); const std::string &to);

View File

@@ -9,9 +9,10 @@
#include "app/gui/input.h" #include "app/gui/input.h"
#include "app/rom.h" #include "app/rom.h"
#include "app/zelda3/dungeon/object_names.h" #include "app/zelda3/dungeon/object_names.h"
#include "app/zelda3/dungeon/room.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "imgui_memory_editor.h" #include "imgui_memory_editor.h"
#include "zelda3/dungeon/room.h" #include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -109,7 +110,7 @@ absl::Status DungeonEditor::Initialize() {
ASSIGN_OR_RETURN(current_palette_group_, ASSIGN_OR_RETURN(current_palette_group_,
gfx::CreatePaletteGroupFromLargePalette(full_palette_)); 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 // Create a vector of pointers to the current block bitmaps
for (int block : rooms_[current_room_id_].blocks()) { for (int block : rooms_[current_room_id_].blocks()) {
room_gfx_sheets_.emplace_back(&graphics_bin_[block]); room_gfx_sheets_.emplace_back(&graphics_bin_[block]);
@@ -327,7 +328,7 @@ void DungeonEditor::DrawRoomSelector() {
int i = 0; int i = 0;
for (const auto each_room_name : zelda3::kRoomNames) { for (const auto each_room_name : zelda3::kRoomNames) {
rom()->resource_label()->SelectableLabelWithNameEdit( 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()); each_room_name.data());
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
// TODO: Jump to tab if room is already open // TODO: Jump to tab if room is already open
@@ -402,7 +403,7 @@ void DungeonEditor::DrawEntranceSelector() {
for (int i = 0; i < 0x85 + 7; i++) { for (int i = 0; i < 0x85 + 7; i++) {
rom()->resource_label()->SelectableLabelWithNameEdit( rom()->resource_label()->SelectableLabelWithNameEdit(
current_entrance_id_ == i, "Dungeon Entrance Names", current_entrance_id_ == i, "Dungeon Entrance Names",
core::HexByte(i), zelda3::kEntranceNames[i].data()); util::HexByte(i), zelda3::kEntranceNames[i].data());
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
current_entrance_id_ = i; current_entrance_id_ = i;

View File

@@ -21,6 +21,7 @@
#include "editor/editor.h" #include "editor/editor.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "imgui/misc/cpp/imgui_stdlib.h" #include "imgui/misc/cpp/imgui_stdlib.h"
#include "util/hex.h"
#include "util/macro.h" #include "util/macro.h"
namespace yaze { namespace yaze {
@@ -345,7 +346,7 @@ void EditorManager::DrawPopups() {
if (BeginPopupModal("ROM Information", nullptr, if (BeginPopupModal("ROM Information", nullptr,
ImGuiWindowFlags_AlwaysAutoResize)) { ImGuiWindowFlags_AlwaysAutoResize)) {
Text("Title: %s", rom()->title().c_str()); 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) || if (Button("Close", gui::kDefaultModalSize) ||
IsKeyPressed(ImGuiKey_Escape)) { IsKeyPressed(ImGuiKey_Escape)) {

View File

@@ -16,6 +16,7 @@
#include "app/gui/icons.h" #include "app/gui/icons.h"
#include "app/gui/input.h" #include "app/gui/input.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "util/hex.h"
#include "util/macro.h" #include "util/macro.h"
namespace yaze { namespace yaze {
@@ -162,7 +163,7 @@ absl::Status ScreenEditor::LoadDungeonMaps() {
gdata[j] = rom()->data()[pc_ptr_gfx++]; 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; dungeon_map_labels_[d][i][j] = label;
} }
@@ -313,7 +314,7 @@ void ScreenEditor::DrawDungeonMapsTabs() {
std::string label = std::string label =
dungeon_map_labels_[selected_dungeon][floor_number][j]; dungeon_map_labels_[selected_dungeon][floor_number][j];
screen_canvas_.DrawText(label, (posX * 2), (posY * 2)); 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); screen_canvas_.DrawText(gfx_id, (posX * 2), (posY * 2) + 16);
} }
} }

View File

@@ -13,6 +13,7 @@
#include "app/rom.h" #include "app/rom.h"
#include "app/zelda3/overworld/overworld.h" #include "app/zelda3/overworld/overworld.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -58,7 +59,7 @@ absl::Status Tile16Editor::InitBlockset(
RETURN_IF_ERROR(LoadTile8()); RETURN_IF_ERROR(LoadTile8());
ImVector<std::string> tile16_names; ImVector<std::string> tile16_names;
for (int i = 0; i < 0x200; ++i) { 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); tile16_names.push_back(str);
} }
*tile8_source_canvas_.mutable_labels(0) = tile16_names; *tile8_source_canvas_.mutable_labels(0) = tile16_names;

View File

@@ -3,6 +3,7 @@
#include <string> #include <string>
#include "app/core/common.h" #include "app/core/common.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -227,7 +228,7 @@ absl::StatusOr<MessageData> ParseSingleMessage(
current_message_raw.append("["); current_message_raw.append("[");
current_message_raw.append(DICTIONARYTOKEN); current_message_raw.append(DICTIONARYTOKEN);
current_message_raw.append(":"); current_message_raw.append(":");
current_message_raw.append(core::HexWord(dictionary)); current_message_raw.append(util::HexWord(dictionary));
current_message_raw.append("]"); current_message_raw.append("]");
auto mutable_rom_data = const_cast<uint8_t *>(rom_data.data()); auto mutable_rom_data = const_cast<uint8_t *>(rom_data.data());
@@ -265,7 +266,7 @@ std::vector<std::string> ParseMessageData(
for (auto &message : message_data) { for (auto &message : message_data) {
std::cout << "Message #" << message.ID << " at address " 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::cout << " " << message.RawString << std::endl;
std::string parsed_message = ""; std::string parsed_message = "";

View File

@@ -16,6 +16,7 @@
#include "app/rom.h" #include "app/rom.h"
#include "imgui.h" #include "imgui.h"
#include "imgui/misc/cpp/imgui_stdlib.h" #include "imgui/misc/cpp/imgui_stdlib.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -131,7 +132,7 @@ void MessageEditor::DrawMessageList() {
for (const auto &message : list_of_texts_) { for (const auto &message : list_of_texts_) {
TableNextColumn(); TableNextColumn();
if (Button(core::HexWord(message.ID).c_str())) { if (Button(util::HexWord(message.ID).c_str())) {
current_message_ = message; current_message_ = message;
DrawMessagePreview(); DrawMessagePreview();
} }
@@ -139,7 +140,7 @@ void MessageEditor::DrawMessageList() {
TextWrapped("%s", parsed_messages_[message.ID].c_str()); TextWrapped("%s", parsed_messages_[message.ID].c_str());
TableNextColumn(); TableNextColumn();
TextWrapped("%s", TextWrapped("%s",
core::HexLong(list_of_texts_[message.ID].Address).c_str()); util::HexLong(list_of_texts_[message.ID].Address).c_str());
} }
EndTable(); EndTable();
@@ -209,7 +210,7 @@ void MessageEditor::DrawDictionary() {
for (const auto &dictionary : all_dictionaries_) { for (const auto &dictionary : all_dictionaries_) {
TableNextColumn(); TableNextColumn();
Text("%s", core::HexWord(dictionary.ID).c_str()); Text("%s", util::HexWord(dictionary.ID).c_str());
TableNextColumn(); TableNextColumn();
Text("%s", dictionary.Contents.c_str()); Text("%s", dictionary.Contents.c_str());
} }
@@ -244,12 +245,12 @@ void MessageEditor::ReadAllTextDataV2() {
std::cout << "Parsed: " << current_parsed_message << std::endl; std::cout << "Parsed: " << current_parsed_message << std::endl;
std::cout << "Raw Bytes: "; std::cout << "Raw Bytes: ";
for (const auto &byte : raw_message) { for (const auto &byte : raw_message) {
std::cout << core::HexByte(byte) << " "; std::cout << util::HexByte(byte) << " ";
} }
std::cout << std::endl; std::cout << std::endl;
std::cout << "Parsed Bytes: "; std::cout << "Parsed Bytes: ";
for (const auto &byte : parsed_message) { for (const auto &byte : parsed_message) {
std::cout << core::HexByte(byte) << " "; std::cout << util::HexByte(byte) << " ";
} }
std::cout << std::endl; std::cout << std::endl;
raw_message.clear(); raw_message.clear();
@@ -295,7 +296,7 @@ void MessageEditor::ReadAllTextDataV2() {
current_raw_message.append("["); current_raw_message.append("[");
current_raw_message.append(DICTIONARYTOKEN); current_raw_message.append(DICTIONARYTOKEN);
current_raw_message.append(":"); current_raw_message.append(":");
current_raw_message.append(core::HexWord(dictionary)); current_raw_message.append(util::HexWord(dictionary));
current_raw_message.append("]"); current_raw_message.append("]");
uint32_t address = core::Get24LocalFromPC( uint32_t address = core::Get24LocalFromPC(
@@ -393,7 +394,7 @@ void MessageEditor::ReadAllTextData() {
current_message_raw.append("["); current_message_raw.append("[");
current_message_raw.append(DICTIONARYTOKEN); current_message_raw.append(DICTIONARYTOKEN);
current_message_raw.append(":"); current_message_raw.append(":");
current_message_raw.append(core::HexWord(dictionary)); current_message_raw.append(util::HexWord(dictionary));
current_message_raw.append("]"); current_message_raw.append("]");
uint32_t address = core::Get24LocalFromPC( uint32_t address = core::Get24LocalFromPC(

View File

@@ -3,6 +3,7 @@
#include "app/gui/icons.h" #include "app/gui/icons.h"
#include "app/gui/input.h" #include "app/gui/input.h"
#include "app/gui/style.h" #include "app/gui/style.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -91,7 +92,7 @@ void HandleEntityDragging(zelda3::GameEntity *entity, ImVec2 canvas_p0,
ImGui::SetDragDropPayload("ENTITY_PAYLOAD", &entity, ImGui::SetDragDropPayload("ENTITY_PAYLOAD", &entity,
sizeof(zelda3::GameEntity)); sizeof(zelda3::GameEntity));
Text("Moving %s ID: %s", entity_type.c_str(), 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(); ImGui::EndDragDropSource();
} }
MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement); MoveEntityOnGrid(dragged_entity, canvas_p0, scrolling, free_movement);
@@ -126,8 +127,7 @@ bool DrawEntranceInserterPopup() {
} }
// TODO: Implement deleting OverworldEntrance objects, currently only hides them // TODO: Implement deleting OverworldEntrance objects, currently only hides them
bool DrawOverworldEntrancePopup( bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance) {
zelda3::OverworldEntrance &entrance) {
static bool set_done = false; static bool set_done = false;
if (set_done) { if (set_done) {
set_done = false; set_done = false;
@@ -317,8 +317,7 @@ void DrawItemInsertPopup() {
BeginChild("ScrollRegion", ImVec2(150, 150), true, BeginChild("ScrollRegion", ImVec2(150, 150), true,
ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGuiWindowFlags_AlwaysVerticalScrollbar);
for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) { for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) {
if (Selectable(zelda3::kSecretItemNames[i].c_str(), if (Selectable(zelda3::kSecretItemNames[i].c_str(), i == new_item_id)) {
i == new_item_id)) {
new_item_id = i; new_item_id = i;
} }
} }
@@ -351,8 +350,7 @@ bool DrawItemEditorPopup(zelda3::OverworldItem &item) {
ImGuiWindowFlags_AlwaysVerticalScrollbar); ImGuiWindowFlags_AlwaysVerticalScrollbar);
ImGui::BeginGroup(); ImGui::BeginGroup();
for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) { for (size_t i = 0; i < zelda3::kSecretItemNames.size(); i++) {
if (Selectable(zelda3::kSecretItemNames[i].c_str(), if (Selectable(zelda3::kSecretItemNames[i].c_str(), item.id_ == i)) {
item.id_ == i)) {
item.id_ = i; item.id_ = i;
} }
} }

View File

@@ -23,8 +23,10 @@
#include "app/zelda3/overworld/overworld.h" #include "app/zelda3/overworld/overworld.h"
#include "imgui/imgui.h" #include "imgui/imgui.h"
#include "imgui_memory_editor.h" #include "imgui_memory_editor.h"
#include "util/hex.h"
#include "util/macro.h" #include "util/macro.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -789,7 +791,7 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
color = ImVec4(255, 255, 255, 200); color = ImVec4(255, 255, 255, 200);
} }
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16, color); 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) { if (current_mode == EditingMode::ENTRANCES) {
HandleEntityDragging(&each, canvas_p0, scrolling, is_dragging_entity_, 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_); ow_map_canvas_.DrawText(str, each.x_, each.y_);
} }
i++; i++;
@@ -1367,7 +1369,7 @@ absl::Status OverworldEditor::UpdateUsageStats() {
ImGuiWindowFlags_HorizontalScrollbar)) { ImGuiWindowFlags_HorizontalScrollbar)) {
for (int i = 0; i < 0x81; i++) { for (int i = 0; i < 0x81; i++) {
auto entrance_name = rom_.resource_label()->CreateOrGetLabel( auto entrance_name = rom_.resource_label()->CreateOrGetLabel(
"Dungeon Entrance Names", core::HexByte(i), "Dungeon Entrance Names", util::HexByte(i),
zelda3::kEntranceNames[i].data()); zelda3::kEntranceNames[i].data());
std::string str = absl::StrFormat("%#x - %s", i, entrance_name); std::string str = absl::StrFormat("%#x - %s", i, entrance_name);
if (Selectable(str.c_str(), selected_entrance_ == i, if (Selectable(str.c_str(), selected_entrance_ == i,

View File

@@ -5,6 +5,7 @@
#include "app/gui/icons.h" #include "app/gui/icons.h"
#include "app/gui/input.h" #include "app/gui/input.h"
#include "app/zelda3/sprite/sprite.h" #include "app/zelda3/sprite/sprite.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace editor { namespace editor {
@@ -175,7 +176,9 @@ void SpriteEditor::DrawCurrentSheets() {
graphics_sheet_canvas_.DrawTileSelector(32); graphics_sheet_canvas_.DrawTileSelector(32);
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
graphics_sheet_canvas_.DrawBitmap( 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_.DrawGrid();
graphics_sheet_canvas_.DrawOverlay(); graphics_sheet_canvas_.DrawOverlay();
@@ -190,7 +193,7 @@ void SpriteEditor::DrawSpritesList() {
int i = 0; int i = 0;
for (const auto each_sprite_name : zelda3::kSpriteDefaultNames) { for (const auto each_sprite_name : zelda3::kSpriteDefaultNames) {
rom()->resource_label()->SelectableLabelWithNameEdit( 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()); zelda3::kSpriteDefaultNames[i].data());
if (ImGui::IsItemClicked()) { if (ImGui::IsItemClicked()) {
current_sprite_id_ = i; current_sprite_id_ = i;

View File

@@ -21,6 +21,7 @@
#include "app/gfx/snes_color.h" #include "app/gfx/snes_color.h"
#include "app/gfx/snes_palette.h" #include "app/gfx/snes_palette.h"
#include "app/gfx/snes_tile.h" #include "app/gfx/snes_tile.h"
#include "util/hex.h"
#include "util/macro.h" #include "util/macro.h"
namespace yaze { namespace yaze {
@@ -303,7 +304,7 @@ absl::Status Rom::WriteByte(int addr, uint8_t value) {
value, addr)); value, addr));
} }
rom_data_[addr] = value; 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(); 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] = (uint8_t)(value & 0xFF);
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 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(); 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] = (uint8_t)(value & 0xFF);
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 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(); 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] = (uint8_t)(value & 0xFF);
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF); rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
rom_data_[addr + 2] = (uint8_t)((value >> 16) & 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(); return absl::OkStatus();
} }
@@ -353,7 +354,7 @@ absl::Status Rom::WriteVector(int addr, std::vector<uint8_t> data) {
for (int i = 0; i < static_cast<int>(data.size()); i++) { for (int i = 0; i < static_cast<int>(data.size()); i++) {
rom_data_[addr + i] = data[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(); return absl::OkStatus();
} }
@@ -362,7 +363,7 @@ absl::Status Rom::WriteColor(uint32_t address, const gfx::SnesColor &color) {
(color.snes() & 0x7C00); (color.snes() & 0x7C00);
// Write the 16-bit color value to the ROM at the specified address // 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); return WriteShort(address, bgr);
} }

View File

@@ -9,6 +9,7 @@
#include "app/gfx/compression.h" #include "app/gfx/compression.h"
#include "app/gfx/snes_tile.h" #include "app/gfx/snes_tile.h"
#include "app/rom.h" #include "app/rom.h"
#include "util/hex.h"
#include "util/macro.h" #include "util/macro.h"
namespace yaze { namespace yaze {
@@ -572,7 +573,7 @@ absl::Status Overworld::SaveOverworldMaps() {
if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) { if ((pos + size_a) >= 0x6411F && (pos + size_a) <= 0x70000) {
core::logf("Pos set to overflow region for map %s at %s", 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; pos = kOverworldMapDataOverflow; // 0x0F8780;
} }
@@ -609,7 +610,7 @@ absl::Status Overworld::SaveOverworldMaps() {
int snes_pos = core::PcToSnes(pos); int snes_pos = core::PcToSnes(pos);
map_pointers1[i] = snes_pos; map_pointers1[i] = snes_pos;
core::logf("Saving map pointers1 and compressed data for map %s at %s", 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( RETURN_IF_ERROR(rom()->WriteLong(
rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i), rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i),
snes_pos)); snes_pos));
@@ -618,8 +619,8 @@ absl::Status Overworld::SaveOverworldMaps() {
} else { } else {
// Save pointer for map1 // Save pointer for map1
int snes_pos = map_pointers1[map_pointers1_id[i]]; int snes_pos = map_pointers1[map_pointers1_id[i]];
core::logf("Saving map pointers1 for map %s at %s", core::HexByte(i), core::logf("Saving map pointers1 for map %s at %s", util::HexByte(i),
core::HexLong(snes_pos)); util::HexLong(snes_pos));
RETURN_IF_ERROR(rom()->WriteLong( RETURN_IF_ERROR(rom()->WriteLong(
rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i), rom()->version_constants().kCompressedAllMap32PointersLow + (3 * i),
snes_pos)); snes_pos));
@@ -631,7 +632,7 @@ absl::Status Overworld::SaveOverworldMaps() {
if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) { if ((pos + b.size()) >= 0x6411F && (pos + b.size()) <= 0x70000) {
core::logf("Pos set to overflow region for map %s at %s", 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; pos = kOverworldMapDataOverflow;
} }
@@ -641,7 +642,7 @@ absl::Status Overworld::SaveOverworldMaps() {
int snes_pos = core::PcToSnes(pos); int snes_pos = core::PcToSnes(pos);
map_pointers2[i] = snes_pos; map_pointers2[i] = snes_pos;
core::logf("Saving map pointers2 and compressed data for map %s at %s", 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( RETURN_IF_ERROR(rom()->WriteLong(
rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i), rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i),
snes_pos)); snes_pos));
@@ -650,8 +651,8 @@ absl::Status Overworld::SaveOverworldMaps() {
} else { } else {
// Save pointer for map2 // Save pointer for map2
int snes_pos = map_pointers2[map_pointers2_id[i]]; int snes_pos = map_pointers2[map_pointers2_id[i]];
core::logf("Saving map pointers2 for map %s at %s", core::HexByte(i), core::logf("Saving map pointers2 for map %s at %s", util::HexByte(i),
core::HexLong(snes_pos)); util::HexLong(snes_pos));
RETURN_IF_ERROR(rom()->WriteLong( RETURN_IF_ERROR(rom()->WriteLong(
rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i), rom()->version_constants().kCompressedAllMap32PointersHigh + (3 * i),
snes_pos)); snes_pos));
@@ -660,7 +661,7 @@ absl::Status Overworld::SaveOverworldMaps() {
// Check if too many maps data // Check if too many maps data
if (pos > kOverworldCompressedOverflowPos) { 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)); return absl::AbortedError("Too many maps data " + std::to_string(pos));
} }

View File

@@ -8,6 +8,7 @@
#include "app/gfx/snes_tile.h" #include "app/gfx/snes_tile.h"
#include "app/rom.h" #include "app/rom.h"
#include "app/zelda3/overworld/overworld.h" #include "app/zelda3/overworld/overworld.h"
#include "util/hex.h"
namespace yaze { namespace yaze {
namespace zelda3 { 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()) { if (message_id.ok()) {
message_id_ = message_id.value(); message_id_ = message_id.value();
} else { } else {
message_id_ = 0; message_id_ = 0;
core::logf("Error reading message id for map %d", parent_); core::logf("Error reading message id for map %d", parent_);
} }
if (index_ < kDarkWorldMapIdStart) { if (index_ < kDarkWorldMapIdStart) {
@@ -405,11 +406,11 @@ void OverworldMap::LoadMainBlocksets() {
// of the 5A sheet, so this will need some special manipulation to make work // 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). // during the BuildBitmap step (or a new one specifically for animating).
void OverworldMap::DrawAnimatedTiles() { 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::endl;
std::cout << "static_graphics_[7] = " << core::HexByte(static_graphics_[7]) std::cout << "static_graphics_[7] = " << util::HexByte(static_graphics_[7])
<< std::endl; << std::endl;
std::cout << "static_graphics_[8] = " << core::HexByte(static_graphics_[8]) std::cout << "static_graphics_[8] = " << util::HexByte(static_graphics_[8])
<< std::endl; << std::endl;
if (static_graphics_[7] == 0x5B) { if (static_graphics_[7] == 0x5B) {
static_graphics_[7] = 0x5A; static_graphics_[7] = 0x5A;
@@ -424,7 +425,7 @@ void OverworldMap::DrawAnimatedTiles() {
void OverworldMap::LoadAreaGraphicsBlocksets() { void OverworldMap::LoadAreaGraphicsBlocksets() {
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
uint8_t value = rom_[rom_.version_constants().kOverworldGfxGroups1 + uint8_t value = rom_[rom_.version_constants().kOverworldGfxGroups1 +
(area_graphics_ * 4) + i]; (area_graphics_ * 4) + i];
if (value != 0) { if (value != 0) {
static_graphics_[3 + i] = value; static_graphics_[3 + i] = value;
} }
@@ -597,15 +598,15 @@ absl::Status OverworldMap::LoadPalette() {
uint8_t pal0 = 0; uint8_t pal0 = 0;
uint8_t pal1 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + uint8_t pal1 = rom_[rom_.version_constants().kOverworldMapPaletteGroup +
(area_palette_ * 4)]; (area_palette_ * 4)];
uint8_t pal2 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + uint8_t pal2 = rom_[rom_.version_constants().kOverworldMapPaletteGroup +
(area_palette_ * 4) + 1]; (area_palette_ * 4) + 1];
uint8_t pal3 = rom_[rom_.version_constants().kOverworldMapPaletteGroup + uint8_t pal3 = rom_[rom_.version_constants().kOverworldMapPaletteGroup +
(area_palette_ * 4) + 2]; (area_palette_ * 4) + 2];
uint8_t pal4 = uint8_t pal4 =
rom_[kOverworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2)]; rom_[kOverworldSpritePaletteGroup + (sprite_palette_[game_state_] * 2)];
uint8_t pal5 = rom_[kOverworldSpritePaletteGroup + 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; auto grass_pal_group = rom_.palette_group().grass;
ASSIGN_OR_RETURN(gfx::SnesColor bgr, grass_pal_group[0].GetColor(0)); ASSIGN_OR_RETURN(gfx::SnesColor bgr, grass_pal_group[0].GetColor(0));

86
src/util/hex.cc Normal file
View File

@@ -0,0 +1,86 @@
#include "hex.h"
#include <string>
#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 &params) {
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

20
src/util/hex.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef YAZE_UTIL_HEX_H
#define YAZE_UTIL_HEX_H
#include <cstdint>
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