@@ -42,6 +42,10 @@ set(
|
|||||||
find_package(PNG REQUIRED)
|
find_package(PNG REQUIRED)
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
find_package(GLEW REQUIRED)
|
find_package(GLEW REQUIRED)
|
||||||
|
find_package(gRPC REQUIRED)
|
||||||
|
set(PROTOBUF_INCLUDE_PATH ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
CACHE INTERNAL "Path to generated protobuf files.")
|
||||||
|
include_directories(${PROTOBUF_INCLUDE_PATH})
|
||||||
|
|
||||||
# Project Files
|
# Project Files
|
||||||
add_subdirectory(src/lib/abseil-cpp)
|
add_subdirectory(src/lib/abseil-cpp)
|
||||||
|
|||||||
@@ -36,12 +36,35 @@ set(
|
|||||||
|
|
||||||
# Asar Assembly ---------------------------------------------------------------
|
# Asar Assembly ---------------------------------------------------------------
|
||||||
add_subdirectory(lib/asar/src)
|
add_subdirectory(lib/asar/src)
|
||||||
set(ASAR_GEN_EXE OFF)
|
get_target_property(ASAR_INCLUDE_DIR asar-static INCLUDE_DIRECTORIES)
|
||||||
set(ASAR_GEN_DLL ON)
|
target_include_directories(asar-static PRIVATE ${ASAR_INCLUDE_DIR})
|
||||||
set(ASAR_GEN_LIB OFF)
|
set(ASAR_GEN_EXE OFF)
|
||||||
|
set(ASAR_GEN_DLL ON)
|
||||||
|
set(ASAR_GEN_LIB ON)
|
||||||
set(ASAR_GEN_EXE_TEST OFF)
|
set(ASAR_GEN_EXE_TEST OFF)
|
||||||
set(ASAR_GEN_DLL_TEST OFF)
|
set(ASAR_GEN_DLL_TEST OFF)
|
||||||
|
|
||||||
|
set(ASAR_STATIC_SRC
|
||||||
|
"lib/asar/src/asar/interface-lib.cpp"
|
||||||
|
"lib/asar/src/asar/addr2line.cpp"
|
||||||
|
"lib/asar/src/asar/arch-65816.cpp"
|
||||||
|
"lib/asar/src/asar/arch-spc700.cpp"
|
||||||
|
"lib/asar/src/asar/arch-superfx.cpp"
|
||||||
|
"lib/asar/src/asar/assembleblock.cpp"
|
||||||
|
"lib/asar/src/asar/crc32.cpp"
|
||||||
|
"lib/asar/src/asar/libcon.cpp"
|
||||||
|
"lib/asar/src/asar/libsmw.cpp"
|
||||||
|
"lib/asar/src/asar/libstr.cpp"
|
||||||
|
"lib/asar/src/asar/macro.cpp"
|
||||||
|
"lib/asar/src/asar/main.cpp"
|
||||||
|
"lib/asar/src/asar/asar_math.cpp"
|
||||||
|
"lib/asar/src/asar/virtualfile.cpp"
|
||||||
|
"lib/asar/src/asar/warnings.cpp"
|
||||||
|
"lib/asar/src/asar/errors.cpp"
|
||||||
|
"lib/asar/src/asar/platform/file-helpers.cpp"
|
||||||
|
"lib/asar/src/asar/platform/linux/file-helpers-linux.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
# yaze source files -----------------------------------------------------------
|
# yaze source files -----------------------------------------------------------
|
||||||
set(
|
set(
|
||||||
YAZE_APP_CORE_SRC
|
YAZE_APP_CORE_SRC
|
||||||
@@ -62,16 +85,17 @@ set(
|
|||||||
set(
|
set(
|
||||||
YAZE_APP_GFX_SRC
|
YAZE_APP_GFX_SRC
|
||||||
app/gfx/bitmap.cc
|
app/gfx/bitmap.cc
|
||||||
app/gfx/pseudo_vram.cc
|
|
||||||
app/gfx/snes_palette.cc
|
app/gfx/snes_palette.cc
|
||||||
app/gfx/snes_tile.cc
|
app/gfx/snes_tile.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(
|
set(
|
||||||
YAZE_APP_ZELDA3_SRC
|
YAZE_APP_ZELDA3_SRC
|
||||||
|
app/zelda3/inventory.cc
|
||||||
app/zelda3/overworld_map.cc
|
app/zelda3/overworld_map.cc
|
||||||
app/zelda3/overworld.cc
|
app/zelda3/overworld.cc
|
||||||
app/zelda3/screen.cc
|
app/zelda3/title_screen.cc
|
||||||
|
app/zelda3/sprite.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(
|
set(
|
||||||
@@ -85,6 +109,7 @@ set(
|
|||||||
gui/input.cc
|
gui/input.cc
|
||||||
gui/style.cc
|
gui/style.cc
|
||||||
gui/widgets.cc
|
gui/widgets.cc
|
||||||
|
gui/color.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
@@ -98,7 +123,7 @@ add_executable(
|
|||||||
${YAZE_APP_ZELDA3_SRC}
|
${YAZE_APP_ZELDA3_SRC}
|
||||||
${YAZE_GUI_SRC}
|
${YAZE_GUI_SRC}
|
||||||
${IMGUI_SRC}
|
${IMGUI_SRC}
|
||||||
lib/asar/src/asar-dll-bindings/c/asardll.c
|
${ASAR_STATIC_SRC}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
@@ -110,7 +135,7 @@ target_include_directories(
|
|||||||
${PNG_INCLUDE_DIRS}
|
${PNG_INCLUDE_DIRS}
|
||||||
${SDL2_INCLUDE_DIR}
|
${SDL2_INCLUDE_DIR}
|
||||||
${GLEW_INCLUDE_DIRS}
|
${GLEW_INCLUDE_DIRS}
|
||||||
lib/asar/src/asar-dll-bindings/c
|
lib/asar/src/
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SDL_TARGETS SDL2::SDL2)
|
set(SDL_TARGETS SDL2::SDL2)
|
||||||
@@ -129,7 +154,10 @@ target_link_libraries(
|
|||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
ImGui
|
ImGui
|
||||||
|
asar-static
|
||||||
)
|
)
|
||||||
|
target_compile_definitions(yaze PRIVATE "linux")
|
||||||
|
target_compile_definitions(yaze PRIVATE "stricmp=strcasecmp")
|
||||||
|
|
||||||
set_target_properties(yaze
|
set_target_properties(yaze
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
@@ -139,6 +167,48 @@ set_target_properties(yaze
|
|||||||
LINK_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/yaze.res"
|
LINK_FLAGS "${CMAKE_CURRENT_SOURCE_DIR}/yaze.res"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_subdirectory(app/delta)
|
||||||
|
|
||||||
|
add_executable(
|
||||||
|
yaze_delta
|
||||||
|
app/delta/delta.cc
|
||||||
|
app/delta/viewer.cc
|
||||||
|
app/delta/client.cc
|
||||||
|
app/rom.cc
|
||||||
|
${YAZE_APP_ASM_SRC}
|
||||||
|
${YAZE_APP_CORE_SRC}
|
||||||
|
${YAZE_APP_EDITOR_SRC}
|
||||||
|
${YAZE_APP_GFX_SRC}
|
||||||
|
${YAZE_APP_ZELDA3_SRC}
|
||||||
|
${YAZE_GUI_SRC}
|
||||||
|
${IMGUI_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(
|
||||||
|
yaze_delta PUBLIC
|
||||||
|
lib/
|
||||||
|
app/
|
||||||
|
${ASAR_INCLUDE_DIR}
|
||||||
|
${CMAKE_SOURCE_DIR}/src/
|
||||||
|
${PNG_INCLUDE_DIRS}
|
||||||
|
${SDL2_INCLUDE_DIR}
|
||||||
|
${GLEW_INCLUDE_DIRS}
|
||||||
|
${ASAR_STATIC_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(
|
||||||
|
yaze_delta PUBLIC
|
||||||
|
${ABSL_TARGETS}
|
||||||
|
${SDL_TARGETS}
|
||||||
|
${PNG_LIBRARIES}
|
||||||
|
${GLEW_LIBRARIES}
|
||||||
|
${OPENGL_LIBRARIES}
|
||||||
|
${CMAKE_DL_LIBS}
|
||||||
|
delta-service
|
||||||
|
asar-static
|
||||||
|
ImGui
|
||||||
|
)
|
||||||
|
|
||||||
set (source "${CMAKE_SOURCE_DIR}/assets")
|
set (source "${CMAKE_SOURCE_DIR}/assets")
|
||||||
set (destination "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
set (destination "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
||||||
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "script.h"
|
#include "script.h"
|
||||||
|
|
||||||
#include <asardll.h>
|
#include <asar/interface-lib.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -20,49 +20,13 @@ namespace yaze {
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace snes_asm {
|
namespace snes_asm {
|
||||||
|
|
||||||
std::string GenerateBytePool(char mosaic_tiles[core::kNumOverworldMaps]) {
|
|
||||||
std::string to_return = "";
|
|
||||||
int column = 0;
|
|
||||||
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
|
|
||||||
std::string to_add = "";
|
|
||||||
|
|
||||||
// if start of line, define byte
|
|
||||||
if (i == 0 || i % 8 == 0) {
|
|
||||||
to_add += " db ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// set byte
|
|
||||||
to_add += "$00";
|
|
||||||
if (mosaic_tiles[i] > 0) {
|
|
||||||
if (i == 0 || i % 8 == 0) {
|
|
||||||
to_add = " db $01";
|
|
||||||
} else {
|
|
||||||
to_add = "$01";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// newline or comma separated
|
|
||||||
if (column == 7) {
|
|
||||||
column = 0;
|
|
||||||
to_add += " \n";
|
|
||||||
} else {
|
|
||||||
column++;
|
|
||||||
to_add += ", ";
|
|
||||||
}
|
|
||||||
|
|
||||||
to_return += to_add;
|
|
||||||
}
|
|
||||||
return to_return;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status Script::ApplyPatchToROM(ROM &rom) {
|
absl::Status Script::ApplyPatchToROM(ROM &rom) {
|
||||||
if (patch_contents_.empty() || patch_filename_.empty()) {
|
if (patch_contents_.empty() || patch_filename_.empty()) {
|
||||||
return absl::InvalidArgumentError("No patch loaded!");
|
return absl::InvalidArgumentError("No patch loaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *data = (char *)rom.data();
|
|
||||||
int size = rom.GetSize();
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
auto data = (char *)rom.data();
|
||||||
|
int size = rom.size();
|
||||||
if (!asar_patch(patch_filename_.c_str(), data, patch_size_, &size)) {
|
if (!asar_patch(patch_filename_.c_str(), data, patch_size_, &size)) {
|
||||||
auto asar_error = asar_geterrors(&count);
|
auto asar_error = asar_geterrors(&count);
|
||||||
auto full_error = asar_error->fullerrdata;
|
auto full_error = asar_error->fullerrdata;
|
||||||
@@ -71,43 +35,37 @@ absl::Status Script::ApplyPatchToROM(ROM &rom) {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::Status Script::GenerateMosaicChangeAssembly(
|
absl::Status Script::PatchOverworldMosaic(
|
||||||
ROM &rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
ROM &rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
||||||
int hook_offset) {
|
int hook_offset) {
|
||||||
|
for (int i = 0; i < core::kNumOverworldMaps; i++) {
|
||||||
|
if (mosaic_tiles[i]) {
|
||||||
|
rom[core::overworldCustomMosaicArray + i] = 0x01;
|
||||||
|
} else {
|
||||||
|
rom[core::overworldCustomMosaicArray + i] = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::fstream file("assets/asm/mosaic_change.asm",
|
std::fstream file("assets/asm/mosaic_change.asm",
|
||||||
std::ios::out | std::ios::in);
|
std::ios::out | std::ios::in);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
return absl::InvalidArgumentError(
|
return absl::InvalidArgumentError(
|
||||||
"Couldn't open mosaic change template file");
|
"Unable to open mosaic change assembly source");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream assembly;
|
std::stringstream assembly;
|
||||||
assembly << file.rdbuf();
|
assembly << file.rdbuf();
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
auto assembly_string = assembly.str();
|
auto assembly_string = assembly.str();
|
||||||
|
|
||||||
if (!core::StringReplace(assembly_string, "<HOOK>", kMosaicChangeOffset)) {
|
if (!core::StringReplace(assembly_string, "<HOOK>", kMosaicChangeOffset)) {
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
"Mosaic template did not have proper `<HOOK>` to replace.");
|
"Mosaic template did not have proper `<HOOK>` to replace.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!core::StringReplace(
|
if (!core::StringReplace(
|
||||||
assembly_string, "<EXPANDED_SPACE>",
|
assembly_string, "<EXPANDED_SPACE>",
|
||||||
absl::StrFormat("$%x", routine_offset + kSNESToPCOffset))) {
|
absl::StrFormat("$%x", routine_offset + kSNESToPCOffset))) {
|
||||||
return absl::InternalError(
|
return absl::InternalError(
|
||||||
"Mosaic template did not have proper `<EXPANDED_SPACE>` to replace.");
|
"Mosaic template did not have proper `<EXPANDED_SPACE>` to replace.");
|
||||||
}
|
}
|
||||||
|
|
||||||
assembly_string += GenerateBytePool(mosaic_tiles);
|
|
||||||
patch_contents_ = assembly_string;
|
patch_contents_ = assembly_string;
|
||||||
patch_filename_ = "assets/asm/mosaic_change_generated.asm";
|
|
||||||
std::ofstream new_file(patch_filename_, std::ios::out);
|
|
||||||
if (new_file.is_open()) {
|
|
||||||
new_file.write(assembly_string.c_str(), assembly_string.size());
|
|
||||||
new_file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ApplyPatchToROM(rom);
|
return ApplyPatchToROM(rom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef YAZE_APP_ASM_SCRIPT_H
|
#ifndef YAZE_APP_ASM_SCRIPT_H
|
||||||
#define YAZE_APP_ASM_SCRIPT_H
|
#define YAZE_APP_ASM_SCRIPT_H
|
||||||
|
|
||||||
#include <asardll.h>
|
#include <asar/interface-lib.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -27,17 +27,15 @@ class ScriptTemplate {
|
|||||||
public:
|
public:
|
||||||
virtual ~ScriptTemplate() = default;
|
virtual ~ScriptTemplate() = default;
|
||||||
virtual absl::Status ApplyPatchToROM(ROM& rom) = 0;
|
virtual absl::Status ApplyPatchToROM(ROM& rom) = 0;
|
||||||
virtual absl::Status GenerateMosaicChangeAssembly(
|
virtual absl::Status PatchOverworldMosaic(
|
||||||
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
||||||
int hook_offset = 0) = 0;
|
int hook_offset = 0) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Script : public ScriptTemplate {
|
class Script : public ScriptTemplate {
|
||||||
public:
|
public:
|
||||||
Script() { asar_init_with_dll_path("assets/libasar.dll"); }
|
|
||||||
|
|
||||||
absl::Status ApplyPatchToROM(ROM& rom) override;
|
absl::Status ApplyPatchToROM(ROM& rom) override;
|
||||||
absl::Status GenerateMosaicChangeAssembly(
|
absl::Status PatchOverworldMosaic(
|
||||||
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
ROM& rom, char mosaic_tiles[core::kNumOverworldMaps], int routine_offset,
|
||||||
int hook_offset = 0) override;
|
int hook_offset = 0) override;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,14 @@
|
|||||||
#define MENU_ITEM(w) if (ImGui::MenuItem(w))
|
#define MENU_ITEM(w) if (ImGui::MenuItem(w))
|
||||||
#define MENU_ITEM2(w, v) if (ImGui::MenuItem(w, v))
|
#define MENU_ITEM2(w, v) if (ImGui::MenuItem(w, v))
|
||||||
|
|
||||||
|
#define BUTTON_COLUMN(w) \
|
||||||
|
ImGui::TableNextColumn(); \
|
||||||
|
ImGui::Button(w);
|
||||||
|
|
||||||
|
#define TEXT_COLUMN(w) \
|
||||||
|
ImGui::TableNextColumn(); \
|
||||||
|
ImGui::Text(w);
|
||||||
|
|
||||||
#define PRINT_IF_ERROR(expression) \
|
#define PRINT_IF_ERROR(expression) \
|
||||||
{ \
|
{ \
|
||||||
auto error = expression; \
|
auto error = expression; \
|
||||||
@@ -474,7 +482,7 @@ constexpr int customAreaSpecificBGPalette =
|
|||||||
constexpr int customAreaSpecificBGASM = 0x140150;
|
constexpr int customAreaSpecificBGASM = 0x140150;
|
||||||
constexpr int customAreaSpecificBGEnabled =
|
constexpr int customAreaSpecificBGEnabled =
|
||||||
0x140140; // 1 byte, not 0 if enabled
|
0x140140; // 1 byte, not 0 if enabled
|
||||||
|
constexpr int overworldCustomMosaicArray = 0x1301F0;
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Dungeon Map Related Variables
|
// Dungeon Map Related Variables
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -1301,6 +1309,294 @@ static const absl::string_view TileTypeNames[] = {
|
|||||||
"$FE Door X top? (unused?)",
|
"$FE Door X top? (unused?)",
|
||||||
"$FF Door X top? (unused?)"};
|
"$FF Door X top? (unused?)"};
|
||||||
|
|
||||||
|
static const absl::string_view kSpriteDefaultNames[]{
|
||||||
|
"00 Raven",
|
||||||
|
"01 Vulture",
|
||||||
|
"02 Flying Stalfos Head",
|
||||||
|
"03 No Pointer (Empty",
|
||||||
|
"04 Pull Switch (good",
|
||||||
|
"05 Pull Switch (unused",
|
||||||
|
"06 Pull Switch (bad",
|
||||||
|
"07 Pull Switch (unused",
|
||||||
|
"08 Octorock (one way",
|
||||||
|
"09 Moldorm (Boss",
|
||||||
|
"0A Octorock (four way",
|
||||||
|
"0B Chicken",
|
||||||
|
"0C Octorock (?",
|
||||||
|
"0D Buzzblock",
|
||||||
|
"0E Snapdragon",
|
||||||
|
"0F Octoballoon",
|
||||||
|
"10 Octoballon Hatchlings",
|
||||||
|
"11 Hinox",
|
||||||
|
"12 Moblin",
|
||||||
|
"13 Mini Helmasaure",
|
||||||
|
"14 Gargoyle's Domain Gate",
|
||||||
|
"15 Antifairy",
|
||||||
|
"16 Sahasrahla / Aginah",
|
||||||
|
"17 Bush Hoarder",
|
||||||
|
"18 Mini Moldorm",
|
||||||
|
"19 Poe",
|
||||||
|
"1A Dwarves",
|
||||||
|
"1B Arrow in wall",
|
||||||
|
"1C Statue",
|
||||||
|
"1D Weathervane",
|
||||||
|
"1E Crystal Switch",
|
||||||
|
"1F Bug-Catching Kid",
|
||||||
|
"20 Sluggula",
|
||||||
|
"21 Push Switch",
|
||||||
|
"22 Ropa",
|
||||||
|
"23 Red Bari",
|
||||||
|
"24 Blue Bari",
|
||||||
|
"25 Talking Tree",
|
||||||
|
"26 Hardhat Beetle",
|
||||||
|
"27 Deadrock",
|
||||||
|
"28 Storytellers",
|
||||||
|
"29 Blind Hideout attendant",
|
||||||
|
"2A Sweeping Lady",
|
||||||
|
"2B Storytellers",
|
||||||
|
"2C Lumberjacks",
|
||||||
|
"2D Telepathic Stones",
|
||||||
|
"2E Multipurpose Sprite",
|
||||||
|
"2F Race Npc",
|
||||||
|
"30 Person?",
|
||||||
|
"31 Fortune Teller",
|
||||||
|
"32 Angry Brothers",
|
||||||
|
"33 Pull for items",
|
||||||
|
"34 Scared Girl",
|
||||||
|
"35 Innkeeper",
|
||||||
|
"36 Witch",
|
||||||
|
"37 Waterfall",
|
||||||
|
"38 Arrow Target",
|
||||||
|
"39 Average Middle",
|
||||||
|
"3A Half Magic Bat",
|
||||||
|
"3B Dash Item",
|
||||||
|
"3C Village Kid",
|
||||||
|
"3D Signs? Chicken lady also showed up / Scared ladies outside houses.",
|
||||||
|
"3E Rock Hoarder",
|
||||||
|
"3F Tutorial Soldier",
|
||||||
|
"40 Lightning Lock",
|
||||||
|
"41 Blue Sword Soldier / Used by guards to detect player",
|
||||||
|
"42 Green Sword Soldier",
|
||||||
|
"43 Red Spear Soldier",
|
||||||
|
"44 Assault Sword Soldier",
|
||||||
|
"45 Green Spear Soldier",
|
||||||
|
"46 Blue Archer",
|
||||||
|
"47 Green Archer",
|
||||||
|
"48 Red Javelin Soldier",
|
||||||
|
"49 Red Javelin Soldier 2",
|
||||||
|
"4A Red Bomb Soldiers",
|
||||||
|
"4B Green Soldier Recruits",
|
||||||
|
"4C Geldman",
|
||||||
|
"4D Rabbit",
|
||||||
|
"4E Popo",
|
||||||
|
"4F Popo 2",
|
||||||
|
"50 Cannon Balls",
|
||||||
|
"51 Armos",
|
||||||
|
"52 Giant Zora",
|
||||||
|
"53 Armos Knights (Boss",
|
||||||
|
"54 Lanmolas (Boss",
|
||||||
|
"55 Fireball Zora",
|
||||||
|
"56 Walking Zora",
|
||||||
|
"57 Desert Palace Barriers",
|
||||||
|
"58 Crab",
|
||||||
|
"59 Bird",
|
||||||
|
"5A Squirrel",
|
||||||
|
"5B Spark (Left to Right",
|
||||||
|
"5C Spark (Right to Left",
|
||||||
|
"5D Roller (vertical moving",
|
||||||
|
"5E Roller (vertical moving",
|
||||||
|
"5F Roller",
|
||||||
|
"60 Roller (horizontal moving",
|
||||||
|
"61 Beamos",
|
||||||
|
"62 Master Sword",
|
||||||
|
"63 Devalant (Non",
|
||||||
|
"64 Devalant (Shooter",
|
||||||
|
"65 Shooting Gallery Proprietor",
|
||||||
|
"66 Moving Cannon Ball Shooters (Right",
|
||||||
|
"67 Moving Cannon Ball Shooters (Left",
|
||||||
|
"68 Moving Cannon Ball Shooters (Down",
|
||||||
|
"69 Moving Cannon Ball Shooters (Up",
|
||||||
|
"6A Ball N' Chain Trooper",
|
||||||
|
"6B Cannon Soldier",
|
||||||
|
"6C Mirror Portal",
|
||||||
|
"6D Rat",
|
||||||
|
"6E Rope",
|
||||||
|
"6F Keese",
|
||||||
|
"70 Helmasaur King Fireball",
|
||||||
|
"71 Leever",
|
||||||
|
"72 Activator for the ponds (where you throw in items",
|
||||||
|
"73 Uncle / Priest",
|
||||||
|
"74 Running Man",
|
||||||
|
"75 Bottle Salesman",
|
||||||
|
"76 Princess Zelda",
|
||||||
|
"77 Antifairy (Alternate",
|
||||||
|
"78 Village Elder",
|
||||||
|
"79 Bee",
|
||||||
|
"7A Agahnim",
|
||||||
|
"7B Agahnim Energy Ball",
|
||||||
|
"7C Hyu",
|
||||||
|
"7D Big Spike Trap",
|
||||||
|
"7E Guruguru Bar (Clockwise",
|
||||||
|
"7F Guruguru Bar (Counter Clockwise",
|
||||||
|
"80 Winder",
|
||||||
|
"81 Water Tektite",
|
||||||
|
"82 Antifairy Circle",
|
||||||
|
"83 Green Eyegore",
|
||||||
|
"84 Red Eyegore",
|
||||||
|
"85 Yellow Stalfos",
|
||||||
|
"86 Kodongos",
|
||||||
|
"87 Flames",
|
||||||
|
"88 Mothula (Boss",
|
||||||
|
"89 Mothula's Beam",
|
||||||
|
"8A Spike Trap",
|
||||||
|
"8B Gibdo",
|
||||||
|
"8C Arrghus (Boss",
|
||||||
|
"8D Arrghus spawn",
|
||||||
|
"8E Terrorpin",
|
||||||
|
"8F Slime",
|
||||||
|
"90 Wallmaster",
|
||||||
|
"91 Stalfos Knight",
|
||||||
|
"92 Helmasaur King",
|
||||||
|
"93 Bumper",
|
||||||
|
"94 Swimmers",
|
||||||
|
"95 Eye Laser (Right",
|
||||||
|
"96 Eye Laser (Left",
|
||||||
|
"97 Eye Laser (Down",
|
||||||
|
"98 Eye Laser (Up",
|
||||||
|
"99 Pengator",
|
||||||
|
"9A Kyameron",
|
||||||
|
"9B Wizzrobe",
|
||||||
|
"9C Tadpoles",
|
||||||
|
"9D Tadpoles",
|
||||||
|
"9E Ostrich (Haunted Grove",
|
||||||
|
"9F Flute",
|
||||||
|
"A0 Birds (Haunted Grove",
|
||||||
|
"A1 Freezor",
|
||||||
|
"A2 Kholdstare (Boss",
|
||||||
|
"A3 Kholdstare's Shell",
|
||||||
|
"A4 Falling Ice",
|
||||||
|
"A5 Zazak Fireball",
|
||||||
|
"A6 Red Zazak",
|
||||||
|
"A7 Stalfos",
|
||||||
|
"A8 Bomber Flying Creatures from Darkworld",
|
||||||
|
"A9 Bomber Flying Creatures from Darkworld",
|
||||||
|
"AA Pikit",
|
||||||
|
"AB Maiden",
|
||||||
|
"AC Apple",
|
||||||
|
"AD Lost Old Man",
|
||||||
|
"AE Down Pipe",
|
||||||
|
"AF Up Pipe",
|
||||||
|
"B0 Right Pip",
|
||||||
|
"B1 Left Pipe",
|
||||||
|
"B2 Good bee again?",
|
||||||
|
"B3 Hylian Inscription",
|
||||||
|
"B4 Thief?s chest (not the one that follows you",
|
||||||
|
"B5 Bomb Salesman",
|
||||||
|
"B6 Kiki",
|
||||||
|
"B7 Maiden following you in Blind Dungeon",
|
||||||
|
"B8 Monologue Testing Sprite",
|
||||||
|
"B9 Feuding Friends on Death Mountain",
|
||||||
|
"BA Whirlpool",
|
||||||
|
"BB Salesman / chestgame guy / 300 rupee giver guy / Chest game thief",
|
||||||
|
"BC Drunk in the inn",
|
||||||
|
"BD Vitreous (Large Eyeball",
|
||||||
|
"BE Vitreous (Small Eyeball",
|
||||||
|
"BF Vitreous' Lightning",
|
||||||
|
"C0 Monster in Lake of Ill Omen / Quake Medallion",
|
||||||
|
"C1 Agahnim teleporting Zelda to dark world",
|
||||||
|
"C2 Boulders",
|
||||||
|
"C3 Gibo",
|
||||||
|
"C4 Thief",
|
||||||
|
"C5 Medusa",
|
||||||
|
"C6 Four Way Fireball Spitters (spit when you use your sword",
|
||||||
|
"C7 Hokku",
|
||||||
|
"C8 Big Fairy who heals you",
|
||||||
|
"C9 Tektite",
|
||||||
|
"CA Chain Chomp",
|
||||||
|
"CB Trinexx",
|
||||||
|
"CC Another part of trinexx",
|
||||||
|
"CD Yet another part of trinexx",
|
||||||
|
"CE Blind The Thief (Boss)",
|
||||||
|
"CF Swamola",
|
||||||
|
"D0 Lynel",
|
||||||
|
"D1 Bunny Beam",
|
||||||
|
"D2 Flopping fish",
|
||||||
|
"D3 Stal",
|
||||||
|
"D4 Landmine",
|
||||||
|
"D5 Digging Game Proprietor",
|
||||||
|
"D6 Ganon",
|
||||||
|
"D7 Copy of Ganon",
|
||||||
|
"D8 Heart",
|
||||||
|
"D9 Green Rupee",
|
||||||
|
"DA Blue Rupee",
|
||||||
|
"DB Red Rupee",
|
||||||
|
"DC Bomb Refill (1)",
|
||||||
|
"DD Bomb Refill (4)",
|
||||||
|
"DE Bomb Refill (8)",
|
||||||
|
"DF Small Magic Refill",
|
||||||
|
"E0 Full Magic Refill",
|
||||||
|
"E1 Arrow Refill (5)",
|
||||||
|
"E2 Arrow Refill (10)",
|
||||||
|
"E3 Fairy",
|
||||||
|
"E4 Key",
|
||||||
|
"E5 Big Key",
|
||||||
|
"E6 Shield",
|
||||||
|
"E7 Mushroom",
|
||||||
|
"E8 Fake Master Sword",
|
||||||
|
"E9 Magic Shop dude / His items",
|
||||||
|
"EA Heart Container",
|
||||||
|
"EB Heart Piece",
|
||||||
|
"EC Bushes",
|
||||||
|
"ED Cane Of Somaria Platform",
|
||||||
|
"EE Mantle",
|
||||||
|
"EF Cane of Somaria Platform (Unused)",
|
||||||
|
"F0 Cane of Somaria Platform (Unused)",
|
||||||
|
"F1 Cane of Somaria Platform (Unused)",
|
||||||
|
"F2 Medallion Tablet",
|
||||||
|
"F3",
|
||||||
|
"F4 Falling Rocks",
|
||||||
|
"F5",
|
||||||
|
"F6",
|
||||||
|
"F7",
|
||||||
|
"F8",
|
||||||
|
"F9",
|
||||||
|
"FA",
|
||||||
|
"FB",
|
||||||
|
"FC",
|
||||||
|
"FD",
|
||||||
|
"FE",
|
||||||
|
"FF",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const absl::string_view overlordnames[] = {
|
||||||
|
"Overlord_SpritePositionTarget",
|
||||||
|
"Overlord_AllDirectionMetalBallFactory",
|
||||||
|
"Overlord_CascadeMetalBallFactory",
|
||||||
|
"Overlord_StalfosFactory",
|
||||||
|
"Overlord_StalfosTrap",
|
||||||
|
"Overlord_SnakeTrap",
|
||||||
|
"Overlord_MovingFloor",
|
||||||
|
"Overlord_ZolFactory",
|
||||||
|
"Overlord_WallMasterFactory",
|
||||||
|
"Overlord_CrumbleTilePath 1",
|
||||||
|
"Overlord_CrumbleTilePath 2",
|
||||||
|
"Overlord_CrumbleTilePath 3",
|
||||||
|
"Overlord_CrumbleTilePath 4",
|
||||||
|
"Overlord_CrumbleTilePath 5",
|
||||||
|
"Overlord_CrumbleTilePath 6",
|
||||||
|
"Overlord_PirogusuFactory 1",
|
||||||
|
"Overlord_PirogusuFactory 2",
|
||||||
|
"Overlord_PirogusuFactory 3",
|
||||||
|
"Overlord_PirogusuFactory 4",
|
||||||
|
"Overlord_FlyingTileFactory",
|
||||||
|
"Overlord_WizzrobeFactory",
|
||||||
|
"Overlord_ZoroFactory",
|
||||||
|
"Overlord_StalfosTrapTriggerWindow",
|
||||||
|
"Overlord_RedStalfosTrap",
|
||||||
|
"Overlord_ArmosCoordinator",
|
||||||
|
"Overlord_BombTrap",
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace core
|
} // namespace core
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class Controller {
|
|||||||
absl::Status onEntry();
|
absl::Status onEntry();
|
||||||
void onInput();
|
void onInput();
|
||||||
void onLoad();
|
void onLoad();
|
||||||
|
void onLoadDelta();
|
||||||
void doRender() const;
|
void doRender() const;
|
||||||
void onExit() const;
|
void onExit() const;
|
||||||
|
|
||||||
|
|||||||
32
src/app/delta/CMakeLists.txt
Normal file
32
src/app/delta/CMakeLists.txt
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
add_library(delta-service delta.proto)
|
||||||
|
target_link_libraries(delta-service
|
||||||
|
PUBLIC
|
||||||
|
protobuf::libprotobuf
|
||||||
|
gRPC::grpc
|
||||||
|
gRPC::grpc++
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(delta-service
|
||||||
|
PUBLIC
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${PROTOBUF_INCLUDE_PATH}
|
||||||
|
)
|
||||||
|
|
||||||
|
get_target_property(grpc_cpp_plugin_location gRPC::grpc_cpp_plugin LOCATION)
|
||||||
|
|
||||||
|
# compile the message types
|
||||||
|
protobuf_generate(TARGET delta-service LANGUAGE cpp)
|
||||||
|
|
||||||
|
# compile the GRPC services
|
||||||
|
protobuf_generate(
|
||||||
|
TARGET
|
||||||
|
delta-service
|
||||||
|
LANGUAGE
|
||||||
|
grpc
|
||||||
|
GENERATE_EXTENSIONS
|
||||||
|
.grpc.pb.h
|
||||||
|
.grpc.pb.cc
|
||||||
|
PLUGIN
|
||||||
|
"protoc-gen-grpc=${grpc_cpp_plugin_location}"
|
||||||
|
)
|
||||||
53
src/app/delta/client.cc
Normal file
53
src/app/delta/client.cc
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#include "client.h"
|
||||||
|
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <grpc/support/log.h>
|
||||||
|
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||||
|
#include <grpcpp/grpcpp.h>
|
||||||
|
#include <grpcpp/health_check_service_interface.h>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "src/app/delta/delta.grpc.pb.h"
|
||||||
|
#include "src/app/delta/delta.pb.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
|
||||||
|
using grpc::Channel;
|
||||||
|
using grpc::ClientAsyncResponseReader;
|
||||||
|
using grpc::ClientContext;
|
||||||
|
using grpc::CompletionQueue;
|
||||||
|
using grpc::Server;
|
||||||
|
using grpc::ServerBuilder;
|
||||||
|
using grpc::Status;
|
||||||
|
|
||||||
|
void Client::CreateChannel() {
|
||||||
|
auto channel = grpc::CreateChannel("localhost:50051",
|
||||||
|
grpc::InsecureChannelCredentials());
|
||||||
|
stub_ = ::YazeDelta::NewStub(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status Client::InitRepo(std::string author_name,
|
||||||
|
std::string project_name) {
|
||||||
|
Repository new_repo;
|
||||||
|
new_repo.set_author_name(author_name);
|
||||||
|
new_repo.set_project_name(project_name);
|
||||||
|
|
||||||
|
InitRequest request;
|
||||||
|
request.set_allocated_repo(&new_repo);
|
||||||
|
|
||||||
|
InitResponse response;
|
||||||
|
Status status = stub_->Init(&rpc_context, request, &response);
|
||||||
|
|
||||||
|
if (!status.ok()) {
|
||||||
|
std::cerr << status.error_code() << ": " << status.error_message()
|
||||||
|
<< std::endl;
|
||||||
|
return absl::InternalError(status.error_message());
|
||||||
|
}
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
44
src/app/delta/client.h
Normal file
44
src/app/delta/client.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef YAZE_APP_DELTA_CLIENT_H
|
||||||
|
#define YAZE_APP_DELTA_CLIENT_H
|
||||||
|
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <grpc/support/log.h>
|
||||||
|
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||||
|
#include <grpcpp/grpcpp.h>
|
||||||
|
#include <grpcpp/health_check_service_interface.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "src/app/delta/delta.grpc.pb.h"
|
||||||
|
#include "src/app/delta/delta.pb.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
|
||||||
|
using grpc::Channel;
|
||||||
|
using grpc::ClientAsyncResponseReader;
|
||||||
|
using grpc::ClientContext;
|
||||||
|
using grpc::CompletionQueue;
|
||||||
|
using grpc::Server;
|
||||||
|
using grpc::ServerBuilder;
|
||||||
|
using grpc::Status;
|
||||||
|
|
||||||
|
class Client {
|
||||||
|
public:
|
||||||
|
Client() = default;
|
||||||
|
void CreateChannel();
|
||||||
|
absl::Status InitRepo(std::string author_name, std::string project_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ClientContext rpc_context;
|
||||||
|
std::vector<Repository> repos_;
|
||||||
|
std::unique_ptr<YazeDelta::Stub> stub_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif
|
||||||
32
src/app/delta/delta.cc
Normal file
32
src/app/delta/delta.cc
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#if defined(_WIN32)
|
||||||
|
#define main SDL_main
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "absl/debugging/failure_signal_handler.h"
|
||||||
|
#include "absl/debugging/symbolize.h"
|
||||||
|
#include "app/core/controller.h"
|
||||||
|
#include "app/delta/viewer.h"
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
absl::InitializeSymbolizer(argv[0]);
|
||||||
|
|
||||||
|
absl::FailureSignalHandlerOptions options;
|
||||||
|
absl::InstallFailureSignalHandler(options);
|
||||||
|
|
||||||
|
yaze::app::core::Controller controller;
|
||||||
|
yaze::app::delta::Viewer viewer;
|
||||||
|
|
||||||
|
auto entry_status = controller.onEntry();
|
||||||
|
if (!entry_status.ok()) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (controller.isActive()) {
|
||||||
|
controller.onInput();
|
||||||
|
viewer.Update();
|
||||||
|
controller.doRender();
|
||||||
|
}
|
||||||
|
controller.onExit();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
80
src/app/delta/delta.proto
Normal file
80
src/app/delta/delta.proto
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
|
||||||
|
service YazeDelta {
|
||||||
|
rpc Init(InitRequest) returns (InitResponse) {}
|
||||||
|
|
||||||
|
rpc Clone(CloneRequest) returns (CloneResponse) {}
|
||||||
|
|
||||||
|
rpc Push(PushRequest) returns (PushResponse) {}
|
||||||
|
rpc Pull(PullRequest) returns (PullResponse) {}
|
||||||
|
|
||||||
|
rpc Sync(stream SyncRequest) returns (stream SyncResponse) {}
|
||||||
|
|
||||||
|
rpc CreateBranch(CreateBranchRequest) returns (CreateBranchResponse) {}
|
||||||
|
rpc DeleteBranch(DeleteBranchRequest) returns (DeleteBranchResponse) {}
|
||||||
|
|
||||||
|
rpc Merge(MergeRequest) returns (MergeResponse) {}
|
||||||
|
rpc UndoMerge(UndoMergeRequest) returns (UndoMergeResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message Commit {
|
||||||
|
int64 commit_id = 1;
|
||||||
|
int64 parent_commit_id = 2;
|
||||||
|
string author_name = 3;
|
||||||
|
string message_header = 4;
|
||||||
|
optional string message_body = 5;
|
||||||
|
bytes data = 6;
|
||||||
|
int64 signature = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Branch {
|
||||||
|
string branch_name = 1;
|
||||||
|
optional string parent_name = 2;
|
||||||
|
repeated Commit commits = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Repository {
|
||||||
|
string project_name = 1;
|
||||||
|
string author_name = 2;
|
||||||
|
int64 signature = 3;
|
||||||
|
optional bool locked = 4;
|
||||||
|
optional string password = 5;
|
||||||
|
repeated Branch tree = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InitRequest {
|
||||||
|
Repository repo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message InitResponse {
|
||||||
|
int32 response = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CloneRequest {}
|
||||||
|
|
||||||
|
message CloneResponse {}
|
||||||
|
|
||||||
|
message PushRequest {
|
||||||
|
string author_name = 1;
|
||||||
|
}
|
||||||
|
message PushResponse {}
|
||||||
|
|
||||||
|
message PullRequest {}
|
||||||
|
message PullResponse {}
|
||||||
|
|
||||||
|
message SyncRequest {}
|
||||||
|
|
||||||
|
message SyncResponse {}
|
||||||
|
|
||||||
|
message CreateBranchRequest {}
|
||||||
|
message CreateBranchResponse {}
|
||||||
|
|
||||||
|
message DeleteBranchRequest {}
|
||||||
|
message DeleteBranchResponse {}
|
||||||
|
|
||||||
|
message MergeRequest {}
|
||||||
|
message MergeResponse {}
|
||||||
|
|
||||||
|
message UndoMergeRequest {}
|
||||||
|
message UndoMergeResponse {}
|
||||||
42
src/app/delta/service.cc
Normal file
42
src/app/delta/service.cc
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "service.h"
|
||||||
|
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <grpc/support/log.h>
|
||||||
|
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||||
|
#include <grpcpp/grpcpp.h>
|
||||||
|
#include <grpcpp/health_check_service_interface.h>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "src/app/delta/delta.grpc.pb.h"
|
||||||
|
#include "src/app/delta/delta.pb.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
|
||||||
|
using grpc::Channel;
|
||||||
|
using grpc::ClientAsyncResponseReader;
|
||||||
|
using grpc::ClientContext;
|
||||||
|
using grpc::CompletionQueue;
|
||||||
|
using grpc::Server;
|
||||||
|
using grpc::ServerBuilder;
|
||||||
|
using grpc::Status;
|
||||||
|
|
||||||
|
Status DeltaService::Init(grpc::ServerContext* context,
|
||||||
|
const InitRequest* request, InitResponse* reply) {
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status DeltaService::Push(grpc::ServerContext* context,
|
||||||
|
const PushRequest* request, PushResponse* reply) {
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status DeltaService::Pull(grpc::ServerContext* context,
|
||||||
|
const PullRequest* request, PullResponse* reply) {
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
37
src/app/delta/service.h
Normal file
37
src/app/delta/service.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef YAZE_APP_DELTA_SERVICE_H
|
||||||
|
#define YAZE_APP_DELTA_SERVICE_H
|
||||||
|
|
||||||
|
#include <google/protobuf/message.h>
|
||||||
|
#include <grpc/support/log.h>
|
||||||
|
#include <grpcpp/ext/proto_server_reflection_plugin.h>
|
||||||
|
#include <grpcpp/grpcpp.h>
|
||||||
|
#include <grpcpp/health_check_service_interface.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "src/app/delta/delta.grpc.pb.h"
|
||||||
|
#include "src/app/delta/delta.pb.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
|
||||||
|
class DeltaService final : public ::YazeDelta::Service {
|
||||||
|
public:
|
||||||
|
Status Init(grpc::ServerContext* context, const InitRequest* request,
|
||||||
|
InitResponse* reply) override;
|
||||||
|
|
||||||
|
Status Push(grpc::ServerContext* context, const PushRequest* request,
|
||||||
|
PushResponse* reply) override;
|
||||||
|
|
||||||
|
Status Pull(grpc::ServerContext* context, const PullRequest* request,
|
||||||
|
PullResponse* reply) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Repository> repos_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
229
src/app/delta/viewer.cc
Normal file
229
src/app/delta/viewer.cc
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
#include "viewer.h"
|
||||||
|
|
||||||
|
#include <ImGuiColorTextEdit/TextEditor.h>
|
||||||
|
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
#include <imgui/misc/cpp/imgui_stdlib.h>
|
||||||
|
#include <imgui_memory_editor.h>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "app/core/constants.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "gui/canvas.h"
|
||||||
|
#include "gui/icons.h"
|
||||||
|
#include "gui/input.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr ImGuiWindowFlags kMainEditorFlags =
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse |
|
||||||
|
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_MenuBar |
|
||||||
|
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar;
|
||||||
|
|
||||||
|
void NewMasterFrame() {
|
||||||
|
const ImGuiIO& io = ImGui::GetIO();
|
||||||
|
ImGui::NewFrame();
|
||||||
|
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||||
|
ImVec2 dimensions(io.DisplaySize.x, io.DisplaySize.y);
|
||||||
|
ImGui::SetNextWindowSize(dimensions, ImGuiCond_Always);
|
||||||
|
|
||||||
|
if (!ImGui::Begin("##YazeMain", nullptr, kMainEditorFlags)) {
|
||||||
|
ImGui::End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void Viewer::Update() {
|
||||||
|
NewMasterFrame();
|
||||||
|
DrawYazeMenu();
|
||||||
|
DrawFileDialog();
|
||||||
|
|
||||||
|
ImGui::Text(ICON_MD_CHANGE_HISTORY);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("%s", rom_.GetTitle());
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::Button(ICON_MD_SYNC);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_ARROW_UPWARD);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_ARROW_DOWNWARD);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_MERGE);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::Button(ICON_MD_MANAGE_HISTORY);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_LAN);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_COMMIT);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Button(ICON_MD_DIFFERENCE);
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(75.f);
|
||||||
|
ImGui::Button(ICON_MD_SEND);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::InputText("Server Address", &client_address_);
|
||||||
|
|
||||||
|
ImGui::SetNextItemWidth(75.f);
|
||||||
|
ImGui::Button(ICON_MD_DOWNLOAD);
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::InputText("Repository Source", &client_address_);
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
DrawBranchTree();
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewer::DrawFileDialog() {
|
||||||
|
if (ImGuiFileDialog::Instance()->Display("ChooseFileDlgKey")) {
|
||||||
|
if (ImGuiFileDialog::Instance()->IsOk()) {
|
||||||
|
std::string filePathName = ImGuiFileDialog::Instance()->GetFilePathName();
|
||||||
|
rom_.LoadFromFile(filePathName);
|
||||||
|
}
|
||||||
|
ImGuiFileDialog::Instance()->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewer::DrawYazeMenu() {
|
||||||
|
MENU_BAR()
|
||||||
|
DrawFileMenu();
|
||||||
|
DrawViewMenu();
|
||||||
|
END_MENU_BAR()
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewer::DrawFileMenu() const {
|
||||||
|
if (ImGui::BeginMenu("File")) {
|
||||||
|
if (ImGui::MenuItem("Open", "Ctrl+O")) {
|
||||||
|
ImGuiFileDialog::Instance()->OpenDialog("ChooseFileDlgKey", "Open ROM",
|
||||||
|
".sfc,.smc", ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
MENU_ITEM2("Save", "Ctrl+S") {}
|
||||||
|
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewer::DrawViewMenu() {
|
||||||
|
static bool show_imgui_metrics = false;
|
||||||
|
static bool show_imgui_style_editor = false;
|
||||||
|
static bool show_memory_editor = false;
|
||||||
|
static bool show_imgui_demo = false;
|
||||||
|
|
||||||
|
if (show_imgui_metrics) {
|
||||||
|
ImGui::ShowMetricsWindow(&show_imgui_metrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_memory_editor) {
|
||||||
|
static MemoryEditor mem_edit;
|
||||||
|
mem_edit.DrawWindow("Memory Editor", (void*)&rom_, rom_.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_imgui_demo) {
|
||||||
|
ImGui::ShowDemoWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_imgui_style_editor) {
|
||||||
|
ImGui::Begin("Style Editor (ImGui)", &show_imgui_style_editor);
|
||||||
|
ImGui::ShowStyleEditor();
|
||||||
|
ImGui::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginMenu("View")) {
|
||||||
|
ImGui::MenuItem("HEX Editor", nullptr, &show_memory_editor);
|
||||||
|
ImGui::MenuItem("ImGui Demo", nullptr, &show_imgui_demo);
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::BeginMenu("GUI Tools")) {
|
||||||
|
ImGui::MenuItem("Metrics (ImGui)", nullptr, &show_imgui_metrics);
|
||||||
|
ImGui::MenuItem("Style Editor (ImGui)", nullptr,
|
||||||
|
&show_imgui_style_editor);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewer::DrawBranchTree() {
|
||||||
|
static ImGuiTableFlags flags =
|
||||||
|
ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH |
|
||||||
|
ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg |
|
||||||
|
ImGuiTableFlags_NoBordersInBody;
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("3ways", 3, flags)) {
|
||||||
|
// The first column will use the default _WidthStretch when ScrollX is Off
|
||||||
|
// and _WidthFixed when ScrollX is On
|
||||||
|
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
|
||||||
|
ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
10 * 12.0f);
|
||||||
|
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed,
|
||||||
|
10 * 18.0f);
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
// Simple storage to output a dummy file-system.
|
||||||
|
struct MyTreeNode {
|
||||||
|
const char* Name;
|
||||||
|
const char* Type;
|
||||||
|
int Size;
|
||||||
|
int ChildIdx;
|
||||||
|
int ChildCount;
|
||||||
|
static void DisplayNode(const MyTreeNode* node,
|
||||||
|
const MyTreeNode* all_nodes) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
const bool is_folder = (node->ChildCount > 0);
|
||||||
|
if (is_folder) {
|
||||||
|
bool open =
|
||||||
|
ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextDisabled("--");
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(node->Type);
|
||||||
|
if (open) {
|
||||||
|
for (int child_n = 0; child_n < node->ChildCount; child_n++)
|
||||||
|
DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
|
||||||
|
ImGui::TreePop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::TreeNodeEx(
|
||||||
|
node->Name, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet |
|
||||||
|
ImGuiTreeNodeFlags_NoTreePushOnOpen |
|
||||||
|
ImGuiTreeNodeFlags_SpanFullWidth);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::Text("%d", node->Size);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(node->Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const MyTreeNode nodes[] = {
|
||||||
|
{"lttp-redux", "Repository", -1, 1, 3},
|
||||||
|
{"main", "Branch", -1, 4, 2},
|
||||||
|
{"hyrule-castle", "Branch", -1, 4, 2},
|
||||||
|
{"lost-woods", "Branch", -1, 6, 3},
|
||||||
|
{"Added some bushes", "Commit", 1024, -1, -1},
|
||||||
|
{"Constructed a new house", "Commit", 123000, -1, -1},
|
||||||
|
{"File1_b.wav", "Commit", 456000, -1, -1},
|
||||||
|
{"Image001.png", "Commit", 203128, -1, -1},
|
||||||
|
{"Copy of Image001.png", "Commit", 203256, -1, -1},
|
||||||
|
{"Copy of Image001 (Final2).png", "Commit", 203512, -1, -1},
|
||||||
|
};
|
||||||
|
|
||||||
|
MyTreeNode::DisplayNode(&nodes[0], nodes);
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
45
src/app/delta/viewer.h
Normal file
45
src/app/delta/viewer.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef YAZE_APP_DELTA_VIEWER_H
|
||||||
|
#define YAZE_APP_DELTA_VIEWER_H
|
||||||
|
|
||||||
|
#include <ImGuiColorTextEdit/TextEditor.h>
|
||||||
|
#include <ImGuiFileDialog/ImGuiFileDialog.h>
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
#include <imgui/misc/cpp/imgui_stdlib.h>
|
||||||
|
#include <imgui_memory_editor.h>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "app/core/constants.h"
|
||||||
|
#include "app/delta/client.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "gui/canvas.h"
|
||||||
|
#include "gui/icons.h"
|
||||||
|
#include "gui/input.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace delta {
|
||||||
|
class Viewer {
|
||||||
|
public:
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DrawFileDialog();
|
||||||
|
|
||||||
|
void DrawYazeMenu();
|
||||||
|
void DrawFileMenu() const;
|
||||||
|
void DrawViewMenu();
|
||||||
|
|
||||||
|
void DrawBranchTree();
|
||||||
|
|
||||||
|
std::string client_address_;
|
||||||
|
|
||||||
|
ROM rom_;
|
||||||
|
Client client_;
|
||||||
|
};
|
||||||
|
} // namespace delta
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -103,6 +103,7 @@ void MasterEditor::DrawFileDialog() {
|
|||||||
status_ = rom_.LoadFromFile(filePathName);
|
status_ = rom_.LoadFromFile(filePathName);
|
||||||
overworld_editor_.SetupROM(rom_);
|
overworld_editor_.SetupROM(rom_);
|
||||||
screen_editor_.SetupROM(rom_);
|
screen_editor_.SetupROM(rom_);
|
||||||
|
palette_editor_.SetupROM(rom_);
|
||||||
}
|
}
|
||||||
ImGuiFileDialog::Instance()->Close();
|
ImGuiFileDialog::Instance()->Close();
|
||||||
}
|
}
|
||||||
@@ -118,10 +119,10 @@ void MasterEditor::DrawAboutPopup() {
|
|||||||
if (about_) ImGui::OpenPopup("About");
|
if (about_) ImGui::OpenPopup("About");
|
||||||
if (ImGui::BeginPopupModal("About", nullptr,
|
if (ImGui::BeginPopupModal("About", nullptr,
|
||||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text("Yet Another Zelda3 Editor - v0.01");
|
ImGui::Text("Yet Another Zelda3 Editor - v0.02");
|
||||||
ImGui::Text("Written by: scawful");
|
ImGui::Text("Written by: scawful");
|
||||||
ImGui::Spacing();
|
ImGui::Spacing();
|
||||||
ImGui::Text("Special Thanks: Zarby89");
|
ImGui::Text("Special Thanks: Zarby89, JaredBrian");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
if (ImGui::Button("Close", ImVec2(200, 0))) {
|
if (ImGui::Button("Close", ImVec2(200, 0))) {
|
||||||
@@ -137,7 +138,7 @@ void MasterEditor::DrawInfoPopup() {
|
|||||||
if (ImGui::BeginPopupModal("ROM Information", nullptr,
|
if (ImGui::BeginPopupModal("ROM Information", nullptr,
|
||||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
ImGui::Text("Title: %s", rom_.GetTitle());
|
ImGui::Text("Title: %s", rom_.GetTitle());
|
||||||
ImGui::Text("ROM Size: %ld", rom_.GetSize());
|
ImGui::Text("ROM Size: %ld", rom_.size());
|
||||||
|
|
||||||
if (ImGui::Button("Close", ImVec2(200, 0))) {
|
if (ImGui::Button("Close", ImVec2(200, 0))) {
|
||||||
rom_info_ = false;
|
rom_info_ = false;
|
||||||
@@ -215,7 +216,7 @@ void MasterEditor::DrawViewMenu() {
|
|||||||
|
|
||||||
if (show_memory_editor) {
|
if (show_memory_editor) {
|
||||||
static MemoryEditor mem_edit;
|
static MemoryEditor mem_edit;
|
||||||
mem_edit.DrawWindow("Memory Editor", (void *)&rom_, rom_.GetSize());
|
mem_edit.DrawWindow("Memory Editor", (void *)&rom_, rom_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show_imgui_demo) {
|
if (show_imgui_demo) {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "absl/container/flat_hash_map.h"
|
#include "absl/container/flat_hash_map.h"
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "app/editor/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.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"
|
||||||
@@ -22,15 +24,15 @@ namespace editor {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void UpdateSelectedTile16(int selected, gfx::Bitmap &tile16_blockset,
|
void UpdateSelectedTile16(int selected, gfx::Bitmap &tile16_blockset,
|
||||||
gfx::Bitmap &selected_tile) {
|
Bytes &selected_tile) {
|
||||||
|
selected_tile.reserve(256);
|
||||||
auto blockset = tile16_blockset.GetData();
|
auto blockset = tile16_blockset.GetData();
|
||||||
auto bitmap = selected_tile.GetData();
|
|
||||||
|
|
||||||
int src_pos = ((selected - ((selected / 0x08) * 0x08)) * 0x10) +
|
int src_pos = ((selected - ((selected / 0x08) * 0x08)) * 0x10) +
|
||||||
((selected / 0x08) * 2048);
|
((selected / 0x08) * 2048);
|
||||||
for (int yy = 0; yy < 0x10; yy++) {
|
for (int yy = 0; yy < 0x10; yy++) {
|
||||||
for (int xx = 0; xx < 0x10; xx++) {
|
for (int xx = 0; xx < 0x10; xx++) {
|
||||||
bitmap[xx + (yy * 0x10)] = blockset[src_pos + xx + (yy * 0x80)];
|
selected_tile[xx + (yy * 0x10)] = blockset[src_pos + xx + (yy * 0x80)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,25 +46,21 @@ absl::Status OverworldEditor::Update() {
|
|||||||
all_gfx_loaded_ = true;
|
all_gfx_loaded_ = true;
|
||||||
|
|
||||||
RETURN_IF_ERROR(overworld_.Load(rom_))
|
RETURN_IF_ERROR(overworld_.Load(rom_))
|
||||||
current_gfx_bmp_.Create(128, 512, 64, overworld_.GetCurrentGraphics());
|
palette_ = overworld_.AreaPalette();
|
||||||
|
current_gfx_bmp_.Create(128, 512, 64, overworld_.AreaGraphics());
|
||||||
|
current_gfx_bmp_.ApplyPalette(palette_);
|
||||||
rom_.RenderBitmap(¤t_gfx_bmp_);
|
rom_.RenderBitmap(¤t_gfx_bmp_);
|
||||||
|
|
||||||
auto tile16_palette = overworld_.GetCurrentPalette();
|
tile16_blockset_bmp_.Create(128, 8192, 128, overworld_.Tile16Blockset());
|
||||||
tile16_blockset_bmp_.Create(128, 8192, 128,
|
tile16_blockset_bmp_.ApplyPalette(palette_);
|
||||||
overworld_.GetCurrentBlockset());
|
|
||||||
for (int j = 0; j < tile16_palette.colors.size(); j++) {
|
|
||||||
tile16_blockset_bmp_.SetPaletteColor(j, tile16_palette.GetColor(j));
|
|
||||||
}
|
|
||||||
rom_.RenderBitmap(&tile16_blockset_bmp_);
|
rom_.RenderBitmap(&tile16_blockset_bmp_);
|
||||||
map_blockset_loaded_ = true;
|
map_blockset_loaded_ = true;
|
||||||
|
|
||||||
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
|
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
|
||||||
overworld_.SetCurrentMap(i);
|
overworld_.SetCurrentMap(i);
|
||||||
auto palette = overworld_.GetCurrentPalette();
|
auto palette = overworld_.AreaPalette();
|
||||||
maps_bmp_[i].Create(512, 512, 512, overworld_.GetCurrentBitmapData());
|
maps_bmp_[i].Create(512, 512, 512, overworld_.BitmapData());
|
||||||
for (int j = 0; j < palette.colors.size(); j++) {
|
maps_bmp_[i].ApplyPalette(palette);
|
||||||
maps_bmp_[i].SetPaletteColor(j, palette.GetColor(j));
|
|
||||||
}
|
|
||||||
rom_.RenderBitmap(&(maps_bmp_[i]));
|
rom_.RenderBitmap(&(maps_bmp_[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,11 +70,8 @@ absl::Status OverworldEditor::Update() {
|
|||||||
selected_tile_bmp_.Create(16, 16, 64, 256);
|
selected_tile_bmp_.Create(16, 16, 64, 256);
|
||||||
}
|
}
|
||||||
UpdateSelectedTile16(selected_tile_, tile16_blockset_bmp_,
|
UpdateSelectedTile16(selected_tile_, tile16_blockset_bmp_,
|
||||||
selected_tile_bmp_);
|
selected_tile_data_);
|
||||||
auto palette = overworld_.GetCurrentPalette();
|
selected_tile_bmp_.ApplyPalette(palette_);
|
||||||
for (int j = 0; j < palette.colors.size(); j++) {
|
|
||||||
selected_tile_bmp_.SetPaletteColor(j, palette.GetColor(j));
|
|
||||||
}
|
|
||||||
rom_.RenderBitmap(&selected_tile_bmp_);
|
rom_.RenderBitmap(&selected_tile_bmp_);
|
||||||
update_selected_tile_ = false;
|
update_selected_tile_ = false;
|
||||||
}
|
}
|
||||||
@@ -102,44 +97,26 @@ absl::Status OverworldEditor::Update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status OverworldEditor::DrawToolset() {
|
absl::Status OverworldEditor::DrawToolset() {
|
||||||
if (ImGui::BeginTable("OWToolset", 15, toolset_table_flags, ImVec2(0, 0))) {
|
if (ImGui::BeginTable("OWToolset", 17, toolset_table_flags, ImVec2(0, 0))) {
|
||||||
for (const auto &name : kToolsetColumnNames)
|
for (const auto &name : kToolsetColumnNames)
|
||||||
ImGui::TableSetupColumn(name.data());
|
ImGui::TableSetupColumn(name.data());
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
BUTTON_COLUMN(ICON_MD_UNDO) // Undo
|
||||||
ImGui::Button(ICON_MD_UNDO);
|
BUTTON_COLUMN(ICON_MD_REDO) // Redo
|
||||||
ImGui::TableNextColumn();
|
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||||
ImGui::Button(ICON_MD_REDO);
|
BUTTON_COLUMN(ICON_MD_ZOOM_OUT) // Zoom Out
|
||||||
ImGui::TableNextColumn();
|
BUTTON_COLUMN(ICON_MD_ZOOM_IN) // Zoom In
|
||||||
ImGui::Text(ICON_MD_MORE_VERT);
|
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||||
|
BUTTON_COLUMN(ICON_MD_DRAW) // Draw Tile
|
||||||
ImGui::TableNextColumn();
|
BUTTON_COLUMN(ICON_MD_DOOR_FRONT) // Entrances
|
||||||
ImGui::Button(ICON_MD_ZOOM_OUT);
|
BUTTON_COLUMN(ICON_MD_DOOR_BACK) // Exits
|
||||||
ImGui::TableNextColumn();
|
BUTTON_COLUMN(ICON_MD_GRASS) // Items
|
||||||
ImGui::Button(ICON_MD_ZOOM_IN);
|
BUTTON_COLUMN(ICON_MD_PEST_CONTROL_RODENT) // Sprites
|
||||||
ImGui::TableNextColumn();
|
BUTTON_COLUMN(ICON_MD_ADD_LOCATION) // Transports
|
||||||
ImGui::Text(ICON_MD_MORE_VERT);
|
BUTTON_COLUMN(ICON_MD_MUSIC_NOTE) // Music
|
||||||
|
TEXT_COLUMN(ICON_MD_MORE_VERT) // Separator
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn(); // Palette
|
||||||
ImGui::Button(ICON_MD_DRAW);
|
palette_editor_.DisplayPalette(palette_, overworld_.isLoaded());
|
||||||
// Entrances
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_DOOR_FRONT);
|
|
||||||
// Exits
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_DOOR_BACK);
|
|
||||||
// Items
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_GRASS);
|
|
||||||
// Sprites
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_PEST_CONTROL_RODENT);
|
|
||||||
// Transports
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_ADD_LOCATION);
|
|
||||||
// Music
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Button(ICON_MD_MUSIC_NOTE);
|
|
||||||
|
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
@@ -218,6 +195,15 @@ void OverworldEditor::DrawOverworldCanvas() {
|
|||||||
xx = 0;
|
xx = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (const auto &each : overworld_.Entrances()) {
|
||||||
|
if (each.mapId_ < 64 + (current_world_ * 0x40) &&
|
||||||
|
each.mapId_ >= (current_world_ * 0x40)) {
|
||||||
|
overworld_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
|
||||||
|
ImVec4(210, 24, 210, 150));
|
||||||
|
std::string str = absl::StrFormat("%#x", each.entranceId_);
|
||||||
|
overworld_map_canvas_.DrawText(str, each.x_ - 4, each.y_ - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
overworld_map_canvas_.DrawGrid(64.f);
|
overworld_map_canvas_.DrawGrid(64.f);
|
||||||
overworld_map_canvas_.DrawOverlay();
|
overworld_map_canvas_.DrawOverlay();
|
||||||
@@ -261,9 +247,7 @@ void OverworldEditor::DrawTileSelector() {
|
|||||||
void OverworldEditor::DrawTile16Selector() {
|
void OverworldEditor::DrawTile16Selector() {
|
||||||
blockset_canvas_.DrawBackground(ImVec2(0x100 + 1, (8192 * 2) + 1));
|
blockset_canvas_.DrawBackground(ImVec2(0x100 + 1, (8192 * 2) + 1));
|
||||||
blockset_canvas_.DrawContextMenu();
|
blockset_canvas_.DrawContextMenu();
|
||||||
if (map_blockset_loaded_) {
|
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 2, map_blockset_loaded_);
|
||||||
blockset_canvas_.DrawBitmap(tile16_blockset_bmp_, 2);
|
|
||||||
}
|
|
||||||
blockset_canvas_.DrawGrid(32.0f);
|
blockset_canvas_.DrawGrid(32.0f);
|
||||||
blockset_canvas_.DrawOverlay();
|
blockset_canvas_.DrawOverlay();
|
||||||
}
|
}
|
||||||
@@ -291,13 +275,11 @@ void OverworldEditor::DrawTile8Selector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::DrawAreaGraphics() {
|
void OverworldEditor::DrawAreaGraphics() {
|
||||||
if (overworld_.isLoaded()) {
|
current_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 16 * 64 + 1));
|
||||||
current_gfx_canvas_.DrawBackground(ImVec2(256 + 1, 16 * 64 + 1));
|
current_gfx_canvas_.DrawContextMenu();
|
||||||
current_gfx_canvas_.DrawContextMenu();
|
current_gfx_canvas_.DrawBitmap(current_gfx_bmp_, 2, overworld_.isLoaded());
|
||||||
current_gfx_canvas_.DrawBitmap(current_gfx_bmp_);
|
current_gfx_canvas_.DrawGrid(32.0f);
|
||||||
current_gfx_canvas_.DrawGrid(32.0f);
|
current_gfx_canvas_.DrawOverlay();
|
||||||
current_gfx_canvas_.DrawOverlay();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::LoadGraphics() {
|
void OverworldEditor::LoadGraphics() {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "absl/container/flat_hash_map.h"
|
#include "absl/container/flat_hash_map.h"
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "app/editor/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.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"
|
||||||
@@ -29,10 +31,10 @@ static constexpr uint kTile8DisplayHeight = 64;
|
|||||||
static constexpr float kInputFieldSize = 30.f;
|
static constexpr float kInputFieldSize = 30.f;
|
||||||
|
|
||||||
static constexpr absl::string_view kToolsetColumnNames[] = {
|
static constexpr absl::string_view kToolsetColumnNames[] = {
|
||||||
"#undoTool", "#redoTool", "#drawTool", "#separator2",
|
"#undoTool", "#redoTool", "#drawTool", "#separator2",
|
||||||
"#zoomOutTool", "#zoomInTool", "#separator", "#history",
|
"#zoomOutTool", "#zoomInTool", "#separator", "#history",
|
||||||
"#entranceTool", "#exitTool", "#itemTool", "#spriteTool",
|
"#entranceTool", "#exitTool", "#itemTool", "#spriteTool",
|
||||||
"#transportTool", "#musicTool" };
|
"#transportTool", "#musicTool"};
|
||||||
|
|
||||||
static constexpr absl::string_view kOverworldSettingsColumnNames[] = {
|
static constexpr absl::string_view kOverworldSettingsColumnNames[] = {
|
||||||
"##1stCol", "##gfxCol", "##palCol", "##sprgfxCol",
|
"##1stCol", "##gfxCol", "##palCol", "##sprgfxCol",
|
||||||
@@ -82,17 +84,20 @@ class OverworldEditor {
|
|||||||
ImGuiTableFlags_Resizable |
|
ImGuiTableFlags_Resizable |
|
||||||
ImGuiTableFlags_SizingStretchSame;
|
ImGuiTableFlags_SizingStretchSame;
|
||||||
|
|
||||||
|
Bytes selected_tile_data_;
|
||||||
std::unordered_map<int, gfx::Bitmap> graphics_bin_;
|
std::unordered_map<int, gfx::Bitmap> graphics_bin_;
|
||||||
std::unordered_map<int, gfx::Bitmap> current_graphics_set_;
|
std::unordered_map<int, gfx::Bitmap> current_graphics_set_;
|
||||||
std::unordered_map<int, gfx::Bitmap> maps_bmp_;
|
std::unordered_map<int, gfx::Bitmap> maps_bmp_;
|
||||||
|
std::unordered_map<int, gfx::Bitmap> sprite_previews_;
|
||||||
|
|
||||||
ROM rom_;
|
ROM rom_;
|
||||||
|
PaletteEditor palette_editor_;
|
||||||
zelda3::Overworld overworld_;
|
zelda3::Overworld overworld_;
|
||||||
|
|
||||||
gfx::SNESPalette palette_;
|
gfx::SNESPalette palette_;
|
||||||
gfx::Bitmap tile16_blockset_bmp_; // pointer size 1048576
|
gfx::Bitmap tile16_blockset_bmp_;
|
||||||
gfx::Bitmap current_gfx_bmp_; // pointer size 32768
|
gfx::Bitmap current_gfx_bmp_;
|
||||||
gfx::Bitmap all_gfx_bmp; // pointer size 456704
|
gfx::Bitmap all_gfx_bmp;
|
||||||
gfx::Bitmap selected_tile_bmp_;
|
gfx::Bitmap selected_tile_bmp_;
|
||||||
|
|
||||||
gui::Canvas overworld_map_canvas_;
|
gui::Canvas overworld_map_canvas_;
|
||||||
|
|||||||
@@ -12,10 +12,28 @@ namespace app {
|
|||||||
namespace editor {
|
namespace editor {
|
||||||
|
|
||||||
absl::Status PaletteEditor::Update() {
|
absl::Status PaletteEditor::Update() {
|
||||||
for (const auto &name : kPaletteCategoryNames) {
|
for (int i = 0; i < 11; ++i) {
|
||||||
if (ImGui::TreeNode(name.data())) {
|
if (ImGui::TreeNode(kPaletteCategoryNames[i].data())) {
|
||||||
ImGui::SameLine();
|
auto size = rom_.GetPaletteGroup(kPaletteGroupNames[i].data()).size;
|
||||||
if (ImGui::SmallButton("button")) {
|
auto palettes = rom_.GetPaletteGroup(kPaletteGroupNames[i].data());
|
||||||
|
for (int j = 0; j < size; j++) {
|
||||||
|
ImGui::Text("%d", j);
|
||||||
|
auto palette = palettes[j];
|
||||||
|
for (int n = 0; n < size; n++) {
|
||||||
|
ImGui::PushID(n);
|
||||||
|
if ((n % 8) != 0)
|
||||||
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||||
|
|
||||||
|
ImGuiColorEditFlags palette_button_flags =
|
||||||
|
ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker;
|
||||||
|
if (ImGui::ColorButton("##palette", palette[n].RGB(),
|
||||||
|
palette_button_flags, ImVec2(20, 20)))
|
||||||
|
current_color_ =
|
||||||
|
ImVec4(palette[n].rgb.x, palette[n].rgb.y, palette[n].rgb.z,
|
||||||
|
current_color_.w); // Preserve alpha!
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
@@ -23,6 +41,88 @@ absl::Status PaletteEditor::Update() {
|
|||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PaletteEditor::DisplayPalette(gfx::SNESPalette& palette, bool loaded) {
|
||||||
|
static ImVec4 color = ImVec4(0, 0, 0, 255.f);
|
||||||
|
ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
|
||||||
|
ImGuiColorEditFlags_NoDragDrop |
|
||||||
|
ImGuiColorEditFlags_NoOptions;
|
||||||
|
|
||||||
|
// Generate a default palette. The palette will persist and can be edited.
|
||||||
|
static bool init = false;
|
||||||
|
static ImVec4 saved_palette[256] = {};
|
||||||
|
if (loaded && !init) {
|
||||||
|
for (int n = 0; n < palette.size_; n++) {
|
||||||
|
saved_palette[n].x = palette.GetColor(n).rgb.x / 255;
|
||||||
|
saved_palette[n].y = palette.GetColor(n).rgb.y / 255;
|
||||||
|
saved_palette[n].z = palette.GetColor(n).rgb.z / 255;
|
||||||
|
saved_palette[n].w = 255; // Alpha
|
||||||
|
}
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImVec4 backup_color;
|
||||||
|
bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
|
||||||
|
ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
|
||||||
|
open_popup |= ImGui::Button("Palette");
|
||||||
|
if (open_popup) {
|
||||||
|
ImGui::OpenPopup("mypicker");
|
||||||
|
backup_color = color;
|
||||||
|
}
|
||||||
|
if (ImGui::BeginPopup("mypicker")) {
|
||||||
|
ImGui::Text("Current Overworld Palette");
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::ColorPicker4("##picker", (float*)&color,
|
||||||
|
misc_flags | ImGuiColorEditFlags_NoSidePreview |
|
||||||
|
ImGuiColorEditFlags_NoSmallPreview);
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::BeginGroup(); // Lock X position
|
||||||
|
ImGui::Text("Current ==>");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Previous");
|
||||||
|
|
||||||
|
ImGui::ColorButton(
|
||||||
|
"##current", color,
|
||||||
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
||||||
|
ImVec2(60, 40));
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::ColorButton(
|
||||||
|
"##previous", backup_color,
|
||||||
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
||||||
|
ImVec2(60, 40)))
|
||||||
|
color = backup_color;
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Text("Palette");
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) {
|
||||||
|
ImGui::PushID(n);
|
||||||
|
if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||||
|
|
||||||
|
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha |
|
||||||
|
ImGuiColorEditFlags_NoPicker |
|
||||||
|
ImGuiColorEditFlags_NoTooltip;
|
||||||
|
if (ImGui::ColorButton("##palette", saved_palette[n],
|
||||||
|
palette_button_flags, ImVec2(20, 20)))
|
||||||
|
color = ImVec4(saved_palette[n].x, saved_palette[n].y,
|
||||||
|
saved_palette[n].z, color.w); // Preserve alpha!
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget()) {
|
||||||
|
if (const ImGuiPayload* payload =
|
||||||
|
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
|
||||||
|
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
|
||||||
|
if (const ImGuiPayload* payload =
|
||||||
|
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
|
||||||
|
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
|
#include "app/rom.h"
|
||||||
#include "gui/canvas.h"
|
#include "gui/canvas.h"
|
||||||
#include "gui/icons.h"
|
#include "gui/icons.h"
|
||||||
|
|
||||||
@@ -17,11 +18,21 @@ static constexpr absl::string_view kPaletteCategoryNames[] = {
|
|||||||
"Area Colors", "Enemies", "Dungeons", "World Map",
|
"Area Colors", "Enemies", "Dungeons", "World Map",
|
||||||
"Dungeon Map", "Triforce", "Crystal"};
|
"Dungeon Map", "Triforce", "Crystal"};
|
||||||
|
|
||||||
|
static constexpr absl::string_view kPaletteGroupNames[] = {
|
||||||
|
"swords", "shields", "armors", "ow_main",
|
||||||
|
"ow_aux", "global_sprites", "dungeon_main", "ow_mini_map",
|
||||||
|
"ow_mini_map", "3d_object", "3d_object"};
|
||||||
|
|
||||||
class PaletteEditor {
|
class PaletteEditor {
|
||||||
public:
|
public:
|
||||||
absl::Status Update();
|
absl::Status Update();
|
||||||
|
void DisplayPalette(gfx::SNESPalette& palette, bool loaded);
|
||||||
|
|
||||||
|
auto SetupROM(ROM& rom) { rom_ = rom; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ImVec4 current_color_;
|
||||||
|
ROM rom_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "gui/canvas.h"
|
#include "gui/canvas.h"
|
||||||
|
#include "gui/icons.h"
|
||||||
#include "gui/input.h"
|
#include "gui/input.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
@@ -27,13 +28,12 @@ ScreenEditor::ScreenEditor() { screen_canvas_.SetCanvasSize(ImVec2(512, 512)); }
|
|||||||
|
|
||||||
void ScreenEditor::Update() {
|
void ScreenEditor::Update() {
|
||||||
TAB_BAR("##TabBar")
|
TAB_BAR("##TabBar")
|
||||||
DrawMosaicEditor();
|
DrawInventoryMenuEditor();
|
||||||
DrawTitleScreenEditor();
|
DrawTitleScreenEditor();
|
||||||
DrawNamingScreenEditor();
|
DrawNamingScreenEditor();
|
||||||
DrawOverworldMapEditor();
|
DrawOverworldMapEditor();
|
||||||
DrawDungeonMapsEditor();
|
DrawDungeonMapsEditor();
|
||||||
DrawGameMenuEditor();
|
DrawMosaicEditor();
|
||||||
DrawHUDEditor();
|
|
||||||
END_TAB_BAR()
|
END_TAB_BAR()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +60,64 @@ void ScreenEditor::DrawWorldGrid(int world, int h, int w) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenEditor::DrawInventoryMenuEditor() {
|
||||||
|
TAB_ITEM("Inventory Menu")
|
||||||
|
|
||||||
|
static bool create = false;
|
||||||
|
if (!create && rom_.isLoaded()) {
|
||||||
|
inventory_.Create();
|
||||||
|
palette_ =inventory_.Palette();
|
||||||
|
create = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawInventoryToolset();
|
||||||
|
|
||||||
|
if (ImGui::BeginTable("InventoryScreen", 3, ImGuiTableFlags_Resizable)) {
|
||||||
|
ImGui::TableSetupColumn("Canvas");
|
||||||
|
ImGui::TableSetupColumn("Tiles");
|
||||||
|
ImGui::TableSetupColumn("Palette");
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
screen_canvas_.DrawBackground();
|
||||||
|
screen_canvas_.DrawContextMenu();
|
||||||
|
screen_canvas_.DrawBitmap(inventory_.Bitmap(), 2, create);
|
||||||
|
screen_canvas_.DrawGrid(32.0f);
|
||||||
|
screen_canvas_.DrawOverlay();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
tilesheet_canvas_.DrawBackground(ImVec2(128 * 2 + 2, (192 * 2) + 4));
|
||||||
|
tilesheet_canvas_.DrawContextMenu();
|
||||||
|
tilesheet_canvas_.DrawBitmap(inventory_.Tilesheet(), 2, create);
|
||||||
|
tilesheet_canvas_.DrawGrid(16.0f);
|
||||||
|
tilesheet_canvas_.DrawOverlay();
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
gui::DisplayPalette(palette_, create);
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
END_TAB_ITEM()
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenEditor::DrawTitleScreenEditor() {
|
||||||
|
TAB_ITEM("Title Screen")
|
||||||
|
END_TAB_ITEM()
|
||||||
|
}
|
||||||
|
void ScreenEditor::DrawNamingScreenEditor() {
|
||||||
|
TAB_ITEM("Naming Screen")
|
||||||
|
END_TAB_ITEM()
|
||||||
|
}
|
||||||
|
void ScreenEditor::DrawOverworldMapEditor() {
|
||||||
|
TAB_ITEM("Overworld Map")
|
||||||
|
END_TAB_ITEM()
|
||||||
|
}
|
||||||
|
void ScreenEditor::DrawDungeonMapsEditor() {
|
||||||
|
TAB_ITEM("Dungeon Maps")
|
||||||
|
END_TAB_ITEM()
|
||||||
|
}
|
||||||
|
|
||||||
void ScreenEditor::DrawMosaicEditor() {
|
void ScreenEditor::DrawMosaicEditor() {
|
||||||
TAB_ITEM("Mosaic Transitions")
|
TAB_ITEM("Mosaic Transitions")
|
||||||
|
|
||||||
@@ -84,7 +142,7 @@ void ScreenEditor::DrawMosaicEditor() {
|
|||||||
gui::InputHex("Routine Location", &overworldCustomMosaicASM);
|
gui::InputHex("Routine Location", &overworldCustomMosaicASM);
|
||||||
|
|
||||||
if (ImGui::Button("Generate Mosaic Assembly")) {
|
if (ImGui::Button("Generate Mosaic Assembly")) {
|
||||||
auto mosaic = mosaic_script_.GenerateMosaicChangeAssembly(
|
auto mosaic = mosaic_script_.PatchOverworldMosaic(
|
||||||
rom_, mosaic_tiles_, overworldCustomMosaicASM);
|
rom_, mosaic_tiles_, overworldCustomMosaicASM);
|
||||||
if (!mosaic.ok()) {
|
if (!mosaic.ok()) {
|
||||||
std::cout << mosaic;
|
std::cout << mosaic;
|
||||||
@@ -94,39 +152,6 @@ void ScreenEditor::DrawMosaicEditor() {
|
|||||||
END_TAB_ITEM()
|
END_TAB_ITEM()
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenEditor::DrawTitleScreenEditor() {
|
|
||||||
TAB_ITEM("Title Screen")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
void ScreenEditor::DrawNamingScreenEditor() {
|
|
||||||
TAB_ITEM("Naming Screen")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
void ScreenEditor::DrawOverworldMapEditor() {
|
|
||||||
TAB_ITEM("Overworld Map")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
void ScreenEditor::DrawDungeonMapsEditor() {
|
|
||||||
TAB_ITEM("Dungeon Maps")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
void ScreenEditor::DrawGameMenuEditor() {
|
|
||||||
TAB_ITEM("Game Menu")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
void ScreenEditor::DrawHUDEditor() {
|
|
||||||
TAB_ITEM("Heads-up Display")
|
|
||||||
END_TAB_ITEM()
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenEditor::DrawCanvas() {
|
|
||||||
screen_canvas_.DrawBackground();
|
|
||||||
screen_canvas_.DrawContextMenu();
|
|
||||||
|
|
||||||
screen_canvas_.DrawGrid();
|
|
||||||
screen_canvas_.DrawOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ScreenEditor::DrawToolset() {
|
void ScreenEditor::DrawToolset() {
|
||||||
static bool show_bg1 = true;
|
static bool show_bg1 = true;
|
||||||
static bool show_bg2 = true;
|
static bool show_bg2 = true;
|
||||||
@@ -147,6 +172,30 @@ void ScreenEditor::DrawToolset() {
|
|||||||
ImGui::Checkbox("Draw BG3", &drawing_bg3);
|
ImGui::Checkbox("Draw BG3", &drawing_bg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenEditor::DrawInventoryToolset() {
|
||||||
|
if (ImGui::BeginTable("InventoryToolset", 8, ImGuiTableFlags_SizingFixedFit, ImVec2(0, 0))) {
|
||||||
|
ImGui::TableSetupColumn("#drawTool");
|
||||||
|
ImGui::TableSetupColumn("#sep1");
|
||||||
|
ImGui::TableSetupColumn("#zoomOut");
|
||||||
|
ImGui::TableSetupColumn("#zoomIN");
|
||||||
|
ImGui::TableSetupColumn("#sep2");
|
||||||
|
ImGui::TableSetupColumn("#bg2Tool");
|
||||||
|
ImGui::TableSetupColumn("#bg3Tool");
|
||||||
|
ImGui::TableSetupColumn("#itemTool");
|
||||||
|
|
||||||
|
BUTTON_COLUMN(ICON_MD_UNDO)
|
||||||
|
BUTTON_COLUMN(ICON_MD_REDO)
|
||||||
|
TEXT_COLUMN(ICON_MD_MORE_VERT)
|
||||||
|
BUTTON_COLUMN(ICON_MD_ZOOM_OUT)
|
||||||
|
BUTTON_COLUMN(ICON_MD_ZOOM_IN)
|
||||||
|
TEXT_COLUMN(ICON_MD_MORE_VERT)
|
||||||
|
BUTTON_COLUMN(ICON_MD_DRAW)
|
||||||
|
BUTTON_COLUMN(ICON_MD_BUILD)
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -9,9 +9,12 @@
|
|||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
#include "app/zelda3/screen.h"
|
#include "app/zelda3/inventory.h"
|
||||||
#include "gui/canvas.h"
|
#include "gui/canvas.h"
|
||||||
|
#include "gui/icons.h"
|
||||||
|
#include "gui/color.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace app {
|
namespace app {
|
||||||
@@ -19,12 +22,14 @@ namespace editor {
|
|||||||
|
|
||||||
using MosaicArray = std::array<int, core::kNumOverworldMaps>;
|
using MosaicArray = std::array<int, core::kNumOverworldMaps>;
|
||||||
static int overworldCustomMosaicASM = 0x1301D0;
|
static int overworldCustomMosaicASM = 0x1301D0;
|
||||||
static int overworldCustomMosaicArray = 0x1301F0;
|
|
||||||
|
|
||||||
class ScreenEditor {
|
class ScreenEditor {
|
||||||
public:
|
public:
|
||||||
ScreenEditor();
|
ScreenEditor();
|
||||||
void SetupROM(ROM &rom) { rom_ = rom; }
|
void SetupROM(ROM &rom) {
|
||||||
|
rom_ = rom;
|
||||||
|
inventory_.SetupROM(rom_);
|
||||||
|
}
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -33,19 +38,21 @@ class ScreenEditor {
|
|||||||
void DrawNamingScreenEditor();
|
void DrawNamingScreenEditor();
|
||||||
void DrawOverworldMapEditor();
|
void DrawOverworldMapEditor();
|
||||||
void DrawDungeonMapsEditor();
|
void DrawDungeonMapsEditor();
|
||||||
void DrawGameMenuEditor();
|
void DrawInventoryMenuEditor();
|
||||||
void DrawHUDEditor();
|
|
||||||
|
|
||||||
void DrawCanvas();
|
|
||||||
void DrawToolset();
|
void DrawToolset();
|
||||||
|
void DrawInventoryToolset();
|
||||||
void DrawWorldGrid(int world, int h = 8, int w = 8);
|
void DrawWorldGrid(int world, int h = 8, int w = 8);
|
||||||
|
|
||||||
char mosaic_tiles_[core::kNumOverworldMaps];
|
char mosaic_tiles_[core::kNumOverworldMaps];
|
||||||
|
|
||||||
ROM rom_;
|
ROM rom_;
|
||||||
|
Bytes all_gfx_;
|
||||||
|
zelda3::Inventory inventory_;
|
||||||
|
gfx::SNESPalette palette_;
|
||||||
snes_asm::Script mosaic_script_;
|
snes_asm::Script mosaic_script_;
|
||||||
zelda3::Screen current_screen_;
|
|
||||||
gui::Canvas screen_canvas_;
|
gui::Canvas screen_canvas_;
|
||||||
|
gui::Canvas tilesheet_canvas_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ void Bitmap::Create(int width, int height, int depth, uchar *data) {
|
|||||||
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
||||||
SDL_PIXELFORMAT_INDEX8),
|
SDL_PIXELFORMAT_INDEX8),
|
||||||
SDL_Surface_Deleter());
|
SDL_Surface_Deleter());
|
||||||
GrayscalePalette(surface_->format->palette);
|
|
||||||
surface_->pixels = pixel_data_;
|
surface_->pixels = pixel_data_;
|
||||||
|
GrayscalePalette(surface_->format->palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserves data to later draw to surface via pointer
|
// Reserves data to later draw to surface via pointer
|
||||||
@@ -57,13 +57,14 @@ void Bitmap::Create(int width, int height, int depth, int size) {
|
|||||||
height_ = height;
|
height_ = height;
|
||||||
depth_ = depth;
|
depth_ = depth;
|
||||||
data_size_ = size;
|
data_size_ = size;
|
||||||
|
data_.reserve(size);
|
||||||
|
pixel_data_ = data_.data();
|
||||||
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
|
surface_ = std::unique_ptr<SDL_Surface, SDL_Surface_Deleter>(
|
||||||
SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
|
SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
|
||||||
SDL_PIXELFORMAT_INDEX8),
|
SDL_PIXELFORMAT_INDEX8),
|
||||||
SDL_Surface_Deleter());
|
SDL_Surface_Deleter());
|
||||||
GrayscalePalette(surface_->format->palette);
|
|
||||||
pixel_data_ = (uchar *)SDL_malloc(size);
|
|
||||||
surface_->pixels = pixel_data_;
|
surface_->pixels = pixel_data_;
|
||||||
|
GrayscalePalette(surface_->format->palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass raw pixel data directly to the surface
|
// Pass raw pixel data directly to the surface
|
||||||
@@ -103,68 +104,21 @@ void Bitmap::CreateTexture(std::shared_ptr<SDL_Renderer> renderer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert SNESPalette to SDL_Palette for surface.
|
// Convert SNESPalette to SDL_Palette for surface.
|
||||||
void Bitmap::ApplyPalette(const SNESPalette & palette) {
|
void Bitmap::ApplyPalette(const SNESPalette &palette) {
|
||||||
palette_ = palette;
|
palette_ = palette;
|
||||||
SDL_SetPaletteColors(surface_->format->palette,
|
for (int i = 0; i < palette.size_; ++i) {
|
||||||
palette_.GetSDL_Palette()->colors,
|
if (palette.GetColor(i).transparent) {
|
||||||
0, 256);
|
surface_->format->palette->colors[i].r = 0;
|
||||||
}
|
surface_->format->palette->colors[i].g = 0;
|
||||||
|
surface_->format->palette->colors[i].b = 0;
|
||||||
void Bitmap::SetPaletteColor(int id, gfx::SNESColor color) {
|
surface_->format->palette->colors[i].a = 0;
|
||||||
surface_->format->palette->colors[id].r = color.rgb.x;
|
} else {
|
||||||
surface_->format->palette->colors[id].g = color.rgb.y;
|
surface_->format->palette->colors[i].r = palette.GetColor(i).rgb.x;
|
||||||
surface_->format->palette->colors[id].b = color.rgb.z;
|
surface_->format->palette->colors[i].g = palette.GetColor(i).rgb.y;
|
||||||
}
|
surface_->format->palette->colors[i].b = palette.GetColor(i).rgb.z;
|
||||||
|
surface_->format->palette->colors[i].a = palette.GetColor(i).rgb.w;
|
||||||
// Creates a vector of bitmaps which are individual 8x8 tiles.
|
|
||||||
absl::StatusOr<std::vector<Bitmap>> Bitmap::CreateTiles() {
|
|
||||||
std::vector<Bitmap> tiles;
|
|
||||||
for (int i = 0; i < 16; ++i) {
|
|
||||||
for (int j = 0; j < 4; ++j) {
|
|
||||||
Bitmap bmp;
|
|
||||||
bmp.Create(8, 8, 8, 32);
|
|
||||||
auto surface = bmp.GetSurface();
|
|
||||||
SDL_Rect src_rect = {i, j, 8, 8};
|
|
||||||
if (SDL_BlitSurface(surface_.get(), &src_rect, surface, nullptr) != 0)
|
|
||||||
return absl::InternalError(
|
|
||||||
absl::StrCat("Failed to blit surface: ", SDL_GetError()));
|
|
||||||
tiles.push_back(bmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a vector of 8x8 tiles into a tilesheet.
|
|
||||||
absl::Status Bitmap::CreateFromTiles(const std::vector<Bitmap> &tiles) {
|
|
||||||
if (tiles.empty())
|
|
||||||
return absl::InvalidArgumentError(
|
|
||||||
"Failed to create bitmap: `tiles` is empty.");
|
|
||||||
|
|
||||||
SDL_Rect tile_rect = {0, 0, 8, 8};
|
|
||||||
SDL_Rect dest_rect = {0, 0, 8, 8};
|
|
||||||
for (const auto &tile : tiles) {
|
|
||||||
auto src = tile.GetSurface();
|
|
||||||
if (SDL_BlitSurface(src, &tile_rect, surface_.get(), &dest_rect) != 0)
|
|
||||||
return absl::InternalError(
|
|
||||||
absl::StrCat("Failed to blit surface: ", SDL_GetError()));
|
|
||||||
|
|
||||||
dest_rect.x++;
|
|
||||||
if (dest_rect.x == 15) {
|
|
||||||
dest_rect.x = 0;
|
|
||||||
dest_rect.y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::Status Bitmap::WritePixel(int pos, uchar pixel) {
|
|
||||||
if (!surface_) {
|
|
||||||
return absl::InternalError("Surface not loaded");
|
|
||||||
}
|
|
||||||
auto pixels = (char *)surface_->pixels;
|
|
||||||
pixels[pos] = pixel;
|
|
||||||
return absl::OkStatus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|||||||
@@ -31,12 +31,6 @@ class Bitmap {
|
|||||||
void CreateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
void CreateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
||||||
|
|
||||||
void ApplyPalette(const SNESPalette &palette);
|
void ApplyPalette(const SNESPalette &palette);
|
||||||
void SetPaletteColor(int id, gfx::SNESColor color);
|
|
||||||
|
|
||||||
absl::StatusOr<std::vector<Bitmap>> CreateTiles();
|
|
||||||
absl::Status CreateFromTiles(const std::vector<Bitmap> &tiles);
|
|
||||||
|
|
||||||
absl::Status WritePixel(int pos, uchar pixel);
|
|
||||||
|
|
||||||
int GetWidth() const { return width_; }
|
int GetWidth() const { return width_; }
|
||||||
int GetHeight() const { return height_; }
|
int GetHeight() const { return height_; }
|
||||||
@@ -59,6 +53,7 @@ class Bitmap {
|
|||||||
struct SDL_Surface_Deleter {
|
struct SDL_Surface_Deleter {
|
||||||
void operator()(SDL_Surface *p) const {
|
void operator()(SDL_Surface *p) const {
|
||||||
if (p != nullptr) {
|
if (p != nullptr) {
|
||||||
|
p->pixels = nullptr;
|
||||||
SDL_FreeSurface(p);
|
SDL_FreeSurface(p);
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
#include "pseudo_vram.h"
|
|
||||||
|
|
||||||
namespace yaze {
|
|
||||||
namespace app {
|
|
||||||
namespace gfx {
|
|
||||||
|
|
||||||
void pseudo_vram::ChangeGraphicsTileset(
|
|
||||||
const std::vector<Bitmap>& graphics_set) {}
|
|
||||||
|
|
||||||
void pseudo_vram::ChangeGraphicsPalette(const SNESPalette& graphics_pal) {}
|
|
||||||
|
|
||||||
void pseudo_vram::ChangeSpriteTileset(const std::vector<Bitmap>& sprite_set) {}
|
|
||||||
|
|
||||||
void pseudo_vram::ChangeSpritePalette(const SNESPalette& sprite_pal) {}
|
|
||||||
|
|
||||||
std::vector<Bitmap> CreateGraphicsSet(
|
|
||||||
int id, const std::unordered_map<int, Bitmap>& all_graphics) {
|
|
||||||
std::vector<Bitmap> graphics_set;
|
|
||||||
return graphics_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Bitmap> CreateSpriteSet(
|
|
||||||
int id, const std::unordered_map<int, Bitmap>& all_graphics) {
|
|
||||||
std::vector<Bitmap> graphics_set;
|
|
||||||
return graphics_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace gfx
|
|
||||||
} // namespace app
|
|
||||||
} // namespace yaze
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#ifndef YAZE_APP_GFX_PSEUDO_VRAM_H
|
|
||||||
#define YAZE_APP_GFX_PSEUDO_VRAM_H
|
|
||||||
|
|
||||||
#include <SDL.h>
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "app/gfx/bitmap.h"
|
|
||||||
#include "app/gfx/snes_palette.h"
|
|
||||||
#include "app/gfx/snes_tile.h"
|
|
||||||
|
|
||||||
namespace yaze {
|
|
||||||
namespace app {
|
|
||||||
namespace gfx {
|
|
||||||
|
|
||||||
// VRAM: 64 KB of VRAM for screen maps and tile sets (backgrounds and objects)
|
|
||||||
// OAM: 512 + 32 bytes for objects (Object Attribute Memory)
|
|
||||||
// CGRAM: 512 bytes for palette data
|
|
||||||
// Palette: 256 entries; 15-Bit color (BGR555) for a total of 32,768 colors.
|
|
||||||
// Resolution: between 256x224 and 512x448.
|
|
||||||
|
|
||||||
class pseudo_vram {
|
|
||||||
public:
|
|
||||||
void ChangeGraphicsTileset(const std::vector<Bitmap>& graphics_set);
|
|
||||||
void ChangeGraphicsPalette(const SNESPalette& graphics_pal);
|
|
||||||
void ChangeSpriteTileset(const std::vector<Bitmap>& sprite_set);
|
|
||||||
void ChangeSpritePalette(const SNESPalette& sprite_pal);
|
|
||||||
|
|
||||||
auto GetTileset(int index) const { return m_vram.at(index); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const uint32_t REAL_VRAM_SIZE = 0x8000;
|
|
||||||
std::unordered_map<int, Bitmap> m_vram;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Bitmap> CreateGraphicsSet(
|
|
||||||
int id, const std::unordered_map<int, Bitmap>& all_graphics);
|
|
||||||
std::vector<Bitmap> CreateSpriteSet(
|
|
||||||
int id, const std::unordered_map<int, Bitmap>& all_graphics);
|
|
||||||
|
|
||||||
} // namespace gfx
|
|
||||||
} // namespace app
|
|
||||||
} // namespace yaze
|
|
||||||
|
|
||||||
#endif // YAZE_APP_GFX_PSEUDO_VRAM_H
|
|
||||||
@@ -66,8 +66,8 @@ SNESColor::SNESColor() : rgb(ImVec4(0.f, 0.f, 0.f, 0.f)) {}
|
|||||||
|
|
||||||
SNESColor::SNESColor(snes_color val) {
|
SNESColor::SNESColor(snes_color val) {
|
||||||
rgb.x = val.red;
|
rgb.x = val.red;
|
||||||
rgb.y = val.blue;
|
rgb.y = val.green;
|
||||||
rgb.z = val.green;
|
rgb.z = val.blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
SNESColor::SNESColor(ImVec4 val) : rgb(val) {
|
SNESColor::SNESColor(ImVec4 val) : rgb(val) {
|
||||||
@@ -88,13 +88,13 @@ void SNESColor::setRgb(ImVec4 val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SNESColor::setSNES(snes_color val) {
|
void SNESColor::setSNES(snes_color val) {
|
||||||
rgb = ImVec4(val.red, val.green, val.blue, 1.f);
|
rgb = ImVec4(val.red, val.green, val.blue, 255.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SNESColor::setSNES(uint16_t val) {
|
void SNESColor::setSNES(uint16_t val) {
|
||||||
snes = val;
|
snes = val;
|
||||||
snes_color col = ConvertSNEStoRGB(val);
|
snes_color col = ConvertSNEStoRGB(val);
|
||||||
rgb = ImVec4(col.red, col.green, col.blue, 1.f);
|
rgb = ImVec4(col.red, col.green, col.blue, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -45,7 +45,13 @@ struct SNESColor {
|
|||||||
void setRgb(ImVec4);
|
void setRgb(ImVec4);
|
||||||
void setSNES(snes_color);
|
void setSNES(snes_color);
|
||||||
void setSNES(uint16_t);
|
void setSNES(uint16_t);
|
||||||
|
void setTransparent(bool t) { transparent = t; }
|
||||||
|
|
||||||
|
auto RGB() {
|
||||||
|
return ImVec4(rgb.x / 255, rgb.y / 255, rgb.z / 255, rgb.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool transparent = false;
|
||||||
uint16_t snes = 0;
|
uint16_t snes = 0;
|
||||||
ImVec4 rgb;
|
ImVec4 rgb;
|
||||||
};
|
};
|
||||||
|
|||||||
246
src/app/rom.cc
246
src/app/rom.cc
@@ -20,61 +20,10 @@
|
|||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
|
|
||||||
#define COMPRESSION_STRING_MOD 7 << 5
|
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace app {
|
namespace app {
|
||||||
|
|
||||||
namespace {
|
namespace lc_lz2 {
|
||||||
|
|
||||||
int GetGraphicsAddress(const uchar* data, uint8_t offset) {
|
|
||||||
auto part_one = data[kOverworldGraphicsPos1 + offset] << 16;
|
|
||||||
auto part_two = data[kOverworldGraphicsPos2 + offset] << 8;
|
|
||||||
auto part_three = data[kOverworldGraphicsPos3 + offset];
|
|
||||||
auto snes_addr = (part_one | part_two | part_three);
|
|
||||||
return core::SnesToPc(snes_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bytes SNES3bppTo8bppSheet(Bytes sheet) {
|
|
||||||
Bytes sheet_buffer_out(0x1000);
|
|
||||||
int xx = 0; // positions where we are at on the sheet
|
|
||||||
int yy = 0;
|
|
||||||
int pos = 0;
|
|
||||||
int ypos = 0;
|
|
||||||
|
|
||||||
// for each tiles, 16 per line
|
|
||||||
for (int i = 0; i < 64; i++) {
|
|
||||||
// for each line
|
|
||||||
for (int y = 0; y < 8; y++) {
|
|
||||||
//[0] + [1] + [16]
|
|
||||||
for (int x = 0; x < 8; x++) {
|
|
||||||
auto b1 = ((sheet[(y * 2) + (24 * pos)] & (kGraphicsBitmap[x])));
|
|
||||||
auto b2 = (sheet[((y * 2) + (24 * pos)) + 1] & (kGraphicsBitmap[x]));
|
|
||||||
auto b3 = (sheet[(16 + y) + (24 * pos)] & (kGraphicsBitmap[x]));
|
|
||||||
unsigned char b = 0;
|
|
||||||
if (b1 != 0) {
|
|
||||||
b |= 1;
|
|
||||||
}
|
|
||||||
if (b2 != 0) {
|
|
||||||
b |= 2;
|
|
||||||
}
|
|
||||||
if (b3 != 0) {
|
|
||||||
b |= 4;
|
|
||||||
}
|
|
||||||
sheet_buffer_out[x + (xx) + (y * 128) + (yy * 1024)] = b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pos++;
|
|
||||||
ypos++;
|
|
||||||
xx += 8;
|
|
||||||
if (ypos >= 16) {
|
|
||||||
yy++;
|
|
||||||
xx = 0;
|
|
||||||
ypos = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sheet_buffer_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintCompressionPiece(const std::shared_ptr<CompressionPiece>& piece) {
|
void PrintCompressionPiece(const std::shared_ptr<CompressionPiece>& piece) {
|
||||||
printf("Command: %d\n", piece->command);
|
printf("Command: %d\n", piece->command);
|
||||||
@@ -298,8 +247,7 @@ Bytes CreateCompressionString(std::shared_ptr<CompressionPiece>& start,
|
|||||||
pos++;
|
pos++;
|
||||||
} else {
|
} else {
|
||||||
if (piece->length <= kMaxLengthCompression) {
|
if (piece->length <= kMaxLengthCompression) {
|
||||||
output.push_back((COMPRESSION_STRING_MOD) |
|
output.push_back(kCompressionStringMod | ((uchar)piece->command << 2) |
|
||||||
((uchar)piece->command << 2) |
|
|
||||||
(((piece->length - 1) & 0xFF00) >> 8));
|
(((piece->length - 1) & 0xFF00) >> 8));
|
||||||
pos++;
|
pos++;
|
||||||
printf("Building extended header : cmd: %d, length: %d - %02X\n",
|
printf("Building extended header : cmd: %d, length: %d - %02X\n",
|
||||||
@@ -354,7 +302,7 @@ absl::Status ValidateCompressionResult(
|
|||||||
RETURN_IF_ERROR(temp_rom.LoadFromBytes(
|
RETURN_IF_ERROR(temp_rom.LoadFromBytes(
|
||||||
CreateCompressionString(compressed_chain_start->next, mode)))
|
CreateCompressionString(compressed_chain_start->next, mode)))
|
||||||
ASSIGN_OR_RETURN(auto decomp_data,
|
ASSIGN_OR_RETURN(auto decomp_data,
|
||||||
temp_rom.Decompress(0, temp_rom.GetSize()))
|
temp_rom.Decompress(0, temp_rom.size()))
|
||||||
if (!std::equal(decomp_data.begin() + start, decomp_data.end(),
|
if (!std::equal(decomp_data.begin() + start, decomp_data.end(),
|
||||||
temp_rom.begin())) {
|
temp_rom.begin())) {
|
||||||
return absl::InternalError(absl::StrFormat(
|
return absl::InternalError(absl::StrFormat(
|
||||||
@@ -392,6 +340,65 @@ std::shared_ptr<CompressionPiece> MergeCopy(
|
|||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace lc_lz2
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
int GetGraphicsAddress(const uchar* data, uint8_t offset) {
|
||||||
|
auto part_one = data[kOverworldGraphicsPos1 + offset] << 16;
|
||||||
|
auto part_two = data[kOverworldGraphicsPos2 + offset] << 8;
|
||||||
|
auto part_three = data[kOverworldGraphicsPos3 + offset];
|
||||||
|
auto snes_addr = (part_one | part_two | part_three);
|
||||||
|
return core::SnesToPc(snes_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bytes SnesTo8bppSheet(Bytes sheet, int bpp) {
|
||||||
|
int xx = 0; // positions where we are at on the sheet
|
||||||
|
int yy = 0;
|
||||||
|
int pos = 0;
|
||||||
|
int ypos = 0;
|
||||||
|
int num_tiles = 64;
|
||||||
|
int buffer_size = 0x1000;
|
||||||
|
if (bpp == 2) {
|
||||||
|
bpp = 16;
|
||||||
|
num_tiles = 128;
|
||||||
|
buffer_size = 0x2000;
|
||||||
|
} else if (bpp == 3) {
|
||||||
|
bpp = 24;
|
||||||
|
}
|
||||||
|
Bytes sheet_buffer_out(buffer_size);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_tiles; i++) { // for each tiles, 16 per line
|
||||||
|
for (int y = 0; y < 8; y++) { // for each line
|
||||||
|
for (int x = 0; x < 8; x++) { //[0] + [1] + [16]
|
||||||
|
auto b1 = ((sheet[(y * 2) + (bpp * pos)] & (kGraphicsBitmap[x])));
|
||||||
|
auto b2 = (sheet[((y * 2) + (bpp * pos)) + 1] & (kGraphicsBitmap[x]));
|
||||||
|
auto b3 = (sheet[(16 + y) + (bpp * pos)] & (kGraphicsBitmap[x]));
|
||||||
|
unsigned char b = 0;
|
||||||
|
if (b1 != 0) {
|
||||||
|
b |= 1;
|
||||||
|
}
|
||||||
|
if (b2 != 0) {
|
||||||
|
b |= 2;
|
||||||
|
}
|
||||||
|
if (b3 != 0 && bpp != 16) {
|
||||||
|
b |= 4;
|
||||||
|
}
|
||||||
|
sheet_buffer_out[x + (xx) + (y * 128) + (yy * 1024)] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
ypos++;
|
||||||
|
xx += 8;
|
||||||
|
if (ypos >= 16) {
|
||||||
|
yy++;
|
||||||
|
xx = 0;
|
||||||
|
ypos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sheet_buffer_out;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// TODO TEST compressed data border for each cmd
|
// TODO TEST compressed data border for each cmd
|
||||||
@@ -413,18 +420,19 @@ absl::StatusOr<Bytes> ROM::Compress(const int start, const int length, int mode,
|
|||||||
data_size_taken.fill({});
|
data_size_taken.fill({});
|
||||||
cmd_args.fill({{}});
|
cmd_args.fill({{}});
|
||||||
|
|
||||||
CheckByteRepeat(rom_data_.data(), data_size_taken, cmd_args, src_data_pos,
|
lc_lz2::CheckByteRepeat(rom_data_.data(), data_size_taken, cmd_args,
|
||||||
last_pos);
|
src_data_pos, last_pos);
|
||||||
CheckWordRepeat(rom_data_.data(), data_size_taken, cmd_args, src_data_pos,
|
lc_lz2::CheckWordRepeat(rom_data_.data(), data_size_taken, cmd_args,
|
||||||
last_pos);
|
src_data_pos, last_pos);
|
||||||
CheckIncByte(rom_data_.data(), data_size_taken, cmd_args, src_data_pos,
|
lc_lz2::CheckIncByte(rom_data_.data(), data_size_taken, cmd_args,
|
||||||
last_pos);
|
src_data_pos, last_pos);
|
||||||
CheckIntraCopy(rom_data_.data(), data_size_taken, cmd_args, src_data_pos,
|
lc_lz2::CheckIntraCopy(rom_data_.data(), data_size_taken, cmd_args,
|
||||||
last_pos, start);
|
src_data_pos, last_pos, start);
|
||||||
|
|
||||||
uint max_win = 2;
|
uint max_win = 2;
|
||||||
uint cmd_with_max = kCommandDirectCopy;
|
uint cmd_with_max = kCommandDirectCopy;
|
||||||
ValidateForByteGain(data_size_taken, cmd_size, max_win, cmd_with_max);
|
lc_lz2::ValidateForByteGain(data_size_taken, cmd_size, max_win,
|
||||||
|
cmd_with_max);
|
||||||
|
|
||||||
if (cmd_with_max == kCommandDirectCopy) {
|
if (cmd_with_max == kCommandDirectCopy) {
|
||||||
// This is the worst case scenario
|
// This is the worst case scenario
|
||||||
@@ -446,10 +454,9 @@ absl::StatusOr<Bytes> ROM::Compress(const int start, const int length, int mode,
|
|||||||
comp_accumulator = 0;
|
comp_accumulator = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Anything is better than directly copying bytes...
|
lc_lz2::CompressionCommandAlternative(
|
||||||
CompressionCommandAlternative(rom_data_.data(), compressed_chain,
|
rom_data_.data(), compressed_chain, cmd_size, cmd_args, src_data_pos,
|
||||||
cmd_size, cmd_args, src_data_pos,
|
comp_accumulator, cmd_with_max, max_win);
|
||||||
comp_accumulator, cmd_with_max, max_win);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src_data_pos > last_pos) {
|
if (src_data_pos > last_pos) {
|
||||||
@@ -458,14 +465,15 @@ absl::StatusOr<Bytes> ROM::Compress(const int start, const int length, int mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (check) {
|
if (check) {
|
||||||
RETURN_IF_ERROR(ValidateCompressionResult(compressed_chain_start, mode,
|
RETURN_IF_ERROR(lc_lz2::ValidateCompressionResult(
|
||||||
start, src_data_pos))
|
compressed_chain_start, mode, start, src_data_pos))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MergeCopy(compressed_chain_start->next); // Skipping compression chain header
|
// Skipping compression chain header
|
||||||
PrintCompressionChain(compressed_chain_start);
|
lc_lz2::MergeCopy(compressed_chain_start->next);
|
||||||
return CreateCompressionString(compressed_chain_start->next, mode);
|
lc_lz2::PrintCompressionChain(compressed_chain_start);
|
||||||
|
return lc_lz2::CreateCompressionString(compressed_chain_start->next, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::StatusOr<Bytes> ROM::CompressGraphics(const int pos, const int length) {
|
absl::StatusOr<Bytes> ROM::CompressGraphics(const int pos, const int length) {
|
||||||
@@ -503,10 +511,8 @@ absl::StatusOr<Bytes> ROM::Decompress(int offset, int size, int mode) {
|
|||||||
offset += length;
|
offset += length;
|
||||||
break;
|
break;
|
||||||
case kCommandByteFill:
|
case kCommandByteFill:
|
||||||
for (int i = 0; i < length; i++) {
|
memset(buffer.data() + buffer_pos, (int)(rom_data_[offset]), length);
|
||||||
buffer[buffer_pos] = rom_data_[offset];
|
buffer_pos += length;
|
||||||
buffer_pos++;
|
|
||||||
}
|
|
||||||
offset += 1; // Advances 1 byte in the ROM
|
offset += 1; // Advances 1 byte in the ROM
|
||||||
break;
|
break;
|
||||||
case kCommandWordFill: {
|
case kCommandWordFill: {
|
||||||
@@ -531,39 +537,27 @@ absl::StatusOr<Bytes> ROM::Decompress(int offset, int size, int mode) {
|
|||||||
ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8);
|
ushort s1 = ((rom_data_[offset + 1] & kSnesByteMax) << 8);
|
||||||
ushort s2 = ((rom_data_[offset] & kSnesByteMax));
|
ushort s2 = ((rom_data_[offset] & kSnesByteMax));
|
||||||
int addr = (s1 | s2);
|
int addr = (s1 | s2);
|
||||||
|
|
||||||
if (mode == kNintendoMode1) { // Reversed byte order for overworld maps
|
if (mode == kNintendoMode1) { // Reversed byte order for overworld maps
|
||||||
// addr = (s2 | s1);
|
addr = (rom_data_[offset + 1] & kSnesByteMax) |
|
||||||
addr = (rom_data_[offset + 1]) | ((rom_data_[offset]) << 8);
|
((rom_data_[offset] & kSnesByteMax) << 8);
|
||||||
memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length);
|
|
||||||
buffer_pos += length;
|
|
||||||
offset += 2;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr > offset) {
|
if (addr > offset) {
|
||||||
return absl::InternalError(absl::StrFormat(
|
return absl::InternalError(absl::StrFormat(
|
||||||
"DecompressOverworld: Offset for command copy exceeds "
|
"Decompress: Offset for command copy exceeds current position "
|
||||||
"current position (Offset : %#04x | Pos : %#06x)\n",
|
"(Offset : %#04x | Pos : %#06x)\n",
|
||||||
addr, offset));
|
addr, offset));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer_pos + length >= size) {
|
if (buffer_pos + length >= size) {
|
||||||
size *= 2;
|
size *= 2;
|
||||||
buffer.resize(size);
|
buffer.resize(size);
|
||||||
}
|
}
|
||||||
|
memcpy(buffer.data() + buffer_pos, buffer.data() + addr, length);
|
||||||
for (int i = 0; i < length; i++) {
|
buffer_pos += length;
|
||||||
buffer[buffer_pos] = buffer[addr + i];
|
offset += 2;
|
||||||
buffer_pos++;
|
|
||||||
}
|
|
||||||
offset += 2; // Advance 2 bytes in the ROM
|
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
std::cout << absl::StrFormat(
|
std::cout << absl::StrFormat(
|
||||||
"DecompressGraphics: Invalid command in header (Offset : %#06x, "
|
"Decompress: Invalid header (Offset : %#06x, Command: %#04x)\n",
|
||||||
"Command: %#04x)\n",
|
|
||||||
offset, command);
|
offset, command);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -582,6 +576,21 @@ absl::StatusOr<Bytes> ROM::DecompressOverworld(int pos, int size) {
|
|||||||
return Decompress(pos, size, kNintendoMode1);
|
return Decompress(pos, size, kNintendoMode1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::StatusOr<Bytes> ROM::Load2bppGraphics() {
|
||||||
|
Bytes sheet;
|
||||||
|
const uint8_t sheets[] = {113, 114, 218, 219, 220, 221};
|
||||||
|
|
||||||
|
for (const auto& sheet_id : sheets) {
|
||||||
|
auto offset = GetGraphicsAddress(rom_data_.data(), sheet_id);
|
||||||
|
ASSIGN_OR_RETURN(auto decomp_sheet, Decompress(offset))
|
||||||
|
auto converted_sheet = SnesTo8bppSheet(decomp_sheet, 2);
|
||||||
|
for (const auto& each_pixel : converted_sheet) {
|
||||||
|
sheet.push_back(each_pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sheet;
|
||||||
|
}
|
||||||
|
|
||||||
// 0-112 -> compressed 3bpp bgr -> (decompressed each) 0x600 chars
|
// 0-112 -> compressed 3bpp bgr -> (decompressed each) 0x600 chars
|
||||||
// 113-114 -> compressed 2bpp -> (decompressed each) 0x800 chars
|
// 113-114 -> compressed 2bpp -> (decompressed each) 0x800 chars
|
||||||
// 115-126 -> uncompressed 3bpp sprites -> (each) 0x600 chars
|
// 115-126 -> uncompressed 3bpp sprites -> (each) 0x600 chars
|
||||||
@@ -589,7 +598,7 @@ absl::StatusOr<Bytes> ROM::DecompressOverworld(int pos, int size) {
|
|||||||
// 218-222 -> compressed 2bpp -> (decompressed each) 0x800 chars
|
// 218-222 -> compressed 2bpp -> (decompressed each) 0x800 chars
|
||||||
absl::Status ROM::LoadAllGraphicsData() {
|
absl::Status ROM::LoadAllGraphicsData() {
|
||||||
Bytes sheet;
|
Bytes sheet;
|
||||||
bool convert = false;
|
bool bpp3 = false;
|
||||||
|
|
||||||
for (int i = 0; i < core::NumberOfSheets; i++) {
|
for (int i = 0; i < core::NumberOfSheets; i++) {
|
||||||
if (i >= 115 && i <= 126) { // uncompressed sheets
|
if (i >= 115 && i <= 126) { // uncompressed sheets
|
||||||
@@ -598,17 +607,17 @@ absl::Status ROM::LoadAllGraphicsData() {
|
|||||||
for (int j = 0; j < core::Uncompressed3BPPSize; j++) {
|
for (int j = 0; j < core::Uncompressed3BPPSize; j++) {
|
||||||
sheet[j] = rom_data_[j + offset];
|
sheet[j] = rom_data_[j + offset];
|
||||||
}
|
}
|
||||||
convert = true;
|
bpp3 = true;
|
||||||
} else if (i == 113 || i == 114 || i >= 218) {
|
} else if (i == 113 || i == 114 || i >= 218) {
|
||||||
convert = false;
|
bpp3 = false;
|
||||||
} else {
|
} else {
|
||||||
auto offset = GetGraphicsAddress(rom_data_.data(), i);
|
auto offset = GetGraphicsAddress(rom_data_.data(), i);
|
||||||
ASSIGN_OR_RETURN(sheet, Decompress(offset))
|
ASSIGN_OR_RETURN(sheet, Decompress(offset))
|
||||||
convert = true;
|
bpp3 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convert) {
|
if (bpp3) {
|
||||||
auto converted_sheet = SNES3bppTo8bppSheet(sheet);
|
auto converted_sheet = SnesTo8bppSheet(sheet, 3);
|
||||||
graphics_bin_[i] =
|
graphics_bin_[i] =
|
||||||
gfx::Bitmap(core::kTilesheetWidth, core::kTilesheetHeight,
|
gfx::Bitmap(core::kTilesheetWidth, core::kTilesheetHeight,
|
||||||
core::kTilesheetDepth, converted_sheet.data(), 0x1000);
|
core::kTilesheetDepth, converted_sheet.data(), 0x1000);
|
||||||
@@ -618,7 +627,7 @@ absl::Status ROM::LoadAllGraphicsData() {
|
|||||||
graphics_buffer_.push_back(graphics_bin_.at(i).GetByte(j));
|
graphics_buffer_.push_back(graphics_bin_.at(i).GetByte(j));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < 0x1000; ++j) {
|
for (int j = 0; j < graphics_bin_.at(0).GetSize(); ++j) {
|
||||||
graphics_buffer_.push_back(0xFF);
|
graphics_buffer_.push_back(0xFF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -687,7 +696,7 @@ void ROM::RenderBitmap(gfx::Bitmap* bitmap) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
gfx::SNESColor ROM::ReadColor(int offset) {
|
gfx::SNESColor ROM::ReadColor(int offset) {
|
||||||
short color = (short)((rom_data_[offset + 1] << 8) + rom_data_[offset]);
|
short color = toint16(offset);
|
||||||
gfx::snes_color new_color;
|
gfx::snes_color new_color;
|
||||||
new_color.red = (color & 0x1F) * 8;
|
new_color.red = (color & 0x1F) * 8;
|
||||||
new_color.green = ((color >> 5) & 0x1F) * 8;
|
new_color.green = ((color >> 5) & 0x1F) * 8;
|
||||||
@@ -701,7 +710,7 @@ gfx::SNESPalette ROM::ReadPalette(int offset, int num_colors) {
|
|||||||
std::vector<gfx::SNESColor> colors(num_colors);
|
std::vector<gfx::SNESColor> colors(num_colors);
|
||||||
|
|
||||||
while (color_offset < num_colors) {
|
while (color_offset < num_colors) {
|
||||||
short color = (short)((rom_data_[offset + 1] << 8) + rom_data_[offset]);
|
short color = toint16(offset);
|
||||||
gfx::snes_color new_color;
|
gfx::snes_color new_color;
|
||||||
new_color.red = (color & 0x1F) * 8;
|
new_color.red = (color & 0x1F) * 8;
|
||||||
new_color.green = ((color >> 5) & 0x1F) * 8;
|
new_color.green = ((color >> 5) & 0x1F) * 8;
|
||||||
@@ -783,31 +792,6 @@ void ROM::LoadAllPalettes() {
|
|||||||
palette_groups_["ow_mini_map"].AddPalette(
|
palette_groups_["ow_mini_map"].AddPalette(
|
||||||
ReadPalette(core::overworldMiniMapPalettes + (i * 256), 128));
|
ReadPalette(core::overworldMiniMapPalettes + (i * 256), 128));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check for the paletts in the empty bank space that kan will allocate
|
|
||||||
// and read them in here
|
|
||||||
// TODO magic colors
|
|
||||||
// LW
|
|
||||||
// int j = 0;
|
|
||||||
// while (j < 64) {
|
|
||||||
// zelda3::overworld_BackgroundPalette[j++] =
|
|
||||||
// Color.FromArgb(0xFF, 0x48, 0x98, 0x48);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // DW
|
|
||||||
// while (j < 128) {
|
|
||||||
// zelda3::overworld_BackgroundPalette[j++] =
|
|
||||||
// Color.FromArgb(0xFF, 0x90, 0x88, 0x50);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // SP
|
|
||||||
// while (j < core::kNumOverworldMaps) {
|
|
||||||
// zelda3::overworld_BackgroundPalette[j++] =
|
|
||||||
// Color.FromArgb(0xFF, 0x48, 0x98, 0x48);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// zelda3::overworld_BackgroundPalette =
|
|
||||||
// ReadPalette(core::customAreaSpecificBGPalette, 160);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
#include "absl/strings/str_cat.h"
|
#include "absl/strings/str_cat.h"
|
||||||
#include "absl/strings/str_format.h"
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "absl/strings/string_view.h"
|
||||||
#include "app/core/common.h"
|
#include "app/core/common.h"
|
||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
@@ -47,6 +48,7 @@ constexpr int kCommandMod = 0x07;
|
|||||||
constexpr int kExpandedMod = 0xE0;
|
constexpr int kExpandedMod = 0xE0;
|
||||||
constexpr int kExpandedLengthMod = 0x3FF;
|
constexpr int kExpandedLengthMod = 0x3FF;
|
||||||
constexpr int kNormalLengthMod = 0x1F;
|
constexpr int kNormalLengthMod = 0x1F;
|
||||||
|
constexpr int kCompressionStringMod = 7 << 5;
|
||||||
constexpr uchar kGraphicsBitmap[8] = {0x80, 0x40, 0x20, 0x10,
|
constexpr uchar kGraphicsBitmap[8] = {0x80, 0x40, 0x20, 0x10,
|
||||||
0x08, 0x04, 0x02, 0x01};
|
0x08, 0x04, 0x02, 0x01};
|
||||||
|
|
||||||
@@ -76,6 +78,8 @@ class ROM {
|
|||||||
absl::StatusOr<Bytes> DecompressGraphics(int pos, int size);
|
absl::StatusOr<Bytes> DecompressGraphics(int pos, int size);
|
||||||
absl::StatusOr<Bytes> DecompressOverworld(int pos, int size);
|
absl::StatusOr<Bytes> DecompressOverworld(int pos, int size);
|
||||||
|
|
||||||
|
absl::StatusOr<Bytes> Load2bppGraphics();
|
||||||
|
|
||||||
absl::Status LoadAllGraphicsData();
|
absl::Status LoadAllGraphicsData();
|
||||||
absl::Status LoadFromFile(const absl::string_view& filename);
|
absl::Status LoadFromFile(const absl::string_view& filename);
|
||||||
absl::Status LoadFromPointer(uchar* data, size_t length);
|
absl::Status LoadFromPointer(uchar* data, size_t length);
|
||||||
@@ -89,7 +93,6 @@ class ROM {
|
|||||||
|
|
||||||
void RenderBitmap(gfx::Bitmap* bitmap) const;
|
void RenderBitmap(gfx::Bitmap* bitmap) const;
|
||||||
|
|
||||||
auto GetSize() const { return size_; }
|
|
||||||
auto GetTitle() const { return title; }
|
auto GetTitle() const { return title; }
|
||||||
auto GetGraphicsBin() const { return graphics_bin_; }
|
auto GetGraphicsBin() const { return graphics_bin_; }
|
||||||
auto GetGraphicsBuffer() const { return graphics_buffer_; }
|
auto GetGraphicsBuffer() const { return graphics_buffer_; }
|
||||||
@@ -101,6 +104,7 @@ class ROM {
|
|||||||
auto begin() { return rom_data_.begin(); }
|
auto begin() { return rom_data_.begin(); }
|
||||||
auto end() { return rom_data_.end(); }
|
auto end() { return rom_data_.end(); }
|
||||||
auto data() { return rom_data_.data(); }
|
auto data() { return rom_data_.data(); }
|
||||||
|
auto size() const { return size_; }
|
||||||
|
|
||||||
uchar& operator[](int i) {
|
uchar& operator[](int i) {
|
||||||
if (i > size_) {
|
if (i > size_) {
|
||||||
|
|||||||
88
src/app/zelda3/inventory.cc
Normal file
88
src/app/zelda3/inventory.cc
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "gui/canvas.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace zelda3 {
|
||||||
|
void Inventory::Create() {
|
||||||
|
data_.reserve(256 * 256);
|
||||||
|
for (int i = 0; i < 256 * 256; i++) {
|
||||||
|
data_.push_back(0xFF);
|
||||||
|
}
|
||||||
|
PRINT_IF_ERROR(BuildTileset())
|
||||||
|
for (int i = 0; i < 0x400; i += 0x08) {
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos)));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x02)));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x04)));
|
||||||
|
tiles_.push_back(gfx::GetTilesInfo(rom_.toint16(i + kBowItemPos + 0x08)));
|
||||||
|
}
|
||||||
|
const int offsets[] = {0x00, 0x08, 0x800, 0x808};
|
||||||
|
auto xx = 0;
|
||||||
|
auto yy = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (const auto& tile : tiles_) {
|
||||||
|
int offset = offsets[i];
|
||||||
|
for (auto y = 0; y < 0x08; ++y) {
|
||||||
|
for (auto x = 0; x < 0x08; ++x) {
|
||||||
|
int mx = x;
|
||||||
|
int my = y;
|
||||||
|
|
||||||
|
if (tile.horizontal_mirror_ != 0) {
|
||||||
|
mx = 0x07 - x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tile.vertical_mirror_ != 0) {
|
||||||
|
my = 0x07 - y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xpos = ((tile.id_ % 0x10) * 0x08);
|
||||||
|
int ypos = (((tile.id_ / 0x10)) * 0x400);
|
||||||
|
int source = ypos + xpos + (x + (y * 0x80));
|
||||||
|
|
||||||
|
auto destination = xx + yy + offset + (mx + (my * 0x100));
|
||||||
|
data_[destination] = (test_[source] & 0x0F) + tile.palette_ * 0x08;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 4) {
|
||||||
|
i = 0;
|
||||||
|
xx += 0x10;
|
||||||
|
if (xx >= 0x100) {
|
||||||
|
yy += 0x1000;
|
||||||
|
xx = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bitmap_.Create(256, 256, 128, data_);
|
||||||
|
bitmap_.ApplyPalette(palette_);
|
||||||
|
rom_.RenderBitmap(&bitmap_);
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::Status Inventory::BuildTileset() {
|
||||||
|
tilesheets_.reserve(6 * 0x2000);
|
||||||
|
for (int i = 0; i < 6 * 0x2000; i++) tilesheets_.push_back(0xFF);
|
||||||
|
ASSIGN_OR_RETURN(tilesheets_, rom_.Load2bppGraphics())
|
||||||
|
Bytes test;
|
||||||
|
for (int i = 0; i < 0x4000; i++) {
|
||||||
|
test_.push_back(tilesheets_[i]);
|
||||||
|
}
|
||||||
|
for (int i = 0x8000; i < + 0x8000 + 0x2000; i++) {
|
||||||
|
test_.push_back(tilesheets_[i]);
|
||||||
|
}
|
||||||
|
tilesheets_bmp_.Create(128, 0x130, 64, test_);
|
||||||
|
palette_ = rom_.GetPaletteGroup("hud")[0];
|
||||||
|
tilesheets_bmp_.ApplyPalette(palette_);
|
||||||
|
rom_.RenderBitmap(&tilesheets_bmp_);
|
||||||
|
return absl::OkStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace zelda3
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
47
src/app/zelda3/inventory.h
Normal file
47
src/app/zelda3/inventory.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef YAZE_APP_ZELDA3_INVENTORY_H
|
||||||
|
#define YAZE_APP_ZELDA3_INVENTORY_H
|
||||||
|
|
||||||
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "gui/canvas.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace zelda3 {
|
||||||
|
|
||||||
|
constexpr int kInventoryStart = 0x6564A;
|
||||||
|
constexpr int kBowItemPos = 0x6F631;
|
||||||
|
|
||||||
|
class Inventory {
|
||||||
|
public:
|
||||||
|
void SetupROM(ROM& rom) { rom_ = rom; }
|
||||||
|
auto Bitmap() const { return bitmap_; }
|
||||||
|
auto Tilesheet() const { return tilesheets_bmp_; }
|
||||||
|
auto Palette() const { return palette_; }
|
||||||
|
|
||||||
|
void Create();
|
||||||
|
|
||||||
|
private:
|
||||||
|
absl::Status BuildTileset();
|
||||||
|
|
||||||
|
ROM rom_;
|
||||||
|
|
||||||
|
Bytes data_;
|
||||||
|
gfx::Bitmap bitmap_;
|
||||||
|
|
||||||
|
Bytes tilesheets_;
|
||||||
|
Bytes test_;
|
||||||
|
gfx::Bitmap tilesheets_bmp_;
|
||||||
|
gfx::SNESPalette palette_;
|
||||||
|
|
||||||
|
gui::Canvas canvas_;
|
||||||
|
std::vector<gfx::TileInfo> tiles_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zelda3
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -38,6 +38,8 @@ absl::Status Overworld::Load(ROM &rom) {
|
|||||||
overworld_maps_.emplace_back(map_index, rom_, tiles16);
|
overworld_maps_.emplace_back(map_index, rom_, tiles16);
|
||||||
|
|
||||||
FetchLargeMaps();
|
FetchLargeMaps();
|
||||||
|
LoadEntrances();
|
||||||
|
LoadSprites();
|
||||||
|
|
||||||
auto size = tiles16.size();
|
auto size = tiles16.size();
|
||||||
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
|
for (int i = 0; i < core::kNumOverworldMaps; ++i) {
|
||||||
@@ -194,8 +196,8 @@ void Overworld::FetchLargeMaps() {
|
|||||||
overworld_maps_[136].SetLargeMap(false);
|
overworld_maps_[136].SetLargeMap(false);
|
||||||
|
|
||||||
bool mapChecked[64];
|
bool mapChecked[64];
|
||||||
for (auto &each : mapChecked) {
|
for (int i = 0; i < 64; i++) {
|
||||||
each = false;
|
mapChecked[i] = false;
|
||||||
}
|
}
|
||||||
int xx = 0;
|
int xx = 0;
|
||||||
int yy = 0;
|
int yy = 0;
|
||||||
@@ -237,6 +239,148 @@ void Overworld::FetchLargeMaps() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Overworld::LoadEntrances() {
|
||||||
|
for (int i = 0; i < 129; i++) {
|
||||||
|
short mapId = rom_.toint16(core::OWEntranceMap + (i * 2));
|
||||||
|
ushort mapPos = rom_.toint16(core::OWEntrancePos + (i * 2));
|
||||||
|
uchar entranceId = (rom_[core::OWEntranceEntranceId + i]);
|
||||||
|
int p = mapPos >> 1;
|
||||||
|
int x = (p % 64);
|
||||||
|
int y = (p >> 6);
|
||||||
|
bool deleted = false;
|
||||||
|
if (mapPos == 0xFFFF) {
|
||||||
|
deleted = true;
|
||||||
|
}
|
||||||
|
all_entrances_.emplace_back(
|
||||||
|
(x * 16) + (((mapId % 64) - (((mapId % 64) / 8) * 8)) * 512),
|
||||||
|
(y * 16) + (((mapId % 64) / 8) * 512), entranceId, mapId, mapPos,
|
||||||
|
deleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 0x13; i++) {
|
||||||
|
short mapId = (short)((rom_[core::OWHoleArea + (i * 2) + 1] << 8) +
|
||||||
|
(rom_[core::OWHoleArea + (i * 2)]));
|
||||||
|
short mapPos = (short)((rom_[core::OWHolePos + (i * 2) + 1] << 8) +
|
||||||
|
(rom_[core::OWHolePos + (i * 2)]));
|
||||||
|
uchar entranceId = (rom_[core::OWHoleEntrance + i]);
|
||||||
|
int p = (mapPos + 0x400) >> 1;
|
||||||
|
int x = (p % 64);
|
||||||
|
int y = (p >> 6);
|
||||||
|
all_holes_.emplace_back(
|
||||||
|
(x * 16) + (((mapId % 64) - (((mapId % 64) / 8) * 8)) * 512),
|
||||||
|
(y * 16) + (((mapId % 64) / 8) * 512), entranceId, mapId,
|
||||||
|
(ushort)(mapPos + 0x400), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Overworld::LoadSprites() {
|
||||||
|
// LW[0] = RainState 0 to 63 there's no data for DW
|
||||||
|
// LW[1] = ZeldaState 0 to 128 ; Contains LW and DW <128 or 144 wtf
|
||||||
|
// LW[2] = AgahState 0 to ?? ;Contains data for LW and DW
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
all_sprites_.emplace_back(std::vector<Sprite>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Console.WriteLine(((core::overworldSpritesBegining & 0xFFFF) + (09 <<
|
||||||
|
// 16)).ToString("X6"));
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
if (map_parent_[i] == i) {
|
||||||
|
// Beginning Sprites
|
||||||
|
int ptrPos = core::overworldSpritesBegining + (i * 2);
|
||||||
|
int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos));
|
||||||
|
while (true) {
|
||||||
|
uchar b1 = rom_[spriteAddress];
|
||||||
|
uchar b2 = rom_[spriteAddress + 1];
|
||||||
|
uchar b3 = rom_[spriteAddress + 2];
|
||||||
|
if (b1 == 0xFF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mapY = (i / 8);
|
||||||
|
int mapX = (i % 8);
|
||||||
|
|
||||||
|
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
||||||
|
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
||||||
|
|
||||||
|
all_sprites_[0].emplace_back(overworld_maps_[i].AreaGraphics(),
|
||||||
|
(uchar)i, b3, (uchar)(b2 & 0x3F),
|
||||||
|
(uchar)(b1 & 0x3F), realX, realY);
|
||||||
|
|
||||||
|
spriteAddress += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 144; i++) {
|
||||||
|
if (map_parent_[i] == i) {
|
||||||
|
// Zelda Saved Sprites
|
||||||
|
int ptrPos = core::overworldSpritesZelda + (i * 2);
|
||||||
|
int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos));
|
||||||
|
while (true) {
|
||||||
|
uchar b1 = rom_[spriteAddress];
|
||||||
|
uchar b2 = rom_[spriteAddress + 1];
|
||||||
|
uchar b3 = rom_[spriteAddress + 2];
|
||||||
|
if (b1 == 0xFF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editorMapIndex = i;
|
||||||
|
if (editorMapIndex >= 128) {
|
||||||
|
editorMapIndex = i - 128;
|
||||||
|
} else if (editorMapIndex >= 64) {
|
||||||
|
editorMapIndex = i - 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mapY = (editorMapIndex / 8);
|
||||||
|
int mapX = (editorMapIndex % 8);
|
||||||
|
|
||||||
|
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
||||||
|
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
||||||
|
|
||||||
|
all_sprites_[1].emplace_back(overworld_maps_[i].AreaGraphics(),
|
||||||
|
(uchar)i, b3, (uchar)(b2 & 0x3F),
|
||||||
|
(uchar)(b1 & 0x3F), realX, realY);
|
||||||
|
|
||||||
|
spriteAddress += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agahnim Dead Sprites
|
||||||
|
if (map_parent_[i] == i) {
|
||||||
|
int ptrPos = core::overworldSpritesAgahnim + (i * 2);
|
||||||
|
int spriteAddress = core::SnesToPc((0x09 << 0x10) + rom_.toint16(ptrPos));
|
||||||
|
while (true) {
|
||||||
|
uchar b1 = rom_[spriteAddress];
|
||||||
|
uchar b2 = rom_[spriteAddress + 1];
|
||||||
|
uchar b3 = rom_[spriteAddress + 2];
|
||||||
|
if (b1 == 0xFF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int editorMapIndex = i;
|
||||||
|
if (editorMapIndex >= 128) {
|
||||||
|
editorMapIndex = i - 128;
|
||||||
|
} else if (editorMapIndex >= 64) {
|
||||||
|
editorMapIndex = i - 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mapY = (editorMapIndex / 8);
|
||||||
|
int mapX = (editorMapIndex % 8);
|
||||||
|
|
||||||
|
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
||||||
|
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
||||||
|
|
||||||
|
all_sprites_[2].emplace_back(overworld_maps_[i].AreaGraphics(),
|
||||||
|
(uchar)i, b3, (uchar)(b2 & 0x3F),
|
||||||
|
(uchar)(b1 & 0x3F), realX, realY);
|
||||||
|
|
||||||
|
spriteAddress += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace zelda3
|
} // namespace zelda3
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -9,33 +9,88 @@
|
|||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/pseudo_vram.h"
|
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
#include "app/zelda3/overworld_map.h"
|
#include "app/zelda3/overworld_map.h"
|
||||||
|
#include "app/zelda3/sprite.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace zelda3 {
|
namespace zelda3 {
|
||||||
|
|
||||||
|
class OverworldEntrance {
|
||||||
|
public:
|
||||||
|
int x_;
|
||||||
|
int y_;
|
||||||
|
ushort mapPos;
|
||||||
|
uchar entranceId_, AreaX, AreaY;
|
||||||
|
short mapId_;
|
||||||
|
bool isHole = false;
|
||||||
|
bool deleted = false;
|
||||||
|
|
||||||
|
OverworldEntrance(int x, int y, uchar entranceId, short mapId, ushort mapPos,
|
||||||
|
bool hole) {
|
||||||
|
x_ = x;
|
||||||
|
y_ = y;
|
||||||
|
entranceId_ = entranceId;
|
||||||
|
mapId_ = mapId;
|
||||||
|
mapPos = mapPos;
|
||||||
|
|
||||||
|
int mapX = (mapId_ - ((mapId / 8) * 8));
|
||||||
|
int mapY = (mapId_ / 8);
|
||||||
|
|
||||||
|
AreaX = (uchar)((std::abs(x - (mapX * 512)) / 16));
|
||||||
|
AreaY = (uchar)((std::abs(y - (mapY * 512)) / 16));
|
||||||
|
|
||||||
|
isHole = hole;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Copy() {
|
||||||
|
return new OverworldEntrance(x_, y_, entranceId_, mapId_, mapPos, isHole);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateMapStuff(short mapId) {
|
||||||
|
mapId_ = mapId;
|
||||||
|
|
||||||
|
if (mapId_ >= 64) {
|
||||||
|
mapId_ -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mapX = (mapId_ - ((mapId_ / 8) * 8));
|
||||||
|
int mapY = (mapId_ / 8);
|
||||||
|
|
||||||
|
AreaX = (uchar)((std::abs(x_ - (mapX * 512)) / 16));
|
||||||
|
AreaY = (uchar)((std::abs(y_ - (mapY * 512)) / 16));
|
||||||
|
|
||||||
|
int mx = (mapId_ - ((mapId_ / 8) * 8));
|
||||||
|
int my = (mapId_ / 8);
|
||||||
|
|
||||||
|
uchar xx = (uchar)((x_ - (mx * 512)) / 16);
|
||||||
|
uchar yy = (uchar)((y_ - (my * 512)) / 16);
|
||||||
|
|
||||||
|
mapPos = (ushort)((((AreaY) << 6) | (AreaX & 0x3F)) << 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Overworld {
|
class Overworld {
|
||||||
public:
|
public:
|
||||||
absl::Status Load(ROM &rom);
|
absl::Status Load(ROM &rom);
|
||||||
auto GetTiles16() const { return tiles16; }
|
auto GetTiles16() const { return tiles16; }
|
||||||
auto GetOverworldMap(uint index) { return overworld_maps_[index]; }
|
auto GetOverworldMap(uint index) { return overworld_maps_[index]; }
|
||||||
auto GetOverworldMaps() const { return overworld_maps_; }
|
auto GetOverworldMaps() const { return overworld_maps_; }
|
||||||
auto GetCurrentBlockset() const {
|
auto Sprites() const { return all_sprites_[game_state_]; }
|
||||||
return overworld_maps_[current_map_].GetCurrentBlockset();
|
auto AreaGraphics() const {
|
||||||
|
return overworld_maps_[current_map_].AreaGraphics();
|
||||||
}
|
}
|
||||||
auto GetCurrentGraphics() const {
|
auto Entrances() const { return all_entrances_; }
|
||||||
return overworld_maps_[current_map_].GetCurrentGraphics();
|
auto AreaPalette() const {
|
||||||
|
return overworld_maps_[current_map_].AreaPalette();
|
||||||
}
|
}
|
||||||
auto GetCurrentBitmapData() const {
|
auto BitmapData() const { return overworld_maps_[current_map_].BitmapData(); }
|
||||||
return overworld_maps_[current_map_].GetBitmapData();
|
auto Tile16Blockset() const {
|
||||||
}
|
return overworld_maps_[current_map_].Tile16Blockset();
|
||||||
auto GetCurrentPalette() const {
|
|
||||||
return overworld_maps_[current_map_].GetCurrentPalette();
|
|
||||||
}
|
}
|
||||||
|
auto GameState() const { return game_state_; }
|
||||||
auto isLoaded() const { return is_loaded_; }
|
auto isLoaded() const { return is_loaded_; }
|
||||||
void SetCurrentMap(int i) { current_map_ = i; }
|
void SetCurrentMap(int i) { current_map_ = i; }
|
||||||
|
|
||||||
@@ -58,9 +113,12 @@ class Overworld {
|
|||||||
int &ttpos);
|
int &ttpos);
|
||||||
absl::Status DecompressAllMapTiles();
|
absl::Status DecompressAllMapTiles();
|
||||||
void FetchLargeMaps();
|
void FetchLargeMaps();
|
||||||
|
void LoadEntrances();
|
||||||
|
void LoadSprites();
|
||||||
|
|
||||||
void LoadOverworldMap();
|
void LoadOverworldMap();
|
||||||
|
|
||||||
int game_state_ = 1;
|
int game_state_ = 0;
|
||||||
int current_map_ = 0;
|
int current_map_ = 0;
|
||||||
uchar map_parent_[160];
|
uchar map_parent_[160];
|
||||||
bool is_loaded_ = false;
|
bool is_loaded_ = false;
|
||||||
@@ -71,6 +129,9 @@ class Overworld {
|
|||||||
std::vector<gfx::Tile16> tiles16;
|
std::vector<gfx::Tile16> tiles16;
|
||||||
std::vector<gfx::Tile32> tiles32;
|
std::vector<gfx::Tile32> tiles32;
|
||||||
std::vector<OverworldMap> overworld_maps_;
|
std::vector<OverworldMap> overworld_maps_;
|
||||||
|
std::vector<OverworldEntrance> all_entrances_;
|
||||||
|
std::vector<OverworldEntrance> all_holes_;
|
||||||
|
std::vector<std::vector<Sprite>> all_sprites_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace zelda3
|
} // namespace zelda3
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
int k = 0;
|
int k = 0;
|
||||||
for (int y = 2; y < 7; y++) {
|
for (int y = 2; y < 7; y++) {
|
||||||
for (int x = 1; x < 8; x++) {
|
for (int x = 1; x < 8; x++) {
|
||||||
new_palette[x + (16 * y)] = main[k++];
|
new_palette[x + (16 * y)] = main[k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +62,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 2; y < 5; y++) {
|
for (int y = 2; y < 5; y++) {
|
||||||
for (int x = 9; x < 16; x++) {
|
for (int x = 9; x < 16; x++) {
|
||||||
new_palette[x + (16 * y)] = aux1[k++];
|
new_palette[x + (16 * y)] = aux1[k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +71,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 5; y < 8; y++) {
|
for (int y = 5; y < 8; y++) {
|
||||||
for (int x = 9; x < 16; x++) {
|
for (int x = 9; x < 16; x++) {
|
||||||
new_palette[x + (16 * y)] = aux2[k++];
|
new_palette[x + (16 * y)] = aux2[k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +91,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 8; y < 9; y++) {
|
for (int y = 8; y < 9; y++) {
|
||||||
for (int x = 1; x < 8; x++) {
|
for (int x = 1; x < 8; x++) {
|
||||||
new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux1")[1][k++];
|
new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux1")[1][k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +100,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 8; y < 9; y++) {
|
for (int y = 8; y < 9; y++) {
|
||||||
for (int x = 9; x < 16; x++) {
|
for (int x = 9; x < 16; x++) {
|
||||||
new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux3")[0][k++];
|
new_palette[x + (16 * y)] = rom.GetPaletteGroup("sprites_aux3")[0][k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +109,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 9; y < 13; y++) {
|
for (int y = 9; y < 13; y++) {
|
||||||
for (int x = 1; x < 16; x++) {
|
for (int x = 1; x < 16; x++) {
|
||||||
new_palette[x + (16 * y)] = rom.GetPaletteGroup("global_sprites")[0][k++];
|
new_palette[x + (16 * y)] = rom.GetPaletteGroup("global_sprites")[0][k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +118,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 13; y < 14; y++) {
|
for (int y = 13; y < 14; y++) {
|
||||||
for (int x = 1; x < 8; x++) {
|
for (int x = 1; x < 8; x++) {
|
||||||
new_palette[x + (16 * y)] = spr[k++];
|
new_palette[x + (16 * y)] = spr[k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +127,8 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 14; y < 15; y++) {
|
for (int y = 14; y < 15; y++) {
|
||||||
for (int x = 1; x < 8; x++) {
|
for (int x = 1; x < 8; x++) {
|
||||||
new_palette[x + (16 * y)] = spr2[k++];
|
new_palette[x + (16 * y)] = spr2[k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,21 +136,15 @@ void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int y = 15; y < 16; y++) {
|
for (int y = 15; y < 16; y++) {
|
||||||
for (int x = 1; x < 16; x++) {
|
for (int x = 1; x < 16; x++) {
|
||||||
new_palette[x + (16 * y)] = rom.GetPaletteGroup("armors")[0][k++];
|
new_palette[x + (16 * y)] = rom.GetPaletteGroup("armors")[0][k];
|
||||||
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
current.Create(new_palette);
|
current.Create(new_palette);
|
||||||
// ColorPalette pal = GFX.editort16Bitmap.Palette;
|
for (int i = 0; i < 256; i++) {
|
||||||
// for (int i = 0; i < 256; i++) {
|
current[(i / 16) * 16].setTransparent(true);
|
||||||
// pal.Entries[i] = new_palette[i];
|
}
|
||||||
// pal.Entries[(i / 16) * 16] = Color.Transparent;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// GFX.mapgfx16Bitmap.Palette = pal;
|
|
||||||
// GFX.mapblockset16Bitmap.Palette = pal;
|
|
||||||
|
|
||||||
// gfxBitmap.Palette = pal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -156,6 +158,7 @@ OverworldMap::OverworldMap(int index, ROM& rom,
|
|||||||
absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
||||||
uchar* map_parent,
|
uchar* map_parent,
|
||||||
OWBlockset& world_blockset) {
|
OWBlockset& world_blockset) {
|
||||||
|
game_state_ = game_state;
|
||||||
world_ = world;
|
world_ = world;
|
||||||
if (large_map_) {
|
if (large_map_) {
|
||||||
parent_ = map_parent[index_];
|
parent_ = map_parent[index_];
|
||||||
@@ -176,16 +179,7 @@ absl::Status OverworldMap::BuildMap(int count, int game_state, int world,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int world_index = 0x20;
|
LoadAreaGraphics();
|
||||||
if (parent_ < 0x40) {
|
|
||||||
world_index = 0x20;
|
|
||||||
} else if (parent_ >= 0x40 && parent_ < 0x80) {
|
|
||||||
world_index = 0x21;
|
|
||||||
} else if (parent_ == 0x88) {
|
|
||||||
world_index = 0x24;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadAreaGraphics(game_state, world_index);
|
|
||||||
RETURN_IF_ERROR(BuildTileset())
|
RETURN_IF_ERROR(BuildTileset())
|
||||||
RETURN_IF_ERROR(BuildTiles16Gfx(count))
|
RETURN_IF_ERROR(BuildTiles16Gfx(count))
|
||||||
LoadPalette();
|
LoadPalette();
|
||||||
@@ -273,7 +267,16 @@ void OverworldMap::LoadAreaInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldMap::LoadAreaGraphics(int game_state, int world_index) {
|
void OverworldMap::LoadAreaGraphics() {
|
||||||
|
int world_index = 0x20;
|
||||||
|
if (parent_ < 0x40) {
|
||||||
|
world_index = 0x20;
|
||||||
|
} else if (parent_ >= 0x40 && parent_ < 0x80) {
|
||||||
|
world_index = 0x21;
|
||||||
|
} else if (parent_ == 0x88) {
|
||||||
|
world_index = 0x24;
|
||||||
|
}
|
||||||
|
|
||||||
// Sprites Blocksets
|
// Sprites Blocksets
|
||||||
static_graphics_[8] = 0x73 + 0x00;
|
static_graphics_[8] = 0x73 + 0x00;
|
||||||
static_graphics_[9] = 0x73 + 0x01;
|
static_graphics_[9] = 0x73 + 0x01;
|
||||||
@@ -281,7 +284,7 @@ void OverworldMap::LoadAreaGraphics(int game_state, int world_index) {
|
|||||||
static_graphics_[11] = 0x73 + 0x07;
|
static_graphics_[11] = 0x73 + 0x07;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
static_graphics_[12 + i] = (rom_[core::kSpriteBlocksetPointer +
|
static_graphics_[12 + i] = (rom_[core::kSpriteBlocksetPointer +
|
||||||
(sprite_graphics_[game_state] * 4) + i] +
|
(sprite_graphics_[game_state_] * 4) + i] +
|
||||||
0x73);
|
0x73);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,8 +336,7 @@ void OverworldMap::LoadPalette() {
|
|||||||
|
|
||||||
uchar pal0 = 0;
|
uchar pal0 = 0;
|
||||||
|
|
||||||
uchar pal1 =
|
uchar pal1 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4)];
|
||||||
rom_[core::overworldMapPaletteGroup + (area_palette_ * 4)]; // aux1
|
|
||||||
uchar pal2 =
|
uchar pal2 =
|
||||||
rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1]; // aux2
|
rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) + 1]; // aux2
|
||||||
uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) +
|
uchar pal3 = rom_[core::overworldMapPaletteGroup + (area_palette_ * 4) +
|
||||||
@@ -387,7 +389,7 @@ void OverworldMap::LoadPalette() {
|
|||||||
if (parent_ < 0x40) {
|
if (parent_ < 0x40) {
|
||||||
// Default LW Palette
|
// Default LW Palette
|
||||||
pal0 = 0;
|
pal0 = 0;
|
||||||
|
bgr = rom_.GetPaletteGroup("grass")[0].GetColor(0);
|
||||||
if (parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07) {
|
if (parent_ == 0x03 || parent_ == 0x05 || parent_ == 0x07) {
|
||||||
pal0 = 2;
|
pal0 = 2;
|
||||||
}
|
}
|
||||||
@@ -457,8 +459,16 @@ absl::Status OverworldMap::BuildTileset() {
|
|||||||
|
|
||||||
for (int i = 0; i < 0x10; i++) {
|
for (int i = 0; i < 0x10; i++) {
|
||||||
for (int j = 0; j < 0x1000; j++) {
|
for (int j = 0; j < 0x1000; j++) {
|
||||||
current_gfx_[(i * 0x1000) + j] =
|
auto byte = all_gfx_[j + (static_graphics_[i] * 0x1000)];
|
||||||
all_gfx_[j + (static_graphics_[i] * 0x1000)];
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
byte += 0x88;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_gfx_[(i * 0x1000) + j] = byte;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return absl::OkStatus();
|
return absl::OkStatus();
|
||||||
@@ -496,7 +506,7 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) {
|
|||||||
|
|
||||||
auto destination = xx + yy + offset + (mx + (my * 0x80));
|
auto destination = xx + yy + offset + (mx + (my * 0x80));
|
||||||
current_blockset_[destination] =
|
current_blockset_[destination] =
|
||||||
current_gfx_[source] + (info.palette_ * 0x10);
|
(current_gfx_[source] & 0x0F) + (info.palette_ * 0x10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,18 +28,17 @@ class OverworldMap {
|
|||||||
absl::Status BuildMap(int count, int game_state, int world, uchar* map_parent,
|
absl::Status BuildMap(int count, int game_state, int world, uchar* map_parent,
|
||||||
OWBlockset& world_blockset);
|
OWBlockset& world_blockset);
|
||||||
|
|
||||||
auto GetCurrentBlockset() const { return current_blockset_; }
|
auto Tile16Blockset() const { return current_blockset_; }
|
||||||
auto GetCurrentGraphics() const { return current_gfx_; }
|
auto AreaGraphics() const { return current_gfx_; }
|
||||||
auto GetCurrentPalette() const { return current_palette_; }
|
auto AreaPalette() const { return current_palette_; }
|
||||||
auto GetBitmapData() const { return bitmap_data_; }
|
auto BitmapData() const { return bitmap_data_; }
|
||||||
auto SetLargeMap(bool is_set) { large_map_ = is_set; }
|
auto SetLargeMap(bool is_set) { large_map_ = is_set; }
|
||||||
auto IsLargeMap() const { return large_map_; }
|
auto IsLargeMap() const { return large_map_; }
|
||||||
auto IsInitialized() const { return initialized_; }
|
auto IsInitialized() const { return initialized_; }
|
||||||
auto IsBuilt() const { return built_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void LoadAreaInfo();
|
void LoadAreaInfo();
|
||||||
void LoadAreaGraphics(int game_state, int world_index);
|
void LoadAreaGraphics();
|
||||||
void LoadPalette();
|
void LoadPalette();
|
||||||
|
|
||||||
absl::Status BuildTileset();
|
absl::Status BuildTileset();
|
||||||
@@ -52,8 +51,6 @@ class OverworldMap {
|
|||||||
int message_id_ = 0;
|
int message_id_ = 0;
|
||||||
int area_graphics_ = 0;
|
int area_graphics_ = 0;
|
||||||
int area_palette_ = 0;
|
int area_palette_ = 0;
|
||||||
|
|
||||||
// TODO SET ME
|
|
||||||
int game_state_ = 0;
|
int game_state_ = 0;
|
||||||
|
|
||||||
uchar sprite_graphics_[3];
|
uchar sprite_graphics_[3];
|
||||||
|
|||||||
921
src/app/zelda3/sprite.cc
Normal file
921
src/app/zelda3/sprite.cc
Normal file
@@ -0,0 +1,921 @@
|
|||||||
|
#include "sprite.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace zelda3 {
|
||||||
|
|
||||||
|
Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x,
|
||||||
|
int map_y) {
|
||||||
|
current_gfx_ = src;
|
||||||
|
overworld_ = true;
|
||||||
|
map_id_ = mapid;
|
||||||
|
id_ = id;
|
||||||
|
x_ = x;
|
||||||
|
y_ = y;
|
||||||
|
nx_ = x;
|
||||||
|
ny_ = y;
|
||||||
|
name_ = core::kSpriteDefaultNames[id];
|
||||||
|
map_x_ = map_x;
|
||||||
|
map_y_ = map_y;
|
||||||
|
preview_gfx_.reserve(64 * 64);
|
||||||
|
for (int i = 0; i < 64 * 64; i++) {
|
||||||
|
preview_gfx_.push_back(0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::updateBBox() {
|
||||||
|
lowerX_ = 1;
|
||||||
|
lowerY_ = 1;
|
||||||
|
higherX_ = 15;
|
||||||
|
higherY_ = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::Draw(bool picker) {
|
||||||
|
uchar x = nx_;
|
||||||
|
uchar y = ny_;
|
||||||
|
picker_ = picker;
|
||||||
|
|
||||||
|
if (overlord_ == 0x07) {
|
||||||
|
if (id_ == 0x1A) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 6, 11); // bomb
|
||||||
|
} else if (id_ == 0x05) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 12, 12, 16, 12, false, true);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 12, false, true);
|
||||||
|
} else if (id_ == 0x06) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 26, 14, true, true, 2,
|
||||||
|
2); // snek
|
||||||
|
} else if (id_ == 0x09) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 26, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 8, 26, 14);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 10, 27, 14, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x14) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 12, 06, 12, false, false, 2,
|
||||||
|
1); // shadow tile
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 3, 29, 8, false, false, 1,
|
||||||
|
1); // tile
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 3, 29, 8, true, false, 1,
|
||||||
|
1); // tile
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 3, 29, 8, false, true, 1,
|
||||||
|
1); // tile
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16), 3, 29, 8, true, true, 1,
|
||||||
|
1); // tile
|
||||||
|
} else {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 4, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nx_ != x || ny_ != y) {
|
||||||
|
bounding_box_.x = (lowerX_ + (nx_ * 16));
|
||||||
|
bounding_box_.y = (lowerY_ + (ny_ * 16));
|
||||||
|
bounding_box_.w = width_;
|
||||||
|
bounding_box_.h = height_;
|
||||||
|
} else {
|
||||||
|
bounding_box_.x = (lowerX_ + (x * 16));
|
||||||
|
bounding_box_.y = (lowerY_ + (y * 16));
|
||||||
|
bounding_box_.w = width_;
|
||||||
|
bounding_box_.h = height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id_ == 0x00) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 28, 10);
|
||||||
|
} else if (id_ == 0x01) {
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16), 6, 24, 12, false, false, 2, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16), 6, 24, 12, true, false, 2, 2);
|
||||||
|
} else if (id_ == 0x02) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
|
||||||
|
} else if (id_ == 0x04) {
|
||||||
|
uchar p = 3;
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
|
||||||
|
} else if (id_ == 0x05) {
|
||||||
|
uchar p = 3;
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
|
||||||
|
} else if (id_ == 0x06) {
|
||||||
|
uchar p = 3;
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
|
||||||
|
} else if (id_ == 0x07) {
|
||||||
|
uchar p = 3;
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 28, p);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 30, p);
|
||||||
|
} else if (id_ == 0x08) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 6);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 6, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x09) {
|
||||||
|
DrawSpriteTile((x * 16) - 22, (y * 16) - 24, 12, 24, 12, false, false, 2,
|
||||||
|
2); // Moldorm tail
|
||||||
|
DrawSpriteTile((x * 16) - 16, (y * 16) - 20, 8, 24, 12, false, false, 2,
|
||||||
|
2); // Moldorm b2
|
||||||
|
DrawSpriteTile((x * 16) - 12, (y * 16) - 16, 4, 24, 12, false, false, 4,
|
||||||
|
4); // Moldorm b
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 12, false, false, 4,
|
||||||
|
4); // Moldorm head
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) + 20, (y * 16) + 12, 8, 26, 14, false, false, 2,
|
||||||
|
2); // Moldorm eye
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 20, 8, 26, 14, false, false, 2,
|
||||||
|
2); // Moldorm eye
|
||||||
|
} else if (id_ == 0x0A) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 8);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 8, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x0B) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 30, 10);
|
||||||
|
} else if (id_ == 0x0C) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 8);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 6, 0, 24, 8, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x0D) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 28, 12);
|
||||||
|
} else if (id_ == 0x0E) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 18, 10, false, false, 3, 2);
|
||||||
|
} else if (id_ == 0x0F) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 8, false, false, 2, 3);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 30, 8, 8, true, false, 1, 3);
|
||||||
|
} else if (id_ == 0x10) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 31, 8, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x11) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 6, 16, 8, false, false, 2,
|
||||||
|
2); // Feet
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 4, 18, 8, false, false, 2,
|
||||||
|
2); // Body1
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 4, 18, 8, true, false, 2,
|
||||||
|
2); // Body2
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 8, false, false, 2,
|
||||||
|
2); // Head
|
||||||
|
} else if (id_ == 0x12) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 8, 26, 8);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 24, 8);
|
||||||
|
} else if (id_ == 0x13) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 22, 2);
|
||||||
|
} else if (id_ == 0x15) {
|
||||||
|
// Antifairy
|
||||||
|
DrawSpriteTile((x * 16) + 2, (y * 16) + 8, 3, 30, 5, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 2, 3, 30, 5, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 14, (y * 16) + 8, 3, 30, 5, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 14, 3, 30, 5, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 1, 30, 5, false, false, 1,
|
||||||
|
1); // Middle
|
||||||
|
} else if (id_ == 0x16) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 2, 26, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 2);
|
||||||
|
} else if (id_ == 0x17) // Bush hoarder
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 30, 10);
|
||||||
|
} else if (id_ == 0x18) // Mini moldorm
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 13, (y * 16) + 17, 13, 21, 8, false, false, 1,
|
||||||
|
1); // Tail
|
||||||
|
DrawSpriteTile((x * 16) + 5, (y * 16) + 8, 2, 22, 8); // Body
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 22, 8); // Head
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 4, 13, 20, 8, false, false, 1,
|
||||||
|
1); // Eyes
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16), 13, 20, 8, false, false, 1,
|
||||||
|
1); // Eyes
|
||||||
|
} else if (id_ == 0x19) // Poe - ghost
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 31, 2); //
|
||||||
|
} else if (id_ == 0x1A) // Smith
|
||||||
|
{
|
||||||
|
// DrawSpriteTile((x*16), (y *16), 2, 4, 10,true); // Smitty
|
||||||
|
// DrawSpriteTile((x*16)+12, (y *16) - 7, 0, 6, 10); // Hammer
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 22, 10);
|
||||||
|
} else if (id_ == 0x1C) // Statue
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 0, 28, 15);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 28, 15, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16), 2, 28, 15, true, false, 1, 1);
|
||||||
|
} else if (id_ == 0x1E) // Crystal switch
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 30, 5);
|
||||||
|
} else if (id_ == 0x1F) // Sick kid
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 10, 16, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 16 - 8, (y * 16) + 8, 10, 16, 14, true);
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 16, 10, 16, 14, false, true, 2, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 16 - 8, (y * 16) + 16, 10, 16, 14, true, true, 2,
|
||||||
|
2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 4, 14, 16, 10);
|
||||||
|
} else if (id_ == 0x20) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 24, 7);
|
||||||
|
} else if (id_ == 0x21) // Push switch
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 20, 13, 29, 3, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 28, 12, 29, 3, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 10, 28, 3);
|
||||||
|
} else if (id_ == 0x22) // Rope
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 26, 5);
|
||||||
|
} else if (id_ == 0x23) // Red bari
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 18, 4, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16), 2, 18, 4, true, false, 1, 2);
|
||||||
|
} else if (id_ == 0x24) // Blue bari
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 18, 6, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16), 2, 18, 6, true, false, 1, 2);
|
||||||
|
} else if (id_ == 0x25) // Talking tree?
|
||||||
|
{
|
||||||
|
// TODO: Add something here?
|
||||||
|
} else if (id_ == 0x26) // Hardhat beetle
|
||||||
|
{
|
||||||
|
if ((x & 0x01) == 0x00) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 20, 8);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 6, 0, 20, 8);
|
||||||
|
} else {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 20, 10);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 6, 0, 20, 10);
|
||||||
|
}
|
||||||
|
} else if (id_ == 0x27) // Deadrock
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 30, 10);
|
||||||
|
} else if (id_ == 0x28) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x29) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x2A) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x2B) // ???
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x2C) // Lumberjack
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 24, (y * 16) + 12, 6, 26, 12, true); // Body
|
||||||
|
DrawSpriteTile((x * 16) - 24, (y * 16), 8, 26, 12, true); // Head
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) - 14, (y * 16) + 12, 14, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) - 6, (y * 16) + 12, 15, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) + 2, (y * 16) + 12, 15, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) + 10, (y * 16) + 12, 15, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) + 18, (y * 16) + 12, 15, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) + 26, (y * 16) + 12, 15, 27, 10, false, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
DrawSpriteTile((x * 16) + 34, (y * 16) + 12, 14, 27, 10, true, false, 1,
|
||||||
|
1); // Saw left edge
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) + 40, (y * 16) + 12, 4, 26, 12); // Body
|
||||||
|
DrawSpriteTile((x * 16) + 40, (y * 16), 8, 26, 12); // Head
|
||||||
|
} else if (id_ == 0x2D) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x2E) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x2F) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x30) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x31) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x32) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else if (id_== 0x33) // Pull for rupees
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else if (id_ == 0x34) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x35) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x36) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else if (id_== 0x37) // Waterfall
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x*16), (y *16), 14, 6, 10);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
else if (id_ == 0x38) // Arrowtarget
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x39) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x3A) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x3B) // Dash item
|
||||||
|
{
|
||||||
|
} else if (id_ == 0x3C) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x3D) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x3E) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x3F) // Npcs
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 22, 10);
|
||||||
|
} else if (id_ == 0x40) // Lightning lock (agah tower)
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 24, (y * 16), 10, 28, 2, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) - 16, (y * 16), 6, 30, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 30, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 6, 30, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 24, (y * 16), 10, 28, 2, false, false, 1, 2);
|
||||||
|
} else if (id_ == 0x41) // Blue soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 10, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 10);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 10, false, false, 1,
|
||||||
|
2); // Shield
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 14, 22, 10, false, true, 1,
|
||||||
|
2); // Sword
|
||||||
|
} else if (id_ == 0x42) // Green soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 12, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 12, false, false, 1,
|
||||||
|
2); // Shield
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 14, 22, 12, false, true, 1,
|
||||||
|
2); // Sword
|
||||||
|
} else if (id_ == 0x43) // Red spear soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 8, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 8);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 8, false, false, 1,
|
||||||
|
2); // Shield
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 11, 22, 8, false, true, 1,
|
||||||
|
2); // Spear
|
||||||
|
} else if (id_ == 0x44) // Sword blue holding up
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 10);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 10); // Head
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 14, 22, 10, false, true, 1,
|
||||||
|
2); // Sword
|
||||||
|
} else if (id_ == 0x45) // Green spear soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 12, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 13, 22, 12, false, false, 1,
|
||||||
|
2); // Shield
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 16, 11, 22, 12, false, true, 1,
|
||||||
|
2); // Spear
|
||||||
|
} else if (id_ == 0x46) // Blue archer
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 10);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 6, 20, 10, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 10); // Head
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 10, 16, 10, false, false, 1,
|
||||||
|
1); // Bow1
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 10, 16, 10, true, false, 1,
|
||||||
|
1); // Bow2
|
||||||
|
} else if (id_ == 0x47) // Green archer
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 14, 16, 12);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 10, 16, 12, false, false, 1,
|
||||||
|
1); // Bow1
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 10, 16, 12, true, false, 1,
|
||||||
|
1); // Bow2
|
||||||
|
} else if (id_ == 0x48) // Javelin soldier red
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 8); // Head
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 11, 22, 8, false, true, 1,
|
||||||
|
2); // Sword
|
||||||
|
} else if (id_ == 0x49) // Javelin soldier red from bush
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 18, 8); // Head
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 24, 0, 20, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 11, 22, 8, false, true, 1,
|
||||||
|
2); // Sword
|
||||||
|
} else if (id_ == 0x4A) // Red bomb soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 8);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 8, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 8); // Head
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 14, 22, 11); // Bomb
|
||||||
|
} else if (id_ == 0x4B) // Green soldier recruit
|
||||||
|
{
|
||||||
|
// 0,4
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 24, 12);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 10, 0, 20, 12);
|
||||||
|
} else if (id_ == 0x4C) // Jazzhand
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 14, false, false, 6, 2);
|
||||||
|
} else if (id_ == 0x4D) // Rabit??
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 12, false, false, 6, 2);
|
||||||
|
} else if (id_ == 0x4E) // Popo1
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 10);
|
||||||
|
} else if (id_ == 0x4F) // Popo2
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 20, 10);
|
||||||
|
} else if (id_ == 0x50) // Canon ball
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 10);
|
||||||
|
} else if (id_ == 0x51) // Armos
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 28, 11, false, false, 2, 4);
|
||||||
|
} else if (id_ == 0x53) // Armos Knight
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 28, 10, false, false, 4, 4);
|
||||||
|
} else if (id_ == 0x54) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 2, 28, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 10, 6, 28, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 18, 10, 28, 12);
|
||||||
|
} else if (id_ == 0x55) // Fireball Zora
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 26, 11);
|
||||||
|
} else if (id_ == 0x56) // Zora
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 20, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 8, 30, 2);
|
||||||
|
} else if (id_ == 0x57) // Desert Rocks
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 2, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 14, 24, 2, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0x58) // Crab
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 14, 24, 12, true);
|
||||||
|
} else if (id_ == 0x5B) // Spark
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 18, 4);
|
||||||
|
} else if (id_ == 0x5C) // Spark
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 18, 4, true);
|
||||||
|
} else if (id_ == 0x5D) // Roller vertical1
|
||||||
|
{
|
||||||
|
// Subset3
|
||||||
|
if (((y * 16) & 0x10) == 0x10) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
DrawSpriteTile((x * 16) + 8 + (i * 16), (y * 16), 9, 24, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) + (16 * 7), (y * 16), 8, 24, 11, true);
|
||||||
|
} else {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 9, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 32, (y * 16), 9, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 48, (y * 16), 8, 24, 11, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (id_ == 0x5E) // Roller vertical2
|
||||||
|
{
|
||||||
|
// Subset3
|
||||||
|
if (((y * 16) & 0x10) == 0x10) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
|
||||||
|
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
DrawSpriteTile((x * 16) + 8 + (i * 16), (y * 16), 9, 24, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) + (16 * 7), (y * 16), 8, 24, 11, true);
|
||||||
|
} else {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 9, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 32, (y * 16), 9, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 48, (y * 16), 8, 24, 11, true);
|
||||||
|
}
|
||||||
|
} else if (id_ == 0x5F) // Roller horizontal
|
||||||
|
{
|
||||||
|
if (((x * 16) & 0x10) == 0x10) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 14, 25, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 32, 14, 25, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 48, 14, 24, 11, false, true);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + i * 16, 14, 25, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + (7 * 16), 14, 24, 11, false, true);
|
||||||
|
}
|
||||||
|
} else if (id_ == 0x60) // Roller horizontal2 (right to left)
|
||||||
|
{
|
||||||
|
// Subset3
|
||||||
|
if (((x * 16) & 0x10) == 0x10) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 14, 25, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 32, 14, 25, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 48, 14, 24, 11, false, true);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + i * 16, 14, 25, 11);
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + (7 * 16), 14, 24, 11, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (id_ == 0x61) // Beamos
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 16, 8, 20, 14, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 10, 20, 14, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x63) // Devalant non-shooter
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) - 8, 2, 16, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 2, 16, 2, true);
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 2, 16, 2, false, true);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 2, 16, 2, true, true);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
|
||||||
|
} else if (id_ == 0x64) // Devalant non-shooter
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) - 8, 2, 16, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) - 8, 2, 16, 2, true);
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 2, 16, 2, false, true);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 2, 16, 2, true, true);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 8);
|
||||||
|
} else if (id_ == 0x66) // Moving wall canon right
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 16, 14, true);
|
||||||
|
} else if (id_ == 0x67) // Moving wall canon right
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 16, 14);
|
||||||
|
} else if (id_ == 0x68) // Moving wall canon right
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 16, 14);
|
||||||
|
} else if (id_ == 0x69) // Moving wall canon right
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 16, 14, false, true);
|
||||||
|
} else if (id_ == 0x6A) // Chainball soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 14);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 14, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 14); // Head
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) - 16, 10, 18, 14); // Ball
|
||||||
|
} else if (id_ == 0x6B) // Cannon soldier
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 6, 16, 14);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 8, 6, 20, 14, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 14); // Head
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 8, 4, 18, 14); // Cannon
|
||||||
|
} else if (id_ == 0x6C) // Mirror portal
|
||||||
|
{
|
||||||
|
// Useless
|
||||||
|
} else if (id_ == 0x6D) // Rat
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 5);
|
||||||
|
} else if (id_ == 0x6E) // Rope
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 26, 5);
|
||||||
|
} else if (id_ == 0x6F) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 24, 10);
|
||||||
|
} else if (id_ == 0x70) // Helma fireball
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 28, 4);
|
||||||
|
} else if (id_ == 0x71) // Leever
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 16, 4);
|
||||||
|
} else if (id_ == 0x73) // Uncle priest
|
||||||
|
{
|
||||||
|
} else if (id_ == 0x79) // Bee
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 14, 11, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x7A) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 16, 2, 24, 12, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 2, 24, 12, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0x7C) // Skull head
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
|
||||||
|
} else if (id_ == 0x7D) // Big spike
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 28, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 4, 28, 11, true);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 4, 28, 11, false, true);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 16, 4, 28, 11, true, true);
|
||||||
|
} else if (id_ == 0x7E) // Guruguru clockwise
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 14, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 28, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 42, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 56, 8, 18, 4);
|
||||||
|
} else if (id_ == 0x7F) // Guruguru Counterclockwise
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 14, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 28, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 42, 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 56, 8, 18, 4);
|
||||||
|
} else if (id_ == 0x80) // Winder (moving firebar)
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16) - 14, (y * 16), 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16) - 28, (y * 16), 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16) - 42, (y * 16), 8, 18, 4);
|
||||||
|
DrawSpriteTile((x * 16) - 56, (y * 16), 8, 18, 4);
|
||||||
|
} else if (id_ == 0x81) // Water tektite
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 11);
|
||||||
|
} else if (id_ == 0x82) // circle antifairy
|
||||||
|
{
|
||||||
|
// Antifairy top
|
||||||
|
DrawSpriteTile((x * 16 + 2) - 4, (y * 16 + 8) - 16, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 2) - 16, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 14) - 4, (y * 16 + 8) - 16, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 14) - 16, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 8) - 16, 1, 30, 5, false, false,
|
||||||
|
1, 1); // Middle
|
||||||
|
// Left
|
||||||
|
DrawSpriteTile((x * 16 + 2) - 16, (y * 16 + 8) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 2) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 14) - 16, (y * 16 + 8) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 14) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 16, (y * 16 + 8) - 4, 1, 30, 5, false, false,
|
||||||
|
1, 1); // Middle
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16 + 2) - 4, (y * 16 + 8) + 8, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 2) + 8, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 14) - 4, (y * 16 + 8) + 8, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 14) + 8, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) - 4, (y * 16 + 8) + 8, 1, 30, 5, false, false,
|
||||||
|
1, 1); // Middle
|
||||||
|
// Left
|
||||||
|
DrawSpriteTile((x * 16 + 2) + 8, (y * 16 + 8) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 2) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 14) + 8, (y * 16 + 8) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 14) - 4, 3, 30, 5, false, false,
|
||||||
|
1, 1);
|
||||||
|
DrawSpriteTile((x * 16 + 8) + 8, (y * 16 + 8) - 4, 1, 30, 5, false, false,
|
||||||
|
1, 1); // Middle
|
||||||
|
} else if (id_ == 0x83) // Green eyegore
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 24, 14, false, false, 2, 3);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 14, true, false, 1, 3);
|
||||||
|
} else if (id_ == 0x84) // Red eyegore
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 24, 8, false, false, 2, 3);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 8, true, false, 1, 3);
|
||||||
|
} else if (id_ == 0x85) // Yellow stalfos
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 16, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 12, 0, 16, 11); // Head
|
||||||
|
} else if (id_ == 0x86) // Kodongo
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 26, 14);
|
||||||
|
} else if (id_ == 0x88) // Mothula
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 24, 14, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 8, 24, 14, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0x8A) // Spike
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 30, 15);
|
||||||
|
} else if (id_ == 0x8B) // Gibdo
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 24, 14);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 0, 24, 14);
|
||||||
|
} else if (id_ == 0x8C) // Arrghus
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 24, 14, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 0, 24, 14, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0x8D) // Arrghus spawn
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 24, 14);
|
||||||
|
} else if (id_ == 0x8E) // Terrorpin
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 24, 12);
|
||||||
|
} else if (id_ == 0x8F) // Slime
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 20, 12);
|
||||||
|
} else if (id_ == 0x90) // Wall master
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 26, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 15, 26, 12, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 8, 9, 26, 12, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 10, 27, 12, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 16, 8, 27, 12, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0x91) // Stalfos knight
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) - 2, (y * 16) + 12, 4, 22, 12, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 10, (y * 16) + 12, 4, 22, 12, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16) + 4, 1, 22, 12);
|
||||||
|
DrawSpriteTile((x * 16) + 12, (y * 16) + 4, 3, 22, 12, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 6, 20, 12);
|
||||||
|
} else if (id_ == 0x92) // Helmaking
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 32, 14, 26, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 32, 0, 28, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 32, (y * 16) + 32, 14, 26, 14, true);
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16 + 32, 2, 28, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 16 + 32, 4, 28, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 32, (y * 16) + 16 + 32, 2, 28, 14, true);
|
||||||
|
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 32 + 32, 6, 28, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 24, (y * 16) + 32 + 32, 6, 28, 14, true);
|
||||||
|
} else if (id_ == 0x93) // Bumper
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 30, 7);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 12, 30, 7, true);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) + 16, 12, 30, 7, true, true);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 12, 30, 7, false, true);
|
||||||
|
} else if (id_ == 0x95) // Right laser eye
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 9, 28, 3, true, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 16, 9, 28, 3, true, true, 1, 1);
|
||||||
|
} else if (id_ == 0x96) // Left laser eye
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) - 4, 9, 28, 3, false, false, 1, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 12, 9, 28, 3, false, true, 1, 1);
|
||||||
|
} else if (id_ == 0x97) // Right laser eye
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 28, 3, false, false, 2, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 6, 28, 3, true, false, 1, 1);
|
||||||
|
} else if (id_ == 0x98) // Right laser eye
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 28, 3, false, true, 2, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 6, 28, 3, true, true, 1, 1);
|
||||||
|
} else if (id_ == 0x99) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 24, 12);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 0, 24, 12);
|
||||||
|
} else if (id_ == 0x9A) // Water bubble kyameron
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 24, 6);
|
||||||
|
} else if (id_ == 0x9B) // Water bubble kyameron
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 6, 24, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 2, 27, 11, false, false, 2, 1);
|
||||||
|
} else if (id_ == 0x9C) // Water bubble kyameron
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 22, 11);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 13, 22, 11, false, false, 1, 2);
|
||||||
|
} else if (id_ == 0x9D) // Water bubble kyameron
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 21, 11);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 16, 14, 20, 11, false, false, 2, 1);
|
||||||
|
} else if (id_ == 0xA1) {
|
||||||
|
DrawSpriteTile((x * 16) - 8, (y * 16) + 8, 6, 26, 14);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 6, 26, 14, true);
|
||||||
|
} else if (id_ == 0xA2) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 0, 24, 14, false, false, 4, 4);
|
||||||
|
} else if (id_ == 0xA5) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 10, false, false, 3, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 0, 24, 10);
|
||||||
|
} else if (id_ == 0xA6) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 8, false, false, 3, 2);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) - 8, 0, 24, 8);
|
||||||
|
} else if (id_ == 0xA7) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 12, 12, 16, 10);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 16, 10);
|
||||||
|
} else if (id_ == 0xAC) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 5, 14, 4);
|
||||||
|
} else if (id_ == 0xAD) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) + 8, 14, 10, 10);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 10, 10);
|
||||||
|
} else if (id_ == 0xBA) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 14, 6);
|
||||||
|
} else if (id_ == 0xC1) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 16, 2, 24, 12, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 2, 24, 12, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0xC3) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 14, 12);
|
||||||
|
} else if (id_ == 0xC4) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 18, 14);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 8, 0, 16, 14);
|
||||||
|
} else if (id_ == 0xC5) {
|
||||||
|
} else if (id_ == 0xC6) {
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 14, 3, 30, 14, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 14, (y * 16) + 4, 3, 30, 14, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 2, 1, 31, 14, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) - 6, (y * 16) + 4, 3, 30, 14, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) - 6, 3, 30, 14, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0xC7) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 26, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 10, 0, 26, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 20, 0, 26, 4);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 30, 2, 26, 4);
|
||||||
|
} else if (id_ == 0xC8) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 24, 12, false, false, 2, 3);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 12, 24, 12, true, false, 1, 3);
|
||||||
|
} else if (id_ == 0xC9) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 28, 8, false);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16), 8, 28, 8, true);
|
||||||
|
} else if (id_ == 0xCA) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 8, 10, 10);
|
||||||
|
} else if (id_ == 0xD0) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 7, 14, 11, false, false, 3, 2);
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 10, 8, 12, 11);
|
||||||
|
} else if (id_ == 0xD1) {
|
||||||
|
DrawSpriteTile((x * 16) + 2, (y * 16) + 8, 7, 13, 11, true, true, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 2, 7, 13, 11, true, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 14, (y * 16) + 8, 7, 13, 11, true, true, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 14, 7, 13, 11, false, true, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 8, (y * 16) + 8, 7, 13, 11, false, false, 1,
|
||||||
|
1); // Middle
|
||||||
|
// 6,7 / 13
|
||||||
|
} else if (id_ == 0xD4) {
|
||||||
|
DrawSpriteTile((x * 16) - 4, (y * 16), 0, 7, 7, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16), 0, 7, 7, true, false, 1, 1);
|
||||||
|
} else if (id_ == 0xE3) // Fairy
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 10, 14, 10);
|
||||||
|
} else if (id_ == 0xE4) // Key
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 11, 06, 11, false, false, 1, 2);
|
||||||
|
} else if (id_ == 0xE7) // Mushroom
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 14, 30, 16);
|
||||||
|
} else if (id_ == 0xE8) // Fake ms
|
||||||
|
{
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16), 4, 31, 10, false, false, 1, 1);
|
||||||
|
DrawSpriteTile((x * 16) + 4, (y * 16) + 8, 5, 31, 10, false, false, 1, 1);
|
||||||
|
} else if (id_ == 0xEB) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 0, 14, 5);
|
||||||
|
} else if (id_ == 0xF2) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16) - 16, 12, 24, 2, false, false, 2, 4);
|
||||||
|
DrawSpriteTile((x * 16) + 16, (y * 16) - 16, 12, 24, 2, true, false, 2, 4);
|
||||||
|
} else if (id_ == 0xF4) {
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 12, 28, 5, false, false, 4, 4);
|
||||||
|
} else {
|
||||||
|
// stringtodraw.Add(new SpriteName(x, (y *16), sprites_name.name[id]));
|
||||||
|
DrawSpriteTile((x * 16), (y * 16), 4, 4, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
bounding_box_.x = (lowerX_ + (x * 16));
|
||||||
|
bounding_box_.y = (lowerY_ + (y * 16));
|
||||||
|
bounding_box_.w = width_;
|
||||||
|
bounding_box_.h = height_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sprite::DrawSpriteTile(int x, int y, int srcx, int srcy, int pal,
|
||||||
|
bool mirror_x, bool mirror_y, int sizex, int sizey,
|
||||||
|
bool iskey) {
|
||||||
|
x += 16;
|
||||||
|
y += 16;
|
||||||
|
int drawid_ = (srcx + (srcy * 16)) + 512;
|
||||||
|
for (auto yl = 0; yl < sizey * 8; yl++) {
|
||||||
|
for (auto xl = 0; xl < (sizex * 8) / 2; xl++) {
|
||||||
|
int mx = xl;
|
||||||
|
int my = yl;
|
||||||
|
|
||||||
|
if (mirror_x) {
|
||||||
|
mx = (((sizex * 8) / 2) - 1) - xl;
|
||||||
|
}
|
||||||
|
if (mirror_y) {
|
||||||
|
my = (((sizey * 8)) - 1) - yl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formula information to get tile index position in the array
|
||||||
|
//((ID / nbrofXtiles) * (imgwidth/2) + (ID - ((ID/16)*16) ))
|
||||||
|
|
||||||
|
int tx = ((drawid_ / 0x10) * 0x400) +
|
||||||
|
((drawid_ - ((drawid_ / 0x10) * 0x10)) * 8);
|
||||||
|
auto pixel = current_gfx_[tx + (yl * 0x80) + xl];
|
||||||
|
// nx,ny = object position, xx,yy = tile position, xl,yl = pixel
|
||||||
|
// position
|
||||||
|
int index = (x) + (y * 64) + (mx + (my * 0x80));
|
||||||
|
|
||||||
|
if (index >= 0 && index <= 4096) {
|
||||||
|
preview_gfx_[index] = (uchar)((pixel & 0x0F) + 112 + (pal * 8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace zelda3
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
68
src/app/zelda3/sprite.h
Normal file
68
src/app/zelda3/sprite.h
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#ifndef YAZE_APP_ZELDA3_SPRITE_H
|
||||||
|
#define YAZE_APP_ZELDA3_SPRITE_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "absl/status/status.h"
|
||||||
|
#include "app/core/constants.h"
|
||||||
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/gfx/snes_tile.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace app {
|
||||||
|
namespace zelda3 {
|
||||||
|
|
||||||
|
class Sprite {
|
||||||
|
public:
|
||||||
|
uchar x_, y_, id_;
|
||||||
|
uchar nx_, ny_;
|
||||||
|
uchar layer_ = 0;
|
||||||
|
uchar subtype_ = 0;
|
||||||
|
uchar overlord_ = 0;
|
||||||
|
std::string name_;
|
||||||
|
uchar keyDrop_ = 0;
|
||||||
|
int sizeMap_ = 512;
|
||||||
|
bool overworld_ = false;
|
||||||
|
bool preview_ = false;
|
||||||
|
uchar map_id_ = 0;
|
||||||
|
int map_x_ = 0;
|
||||||
|
int map_y_ = 0;
|
||||||
|
short room_id_ = 0;
|
||||||
|
bool picker_ = false;
|
||||||
|
bool selected_ = false;
|
||||||
|
SDL_Rect bounding_box_;
|
||||||
|
|
||||||
|
Bytes current_gfx_;
|
||||||
|
Bytes preview_gfx_;
|
||||||
|
|
||||||
|
int lowerX_ = 32;
|
||||||
|
int lowerY_ = 32;
|
||||||
|
int higherX_ = 0;
|
||||||
|
int higherY_ = 0;
|
||||||
|
int width_ = 16;
|
||||||
|
int height_ = 16;
|
||||||
|
|
||||||
|
Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x,
|
||||||
|
int map_y);
|
||||||
|
void updateBBox();
|
||||||
|
|
||||||
|
void Draw(bool picker = false);
|
||||||
|
|
||||||
|
void DrawSpriteTile(int x, int y, int srcx, int srcy, int pal,
|
||||||
|
bool mirror_x = false, bool mirror_y = false,
|
||||||
|
int sizex = 2, int sizey = 2, bool iskey = false);
|
||||||
|
|
||||||
|
auto PreviewGraphics() { return preview_gfx_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace zelda3
|
||||||
|
} // namespace app
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "screen.h"
|
#include "title_screen.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ namespace yaze {
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace zelda3 {
|
namespace zelda3 {
|
||||||
|
|
||||||
void Screen::Create() {
|
void TitleScreen::Create() {
|
||||||
tiles8Bitmap.Create(128, 512, 8, 0x20000);
|
tiles8Bitmap.Create(128, 512, 8, 0x20000);
|
||||||
tilesBG1Bitmap.Create(256, 256, 8, 0x80000);
|
tilesBG1Bitmap.Create(256, 256, 8, 0x80000);
|
||||||
tilesBG2Bitmap.Create(256, 256, 8, 0x80000);
|
tilesBG2Bitmap.Create(256, 256, 8, 0x80000);
|
||||||
@@ -20,12 +20,9 @@ void Screen::Create() {
|
|||||||
BuildTileset();
|
BuildTileset();
|
||||||
|
|
||||||
LoadTitleScreen();
|
LoadTitleScreen();
|
||||||
LoadOverworldMap();
|
|
||||||
LoadDungeonMaps();
|
|
||||||
LoadAllMapIcons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::BuildTileset() {
|
void TitleScreen::BuildTileset() {
|
||||||
uchar staticgfx[16];
|
uchar staticgfx[16];
|
||||||
|
|
||||||
// Main Blocksets
|
// Main Blocksets
|
||||||
@@ -66,7 +63,7 @@ void Screen::BuildTileset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::LoadTitleScreen() {
|
void TitleScreen::LoadTitleScreen() {
|
||||||
int pos =
|
int pos =
|
||||||
(rom_[0x138C + 3] << 16) + (rom_[0x1383 + 3] << 8) + rom_[0x137A + 3];
|
(rom_[0x138C + 3] << 16) + (rom_[0x1383 + 3] << 8) + rom_[0x137A + 3];
|
||||||
|
|
||||||
@@ -127,14 +124,6 @@ void Screen::LoadTitleScreen() {
|
|||||||
pal_selected_ = 2;
|
pal_selected_ = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Screen::LoadNamingScreen() {}
|
|
||||||
|
|
||||||
void Screen::LoadOverworldMap() {}
|
|
||||||
|
|
||||||
void Screen::LoadDungeonMaps() {}
|
|
||||||
|
|
||||||
void Screen::LoadAllMapIcons() {}
|
|
||||||
|
|
||||||
} // namespace zelda3
|
} // namespace zelda3
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -12,17 +12,13 @@ namespace yaze {
|
|||||||
namespace app {
|
namespace app {
|
||||||
namespace zelda3 {
|
namespace zelda3 {
|
||||||
|
|
||||||
class Screen {
|
class TitleScreen {
|
||||||
public:
|
public:
|
||||||
void Create();
|
void Create();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void BuildTileset();
|
void BuildTileset();
|
||||||
void LoadTitleScreen();
|
void LoadTitleScreen();
|
||||||
void LoadNamingScreen();
|
|
||||||
void LoadOverworldMap();
|
|
||||||
void LoadDungeonMaps();
|
|
||||||
void LoadAllMapIcons();
|
|
||||||
|
|
||||||
int sword_x_ = 0;
|
int sword_x_ = 0;
|
||||||
int mx_click_ = 0;
|
int mx_click_ = 0;
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace gui {
|
namespace gui {
|
||||||
@@ -39,8 +40,10 @@ void Canvas::DrawContextMenu() {
|
|||||||
// Add first and second point
|
// Add first and second point
|
||||||
if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
if (is_hovered && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||||
ImVec2 draw_tile_outline_pos;
|
ImVec2 draw_tile_outline_pos;
|
||||||
draw_tile_outline_pos.x = std::round((double)mouse_pos_in_canvas.x / 32) * 32;
|
draw_tile_outline_pos.x =
|
||||||
draw_tile_outline_pos.y = std::round((double)mouse_pos_in_canvas.y / 32) * 32;
|
std::round((double)mouse_pos_in_canvas.x / 32) * 32;
|
||||||
|
draw_tile_outline_pos.y =
|
||||||
|
std::round((double)mouse_pos_in_canvas.y / 32) * 32;
|
||||||
|
|
||||||
points_.push_back(draw_tile_outline_pos);
|
points_.push_back(draw_tile_outline_pos);
|
||||||
points_.push_back(
|
points_.push_back(
|
||||||
@@ -61,6 +64,11 @@ void Canvas::DrawContextMenu() {
|
|||||||
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
|
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
|
||||||
|
|
||||||
if (ImGui::BeginPopup("context")) {
|
if (ImGui::BeginPopup("context")) {
|
||||||
|
ImGui::MenuItem("Show Grid", nullptr, &enable_grid_);
|
||||||
|
if (ImGui::MenuItem("Reset Position", nullptr, false)) {
|
||||||
|
scrolling_.x = 0;
|
||||||
|
scrolling_.y = 0;
|
||||||
|
}
|
||||||
if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) {
|
if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) {
|
||||||
points_.clear();
|
points_.clear();
|
||||||
}
|
}
|
||||||
@@ -68,12 +76,35 @@ void Canvas::DrawContextMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset) {
|
void Canvas::DrawTilesFromUser(app::ROM &rom, Bytes &tile,
|
||||||
draw_list_->AddImage(
|
app::gfx::SNESPalette &pal) {
|
||||||
(void *)bitmap.GetTexture(),
|
ImVec2 draw_tile_outline_pos;
|
||||||
ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset),
|
|
||||||
ImVec2(canvas_p0_.x + (bitmap.GetWidth() * 2),
|
// Add rectangle
|
||||||
canvas_p0_.y + (bitmap.GetHeight() * 2)));
|
if (is_hovered_ && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||||
|
draw_tile_outline_pos.x =
|
||||||
|
std::round((double)mouse_pos_in_canvas_.x / 16) * 16;
|
||||||
|
draw_tile_outline_pos.y =
|
||||||
|
std::round((double)mouse_pos_in_canvas_.y / 16) * 16;
|
||||||
|
|
||||||
|
points_.push_back(draw_tile_outline_pos);
|
||||||
|
points_.push_back(
|
||||||
|
ImVec2(draw_tile_outline_pos.x + 16, draw_tile_outline_pos.y + 16));
|
||||||
|
|
||||||
|
changed_tiles_.emplace_back(app::gfx::Bitmap(16, 16, 64, tile.data()));
|
||||||
|
changed_tiles_.back().ApplyPalette(pal);
|
||||||
|
rom.RenderBitmap(&(changed_tiles_.back()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawBitmap(const Bitmap &bitmap, int border_offset, bool ready) {
|
||||||
|
if (ready) {
|
||||||
|
draw_list_->AddImage(
|
||||||
|
(void *)bitmap.GetTexture(),
|
||||||
|
ImVec2(canvas_p0_.x + border_offset, canvas_p0_.y + border_offset),
|
||||||
|
ImVec2(canvas_p0_.x + (bitmap.GetWidth() * 2),
|
||||||
|
canvas_p0_.y + (bitmap.GetHeight() * 2)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) {
|
void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) {
|
||||||
@@ -86,11 +117,28 @@ void Canvas::DrawBitmap(const Bitmap &bitmap, int x_offset, int y_offset) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawOutline(int x, int y, int w, int h) {
|
void Canvas::DrawOutline(int x, int y, int w, int h) {
|
||||||
ImVec2 origin(x, y);
|
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
||||||
ImVec2 size(x + w, y + h);
|
canvas_p0_.y + scrolling_.y + y);
|
||||||
|
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
|
||||||
|
canvas_p0_.y + scrolling_.y + y + h);
|
||||||
draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255));
|
draw_list_->AddRect(origin, size, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawRect(int x, int y, int w, int h, ImVec4 color) {
|
||||||
|
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
||||||
|
canvas_p0_.y + scrolling_.y + y);
|
||||||
|
ImVec2 size(canvas_p0_.x + scrolling_.x + x + w,
|
||||||
|
canvas_p0_.y + scrolling_.y + y + h);
|
||||||
|
draw_list_->AddRectFilled(origin, size,
|
||||||
|
IM_COL32(color.x, color.y, color.z, color.w));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawText(std::string text, int x, int y) {
|
||||||
|
draw_list_->AddText(
|
||||||
|
ImVec2(canvas_p0_.x + scrolling_.x + x, canvas_p0_.y + scrolling_.y + y),
|
||||||
|
IM_COL32(255, 255, 255, 255), text.data());
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::DrawGrid(float grid_step) {
|
void Canvas::DrawGrid(float grid_step) {
|
||||||
// Draw grid + all lines in the canvas
|
// Draw grid + all lines in the canvas
|
||||||
draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true);
|
draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/rom.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace gui {
|
namespace gui {
|
||||||
@@ -21,9 +22,14 @@ class Canvas {
|
|||||||
|
|
||||||
void DrawBackground(ImVec2 canvas_size = ImVec2(0, 0));
|
void DrawBackground(ImVec2 canvas_size = ImVec2(0, 0));
|
||||||
void DrawContextMenu();
|
void DrawContextMenu();
|
||||||
void DrawBitmap(const Bitmap& bitmap, int border_offset = 0);
|
void DrawTilesFromUser(app::ROM& rom, Bytes& tile,
|
||||||
|
app::gfx::SNESPalette& pal);
|
||||||
|
void DrawBitmap(const Bitmap& bitmap, int border_offset = 0,
|
||||||
|
bool ready = true);
|
||||||
void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset);
|
void DrawBitmap(const Bitmap& bitmap, int x_offset, int y_offset);
|
||||||
void DrawOutline(int x, int y, int w, int h);
|
void DrawOutline(int x, int y, int w, int h);
|
||||||
|
void DrawRect(int x, int y, int w, int h, ImVec4 color);
|
||||||
|
void DrawText(std::string text, int x, int y);
|
||||||
void DrawGrid(float grid_step = 64.0f);
|
void DrawGrid(float grid_step = 64.0f);
|
||||||
void DrawOverlay(); // last
|
void DrawOverlay(); // last
|
||||||
|
|
||||||
@@ -38,6 +44,7 @@ class Canvas {
|
|||||||
bool enable_grid_ = true;
|
bool enable_grid_ = true;
|
||||||
bool enable_context_menu_ = true;
|
bool enable_context_menu_ = true;
|
||||||
bool custom_canvas_size_ = false;
|
bool custom_canvas_size_ = false;
|
||||||
|
bool is_hovered_ = false;
|
||||||
|
|
||||||
ImDrawList* draw_list_;
|
ImDrawList* draw_list_;
|
||||||
ImVector<ImVec2> points_;
|
ImVector<ImVec2> points_;
|
||||||
@@ -45,6 +52,9 @@ class Canvas {
|
|||||||
ImVec2 canvas_sz_;
|
ImVec2 canvas_sz_;
|
||||||
ImVec2 canvas_p0_;
|
ImVec2 canvas_p0_;
|
||||||
ImVec2 canvas_p1_;
|
ImVec2 canvas_p1_;
|
||||||
|
ImVec2 mouse_pos_in_canvas_;
|
||||||
|
|
||||||
|
std::vector<app::gfx::Bitmap> changed_tiles_;
|
||||||
|
|
||||||
std::string title_;
|
std::string title_;
|
||||||
};
|
};
|
||||||
|
|||||||
84
src/gui/color.cc
Normal file
84
src/gui/color.cc
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#include "color.h"
|
||||||
|
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace gui {
|
||||||
|
void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded) {
|
||||||
|
static ImVec4 color = ImVec4(0, 0, 0, 255.f);
|
||||||
|
ImGuiColorEditFlags misc_flags = ImGuiColorEditFlags_AlphaPreview |
|
||||||
|
ImGuiColorEditFlags_NoDragDrop |
|
||||||
|
ImGuiColorEditFlags_NoOptions;
|
||||||
|
|
||||||
|
// Generate a default palette. The palette will persist and can be edited.
|
||||||
|
static bool init = false;
|
||||||
|
static ImVec4 saved_palette[32] = {};
|
||||||
|
if (loaded && !init) {
|
||||||
|
for (int n = 0; n < palette.size_; n++) {
|
||||||
|
saved_palette[n].x = palette.GetColor(n).rgb.x / 255;
|
||||||
|
saved_palette[n].y = palette.GetColor(n).rgb.y / 255;
|
||||||
|
saved_palette[n].z = palette.GetColor(n).rgb.z / 255;
|
||||||
|
saved_palette[n].w = 255; // Alpha
|
||||||
|
}
|
||||||
|
init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ImVec4 backup_color;
|
||||||
|
ImGui::Text("Current ==>");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::Text("Previous");
|
||||||
|
|
||||||
|
ImGui::ColorButton(
|
||||||
|
"##current", color,
|
||||||
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
||||||
|
ImVec2(60, 40));
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::ColorButton(
|
||||||
|
"##previous", backup_color,
|
||||||
|
ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf,
|
||||||
|
ImVec2(60, 40)))
|
||||||
|
color = backup_color;
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
ImGui::BeginGroup(); // Lock X position
|
||||||
|
ImGui::Text("Palette");
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) {
|
||||||
|
ImGui::PushID(n);
|
||||||
|
if ((n % 4) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
|
||||||
|
|
||||||
|
ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha |
|
||||||
|
ImGuiColorEditFlags_NoPicker |
|
||||||
|
ImGuiColorEditFlags_NoTooltip;
|
||||||
|
if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags,
|
||||||
|
ImVec2(20, 20)))
|
||||||
|
color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z,
|
||||||
|
color.w); // Preserve alpha!
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget()) {
|
||||||
|
if (const ImGuiPayload* payload =
|
||||||
|
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
|
||||||
|
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
|
||||||
|
if (const ImGuiPayload* payload =
|
||||||
|
ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
|
||||||
|
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::ColorPicker4("##picker", (float*)&color,
|
||||||
|
misc_flags | ImGuiColorEditFlags_NoSidePreview |
|
||||||
|
ImGuiColorEditFlags_NoSmallPreview);
|
||||||
|
}
|
||||||
|
} // namespace gui
|
||||||
|
} // namespace yaze
|
||||||
20
src/gui/color.h
Normal file
20
src/gui/color.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef YAZE_GUI_COLOR_H
|
||||||
|
#define YAZE_GUI_COLOR_H
|
||||||
|
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "app/gfx/bitmap.h"
|
||||||
|
#include "app/gfx/snes_palette.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace gui {
|
||||||
|
|
||||||
|
void DisplayPalette(app::gfx::SNESPalette& palette, bool loaded);
|
||||||
|
|
||||||
|
} // namespace gui
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -30,7 +30,7 @@ using ::testing::Return;
|
|||||||
class MockScript : public Script {
|
class MockScript : public Script {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD(absl::Status, ApplyPatchToROM, (ROM & rom));
|
MOCK_METHOD(absl::Status, ApplyPatchToROM, (ROM & rom));
|
||||||
MOCK_METHOD(absl::Status, GenerateMosaicChangeAssembly,
|
MOCK_METHOD(absl::Status, PatchOverworldMosaic,
|
||||||
(ROM & rom, char mosaic_tiles[yaze::app::core::kNumOverworldMaps],
|
(ROM & rom, char mosaic_tiles[yaze::app::core::kNumOverworldMaps],
|
||||||
int routine_offset, int hook_offset));
|
int routine_offset, int hook_offset));
|
||||||
};
|
};
|
||||||
@@ -40,15 +40,15 @@ TEST(ASMTest, ApplyMosaicChangePatchOk) {
|
|||||||
MockScript script;
|
MockScript script;
|
||||||
char mosaic_tiles[yaze::app::core::kNumOverworldMaps];
|
char mosaic_tiles[yaze::app::core::kNumOverworldMaps];
|
||||||
|
|
||||||
EXPECT_CALL(script, GenerateMosaicChangeAssembly(_, Eq(mosaic_tiles),
|
EXPECT_CALL(script, PatchOverworldMosaic(_, Eq(mosaic_tiles),
|
||||||
Eq(0x1301D0 + 0x138000), 0))
|
Eq(0x1301D0 + 0x138000), 0))
|
||||||
.WillOnce(Return(absl::OkStatus()));
|
.WillOnce(Return(absl::OkStatus()));
|
||||||
|
|
||||||
EXPECT_CALL(script, ApplyPatchToROM(_)).WillOnce(Return(absl::OkStatus()));
|
EXPECT_CALL(script, ApplyPatchToROM(_)).WillOnce(Return(absl::OkStatus()));
|
||||||
|
|
||||||
EXPECT_THAT(script.GenerateMosaicChangeAssembly(rom, mosaic_tiles,
|
EXPECT_THAT(
|
||||||
0x1301D0 + 0x138000, 0),
|
script.PatchOverworldMosaic(rom, mosaic_tiles, 0x1301D0 + 0x138000, 0),
|
||||||
absl::OkStatus());
|
absl::OkStatus());
|
||||||
EXPECT_THAT(script.ApplyPatchToROM(rom), absl::OkStatus());
|
EXPECT_THAT(script.ApplyPatchToROM(rom), absl::OkStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user