Merge branch 'HarbourMasters:develop' into develop

This commit is contained in:
MelonSpeedruns 2022-05-18 11:21:22 -04:00 committed by GitHub
commit 72bacabf45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
69 changed files with 1779 additions and 401 deletions

View File

@ -2,9 +2,9 @@
## Windows
1. Install [Python](https://www.python.org/ftp/python/3.10.2/python-3.10.2-amd64.exe)
1. Requires [Python](https://www.python.org/downloads/) >= 3.6.
2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/)
2b. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`.
3. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`.
4. Clone the Ship of Harkinian repository.
5. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice.
6. Run `OTRExporter/OTRExporter.sln`.
@ -41,9 +41,9 @@ cp /usr/local/lib/libGLEW.a external
cd soh
# Extract the assets/Compile the exporter/Run the exporter
make setup -j$(nproc)
make setup -j$(nproc) OPTFLAGS=-O0 DEBUG=0
# Compile the code
make -j $(nproc)
make -j $(nproc) OPTFLAGS=-O0 DEBUG=0
```
# Compatible Roms
@ -51,3 +51,16 @@ make -j $(nproc)
OOT_PAL_GC checksum 0x09465AC3
OOT_PAL_GC_DBG1 checksum 0x871E1C92 (debug non-master quest)
```
# OTRExporter Usage
The OTRExporter exports an `oot.otr` archive file which Ship of Harkinian requires to play.
Use the `extract_assets.py` script file to run the exporter using any of the following methods:
1) Double click on the script after placing one or more roms in the directory.
2) Drag & Drop a rom onto the script.
3) In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory.
4) In a terminal run `python3 extract_assets.py <path_to_rom>`
If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key.

View File

@ -188,7 +188,7 @@ void OTRGame::draw() {
sohFolder = path;
}
if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nMaster Quest or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) {
if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nGameCube PAL or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) {
const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FILE);
if (path != NULLSTR) {
const std::string patched_n64 = std::string(patched_rom);

View File

@ -6,7 +6,7 @@ The Ship does not include assets and as such requires a prior copy of the game t
## Quick Start
1) Download The Ship of Harkinian from Discord.
1) Download The Ship of Harkinian from [Discord](https://discord.com/invite/BtBmd55HVH).
2) Requires a supported copy of the game (See supported games below).
3) Use the OTRGui to generate an `oot.otr` archive file.
4) Launch `soh.exe`
@ -18,9 +18,9 @@ Build team: `zelda@srd022j`
Build date: `03-02-21 00:49:18` (year-month-day)
sha1: cee6bc3c2a634b41728f2af8da54d9bf8cc14099
```
Ocarina of Time Pal Gamecube
Ocarina of Time PAL GameCube
```
sha1: d0c95b2cb3c6682a171db267932af7af8cf5fa82
sha1: 0227d7c0074f2d0ac935631990da8ec5914597b4
```
Congratulations, you are now sailing with the Ship of Harkinian! Have fun!
@ -64,42 +64,51 @@ Refer to the [building instructions](BUILDING.md) to compile SoH.
- Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe
- Affirm that `zapd.exe` exists in the `/assets/extractor` folder
## Nightly Builds
Nightly builds of Ship of Harkinian are available at [https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop]
## The Harbour Masters Are...
Kenix | Lead Developer/Public Relations - Resource Management Programmer, Audio System Programmer, and General Programmer
Jack Walker | Lead Developer - OTR Format Programmer, Resource Load Programmer, and General Programmer
Louist103 | Developer - Save System Programmer and General Programmer
Emil | Developer - Fast3D Programmer
m4xw | Developer - Shipwright, Throwing Baguettes, and General Programmer
MelonSpeedruns | Developer - General Programmer
Rozlette | Developer - General Programmer
JoshDuMan | Developer - General Programmer
KiritoDev/Lywx | Developer - General Programmer
Theo3 | Developer - General Programmer
Random06457 | Developer - Linux Build
Kenix | Lead Developer/Public Relations - Resource Management Programmer, Audio System Programmer, and General Programmer
Jack Walker | Lead Developer - OTR Format Programmer, Resource Load Programmer, and General Programmer
Louist103 | Developer - Save System Programmer and General Programmer
Emil | Developer - Fast3D Programmer
m4xw | Developer - Shipwright, Throwing Baguettes, and General Programmer
MelonSpeedruns | Developer - General Programmer
Rozlette | Developer - General Programmer
JoshDuMan | Developer - General Programmer
KiritoDev/Lywx | Developer - General Programmer
Theo3 | Developer - General Programmer
Random06457 | Developer - Linux Build
## Special Thanks
Decomp & ZAPD | Made this project even possible in the first place!
MNGoldenEagle | Patiently explained audio data formats, encouragement, and founding ZSO which was the first source of the game's code and resource format documentation.
Rrrrry123 | Speedbunner, encouragement, and community moderation
Fierce deity | Encouragement and community moderation
mzxrules | For his contributions to decomp
zel. | For his contributions to decomp
Aloxado | Developer - General Programmer
MegaMech | Developer - General Programmer
Revo | Tester - GCC support and General Testing
zfg | Tester - General Testing
Horseless Headman | Tester - General Testing
Steven Pritchett | Tester - General Testing
Trenton May | Tester - General Testing
Zeldaboy14 | Tester - General Testing, encouragement, and community moderation
Koby Howell | Tester - General Testing
Logg | Tester - General Testing
Taylor Daley | Graphic Design
Can't Sleep | Graphic Design
MicTheMicrophone | Voice actor for the King
Amphibibro | Voice actor for Link
Lemons
Decomp & ZAPD | Made this project even possible in the first place!
MNGoldenEagle | Patiently explained audio data formats, encouragement, and founding ZSO which was the first source of the game's code and resource format documentation.
Rrrrry123 | Speedbunner, encouragement, and community moderation
Fierce deity | Encouragement and community moderation
mzxrules | For his contributions to decomp
zel. | For his contributions to decomp
Aloxado | Developer - General Programmer
MegaMech | Developer - General Programmer
Revo | Tester - GCC support and General Testing
zfg | Tester - General Testing
Horseless Headman | Tester - General Testing
Steven Pritchett | Tester - General Testing
Trenton May | Tester - General Testing
Zeldaboy14 | Tester - General Testing, encouragement, and community moderation
Koby Howell | Tester - General Testing
Logg | Tester - General Testing
Taylor Daley | Graphic Design
Can't Sleep | Graphic Design
## Video Credits
Kenix | Producer / Writer
rainbow_fash | Executive Producer
TheLegendOfXela | Editor
MicTheMicrophone | Gwonam / The King
Amphibibro | Link
AceHeart | Zelda
###### Lemons

View File

@ -204,7 +204,7 @@ namespace Ship {
return true;
}
std::vector<SFILE_FIND_DATA> Archive::ListFiles(const std::string& searchMask) {
std::vector<SFILE_FIND_DATA> Archive::ListFiles(const std::string& searchMask) const {
auto fileList = std::vector<SFILE_FIND_DATA>();
SFILE_FIND_DATA findContext;
HANDLE hFind;
@ -248,7 +248,7 @@ namespace Ship {
return fileList;
}
bool Archive::HasFile(const std::string& filename) {
bool Archive::HasFile(const std::string& filename) const {
bool result = false;
auto start = std::chrono::steady_clock::now();
@ -267,8 +267,9 @@ namespace Ship {
return result;
}
std::string Archive::HashToString(uint64_t hash) {
return hashes[hash];
const std::string* Archive::HashToString(uint64_t hash) const {
auto it = hashes.find(hash);
return it != hashes.end() ? &it->second : nullptr;
}
bool Archive::Load(bool enableWriting, bool genCRCMap) {

View File

@ -34,9 +34,9 @@ namespace Ship
bool AddFile(const std::string& path, uintptr_t fileData, DWORD dwFileSize);
bool RemoveFile(const std::string& path);
bool RenameFile(const std::string& oldPath, const std::string& newPath);
std::vector<SFILE_FIND_DATA> ListFiles(const std::string& searchMask);
bool HasFile(const std::string& searchMask);
std::string HashToString(uint64_t hash);
std::vector<SFILE_FIND_DATA> ListFiles(const std::string& searchMask) const;
bool HasFile(const std::string& searchMask) const;
const std::string* HashToString(uint64_t hash) const;
protected:
bool Load(bool enableWriting, bool genCRCMap);
bool Unload();

View File

@ -72,7 +72,7 @@ namespace Ship {
(*this)["WINDOW"]["FULLSCREEN WIDTH"] = std::to_string(1920);
(*this)["WINDOW"]["FULLSCREEN HEIGHT"] = std::to_string(1080);
(*this)["WINDOW"]["FULLSCREEN"] = std::to_string(false);
(*this)["WINDOW"]["GFX BACKEND"] = "sdl";
(*this)["WINDOW"]["GFX BACKEND"] = "";
(*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CRIGHT)] = std::to_string(0x14D);
(*this)["KEYBOARD CONTROLLER BINDING 1"][STR(BTN_CLEFT)] = std::to_string(0x14B);

View File

@ -8,6 +8,7 @@
#include "SohImGuiImpl.h"
#include "TextureMod.h"
#include "Lib/ImGui/imgui_internal.h"
#include "Utils/StringHelper.h"
void Ship::GameOverlay::LoadFont(const std::string& name, const std::string& path, float fontSize) {
ImGuiIO& io = ImGui::GetIO();
@ -50,10 +51,21 @@ void Ship::GameOverlay::TextDrawNotification(float duration, bool shadow, const
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
this->RegisteredOverlays[fmt] = new Overlay({ OverlayType::NOTIFICATION, ImStrdup(buf), duration, duration });
this->RegisteredOverlays[StringHelper::Sprintf("NotificationID:%d%d", rand(), this->RegisteredOverlays.size())] = new Overlay({ OverlayType::NOTIFICATION, ImStrdup(buf), duration, duration });
NeedsCleanup = true;
}
void Ship::GameOverlay::CleanupNotifications() {
if(!NeedsCleanup) return;
for (auto it = this->RegisteredOverlays.begin(); it != this->RegisteredOverlays.end(); ) {
if (it->second->type == OverlayType::NOTIFICATION && it->second->duration <= 0.0f) {
it = this->RegisteredOverlays.erase(it);
} else {
++it;
}
}
NeedsCleanup = false;
}
float Ship::GameOverlay::GetScreenWidth() {
const ImGuiViewport* viewport = ImGui::GetMainViewport();
@ -137,6 +149,8 @@ void Ship::GameOverlay::Draw() {
ImGui::Begin("SoHOverlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoInputs);
this->CleanupNotifications();
float textY = 50;
float notY = 0;

View File

@ -33,6 +33,8 @@ namespace Ship {
void TextDraw(float x, float y, bool shadow, ImVec4 color, const char* text, ...);
void TextDrawNotification(float duration, bool shadow, const char* fmt, ...);
private:
bool NeedsCleanup = false;
void CleanupNotifications();
void LoadFont(const std::string& name, const std::string& path, float fontSize);
};

View File

@ -36,7 +36,7 @@
// OTRTODO: fix header files for these
extern "C" {
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc);
const char* ResourceMgr_GetNameByCRC(uint64_t crc);
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc);
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc);
@ -88,7 +88,7 @@ struct LoadedVertex {
static struct {
TextureCacheMap map;
list<TextureCacheMap::iterator> lru;
list<TextureCacheMapIter> lru;
vector<uint32_t> free_texture_ids;
} gfx_texture_cache;
@ -134,14 +134,14 @@ static struct RDP {
const uint8_t *addr;
uint8_t siz;
uint32_t width;
char* otr_path;
const char* otr_path;
} texture_to_load;
struct {
const uint8_t *addr;
uint32_t size_bytes;
uint32_t full_image_line_size_bytes;
uint32_t line_size_bytes;
char* otr_path;
const char* otr_path;
} loaded_texture[2];
struct {
uint8_t fmt;
@ -190,8 +190,12 @@ static int game_framebuffer_msaa_resolved;
uint32_t gfx_msaa_level = 1;
static bool has_drawn_imgui_menu;
static bool dropped_frame;
static const std::unordered_map<Mtx *, MtxF> *current_mtx_replacements;
static float buf_vbo[MAX_BUFFERED * (32 * 3)]; // 3 vertices in a triangle and 32 floats per vtx
static size_t buf_vbo_len;
static size_t buf_vbo_num_tris;
@ -523,18 +527,18 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
key = { orig_addr, { }, fmt, siz, palette_index };
}
auto it = gfx_texture_cache.map.find(key);
TextureCacheMap::iterator it = gfx_texture_cache.map.find(key);
if (it != gfx_texture_cache.map.end()) {
gfx_rapi->select_texture(i, it->second.texture_id);
*n = &*it;
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, *(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location); // move to back
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, it->second.lru_location); // move to back
return true;
}
if (gfx_texture_cache.map.size() >= TEXTURE_CACHE_MAX_SIZE) {
// Remove the texture that was least recently used
it = gfx_texture_cache.lru.front();
it = gfx_texture_cache.lru.front().it;
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
gfx_texture_cache.map.erase(it);
gfx_texture_cache.lru.pop_front();
@ -551,7 +555,7 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
it = gfx_texture_cache.map.insert(make_pair(key, TextureCacheValue())).first;
TextureCacheNode* node = &*it;
node->second.texture_id = texture_id;
*(list<TextureCacheMap::iterator>::iterator*)&node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), it);
node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it });
gfx_rapi->select_texture(i, texture_id);
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
@ -567,7 +571,7 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr)
bool again = false;
for (auto it = gfx_texture_cache.map.begin(bucket); it != gfx_texture_cache.map.end(bucket); ++it) {
if (it->first.texture_addr == orig_addr) {
gfx_texture_cache.lru.erase(*(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location);
gfx_texture_cache.lru.erase(it->second.lru_location);
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
gfx_texture_cache.map.erase(it->first);
again = true;
@ -916,20 +920,31 @@ static void gfx_matrix_mul(float res[4][4], const float a[4][4], const float b[4
static void gfx_sp_matrix(uint8_t parameters, const int32_t *addr) {
float matrix[4][4];
#ifndef GBI_FLOATS
// Original GBI where fixed point matrices are used
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j += 2) {
int32_t int_part = addr[i * 2 + j / 2];
uint32_t frac_part = addr[8 + i * 2 + j / 2];
matrix[i][j] = (int32_t)((int_part & 0xffff0000) | (frac_part >> 16)) / 65536.0f;
matrix[i][j + 1] = (int32_t)((int_part << 16) | (frac_part & 0xffff)) / 65536.0f;
if (auto it = current_mtx_replacements->find((Mtx *)addr); it != current_mtx_replacements->end()) {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
float v = it->second.mf[i][j];
int as_int = (int)(v * 65536.0f);
matrix[i][j] = as_int * (1.0f / 65536.0f);
}
}
} else {
#ifndef GBI_FLOATS
// Original GBI where fixed point matrices are used
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j += 2) {
int32_t int_part = addr[i * 2 + j / 2];
uint32_t frac_part = addr[8 + i * 2 + j / 2];
matrix[i][j] = (int32_t)((int_part & 0xffff0000) | (frac_part >> 16)) / 65536.0f;
matrix[i][j + 1] = (int32_t)((int_part << 16) | (frac_part & 0xffff)) / 65536.0f;
}
}
}
#else
// For a modified GBI where fixed point values are replaced with floats
memcpy(matrix, addr, sizeof(matrix));
// For a modified GBI where fixed point values are replaced with floats
memcpy(matrix, addr, sizeof(matrix));
#endif
}
if (parameters & G_MTX_PROJECTION) {
if (parameters & G_MTX_LOAD) {
@ -1621,11 +1636,11 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32
rdp.viewport_or_scissor_changed = true;
}
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, char* otr_path) {
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, const char* otr_path) {
rdp.texture_to_load.addr = (const uint8_t*)addr;
rdp.texture_to_load.siz = size;
rdp.texture_to_load.width = width;
if ( otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
if (otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
rdp.texture_to_load.otr_path = otr_path;
}
@ -2099,7 +2114,7 @@ static void gfx_run_dl(Gfx* cmd) {
//puts("dl");
int dummy = 0;
char dlName[128];
char fileName[128];
const char* fileName;
Gfx* dListStart = cmd;
uint64_t ourHash = -1;
@ -2422,7 +2437,7 @@ static void gfx_run_dl(Gfx* cmd) {
uintptr_t addr = cmd->words.w1;
cmd++;
uint64_t hash = ((uint64_t)cmd->words.w0 << 32) + (uint64_t)cmd->words.w1;
ResourceMgr_GetNameByCRC(hash, fileName);
fileName = ResourceMgr_GetNameByCRC(hash);
#if _DEBUG && 0
char* tex = ResourceMgr_LoadTexByCRC(hash);
ResourceMgr_GetNameByCRC(hash, fileName);
@ -2708,6 +2723,7 @@ void gfx_start_frame(void) {
gfx_wapi->handle_events();
gfx_wapi->get_dimensions(&gfx_current_window_dimensions.width, &gfx_current_window_dimensions.height);
SohImGui::DrawMainMenuAndCalculateGameSize();
has_drawn_imgui_menu = true;
if (gfx_current_dimensions.height == 0) {
// Avoid division by zero
gfx_current_dimensions.height = 1;
@ -2746,7 +2762,7 @@ void gfx_start_frame(void) {
fbActive = 0;
}
void gfx_run(Gfx *commands) {
void gfx_run(Gfx *commands, const std::unordered_map<Mtx *, MtxF>& mtx_replacements) {
gfx_sp_reset();
//puts("New frame");
@ -2755,12 +2771,21 @@ void gfx_run(Gfx *commands) {
if (!gfx_wapi->start_frame()) {
dropped_frame = true;
SohImGui::DrawFramebufferAndGameInput();
SohImGui::CancelFrame();
if (has_drawn_imgui_menu) {
SohImGui::DrawFramebufferAndGameInput();
SohImGui::CancelFrame();
has_drawn_imgui_menu = false;
}
return;
}
dropped_frame = false;
if (!has_drawn_imgui_menu) {
SohImGui::DrawMainMenuAndCalculateGameSize();
}
current_mtx_replacements = &mtx_replacements;
double t0 = gfx_wapi->get_time();
gfx_rapi->update_framebuffer_parameters(0, gfx_current_window_dimensions.width, gfx_current_window_dimensions.height, 1, false, true, true, !game_renders_to_framebuffer);
gfx_rapi->start_frame();
@ -2792,6 +2817,7 @@ void gfx_run(Gfx *commands) {
//printf("Process %f %f\n", t1, t1 - t0);
gfx_rapi->end_frame();
gfx_wapi->swap_buffers_begin();
has_drawn_imgui_menu = false;
}
void gfx_end_frame(void) {

View File

@ -6,6 +6,8 @@
#include <unordered_map>
#include <list>
#include "U64/PR/ultra64/types.h"
struct GfxRenderingAPI;
struct GfxWindowManagerAPI;
@ -44,34 +46,31 @@ struct TextureCacheValue {
uint8_t cms, cmt;
bool linear_filter;
// Old versions of libstdc++ fail to compile this
#ifdef _MSC_VER
std::list<TextureCacheMap::iterator>::iterator lru_location;
#else
std::list<int>::iterator lru_location;
#endif
std::list<struct TextureCacheMapIter>::iterator lru_location;
};
struct TextureCacheMapIter {
TextureCacheMap::iterator it;
};
#ifdef __cplusplus
extern "C" {
#endif
extern struct GfxDimensions gfx_current_window_dimensions; // The dimensions of the window
extern struct GfxDimensions gfx_current_dimensions; // The dimensions of the draw area the game draws to, before scaling (if applicable)
extern struct XYWidthHeight gfx_current_game_window_viewport; // The area of the window the game is drawn to, (0, 0) is top-left corner
extern uint32_t gfx_msaa_level;
}
void gfx_init(struct GfxWindowManagerAPI* wapi, struct GfxRenderingAPI* rapi, const char* game_name, bool start_in_fullscreen);
struct GfxRenderingAPI* gfx_get_current_rendering_api(void);
void gfx_start_frame(void);
void gfx_run(Gfx* commands);
void gfx_run(Gfx* commands, const std::unordered_map<Mtx*, MtxF>& mtx_replacements);
void gfx_end_frame(void);
void gfx_set_framedivisor(int);
void gfx_texture_cache_clear();
int gfx_create_framebuffer(uint32_t width, uint32_t height);
extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height);
void gfx_get_pixel_depth_prepare(float x, float y);
uint16_t gfx_get_pixel_depth(float x, float y);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -40,8 +40,11 @@ namespace Ship
for (size_t i = 0; i < patches.size(); i++)
{
std::string hashStr = resMgr->HashToString(patches[i].crc);
auto resShared = resMgr->GetCachedFile(hashStr);
const std::string* hashStr = resMgr->HashToString(patches[i].crc);
if (hashStr == nullptr)
continue;
auto resShared = resMgr->GetCachedFile(hashStr->c_str());
if (resShared != nullptr)
{
auto res = (Ship::DisplayList*)resShared.get();

View File

@ -215,7 +215,7 @@ namespace Ship {
return ToLoad;
}
std::shared_ptr<Ship::Resource> ResourceMgr::GetCachedFile(std::string FilePath) {
std::shared_ptr<Ship::Resource> ResourceMgr::GetCachedFile(const char* FilePath) const {
auto resCacheFind = ResourceCache.find(FilePath);
if (resCacheFind != ResourceCache.end() &&
@ -227,8 +227,13 @@ namespace Ship {
return nullptr;
}
std::shared_ptr<Resource> ResourceMgr::LoadResource(std::string FilePath) {
auto Promise = LoadResourceAsync(FilePath);
std::shared_ptr<Resource> ResourceMgr::LoadResource(const char* FilePath) {
auto Res = LoadResourceAsync(FilePath);
if (std::holds_alternative<std::shared_ptr<Resource>>(Res))
return std::get<std::shared_ptr<Resource>>(Res);
auto& Promise = std::get<std::shared_ptr<ResourcePromise>>(Res);
if (!Promise->bHasResourceLoaded)
{
@ -241,21 +246,18 @@ namespace Ship {
return Promise->resource;
}
std::shared_ptr<ResourcePromise> ResourceMgr::LoadResourceAsync(std::string FilePath) {
StringHelper::ReplaceOriginal(FilePath, "\\", "/");
if (StringHelper::StartsWith(FilePath, "__OTR__"))
FilePath = StringHelper::Split(FilePath, "__OTR__")[1];
std::shared_ptr<ResourcePromise> Promise = std::make_shared<ResourcePromise>();
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> ResourceMgr::LoadResourceAsync(const char* FilePath) {
if (FilePath[0] == '_' && FilePath[1] == '_' && FilePath[2] == 'O' && FilePath[3] == 'T' && FilePath[4] == 'R' && FilePath[5] == '_' && FilePath[6] == '_')
FilePath += 7;
const std::lock_guard<std::mutex> ResLock(ResourceLoadMutex);
auto resCacheFind = ResourceCache.find(FilePath);
if (resCacheFind == ResourceCache.end() || resCacheFind->second->isDirty/* || !FileData->bIsLoaded*/) {
if (resCacheFind == ResourceCache.end()) {
SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath.c_str());
SPDLOG_TRACE("Cache miss on Resource load: {}", FilePath);
}
std::shared_ptr<ResourcePromise> Promise = std::make_shared<ResourcePromise>();
std::shared_ptr<File> FileData = LoadFile(FilePath);
Promise->file = FileData;
@ -269,12 +271,13 @@ namespace Ship {
ResourceLoadQueue.push(Promise);
ResourceLoadNotifier.notify_all();
}
} else {
Promise->bHasResourceLoaded = true;
Promise->resource = resCacheFind->second;
}
return Promise;
return Promise;
}
else
{
return resCacheFind->second;
}
}
std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> ResourceMgr::CacheDirectoryAsync(std::string SearchMask) {
@ -282,10 +285,15 @@ namespace Ship {
auto fileList = OTR->ListFiles(SearchMask);
for (DWORD i = 0; i < fileList.size(); i++) {
auto file = LoadResourceAsync(fileList.operator[](i).cFileName);
if (file != nullptr) {
loadedList->push_back(file);
auto resource = LoadResourceAsync(fileList.operator[](i).cFileName);
if (std::holds_alternative<std::shared_ptr<Resource>>(resource))
{
auto promise = std::make_shared<ResourcePromise>();
promise->bHasResourceLoaded = true;
promise->resource = std::get<std::shared_ptr<Resource>>(resource);
resource = promise;
}
loadedList->push_back(std::get<std::shared_ptr<ResourcePromise>>(resource));
}
return loadedList;
@ -335,7 +343,7 @@ namespace Ship {
ResourceCache.clear();
}
std::string ResourceMgr::HashToString(uint64_t Hash) {
const std::string* ResourceMgr::HashToString(uint64_t Hash) const {
return OTR->HashToString(Hash);
}
}

View File

@ -4,6 +4,7 @@
#include <string>
#include <thread>
#include <queue>
#include <variant>
#include "Resource.h"
#include "GlobalCtx2.h"
@ -25,7 +26,7 @@ namespace Ship
std::shared_ptr<Archive> GetArchive() { return OTR; }
std::shared_ptr<GlobalCtx2> GetContext() { return Context.lock(); }
std::string HashToString(uint64_t Hash);
const std::string* HashToString(uint64_t Hash) const;
void InvalidateResourceCache();
@ -33,9 +34,10 @@ namespace Ship
void SetGameVersion(uint32_t newGameVersion);
std::shared_ptr<File> LoadFileAsync(std::string FilePath);
std::shared_ptr<File> LoadFile(std::string FilePath);
std::shared_ptr<Ship::Resource> GetCachedFile(std::string FilePath);
std::shared_ptr<Resource> LoadResource(std::string FilePath);
std::shared_ptr<ResourcePromise> LoadResourceAsync(std::string FilePath);
std::shared_ptr<Ship::Resource> GetCachedFile(const char* FilePath) const;
std::shared_ptr<Resource> LoadResource(const char* FilePath);
std::shared_ptr<Resource> LoadResource(const std::string& FilePath) { return LoadResource(FilePath.c_str()); }
std::variant<std::shared_ptr<Resource>, std::shared_ptr<ResourcePromise>> LoadResourceAsync(const char* FilePath);
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> CacheDirectory(std::string SearchMask);
std::shared_ptr<std::vector<std::shared_ptr<ResourcePromise>>> CacheDirectoryAsync(std::string SearchMask);
std::shared_ptr<std::vector<std::shared_ptr<Resource>>> DirtyDirectory(std::string SearchMask);
@ -50,7 +52,7 @@ namespace Ship
std::weak_ptr<GlobalCtx2> Context;
volatile bool bIsRunning;
std::map<std::string, std::shared_ptr<File>> FileCache;
std::map<std::string, std::shared_ptr<Resource>> ResourceCache;
std::map<std::string, std::shared_ptr<Resource>, std::less<>> ResourceCache;
std::queue<std::shared_ptr<File>> FileLoadQueue;
std::queue<std::shared_ptr<ResourcePromise>> ResourceLoadQueue;
std::shared_ptr<Archive> OTR;

View File

@ -363,7 +363,7 @@ namespace SohImGui {
ModInternal::registerHookListener({ CONTROLLER_READ, [](const HookEvent ev) {
pads = static_cast<OSContPad*>(ev->baseArgs["cont_pad"]);
}});
} });
Game::InitSettings();
}
@ -402,7 +402,7 @@ namespace SohImGui {
EnhancementRadioButton("French", "gLanguages", 2);
*/
int val = CVar_GetS32(cvarName.c_str(), 0);
if (ImGui::RadioButton(text.c_str(), id==val)) {
if (ImGui::RadioButton(text.c_str(), id == val)) {
CVar_SetS32(cvarName.c_str(), (int)id);
needs_save = true;
}
@ -505,7 +505,12 @@ namespace SohImGui {
}
}
void DrawMainMenuAndCalculateGameSize() {
void Tooltip(std::string text) {
if (ImGui::IsItemHovered())
ImGui::SetTooltip("%s", text.c_str());
}
void DrawMainMenuAndCalculateGameSize() {
console->Update();
ImGuiBackendNewFrame();
ImGuiWMNewFrame();
@ -603,15 +608,17 @@ namespace SohImGui {
}
EnhancementCheckbox("Show Inputs", "gInputEnabled");
Tooltip("Shows currently pressed inputs on the bottom right of the screen");
EnhancementCheckbox("Rumble Enabled", "gRumbleEnabled");
EnhancementSliderFloat("Input Scale: %.1f", "##Input", "gInputScale", 1.0f, 3.0f, "", 1.0f, false);
Tooltip("Sets the on screen size of the displayed inputs from Show Inputs");
ImGui::Separator();
EnhancementCheckbox("Dpad Support on Pause and File Select", "gDpadPauseName");
EnhancementCheckbox("DPad Support in Ocarina and Text Choice", "gDpadOcarinaText");
EnhancementCheckbox("DPad Support for Browsing Shop Items", "gDpadShop");
EnhancementCheckbox("D-pad Support on Pause and File Select", "gDpadPauseName");
EnhancementCheckbox("D-pad Support in Ocarina and Text Choice", "gDpadOcarinaText");
EnhancementCheckbox("D-pad Support for Browsing Shop Items", "gDpadShop");
ImGui::EndMenu();
}
@ -619,8 +626,10 @@ namespace SohImGui {
if (ImGui::BeginMenu("Graphics"))
{
EnhancementSliderInt("Internal Resolution: %dx", "##IMul", "gInternalResolution", 1, 8, "");
Tooltip("Increases the render resolution of the game, up to 8x your output resolution,\nas a more intensive but effective form of anti-aliasing");
gfx_current_dimensions.internal_mul = CVar_GetS32("gInternalResolution", 1);
EnhancementSliderInt("MSAA: %d", "##IMSAA", "gMSAAValue", 1, 8, "");
Tooltip("Activates anti-aliasing when above 1, up to 8x for 8 samples for every pixel");
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
EXPERIMENTAL();
@ -632,7 +641,7 @@ namespace SohImGui {
INFO("New Filter: %s", filters[fId]);
gapi->set_texture_filter((FilteringMode)fId);
CVar_SetS32("gTextureFilter", (int) fId);
CVar_SetS32("gTextureFilter", (int)fId);
needs_save = true;
}
@ -652,36 +661,59 @@ namespace SohImGui {
if (ImGui::BeginMenu("Enhancements"))
{
ImGui::Text("Gameplay");
ImGui::Separator();
if (ImGui::BeginMenu("Gameplay"))
{
EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "");
EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, "");
EnhancementSliderInt("Text Speed: %dx", "##TEXTSPEED", "gTextSpeed", 1, 5, "");
EnhancementSliderInt("King Zora Speed: %dx", "##WEEPSPEED", "gMweepSpeed", 1, 5, "");
EnhancementCheckbox("Skip Text", "gSkipText");
Tooltip("Holding down B skips text");
EnhancementCheckbox("Mute Low HP Alarm", "gLowHpAlarm");
Tooltip("Disable the low HP beeping sound");
EnhancementCheckbox("Minimal UI", "gMinimalUI");
Tooltip("Hides most of the UI when not needed");
EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony");
Tooltip("Displays an icon and plays a sound when Stone of Agony should be activated, for those without rumble");
EnhancementCheckbox("Faster Block Push", "gFasterBlockPush");
EnhancementCheckbox("Assignable Tunics and Boots", "gAssignableTunicsAndBoots");
Tooltip("Allows equiping the tunic and boots to c-buttons");
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask");
EnhancementCheckbox("Skip Text", "gSkipText");
EnhancementCheckbox("Minimal UI", "gMinimalUI");
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
EnhancementCheckbox("Visual Stone of Agony", "gVisualAgony");
ImGui::EndMenu();
}
ImGui::Text("Graphics");
ImGui::Separator();
if (ImGui::BeginMenu("Graphics"))
{
EnhancementCheckbox("N64 Mode", "gN64Mode");
Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops");
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
Tooltip("Changes the rupee in the wallet icon to match the wallet size you currently have");
EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon");
Tooltip("Always shows dungeon entrance icons on the minimap");
EnhancementCheckbox("N64 Mode", "gN64Mode");
ImGui::EndMenu();
}
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
EnhancementCheckbox("Enable 3D Dropped items", "gNewDrops");
EnhancementCheckbox("Faster Block Push", "gFasterBlockPush");
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
EnhancementCheckbox("Always show dungeon entrances", "gAlwaysShowDungeonMinimapIcon");
if (ImGui::BeginMenu("Fixes"))
{
EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR");
Tooltip("Makes the L and R buttons in the pause menu the same color");
EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon");
Tooltip("Show dungeon entrances icon only when it should be");
EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle");
Tooltip("Makes two handed idle animation play, a seemingly finished animation that was disabled on accident in the original game");
ImGui::Text("Fixes");
ImGui::Separator();
EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR");
EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon");
ImGui::EndMenu();
}
EXPERIMENTAL();
EnhancementCheckbox("60FPS Interpolation", "g60FPS");
EnhancementCheckbox("Disable LOD", "gDisableLOD");
Tooltip("Turns off the level of detail setting, making models always use their higher poly variants");
ImGui::EndMenu();
}
@ -723,12 +755,19 @@ namespace SohImGui {
}
EnhancementCheckbox("No Clip", "gNoClip");
Tooltip("Allows you to walk through walls");
EnhancementCheckbox("Climb Everything", "gClimbEverything");
Tooltip("Makes every surface in the game climbable");
EnhancementCheckbox("Moon Jump on L", "gMoonJumpOnL");
Tooltip("Holding L makes you float into the air");
EnhancementCheckbox("Super Tunic", "gSuperTunic");
Tooltip("Makes every tunic have the effects of every other tunic");
EnhancementCheckbox("Easy ISG", "gEzISG");
Tooltip("Automatically activates the Infinite Sword glitch, making you constantly swing your sword");
EnhancementCheckbox("Unrestricted Items", "gNoRestrictItems");
Tooltip("Allows you to use any item at any location");
EnhancementCheckbox("Freeze Time", "gFreezeTime");
Tooltip("Freezes the time of day");
ImGui::EndMenu();
}
@ -736,9 +775,12 @@ namespace SohImGui {
if (ImGui::BeginMenu("Developer Tools"))
{
EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
Tooltip("Enables Debug Mode, allowing you to select maps with L + R + Z, noclip with L + D-pad Right,\nand open the debug menu with L on the pause screen");
ImGui::Separator();
EnhancementCheckbox("Stats", "gStatsEnabled");
Tooltip("Shows the stats window, with your FPS and frametimes, and the OS you're playing on");
EnhancementCheckbox("Console", "gConsoleEnabled");
Tooltip("Enables the console window, allowing you to input commands, type help for some examples");
console->opened = CVar_GetS32("gConsoleEnabled", 0);
ImGui::EndMenu();
@ -748,7 +790,7 @@ namespace SohImGui {
if (ImGui::BeginMenu(category.first.c_str())) {
for (const std::string& name : category.second) {
std::string varName(name);
varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end());
varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end());
std::string toggleName = "g" + varName + "Enabled";
EnhancementCheckbox(name, toggleName);

View File

@ -119,17 +119,16 @@ extern "C" {
ModInternal::callBindHook(0);
}
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
strcpy(alloc, hashStr.c_str());
return (char*)hashStr.c_str();
const char* ResourceMgr_GetNameByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
return hashStr != nullptr ? hashStr->c_str() : nullptr;
}
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
//if (res != nullptr)
return (Vtx*)res->vertices.data();
@ -142,10 +141,10 @@ extern "C" {
}
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (int32_t*)res->mtx.data();
} else {
return nullptr;
@ -153,10 +152,10 @@ extern "C" {
}
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (Gfx*)&res->instructions[0];
} else {
return nullptr;
@ -164,14 +163,14 @@ extern "C" {
}
char* ResourceMgr_LoadTexByCRC(uint64_t crc) {
const std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (!hashStr.empty()) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get());
if (hashStr != nullptr) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get());
ModInternal::bindHook(LOAD_TEXTURE);
ModInternal::initBindHook(2,
HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }),
HookParameter({.name = "path", .parameter = (void*)hashStr->c_str() }),
HookParameter({.name = "texture", .parameter = static_cast<void*>(&res->imageData) })
);
ModInternal::callBindHook(0);
@ -184,11 +183,11 @@ extern "C" {
void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData)
{
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
if (hashStr != "")
if (hashStr != nullptr)
{
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get();
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get();
Ship::Patch patch;
patch.crc = hash;
@ -282,8 +281,12 @@ namespace Ship {
gfx_start_frame();
}
void Window::RunCommands(Gfx* Commands) {
gfx_run(Commands);
void Window::RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements) {
for (const auto& m : mtx_replacements) {
gfx_run(Commands, m);
gfx_end_frame();
}
gfx_run(Commands, {});
gfx_end_frame();
}

View File

@ -19,7 +19,7 @@ namespace Ship {
void MainLoop(void (*MainFunction)(void));
void Init();
void StartFrame();
void RunCommands(Gfx* Commands);
void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements);
void SetFrameDivisor(int divisor);
void GetPixelDepthPrepare(float x, float y);
uint16_t GetPixelDepth(float x, float y);

View File

@ -1,72 +1,72 @@
<Root>
<File Name="map_48x85_static" Segment="12">
<Texture Name="gDekuTreePauseScreenMapFloor3LeftTex" OutName="deku_tree_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor3RightTex" OutName="deku_tree_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor2LeftTex" OutName="deku_tree_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor2RightTex" OutName="deku_tree_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor1LeftTex" OutName="deku_tree_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor1RightTex" OutName="deku_tree_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement1LeftTex" OutName="deku_tree_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement1RightTex" OutName="deku_tree_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement2LeftTex" OutName="deku_tree_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement2RightTex" OutName="deku_tree_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2RightTex" OutName="dodongos_cavern_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1RightTex" OutName="dodongos_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapFloor1LeftTex" OutName="jabu_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapFloor1RightTex" OutName="jabu_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapBasement1LeftTex" OutName="jabu_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapBasement1RightTex" OutName="jabu_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor2LeftTex" OutName="forest_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor2RightTex" OutName="forest_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor1LeftTex" OutName="forest_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor1RightTex" OutName="forest_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement1LeftTex" OutName="forest_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement1RightTex" OutName="forest_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement2LeftTex" OutName="forest_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement2RightTex" OutName="forest_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor5LeftTex" OutName="fire_temple_pause_screen_map_floor_5_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor5RightTex" OutName="fire_temple_pause_screen_map_floor_5_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor4LeftTex" OutName="fire_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor4RightTex" OutName="fire_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor3LeftTex" OutName="fire_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor3RightTex" OutName="fire_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor2LeftTex" OutName="fire_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor2RightTex" OutName="fire_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor1LeftTex" OutName="fire_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor1RightTex" OutName="fire_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3LeftTex" OutName="water_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3RightTex" OutName="water_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2LeftTex" OutName="water_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2RightTex" OutName="water_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1LeftTex" OutName="water_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1RightTex" OutName="water_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1LeftTex" OutName="water_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1RightTex" OutName="water_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4LeftTex" OutName="spirit_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4RightTex" OutName="spirit_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3LeftTex" OutName="spirit_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3RightTex" OutName="spirit_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2LeftTex" OutName="spirit_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2RightTex" OutName="spirit_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1LeftTex" OutName="spirit_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1RightTex" OutName="spirit_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1LeftTex" OutName="shadow_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1RightTex" OutName="shadow_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2LeftTex" OutName="shadow_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2RightTex" OutName="shadow_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3LeftTex" OutName="shadow_temple_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3RightTex" OutName="shadow_temple_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4LeftTex" OutName="shadow_temple_pause_screen_map_basement_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4RightTex" OutName="shadow_temple_pause_screen_map_basement_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gIceCavernPauseScreenMapFloor1LeftTex" OutName="ice_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gIceCavernPauseScreenMapFloor1RightTex" OutName="ice_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor3LeftTex" OutName="deku_tree_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x0"/>
<Texture Name="gDekuTreePauseScreenMapFloor3RightTex" OutName="deku_tree_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x07F8"/>
<Texture Name="gDekuTreePauseScreenMapFloor2LeftTex" OutName="deku_tree_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x0FF0"/>
<Texture Name="gDekuTreePauseScreenMapFloor2RightTex" OutName="deku_tree_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x17E8"/>
<Texture Name="gDekuTreePauseScreenMapFloor1LeftTex" OutName="deku_tree_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x1FE0"/>
<Texture Name="gDekuTreePauseScreenMapFloor1RightTex" OutName="deku_tree_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x27D8"/>
<Texture Name="gDekuTreePauseScreenMapBasement1LeftTex" OutName="deku_tree_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x2FD0"/>
<Texture Name="gDekuTreePauseScreenMapBasement1RightTex" OutName="deku_tree_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x37C8"/>
<Texture Name="gDekuTreePauseScreenMapBasement2LeftTex" OutName="deku_tree_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x3FC0"/>
<Texture Name="gDekuTreePauseScreenMapBasement2RightTex" OutName="deku_tree_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x47B8"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x4FB0"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2RightTex" OutName="dodongos_cavern_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x57A8"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x5FA0"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1RightTex" OutName="dodongos_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x6798"/>
<Texture Name="gJabuPauseScreenMapFloor1LeftTex" OutName="jabu_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x6F90"/>
<Texture Name="gJabuPauseScreenMapFloor1RightTex" OutName="jabu_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x7788"/>
<Texture Name="gJabuPauseScreenMapBasement1LeftTex" OutName="jabu_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x7F80"/>
<Texture Name="gJabuPauseScreenMapBasement1RightTex" OutName="jabu_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x8778"/>
<Texture Name="gForestTemplePauseScreenMapFloor2LeftTex" OutName="forest_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x8F70"/>
<Texture Name="gForestTemplePauseScreenMapFloor2RightTex" OutName="forest_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x9768"/>
<Texture Name="gForestTemplePauseScreenMapFloor1LeftTex" OutName="forest_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x9F60"/>
<Texture Name="gForestTemplePauseScreenMapFloor1RightTex" OutName="forest_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0xA758"/>
<Texture Name="gForestTemplePauseScreenMapBasement1LeftTex" OutName="forest_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0xAF50"/>
<Texture Name="gForestTemplePauseScreenMapBasement1RightTex" OutName="forest_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0xB748"/>
<Texture Name="gForestTemplePauseScreenMapBasement2LeftTex" OutName="forest_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0xBF40"/>
<Texture Name="gForestTemplePauseScreenMapBasement2RightTex" OutName="forest_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0xC738"/>
<Texture Name="gFireTemplePauseScreenMapFloor5LeftTex" OutName="fire_temple_pause_screen_map_floor_5_left" Format="ci4" Width="48" Height="85" Offset="0xCF30"/>
<Texture Name="gFireTemplePauseScreenMapFloor5RightTex" OutName="fire_temple_pause_screen_map_floor_5_right" Format="ci4" Width="48" Height="85" Offset="0xD728"/>
<Texture Name="gFireTemplePauseScreenMapFloor4LeftTex" OutName="fire_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85" Offset="0xDF20"/>
<Texture Name="gFireTemplePauseScreenMapFloor4RightTex" OutName="fire_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85" Offset="0xE718"/>
<Texture Name="gFireTemplePauseScreenMapFloor3LeftTex" OutName="fire_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0xEF10"/>
<Texture Name="gFireTemplePauseScreenMapFloor3RightTex" OutName="fire_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0xF708"/>
<Texture Name="gFireTemplePauseScreenMapFloor2LeftTex" OutName="fire_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0xFF00"/>
<Texture Name="gFireTemplePauseScreenMapFloor2RightTex" OutName="fire_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x106F8"/>
<Texture Name="gFireTemplePauseScreenMapFloor1LeftTex" OutName="fire_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x10EF0"/>
<Texture Name="gFireTemplePauseScreenMapFloor1RightTex" OutName="fire_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x116E8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3LeftTex" OutName="water_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x11EE0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3RightTex" OutName="water_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x126D8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2LeftTex" OutName="water_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x12ED0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2RightTex" OutName="water_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x136C8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1LeftTex" OutName="water_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x13EC0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1RightTex" OutName="water_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x146B8"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1LeftTex" OutName="water_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x14EB0"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1RightTex" OutName="water_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x156A8"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4LeftTex" OutName="spirit_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85" Offset="0x15EA0"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4RightTex" OutName="spirit_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85" Offset="0x16698"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3LeftTex" OutName="spirit_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x16E90"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3RightTex" OutName="spirit_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x17688"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2LeftTex" OutName="spirit_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x17E80"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2RightTex" OutName="spirit_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x18678"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1LeftTex" OutName="spirit_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x18E70"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1RightTex" OutName="spirit_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x19668"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1LeftTex" OutName="shadow_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x19E60"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1RightTex" OutName="shadow_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x1A658"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2LeftTex" OutName="shadow_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x1AE50"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2RightTex" OutName="shadow_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x1B648"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3LeftTex" OutName="shadow_temple_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85" Offset="0x1BE40"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3RightTex" OutName="shadow_temple_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85" Offset="0x1C638"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4LeftTex" OutName="shadow_temple_pause_screen_map_basement_4_left" Format="ci4" Width="48" Height="85" Offset="0x1CE30"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4RightTex" OutName="shadow_temple_pause_screen_map_basement_4_right" Format="ci4" Width="48" Height="85" Offset="0x1D628"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x1DE20"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x1E618"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x1EE10"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x1F608"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85" Offset="0x1FE00"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85" Offset="0x205F8"/>
<Texture Name="gIceCavernPauseScreenMapFloor1LeftTex" OutName="ice_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x20DF0"/>
<Texture Name="gIceCavernPauseScreenMapFloor1RightTex" OutName="ice_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x215E8"/>
</File>
</Root>

View File

@ -1,72 +1,72 @@
<Root>
<File Name="map_48x85_static" Segment="12">
<Texture Name="gDekuTreePauseScreenMapFloor3LeftTex" OutName="deku_tree_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor3RightTex" OutName="deku_tree_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor2LeftTex" OutName="deku_tree_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor2RightTex" OutName="deku_tree_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor1LeftTex" OutName="deku_tree_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor1RightTex" OutName="deku_tree_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement1LeftTex" OutName="deku_tree_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement1RightTex" OutName="deku_tree_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement2LeftTex" OutName="deku_tree_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapBasement2RightTex" OutName="deku_tree_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2RightTex" OutName="dodongos_cavern_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1RightTex" OutName="dodongos_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapFloor1LeftTex" OutName="jabu_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapFloor1RightTex" OutName="jabu_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapBasement1LeftTex" OutName="jabu_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gJabuPauseScreenMapBasement1RightTex" OutName="jabu_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor2LeftTex" OutName="forest_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor2RightTex" OutName="forest_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor1LeftTex" OutName="forest_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapFloor1RightTex" OutName="forest_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement1LeftTex" OutName="forest_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement1RightTex" OutName="forest_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement2LeftTex" OutName="forest_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gForestTemplePauseScreenMapBasement2RightTex" OutName="forest_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor5LeftTex" OutName="fire_temple_pause_screen_map_floor_5_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor5RightTex" OutName="fire_temple_pause_screen_map_floor_5_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor4LeftTex" OutName="fire_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor4RightTex" OutName="fire_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor3LeftTex" OutName="fire_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor3RightTex" OutName="fire_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor2LeftTex" OutName="fire_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor2RightTex" OutName="fire_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor1LeftTex" OutName="fire_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gFireTemplePauseScreenMapFloor1RightTex" OutName="fire_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3LeftTex" OutName="water_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3RightTex" OutName="water_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2LeftTex" OutName="water_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2RightTex" OutName="water_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1LeftTex" OutName="water_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1RightTex" OutName="water_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1LeftTex" OutName="water_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1RightTex" OutName="water_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4LeftTex" OutName="spirit_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4RightTex" OutName="spirit_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3LeftTex" OutName="spirit_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3RightTex" OutName="spirit_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2LeftTex" OutName="spirit_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2RightTex" OutName="spirit_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1LeftTex" OutName="spirit_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1RightTex" OutName="spirit_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1LeftTex" OutName="shadow_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1RightTex" OutName="shadow_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2LeftTex" OutName="shadow_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2RightTex" OutName="shadow_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3LeftTex" OutName="shadow_temple_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3RightTex" OutName="shadow_temple_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4LeftTex" OutName="shadow_temple_pause_screen_map_basement_4_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4RightTex" OutName="shadow_temple_pause_screen_map_basement_4_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gIceCavernPauseScreenMapFloor1LeftTex" OutName="ice_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85"/>
<Texture Name="gIceCavernPauseScreenMapFloor1RightTex" OutName="ice_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85"/>
<Texture Name="gDekuTreePauseScreenMapFloor3LeftTex" OutName="deku_tree_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x0"/>
<Texture Name="gDekuTreePauseScreenMapFloor3RightTex" OutName="deku_tree_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x07F8"/>
<Texture Name="gDekuTreePauseScreenMapFloor2LeftTex" OutName="deku_tree_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x0FF0"/>
<Texture Name="gDekuTreePauseScreenMapFloor2RightTex" OutName="deku_tree_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x17E8"/>
<Texture Name="gDekuTreePauseScreenMapFloor1LeftTex" OutName="deku_tree_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x1FE0"/>
<Texture Name="gDekuTreePauseScreenMapFloor1RightTex" OutName="deku_tree_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x27D8"/>
<Texture Name="gDekuTreePauseScreenMapBasement1LeftTex" OutName="deku_tree_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x2FD0"/>
<Texture Name="gDekuTreePauseScreenMapBasement1RightTex" OutName="deku_tree_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x37C8"/>
<Texture Name="gDekuTreePauseScreenMapBasement2LeftTex" OutName="deku_tree_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x3FC0"/>
<Texture Name="gDekuTreePauseScreenMapBasement2RightTex" OutName="deku_tree_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x47B8"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x4FB0"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor2RightTex" OutName="dodongos_cavern_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x57A8"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1LeftTex" OutName="dodongos_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x5FA0"/>
<Texture Name="gDodongosCavernPauseScreenMapFloor1RightTex" OutName="dodongos_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x6798"/>
<Texture Name="gJabuPauseScreenMapFloor1LeftTex" OutName="jabu_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x6F90"/>
<Texture Name="gJabuPauseScreenMapFloor1RightTex" OutName="jabu_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x7788"/>
<Texture Name="gJabuPauseScreenMapBasement1LeftTex" OutName="jabu_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x7F80"/>
<Texture Name="gJabuPauseScreenMapBasement1RightTex" OutName="jabu_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x8778"/>
<Texture Name="gForestTemplePauseScreenMapFloor2LeftTex" OutName="forest_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x8F70"/>
<Texture Name="gForestTemplePauseScreenMapFloor2RightTex" OutName="forest_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x9768"/>
<Texture Name="gForestTemplePauseScreenMapFloor1LeftTex" OutName="forest_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x9F60"/>
<Texture Name="gForestTemplePauseScreenMapFloor1RightTex" OutName="forest_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0xA758"/>
<Texture Name="gForestTemplePauseScreenMapBasement1LeftTex" OutName="forest_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0xAF50"/>
<Texture Name="gForestTemplePauseScreenMapBasement1RightTex" OutName="forest_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0xB748"/>
<Texture Name="gForestTemplePauseScreenMapBasement2LeftTex" OutName="forest_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0xBF40"/>
<Texture Name="gForestTemplePauseScreenMapBasement2RightTex" OutName="forest_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0xC738"/>
<Texture Name="gFireTemplePauseScreenMapFloor5LeftTex" OutName="fire_temple_pause_screen_map_floor_5_left" Format="ci4" Width="48" Height="85" Offset="0xCF30"/>
<Texture Name="gFireTemplePauseScreenMapFloor5RightTex" OutName="fire_temple_pause_screen_map_floor_5_right" Format="ci4" Width="48" Height="85" Offset="0xD728"/>
<Texture Name="gFireTemplePauseScreenMapFloor4LeftTex" OutName="fire_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85" Offset="0xDF20"/>
<Texture Name="gFireTemplePauseScreenMapFloor4RightTex" OutName="fire_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85" Offset="0xE718"/>
<Texture Name="gFireTemplePauseScreenMapFloor3LeftTex" OutName="fire_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0xEF10"/>
<Texture Name="gFireTemplePauseScreenMapFloor3RightTex" OutName="fire_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0xF708"/>
<Texture Name="gFireTemplePauseScreenMapFloor2LeftTex" OutName="fire_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0xFF00"/>
<Texture Name="gFireTemplePauseScreenMapFloor2RightTex" OutName="fire_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x106F8"/>
<Texture Name="gFireTemplePauseScreenMapFloor1LeftTex" OutName="fire_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x10EF0"/>
<Texture Name="gFireTemplePauseScreenMapFloor1RightTex" OutName="fire_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x116E8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3LeftTex" OutName="water_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x11EE0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor3RightTex" OutName="water_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x126D8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2LeftTex" OutName="water_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x12ED0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor2RightTex" OutName="water_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x136C8"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1LeftTex" OutName="water_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x13EC0"/>
<Texture Name="gWaterTemplePauseScreenMapFloor1RightTex" OutName="water_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x146B8"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1LeftTex" OutName="water_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x14EB0"/>
<Texture Name="gWaterTemplePauseScreenMapBasement1RightTex" OutName="water_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x156A8"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4LeftTex" OutName="spirit_temple_pause_screen_map_floor_4_left" Format="ci4" Width="48" Height="85" Offset="0x15EA0"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor4RightTex" OutName="spirit_temple_pause_screen_map_floor_4_right" Format="ci4" Width="48" Height="85" Offset="0x16698"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3LeftTex" OutName="spirit_temple_pause_screen_map_floor_3_left" Format="ci4" Width="48" Height="85" Offset="0x16E90"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor3RightTex" OutName="spirit_temple_pause_screen_map_floor_3_right" Format="ci4" Width="48" Height="85" Offset="0x17688"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2LeftTex" OutName="spirit_temple_pause_screen_map_floor_2_left" Format="ci4" Width="48" Height="85" Offset="0x17E80"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor2RightTex" OutName="spirit_temple_pause_screen_map_floor_2_right" Format="ci4" Width="48" Height="85" Offset="0x18678"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1LeftTex" OutName="spirit_temple_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x18E70"/>
<Texture Name="gSpiritTemplePauseScreenMapFloor1RightTex" OutName="spirit_temple_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x19668"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1LeftTex" OutName="shadow_temple_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x19E60"/>
<Texture Name="gShadowTemplePauseScreenMapBasement1RightTex" OutName="shadow_temple_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x1A658"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2LeftTex" OutName="shadow_temple_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x1AE50"/>
<Texture Name="gShadowTemplePauseScreenMapBasement2RightTex" OutName="shadow_temple_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x1B648"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3LeftTex" OutName="shadow_temple_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85" Offset="0x1BE40"/>
<Texture Name="gShadowTemplePauseScreenMapBasement3RightTex" OutName="shadow_temple_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85" Offset="0x1C638"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4LeftTex" OutName="shadow_temple_pause_screen_map_basement_4_left" Format="ci4" Width="48" Height="85" Offset="0x1CE30"/>
<Texture Name="gShadowTemplePauseScreenMapBasement4RightTex" OutName="shadow_temple_pause_screen_map_basement_4_right" Format="ci4" Width="48" Height="85" Offset="0x1D628"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_left" Format="ci4" Width="48" Height="85" Offset="0x1DE20"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement1RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_1_right" Format="ci4" Width="48" Height="85" Offset="0x1E618"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_left" Format="ci4" Width="48" Height="85" Offset="0x1EE10"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement2RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_2_right" Format="ci4" Width="48" Height="85" Offset="0x1F608"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3LeftTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_left" Format="ci4" Width="48" Height="85" Offset="0x1FE00"/>
<Texture Name="gBottomOfTheWellPauseScreenMapBasement3RightTex" OutName="bottom_of_the_well_pause_screen_map_basement_3_right" Format="ci4" Width="48" Height="85" Offset="0x205F8"/>
<Texture Name="gIceCavernPauseScreenMapFloor1LeftTex" OutName="ice_cavern_pause_screen_map_floor_1_left" Format="ci4" Width="48" Height="85" Offset="0x20DF0"/>
<Texture Name="gIceCavernPauseScreenMapFloor1RightTex" OutName="ice_cavern_pause_screen_map_floor_1_right" Format="ci4" Width="48" Height="85" Offset="0x215E8"/>
</File>
</Root>
</Root>

View File

@ -138,6 +138,8 @@ extern GraphicsContext* __gfxCtx;
#ifndef NDEBUG
#define OPEN_DISPS(gfxCtx, file, line) \
{ \
void FrameInterpolation_RecordOpenChild(const void* a, int b); \
FrameInterpolation_RecordOpenChild(file, line); \
GraphicsContext* __gfxCtx; \
Gfx* dispRefs[4]; \
__gfxCtx = gfxCtx; \
@ -146,6 +148,8 @@ extern GraphicsContext* __gfxCtx;
#else
#define OPEN_DISPS(gfxCtx, file, line) \
{ \
void FrameInterpolation_RecordOpenChild(const void* a, int b); \
FrameInterpolation_RecordOpenChild(file, line); \
GraphicsContext* __gfxCtx; \
__gfxCtx = gfxCtx; \
(void)__gfxCtx;
@ -153,11 +157,15 @@ extern GraphicsContext* __gfxCtx;
#ifndef NDEBUG
#define CLOSE_DISPS(gfxCtx, file, line) \
{void FrameInterpolation_RecordCloseChild(void); \
FrameInterpolation_RecordCloseChild();} \
Graph_CloseDisps(dispRefs, gfxCtx, file, line); \
} \
(void)0
#else
#define CLOSE_DISPS(gfxCtx, file, line) \
{void FrameInterpolation_RecordCloseChild(void); \
FrameInterpolation_RecordCloseChild();} \
(void)0; \
} \
(void)0

View File

@ -225,6 +225,7 @@ typedef struct EffectSs {
/* 0x5C */ s16 life; // -1 means this entry is free
/* 0x5E */ u8 priority; // Lower value means higher priority
/* 0x5F */ u8 type;
u32 epoch;
} EffectSs; // size = 0x60
typedef struct {

View File

@ -78,6 +78,12 @@ typedef enum {
/* 0x15 */ SLOT_BOTTLE_4,
/* 0x16 */ SLOT_TRADE_ADULT,
/* 0x17 */ SLOT_TRADE_CHILD,
/* 0x18 */ SLOT_TUNIC_KOKIRI,
/* 0x19 */ SLOT_TUNIC_GORON,
/* 0x1A */ SLOT_TUNIC_ZORA,
/* 0x1B */ SLOT_BOOTS_KOKIRI,
/* 0x1C */ SLOT_BOOTS_IRON,
/* 0x1D */ SLOT_BOOTS_HOVER,
/* 0xFF */ SLOT_NONE = 0xFF
} InventorySlot;

View File

@ -128,7 +128,16 @@ typedef enum {
/* 0x40 */ PLAYER_AP_MASK_GERUDO,
/* 0x41 */ PLAYER_AP_MASK_TRUTH,
/* 0x42 */ PLAYER_AP_LENS,
/* 0x43 */ PLAYER_AP_MAX
/* 0x43 */ PLAYER_AP_SHIELD_DEKU,
/* 0x44 */ PLAYER_AP_SHIELD_HYLIAN,
/* 0x45 */ PLAYER_AP_SHIELD_MIRROR,
/* 0x46 */ PLAYER_AP_TUNIC_KOKIRI,
/* 0x47 */ PLAYER_AP_TUNIC_GORON,
/* 0x48 */ PLAYER_AP_TUNIC_ZORA,
/* 0x49 */ PLAYER_AP_BOOTS_KOKIRI,
/* 0x4A */ PLAYER_AP_BOOTS_IRON,
/* 0x4B */ PLAYER_AP_BOOTS_HOVER,
/* 0x4C */ PLAYER_AP_MAX
} PlayerActionParam;
typedef enum {

View File

@ -173,6 +173,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="soh\frame_interpolation.cpp" />
<ClCompile Include="soh\Enhancements\bootcommands.c" />
<ClCompile Include="soh\Enhancements\debugconsole.cpp" />
<ClCompile Include="soh\Enhancements\debugger\colViewer.cpp" />
@ -878,6 +879,7 @@
<ClCompile Include="src\overlays\misc\ovl_map_mark_data\z_map_mark_data.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="soh\frame_interpolation.h" />
<ClInclude Include="include\alloca.h" />
<ClInclude Include="include\bgm.h" />
<ClInclude Include="include\color.h" />

View File

@ -2186,6 +2186,8 @@
</ClCompile>
<ClCompile Include="soh\Enhancements\debugger\ImGuiHelpers.cpp">
<Filter>Source Files\soh\Enhancements\debugger</Filter>
<ClCompile Include="soh\frame_interpolation.cpp">
<Filter>Source Files\soh</Filter>
</ClCompile>
<ClCompile Include="src\code\z_cheap_proc.c">
<Filter>Source Files</Filter>
@ -3748,6 +3750,8 @@
</ClInclude>
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h">
<Filter>Header Files\soh\Enhancements\debugger</Filter>
<ClInclude Include="soh\frame_interpolation.h">
<Filter>Header Files\soh</Filter>
</ClInclude>
<ClInclude Include="soh\Enhancements\savestates.h">
<Filter>Source Files\soh\Enhancements</Filter>

View File

@ -27,6 +27,7 @@ void BootCommands_Init()
CVar_RegisterS32("gMinimalUI", 0);
CVar_RegisterS32("gRumbleEnabled", 0);
CVar_RegisterS32("gUniformLR", 1);
CVar_RegisterS32("gTwoHandedIdle", 0);
CVar_RegisterS32("gNewDrops", 0);
CVar_RegisterS32("gVisualAgony", 0);
CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French

View File

@ -1,6 +1,7 @@
#include "colViewer.h"
#include "../libultraship/SohImGuiImpl.h"
#include "ImGuiHelpers.h"
#include "../../frame_interpolation.h"
#include <vector>
#include <string>

View File

@ -29,6 +29,7 @@
#include "AudioPlayer.h"
#include "Enhancements/debugconsole.h"
#include "Enhancements/debugger/debugger.h"
#include "soh/frame_interpolation.h"
#include "Utils/BitConverter.h"
#include "variables.h"
#include "macros.h"
@ -174,7 +175,7 @@ extern "C" void Graph_StartFrame() {
// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
OTRGlobals::Instance->context->GetWindow()->SetFrameDivisor(R_UPDATE_RATE);
OTRGlobals::Instance->context->GetWindow()->SetFrameDivisor(CVar_GetS32("g60FPS", 0) == 0 ? R_UPDATE_RATE : 1);
if (!audio.initialized) {
audio.initialized = true;
@ -224,7 +225,15 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
}
audio.cv_to_thread.notify_one();
OTRGlobals::Instance->context->GetWindow()->RunCommands(commands);
std::vector<std::unordered_map<Mtx*, MtxF>> mtx_replacements;
if (CVar_GetS32("g60FPS", 0) != 0) {
int to = R_UPDATE_RATE;
for (int i = 1; i < to; i++) {
mtx_replacements.push_back(FrameInterpolation_Interpolate(i / (float)to));
}
}
OTRGlobals::Instance->context->GetWindow()->RunCommands(commands, mtx_replacements);
{
std::unique_lock<std::mutex> Lock(audio.mutex);

View File

@ -0,0 +1,732 @@
#include "Cvar.h"
#include <vector>
#include <map>
#include <unordered_map>
#include <math.h>
#include "frame_interpolation.h"
/*
Frame interpolation.
The idea of this code is to interpolate all matrices.
The code contains two approaches. The first is to interpolate
all inputs in transformations, such as angles, scale and distances,
and then perform the same transformations with the interpolated values.
After evaluation for some reason some animations such rolling look strange.
The second approach is to simply interpolate the final matrices. This will
more or less simply interpolate the world coordinates for movements.
This will however make rotations ~180 degrees get the "paper effect".
The mitigation is to identify this case for actors and interpolate the
matrix but in model coordinates instead, by "removing" the rotation-
translation before interpolating, create a rotation matrix with the
interpolated angle which is then applied to the matrix.
Currently the code contains both methods but only the second one is currently
used.
Both approaches build a tree of instructions, containing matrices
at leaves. Every node is built from OPEN_DISPS/CLOSE_DISPS and manually
inserted FrameInterpolation_OpenChild/FrameInterpolation_Close child calls.
These nodes contain information that should suffice to identify the matrix,
so we can find it in an adjacent frame.
We can interpolate an arbitrary amount of frames between two original frames,
given a specific interpolation factor (0=old frame, 0.5=average of frames,
1.0=new frame).
*/
extern "C" {
void Matrix_Init(struct GameState* gameState);
void Matrix_Push(void);
void Matrix_Pop(void);
void Matrix_Get(MtxF* dest);
void Matrix_Put(MtxF* src);
void Matrix_Mult(MtxF* mf, u8 mode);
void Matrix_Translate(f32 x, f32 y, f32 z, u8 mode);
void Matrix_Scale(f32 x, f32 y, f32 z, u8 mode);
void Matrix_RotateX(f32 x, u8 mode);
void Matrix_RotateY(f32 y, u8 mode);
void Matrix_RotateZ(f32 z, u8 mode);
void Matrix_RotateZYX(s16 x, s16 y, s16 z, u8 mode);
void Matrix_TranslateRotateZYX(Vec3f* translation, Vec3s* rotation);
void Matrix_SetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot);
Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest);
Mtx* Matrix_ToMtx(Mtx* dest, char* file, s32 line);
Mtx* Matrix_NewMtx(struct GraphicsContext* gfxCtx, char* file, s32 line);
Mtx* Matrix_MtxFToNewMtx(MtxF* src, struct GraphicsContext* gfxCtx);
void Matrix_MultVec3f(Vec3f* src, Vec3f* dest);
void Matrix_MtxFCopy(MtxF* dest, MtxF* src);
void Matrix_MtxToMtxF(Mtx* src, MtxF* dest);
void Matrix_MultVec3fExt(Vec3f* src, Vec3f* dest, MtxF* mf);
void Matrix_Transpose(MtxF* mf);
void Matrix_ReplaceRotation(MtxF* mf);
void Matrix_MtxFToYXZRotS(MtxF* mf, Vec3s* rotDest, s32 flag);
void Matrix_MtxFToZYXRotS(MtxF* mf, Vec3s* rotDest, s32 flag);
void Matrix_RotateAxis(f32 angle, Vec3f* axis, u8 mode);
MtxF* Matrix_CheckFloats(MtxF* mf, char* file, s32 line);
void Matrix_SetTranslateScaleMtx2(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY,
f32 translateZ);
MtxF* Matrix_GetCurrent(void);
void SkinMatrix_MtxFMtxFMult(MtxF* mfA, MtxF* mfB, MtxF* dest);
}
static bool invert_matrix(const float m[16], float invOut[16]);
using namespace std;
namespace {
enum class Op {
OpenChild,
CloseChild,
MatrixPush,
MatrixPop,
MatrixPut,
MatrixMult,
MatrixTranslate,
MatrixScale,
MatrixRotate1Coord,
MatrixRotateZYX,
MatrixTranslateRotateZYX,
MatrixSetTranslateRotateYXZ,
MatrixMtxFToMtx,
MatrixToMtx,
MatrixReplaceRotation,
MatrixRotateAxis,
SkinMatrixMtxFToMtx
};
typedef pair<const void*, int> label;
union Data {
Data() {
}
struct {
MtxF src;
} matrix_put;
struct {
MtxF mf;
u8 mode;
} matrix_mult;
struct {
f32 x, y, z;
u8 mode;
} matrix_translate, matrix_scale;
struct {
u32 coord;
f32 value;
u8 mode;
} matrix_rotate_1_coord;
struct {
s16 x, y, z;
u8 mode;
} matrix_rotate_zyx;
struct {
Vec3f translation;
Vec3s rotation;
} matrix_translate_rotate_zyx;
struct {
f32 translateX, translateY, translateZ;
Vec3s rot;
//MtxF mtx;
bool has_mtx;
} matrix_set_translate_rotate_yxz;
struct {
MtxF src;
Mtx* dest;
} matrix_mtxf_to_mtx;
struct {
Mtx* dest;
MtxF src;
bool has_adjusted;
} matrix_to_mtx;
struct {
MtxF mf;
} matrix_replace_rotation;
struct {
f32 angle;
Vec3f axis;
u8 mode;
} matrix_rotate_axis;
struct {
label key;
size_t idx;
} open_child;
};
struct Path {
map<label, vector<Path>> children;
map<Op, vector<Data>> ops;
vector<pair<Op, size_t>> items;
};
struct Recording {
Path root_path;
};
bool is_recording;
vector<Path*> current_path;
uint32_t camera_epoch;
uint32_t previous_camera_epoch;
Recording current_recording;
Recording previous_recording;
bool next_is_actor_pos_rot_matrix;
bool has_inv_actor_mtx;
MtxF inv_actor_mtx;
size_t inv_actor_mtx_path_index;
Data& append(Op op) {
auto& m = current_path.back()->ops[op];
current_path.back()->items.emplace_back(op, m.size());
return m.emplace_back();
}
struct InterpolateCtx {
float step;
float w;
unordered_map<Mtx*, MtxF> mtx_replacements;
MtxF tmp_mtxf, tmp_mtxf2;
Vec3f tmp_vec3f;
Vec3s tmp_vec3s;
MtxF actor_mtx;
MtxF* new_replacement(Mtx* addr) {
return &mtx_replacements[addr];
}
void interpolate_mtxf(MtxF* res, MtxF* o, MtxF* n) {
for (size_t i = 0; i < 4; i++) {
for (size_t j = 0; j < 4; j++) {
res->mf[i][j] = w * o->mf[i][j] + step * n->mf[i][j];
}
}
}
float lerp(f32 o, f32 n) {
return w * o + step * n;
}
void lerp_vec3f(Vec3f* res, Vec3f* o, Vec3f* n) {
res->x = lerp(o->x, n->x);
res->y = lerp(o->y, n->y);
res->z = lerp(o->z, n->z);
}
float interpolate_angle(f32 o, f32 n) {
if (o == n)
return n;
o = fmodf(o, 2 * M_PI);
if (o < 0.0f) {
o += 2 * M_PI;
}
n = fmodf(n, 2 * M_PI);
if (n < 0.0f) {
n += 2 * M_PI;
}
if (fabsf(o - n) > M_PI) {
if (o < n) {
o += 2 * M_PI;
} else {
n += 2 * M_PI;
}
}
if (fabsf(o - n) > M_PI / 2) {
//return n;
}
return lerp(o, n);
}
s16 interpolate_angle(s16 os, s16 ns) {
if (os == ns)
return ns;
int o = (u16)os;
int n = (u16)ns;
u16 res;
int diff = o - n;
if (-0x8000 <= diff && diff <= 0x8000) {
if (diff < -0x4000 || diff > 0x4000) {
return ns;
}
res = (u16)(w * o + step * n);
} else {
if (o < n) {
o += 0x10000;
} else {
n += 0x10000;
}
diff = o - n;
if (diff < -0x4000 || diff > 0x4000) {
return ns;
}
res = (u16)(w * o + step * n);
}
if (os / 327 == ns / 327 && (s16)res / 327 != os / 327) {
int bp = 0;
}
return res;
}
void interpolate_angles(Vec3s* res, Vec3s* o, Vec3s* n) {
res->x = interpolate_angle(o->x, n->x);
res->y = interpolate_angle(o->y, n->y);
res->z = interpolate_angle(o->z, n->z);
}
void interpolate_branch(Path* old_path, Path *new_path) {
for (auto& item : new_path->items) {
Data& new_op = new_path->ops[item.first][item.second];
if (item.first == Op::OpenChild) {
if (auto it = old_path->children.find(new_op.open_child.key);
it != old_path->children.end() && new_op.open_child.idx < it->second.size()) {
interpolate_branch(&it->second[new_op.open_child.idx],
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx]);
} else {
interpolate_branch(
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx],
&new_path->children.find(new_op.open_child.key)->second[new_op.open_child.idx]);
}
continue;
}
if (auto it = old_path->ops.find(item.first); it != old_path->ops.end()) {
if (item.second < it->second.size()) {
Data& old_op = it->second[item.second];
switch (item.first) {
case Op::OpenChild:
break;
case Op::CloseChild:
break;
case Op::MatrixPush:
Matrix_Push();
break;
case Op::MatrixPop:
Matrix_Pop();
break;
case Op::MatrixPut:
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_put.src, &new_op.matrix_put.src);
Matrix_Put(&tmp_mtxf);
break;
case Op::MatrixMult:
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_mult.mf, &new_op.matrix_mult.mf);
Matrix_Mult(&tmp_mtxf, new_op.matrix_mult.mode);
break;
case Op::MatrixTranslate:
Matrix_Translate(lerp(old_op.matrix_translate.x, new_op.matrix_translate.x),
lerp(old_op.matrix_translate.y, new_op.matrix_translate.y),
lerp(old_op.matrix_translate.z, new_op.matrix_translate.z),
new_op.matrix_translate.mode);
break;
case Op::MatrixScale:
Matrix_Scale(lerp(old_op.matrix_scale.x, new_op.matrix_scale.x),
lerp(old_op.matrix_scale.y, new_op.matrix_scale.y),
lerp(old_op.matrix_scale.z, new_op.matrix_scale.z),
new_op.matrix_scale.mode);
break;
case Op::MatrixRotate1Coord: {
float v = interpolate_angle(old_op.matrix_rotate_1_coord.value, new_op.matrix_rotate_1_coord.value);
u8 mode = new_op.matrix_rotate_1_coord.mode;
switch (new_op.matrix_rotate_1_coord.coord) {
case 0:
Matrix_RotateX(v, mode);
break;
case 1:
Matrix_RotateY(v, mode);
break;
case 2:
Matrix_RotateZ(v, mode);
break;
}
break;
}
case Op::MatrixRotateZYX:
Matrix_RotateZYX(interpolate_angle(old_op.matrix_rotate_zyx.x, new_op.matrix_rotate_zyx.x),
interpolate_angle(old_op.matrix_rotate_zyx.y, new_op.matrix_rotate_zyx.y),
interpolate_angle(old_op.matrix_rotate_zyx.z, new_op.matrix_rotate_zyx.z),
new_op.matrix_rotate_zyx.mode);
break;
case Op::MatrixTranslateRotateZYX:
lerp_vec3f(&tmp_vec3f, &old_op.matrix_translate_rotate_zyx.translation, &new_op.matrix_translate_rotate_zyx.translation);
interpolate_angles(&tmp_vec3s, &old_op.matrix_translate_rotate_zyx.rotation, &new_op.matrix_translate_rotate_zyx.rotation);
Matrix_TranslateRotateZYX(&tmp_vec3f, &tmp_vec3s);
break;
case Op::MatrixSetTranslateRotateYXZ:
interpolate_angles(&tmp_vec3s, &old_op.matrix_set_translate_rotate_yxz.rot,
&new_op.matrix_set_translate_rotate_yxz.rot);
Matrix_SetTranslateRotateYXZ(lerp(old_op.matrix_set_translate_rotate_yxz.translateX,
new_op.matrix_set_translate_rotate_yxz.translateX),
lerp(old_op.matrix_set_translate_rotate_yxz.translateY,
new_op.matrix_set_translate_rotate_yxz.translateY),
lerp(old_op.matrix_set_translate_rotate_yxz.translateZ,
new_op.matrix_set_translate_rotate_yxz.translateZ),
&tmp_vec3s);
if (new_op.matrix_set_translate_rotate_yxz.has_mtx && old_op.matrix_set_translate_rotate_yxz.has_mtx) {
actor_mtx = *Matrix_GetCurrent();
}
break;
case Op::MatrixMtxFToMtx:
interpolate_mtxf(new_replacement(new_op.matrix_mtxf_to_mtx.dest),
&old_op.matrix_mtxf_to_mtx.src, &new_op.matrix_mtxf_to_mtx.src);
break;
case Op::MatrixToMtx: {
//*new_replacement(new_op.matrix_to_mtx.dest) = *Matrix_GetCurrent();
if (old_op.matrix_to_mtx.has_adjusted && new_op.matrix_to_mtx.has_adjusted) {
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_to_mtx.src, &new_op.matrix_to_mtx.src);
SkinMatrix_MtxFMtxFMult(&actor_mtx, &tmp_mtxf, new_replacement(new_op.matrix_to_mtx.dest));
} else {
interpolate_mtxf(new_replacement(new_op.matrix_to_mtx.dest),
&old_op.matrix_to_mtx.src, &new_op.matrix_to_mtx.src);
}
break;
}
case Op::MatrixReplaceRotation:
interpolate_mtxf(&tmp_mtxf, &old_op.matrix_replace_rotation.mf, &new_op.matrix_replace_rotation.mf);
Matrix_ReplaceRotation(&tmp_mtxf);
break;
case Op::MatrixRotateAxis:
lerp_vec3f(&tmp_vec3f, &old_op.matrix_rotate_axis.axis, &new_op.matrix_rotate_axis.axis);
Matrix_RotateAxis(interpolate_angle(old_op.matrix_rotate_axis.angle, new_op.matrix_rotate_axis.angle),
&tmp_vec3f, new_op.matrix_rotate_axis.mode);
break;
case Op::SkinMatrixMtxFToMtx:
break;
}
}
}
}
}
};
} // anonymous namespace
unordered_map<Mtx*, MtxF> FrameInterpolation_Interpolate(float step) {
InterpolateCtx ctx;
ctx.step = step;
ctx.w = 1.0f - step;
ctx.interpolate_branch(&previous_recording.root_path, &current_recording.root_path);
return ctx.mtx_replacements;
}
void FrameInterpolation_StartRecord(void) {
previous_recording = move(current_recording);
current_recording = {};
current_path.clear();
current_path.push_back(&current_recording.root_path);
if (CVar_GetS32("g60FPS", 0) != 0) {
is_recording = true;
}
}
void FrameInterpolation_StopRecord(void) {
previous_camera_epoch = camera_epoch;
is_recording = false;
}
void FrameInterpolation_RecordOpenChild(const void* a, int b) {
if (!is_recording)
return;
label key = { a, b };
auto& m = current_path.back()->children[key];
append(Op::OpenChild).open_child = { key, m.size() };
current_path.push_back(&m.emplace_back());
}
void FrameInterpolation_RecordCloseChild(void) {
if (!is_recording)
return;
//append(Op::CloseChild);
if (has_inv_actor_mtx && current_path.size() == inv_actor_mtx_path_index) {
has_inv_actor_mtx = false;
}
current_path.pop_back();
}
void FrameInterpolation_DontInterpolateCamera(void) {
camera_epoch = previous_camera_epoch + 1;
}
int FrameInterpolation_GetCameraEpoch(void) {
return (int)camera_epoch;
}
void FrameInterpolation_RecordActorPosRotMatrix(void) {
if (!is_recording)
return;
next_is_actor_pos_rot_matrix = true;
}
void FrameInterpolation_RecordMatrixPush(void) {
if (!is_recording)
return;
append(Op::MatrixPush);
}
void FrameInterpolation_RecordMatrixPop(void) {
if (!is_recording)
return;
append(Op::MatrixPop);
}
void FrameInterpolation_RecordMatrixPut(MtxF* src) {
if (!is_recording)
return;
append(Op::MatrixPut).matrix_put = { *src };
}
void FrameInterpolation_RecordMatrixMult(MtxF* mf, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixMult).matrix_mult = { *mf, mode };
}
void FrameInterpolation_RecordMatrixTranslate(f32 x, f32 y, f32 z, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixTranslate).matrix_translate = { x, y, z, mode };
}
void FrameInterpolation_RecordMatrixScale(f32 x, f32 y, f32 z, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixScale).matrix_scale = { x, y, z, mode };
}
void FrameInterpolation_RecordMatrixRotate1Coord(u32 coord, f32 value, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixRotate1Coord).matrix_rotate_1_coord = { coord, value, mode };
}
void FrameInterpolation_RecordMatrixRotateZYX(s16 x, s16 y, s16 z, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixRotateZYX).matrix_rotate_zyx = { x, y, z, mode };
}
void FrameInterpolation_RecordMatrixTranslateRotateZYX(Vec3f* translation, Vec3s* rotation) {
if (!is_recording)
return;
append(Op::MatrixTranslateRotateZYX).matrix_translate_rotate_zyx = { *translation, *rotation };
}
void FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot) {
if (!is_recording)
return;
auto& d = append(Op::MatrixSetTranslateRotateYXZ).matrix_set_translate_rotate_yxz = { translateX, translateY, translateZ,
*rot };
if (next_is_actor_pos_rot_matrix) {
d.has_mtx = true;
//d.mtx = *Matrix_GetCurrent();
invert_matrix((const float *)Matrix_GetCurrent()->mf, (float *)inv_actor_mtx.mf);
next_is_actor_pos_rot_matrix = false;
has_inv_actor_mtx = true;
inv_actor_mtx_path_index = current_path.size();
}
}
void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest) {
if (!is_recording)
return;
append(Op::MatrixMtxFToMtx).matrix_mtxf_to_mtx = { *src, dest };
}
void FrameInterpolation_RecordMatrixToMtx(Mtx* dest, char* file, s32 line) {
if (!is_recording)
return;
auto& d = append(Op::MatrixToMtx).matrix_to_mtx = { dest };
if (has_inv_actor_mtx) {
d.has_adjusted = true;
SkinMatrix_MtxFMtxFMult(&inv_actor_mtx, Matrix_GetCurrent(), &d.src);
} else {
d.src = *Matrix_GetCurrent();
}
}
void FrameInterpolation_RecordMatrixReplaceRotation(MtxF* mf) {
if (!is_recording)
return;
append(Op::MatrixReplaceRotation).matrix_replace_rotation = { *mf };
}
void FrameInterpolation_RecordMatrixRotateAxis(f32 angle, Vec3f* axis, u8 mode) {
if (!is_recording)
return;
append(Op::MatrixRotateAxis).matrix_rotate_axis = { angle, *axis, mode };
}
void FrameInterpolation_RecordSkinMatrixMtxFToMtx(MtxF* src, Mtx* dest) {
if (!is_recording)
return;
FrameInterpolation_RecordMatrixMtxFToMtx(src, dest);
}
// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
static bool invert_matrix(const float m[16], float invOut[16]) {
float inv[16], det;
int i;
inv[0] = m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];
inv[4] = -m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10];
inv[8] = m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];
inv[12] = -m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];
inv[1] = -m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];
inv[5] = m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];
inv[9] = -m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9];
inv[13] = m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];
inv[2] = m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];
inv[6] = -m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];
inv[10] = m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];
inv[14] = -m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];
inv[3] = -m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];
inv[7] = m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];
inv[11] = -m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];
inv[15] = m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0) {
return false;
}
det = 1.0 / det;
for (i = 0; i < 16; i++) {
invOut[i] = inv[i] * det;
}
return true;
}

View File

@ -0,0 +1,61 @@
#pragma once
#include "include/z64math.h"
#ifdef __cplusplus
#include <unordered_map>
std::unordered_map<Mtx*, MtxF> FrameInterpolation_Interpolate(float step);
extern "C" {
#endif
void FrameInterpolation_StartRecord(void);
void FrameInterpolation_StopRecord(void);
void FrameInterpolation_RecordOpenChild(const void* a, int b);
void FrameInterpolation_RecordCloseChild(void);
void FrameInterpolation_DontInterpolateCamera(void);
int FrameInterpolation_GetCameraEpoch(void);
void FrameInterpolation_RecordActorPosRotMatrix(void);
void FrameInterpolation_RecordMatrixPush(void);
void FrameInterpolation_RecordMatrixPop(void);
void FrameInterpolation_RecordMatrixPut(MtxF* src);
void FrameInterpolation_RecordMatrixMult(MtxF* mf, u8 mode);
void FrameInterpolation_RecordMatrixTranslate(f32 x, f32 y, f32 z, u8 mode);
void FrameInterpolation_RecordMatrixScale(f32 x, f32 y, f32 z, u8 mode);
void FrameInterpolation_RecordMatrixRotate1Coord(u32 coord, f32 value, u8 mode);
void FrameInterpolation_RecordMatrixRotateZYX(s16 x, s16 y, s16 z, u8 mode);
void FrameInterpolation_RecordMatrixTranslateRotateZYX(Vec3f* translation, Vec3s* rotation);
void FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ, Vec3s* rot);
void FrameInterpolation_RecordMatrixMtxFToMtx(MtxF* src, Mtx* dest);
void FrameInterpolation_RecordMatrixToMtx(Mtx* dest, char* file, s32 line);
void FrameInterpolation_RecordMatrixReplaceRotation(MtxF* mf);
void FrameInterpolation_RecordMatrixRotateAxis(f32 angle, Vec3f* axis, u8 mode);
void FrameInterpolation_RecordSkinMatrixMtxFToMtx(MtxF* src, Mtx* dest);
#ifdef __cplusplus
}
#endif

View File

@ -1,4 +1,4 @@
const char gBuildVersion[] = "DECKARD ALFA (1.0.0)";
const char gBuildVersion[] = "ROY ALFA (2.0.0)";
const char gBuildTeam[] = "github.com/harbourmasters";
const char gBuildDate[] = __DATE__ " " __TIME__;
const char gBuildMakeOption[] = "";

View File

@ -478,7 +478,10 @@ static void RunFrame()
Graph_StartFrame();
PadMgr_ThreadEntry(&gPadMgr);
// TODO: Workaround for rumble being too long. Implement os thread functions.
for (int i = 0; i < 3; i++) {
PadMgr_ThreadEntry(&gPadMgr);
}
Graph_Update(&runFrameContext.gfxCtx, runFrameContext.gameState);
ticksB = GetPerfCounter();

View File

@ -1,5 +1,7 @@
#include "global.h"
#include "soh/frame_interpolation.h"
// clang-format off
Mtx gMtxClear = {
65536, 0, 1, 0,
@ -25,11 +27,13 @@ void Matrix_Init(GameState* gameState) {
}
void Matrix_Push(void) {
FrameInterpolation_RecordMatrixPush();
Matrix_MtxFCopy(sCurrentMatrix + 1, sCurrentMatrix);
sCurrentMatrix++;
}
void Matrix_Pop(void) {
FrameInterpolation_RecordMatrixPop();
sCurrentMatrix--;
ASSERT(sCurrentMatrix >= sMatrixStack, "Matrix_now >= Matrix_stack", "../sys_matrix.c", 176);
}
@ -39,6 +43,7 @@ void Matrix_Get(MtxF* dest) {
}
void Matrix_Put(MtxF* src) {
FrameInterpolation_RecordMatrixPut(src);
Matrix_MtxFCopy(sCurrentMatrix, src);
}
@ -47,6 +52,7 @@ MtxF* Matrix_GetCurrent(void) {
}
void Matrix_Mult(MtxF* mf, u8 mode) {
FrameInterpolation_RecordMatrixMult(mf, mode);
MtxF* cmf = Matrix_GetCurrent();
if (mode == MTXMODE_APPLY) {
@ -57,6 +63,7 @@ void Matrix_Mult(MtxF* mf, u8 mode) {
}
void Matrix_Translate(f32 x, f32 y, f32 z, u8 mode) {
FrameInterpolation_RecordMatrixTranslate(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
f32 tx;
f32 ty;
@ -80,6 +87,7 @@ void Matrix_Translate(f32 x, f32 y, f32 z, u8 mode) {
}
void Matrix_Scale(f32 x, f32 y, f32 z, u8 mode) {
FrameInterpolation_RecordMatrixScale(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
if (mode == MTXMODE_APPLY) {
@ -101,6 +109,7 @@ void Matrix_Scale(f32 x, f32 y, f32 z, u8 mode) {
}
void Matrix_RotateX(f32 x, u8 mode) {
FrameInterpolation_RecordMatrixRotate1Coord(0, x, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@ -165,6 +174,7 @@ void Matrix_RotateX(f32 x, u8 mode) {
}
void Matrix_RotateY(f32 y, u8 mode) {
FrameInterpolation_RecordMatrixRotate1Coord(1, y, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@ -229,6 +239,7 @@ void Matrix_RotateY(f32 y, u8 mode) {
}
void Matrix_RotateZ(f32 z, u8 mode) {
FrameInterpolation_RecordMatrixRotate1Coord(2, z, mode);
MtxF* cmf;
f32 sin;
f32 cos;
@ -299,6 +310,7 @@ void Matrix_RotateZ(f32 z, u8 mode) {
* Original Name: Matrix_RotateXYZ, changed to reflect rotation order.
*/
void Matrix_RotateZYX(s16 x, s16 y, s16 z, u8 mode) {
FrameInterpolation_RecordMatrixRotateZYX(x, y, z, mode);
MtxF* cmf = sCurrentMatrix;
f32 temp1;
f32 temp2;
@ -389,6 +401,7 @@ void Matrix_RotateZYX(s16 x, s16 y, s16 z, u8 mode) {
* transformed according to whatever the matrix was previously.
*/
void Matrix_TranslateRotateZYX(Vec3f* translation, Vec3s* rotation) {
FrameInterpolation_RecordMatrixTranslateRotateZYX(translation, rotation);
MtxF* cmf = sCurrentMatrix;
f32 sin = Math_SinS(rotation->z);
f32 cos = Math_CosS(rotation->z);
@ -530,15 +543,20 @@ void Matrix_SetTranslateRotateYXZ(f32 translateX, f32 translateY, f32 translateZ
} else {
cmf->yx = 0.0f;
}
FrameInterpolation_RecordMatrixSetTranslateRotateYXZ(translateX, translateY, translateZ, rot);
}
Mtx* Matrix_MtxFToMtx(MtxF* src, Mtx* dest) {
FrameInterpolation_RecordMatrixMtxFToMtx(src, dest);
guMtxF2L(src, dest);
return dest;
}
Mtx* Matrix_ToMtx(Mtx* dest, char* file, s32 line) {
return Matrix_MtxFToMtx(Matrix_CheckFloats(sCurrentMatrix, file, line), dest);
FrameInterpolation_RecordMatrixToMtx(dest, file, line);
guMtxF2L(Matrix_CheckFloats(sCurrentMatrix, file, line), dest);
return dest;
//return Matrix_MtxFToMtx(Matrix_CheckFloats(sCurrentMatrix, file, line), dest);
}
Mtx* Matrix_NewMtx(GraphicsContext* gfxCtx, char* file, s32 line) {
@ -627,6 +645,7 @@ void Matrix_Transpose(MtxF* mf) {
* seen as replacing the R rotation with `mf`, hence the function name.
*/
void Matrix_ReplaceRotation(MtxF* mf) {
FrameInterpolation_RecordMatrixReplaceRotation(mf);
MtxF* cmf = sCurrentMatrix;
f32 acc;
f32 temp;
@ -779,6 +798,7 @@ void Matrix_MtxFToZYXRotS(MtxF* mf, Vec3s* rotDest, s32 flag) {
* NB: `axis` is assumed to be a unit vector.
*/
void Matrix_RotateAxis(f32 angle, Vec3f* axis, u8 mode) {
FrameInterpolation_RecordMatrixRotateAxis(angle, axis, mode);
MtxF* cmf;
f32 sin;
f32 cos;

View File

@ -6,6 +6,7 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
#include "objects/object_bdoor/object_bdoor.h"
#include "soh/frame_interpolation.h"
#if defined(_MSC_VER) || defined(__GNUC__)
#include <string.h>
@ -410,6 +411,7 @@ void func_8002C124(TargetContext* targetCtx, GlobalContext* globalCtx) {
f32 var2;
s32 i;
FrameInterpolation_RecordOpenChild(actor, 0);
player = GET_PLAYER(globalCtx);
spCE = 0xFF;
@ -486,10 +488,12 @@ void func_8002C124(TargetContext* targetCtx, GlobalContext* globalCtx) {
}
}
}
FrameInterpolation_RecordCloseChild();
}
actor = targetCtx->unk_94;
if ((actor != NULL) && !(actor->flags & ACTOR_FLAG_27)) {
FrameInterpolation_RecordOpenChild(actor, 1);
NaviColor* naviColor = &sNaviColorList[actor->category];
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x7);
@ -503,6 +507,7 @@ void func_8002C124(TargetContext* targetCtx, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_actor.c", 2153),
G_MTX_MODELVIEW | G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, gZTargetArrowDL);
FrameInterpolation_RecordCloseChild();
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 2158);
@ -2490,6 +2495,7 @@ void Actor_Draw(GlobalContext* globalCtx, Actor* actor) {
Fault_AddClient(&faultClient, Actor_FaultPrint, actor, "Actor_draw");
FrameInterpolation_RecordOpenChild(actor, 0);
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 6035);
lights = LightContext_NewLights(&globalCtx->lightCtx, globalCtx->state.gfxCtx);
@ -2497,6 +2503,7 @@ void Actor_Draw(GlobalContext* globalCtx, Actor* actor) {
Lights_BindAll(lights, globalCtx->lightCtx.listHead, (actor->flags & ACTOR_FLAG_22) ? NULL : &actor->world.pos);
Lights_Draw(lights, globalCtx->state.gfxCtx);
FrameInterpolation_RecordActorPosRotMatrix();
if (actor->flags & ACTOR_FLAG_12) {
Matrix_SetTranslateRotateYXZ(
actor->world.pos.x + globalCtx->mainCamera.skyboxOffset.x,
@ -2546,6 +2553,7 @@ void Actor_Draw(GlobalContext* globalCtx, Actor* actor) {
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 6119);
FrameInterpolation_RecordCloseChild();
Fault_RemoveClient(&faultClient);
}

View File

@ -6,6 +6,8 @@
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
#include "soh/frame_interpolation.h"
s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags);
s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 flags);
s32 Camera_QRegInit(void);
@ -6675,6 +6677,7 @@ s32 Camera_Special9(Camera* camera) {
case 1:
spec9->doorParams.timer1--;
if (spec9->doorParams.timer1 <= 0) {
FrameInterpolation_DontInterpolateCamera();
camera->animState++;
if (params->interfaceFlags & 1) {
camPosData = Camera_GetCamBGData(camera);
@ -7968,6 +7971,8 @@ s32 Camera_SetCSParams(Camera* camera, CutsceneCameraPoint* atPoints, CutsceneCa
camera->speedRatio = 0.0f;
}
FrameInterpolation_DontInterpolateCamera();
return 1;
}

View File

@ -1,6 +1,8 @@
#include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
void EffectBlure_AddVertex(EffectBlure* this, Vec3f* p1, Vec3f* p2) {
EffectBlureElement* elem;
s32 numElements;
@ -946,6 +948,7 @@ void EffectBlure_Draw(void* thisx, GraphicsContext* gfxCtx) {
s32 j;
s32 phi_t2;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx, "../z_eff_blure.c", 1596);
gSPMatrix(POLY_XLU_DISP++, &gMtxClear, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@ -1059,4 +1062,5 @@ void EffectBlure_Draw(void* thisx, GraphicsContext* gfxCtx) {
}
CLOSE_DISPS(gfxCtx, "../z_eff_blure.c", 1823);
FrameInterpolation_RecordCloseChild();
}

View File

@ -2,6 +2,8 @@
#include "vt.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
static Vtx sVertices[5] = {
VTX(-32, -32, 0, 0, 1024, 0xFF, 0xFF, 0xFF, 0xFF),
VTX(32, 32, 0, 1024, 0, 0xFF, 0xFF, 0xFF, 0xFF),
@ -154,6 +156,7 @@ void EffectShieldParticle_Draw(void* thisx, GraphicsContext* gfxCtx) {
Color_RGBA8 primColor;
Color_RGBA8 envColor;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx, "../z_eff_shield_particle.c", 272);
if (this != NULL) {
@ -213,4 +216,5 @@ void EffectShieldParticle_Draw(void* thisx, GraphicsContext* gfxCtx) {
}
CLOSE_DISPS(gfxCtx, "../z_eff_shield_particle.c", 359);
FrameInterpolation_RecordCloseChild();
}

View File

@ -1,6 +1,8 @@
#include "global.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
// original name: "spark"
void EffectSpark_Init(void* thisx, void* initParamsx) {
EffectSpark* this = (EffectSpark*)thisx;
@ -152,6 +154,7 @@ void EffectSpark_Draw(void* thisx, GraphicsContext* gfxCtx) {
u8 sp1C4;
f32 ratio;
FrameInterpolation_RecordOpenChild(this, 0);
OPEN_DISPS(gfxCtx, "../z_eff_spark.c", 293);
if (this != NULL) {
@ -274,4 +277,5 @@ void EffectSpark_Draw(void* thisx, GraphicsContext* gfxCtx) {
end:
CLOSE_DISPS(gfxCtx, "../z_eff_spark.c", 498);
FrameInterpolation_RecordCloseChild();
}

View File

@ -1,6 +1,8 @@
#include "global.h"
#include "vt.h"
#include "soh/frame_interpolation.h"
EffectSsInfo sEffectSsInfo = { 0 }; // "EffectSS2Info"
void EffectSs_InitInfo(GlobalContext* globalCtx, s32 tableSize) {
@ -233,6 +235,7 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
sEffectSsInfo.table[index].type = type;
sEffectSsInfo.table[index].priority = priority;
sEffectSsInfo.table[index].epoch++;
if (initInfo->init(globalCtx, index, &sEffectSsInfo.table[index], initParams) == 0) {
osSyncPrintf(VT_FGCOL(GREEN));
@ -284,7 +287,9 @@ void EffectSs_Draw(GlobalContext* globalCtx, s32 index) {
EffectSs* effectSs = &sEffectSsInfo.table[index];
if (effectSs->draw != NULL) {
FrameInterpolation_RecordOpenChild(effectSs, effectSs->epoch);
effectSs->draw(globalCtx, index, effectSs);
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -498,8 +498,8 @@ void HealthMeter_HandleCriticalAlarm(GlobalContext* globalCtx) {
if (interfaceCtx->unk_22A <= 0) {
interfaceCtx->unk_22A = 0;
interfaceCtx->unk_22C = 0;
if (!Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
if (CVar_GetS32("gLowHpAlarm", 0) == 0 && !Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
func_80078884(NA_SE_SY_HITPOINT_ALARM);
}
}

View File

@ -4,6 +4,8 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
#define LIGHTS_BUFFER_SIZE 32
//#define LIGHTS_BUFFER_SIZE 1024 // Kill me
@ -434,12 +436,14 @@ void Lights_DrawGlow(GlobalContext* globalCtx) {
if ((info->type == LIGHT_POINT_GLOW) && (params->drawGlow)) {
scale = SQ(params->radius) * 0.0000026f;
FrameInterpolation_RecordOpenChild(node, 0);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, params->color[0], params->color[1], params->color[2], 50);
Matrix_Translate(params->x, params->y, params->z, MTXMODE_NEW);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_lights.c", 918),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gGlowCircleDL);
FrameInterpolation_RecordCloseChild();
}
node = node->next;

View File

@ -753,7 +753,15 @@ void func_80083108(GlobalContext* globalCtx) {
gSaveContext.buttonStatus[0] = BTN_DISABLED;
for (i = 1; i < 4; i++) {
if (func_8008F2F8(globalCtx) == 2) {
if ((gSaveContext.equips.buttonItems[i] >= ITEM_SHIELD_DEKU) &&
(gSaveContext.equips.buttonItems[i] <= ITEM_BOOTS_HOVER)) {
// Equipment on c-buttons is always enabled
if (gSaveContext.buttonStatus[i] == BTN_DISABLED) {
sp28 = 1;
}
gSaveContext.buttonStatus[i] = BTN_ENABLED;
} else if (func_8008F2F8(globalCtx) == 2) {
if ((gSaveContext.equips.buttonItems[i] != ITEM_HOOKSHOT) &&
(gSaveContext.equips.buttonItems[i] != ITEM_LONGSHOT)) {
if (gSaveContext.buttonStatus[i] == BTN_ENABLED) {

View File

@ -5,6 +5,8 @@
#include "soh/Enhancements/gameconsole.h"
#include "soh/frame_interpolation.h"
void* D_8012D1F0 = NULL;
//UNK_TYPE D_8012D1F4 = 0; // unused
Input* D_8012D1F8 = NULL;
@ -1379,7 +1381,9 @@ void Gameplay_Main(GameState* thisx) {
LOG_NUM("1", 1, "../z_play.c", 4583);
}
FrameInterpolation_StartRecord();
Gameplay_Draw(globalCtx);
FrameInterpolation_StopRecord();
if (1 && HREG(63)) {
LOG_NUM("1", 1, "../z_play.c", 4587);

View File

@ -29,7 +29,8 @@ s16 sBootData[PLAYER_BOOTS_MAX][17] = {
// Used to map action params to model groups
u8 sActionModelGroups[] = {
3, 15, 10, 2, 2, 5, 10, 11, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 7, 7, 8, 3, 3, 6, 3, 3, 3, 3, 12, 13, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3
};
TextTriggerEntry sTextTriggers[] = {

View File

@ -1,6 +1,8 @@
#include "global.h"
#include "vt.h"
#include "soh/frame_interpolation.h"
// clang-format off
MtxF sMtxFClear = {
1.0f, 0.0f, 0.0f, 0.0f,
@ -523,6 +525,7 @@ void SkinMatrix_Vec3sToVec3f(Vec3s* src, Vec3f* dest) {
}
void SkinMatrix_MtxFToMtx(MtxF* src, Mtx* dest) {
FrameInterpolation_RecordSkinMatrixMtxFToMtx(src, dest);
guMtxF2L(src, dest);
}

View File

@ -2,6 +2,9 @@
#include "vt.h"
#include <string.h>
#include <math.h>
#include "soh/frame_interpolation.h"
vu32 D_8012ABF0 = true;
@ -277,6 +280,10 @@ void func_800AAA50(View* view, s32 arg1) {
}
}
static float sqr(float a) {
return a * a;
}
s32 func_800AAA9C(View* view) {
f32 aspect;
s32 width;
@ -307,6 +314,85 @@ s32 func_800AAA9C(View* view) {
height = view->viewport.bottomY - view->viewport.topY;
aspect = (f32)width / (f32)height;
viewing = Graph_Alloc(gfxCtx, sizeof(Mtx));
LogUtils_CheckNullPointer("viewing", viewing, "../z_view.c", 667);
view->viewingPtr = viewing;
if (view->eye.x == view->lookAt.x && view->eye.y == view->lookAt.y && view->eye.z == view->lookAt.z) {
view->eye.x += 1.0f;
view->eye.y += 1.0f;
view->eye.z += 1.0f;
}
func_800ABE74(view->eye.x, view->eye.y, view->eye.z);
MtxF viewingF;
guLookAtF(viewingF.mf, view->eye.x, view->eye.y, view->eye.z, view->lookAt.x, view->lookAt.y, view->lookAt.z, view->up.x,
view->up.y, view->up.z);
// Some heuristics to identify instant camera movements and skip interpolation in that case
static View old_view;
float dirx = view->eye.x - view->lookAt.x;
float diry = view->eye.y - view->lookAt.y;
float dirz = view->eye.z - view->lookAt.z;
float dir_dist = sqrtf(sqr(dirx) + sqr(diry) + sqr(dirz));
dirx /= dir_dist;
diry /= dir_dist;
dirz /= dir_dist;
float odirx = old_view.eye.x - old_view.lookAt.x;
float odiry = old_view.eye.y - old_view.lookAt.y;
float odirz = old_view.eye.z - old_view.lookAt.z;
float odir_dist = sqrtf(sqr(odirx) + sqr(odiry) + sqr(odirz));
odirx /= odir_dist;
odiry /= odir_dist;
odirz /= odir_dist;
float eye_dist = sqrtf(sqr(view->eye.x - old_view.eye.x) + sqr(view->eye.y - old_view.eye.y) + sqr(view->eye.z - old_view.eye.z));
float look_dist = sqrtf(sqr(view->lookAt.x - old_view.lookAt.x) + sqr(view->lookAt.y - old_view.lookAt.y) + sqr(view->lookAt.z - old_view.lookAt.z));
float up_dist = sqrtf(sqr(view->up.x - old_view.up.x) + sqr(view->up.y - old_view.up.y) + sqr(view->up.z - old_view.up.z));
float d_dist = sqrtf(sqr(dirx - odirx) + sqr(diry - odiry) + sqr(dirz - odirz));
bool dont_interpolate = false;
if (up_dist < 0.01 && d_dist < 0.01) {
if (eye_dist + look_dist > 300) {
dont_interpolate = true;
}
} else {
if (eye_dist >= 400) {
dont_interpolate = true;
}
if (look_dist >= 100) {
dont_interpolate = true;
}
if (up_dist >= 1.50f) {
dont_interpolate = true;
}
if (d_dist >= 1.414f && look_dist >= 15) {
dont_interpolate = true;
}
if (d_dist >= 1.414f && up_dist >= 0.31f && look_dist >= 1 && eye_dist >= 300) {
dont_interpolate = true;
}
if (d_dist >= 0.5f && up_dist >= 0.31f && look_dist >= 3 && eye_dist >= 170) {
dont_interpolate = true;
}
if (look_dist >= 52 && eye_dist >= 52) {
dont_interpolate = true;
}
if (look_dist >= 30 && eye_dist >= 90) {
dont_interpolate = true;
}
}
if (dont_interpolate) {
FrameInterpolation_DontInterpolateCamera();
}
FrameInterpolation_RecordOpenChild(NULL, FrameInterpolation_GetCameraEpoch());
if (HREG(80) == 11) {
if (HREG(94) != 11) {
HREG(94) = 11;
@ -347,22 +433,17 @@ s32 func_800AAA9C(View* view) {
gSPPerspNormalize(POLY_KAL_DISP++, view->normal);
gSPMatrix(POLY_KAL_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
viewing = Graph_Alloc(gfxCtx, sizeof(Mtx));
LogUtils_CheckNullPointer("viewing", viewing, "../z_view.c", 667);
view->viewingPtr = viewing;
if (view->eye.x == view->lookAt.x && view->eye.y == view->lookAt.y && view->eye.z == view->lookAt.z) {
view->eye.x += 1.0f;
view->eye.y += 1.0f;
view->eye.z += 1.0f;
}
func_800ABE74(view->eye.x, view->eye.y, view->eye.z);
guLookAt(viewing, view->eye.x, view->eye.y, view->eye.z, view->lookAt.x, view->lookAt.y, view->lookAt.z, view->up.x,
view->up.y, view->up.z);
Matrix_MtxFToMtx(viewingF.mf, viewing);
view->viewing = *viewing;
/*if (eye_dist > 1 || look_dist > 1 || abs(up_dist) > 0.1 || abs(d_dist) > 0.1)
printf("%d %f %f %f, %f %f %f, %f %f %f, %f %f %f %f %d\n", (int)view->fovy, view->eye.x, view->eye.y, view->eye.z, view->lookAt.x, view->lookAt.y, view->lookAt.z,
view->up.x, view->up.y, view->up.z, eye_dist, look_dist, up_dist, d_dist, dont_interpolate);*/
old_view = *view;
if (QREG(88) & 2) {
s32 i;
MtxF mf;
@ -374,10 +455,10 @@ s32 func_800AAA9C(View* view) {
}
osSyncPrintf("\n");
}
gSPMatrix(POLY_OPA_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
gSPMatrix(POLY_XLU_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
gSPMatrix(POLY_KAL_DISP++, viewing, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
FrameInterpolation_RecordCloseChild();
CLOSE_DISPS(gfxCtx, "../z_view.c", 711);

View File

@ -1,5 +1,7 @@
#include "global.h"
#include "soh/frame_interpolation.h"
Mtx* sSkyboxDrawMatrix;
Mtx* SkyboxDraw_UpdateMatrix(SkyboxContext* skyboxCtx, f32 x, f32 y, f32 z) {
@ -13,6 +15,7 @@ Mtx* SkyboxDraw_UpdateMatrix(SkyboxContext* skyboxCtx, f32 x, f32 y, f32 z) {
void SkyboxDraw_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyboxId, s16 blend, f32 x, f32 y, f32 z) {
OPEN_DISPS(gfxCtx, "../z_vr_box_draw.c", 52);
FrameInterpolation_RecordOpenChild(NULL, FrameInterpolation_GetCameraEpoch());
func_800945A0(gfxCtx);
@ -85,7 +88,7 @@ void SkyboxDraw_Draw(SkyboxContext* skyboxCtx, GraphicsContext* gfxCtx, s16 skyb
gDPPipeSync(POLY_OPA_DISP++);
//gsSPShaderTest2(POLY_OPA_DISP++);
FrameInterpolation_RecordCloseChild();
CLOSE_DISPS(gfxCtx, "../z_vr_box_draw.c", 125);
}

View File

@ -62,5 +62,6 @@ void guLookAt(Mtx* m, f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32 zAt, f
guLookAtF(mf, xEye, yEye, zEye, xAt, yAt, zAt, xUp, yUp, zUp);
guMtxF2L((MtxF*)mf, m);
//guMtxF2L((MtxF*)mf, m);
Matrix_MtxFToMtx((MtxF*)mf, m);
}

View File

@ -37,6 +37,6 @@ void guPerspective(Mtx* m, u16* perspNorm, f32 fovy, f32 aspect, f32 near, f32 f
f32 mf[4][4];
guPerspectiveF(mf, perspNorm, fovy, aspect, near, far, scale);
guMtxF2L((MtxF*)mf, m);
//guMtxF2L((MtxF*)mf, m);
Matrix_MtxFToMtx((MtxF*)mf, m);
}

View File

@ -1,5 +1,7 @@
#include "global.h"
#include "soh/frame_interpolation.h"
void guOrthoF(f32 mf[4][4], f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far, f32 scale) {
s32 i, j;
@ -25,5 +27,8 @@ void guOrtho(Mtx* mtx, f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 f
guOrthoF(mf, left, right, bottom, top, near, far, scale);
guMtxF2L((MtxF*)mf, mtx);
//guMtxF2L((MtxF*)mf, mtx);
FrameInterpolation_RecordOpenChild("ortho", 0);
Matrix_MtxFToMtx((MtxF*)mf, mtx);
FrameInterpolation_RecordCloseChild();
}

View File

@ -8,6 +8,8 @@
#include "overlays/actors/ovl_Boss_Ganon/z_boss_ganon.h"
#include "vt.h"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
typedef enum {
@ -283,6 +285,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
platform = (BgGanonOtyuka*)actor;
if (platform->dyna.actor.projectedPos.z > spBC) {
FrameInterpolation_RecordOpenChild(platform, 0);
if (camera->eye.y > platform->dyna.actor.world.pos.y) {
phi_s2 = sPlatformTopDL;
} else {
@ -309,7 +312,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
}
for (i = 0; i < ARRAY_COUNT(sSides); i++) {
if (platform->visibleSides & sSides[i]) {
if ((platform->visibleSides & sSides[i]) || 1) { // || 1 for frame interpolation
Matrix_Push();
Matrix_Translate(sSideCenters[i].x, 0.0f, sSideCenters[i].z, MTXMODE_APPLY);
Matrix_RotateY(sSideAngles[i], MTXMODE_APPLY);
@ -320,6 +323,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
Matrix_Pop();
}
}
FrameInterpolation_RecordCloseChild();
}
}
@ -333,6 +337,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
platform = (BgGanonOtyuka*)actor;
if ((platform->dyna.actor.projectedPos.z > -30.0f) && (platform->flashState != FLASH_NONE)) {
FrameInterpolation_RecordOpenChild(platform, 0);
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, platform->flashTimer * 4, 0, 32, 64, 1,
platform->flashTimer * 4, 0, 32, 64));
@ -344,7 +349,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
Matrix_Translate(platform->dyna.actor.world.pos.x, 0.0f, platform->dyna.actor.world.pos.z, MTXMODE_NEW);
for (i = 0; i < ARRAY_COUNT(sSides); i++) {
if (platform->unwalledSides & sSides[i]) {
if ((platform->unwalledSides & sSides[i]) || 1) { // || 1 for frame interpolation
Matrix_Push();
Matrix_Translate(sSideCenters[i].x, 0.0f, sSideCenters[i].z, MTXMODE_APPLY);
Matrix_RotateY(sSideAngles[i], MTXMODE_APPLY);
@ -356,6 +361,7 @@ void BgGanonOtyuka_Draw(Actor* thisx, GlobalContext* globalCtx) {
Matrix_Pop();
}
}
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -240,7 +240,8 @@ void BgHidanRsekizou_Draw(Actor* thisx, GlobalContext* globalCtx) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x14);
if ((s16)((Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx)) - this->dyna.actor.shape.rot.y) - 0x2E6C) >= 0) {
// Strange original code. Add || 1 for frame interpolation to get correct.
if ((s16)((Camera_GetCamDirYaw(GET_ACTIVE_CAM(globalCtx)) - this->dyna.actor.shape.rot.y) - 0x2E6C) >= 0 || 1) {
for (i = 3; i >= 0; i--) {
POLY_XLU_DISP = BgHidanRsekizou_DrawFireball(globalCtx, this, i, &mf, 0, POLY_XLU_DISP);
}

View File

@ -12,6 +12,8 @@
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
typedef enum {
@ -78,6 +80,7 @@ void BossFd_SpawnEmber(BossFdEffect* effect, Vec3f* position, Vec3f* velocity, V
effect->scale = scale / 1000.0f;
effect->alpha = 255;
effect->timer1 = (s16)Rand_ZeroFloat(10.0f);
effect->epoch++;
break;
}
}
@ -95,6 +98,7 @@ void BossFd_SpawnDebris(BossFdEffect* effect, Vec3f* position, Vec3f* velocity,
effect->scale = scale / 1000.0f;
effect->vFdFxRotX = Rand_ZeroFloat(100.0f);
effect->vFdFxRotY = Rand_ZeroFloat(100.0f);
effect->epoch++;
break;
}
}
@ -111,6 +115,7 @@ void BossFd_SpawnDust(BossFdEffect* effect, Vec3f* position, Vec3f* velocity, Ve
effect->accel = *acceleration;
effect->timer2 = 0;
effect->scale = scale / 400.0f;
effect->epoch++;
break;
}
}
@ -136,6 +141,7 @@ void BossFd_SpawnFireBreath(BossFdEffect* effect, Vec3f* position, Vec3f* veloci
effect->timer2 = 0;
effect->scale = scale / 400.0f;
effect->kbAngle = kbAngle;
effect->epoch++;
break;
}
}
@ -1522,6 +1528,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
for (i = 0; i < 180; i++, effect++) {
if (effect->type == BFD_FX_EMBER) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaEmberMaterialDL);
@ -1536,6 +1543,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_fd.c", 4046),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaEmberModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -1543,6 +1551,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
flag = false;
for (i = 0; i < 180; i++, effect++) {
if (effect->type == BFD_FX_DEBRIS) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D18(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, gVolvagiaDebrisMaterialDL);
@ -1557,6 +1566,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_fd.c", 4068),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gVolvagiaDebrisModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -1564,6 +1574,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
flag = false;
for (i = 0; i < 180; i++, effect++) {
if (effect->type == BFD_FX_DUST) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaDustMaterialDL);
@ -1580,6 +1591,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(dustTex[effect->timer2]));
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaDustModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -1587,6 +1599,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
flag = false;
for (i = 0; i < 180; i++, effect++) {
if (effect->type == BFD_FX_FIRE_BREATH) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaDustMaterialDL);
@ -1603,6 +1616,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(dustTex[effect->timer2]));
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaDustModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -1610,6 +1624,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
flag = false;
for (i = 0; i < 180; i++, effect++) {
if (effect->type == BFD_FX_SKULL_PIECE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaSkullPieceMaterialDL);
@ -1624,6 +1639,7 @@ void BossFd_DrawEffects(BossFdEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_fd.c", 4192),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gVolvagiaSkullPieceModelDL);
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -49,6 +49,7 @@ typedef struct {
/* 0x30 */ f32 scale;
/* 0x34 */ f32 bFdFxFloat1;
/* 0x38 */ f32 bFdFxFloat2;
u32 epoch;
} BossFdEffect; // size = 0x3C
#define BOSSFD_EFFECT_COUNT 180

View File

@ -87,6 +87,7 @@ void BossFd2_SpawnDebris(GlobalContext* globalCtx, BossFdEffect* effect, Vec3f*
effect->scale = scale / 1000.0f;
effect->vFdFxRotX = Rand_ZeroFloat(100.0f);
effect->vFdFxRotY = Rand_ZeroFloat(100.0f);
effect->epoch++;
break;
}
}
@ -112,6 +113,7 @@ void BossFd2_SpawnFireBreath(GlobalContext* globalCtx, BossFdEffect* effect, Vec
effect->timer2 = 0;
effect->scale = scale / 400.0f;
effect->kbAngle = kbAngle;
effect->epoch++;
break;
}
}
@ -130,6 +132,7 @@ void BossFd2_SpawnEmber(GlobalContext* globalCtx, BossFdEffect* effect, Vec3f* p
effect->scale = scale / 1000.0f;
effect->alpha = 255;
effect->timer1 = (s16)Rand_ZeroFloat(10.0f);
effect->epoch++;
break;
}
}
@ -148,6 +151,7 @@ void BossFd2_SpawnSkullPiece(GlobalContext* globalCtx, BossFdEffect* effect, Vec
effect->scale = scale / 1000.0f;
effect->vFdFxRotX = Rand_ZeroFloat(100.0f);
effect->vFdFxRotY = Rand_ZeroFloat(100.0f);
effect->epoch++;
break;
}
}
@ -164,6 +168,7 @@ void BossFd2_SpawnDust(BossFdEffect* effect, Vec3f* position, Vec3f* velocity, V
effect->accel = *acceleration;
effect->timer2 = 0;
effect->scale = scale / 400.0f;
effect->epoch++;
break;
}
}

View File

@ -9,6 +9,8 @@
#include "assets/objects/object_ganon_anime2/object_ganon_anime2.h"
#include "assets/scenes/dungeons/ganon_boss/ganon_boss_scene.h"
#include "soh/frame_interpolation.h"
#include <string.h>
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@ -138,6 +140,7 @@ void BossGanonEff_SpawnWindowShard(GlobalContext* globalCtx, Vec3f* pos, Vec3f*
eff->color.g = color->g;
eff->color.b = color->b;
eff->timer = (s16)Rand_ZeroFloat(20.0f);
eff->epoch++;
break;
}
}
@ -158,6 +161,7 @@ void BossGanonEff_SpawnSparkle(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velo
eff->unk_2E = (s16)Rand_ZeroFloat(100.0f) + 0xC8;
eff->unk_30 = arg6;
eff->timer = (s16)Rand_ZeroFloat(10.0f);
eff->epoch++;
break;
}
}
@ -182,6 +186,7 @@ void BossGanonEff_SpawnLightRay(GlobalContext* globalCtx, Vec3f* pos, Vec3f* vel
eff->timer = (s16)Rand_ZeroFloat(10.0f);
eff->unk_48 = Math_Atan2F(eff->velocity.z, eff->velocity.x);
eff->unk_44 = -Math_Atan2F(sqrtf(SQXZ(eff->velocity)), eff->velocity.y);
eff->epoch++;
break;
}
}
@ -201,6 +206,7 @@ void BossGanonEff_SpawnShock(GlobalContext* globalCtx, f32 scale, s16 shockType)
eff->scale = scale / 1000.0f;
eff->unk_2E = shockType;
eff->timer = 0;
eff->epoch++;
break;
}
}
@ -220,6 +226,7 @@ void BossGanonEff_SpawnLightning(GlobalContext* globalCtx, f32 scale, f32 arg2,
eff->unk_48 = arg2;
eff->unk_3C = arg3;
eff->timer = 0;
eff->epoch++;
break;
}
}
@ -240,6 +247,7 @@ void BossGanonEff_SpawnDustDark(GlobalContext* globalCtx, Vec3f* pos, f32 scale,
eff->unk_38 = arg3;
eff->unk_30 = (s16)Rand_ZeroFloat(100.0f);
eff->unk_2E = eff->timer = eff->alpha = 0;
eff->epoch++;
break;
}
}
@ -257,6 +265,7 @@ void BossGanonEff_SpawnDustLight(GlobalContext* globalCtx, Vec3f* pos, f32 scale
effArr[bufIndex].unk_38 = arg3;
effArr[bufIndex].unk_30 = Rand_ZeroFloat(100.0f);
effArr[bufIndex].unk_2E = effArr[bufIndex].timer = effArr[bufIndex].alpha = 0;
effArr[bufIndex].epoch++;
}
void BossGanonEff_SpawnShockwave(GlobalContext* globalCtx, Vec3f* pos, f32 scale, f32 arg3) {
@ -275,6 +284,7 @@ void BossGanonEff_SpawnShockwave(GlobalContext* globalCtx, Vec3f* pos, f32 scale
eff->unk_38 = arg3;
eff->unk_30 = (s16)Rand_ZeroFloat(100.0f);
eff->unk_2E = eff->timer = 0;
eff->epoch++;
break;
}
}
@ -295,6 +305,7 @@ void BossGanonEff_SpawnBlackDot(GlobalContext* globalCtx, Vec3f* pos, f32 scale)
eff->timer = 0;
eff->alpha = 0;
eff->unk_2E = 0;
eff->epoch++;
break;
}
}
@ -4820,6 +4831,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 200; i++, eff++) {
if (eff->type == GDF_EFF_WINDOW_SHARD) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_OPA_DISP++);
if (flag == 0) {
gSPDisplayList(POLY_OPA_DISP++, gDorfWindowShardMaterialDL);
@ -4837,6 +4849,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 10898),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gDorfWindowShardModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4845,6 +4858,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_SPARKLE) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
if (flag == 0) {
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 0, 0);
@ -4859,6 +4873,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 10932),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfSquareDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4867,6 +4882,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_LIGHT_RAY) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
if (flag == 0) {
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 0, 0);
@ -4883,6 +4899,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 10971),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfSquareDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4891,6 +4908,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_SHOCK) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
if (flag == 0) {
gDPPipeSync(POLY_XLU_DISP++);
if (eff->unk_2E == GDF_SHOCK_PLAYER_PURPLE) {
@ -4909,6 +4927,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 11023),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfShockDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4916,6 +4935,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_LIGHTNING) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, sLightningPrimColors[(eff->timer * 3) + 0],
sLightningPrimColors[(eff->timer * 3) + 1], sLightningPrimColors[(eff->timer * 3) + 2],
@ -4931,6 +4951,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sLightningTextures[eff->timer]));
gSPDisplayList(POLY_XLU_DISP++, gDorfLightningDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4938,6 +4959,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_IMPACT_DUST_DARK) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, eff->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 100, 70, 0, 128);
@ -4949,6 +4971,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 11121),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfImpactDarkDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4956,6 +4979,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_IMPACT_DUST_LIGHT) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, eff->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 200, 100, 0, 128);
@ -4967,6 +4991,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 11165),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfImpactLightDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4974,6 +4999,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_SHOCKWAVE) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 170, eff->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 150, 255, 0, 128);
@ -4986,6 +5012,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 11209),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfShockwaveDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4993,6 +5020,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
for (i = 0; i < 150; i++, eff++) {
if (eff->type == GDF_EFF_BLACK_DOT) {
FrameInterpolation_RecordOpenChild(eff, eff->epoch);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 150, 170, 0, eff->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128);
@ -5005,6 +5033,7 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_ganon.c", 11250),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gDorfDotDL);
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -69,6 +69,7 @@ typedef struct {
/* 0x40 */ f32 unk_40;
/* 0x44 */ f32 unk_44; // mostly x rot
/* 0x48 */ f32 unk_48; // mostly y rot
u32 epoch;
} GanondorfEffect; // size = 0x4C
typedef struct BossGanon {

View File

@ -10,6 +10,8 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "vt.h"
#include "soh/frame_interpolation.h"
#include <string.h>
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
@ -34,6 +36,7 @@ typedef struct {
/* 0x30 */ f32 scale;
/* 0x30 */ f32 fwork[2];
/* 0x3C */ Vec3f* targetPos;
u32 epoch;
} BossMoEffect; // size = 0x40
#define MO_FX_MAX_SIZE 0
@ -211,6 +214,7 @@ void BossMo_SpawnRipple(BossMoEffect* effect, Vec3f* pos, f32 scale, f32 maxScal
effect->rippleMode = 1;
effect->fwork[MO_FX_SPREAD_RATE] = (effect->fwork[MO_FX_MAX_SIZE] - effect->scale) * 0.1f;
}
effect->epoch++;
break;
}
}
@ -232,6 +236,7 @@ void BossMo_SpawnDroplet(s16 type, BossMoEffect* effect, Vec3f* pos, Vec3f* vel,
effect->scale = scale;
effect->fwork[MO_FX_SPREAD_RATE] = 1.0f;
effect->stopTimer = 0;
effect->epoch++;
break;
}
}
@ -250,6 +255,7 @@ void BossMo_SpawnStillDroplet(BossMoEffect* effect, Vec3f* pos, f32 scale) {
effect->accel = zeroVec;
effect->scale = scale;
effect->fwork[MO_FX_SPREAD_RATE] = 1.0f;
effect->epoch++;
break;
}
}
@ -274,6 +280,7 @@ void BossMo_SpawnBubble(BossMoEffect* effect, Vec3f* pos, Vec3f* vel, Vec3f* acc
effect->alpha = 0;
}
effect->timer = 0;
effect->epoch++;
break;
}
}
@ -2909,6 +2916,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
if (effect->type == MO_FX_BIG_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
func_80094BC4(gfxCtx);
@ -2925,6 +2933,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffWaterRippleDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -2932,6 +2941,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
if (effect->type == MO_FX_SMALL_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
func_80093D84(globalCtx->state.gfxCtx);
@ -2948,6 +2958,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffShockwaveDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -2956,6 +2967,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
if (((effect->type == MO_FX_DROPLET) || (effect->type == MO_FX_SPLASH)) ||
(effect->type == MO_FX_SPLASH_TRAIL)) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
@ -2977,6 +2989,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gMorphaDropletModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -2984,6 +2997,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
if (effect->type == MO_FX_WET_SPOT) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
func_80094044(gfxCtx);
@ -3003,6 +3017,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gMorphaWetSpotModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -3010,6 +3025,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
if (effect->type == MO_FX_BUBBLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
func_80093D18(globalCtx->state.gfxCtx);
@ -3027,6 +3043,7 @@ void BossMo_DrawEffects(BossMoEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gMorphaBubbleDL);
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -12,6 +12,8 @@
#include "overlays/actors/ovl_En_Boom/z_en_boom.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
#define GET_BODY(this) ((BossVa*)(this)->actor.parent)
@ -40,6 +42,7 @@ typedef struct BossVaEffect {
/* 0x44 */ f32 scaleMod;
/* 0x48 */ Vec3f offset;
/* 0x54 */ struct BossVa* parent;
u32 epoch;
} BossVaEffect; // size = 0x58
typedef enum {
@ -3519,6 +3522,7 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
for (i = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_LARGE_SPARK) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gDPSetEnvColor(POLY_XLU_DISP++, 130, 130, 30, 0);
@ -3534,12 +3538,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 4976),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_015710);
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_SPARK_BALL) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_011738);
@ -3560,12 +3566,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gDPSetEnvColor(POLY_XLU_DISP++, effect->envColor[0], effect->envColor[1], effect->envColor[2],
effect->envColor[3]);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_011768);
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_BLOOD) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_009430);
@ -3590,6 +3598,7 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 5052),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_009468);
FrameInterpolation_RecordCloseChild();
}
}
@ -3598,6 +3607,7 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
if (effect->type == VA_TUMOR) {
BossVa* parent = effect->parent;
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D18(globalCtx->state.gfxCtx);
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, effect->envColor[3]);
@ -3614,12 +3624,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gBarinadeDL_012948);
}
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_GORE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D18(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, gBarinadeDL_012BA0);
@ -3645,12 +3657,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 5124),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gBarinadeDL_012C50);
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_ZAP_CHARGE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_0135B0);
@ -3668,12 +3682,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 5152),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_013638);
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_BLAST_SPARK) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093C14(globalCtx->state.gfxCtx);
gDPSetEnvColor(POLY_XLU_DISP++, 130, 130, 30, 0);
@ -3690,12 +3706,14 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 5180),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_015710);
FrameInterpolation_RecordCloseChild();
}
}
effect = effectHead;
for (i = 0, flag = 0; i < ARRAY_COUNT(sVaEffects); i++, effect++) {
if (effect->type == VA_SMALL_SPARK) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!flag) {
func_80093D84(globalCtx->state.gfxCtx);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 100, 0);
@ -3712,6 +3730,7 @@ void BossVa_DrawEffects(BossVaEffect* effect, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_boss_va.c", 5208),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gBarinadeDL_008F70);
FrameInterpolation_RecordCloseChild();
}
}
@ -3734,6 +3753,7 @@ void BossVa_SpawnSpark(GlobalContext* globalCtx, BossVaEffect* effect, BossVa* t
effect->timer = (s16)(Rand_ZeroOne() * 10.0f) + 111;
effect->velocity = effect->accel = sZeroVec;
effect->mode = mode;
effect->epoch++;
switch (mode) {
case SPARK_UNUSED:

View File

@ -427,7 +427,8 @@ void EnFloormas_SetupFreeze(EnFloormas* this) {
}
void EnFloormas_Die(EnFloormas* this, GlobalContext* globalCtx) {
if (this->actor.scale.x > 0.004f) {
//Originally was doing > 0.004f, better fix thanks Gary :D
if (this->actor.scale.x > (f32)0.004f) {
// split
this->actor.shape.rot.y = this->actor.yawTowardsPlayer + 0x8000;
EnFloormas_SetupSplit((EnFloormas*)this->actor.child);

View File

@ -7,6 +7,8 @@
#include "z_en_zo.h"
#include "objects/object_zo/object_zo.h"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3)
typedef enum {
@ -41,6 +43,7 @@ void EnZo_Ripple(EnZo* this, Vec3f* pos, f32 scale, f32 targetScale, u8 alpha) {
effect->scale = scale;
effect->targetScale = targetScale;
effect->color.a = alpha;
effect->epoch++;
break;
}
effect++;
@ -65,6 +68,7 @@ void EnZo_Bubble(EnZo* this, Vec3f* pos) {
effect->vec = *pos;
effect->vel = vel;
effect->scale = ((Rand_ZeroOne() - 0.5f) * 0.02f) + 0.12f;
effect->epoch++;
break;
}
}
@ -87,6 +91,7 @@ void EnZo_Splash(EnZo* this, Vec3f* pos, Vec3f* vel, f32 scale) {
effect->vel = *vel;
effect->color.a = (Rand_ZeroOne() * 100.0f) + 100.0f;
effect->scale = scale;
effect->epoch++;
break;
}
effect++;
@ -180,6 +185,7 @@ void EnZo_DrawRipples(EnZo* this, GlobalContext* globalCtx) {
func_80093D84(globalCtx->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->effects); i++) {
if (effect->type == ENZO_EFFECT_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!setup) {
if (1) {}
gDPPipeSync(POLY_XLU_DISP++);
@ -194,6 +200,7 @@ void EnZo_DrawRipples(EnZo* this, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_zo_eff.c", 242),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gZoraRipplesModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -210,6 +217,7 @@ void EnZo_DrawBubbles(EnZo* this, GlobalContext* globalCtx) {
func_80093D84(globalCtx->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->effects); i++) {
if (effect->type == ENZO_EFFECT_BUBBLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!setup) {
if (1) {}
gSPDisplayList(POLY_XLU_DISP++, gZoraBubblesMaterialDL);
@ -227,6 +235,7 @@ void EnZo_DrawBubbles(EnZo* this, GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_zo_eff.c", 281),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gZoraBubblesModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -244,6 +253,7 @@ void EnZo_DrawSplashes(EnZo* this, GlobalContext* globalCtx) {
func_80093D84(globalCtx->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->effects); i++) {
if (effect->type == ENZO_EFFECT_SPLASH) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (!setup) {
if (1) {}
gSPDisplayList(POLY_XLU_DISP++, gZoraSplashesMaterialDL);
@ -260,6 +270,7 @@ void EnZo_DrawSplashes(EnZo* this, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gZoraSplashesModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}

View File

@ -15,6 +15,7 @@ typedef struct {
/* 0x14 */ Vec3f pos;
/* 0x20 */ Vec3f vel;
/* 0x2C */ Vec3f vec; // Usage specific
u32 epoch;
} EnZoEffect; // size = 0x38
typedef void (*EnZoActionFunc)(struct EnZo*, GlobalContext*);

View File

@ -10,6 +10,8 @@
#include "objects/object_fish/object_fish.h"
#include "vt.h"
#include "soh/frame_interpolation.h"
#define FLAGS ACTOR_FLAG_4
#define WATER_SURFACE_Y(globalCtx) globalCtx->colCtx.colHeader->waterBoxes->ySurface
@ -56,6 +58,7 @@ typedef struct {
/* 0x34 */ f32 unk_34;
/* 0x38 */ f32 unk_38;
/* 0x3C */ f32 unk_3C;
u32 epoch;
} FishingEffect; // size = 0x40
#define POND_PROP_COUNT 140
@ -490,6 +493,8 @@ void Fishing_SpawnRipple(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos,
effect->unk_2C = 1;
effect->unk_38 = (effect->unk_34 - effect->unk_30) * 0.1f;
}
effect->epoch++;
break;
}
@ -514,6 +519,7 @@ void Fishing_SpawnDustSplash(Vec3f* projectedPos, FishingEffect* effect, Vec3f*
effect->accel = accel;
effect->alpha = 100 + (s16)Rand_ZeroFloat(100.0f);
effect->unk_30 = scale;
effect->epoch++;
break;
}
@ -539,6 +545,7 @@ void Fishing_SpawnWaterDust(Vec3f* projectedPos, FishingEffect* effect, Vec3f* p
effect->timer = (s16)Rand_ZeroFloat(100.0f);
effect->unk_30 = scale;
effect->unk_34 = 2.0f * scale;
effect->epoch++;
break;
}
@ -563,6 +570,7 @@ void Fishing_SpawnBubble(Vec3f* projectedPos, FishingEffect* effect, Vec3f* pos,
effect->timer = (s16)Rand_ZeroFloat(100.0f);
effect->unk_30 = scale;
effect->unk_2C = arg4;
effect->epoch++;
break;
}
@ -591,6 +599,7 @@ void Fishing_SpawnRainDrop(FishingEffect* effect, Vec3f* pos, Vec3f* rot) {
Matrix_RotateY(rot->y, MTXMODE_NEW);
Matrix_RotateX(rot->x, MTXMODE_APPLY);
Matrix_MultVec3f(&velSrc, &effect->vel);
effect->epoch++;
break;
}
@ -1182,6 +1191,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
for (i = 0; i < 100; i++) {
if (effect->type == FS_EFF_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingRippleMaterialDL);
gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 155, 0);
@ -1197,6 +1207,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingRippleModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1205,6 +1216,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < 100; i++) {
if (effect->type == FS_EFF_DUST_SPLASH) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingDustSplashMaterialDL);
gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, 0);
@ -1221,6 +1233,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingDustSplashModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1229,6 +1242,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < 100; i++) {
if (effect->type == FS_EFF_WATER_DUST) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_OPA_DISP++, gFishingWaterDustMaterialDL);
gDPSetEnvColor(POLY_OPA_DISP++, 40, 90, 80, 128);
@ -1249,6 +1263,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gFishingWaterDustModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1257,6 +1272,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 0; i < 100; i++) {
if (effect->type == FS_EFF_BUBBLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingBubbleMaterialDL);
gDPSetEnvColor(POLY_XLU_DISP++, 150, 150, 150, 0);
@ -1272,6 +1288,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingBubbleModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1280,6 +1297,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 30; i < EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_DROP) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0x14);
gDPSetCombineMode(POLY_XLU_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
@ -1297,6 +1315,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingRainDropModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1307,6 +1326,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 30; i < EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_RIPPLE) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingRippleMaterialDL);
gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 155, 0);
@ -1321,6 +1341,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingRippleModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
@ -1329,6 +1350,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
flag = 0;
for (i = 30; i < EFFECT_COUNT; i++) {
if (effect->type == FS_EFF_RAIN_SPLASH) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
if (flag == 0) {
gSPDisplayList(POLY_XLU_DISP++, gFishingRainSplashMaterialDL);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, KREG(19) + 80);
@ -1350,12 +1372,14 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingRainSplashModelDL);
FrameInterpolation_RecordCloseChild();
}
effect++;
}
effect = firstEffect;
if (effect->type == FS_EFF_OWNER_HAT) {
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_RotateY((sEffOwnerHatRot.y * M_PI) / 32768, MTXMODE_APPLY);
Matrix_RotateX((sEffOwnerHatRot.x * M_PI) / 32768, MTXMODE_APPLY);
@ -1367,6 +1391,7 @@ void Fishing_DrawEffects(FishingEffect* effect, GlobalContext* globalCtx) {
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gFishingOwnerHatDL);
FrameInterpolation_RecordCloseChild();
}
Matrix_Pop();
@ -4398,6 +4423,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
}
if (prop->shouldDraw) {
FrameInterpolation_RecordOpenChild(prop, 0);
Matrix_Translate(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW);
Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY);
Matrix_RotateY(prop->rotY, MTXMODE_APPLY);
@ -4407,6 +4433,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_fishing.c", 7726),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingReedModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4423,12 +4450,14 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
}
if (prop->shouldDraw) {
FrameInterpolation_RecordOpenChild(prop, 0);
Matrix_Translate(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW);
Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_fishing.c", 7748),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gFishingWoodPostModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4445,6 +4474,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
}
if (prop->shouldDraw) {
FrameInterpolation_RecordOpenChild(prop, 0);
Matrix_Translate(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW);
Matrix_Scale(prop->scale, 1.0f, prop->scale, MTXMODE_APPLY);
Matrix_RotateY(prop->lilyPadAngle * (M_PI / 32768), MTXMODE_APPLY);
@ -4454,6 +4484,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_fishing.c", 7774),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gFishingLilyPadModelDL);
FrameInterpolation_RecordCloseChild();
}
}
@ -4470,6 +4501,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
}
if (prop->shouldDraw) {
FrameInterpolation_RecordOpenChild(prop, 0);
Matrix_Translate(prop->pos.x, prop->pos.y, prop->pos.z, MTXMODE_NEW);
Matrix_Scale(prop->scale, prop->scale, prop->scale, MTXMODE_APPLY);
Matrix_RotateY(prop->rotY, MTXMODE_APPLY);
@ -4477,6 +4509,7 @@ void Fishing_DrawPondProps(GlobalContext* globalCtx) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_fishing.c", 7798),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gFishingRockModelDL);
FrameInterpolation_RecordCloseChild();
}
}

View File

@ -9,6 +9,8 @@
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_spot02_objects/object_spot02_objects.h"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5 | ACTOR_FLAG_25)
void ObjectKankyo_Init(Actor* thisx, GlobalContext* globalCtx);
@ -260,6 +262,7 @@ void ObjectKankyo_Fairies(ObjectKankyo* this, GlobalContext* globalCtx) {
this->effects[i].dirPhase.z = Rand_ZeroOne() * 360.0f;
this->effects[i].state++;
this->effects[i].timer = 0;
this->effects[i].epoch++;
break;
case 1: // blinking fairies / inactive fairy trails
@ -417,26 +420,32 @@ void ObjectKankyo_Fairies(ObjectKankyo* this, GlobalContext* globalCtx) {
if (this->effects[i].base.x + this->effects[i].pos.x - baseX > maxDist) {
this->effects[i].base.x = baseX - maxDist;
this->effects[i].pos.x = 0.0f;
this->effects[i].epoch++;
}
if (this->effects[i].base.x + this->effects[i].pos.x - baseX < -maxDist) {
this->effects[i].base.x = baseX + maxDist;
this->effects[i].pos.x = 0.0f;
this->effects[i].epoch++;
}
if (this->effects[i].base.y + this->effects[i].pos.y - baseY > 50.0f) {
this->effects[i].base.y = baseY - 50.0f;
this->effects[i].pos.y = 0.0f;
this->effects[i].epoch++;
}
if (this->effects[i].base.y + this->effects[i].pos.y - baseY < -50.0f) {
this->effects[i].base.y = baseY + 50.0f;
this->effects[i].pos.y = 0.0f;
this->effects[i].epoch++;
}
if (this->effects[i].base.z + this->effects[i].pos.z - baseZ > maxDist) {
this->effects[i].base.z = baseZ - maxDist;
this->effects[i].pos.z = 0.0f;
this->effects[i].epoch++;
}
if (this->effects[i].base.z + this->effects[i].pos.z - baseZ < -maxDist) {
this->effects[i].base.z = baseZ + maxDist;
this->effects[i].pos.z = 0.0f;
this->effects[i].epoch++;
}
}
}
@ -496,6 +505,7 @@ void ObjectKankyo_DrawFairies(ObjectKankyo* this2, GlobalContext* globalCtx2) {
gSPDisplayList(POLY_XLU_DISP++, gKokiriDustMoteTextureLoadDL);
for (i = 0; i < globalCtx->envCtx.unk_EE[3]; i++) {
FrameInterpolation_RecordOpenChild(&this->effects[i], this->effects[i].epoch);
Matrix_Translate(this->effects[i].base.x + this->effects[i].pos.x,
this->effects[i].base.y + this->effects[i].pos.y,
this->effects[i].base.z + this->effects[i].pos.z, MTXMODE_NEW);
@ -561,6 +571,7 @@ void ObjectKankyo_DrawFairies(ObjectKankyo* this2, GlobalContext* globalCtx2) {
Matrix_RotateZ(DEG_TO_RAD(globalCtx->state.frames * 20.0f), MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_object_kankyo.c", 913), G_MTX_LOAD);
gSPDisplayList(POLY_XLU_DISP++, gKokiriDustMoteDL);
FrameInterpolation_RecordCloseChild();
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_object_kankyo.c", 922);
}

View File

@ -24,6 +24,7 @@ typedef struct ObjectKankyoEffect {
/* 0x4A */ u16 flightRadius;
/* 0x4C */ f32 amplitude;
/* 0x50 */ u16 timer;
u32 epoch;
} ObjectKankyoEffect; // size = 0x54
typedef struct ObjectKankyo {

View File

@ -898,6 +898,15 @@ static s8 sItemActionParams[] = {
PLAYER_AP_SWORD_KOKIRI,
PLAYER_AP_SWORD_MASTER,
PLAYER_AP_SWORD_BGS,
PLAYER_AP_SHIELD_DEKU,
PLAYER_AP_SHIELD_HYLIAN,
PLAYER_AP_SHIELD_MIRROR,
PLAYER_AP_TUNIC_KOKIRI,
PLAYER_AP_TUNIC_GORON,
PLAYER_AP_TUNIC_ZORA,
PLAYER_AP_BOOTS_KOKIRI,
PLAYER_AP_BOOTS_IRON,
PLAYER_AP_BOOTS_HOVER,
};
static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
@ -910,7 +919,8 @@ static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
};
static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
@ -923,7 +933,8 @@ static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
};
typedef enum {
@ -2752,7 +2763,8 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
if ((actionParam == PLAYER_AP_NONE) || !(this->stateFlags1 & PLAYER_STATE1_27) ||
((this->actor.bgCheckFlags & 1) &&
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT)))) {
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT))) ||
((actionParam >= PLAYER_AP_SHIELD_DEKU) && (actionParam <= PLAYER_AP_BOOTS_HOVER))) {
if ((globalCtx->bombchuBowlingStatus == 0) &&
(((actionParam == PLAYER_AP_STICK) && (AMMO(ITEM_STICK) == 0)) ||
@ -2764,6 +2776,33 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
return;
}
if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) {
u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
Inventory_ChangeEquipment(EQUIP_BOOTS, 1);
} else {
Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
}
Player_SetEquipmentData(globalCtx, this);
return;
}
if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) {
u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
Inventory_ChangeEquipment(EQUIP_TUNIC, 1);
} else {
Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
}
Player_SetEquipmentData(globalCtx, this);
return;
}
if (actionParam >= PLAYER_AP_SHIELD_DEKU) {
// Changing shields through action commands is unimplemented
return;
}
if (actionParam == PLAYER_AP_LENS) {
if (func_80087708(globalCtx, 0, 3)) {
if (globalCtx->actorCtx.unk_03 != 0) {
@ -6981,7 +7020,7 @@ void func_808409CC(GlobalContext* globalCtx, Player* this) {
if (sp34 < 4) {
if (((sp34 != 0) && (sp34 != 3)) || ((this->rightHandType == PLAYER_MODELTYPE_RH_SHIELD) &&
((sp34 == 3) || Player_GetSwordHeld(this)))) {
if ((sp34 == 0) && Player_HoldsTwoHandedWeapon(this)) {
if ((sp34 == 1) && Player_HoldsTwoHandedWeapon(this) && CVar_GetS32("gTwoHandedIdle", 1) == 1) {
sp34 = 4;
}
sp38 = sp34 + 9;

View File

@ -471,39 +471,76 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) {
KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->equipVtx);
if ((pauseCtx->cursorSpecialPos == 0) && (cursorItem != PAUSE_ITEM_NONE) && (pauseCtx->state == 6) &&
(pauseCtx->unk_1E4 == 0) && CHECK_BTN_ALL(input->press.button, BTN_A) &&
(pauseCtx->unk_1E4 == 0) &&
CHECK_BTN_ANY(input->press.button, BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT) &&
(pauseCtx->cursorX[PAUSE_EQUIP] != 0)) {
if ((gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == 9) ||
(gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] ==
((void)0, gSaveContext.linkAge))) {
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
gSaveContext.infTable[29] = 0;
gSaveContext.equips.buttonItems[0] = cursorItem;
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
gSaveContext.infTable[29] = 0;
gSaveContext.equips.buttonItems[0] = cursorItem;
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
gSaveContext.swordHealth = 8;
} else {
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
gSaveContext.swordHealth = 8;
} else {
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
}
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
}
}
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
}
Interface_LoadItemIcon1(globalCtx, 0);
}
Interface_LoadItemIcon1(globalCtx, 0);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
pauseCtx->unk_1E4 = 7;
sEquipTimer = 10;
} else if (CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) {
// Only allow assigning tunic and boots to c-buttons
if (pauseCtx->cursorY[PAUSE_EQUIP] > 1) {
u16 slot = 0;
switch (cursorItem) {
case ITEM_TUNIC_KOKIRI:
slot = SLOT_TUNIC_KOKIRI;
break;
case ITEM_TUNIC_GORON:
slot = SLOT_TUNIC_GORON;
break;
case ITEM_TUNIC_ZORA:
slot = SLOT_TUNIC_ZORA;
break;
case ITEM_BOOTS_KOKIRI:
slot = SLOT_BOOTS_KOKIRI;
break;
case ITEM_BOOTS_IRON:
slot = SLOT_BOOTS_IRON;
break;
case ITEM_BOOTS_HOVER:
slot = SLOT_BOOTS_HOVER;
break;
default:
break;
}
KaleidoScope_SetupItemEquip(globalCtx, cursorItem, slot,
pauseCtx->equipVtx[cursorSlot * 4].v.ob[0] * 10,
pauseCtx->equipVtx[cursorSlot * 4].v.ob[1] * 10);
}
}
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
pauseCtx->unk_1E4 = 7;
sEquipTimer = 10;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
}
}
}

View File

@ -351,43 +351,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
if (((gSlotAgeReqs[cursorSlot] == 9) ||
(gSlotAgeReqs[cursorSlot] == ((void)0, gSaveContext.linkAge))) &&
(cursorItem != ITEM_SOLD_OUT)) {
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
pauseCtx->equipTargetCBtn = 0;
} else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
pauseCtx->equipTargetCBtn = 1;
} else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) {
pauseCtx->equipTargetCBtn = 2;
}
pauseCtx->equipTargetItem = cursorItem;
pauseCtx->equipTargetSlot = cursorSlot;
pauseCtx->unk_1E4 = 3;
pauseCtx->equipAnimX = pauseCtx->itemVtx[index].v.ob[0] * 10;
pauseCtx->equipAnimY = pauseCtx->itemVtx[index].v.ob[1] * 10;
pauseCtx->equipAnimAlpha = 255;
sEquipAnimTimer = 0;
sEquipState = 3;
sEquipMoveTimer = 10;
if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) ||
(pauseCtx->equipTargetItem == ITEM_ARROW_ICE) ||
(pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) {
index = 0;
if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) {
index = 1;
}
if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) {
index = 2;
}
Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0,
&D_801333E0, &D_801333E8);
pauseCtx->equipTargetItem = 0xBF + index;
sEquipState = 0;
pauseCtx->equipAnimAlpha = 0;
sEquipMoveTimer = 6;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
}
KaleidoScope_SetupItemEquip(globalCtx, cursorItem, cursorSlot,
pauseCtx->itemVtx[index].v.ob[0] * 10,
pauseCtx->itemVtx[index].v.ob[1] * 10);
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
@ -419,7 +385,9 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
gDPSetEnvColor(POLY_KAL_DISP++, 0, 0, 0, 0);
for (i = 0, j = 24 * 4; i < 3; i++, j += 4) {
if (gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) {
if ((gSaveContext.equips.buttonItems[i + 1] != ITEM_NONE) &&
!((gSaveContext.equips.buttonItems[i + 1] >= ITEM_SHIELD_DEKU) &&
(gSaveContext.equips.buttonItems[i + 1] <= ITEM_BOOTS_HOVER))) {
gSPVertex(POLY_KAL_DISP++, &pauseCtx->itemVtx[j], 4, 0);
POLY_KAL_DISP = KaleidoScope_QuadTextureIA8(POLY_KAL_DISP, gEquippedItemOutlineTex, 32, 32, 0);
}
@ -496,6 +464,46 @@ void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx) {
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kaleido_item.c", 516);
}
void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY) {
Input* input = &globalCtx->state.input[0];
PauseContext* pauseCtx = &globalCtx->pauseCtx;
if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
pauseCtx->equipTargetCBtn = 0;
} else if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
pauseCtx->equipTargetCBtn = 1;
} else if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) {
pauseCtx->equipTargetCBtn = 2;
}
pauseCtx->equipTargetItem = item;
pauseCtx->equipTargetSlot = slot;
pauseCtx->unk_1E4 = 3;
pauseCtx->equipAnimX = animX;
pauseCtx->equipAnimY = animY;
pauseCtx->equipAnimAlpha = 255;
sEquipAnimTimer = 0;
sEquipState = 3;
sEquipMoveTimer = 10;
if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) ||
(pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) {
u16 index = 0;
if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) {
index = 1;
}
if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) {
index = 2;
}
Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
pauseCtx->equipTargetItem = 0xBF + index;
sEquipState = 0;
pauseCtx->equipAnimAlpha = 0;
sEquipMoveTimer = 6;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
}
}
static s16 sCButtonPosX[] = { 66, 90, 114 };
static s16 sCButtonPosY[] = { 110, 92, 110 };

View File

@ -18,6 +18,7 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx);
void KaleidoScope_DrawEquipment(GlobalContext* globalCtx);
void KaleidoScope_SetCursorVtx(PauseContext* pauseCtx, u16 index, Vtx* vtx);
void KaleidoScope_DrawItemSelect(GlobalContext* globalCtx);
void KaleidoScope_SetupItemEquip(GlobalContext* globalCtx, u16 item, u16 slot, s16 animX, s16 animY);
void KaleidoScope_UpdateItemEquip(GlobalContext* globalCtx);
void KaleidoScope_DrawDungeonMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx);
void KaleidoScope_DrawWorldMap(GlobalContext* globalCtx, GraphicsContext* gfxCtx);

View File

@ -14,6 +14,8 @@
#include "vt.h"
#include "SohHooks.h"
#include "soh/frame_interpolation.h"
static void* sEquipmentFRATexs[] = {
gPauseEquipment00FRATex, gPauseEquipment01Tex, gPauseEquipment02Tex, gPauseEquipment03Tex, gPauseEquipment04Tex,
gPauseEquipment10FRATex, gPauseEquipment11Tex, gPauseEquipment12Tex, gPauseEquipment13Tex, gPauseEquipment14Tex,
@ -914,6 +916,13 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) {
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex + pt][3];
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex + pt][4];
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) {
gSaveContext.buttonStatus[1] = BTN_ENABLED;
gSaveContext.buttonStatus[2] = BTN_ENABLED;
gSaveContext.buttonStatus[3] = BTN_ENABLED;
gSaveContext.buttonStatus[4] = BTN_ENABLED;
}
osSyncPrintf("kscope->kscp_pos+pt = %d\n", pauseCtx->pageIndex + pt);
gSaveContext.unk_13EA = 0;
@ -1047,6 +1056,7 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
s16 stepG;
s16 stepB;
FrameInterpolation_RecordOpenChild(NULL, pauseCtx->state + pauseCtx->pageIndex * 100);
OPEN_DISPS(gfxCtx, "../z_kaleido_scope_PAL.c", 1100);
if ((pauseCtx->state < 8) || (pauseCtx->state > 0x11)) {
@ -1418,6 +1428,7 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
}
CLOSE_DISPS(gfxCtx, "../z_kaleido_scope_PAL.c", 1577);
FrameInterpolation_RecordCloseChild();
}
void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
@ -2898,7 +2909,16 @@ void func_808265BC(GlobalContext* globalCtx) {
gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex][2];
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex][3];
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex][4];
pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode];
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) {
gSaveContext.buttonStatus[1] = BTN_ENABLED;
gSaveContext.buttonStatus[2] = BTN_ENABLED;
gSaveContext.buttonStatus[3] = BTN_ENABLED;
gSaveContext.buttonStatus[4] = BTN_ENABLED;
}
pauseCtx->unk_1E4 = 0;
pauseCtx->state++;
pauseCtx->alpha = 255;