Merge branch 'develop' into patch-7

This commit is contained in:
MegaMech 2022-05-14 12:37:02 -06:00 committed by GitHub
commit 4cbfa99a24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
117 changed files with 3592 additions and 923 deletions

View file

@ -1,9 +1,10 @@
# Building Ship of Harkinian
## Windows
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`.
@ -40,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
@ -54,6 +55,7 @@ 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.
@ -61,3 +63,4 @@ Use the `extract_assets.py` script file to run the exporter using any of the fol
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.

1
Jenkinsfile vendored
View file

@ -3,7 +3,6 @@ pipeline {
options {
timestamps()
timeout(time: 30, unit: 'MINUTES')
skipDefaultCheckout(true)
}

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

@ -67,39 +67,45 @@ Refer to the [building instructions](BUILDING.md) to compile SoH.
## 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

@ -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

@ -1,3 +1,6 @@
#ifndef CONFIG_FILE_H
#define CONFIG_FILE_H
#pragma once
#include <string>
@ -35,3 +38,5 @@ namespace Ship {
mINI::INIFile File;
};
}
#endif

View file

@ -43,7 +43,6 @@ void CVar_RegisterString(const char* name, const char* defaultValue);
#include <memory>
extern std::map<std::string, std::unique_ptr<CVar>, std::less<>> cvars;
CVar* CVar_GetVar(const char* name);
void CVar_SetFloat(const char* name, float value);
void CVar_SetString(const char* name, const char* value);
#endif

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();
@ -21,7 +22,7 @@ void Ship::GameOverlay::LoadFont(const std::string& name, const std::string& pat
}
}
void Ship::GameOverlay::TextDraw(float x, float y, bool shadow, const char* fmt, ...) {
void Ship::GameOverlay::TextDraw(float x, float y, bool shadow, ImVec4 color, const char* fmt, ...) {
char buf[1024];
va_list args;
va_start(args, fmt);
@ -29,16 +30,41 @@ void Ship::GameOverlay::TextDraw(float x, float y, bool shadow, const char* fmt,
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
ImGui::PushStyleColor(ImGuiCol_Text, color);
ImGui::PushFont(Fonts[this->CurrentFont]);
if (shadow) {
ImGui::SetCursorPos(ImVec2(x + 1, y + 1));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(.0f, .0f, .0f, 255));
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(.0f, .0f, .0f, color.w));
ImGui::Text(buf, args);
}
ImGui::PopStyleColor();
ImGui::SetCursorPos(ImVec2(x, y));
ImGui::Text(buf, args);
ImGui::PopFont();
ImGui::PopStyleColor();
}
void Ship::GameOverlay::TextDrawNotification(float duration, bool shadow, const char* fmt, ...) {
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
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() {
@ -123,28 +149,45 @@ 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;
for (auto &[key, overlay] : this->RegisteredOverlays) {
if (overlay.type == OverlayType::TEXT) {
const char* text = ImStrdup(key.c_str());
const CVar* var = CVar_GetVar(text);
if (overlay->type == OverlayType::TEXT) {
const char* text = ImStrdup(overlay->value);
const CVar* var = CVar_Get(text);
ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
switch (var->type) {
case CVAR_TYPE_FLOAT:
this->TextDraw(30, textY, true, "%s %.2f", text, var->value.valueFloat);
this->TextDraw(30, textY, true, color, "%s %.2f", text, var->value.valueFloat);
break;
case CVAR_TYPE_S32:
this->TextDraw(30, textY, true, "%s %d", text, var->value.valueS32);
this->TextDraw(30, textY, true, color, "%s %d", text, var->value.valueS32);
break;
case CVAR_TYPE_STRING:
this->TextDraw(30, textY, true, "%s %s", text, var->value.valueStr);
this->TextDraw(30, textY, true, color, "%s %s", text, var->value.valueStr);
break;
}
free((void*) text);
textY += 30;
}
if (overlay->type == OverlayType::NOTIFICATION && overlay->duration > 0) {
const char* text = overlay->value;
const float duration = overlay->duration / overlay->fadeTime;
const ImVec4 color = ImVec4(1.0f, 1.0f, 1.0f, duration);
const float textWidth = this->GetStringWidth(overlay->value);
this->TextDraw(GetScreenWidth() - textWidth - 40, GetScreenHeight() - 40 - notY, true, color, text);
notY += 30;
overlay->duration -= .05f;
}
}
ImGui::End();
@ -156,23 +199,19 @@ bool Ship::OverlayCommand(const std::vector<std::string>& args) {
return CMD_FAILED;
}
if (CVar_GetVar(args[2].c_str()) != nullptr) {
if (CVar_Get(args[2].c_str()) != nullptr) {
const char* key = args[2].c_str();
GameOverlay* overlay = SohImGui::overlay;
if (args[1] == "add") {
if (!overlay->RegisteredOverlays.contains(args[2])) {
overlay->RegisteredOverlays[args[2]] = {
OverlayType::TEXT,
key
};
if (!overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays[key] = new Overlay({ OverlayType::TEXT, ImStrdup(key), -1.0f });
INFO("Added overlay: %s ", key);
} else {
ERROR("Overlay already exists: %s", key);
}
}
else if (args[1] == "remove") {
if (overlay->RegisteredOverlays.contains(args[2])) {
overlay->RegisteredOverlays.erase(args[2]);
} else if (args[1] == "remove") {
if (overlay->RegisteredOverlays.contains(key)) {
overlay->RegisteredOverlays.erase(key);
INFO("Removed overlay: %s ", key);
} else {
ERROR("Overlay not found: %s ", key);
@ -183,4 +222,4 @@ bool Ship::OverlayCommand(const std::vector<std::string>& args) {
}
return CMD_SUCCESS;
}
}

View file

@ -7,18 +7,20 @@
#include <unordered_map>
enum class OverlayType {
TEXT, IMAGE
TEXT, IMAGE, NOTIFICATION
};
struct Overlay {
OverlayType type;
const char* value;
float fadeTime;
float duration;
};
namespace Ship {
class GameOverlay {
public:
std::unordered_map<std::string, Overlay> RegisteredOverlays;
std::unordered_map<std::string, Overlay*> RegisteredOverlays;
std::unordered_map<std::string, ImFont*> Fonts;
std::string CurrentFont = "Default";
void Init();
@ -28,11 +30,13 @@ namespace Ship {
static float GetScreenHeight();
static float GetStringWidth(const char* text);
static ImVec2 CalculateTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f);
void TextDraw(float x, float y, bool shadow, ImVec4 color, const char* text, ...);
void TextDrawNotification(float duration, bool shadow, const char* fmt, ...);
private:
void TextDraw(float x, float y, bool shadow, const char* text, ...);
bool NeedsCleanup = false;
void CleanupNotifications();
void LoadFont(const std::string& name, const std::string& path, float fontSize);
};
static bool OverlayCommand(const std::vector<std::string>& args);
}

View file

@ -1,3 +1,6 @@
#ifndef GAME_VERSION_H
#define GAME_VERSION_H
#pragma once
#define OOT_NTSC_10 0xEC7011B7
@ -17,4 +20,6 @@
#define OOT_PAL_GC_MQ_DBG 0x917D18F6
#define OOT_IQUE_TW 0x3D81FB3E
#define OOT_IQUE_CN 0xB1E1E07B
#define OOT_UNKNOWN 0xFFFFFFFF
#define OOT_UNKNOWN 0xFFFFFFFF
#endif

View file

@ -1,3 +1,6 @@
#ifndef GLOBAL_CTX_2
#define GLOBAL_CTX_2
#pragma once
#ifdef __cplusplus
@ -38,4 +41,6 @@ namespace Ship {
std::string PatchesPath;
};
}
#endif
#endif
#endif

View file

@ -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;
@ -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) {
@ -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;
@ -52,26 +54,24 @@ struct TextureCacheValue {
#endif
};
#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

@ -106,7 +106,7 @@ void Console::Draw() {
if (!this->opened) return;
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
ImGui::Begin("Console", nullptr);
ImGui::Begin("Console", nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
const ImVec2 pos = ImGui::GetWindowPos();
const ImVec2 size = ImGui::GetWindowSize();

View file

@ -257,7 +257,7 @@ namespace SohImGui {
void LoadTexture(const std::string& name, const std::string& path) {
GfxRenderingAPI* api = gfx_get_current_rendering_api();
const auto res = GlobalCtx2::GetInstance()->GetResourceManager()->LoadFile(normalize(path));
const auto res = GlobalCtx2::GetInstance()->GetResourceManager()->LoadFile(path);
const auto asset = new GameAsset{ api->new_texture() };
uint8_t* img_data = stbi_load_from_memory(reinterpret_cast<const stbi_uc*>(res->buffer.get()), res->dwBufferSize, &asset->width, &asset->height, nullptr, 4);
@ -277,7 +277,7 @@ namespace SohImGui {
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint) {
GfxRenderingAPI* api = gfx_get_current_rendering_api();
const auto res = static_cast<Ship::Texture*>(GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(normalize(path)).get());
const auto res = static_cast<Ship::Texture*>(GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(path).get());
std::vector<uint8_t> texBuffer;
texBuffer.reserve(res->width * res->height * 4);
@ -417,6 +417,15 @@ namespace SohImGui {
}
}
void EnhancementButton(std::string text, std::string cvarName)
{
bool val = (bool)CVar_GetS32(cvarName.c_str(), 0);
if (ImGui::Button(text.c_str())) {
CVar_SetS32(cvarName.c_str(), !val);
needs_save = true;
}
}
void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format)
{
int val = CVar_GetS32(cvarName.c_str(), 0);
@ -661,6 +670,7 @@ namespace SohImGui {
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");
@ -668,9 +678,11 @@ namespace SohImGui {
ImGui::Separator();
EnhancementCheckbox("Fix L&R Pause menu", "gUniformLR");
EnhancementCheckbox("Fix Dungeon entrances", "gFixDungeonMinimapIcon");
EnhancementCheckbox("Fix Two Handed idle animations", "gTwoHandedIdle");
EXPERIMENTAL();
EnhancementCheckbox("60 fps interpolation", "g60FPS");
EnhancementCheckbox("Disable LOD", "gDisableLOD");
ImGui::EndMenu();
@ -725,10 +737,11 @@ namespace SohImGui {
if (ImGui::BeginMenu("Developer Tools"))
{
EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
ImGui::Separator();
EnhancementCheckbox("Stats", "gStatsEnabled");
EnhancementCheckbox("Console", "gConsoleEnabled");
console->opened = CVar_GetS32("gConsoleEnabled", 0);
EnhancementCheckbox("OoT Debug Mode", "gDebugEnabled");
ImGui::EndMenu();
}
@ -745,6 +758,7 @@ namespace SohImGui {
}
ImGui::EndMenu();
}
}
ImGui::EndMenuBar();
@ -755,7 +769,7 @@ namespace SohImGui {
if (CVar_GetS32("gStatsEnabled", 0)) {
const float framerate = ImGui::GetIO().Framerate;
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0));
ImGui::Begin("Debug Stats", nullptr, ImGuiWindowFlags_None);
ImGui::Begin("Debug Stats", nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
#ifdef _WIN32
ImGui::Text("Platform: Windows");
@ -921,13 +935,12 @@ namespace SohImGui {
ImTextureID GetTextureByID(int id) {
#ifdef ENABLE_DX11
if (impl.backend == Backend::DX11)
{
ImTextureID gfx_d3d11_get_texture_by_id(int id);
return gfx_d3d11_get_texture_by_id(id);
}
#else
return reinterpret_cast<ImTextureID>(id);
if (impl.backend == Backend::DX11)
{
ImTextureID gfx_d3d11_get_texture_by_id(int id);
return gfx_d3d11_get_texture_by_id(id);
}
#endif
return reinterpret_cast<ImTextureID>(id);
}
}

View file

@ -43,7 +43,7 @@ namespace Ship {
if (raw_path == nullptr) return;
const auto api = BIND_PTR("gfx_api", GfxRenderingAPI*);
const auto path = normalize(raw_path) + ".png";
const auto path = std::string(raw_path) + ".png";
const auto node = BIND_PTR("node", TextureCacheNode**);
const auto fmt = BIND_VAR("fmt", uint32_t*);
const auto siz = BIND_VAR("siz", uint32_t*);

View file

@ -36,15 +36,6 @@ namespace Ship {
void Hook_InvalidateTexture(HookEvent event);
};
inline std::string normalize(std::string path) {
#ifdef _WIN32
std::ranges::replace(path, '/', '\\');
#else
std::replace(path.begin(), path.end(), '\\', '/');
#endif
return path;
}
inline void GrayOutTexture(uint8_t* data, int width, int height) {
for (int x = 0; x < width * height * 4; x += 4) {

View file

@ -24,6 +24,7 @@
#include <chrono>
#include "SohHooks.h"
#include "SohConsole.h"
#include <iostream>
extern "C" {
@ -281,8 +282,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();
}
@ -328,6 +333,8 @@ namespace Ship {
GlobalCtx2::GetInstance()->GetWindow()->ToggleFullscreen();
}
// OTRTODO: Rig with Kirito's console?
//if (dwScancode == Ship::stoi(Conf["KEYBOARD SHORTCUTS"]["KEY_CONSOLE"])) {
// ToggleConsole();

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

@ -29,6 +29,7 @@ void gDPSetTextureImage(Gfx* pkt, u32 f, u32 s, u32 w, uintptr_t i);
void gSPDisplayList(Gfx* pkt, Gfx* dl);
void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset);
void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0);
void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr);
void cleararena(void);
void bootproc(void);
@ -2404,7 +2405,9 @@ void Heaps_Alloc(void);
void Heaps_Free(void);
#ifdef __cplusplus
#undef this
};
#undef this
#endif
#endif

View file

@ -1,7 +1,12 @@
#ifndef STDDEF_H
#define STDDEF_H
#ifndef __cplusplus
#define NULL ((void*)0)
#else
#define NULL nullptr
#endif
#if 0
#define size_t unsigned long
#define ssize_t long

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

@ -30,6 +30,9 @@
#include "ichain.h"
#include "regs.h"
#define AUDIO_HEAP_SIZE 0x38000
#define SYSTEM_HEAP_SIZE (1024 * 1024 * 4)
#ifdef __cplusplus
namespace Ship
{

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

@ -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" />
@ -180,6 +181,7 @@
<ClCompile Include="soh\Enhancements\debugger\debugSaveEditor.cpp" />
<ClCompile Include="soh\Enhancements\debugger\ImGuiHelpers.cpp" />
<ClCompile Include="soh\Enhancements\gameconsole.c" />
<ClCompile Include="soh\Enhancements\savestates.cpp" />
<ClCompile Include="soh\GbiWrap.cpp" />
<ClCompile Include="soh\gu_pc.c" />
<ClCompile Include="soh\OTRGlobals.cpp" />
@ -328,7 +330,6 @@
<ClCompile Include="src\code\z_msgevent.c" />
<ClCompile Include="src\code\z_olib.c" />
<ClCompile Include="src\code\z_onepointdemo.c" />
<ClCompile Include="src\code\z_onepointdemo_data.c" />
<ClCompile Include="src\code\z_parameter.c" />
<ClCompile Include="src\code\z_path.c" />
<ClCompile Include="src\code\z_play.c" />
@ -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" />
@ -926,10 +928,12 @@
<ClInclude Include="soh\Enhancements\cvar.h" />
<ClInclude Include="soh\Enhancements\debugconsole.h" />
<ClInclude Include="soh\Enhancements\debugger\colViewer.h" />
<ClInclude Include="soh\Enhancements\savestates.h" />
<ClInclude Include="soh\Enhancements\debugger\debugger.h" />
<ClInclude Include="soh\Enhancements\debugger\debugSaveEditor.h" />
<ClInclude Include="soh\Enhancements\debugger\ImGuiHelpers.h" />
<ClInclude Include="soh\gameconsole.h" />
<ClInclude Include="soh\OTRAudio.h" />
<ClInclude Include="soh\OTRGlobals.h" />
<ClInclude Include="soh\util.h" />
<ClInclude Include="src\overlays\actors\ovl_Arms_Hook\z_arms_hook.h" />
@ -1409,4 +1413,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -630,9 +630,6 @@
<ClCompile Include="src\code\z_onepointdemo.c">
<Filter>Source Files\src\code</Filter>
</ClCompile>
<ClCompile Include="src\code\z_onepointdemo_data.c">
<Filter>Source Files\src\code</Filter>
</ClCompile>
<ClCompile Include="src\code\z_parameter.c">
<Filter>Source Files\src\code</Filter>
</ClCompile>
@ -2189,6 +2186,14 @@
</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>
</ClCompile>
<ClCompile Include="soh\Enhancements\savestates.cpp">
<Filter>Source Files\soh\Enhancements</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@ -3745,6 +3750,14 @@
</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>
</ClInclude>
<ClInclude Include="soh\OTRAudio.h">
<Filter>Source Files\soh</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>

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,7 +1,15 @@
#ifdef _MSC_VER
#define NOGDI
#endif
#include "debugconsole.h"
#include "../libultraship/SohImGuiImpl.h"
#include "savestates.h"
#include <vector>
#include <string>
#include "soh/OTRGlobals.h"
#define Path _Path
#define PATH_HACK
@ -303,6 +311,66 @@ static bool EntranceHandler(const std::vector<std::string>& args) {
gSaveContext.nextTransition = 11;
}
static bool SaveStateHandler(const std::vector<std::string>& args) {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE });
switch (rtn) {
case SaveStateReturn::SUCCESS:
INFO("[SOH] Saved state to slot %u", slot);
return CMD_SUCCESS;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
ERROR("[SOH] Can not save a state outside of \"GamePlay\"");
return CMD_FAILED;
}
}
static bool LoadStateHandler(const std::vector<std::string>& args) {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn rtn = OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD });
switch (rtn) {
case SaveStateReturn::SUCCESS:
INFO("[SOH] Loaded state from slot %u", slot);
return CMD_SUCCESS;
case SaveStateReturn::FAIL_INVALID_SLOT:
ERROR("[SOH] Invalid State Slot Number (%u)", slot);
return CMD_FAILED;
case SaveStateReturn::FAIL_STATE_EMPTY:
ERROR("[SOH] State Slot (%u) is empty", slot);
return CMD_FAILED;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
ERROR("[SOH] Can not load a state outside of \"GamePlay\"");
return CMD_FAILED;
}
}
static bool StateSlotSelectHandler(const std::vector<std::string>& args) {
if (args.size() != 2) {
ERROR("[SOH] Unexpected arguments passed");
return CMD_FAILED;
}
int slot;
try {
slot = std::stoi(args[1], nullptr, 10);
} catch (std::invalid_argument const& ex) {
ERROR("[SOH] SaveState slot value must be a number.");
return CMD_FAILED;
}
if (slot < 0) {
ERROR("[SOH] Invalid slot passed. Slot must be between 0 and 2");
return CMD_FAILED;
}
OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot);
INFO("[SOH] Slot %u selected", OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot());
return CMD_SUCCESS;
}
#define VARTYPE_INTEGER 0
#define VARTYPE_FLOAT 1
#define VARTYPE_STRING 2
@ -416,6 +484,13 @@ void DebugConsole_Init(void) {
{ { "slot", ArgumentType::NUMBER }, { "item id", ArgumentType::NUMBER } } });
CMD_REGISTER("entrance",
{ EntranceHandler, "Sends player to the entered entrance (hex)", { { "entrance", ArgumentType::NUMBER } } });
CMD_REGISTER("save_state", { SaveStateHandler, "Save a state." });
CMD_REGISTER("load_state", { LoadStateHandler, "Load a state." });
CMD_REGISTER("set_slot", { StateSlotSelectHandler, "Selects a SaveState slot", {
{ "Slot number", ArgumentType::NUMBER, }
} });
DebugConsole_LoadCVars();
}
template <typename Numeric> bool is_number(const std::string& s) {

View file

@ -1,6 +1,7 @@
#include "colViewer.h"
#include "../libultraship/SohImGuiImpl.h"
#include "ImGuiHelpers.h"
#include "../../frame_interpolation.h"
#include <vector>
#include <string>
@ -97,7 +98,7 @@ void DrawColViewerWindow(bool& open) {
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Collision Viewer", &open)) {
if (!ImGui::Begin("Collision Viewer", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}

View file

@ -1540,7 +1540,7 @@ void DrawSaveEditor(bool& open) {
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Save Editor", &open)) {
if (!ImGui::Begin("Save Editor", &open, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGui::End();
return;
}

View file

@ -0,0 +1,957 @@
#include "savestates.h"
#include "GameVersions.h"
#include <cstdio> // std::sprintf
#include "spdlog/spdlog.h"
#include <soh/OTRGlobals.h>
#include <soh/OTRAudio.h>
#include <SohImGuiImpl.h>
#include "z64.h"
#include "z64save.h"
#include <variables.h>
#include <functions.h>
#include "z64map_mark.h"
#include "../../src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.h"
#include "../../src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.h"
#include "../../src/overlays/actors/ovl_Boss_Tw/z_boss_tw.h"
#include "../../src/overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h"
#include "../../src/overlays/actors/ovl_En_Fr/z_en_fr.h"
extern "C" GlobalContext* gGlobalCtx;
// FROM z_lights.c
// I didn't feel like moving it into a header file.
#define LIGHTS_BUFFER_SIZE 32
typedef struct {
/* 0x000 */ s32 numOccupied;
/* 0x004 */ s32 searchIndex;
/* 0x008 */ LightNode buf[LIGHTS_BUFFER_SIZE];
} LightsBuffer; // size = 0x188
#include "savestates_extern.inc"
typedef struct SaveStateInfo {
unsigned char sysHeapCopy[SYSTEM_HEAP_SIZE];
unsigned char audioHeapCopy[AUDIO_HEAP_SIZE];
SaveContext saveContextCopy;
GameInfo gameInfoCopy;
LightsBuffer lightBufferCopy;
AudioContext audioContextCopy;
MtxF mtxStackCopy[20]; // always 20 matricies
MtxF currentMtxCopy;
uint32_t rngSeed;
int16_t blueWarpTimerCopy; /* From door_warp_1 */
SeqScriptState seqScriptStateCopy[4];// Unrelocated
unk_D_8016E750 unk_D_8016E750Copy[4];
ActiveSound gActiveSoundsCopy[7][MAX_CHANNELS_PER_BANK];
uint8_t gSoundBankMutedCopy[7];
u8 D_801333F0_copy;
u8 gAudioSfxSwapOff_copy;
uint16_t gAudioSfxSwapSource_copy[10];
uint16_t gAudioSfxSwapTarget_copy[10];
uint8_t gAudioSfxSwapMode_copy[10];
void (*D_801755D0_copy)(void);
MapMarkData** sLoadedMarkDataTableCopy;
//Static Data
//Camera data
int32_t sInitRegs_copy;
int32_t gDbgCamEnabled_copy;
int32_t sDbgModeIdx_copy;
int16_t sNextUID_copy;
int32_t sCameraInterfaceFlags_copy;
int32_t sCameraInterfaceAlpha_copy;
int32_t sCameraShrinkWindowVal_copy;
int32_t D_8011D3AC_copy;
int32_t sDemo5PrevAction12Frame_copy;
int32_t sDemo5PrevSfxFrame_copy;
int32_t D_8011D3F0_copy;
OnePointCsFull D_8011D6AC_copy[3];
OnePointCsFull D_8011D724_copy[3];
OnePointCsFull D_8011D79C_copy[3];
OnePointCsFull D_8011D83C_copy[2];
OnePointCsFull D_8011D88C_copy[2];
OnePointCsFull D_8011D8DC_copy[3];
OnePointCsFull D_8011D954_copy[4];
OnePointCsFull D_8011D9F4_copy[3];
int16_t D_8011DB08_copy;
int16_t D_8011DB0C_copy;
int32_t sOOBTimer_copy;
f32 D_8015CE50_copy;
f32 D_8015CE54_copy;
CamColChk D_8015CE58_copy;
//Gameover
uint16_t gGameOverTimer_copy;
//One point demo
uint32_t sPrevFrameCs1100_copy;
CutsceneCameraPoint D_8012013C_copy[14];
CutsceneCameraPoint D_8012021C_copy[14];
CutsceneCameraPoint D_801204D4_copy[14];
CutsceneCameraPoint D_801205B4_copy[14];
OnePointCsFull D_801208EC_copy[3];
OnePointCsFull D_80120964_copy[2];
OnePointCsFull D_801209B4_copy[4];
OnePointCsFull D_80120ACC_copy[5];
OnePointCsFull D_80120B94_copy[11];
OnePointCsFull D_80120D4C_copy[7];
OnePointCsFull D_80120FA4_copy[6];
OnePointCsFull D_80121184_copy[2];
OnePointCsFull D_801211D4_copy[2];
OnePointCsFull D_8012133C_copy[3];
OnePointCsFull D_801213B4_copy[5];
OnePointCsFull D_8012151C_copy[2];
OnePointCsFull D_8012156C_copy[2];
OnePointCsFull D_801215BC_copy[1];
OnePointCsFull D_80121C24_copy[7];
OnePointCsFull D_80121D3C_copy[3];
OnePointCsFull D_80121F1C_copy[4];
OnePointCsFull D_80121FBC_copy[4];
OnePointCsFull D_801220D4_copy[5];
OnePointCsFull D_80122714_copy[4];
OnePointCsFull D_80122CB4_copy[2];
OnePointCsFull D_80122D04_copy[2];
OnePointCsFull D_80122E44_copy[2][7];
OnePointCsFull D_8012313C_copy[3];
OnePointCsFull D_801231B4_copy[4];
OnePointCsFull D_80123254_copy[2];
OnePointCsFull D_801232A4_copy[1];
OnePointCsFull D_80123894_copy[3];
OnePointCsFull D_8012390C_copy[2];
OnePointCsFull D_8012395C_copy[3];
OnePointCsFull D_801239D4_copy[3];
uint16_t gTimeIncrement_copy;
//Overlay static data
// z_bg_ddan_kd
Vec3f sBgDdanKdVelocity_copy;
Vec3f sBgDdanKdAccel_copy;
// z_bg_dodoago
s16 sBgDodoagoFirstExplosiveFlag_copy;
u8 sBgDodoagoDisableBombCatcher_copy;
s32 sBgDodoagoTimer_copy;
// z_bg_haka_trap
uint32_t D_80880F30_copy;
uint32_t D_80881014_copy;
// z_bg_hidan_rock
float D_8088BFC0_copy;
// z_bg_menkuri_eye
int32_t D_8089C1A0_copy;
// z_bg_mori_hineri
int16_t sBgMoriHineriNextCamIdx_copy;
// z_bg_po_event
uint8_t sBgPoEventBlocksAtRest_copy;
uint8_t sBgPoEventPuzzleState_copy;
float sBgPoEventblockPushDist_copy;
// z_bg_relay_objects
uint32_t D_808A9508_copy;
// z_bg_spot18_basket
int16_t D_808B85D0_copy;
// z_boss_ganon
uint32_t sBossGanonSeed1_copy;
uint32_t sBossGanonSeed2_copy;
uint32_t sBossGanonSeed3_copy;
void* sBossGanonGanondorf_copy;
void* sBossGanonZelda_copy;
void* sBossGanonCape_copy;
GanondorfEffect sBossGanonEffectBuf_copy[200];
// z_boss_ganon
uint32_t sBossGanonSeed1;
uint32_t sBossGanonSeed2;
uint32_t sBossGanonSeed3;
void* sBossGanonGanondorf;
void* sBossGanonZelda;
void* sBossGanonCape;
GanondorfEffect sBossGanonEffectBuf[200];
// z_boss_ganon2
Vec3f D_8090EB20_copy;
int8_t D_80910638_copy;
void* sBossGanon2Zelda_copy;
void* D_8090EB30_copy;
int32_t sBossGanon2Seed1_copy;
int32_t sBossGanon2Seed2_copy;
int32_t sBossGanon2Seed3_copy;
Vec3f D_809105D8_copy[4];
Vec3f D_80910608_copy[4];
BossGanon2Effect sBossGanon2Particles_copy[100];
// z_boss_tw
uint8_t sTwInitalized_copy;
BossTwEffect sTwEffects_copy[150];
// z_demo_6k
Vec3f sDemo6kVelocity_copy;
// z_demo_du
int32_t D_8096CE94_copy;
// z_demo_kekkai
Vec3f demoKekkaiVel_copy;
// z_en_bw
int32_t sSlugGroup_copy;
// z_en_clear_tag
uint8_t sClearTagIsEffectInitialized_copy;
EnClearTagEffect sClearTagEffects_copy[CLEAR_TAG_EFFECT_MAX_COUNT];
// z_en_fr
EnFrPointers sEnFrPointers_copy;
// z_en_goma
uint8_t sSpawnNum_copy;
// z_en_insect
float D_80A7DEB0_copy;
int16_t D_80A7DEB4_copy;
int16_t D_80A7DEB8_copy;
// z_en_ishi
int16_t sRockRotSpeedX_copy;
int16_t sRockRotSpeedY_copy;
// z_en_niw
int16_t D_80AB85E0_copy;
uint8_t sLowerRiverSpawned_copy;
uint8_t sUpperRiverSpawned_copy;
// z_en_po_field
int32_t sEnPoFieldNumSpawned_copy;
Vec3s sEnPoFieldSpawnPositions_copy[10];
u8 sEnPoFieldSpawnSwitchFlags_copy[10];
// z_en_takara_man
uint8_t sTakaraIsInitialized_copy;
// z_en_xc
int32_t D_80B41D90_copy;
int32_t sEnXcFlameSpawned_copy;
int32_t D_80B41DA8_copy;
int32_t D_80B41DAC_copy;
// z_en_zf
int16_t D_80B4A1B0_copy;
int16_t D_80B4A1B4_copy;
int32_t D_80B5A468_copy;
int32_t D_80B5A494_copy;
int32_t D_80B5A4BC_copy;
uint8_t sKankyoIsSpawned_copy;
int16_t sTrailingFairies_copy;
//Misc static data
// z_map_exp
s16 sPlayerInitialPosX_copy;
s16 sPlayerInitialPosZ_copy;
s16 sPlayerInitialDirection_copy;
// code_800E(something. fill me in later)
u8 sOcarinaInpEnabled_copy;
s8 D_80130F10_copy;
u8 sCurOcarinaBtnVal_copy;
u8 sPrevOcarinaNoteVal_copy;
u8 sCurOcarinaBtnIdx_copy;
u8 sLearnSongLastBtn_copy;
f32 D_80130F24_copy;
f32 D_80130F28_copy;
s8 D_80130F2C_copy;
s8 D_80130F30_copy;
s8 D_80130F34_copy;
u8 sDisplayedNoteValue_copy;
u8 sPlaybackState_copy;
u32 D_80130F3C_copy;
u32 sNotePlaybackTimer_copy;
u16 sPlaybackNotePos_copy;
u16 sStaffPlaybackPos_copy;
u32 sCurOcarinaBtnPress_copy;
u32 D_8016BA10_copy;
u32 sPrevOcarinaBtnPress_copy;
s32 D_8016BA18_copy;
s32 D_8016BA1C_copy;
u8 sCurOcarinaSong_copy[8];
u8 sOcarinaSongAppendPos_copy;
u8 sOcarinaHasStartedSong_copy;
u8 sOcarinaSongNoteStartIdx_copy;
u8 sOcarinaSongCnt_copy;
u16 sOcarinaAvailSongs_copy;
u8 sStaffPlayingPos_copy;
u16 sLearnSongPos_copy[0x10];
u16 D_8016BA50_copy[0x10];
u16 D_8016BA70_copy[0x10];
u8 sLearnSongExpectedNote_copy[0x10];
OcarinaNote D_8016BAA0_copy;
u8 sAudioHasMalonBgm_copy;
f32 sAudioMalonBgmDist_copy;
// Message_PAL
s16 sOcarinaNoteBufPos_copy;
s16 sOcarinaNoteBufLen_copy;
u8 sOcarinaNoteBuf_copy[12];
u8 D_8014B2F4_copy;
u8 sTextboxSkipped_copy;
u16 sNextTextId_copy;
s16 sLastPlayedSong_copy;
s16 sHasSunsSong_copy;
s16 sMessageHasSetSfx_copy;
u16 sOcarinaSongBitFlags_copy;
} SaveStateInfo;
class SaveState {
friend class SaveStateMgr;
public:
SaveState(std::shared_ptr<SaveStateMgr> mgr, unsigned int slot);
private:
unsigned int slot;
std::shared_ptr<SaveStateMgr> saveStateMgr;
std::shared_ptr<SaveStateInfo> info;
void Save(void);
void Load(void);
void BackupSeqScriptState(void);
void LoadSeqScriptState(void);
void BackupCameraData(void);
void LoadCameraData(void);
void SaveOnePointDemoData(void);
void LoadOnePointDemoData(void);
void SaveOverlayStaticData(void);
void LoadOverlayStaticData(void);
void SaveMiscCodeData(void);
void LoadMiscCodeData(void);
SaveStateInfo* GetSaveStateInfo(void);
};
SaveStateMgr::SaveStateMgr() {
this->SetCurrentSlot(0);
}
SaveStateMgr::~SaveStateMgr() {
this->states.clear();
}
SaveState::SaveState(std::shared_ptr<SaveStateMgr> mgr, unsigned int slot) : saveStateMgr(mgr), slot(slot), info(nullptr) {
this->info = std::make_shared<SaveStateInfo>();
}
void SaveState::BackupSeqScriptState(void) {
for (unsigned int i = 0; i < 4; i++) {
info->seqScriptStateCopy[i].value = gAudioContext.seqPlayers[i].scriptState.value;
info->seqScriptStateCopy[i].remLoopIters[0] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[0];
info->seqScriptStateCopy[i].remLoopIters[1] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[1];
info->seqScriptStateCopy[i].remLoopIters[2] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[2];
info->seqScriptStateCopy[i].remLoopIters[3] = gAudioContext.seqPlayers[i].scriptState.remLoopIters[3];
info->seqScriptStateCopy[i].depth = gAudioContext.seqPlayers[i].scriptState.depth;
info->seqScriptStateCopy[i].pc = (u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.pc - (uintptr_t)gAudioHeap);
info->seqScriptStateCopy[i].stack[0] =
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[0] - (uintptr_t)gAudioHeap);
info->seqScriptStateCopy[i].stack[1] =
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[1] - (uintptr_t)gAudioHeap);
info->seqScriptStateCopy[i].stack[2] =
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[2] - (uintptr_t)gAudioHeap);
info->seqScriptStateCopy[i].stack[3] =
(u8*)((uintptr_t)gAudioContext.seqPlayers[i].scriptState.stack[3] - (uintptr_t)gAudioHeap);
}
}
void SaveState::LoadSeqScriptState(void) {
for (unsigned int i = 0; i < 4; i++) {
gAudioContext.seqPlayers[i].scriptState.value = info->seqScriptStateCopy[i].value;
gAudioContext.seqPlayers[i].scriptState.remLoopIters[0] = info->seqScriptStateCopy[i].remLoopIters[0];
gAudioContext.seqPlayers[i].scriptState.remLoopIters[1] = info->seqScriptStateCopy[i].remLoopIters[1];
gAudioContext.seqPlayers[i].scriptState.remLoopIters[2] = info->seqScriptStateCopy[i].remLoopIters[2];
gAudioContext.seqPlayers[i].scriptState.remLoopIters[3] = info->seqScriptStateCopy[i].remLoopIters[3];
gAudioContext.seqPlayers[i].scriptState.depth = info->seqScriptStateCopy[i].depth;
gAudioContext.seqPlayers[i].scriptState.pc =
(u8*)((uintptr_t)info->seqScriptStateCopy[i].pc + (uintptr_t)gAudioHeap);
gAudioContext.seqPlayers[i].scriptState.stack[0] =
(u8*)((uintptr_t)info->seqScriptStateCopy[i].stack[0] + (uintptr_t)gAudioHeap);
gAudioContext.seqPlayers[i].scriptState.stack[1] =
(u8*)((uintptr_t)info->seqScriptStateCopy[i].stack[1] + (uintptr_t)gAudioHeap);
gAudioContext.seqPlayers[i].scriptState.stack[2] =
(u8*)((uintptr_t)info->seqScriptStateCopy[i].stack[2] + (uintptr_t)gAudioHeap);
gAudioContext.seqPlayers[i].scriptState.stack[3] =
(u8*)((uintptr_t)info->seqScriptStateCopy[i].stack[3] + (uintptr_t)gAudioHeap);
}
}
void SaveState::BackupCameraData(void) {
info->sInitRegs_copy = sInitRegs;
info->gDbgCamEnabled_copy = gDbgCamEnabled;
info->sNextUID_copy = sNextUID;
info->sCameraInterfaceFlags_copy = sCameraInterfaceFlags;
info->sCameraInterfaceAlpha_copy = sCameraInterfaceAlpha;
info->sCameraShrinkWindowVal_copy = sCameraShrinkWindowVal;
info->D_8011D3AC_copy = D_8011D3AC;
info->sDemo5PrevAction12Frame_copy = sDemo5PrevAction12Frame;
info->sDemo5PrevSfxFrame_copy = sDemo5PrevSfxFrame;
info->D_8011D3F0_copy = D_8011D3F0;
memcpy(info->D_8011D6AC_copy, D_8011D6AC, sizeof(info->D_8011D6AC_copy));
memcpy(info->D_8011D724_copy, D_8011D724, sizeof(info->D_8011D724_copy));
memcpy(info->D_8011D79C_copy, D_8011D79C, sizeof(info->D_8011D79C_copy));
memcpy(info->D_8011D83C_copy, D_8011D83C, sizeof(info->D_8011D83C_copy));
memcpy(info->D_8011D88C_copy, D_8011D88C, sizeof(info->D_8011D88C_copy));
memcpy(info->D_8011D8DC_copy, D_8011D8DC, sizeof(info->D_8011D8DC_copy));
memcpy(info->D_8011D954_copy, D_8011D954, sizeof(info->D_8011D954_copy));
memcpy(info->D_8011D9F4_copy, D_8011D9F4, sizeof(info->D_8011D9F4_copy));
info->D_8011DB08_copy = D_8011DB08;
info->D_8011DB0C_copy = D_8011DB0C;
info->sOOBTimer_copy = sOOBTimer;
info->D_8015CE50_copy = D_8015CE50;
info->D_8015CE54_copy = D_8015CE54;
memcpy(&info->D_8015CE58_copy, &D_8015CE58, sizeof(info->D_8015CE58_copy));
}
void SaveState::LoadCameraData(void) {
sInitRegs = info->sInitRegs_copy;
gDbgCamEnabled = info->gDbgCamEnabled_copy;
sDbgModeIdx = info->sDbgModeIdx_copy;
sNextUID = info->sNextUID_copy;
sCameraInterfaceAlpha = info->sCameraInterfaceAlpha_copy;
sCameraInterfaceFlags = info->sCameraInterfaceFlags_copy;
sCameraShrinkWindowVal = info->sCameraShrinkWindowVal_copy;
D_8011D3AC = info->D_8011D3AC_copy;
sDemo5PrevAction12Frame = info->sDemo5PrevAction12Frame_copy;
sDemo5PrevSfxFrame = info->sDemo5PrevSfxFrame_copy;
D_8011D3F0 = info->D_8011D3F0_copy;
memcpy(D_8011D6AC, info->D_8011D6AC_copy, sizeof(info->D_8011D6AC_copy));
memcpy(D_8011D724, info->D_8011D724_copy, sizeof(info->D_8011D724_copy));
memcpy(D_8011D79C, info->D_8011D79C_copy, sizeof(info->D_8011D79C_copy));
memcpy(D_8011D83C, info->D_8011D83C_copy, sizeof(info->D_8011D83C_copy));
memcpy(D_8011D88C, info->D_8011D88C_copy, sizeof(info->D_8011D88C_copy));
memcpy(D_8011D8DC, info->D_8011D8DC_copy, sizeof(info->D_8011D8DC_copy));
memcpy(D_8011D954, info->D_8011D954_copy, sizeof(info->D_8011D954_copy));
memcpy(D_8011D9F4, info->D_8011D9F4_copy, sizeof(info->D_8011D9F4_copy));
D_8011DB08 = info->D_8011DB08_copy;
D_8011DB0C = info->D_8011DB0C_copy;
sOOBTimer = info->sOOBTimer_copy;
D_8015CE50 = info->D_8015CE50_copy;
D_8015CE54 = info->D_8015CE54_copy;
memcpy(&D_8015CE58, &info->D_8015CE58_copy, sizeof(info->D_8015CE58_copy));
}
void SaveState::SaveOnePointDemoData(void) {
info->sPrevFrameCs1100_copy = sPrevFrameCs1100;
memcpy(info->D_8012013C_copy, D_8012013C, sizeof(info->D_8012013C_copy));
memcpy(info->D_8012021C_copy, D_8012021C, sizeof(info->D_8012021C_copy));
memcpy(info->D_801204D4_copy, D_801204D4, sizeof(info->D_801204D4_copy));
memcpy(info->D_801205B4_copy, D_801205B4, sizeof(info->D_801205B4_copy));
memcpy(info->D_801208EC_copy, D_801208EC, sizeof(info->D_801208EC_copy));
memcpy(info->D_80120964_copy, D_80120964, sizeof(info->D_80120964_copy));
memcpy(info->D_801209B4_copy, D_801209B4, sizeof(info->D_801209B4_copy));
memcpy(info->D_80120ACC_copy, D_80120ACC, sizeof(info->D_80120ACC_copy));
memcpy(info->D_80120B94_copy, D_80120B94, sizeof(info->D_80120B94_copy));
memcpy(info->D_80120D4C_copy, D_80120D4C, sizeof(info->D_80120D4C_copy));
memcpy(info->D_80120FA4_copy, D_80120FA4, sizeof(info->D_80120FA4_copy));
memcpy(info->D_80121184_copy, D_80121184, sizeof(info->D_80121184_copy));
memcpy(info->D_801211D4_copy, D_801211D4, sizeof(info->D_801211D4_copy));
memcpy(info->D_8012133C_copy, D_8012133C, sizeof(info->D_8012133C_copy));
memcpy(info->D_801213B4_copy, D_801213B4, sizeof(info->D_801213B4_copy));
memcpy(info->D_8012151C_copy, D_8012151C, sizeof(info->D_8012151C_copy));
memcpy(info->D_8012156C_copy, D_8012156C, sizeof(info->D_8012156C_copy));
memcpy(info->D_801215BC_copy, D_801215BC, sizeof(info->D_801215BC_copy));
memcpy(info->D_80121C24_copy, D_80121C24, sizeof(info->D_80121C24_copy));
memcpy(info->D_80121D3C_copy, D_80121D3C, sizeof(info->D_80121D3C_copy));
memcpy(info->D_80121F1C_copy, D_80121F1C, sizeof(info->D_80121F1C_copy));
memcpy(info->D_80121FBC_copy, D_80121FBC, sizeof(info->D_80121FBC_copy));
memcpy(info->D_801220D4_copy, D_801220D4, sizeof(info->D_801220D4_copy));
memcpy(info->D_80122714_copy, D_80122714, sizeof(info->D_80122714_copy));
memcpy(info->D_80122CB4_copy, D_80122CB4, sizeof(info->D_80122CB4_copy));
memcpy(info->D_80122D04_copy, D_80122D04, sizeof(info->D_80122D04_copy));
memcpy(info->D_80122E44_copy, D_80122E44, sizeof(info->D_80122E44_copy));
memcpy(info->D_8012313C_copy, D_8012313C, sizeof(info->D_8012313C_copy));
memcpy(info->D_801231B4_copy, D_801231B4, sizeof(info->D_801231B4_copy));
memcpy(info->D_80123254_copy, D_80123254, sizeof(info->D_80123254_copy));
memcpy(info->D_801232A4_copy, D_801232A4, sizeof(info->D_801232A4_copy));
memcpy(info->D_80123894_copy, D_80123894, sizeof(info->D_80123894_copy));
memcpy(info->D_8012390C_copy, D_8012390C, sizeof(info->D_8012390C_copy));
memcpy(info->D_8012395C_copy, D_8012395C, sizeof(info->D_8012395C_copy));
memcpy(info->D_801239D4_copy, D_801239D4, sizeof(info->D_801239D4_copy));
}
void SaveState::LoadOnePointDemoData(void) {
sPrevFrameCs1100 = info->sPrevFrameCs1100_copy;
memcpy(D_8012013C, info->D_8012013C_copy, sizeof(info->D_8012013C_copy));
memcpy(D_8012021C, info->D_8012021C_copy, sizeof(info->D_8012021C_copy));
memcpy(D_801204D4, info->D_801204D4_copy, sizeof(info->D_801204D4_copy));
memcpy(D_801205B4, info->D_801205B4_copy, sizeof(info->D_801205B4_copy));
memcpy(D_801208EC, info->D_801208EC_copy, sizeof(info->D_801208EC_copy));
memcpy(D_80120964, info->D_80120964_copy, sizeof(info->D_80120964_copy));
memcpy(D_801209B4, info->D_801209B4_copy, sizeof(info->D_801209B4_copy));
memcpy(D_80120ACC, info->D_80120ACC_copy, sizeof(info->D_80120ACC_copy));
memcpy(D_80120B94, info->D_80120B94_copy, sizeof(info->D_80120B94_copy));
memcpy(D_80120D4C, info->D_80120D4C_copy, sizeof(info->D_80120D4C_copy));
memcpy(D_80120FA4, info->D_80120FA4_copy, sizeof(info->D_80120FA4_copy));
memcpy(D_80121184, info->D_80121184_copy, sizeof(info->D_80121184_copy));
memcpy(D_801211D4, info->D_801211D4_copy, sizeof(info->D_801211D4_copy));
memcpy(D_8012133C, info->D_8012133C_copy, sizeof(info->D_8012133C_copy));
memcpy(D_801213B4, info->D_801213B4_copy, sizeof(info->D_801213B4_copy));
memcpy(D_8012151C, info->D_8012151C_copy, sizeof(info->D_8012151C_copy));
memcpy(D_8012156C, info->D_8012156C_copy, sizeof(info->D_8012156C_copy));
memcpy(D_801215BC, info->D_801215BC_copy, sizeof(info->D_801215BC_copy));
memcpy(D_80121C24, info->D_80121C24_copy, sizeof(info->D_80121C24_copy));
memcpy(D_80121D3C, info->D_80121D3C_copy, sizeof(info->D_80121D3C_copy));
memcpy(D_80121F1C, info->D_80121F1C_copy, sizeof(info->D_80121F1C_copy));
memcpy(D_80121FBC, info->D_80121FBC_copy, sizeof(info->D_80121FBC_copy));
memcpy(D_801220D4, info->D_801220D4_copy, sizeof(info->D_801220D4_copy));
memcpy(D_80122714, info->D_80122714_copy, sizeof(info->D_80122714_copy));
memcpy(D_80122CB4, info->D_80122CB4_copy, sizeof(info->D_80122CB4_copy));
memcpy(D_80122D04, info->D_80122D04_copy, sizeof(info->D_80122D04_copy));
memcpy(D_80122E44, info->D_80122E44_copy, sizeof(info->D_80122E44_copy));
memcpy(D_8012313C, info->D_8012313C_copy, sizeof(info->D_8012313C_copy));
memcpy(D_801231B4, info->D_801231B4_copy, sizeof(info->D_801231B4_copy));
memcpy(D_80123254, info->D_80123254_copy, sizeof(info->D_80123254_copy));
memcpy(D_801232A4, info->D_801232A4_copy, sizeof(info->D_801232A4_copy));
memcpy(D_80123894, info->D_80123894_copy, sizeof(info->D_80123894_copy));
memcpy(D_8012390C, info->D_8012390C_copy, sizeof(info->D_8012390C_copy));
memcpy(D_8012395C, info->D_8012395C_copy, sizeof(info->D_8012395C_copy));
memcpy(D_801239D4, info->D_801239D4_copy, sizeof(info->D_801239D4_copy));
}
void SaveState::SaveOverlayStaticData(void) {
info->sBgDdanKdVelocity_copy = sBgDdanKdVelocity;
info->sBgDdanKdAccel_copy = sBgDdanKdAccel;
info->sBgDodoagoFirstExplosiveFlag_copy = sBgDodoagoFirstExplosiveFlag;
info->sBgDodoagoDisableBombCatcher_copy = sBgDodoagoDisableBombCatcher;
info->sBgDodoagoTimer_copy = sBgDodoagoTimer;
info->D_80880F30_copy = D_80880F30;
info->D_80881014_copy = D_80881014;
info->D_8088BFC0_copy = D_8088BFC0;
info->sBgMoriHineriNextCamIdx_copy = sBgMoriHineriNextCamIdx;
info->sBgPoEventBlocksAtRest_copy = sBgPoEventBlocksAtRest;
info->sBgPoEventPuzzleState_copy = sBgPoEventPuzzleState;
info->sBgPoEventblockPushDist_copy = sBgPoEventblockPushDist;
info->D_808A9508_copy = D_808A9508;
info->D_808B85D0_copy = D_808B85D0;
info->sBossGanonSeed1_copy = sBossGanonSeed1;
info->sBossGanonSeed2_copy = sBossGanonSeed2;
info->sBossGanonSeed3_copy = sBossGanonSeed3;
info->sBossGanonGanondorf_copy = sBossGanonGanondorf;
info->sBossGanonZelda_copy = sBossGanonZelda;
info->sBossGanonCape_copy = sBossGanonCape;
memcpy(info->sBossGanonEffectBuf_copy, sBossGanonEffectBuf, sizeof(info->sBossGanonEffectBuf_copy));
info->D_8090EB20_copy = D_8090EB20;
info->D_80910638_copy = D_80910638;
info->sBossGanon2Zelda_copy = sBossGanon2Zelda;
info->D_8090EB30_copy = D_8090EB30;
info->sBossGanon2Seed1_copy = sBossGanon2Seed1;
info->sBossGanon2Seed2_copy = sBossGanon2Seed2;
info->sBossGanon2Seed3_copy = sBossGanon2Seed3;
memcpy(info->D_809105D8_copy, D_809105D8, sizeof(D_809105D8));
memcpy(info->D_80910608_copy, D_80910608, sizeof(D_80910608));
memcpy(info->sBossGanon2Particles_copy, sBossGanon2Particles, sizeof(sBossGanon2Particles));
info->sTwInitalized_copy = sTwInitalized;
memcpy(info->sTwEffects_copy, sTwEffects, sizeof(sTwEffects));
info->sDemo6kVelocity_copy = sDemo6kVelocity;
info->D_8096CE94_copy = D_8096CE94;
info->demoKekkaiVel_copy = demoKekkaiVel;
info->sSlugGroup_copy = sSlugGroup;
info->sClearTagIsEffectInitialized_copy = sClearTagIsEffectsInitialized;
memcpy(info->sClearTagEffects_copy, sClearTagEffects, sizeof(sClearTagEffects));
memcpy(&info->sEnFrPointers_copy, &sEnFrPointers, sizeof(info->sEnFrPointers_copy));
info->sSpawnNum_copy = sSpawnNum;
info->D_80A7DEB0_copy = D_80A7DEB0;
info->D_80A7DEB4_copy = D_80A7DEB4;
info->D_80A7DEB8_copy = D_80A7DEB8;
info->sRockRotSpeedX_copy = sRockRotSpeedX;
info->sRockRotSpeedY_copy = sRockRotSpeedY;
info->D_80AB85E0_copy = D_80AB85E0;
info->sLowerRiverSpawned_copy = sLowerRiverSpawned;
info->sUpperRiverSpawned_copy = sUpperRiverSpawned;
info->sEnPoFieldNumSpawned_copy = sEnPoFieldNumSpawned;
memcpy(info->sEnPoFieldSpawnPositions_copy, sEnPoFieldSpawnPositions, sizeof(info->sEnPoFieldSpawnPositions_copy));
memcpy(info->sEnPoFieldSpawnSwitchFlags_copy, sEnPoFieldSpawnSwitchFlags, sizeof(info->sEnPoFieldSpawnSwitchFlags_copy));
info->sTakaraIsInitialized_copy = sTakaraIsInitialized;
info->D_80B41D90_copy = D_80B41D90;
info->sEnXcFlameSpawned_copy = sEnXcFlameSpawned;
info->D_80B41DA8_copy = D_80B41DA8;
info->D_80B41DAC_copy = D_80B41DAC;
info->D_80B4A1B0_copy = D_80B4A1B0;
info->D_80B4A1B4_copy = D_80B4A1B4;
info->D_80B5A468_copy = D_80B5A468;
info->D_80B5A494_copy = D_80B5A494;
info->D_80B5A4BC_copy = D_80B5A4BC;
info->sKankyoIsSpawned_copy = sKankyoIsSpawned;
info->sTrailingFairies_copy = sTrailingFairies;
}
void SaveState::LoadOverlayStaticData(void) {
sBgDdanKdVelocity = info->sBgDdanKdVelocity_copy;
sBgDdanKdAccel = info->sBgDdanKdAccel_copy;
sBgDodoagoFirstExplosiveFlag = info->sBgDodoagoFirstExplosiveFlag_copy;
sBgDodoagoDisableBombCatcher = info->sBgDodoagoDisableBombCatcher_copy;
sBgDodoagoTimer = info->sBgDodoagoTimer_copy;
D_80880F30 = info->D_80880F30_copy;
D_80881014 = info->D_80881014_copy;
D_8088BFC0 = info->D_8088BFC0_copy;
sBgMoriHineriNextCamIdx = info->sBgMoriHineriNextCamIdx_copy;
sBgPoEventBlocksAtRest = info->sBgPoEventBlocksAtRest_copy;
sBgPoEventPuzzleState = info->sBgPoEventPuzzleState_copy;
sBgPoEventblockPushDist = info->sBgPoEventblockPushDist_copy;
D_808A9508 = info->D_808A9508_copy;
D_808B85D0 = info->D_808B85D0_copy;
sBossGanonSeed1 = info->sBossGanonSeed1_copy;
sBossGanonSeed2 = info->sBossGanonSeed2_copy;
sBossGanonSeed3 = info->sBossGanonSeed3_copy;
sBossGanonGanondorf = info->sBossGanonGanondorf_copy;
sBossGanonZelda = info->sBossGanonZelda_copy;
sBossGanonCape = info->sBossGanonCape_copy;
memcpy(sBossGanonEffectBuf, info->sBossGanonEffectBuf_copy, sizeof(info->sBossGanonEffectBuf_copy));
D_8090EB20 = info->D_8090EB20_copy;
D_80910638 = info->D_80910638_copy;
sBossGanon2Zelda = info->sBossGanon2Zelda_copy;
D_8090EB30 = info->D_8090EB30_copy;
sBossGanon2Seed1 = info->sBossGanon2Seed1_copy;
sBossGanon2Seed2 = info->sBossGanon2Seed2_copy;
sBossGanon2Seed3 = info->sBossGanon2Seed3_copy;
memcpy(D_809105D8, info->D_809105D8_copy, sizeof(D_809105D8));
memcpy(D_80910608, info->D_80910608_copy, sizeof(D_80910608));
memcpy(sBossGanon2Particles, info->sBossGanon2Particles_copy, sizeof(sBossGanon2Particles));
sTwInitalized = info->sTwInitalized_copy;
memcpy(sTwEffects, info->sTwEffects_copy, sizeof(sTwEffects));
sDemo6kVelocity = info->sDemo6kVelocity_copy;
D_8096CE94 = info->D_8096CE94_copy;
demoKekkaiVel = info->demoKekkaiVel_copy;
sSlugGroup = info->sSlugGroup_copy;
sClearTagIsEffectsInitialized = info->sClearTagIsEffectInitialized_copy;
memcpy(sClearTagEffects, info->sClearTagEffects_copy, sizeof(sClearTagEffects));
D_80A7DEB0 = info->D_80A7DEB0_copy;
D_80A7DEB4 = info->D_80A7DEB4_copy;
D_80A7DEB8 = info->D_80A7DEB8_copy;
sRockRotSpeedX = info->sRockRotSpeedX_copy;
sRockRotSpeedY = info->sRockRotSpeedY_copy;
D_80AB85E0 = info->D_80AB85E0_copy;
sLowerRiverSpawned = info->sLowerRiverSpawned_copy;
sUpperRiverSpawned = info->sUpperRiverSpawned_copy;
sEnPoFieldNumSpawned = info->sEnPoFieldNumSpawned_copy;
memcpy(sEnPoFieldSpawnPositions, info->sEnPoFieldSpawnPositions_copy, sizeof(info->sEnPoFieldSpawnPositions_copy));
memcpy(sEnPoFieldSpawnSwitchFlags, info->sEnPoFieldSpawnSwitchFlags_copy, sizeof(info->sEnPoFieldSpawnSwitchFlags_copy));
sTakaraIsInitialized = info->sTakaraIsInitialized_copy;
D_80B41D90 = info->D_80B41D90_copy;
sEnXcFlameSpawned = info->sEnXcFlameSpawned_copy;
D_80B41DA8 = info->D_80B41DA8_copy;
D_80B41DAC = info->D_80B41DAC_copy;
D_80B4A1B0 = info->D_80B4A1B0_copy;
D_80B4A1B4 = info->D_80B4A1B4_copy;
D_80B5A468 = info->D_80B5A468_copy;
D_80B5A494 = info->D_80B5A494_copy;
D_80B5A4BC = info->D_80B5A4BC_copy;
sKankyoIsSpawned = info->sKankyoIsSpawned_copy;
sTrailingFairies = info->sTrailingFairies_copy;
}
void SaveState::SaveMiscCodeData(void) {
info->gGameOverTimer_copy = gGameOverTimer;
info->gTimeIncrement_copy = gTimeIncrement;
info->sLoadedMarkDataTableCopy = sLoadedMarkDataTable;
info->sPlayerInitialPosX_copy = sPlayerInitialPosX;
info->sPlayerInitialPosZ_copy = sPlayerInitialPosZ;
info->sPlayerInitialDirection_copy = sPlayerInitialDirection;
info->sOcarinaInpEnabled_copy = sOcarinaInpEnabled;
info->D_80130F10_copy = D_80130F10;
info->sCurOcarinaBtnVal_copy = sCurOcarinaBtnVal;
info->sPrevOcarinaNoteVal_copy = sPrevOcarinaNoteVal;
info->sCurOcarinaBtnIdx_copy = sCurOcarinaBtnIdx;
info->sLearnSongLastBtn_copy = sLearnSongLastBtn;
info->D_80130F24_copy = D_80130F24;
info->D_80130F28_copy = D_80130F28;
info->D_80130F2C_copy = D_80130F2C;
info->D_80130F30_copy = D_80130F30;
info->D_80130F34_copy = D_80130F34;
info->sPlaybackState_copy = sPlaybackState;
info->D_80130F3C_copy = D_80130F3C;
info->sNotePlaybackTimer_copy = sNotePlaybackTimer;
info->sPlaybackNotePos_copy = sPlaybackNotePos;
info->sStaffPlaybackPos_copy = sStaffPlaybackPos;
info->sCurOcarinaBtnPress_copy = sCurOcarinaBtnPress;
info->D_8016BA10_copy = D_8016BA10;
info->sPrevOcarinaBtnPress_copy = sPrevOcarinaBtnPress;
info->D_8016BA18_copy = D_8016BA18;
info->D_8016BA1C_copy = D_8016BA1C;
memcpy(info->sCurOcarinaSong_copy, sCurOcarinaSong, sizeof(sCurOcarinaSong));
info->sOcarinaSongAppendPos_copy = sOcarinaSongAppendPos;
info->sOcarinaHasStartedSong_copy = sOcarinaHasStartedSong;
info->sOcarinaSongNoteStartIdx_copy = sOcarinaSongNoteStartIdx;
info->sOcarinaSongCnt_copy = sOcarinaSongCnt;
info->sOcarinaAvailSongs_copy = sOcarinaAvailSongs;
info->sStaffPlayingPos_copy = sStaffPlayingPos;
memcpy(info->sLearnSongPos_copy, sLearnSongPos, sizeof(sLearnSongPos));
memcpy(info->D_8016BA50_copy, D_8016BA50, sizeof(D_8016BA50));
memcpy(info->D_8016BA70_copy, D_8016BA70, sizeof(D_8016BA70));
memcpy(info->sLearnSongExpectedNote_copy, sLearnSongExpectedNote, sizeof(sLearnSongExpectedNote));
memcpy(&info->D_8016BAA0_copy, &D_8016BAA0, sizeof(D_8016BAA0));
info->sAudioHasMalonBgm_copy = sAudioHasMalonBgm;
info->sAudioMalonBgmDist_copy = sAudioMalonBgmDist;
info->sDisplayedNoteValue_copy = sDisplayedNoteValue;
info->sOcarinaNoteBufPos_copy = sOcarinaNoteBufPos;
info->sOcarinaNoteBufLen_copy = sOcarinaNoteBufLen;
memcpy(info->sOcarinaNoteBuf_copy, sOcarinaNoteBuf, sizeof(sOcarinaNoteBuf));
info->D_8014B2F4_copy = D_8014B2F4;
info->sTextboxSkipped_copy = sTextboxSkipped;
info->sNextTextId_copy = sNextTextId;
info->sLastPlayedSong_copy = sLastPlayedSong;
info->sHasSunsSong_copy = sHasSunsSong;
info->sMessageHasSetSfx_copy = sMessageHasSetSfx;
info->sOcarinaSongBitFlags_copy = sOcarinaSongBitFlags;
}
void SaveState::LoadMiscCodeData(void) {
gGameOverTimer = info->gGameOverTimer_copy;
gTimeIncrement = info->gTimeIncrement_copy;
sLoadedMarkDataTable = info->sLoadedMarkDataTableCopy;
sPlayerInitialPosX = info->sPlayerInitialPosX_copy;
sPlayerInitialPosZ = info->sPlayerInitialPosZ_copy;
sPlayerInitialDirection = info->sPlayerInitialDirection_copy;
sOcarinaInpEnabled = info->sOcarinaInpEnabled_copy;
D_80130F10 = info->D_80130F10_copy;
sCurOcarinaBtnVal = info->sCurOcarinaBtnVal_copy;
sPrevOcarinaNoteVal = info->sPrevOcarinaNoteVal_copy;
sCurOcarinaBtnIdx = info->sCurOcarinaBtnIdx_copy;
sLearnSongLastBtn = info->sLearnSongLastBtn_copy;
D_80130F24 = info->D_80130F24_copy;
D_80130F28 = info->D_80130F28_copy;
D_80130F2C = info->D_80130F2C_copy;
D_80130F30 = info->D_80130F30_copy;
D_80130F34 = info->D_80130F34_copy;
sPlaybackState = info->sPlaybackState_copy;
D_80130F3C = info->D_80130F3C_copy;
sNotePlaybackTimer = info->sNotePlaybackTimer_copy;
sPlaybackNotePos = info->sPlaybackNotePos_copy;
sStaffPlaybackPos = info->sStaffPlaybackPos_copy;
sCurOcarinaBtnPress = info->sCurOcarinaBtnPress_copy;
D_8016BA10 = info->D_8016BA10_copy;
sPrevOcarinaBtnPress = info->sPrevOcarinaBtnPress_copy;
D_8016BA18 = info->D_8016BA18_copy;
D_8016BA1C = info->D_8016BA1C_copy;
memcpy(sCurOcarinaSong, info->sCurOcarinaSong_copy, sizeof(sCurOcarinaSong));
sOcarinaSongAppendPos = info->sOcarinaSongAppendPos_copy;
sOcarinaHasStartedSong = info->sOcarinaHasStartedSong_copy;
sOcarinaSongNoteStartIdx = info->sOcarinaSongNoteStartIdx_copy;
sOcarinaSongCnt = info->sOcarinaSongCnt_copy;
sOcarinaAvailSongs = info->sOcarinaAvailSongs_copy;
sStaffPlayingPos = info->sStaffPlayingPos_copy;
memcpy(info->sLearnSongPos_copy, info->sLearnSongPos_copy, sizeof(sLearnSongPos));
memcpy(info->D_8016BA50_copy, info->D_8016BA50_copy, sizeof(D_8016BA50));
memcpy(info->D_8016BA70_copy, info->D_8016BA70_copy, sizeof(D_8016BA70));
memcpy(info->sLearnSongExpectedNote_copy, info->sLearnSongExpectedNote_copy, sizeof(sLearnSongExpectedNote));
memcpy(&D_8016BAA0, &info->D_8016BAA0_copy, sizeof(D_8016BAA0));
sAudioHasMalonBgm = info->sAudioHasMalonBgm_copy;
sAudioMalonBgmDist = info->sAudioMalonBgmDist_copy;
sDisplayedNoteValue = info->sDisplayedNoteValue_copy;
sOcarinaNoteBufPos = info->sOcarinaNoteBufPos_copy;
sOcarinaNoteBufLen = info->sOcarinaNoteBufLen_copy;
memcpy(sOcarinaNoteBuf, info->sOcarinaNoteBuf_copy, sizeof(sOcarinaNoteBuf));
D_8014B2F4 = info->D_8014B2F4_copy;
sTextboxSkipped = info->sTextboxSkipped_copy;
sNextTextId = info->sNextTextId_copy;
sLastPlayedSong = info->sLastPlayedSong_copy;
sHasSunsSong = info->sHasSunsSong_copy;
sMessageHasSetSfx = info->sMessageHasSetSfx_copy;
sOcarinaSongBitFlags = info->sOcarinaSongBitFlags_copy;
}
extern "C" void ProcessSaveStateRequests(void) {
OTRGlobals::Instance->gSaveStateMgr->ProcessSaveStateRequests();
}
void SaveStateMgr::SetCurrentSlot(unsigned int slot) {
SohImGui::overlay->TextDrawNotification(1.0f, true, "slot %u set", slot);
this->currentSlot = slot;
}
unsigned int SaveStateMgr::GetCurrentSlot(void) {
return this->currentSlot;
}
void SaveStateMgr::ProcessSaveStateRequests(void) {
while (!this->requests.empty()) {
const auto& request = this->requests.front();
switch (request.type) {
case RequestType::SAVE:
if (!this->states.contains(request.slot)) {
this->states[request.slot] = std::make_shared<SaveState>(OTRGlobals::Instance->gSaveStateMgr, request.slot);
}
this->states[request.slot]->Save();
SohImGui::overlay->TextDrawNotification(1.0f, true, "saved state %u", request.slot);
break;
case RequestType::LOAD:
if (this->states.contains(request.slot)) {
this->states[request.slot]->Load();
SohImGui::overlay->TextDrawNotification(1.0f, true, "loaded state %u", request.slot);
} else {
SPDLOG_ERROR("Invalid SaveState slot: {}", request.type);
}
break;
[[unlikely]] default:
SPDLOG_ERROR("Invalid SaveState request type: {}", request.type);
break;
}
this->requests.pop();
}
}
SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) {
if (gGlobalCtx == nullptr) {
SPDLOG_ERROR("[SOH] Can not save or load a state outside of \"GamePlay\"");
SohImGui::overlay->TextDrawNotification(1.0f, true, "states not available here", request.slot);
return SaveStateReturn::FAIL_WRONG_GAMESTATE;
}
switch (request.type) {
case RequestType::SAVE:
requests.push(request);
break;
case RequestType::LOAD:
if (states.contains(request.slot)) {
requests.push(request);
} else {
SPDLOG_ERROR("Invalid SaveState slot: {}", request.type);
SohImGui::overlay->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot);
return SaveStateReturn::FAIL_INVALID_SLOT;
}
break;
[[unlikely]] default:
SPDLOG_ERROR("Invalid SaveState request type: {}", request.type);
return SaveStateReturn::FAIL_BAD_REQUEST;
break;
}
}
void SaveState::Save(void) {
std::unique_lock<std::mutex> Lock(audio.mutex);
memcpy(&info->sysHeapCopy, gSystemHeap, SYSTEM_HEAP_SIZE /* sizeof(gSystemHeap) */);
memcpy(&info->audioHeapCopy, gAudioHeap, AUDIO_HEAP_SIZE /* sizeof(gAudioContext) */);
memcpy(&info->audioContextCopy, &gAudioContext, sizeof(AudioContext));
memcpy(&info->unk_D_8016E750Copy, D_8016E750, sizeof(info->unk_D_8016E750Copy));
BackupSeqScriptState();
memcpy(info->gActiveSoundsCopy, gActiveSounds, sizeof(gActiveSounds));
memcpy(&info->gSoundBankMutedCopy, gSoundBankMuted, sizeof(info->gSoundBankMutedCopy));
info->D_801333F0_copy = D_801333F0;
info->gAudioSfxSwapOff_copy = gAudioSfxSwapOff;
memcpy(&info->gAudioSfxSwapSource_copy, gAudioSfxSwapSource,
sizeof(info->gAudioSfxSwapSource_copy));
memcpy(&info->gAudioSfxSwapTarget_copy, gAudioSfxSwapTarget,
sizeof(info->gAudioSfxSwapTarget_copy));
memcpy(&info->gAudioSfxSwapMode_copy, gAudioSfxSwapMode,
sizeof(info->gAudioSfxSwapMode_copy));
info->D_801755D0_copy = D_801755D0;
memcpy(&info->saveContextCopy, &gSaveContext, sizeof(gSaveContext));
memcpy(&info->gameInfoCopy, gGameInfo, sizeof(*gGameInfo));
memcpy(&info->lightBufferCopy, &sLightsBuffer, sizeof(sLightsBuffer));
memcpy(&info->mtxStackCopy, &sMatrixStack, sizeof(MtxF) * 20);
memcpy(&info->currentMtxCopy, &sCurrentMatrix, sizeof(MtxF));
//Various static data
info->blueWarpTimerCopy = sWarpTimerTarget;
BackupCameraData();
SaveOnePointDemoData();
SaveOverlayStaticData();
SaveMiscCodeData();
}
void SaveState::Load(void) {
std::unique_lock<std::mutex> Lock(audio.mutex);
memcpy(gSystemHeap, &info->sysHeapCopy, SYSTEM_HEAP_SIZE);
memcpy(gAudioHeap, &info->audioHeapCopy, AUDIO_HEAP_SIZE);
memcpy(&gAudioContext, &info->audioContextCopy, sizeof(AudioContext));
memcpy(D_8016E750, &info->unk_D_8016E750Copy, sizeof(info->unk_D_8016E750Copy));
LoadSeqScriptState();
memcpy(&gSaveContext, &info->saveContextCopy, sizeof(gSaveContext));
memcpy(gGameInfo, &info->gameInfoCopy, sizeof(*gGameInfo));
memcpy(&sLightsBuffer, &info->lightBufferCopy, sizeof(sLightsBuffer));
memcpy(&sMatrixStack, &info->mtxStackCopy, sizeof(MtxF) * 20);
memcpy(&sCurrentMatrix, &info->currentMtxCopy, sizeof(MtxF));
sWarpTimerTarget = info->blueWarpTimerCopy;
memcpy(gActiveSounds, info->gActiveSoundsCopy, sizeof(gActiveSounds));
memcpy(gSoundBankMuted, &info->gSoundBankMutedCopy, sizeof(info->gSoundBankMutedCopy));
D_801333F0 = info->D_801333F0_copy;
gAudioSfxSwapOff = info->gAudioSfxSwapOff_copy;
memcpy(gAudioSfxSwapSource, &info->gAudioSfxSwapSource_copy,
sizeof(info->gAudioSfxSwapSource_copy));
memcpy(gAudioSfxSwapTarget, &info->gAudioSfxSwapTarget_copy,
sizeof(info->gAudioSfxSwapTarget_copy));
memcpy(gAudioSfxSwapMode, &info->gAudioSfxSwapMode_copy,
sizeof(info->gAudioSfxSwapMode_copy));
//Various static data
D_801755D0 = info->D_801755D0_copy;
LoadCameraData();
LoadOnePointDemoData();
LoadOverlayStaticData();
LoadMiscCodeData();
}

View file

@ -0,0 +1,62 @@
#ifndef SAVE_STATES_H
#define SAVE_STATES_H
#include <cstdint>
#include <queue>
#include <unordered_map>
#include <memory>
#include <mutex>
enum class SaveStateReturn {
SUCCESS,
FAIL_INVALID_SLOT,
FAIL_NO_MEMORY,
FAIL_STATE_EMPTY,
FAIL_WRONG_GAMESTATE,
FAIL_BAD_REQUEST,
};
typedef struct SaveStateHeader {
uint32_t stateMagic;
uint32_t stateVersion;
//uint32_t gameVersion;
} SaveStateHeader;
enum class RequestType {
SAVE,
LOAD,
};
typedef struct SaveStateRequest {
unsigned int slot;
RequestType type;
} SaveStateRequest;
class SaveState;
class SaveStateMgr {
friend class SaveState;
private:
unsigned int currentSlot;
std::unordered_map<unsigned int, std::shared_ptr<SaveState>> states;
std::queue <SaveStateRequest> requests;
std::mutex mutex;
public:
SaveStateReturn AddRequest(const SaveStateRequest request);
SaveStateMgr();
~SaveStateMgr();
void SetCurrentSlot(unsigned int slot);
unsigned int GetCurrentSlot(void);
SaveStateMgr& operator=(const SaveStateMgr& rhs) = delete;
SaveStateMgr(const SaveStateMgr& rhs) = delete;
void ProcessSaveStateRequests(void);
};
extern std::shared_ptr<SaveStateMgr> gSaveStateMgr;
#endif

View file

@ -0,0 +1,257 @@
extern "C" MtxF* sMatrixStack;
extern "C" MtxF* sCurrentMatrix;
extern "C" LightsBuffer sLightsBuffer;
extern "C" s16 sWarpTimerTarget;
extern "C" MapMarkData** sLoadedMarkDataTable;
//Camera static data
extern "C" int32_t sInitRegs;
extern "C" int32_t gDbgCamEnabled;
extern "C" int32_t sDbgModeIdx;
extern "C" int16_t sNextUID;
extern "C" int32_t sCameraInterfaceFlags;
extern "C" int32_t sCameraInterfaceAlpha;
extern "C" int32_t sCameraShrinkWindowVal;
extern "C" int32_t D_8011D3AC;
extern "C" int32_t sDemo5PrevAction12Frame;
extern "C" int32_t sDemo5PrevSfxFrame;
extern "C" int32_t D_8011D3F0;
extern "C" OnePointCsFull D_8011D6AC[];
extern "C" OnePointCsFull D_8011D724[];
extern "C" OnePointCsFull D_8011D79C[];
extern "C" OnePointCsFull D_8011D83C[];
extern "C" OnePointCsFull D_8011D88C[];
extern "C" OnePointCsFull D_8011D8DC[];
extern "C" OnePointCsFull D_8011D954[];
extern "C" OnePointCsFull D_8011D9F4[];
extern "C" int16_t D_8011DB08;
extern "C" int16_t D_8011DB0C;
extern "C" int32_t sOOBTimer;
extern "C" f32 D_8015CE50;
extern "C" f32 D_8015CE54;
extern "C" CamColChk D_8015CE58;
//Gameover
extern "C" uint16_t gGameOverTimer;
//One Point Demo
extern "C" uint32_t sPrevFrameCs1100;
extern "C" CutsceneCameraPoint D_8012013C[14];
extern "C" CutsceneCameraPoint D_8012021C[14];
extern "C" CutsceneCameraPoint D_801204D4[14];
extern "C" CutsceneCameraPoint D_801205B4[14];
extern "C" OnePointCsFull D_801208EC[3];
extern "C" OnePointCsFull D_80120964[2];
extern "C" OnePointCsFull D_801209B4[4];
extern "C" OnePointCsFull D_80120ACC[5];
extern "C" OnePointCsFull D_80120B94[11];
extern "C" OnePointCsFull D_80120D4C[7];
extern "C" OnePointCsFull D_80120FA4[6];
extern "C" OnePointCsFull D_80121184[2];
extern "C" OnePointCsFull D_801211D4[2];
extern "C" OnePointCsFull D_8012133C[3];
extern "C" OnePointCsFull D_801213B4[5];
extern "C" OnePointCsFull D_8012151C[2];
extern "C" OnePointCsFull D_8012156C[2];
extern "C" OnePointCsFull D_801215BC[1];
extern "C" OnePointCsFull D_80121C24[7];
extern "C" OnePointCsFull D_80121D3C[3];
extern "C" OnePointCsFull D_80121F1C[4];
extern "C" OnePointCsFull D_80121FBC[4];
extern "C" OnePointCsFull D_801220D4[5];
extern "C" OnePointCsFull D_80122714[4];
extern "C" OnePointCsFull D_80122CB4[2];
extern "C" OnePointCsFull D_80122D04[2];
extern "C" OnePointCsFull D_80122E44[2][7];
extern "C" OnePointCsFull D_8012313C[3];
extern "C" OnePointCsFull D_801231B4[4];
extern "C" OnePointCsFull D_80123254[2];
extern "C" OnePointCsFull D_801232A4[1];
extern "C" OnePointCsFull D_80123894[3];
extern "C" OnePointCsFull D_8012390C[2];
extern "C" OnePointCsFull D_8012395C[3];
extern "C" OnePointCsFull D_801239D4[3];
// z_bg_ddan_kd
extern "C" Vec3f sBgDdanKdVelocity;
extern "C" Vec3f sBgDdanKdAccel;
// z_bg_dodoago
extern "C" s16 sBgDodoagoFirstExplosiveFlag;
extern "C" u8 sBgDodoagoDisableBombCatcher;
extern "C" s32 sBgDodoagoTimer;
// z_bg_haka_trap
extern "C" uint32_t D_80880F30;
extern "C" uint32_t D_80881014;
// z_bg_hidan_rock
extern "C" float D_8088BFC0;
// z_bg_menkuri_eye
extern "C" int32_t D_8089C1A0;
// z_bg_mori_hineri
extern "C" int16_t sBgMoriHineriNextCamIdx;
// z_bg_po_event
extern "C" uint8_t sBgPoEventBlocksAtRest;
extern "C" uint8_t sBgPoEventPuzzleState;
extern "C" float sBgPoEventblockPushDist;
// z_bg_relay_objects
extern "C" uint32_t D_808A9508;
// z_bg_spot18_basket
extern "C" int16_t D_808B85D0;
// z_boss_ganon
extern "C" uint32_t sBossGanonSeed1;
extern "C" uint32_t sBossGanonSeed2;
extern "C" uint32_t sBossGanonSeed3;
extern "C" void* sBossGanonGanondorf;
extern "C" void* sBossGanonZelda;
extern "C" void* sBossGanonCape;
extern "C" GanondorfEffect sBossGanonEffectBuf[200];
// z_boss_ganon2
extern "C" Vec3f D_8090EB20;
extern "C" int8_t D_80910638;
extern "C" void* sBossGanon2Zelda;
extern "C" void* D_8090EB30;
extern "C" int32_t sBossGanon2Seed1;
extern "C" int32_t sBossGanon2Seed2;
extern "C" int32_t sBossGanon2Seed3;
extern "C" Vec3f D_809105D8[4];
extern "C" Vec3f D_80910608[4];
extern "C" BossGanon2Effect sBossGanon2Particles[100];
// z_boss_tw
extern "C" uint8_t sTwInitalized;
extern "C" BossTwEffect sTwEffects[150];
// z_demo_6k
extern "C" Vec3f sDemo6kVelocity;
// z_demo_du
extern "C" int32_t D_8096CE94;
// z_demo_kekkai
extern "C" Vec3f demoKekkaiVel;
// z_en_bw
extern "C" int32_t sSlugGroup;
// z_en_clear_tag
extern "C" uint8_t sClearTagIsEffectsInitialized;
extern "C" EnClearTagEffect sClearTagEffects[CLEAR_TAG_EFFECT_MAX_COUNT];
// z_en_fr
extern "C" EnFrPointers sEnFrPointers;
// z_en_goma
extern "C" uint8_t sSpawnNum;
// z_en_in
extern "C" int32_t D_80A7B998;
// z_en_insect
extern "C" float D_80A7DEB0;
extern "C" int16_t D_80A7DEB4;
extern "C" int16_t D_80A7DEB8;
// z_en_ishi
extern "C" int16_t sRockRotSpeedX;
extern "C" int16_t sRockRotSpeedY;
// z_en_niw
extern "C" int16_t D_80AB85E0;
extern "C" uint8_t sLowerRiverSpawned;
extern "C" uint8_t sUpperRiverSpawned;
// z_en_po_field
extern "C" int32_t sEnPoFieldNumSpawned;
extern "C" Vec3s sEnPoFieldSpawnPositions[10];
extern "C" u8 sEnPoFieldSpawnSwitchFlags[10];
// z_en_takara_man
extern "C" uint8_t sTakaraIsInitialized;
// z_en_xc
extern "C" int32_t D_80B41D90;
extern "C" int32_t sEnXcFlameSpawned;
extern "C" int32_t D_80B41DA8;
extern "C" int32_t D_80B41DAC;
// z_en_zf
extern "C" int16_t D_80B4A1B0;
extern "C" int16_t D_80B4A1B4;
extern "C" int32_t D_80B5A468;
extern "C" int32_t D_80B5A494;
extern "C" int32_t D_80B5A4BC;
extern "C" uint8_t sKankyoIsSpawned;
extern "C" int16_t sTrailingFairies;
extern "C" uint16_t gTimeIncrement;
extern "C" s16 sPlayerInitialPosX;
extern "C" s16 sPlayerInitialPosZ;
extern "C" s16 sPlayerInitialDirection;
// code_800EC960
// Related to ocarina
extern "C" u8 sOcarinaInpEnabled;
extern "C" s8 D_80130F10;
extern "C" u8 sCurOcarinaBtnVal;
extern "C" u8 sPrevOcarinaNoteVal;
extern "C" u8 sCurOcarinaBtnIdx;
extern "C" u8 sLearnSongLastBtn;
extern "C" f32 D_80130F24;
extern "C" f32 D_80130F28;
extern "C" s8 D_80130F2C;
extern "C" s8 D_80130F30;
extern "C" s8 D_80130F34;
extern "C" u8 sPlaybackState;
extern "C" u32 D_80130F3C;
extern "C" u32 sNotePlaybackTimer;
extern "C" u16 sPlaybackNotePos;
extern "C" u16 sStaffPlaybackPos;
//IDK what this is but it looks important
extern "C" u32 sCurOcarinaBtnPress;
extern "C" u32 D_8016BA10;
extern "C" u32 sPrevOcarinaBtnPress;
extern "C" s32 D_8016BA18;
extern "C" s32 D_8016BA1C;
extern "C" u8 sCurOcarinaSong[8];
extern "C" u8 sOcarinaSongAppendPos;
extern "C" u8 sOcarinaHasStartedSong;
extern "C" u8 sOcarinaSongNoteStartIdx;
extern "C" u8 sOcarinaSongCnt;
extern "C" u16 sOcarinaAvailSongs;
extern "C" u8 sStaffPlayingPos;
extern "C" u16 sLearnSongPos[0x10];
extern "C" u16 D_8016BA50[0x10];
extern "C" u16 D_8016BA70[0x10];
extern "C" u8 sLearnSongExpectedNote[0x10];
extern "C" OcarinaNote D_8016BAA0;
extern "C" u8 sAudioHasMalonBgm;
extern "C" f32 sAudioMalonBgmDist;
extern "C" u8 sDisplayedNoteValue;
// z_message_PAL
extern "C" s16 sOcarinaNoteBufPos;
extern "C" s16 sOcarinaNoteBufLen;
extern "C" u8 sOcarinaNoteBuf[12];
extern "C" u8 D_8014B2F4;
extern "C" u8 sTextboxSkipped;
extern "C" u16 sNextTextId;
extern "C" s16 sLastPlayedSong;
extern "C" s16 sHasSunsSong;
extern "C" s16 sMessageHasSetSfx;
extern "C" u16 sOcarinaSongBitFlags;

8
soh/soh/OTRAudio.h Normal file
View file

@ -0,0 +1,8 @@
#pragma once
static struct {
std::condition_variable cv_to_thread, cv_from_thread;
std::mutex mutex;
bool initialized;
bool processing;
} audio;

View file

@ -1,4 +1,5 @@
#include "OTRGlobals.h"
#include "OTRAudio.h"
#include <iostream>
#include <locale>
#include <codecvt>
@ -28,22 +29,20 @@
#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"
#include <Utils/StringHelper.h>
#include <SDL2/SDL_scancode.h>
OTRGlobals* OTRGlobals::Instance;
static struct {
std::condition_variable cv_to_thread, cv_from_thread;
std::mutex mutex;
bool initialized;
bool processing;
} audio;
OTRGlobals::OTRGlobals() {
context = Ship::GlobalCtx2::CreateInstance("Ship of Harkinian");
gSaveStateMgr = std::make_shared<SaveStateMgr>();
context->GetWindow()->Init();
}
@ -114,12 +113,69 @@ extern "C" void Graph_ProcessFrame(void (*run_one_game_iter)(void)) {
}
extern "C" void Graph_StartFrame() {
// Why -1?
int32_t dwScancode = OTRGlobals::Instance->context->GetWindow()->lastScancode;
OTRGlobals::Instance->context->GetWindow()->lastScancode = -1;
switch (dwScancode - 1) {
case SDL_SCANCODE_F5: {
const unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn stateReturn =
OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::SAVE });
switch (stateReturn) {
case SaveStateReturn::SUCCESS:
SPDLOG_INFO("[SOH] Saved state to slot {}", slot);
break;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
SPDLOG_ERROR("[SOH] Can not save a state outside of \"GamePlay\"");
break;
[[unlikely]] default:
break;
}
break;
}
case SDL_SCANCODE_F6: {
unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
slot++;
if (slot > 5) {
slot = 0;
}
OTRGlobals::Instance->gSaveStateMgr->SetCurrentSlot(slot);
SPDLOG_INFO("Set SaveState slot to {}.", slot);
break;
}
case SDL_SCANCODE_F7: {
const unsigned int slot = OTRGlobals::Instance->gSaveStateMgr->GetCurrentSlot();
const SaveStateReturn stateReturn =
OTRGlobals::Instance->gSaveStateMgr->AddRequest({ slot, RequestType::LOAD });
switch (stateReturn) {
case SaveStateReturn::SUCCESS:
SPDLOG_INFO("[SOH] Loaded state from slot {}", slot);
break;
case SaveStateReturn::FAIL_INVALID_SLOT:
SPDLOG_ERROR("[SOH] Invalid State Slot Number {}", slot);
break;
case SaveStateReturn::FAIL_STATE_EMPTY:
SPDLOG_ERROR("[SOH] State Slot {} is empty", slot);
break;
case SaveStateReturn::FAIL_WRONG_GAMESTATE:
SPDLOG_ERROR("[SOH] Can not load a state outside of \"GamePlay\"");
break;
[[unlikely]] default:
break;
}
break;
}
}
OTRGlobals::Instance->context->GetWindow()->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;
@ -131,6 +187,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
audio.cv_to_thread.wait(Lock);
}
}
std::unique_lock<std::mutex> Lock(audio.mutex);
//AudioMgr_ThreadEntry(&gAudioMgr);
// 528 and 544 relate to 60 fps at 32 kHz 32000/60 = 533.333..
// in an ideal world, one third of the calls should use num_samples=544 and two thirds num_samples=528
@ -156,10 +213,7 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
// printf("Audio samples before submitting: %d\n", audio_api->buffered());
AudioPlayer_Play((u8*)audio_buffer, num_audio_samples * (sizeof(int16_t) * NUM_AUDIO_CHANNELS * AUDIO_FRAMES_PER_UPDATE));
{
std::unique_lock<std::mutex> Lock(audio.mutex);
audio.processing = false;
}
audio.processing = false;
audio.cv_from_thread.notify_one();
}
}).detach();
@ -171,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

@ -1,17 +1,22 @@
#ifndef OTR_GLOBALS_H
#define OTR_GLOBALS_H
#pragma once
#include "GlobalCtx2.h"
#ifdef __cplusplus
#include "Enhancements/savestates.h"
class OTRGlobals
{
public:
static OTRGlobals* Instance;
static OTRGlobals* Instance;
std::shared_ptr<Ship::GlobalCtx2> context;
std::shared_ptr<Ship::GlobalCtx2> context;
std::shared_ptr<SaveStateMgr> gSaveStateMgr;
OTRGlobals();
~OTRGlobals();
OTRGlobals();
~OTRGlobals();
private:
@ -68,3 +73,5 @@ void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
int Controller_ShouldRumble(size_t i);
#endif
#endif

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

@ -6,9 +6,6 @@
#include <unistd.h>
#endif
#define AUDIO_HEAP_SIZE 0x38000
#define SYSTEM_HEAP_SIZE (1024 * 1024 * 128)
u8* gAudioHeap;
u8* gSystemHeap;

View file

@ -431,6 +431,8 @@ static struct RunFrameContext {
extern AudioMgr gAudioMgr;
extern void ProcessSaveStateRequests(void);
static void RunFrame()
{
u32 size;
@ -487,6 +489,7 @@ static void RunFrame()
//uint64_t diff = (ticksB - ticksA) / (freq / 1000);
//printf("Frame simulated in %ims\n", diff);
runFrameContext.state = 1;
ProcessSaveStateRequests();
return;
nextFrame:;
}

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);
@ -565,10 +567,10 @@ s16 Camera_XZAngle(Vec3f* to, Vec3f* from) {
return DEGF_TO_BINANG(RADF_TO_DEGF(Math_FAtan2F(from->x - to->x, from->z - to->z)));
}
f32 D_8015CE50;
f32 D_8015CE54;
CamColChk D_8015CE58;
s16 func_80044ADC(Camera* camera, s16 yaw, s16 arg2) {
static f32 D_8015CE50;
static f32 D_8015CE54;
static CamColChk D_8015CE58;
Vec3f playerPos;
Vec3f rotatedPos;
Vec3f floorNorm;
@ -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);
@ -7221,9 +7224,9 @@ s32 Camera_DbgChangeMode(Camera* camera) {
return true;
}
s16 D_8011DB08 = 0x3F0;
s16 D_8011DB0C = 0x156;
void func_80058E8C(Camera* camera) {
static s16 D_8011DB08 = 0x3F0;
static s16 D_8011DB0C = 0x156;
s32 pad3;
f32 sp60;
s32 pad;
@ -7299,8 +7302,8 @@ void func_80058E8C(Camera* camera) {
}
}
s32 sOOBTimer = 0;
Vec3s Camera_Update(Camera* camera) {
static s32 sOOBTimer = 0;
Vec3f viewAt;
Vec3f viewEye;
Vec3f viewUp;
@ -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

@ -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

@ -52,7 +52,7 @@ static MapMarkDataOverlay sMapMarkDataOvl = {
gMapMarkDataTable,
};
static MapMarkData** sLoadedMarkDataTable;
MapMarkData** sLoadedMarkDataTable;
void MapMark_Init(GlobalContext* globalCtx) {
MapMarkDataOverlay* overlay = &sMapMarkDataOvl;

View file

@ -4,9 +4,9 @@
static s16 sDisableAttention = false;
static s16 sUnused = -1;
static s32 sPrevFrameCs1100 = -4096;
s32 sPrevFrameCs1100 = -4096;
#include "z_onepointdemo_data.c"
#include "z_onepointdemo_data.inc"
void OnePointCutscene_AddVecSphToVec3f(Vec3f* dst, Vec3f* src, VecSph* vecSph) {
Vec3f out;

View file

@ -1,6 +1,6 @@
#include "global.h"
static CutsceneCameraPoint D_8012013C[14] = {
CutsceneCameraPoint D_8012013C[14] = {
{ CS_CMD_CONTINUE, 25, 40, 70.79991f, { -1814, 533, -1297 } },
{ CS_CMD_CONTINUE, 20, 40, 70.99991f, { -1805, 434, -1293 } },
{ CS_CMD_CONTINUE, 10, 30, 60.0f, { -1794, 323, -1280 } },
@ -16,7 +16,7 @@ static CutsceneCameraPoint D_8012013C[14] = {
{ CS_CMD_STOP, 0, 50, 60.0f, { -1974, 12, -1179 } },
{ CS_CMD_STOP, 0, 30, 60.0f, { -1974, 12, -1179 } },
};
static CutsceneCameraPoint D_8012021C[14] = {
CutsceneCameraPoint D_8012021C[14] = {
{ CS_CMD_CONTINUE, 0, 0, 60.0f, { -1751, 604, -1233 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { -1752, 516, -1233 } },
{ CS_CMD_CONTINUE, 0, 0, 60.0f, { -1751, 417, -1233 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { -1767, 306, -1219 } },
{ CS_CMD_CONTINUE, 0, 0, 60.0f, { -1776, 257, -1205 } }, { CS_CMD_CONTINUE, 0, 0, 60.0f, { -1881, 147, -1149 } },
@ -54,7 +54,7 @@ static CutsceneCameraPoint D_80120434[10] = {
{ CS_CMD_STOP, 0, 0, 60.0f, { 0, 62, -119 } }, { CS_CMD_STOP, 0, 0, 60.0f, { 0, 62, -119 } },
};
static CutsceneCameraPoint D_801204D4[14] = {
CutsceneCameraPoint D_801204D4[14] = {
{ CS_CMD_CONTINUE, -15, 40, 80.600006f, { -60, 332, 183 } },
{ CS_CMD_CONTINUE, -22, 30, 80.600006f, { -60, 332, 183 } },
{ CS_CMD_CONTINUE, -20, 38, 80.600006f, { -118, 344, 41 } },
@ -70,7 +70,7 @@ static CutsceneCameraPoint D_801204D4[14] = {
{ CS_CMD_STOP, 6, 30, 85.199936f, { 25, 127, -950 } },
{ CS_CMD_STOP, 0, 30, 85.199936f, { 25, 127, -950 } },
};
static CutsceneCameraPoint D_801205B4[14] = {
CutsceneCameraPoint D_801205B4[14] = {
{ CS_CMD_CONTINUE, 0, 0, 60.0f, { -225, 785, -242 } },
{ CS_CMD_CONTINUE, -21, 0, 80.600006f, { -245, 784, -242 } },
{ CS_CMD_CONTINUE, -21, 0, 80.600006f, { -288, 485, -379 } },
@ -118,18 +118,18 @@ static s16 D_801208E0 = 12;
static s16 D_801208E4 = 90;
static s16 D_801208E8 = 8;
static OnePointCsFull D_801208EC[3] = {
OnePointCsFull D_801208EC[3] = {
{ 0x0F, 0x08, 0x0101, 1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x81, 0xFF, 0x0101, 1, 0, 60.0f, 1.0f, { 0.0f, -10.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80120964[2] = {
OnePointCsFull D_80120964[2] = {
{ 0x8F, 0xFF, 0x0101, 1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x81, 0xFF, 0xA121, 1, 0, 75.0f, 0.6f, { 0.0f, -10.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
};
static OnePointCsFull D_801209B4[4] = {
OnePointCsFull D_801209B4[4] = {
{ 0x8F, 0x08, 0x0101, 1, 0, 60.0f, 0.9f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x84, 0x01, 0x0100, 29, 0, 45.0f, 0.1f, { 0.0f, -10.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
{ 0x83, 0xFF, 0x0000, 10, 0, 60.0f, 0.2f, { 0.0f, -10.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
@ -142,7 +142,7 @@ static OnePointCsFull D_80120A54[3] = {
{ 0x8B, 0xFF, 0x0022, 5000, 0, 75.0f, 0.005f, { 0.0f, 0.0f, -10.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80120ACC[5] = {
OnePointCsFull D_80120ACC[5] = {
{ 0x8F, 0xFF, 0x0442, 10, 0, 40.0f, 1.0f, { -10.0f, 45.0f, 20.0f }, { 20.0f, 30.0f, 160.0f } },
{ 0x95, 0xFF, 0x0000, 1, 0, 40.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
{ 0x8F, 0x01, 0x0442, 10, 0, 40.0f, 1.0f, { -10.0f, 45.0f, 20.0f }, { 20.0f, 30.0f, 160.0f } },
@ -150,7 +150,7 @@ static OnePointCsFull D_80120ACC[5] = {
{ 0x11, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80120B94[11] = {
OnePointCsFull D_80120B94[11] = {
{ 0x8F, 0x01, 0x2142, 1, 0, 40.0f, 1.0f, { 20.0f, 40.0f, 20.0f }, { -20.0f, 0.0f, -30.0f } },
{ 0x84, 0xFF, 0x0404, 19, 5, 70.0f, 0.01f, { 0.0f, 30.0f, 20.0f }, { 120.0f, 60.0f, 120.0f } },
{ 0x84, 0xFF, 0x0404, 20, 0, 60.0f, 0.01f, { 0.0f, 20.0f, 20.0f }, { 120.0f, 60.0f, 120.0f } },
@ -164,7 +164,7 @@ static OnePointCsFull D_80120B94[11] = {
{ 0x98, 0xFF, 0x0000, 1, 0, 50.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80120D4C[7] = {
OnePointCsFull D_80120D4C[7] = {
{ 0x8F, 0x01, 0x2142, 1, 0, 40.0f, 1.0f, { 20.0f, 40.0f, 20.0f }, { -20.0f, 0.0f, -30.0f } },
{ 0x84, 0xFF, 0x0404, 19, 5, 70.0f, 0.01f, { 0.0f, 30.0f, 20.0f }, { 120.0f, 60.0f, 120.0f } },
{ 0x84, 0xFF, 0x0404, 20, 0, 60.0f, 0.01f, { 0.0f, 20.0f, 20.0f }, { 120.0f, 60.0f, 120.0f } },
@ -185,7 +185,7 @@ static OnePointCsFull D_80120E64[8] = {
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80120FA4[6] = {
OnePointCsFull D_80120FA4[6] = {
{ 0x8F, 0x01, 0x2143, 30, 0, 70.0f, 0.4f, { 0.0f, 40.0f, 50.0f }, { 30.0f, 10.0f, -50.0f } },
{ 0x95, 0xFF, 0x0000, 1, 0, 50.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
{ 0x8F, 0xFF, 0x2222, 10, 0, 42.0f, 1.0f, { 0.0f, 40.0f, 0.0f }, { 0.0f, 85.0f, 45.0f } },
@ -206,12 +206,12 @@ static OnePointCsFull D_8012110C[3] = {
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80121184[2] = {
OnePointCsFull D_80121184[2] = {
{ 0x83, 0x01, 0x0101, 40, 0, -1.0f, 0.1f, { 0.0f, 10.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_801211D4[2] = {
OnePointCsFull D_801211D4[2] = {
{ 0x8F, 0x08, 0x0101, 50, 0, 60.0f, 1.0f, { 0.0f, 10.0f, 0.0f }, { -10.0f, 85.0f, 0.0f } },
{ 0x11, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
@ -229,13 +229,13 @@ static OnePointCsFull D_80121314[1] = {
{ 0x8F, 0x08, 0x4141, 1000, 0, 75.0f, 0.6f, { 0.0f, 0.0f, 10.0f }, { 0.0f, 0.0f, 100.0f } },
};
static OnePointCsFull D_8012133C[3] = {
OnePointCsFull D_8012133C[3] = {
{ 0x8F, 0x01, 0x0141, 40, 0, 75.0f, 1.0f, { 0.0f, 60.0f, 0.0f }, { 0.0f, 0.0f, 100.0f } },
{ 0x83, 0xFF, 0x2121, 20, 0, 60.0f, 0.2f, { 0.0f, -10.0f, -10.0f }, { 0.0f, 10.0f, -100.0f } },
{ 0x11, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_801213B4[5] = {
OnePointCsFull D_801213B4[5] = {
{ 0x8F, 0x08, 0xC2C2, 40, 0, 70.0f, 1.0f, { 80.0f, 0.0f, 20.0f }, { 20.0f, 0.0f, 80.0f } },
{ 0x8B, 0x01, 0xC2C2, 120, 0, 70.0f, 0.1f, { 80.0f, 0.0f, 20.0f }, { 20.0f, 0.0f, 80.0f } },
{ 0x8F, 0x53, 0xC2C2, 30, 0, 50.0f, 1.0f, { 60.0f, 0.0f, 20.0f }, { 60.0f, 0.0f, 60.0f } },
@ -250,17 +250,17 @@ static OnePointCsFull D_8012147C[4] = {
{ 0x11, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_8012151C[2] = {
OnePointCsFull D_8012151C[2] = {
{ 0x0F, 0x01, 0x0101, 29, 0, 60.0f, 1.0f, { -700.0f, 875.0f, -100.0f }, { -550.0f, 920.0f, -150.0f } },
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_8012156C[2] = {
OnePointCsFull D_8012156C[2] = {
{ 0x8F, 0x4D, 0x4242, 1, 0, 65.0f, 1.0f, { 60.0f, 30.0f, 0.0f }, { 50.0f, 20.0f, 150.0f } },
{ 0x81, 0xFF, 0x4242, -1, 0, 65.0f, 1.0f, { -50.0f, 60.0f, 0.0f }, { -60.0f, 40.0f, 150.0f } },
};
static OnePointCsFull D_801215BC[1] = {
OnePointCsFull D_801215BC[1] = {
{ 0x0F, 0xFF, 0x0101, 5, 0, 65.0f, 1.0f, { -1185.0f, 655.0f, 1185.0f }, { -1255.0f, 735.0f, 1255.0f } },
};
@ -331,7 +331,7 @@ static OnePointCsFull D_80121A44[12] = {
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80121C24[7] = {
OnePointCsFull D_80121C24[7] = {
{ 0x0F, 0x05, 0x0101, 1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x03, 0xFF, 0x0101, 89, 0, 50.0f, 0.4f, { 125.0f, 320.0f, -1500.0f }, { 125.0f, 500.0f, -1150.0f } },
{ 0x0F, 0x08, 0x0101, 40, 4, 55.0f, 1.0f, { 0.0f, 375.0f, -1440.0f }, { 5.0f, 365.0f, -1315.0f } },
@ -341,7 +341,7 @@ static OnePointCsFull D_80121C24[7] = {
{ 0x11, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80121D3C[3] = {
OnePointCsFull D_80121D3C[3] = {
{ 0x0F, 0xFF, 0x0101, 1, 0, 60.0f, 1.0f, { 1023.0f, 738.0f, -2628.0f }, { 993.0f, 770.0f, -2740.0f } },
{ 0x02, 0xFF, 0x0101, 4, 0, 50.0f, 1.0f, { 1255.0f, 350.0f, -1870.0f }, { 1240.0f, 575.0f, -2100.0f } },
{ 0x0F, 0xFF, 0x0000, -1, 0, 75.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
@ -359,14 +359,14 @@ static OnePointCsFull D_80121DB4[9] = {
{ 0x12, 0xFF, 0x0000, 1, -1, -1.0f, -1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80121F1C[4] = {
OnePointCsFull D_80121F1C[4] = {
{ 0x0F, 0x08, 0x0101, 10, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x01, 0xFF, 0x2121, 10, 0, 50.0f, 0.5f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
{ 0x01, 0x02, 0x2121, 23, 0, 50.0f, 0.5f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 150.0f } },
{ 0x11, 0xFF, 0x0000, 1, -1, -1.0f, -1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80121FBC[4] = {
OnePointCsFull D_80121FBC[4] = {
{ 0x0F, 0xFF, 0x0101, 5, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x01, 0xFF, 0x0101, 10, 0, 30.0f, 1.0f, { -2130.0f, 2885.0f, -1055.0f }, { -2085.0f, 2875.0f, -1145.0f } },
{ 0x0F, 0xFF, 0x0000, 30, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
@ -379,7 +379,7 @@ static OnePointCsFull D_8012205C[3] = {
{ 0x01, 0x01, 0x21A1, 10, 0, 60.0f, 1.0f, { 0.0f, -10.0f, 0.0f }, { 0.0f, 10.0f, -200.0f } },
};
static OnePointCsFull D_801220D4[5] = {
OnePointCsFull D_801220D4[5] = {
{ 0x0F, 0x01, 0x0101, 5, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x01, 0xFF, 0x4141, 10, 5, 55.0f, 0.75f, { 400.0f, -50.0f, 800.0f }, { 600.0f, -60.0f, 800.0f } },
{ 0x01, 0xFF, 0x4141, 15, 10, 40.0f, 0.75f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 10.0f, 200.0f } },
@ -443,7 +443,7 @@ static OnePointCsFull D_8012269C[3] = {
{ 0x11, 0xFF, 0x0000, 1, -1, -1.0f, -1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80122714[4] = {
OnePointCsFull D_80122714[4] = {
{ 0x0F, 0xFF, 0x0101, 20, 0, 45.0f, 1.0f, { -915.0f, -2185.0f, 6335.0f }, { -915.0f, -2290.0f, 6165.0f } },
{ 0x02, 0xFF, 0x0101, -1, 0, 80.0f, 0.8f, { -920.0f, -2270.0f, 6140.0f }, { -920.0f, -2280.0f, 6070.0f } },
{ 0x02, 0xFF, 0x0101, 20, 0, 80.0f, 0.9f, { -920.0f, -2300.0f, 6140.0f }, { -920.0f, -2300.0f, 6070.0f } },
@ -512,12 +512,12 @@ static OnePointCsFull D_80122C8C[1] = {
{ 0x0F, 0xFF, 0x0101, 999, 5, 60.0f, 1.0f, { -70.0f, 140.0f, 25.0f }, { 10.0f, 180.0f, 195.0f } },
};
static OnePointCsFull D_80122CB4[2] = {
OnePointCsFull D_80122CB4[2] = {
{ 0x0F, 0xFF, 0x4242, 5, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 1000.0f }, { 0.0f, 0.0f, 1100.0f } },
{ 0x02, 0xFF, 0x4242, -1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, -100.0f }, { 0.0f, 0.0f, 0.0f } },
};
static OnePointCsFull D_80122D04[2] = {
OnePointCsFull D_80122D04[2] = {
{ 0x0F, 0xFF, 0x4242, 10, 0, 60.0f, 1.0f, { 0.0f, 0.0f, -100.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x02, 0xFF, 0x4242, -1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 1000.0f }, { 0.0f, 0.0f, 1100.0f } },
};
@ -534,7 +534,7 @@ static OnePointCsFull D_80122DCC[3] = {
{ 0x11, 0xFF, 0x0000, 1, -1, -1.0f, -1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80122E44[2][7] = {
OnePointCsFull D_80122E44[2][7] = {
{
{ 0x83, 0xFF, 0x2222, 10, 5, 90.0f, 0.2f, { 50.0f, 100.0f, 140.0f }, { -30.0f, 10.0f, -20.0f } },
{ 0x8F, 0xFF, 0x0000, 20, 0, 90.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
@ -563,25 +563,25 @@ static OnePointCsFull D_80123074[5] = {
{ 0x92, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_8012313C[3] = {
OnePointCsFull D_8012313C[3] = {
{ 0x8F, 0xFF, 0xA2A2, 20, 8, 70.0f, 1.0f, { 65.0f, -150.0f, 50.0f }, { 30.0f, 10.0f, 90.0f } },
{ 0x81, 0xFF, 0xA2A2, 100, 0, 60.0f, 1.0f, { 70.0f, -160.0f, 50.0f }, { 25.0f, 180.0f, 180.0f } },
{ 0x92, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_801231B4[4] = {
OnePointCsFull D_801231B4[4] = {
{ 0x8F, 0xC5, 0x4343, 1, 0, 50.0f, 1.0f, { 0.0f, 20.0f, 0.0f }, { 0.0f, 5.0f, -1.0f } },
{ 0x81, 0xC5, 0x4343, 48, 0, 50.0f, 0.75f, { 0.0f, 80.0f, 0.0f }, { 0.0f, 15.0f, -1.0f } },
{ 0x8F, 0xC5, 0x4343, 1, 5, 45.0f, 1.0f, { 0.0f, 0.0f, 30.0f }, { 30.0f, 120.0f, 60.0f } },
{ 0x81, 0xC5, 0x4343, -1, 0, -1.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80123254[2] = {
OnePointCsFull D_80123254[2] = {
{ 0x0F, 0xFF, 0x0101, 1, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x03, 0xC5, 0x0101, 49, 0, 50.0f, 0.05f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
};
static OnePointCsFull D_801232A4[1] = {
OnePointCsFull D_801232A4[1] = {
{ 0x0F, 0x45, 0x0101, 9999, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
};
@ -646,24 +646,24 @@ static OnePointCsFull D_801237CC[5] = {
{ 0x0F, 0xFF, 0x0000, 100, -45, 75.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },
};
static OnePointCsFull D_80123894[3] = {
OnePointCsFull D_80123894[3] = {
{ 0x0F, 0xFF, 0x0101, 60, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x0F, 0xFF, 0x4242, 30, 0, 50.0f, 1.0f, { 0.0f, 28.0f, 0.0f }, { 0.0f, 20.0f, 40.0f } },
{ 0x0D, 0xFF, 0x0000, 120, 0, 180.0f, 0.4f, { 0.0f, -5.0f, 0.0f }, { 0.0f, 2.0f, 40.0f } },
};
static OnePointCsFull D_8012390C[2] = {
OnePointCsFull D_8012390C[2] = {
{ 0x0F, 0xFF, 0x0101, 30, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x0F, 0xFF, 0x4242, 180, 0, 60.0f, 1.0f, { 0.0f, 78.0f, 0.0f }, { 0.0f, 78.0f, 200.0f } },
};
static OnePointCsFull D_8012395C[3] = {
OnePointCsFull D_8012395C[3] = {
{ 0x0F, 0xFF, 0x0101, 60, 0, 60.0f, 1.0f, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x0F, 0xFF, 0x4242, 30, 0, 50.0f, 1.0f, { 0.0f, 28.0f, 0.0f }, { 0.0f, 20.0f, -45.0f } },
{ 0x0D, 0xFF, 0x0000, 120, 0, 180.0f, 0.4f, { 0.0f, -5.0f, 0.0f }, { 0.0f, 2.0f, 45.0f } },
};
static OnePointCsFull D_801239D4[3] = {
OnePointCsFull D_801239D4[3] = {
{ 0x0F, 0xFF, 0x4242, 5, 0, 60.0f, 1.0f, { 0.0f, 20.0f, 0.0f }, { 0.0f, 40.0f, -120.0f } },
{ 0x09, 0xFF, 0x4242, 0, 0, 60.0f, 1.0f, { 0.0f, 20.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } },
{ 0x12, 0xFF, 0x0000, 1, 0, 60.0f, 1.0f, { -1.0f, -1.0f, -1.0f }, { -1.0f, -1.0f, -1.0f } },

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;
@ -421,7 +423,7 @@ void Gameplay_Update(GlobalContext* globalCtx) {
input = globalCtx->state.input;
if ((SREG(1) < 0) || (DREG(0) != 0)) {
if ((SREG(1) < 0) || (DREG(0) != 0)) {
SREG(1) = 0;
ZeldaArena_Display();
}
@ -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

@ -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

@ -121,8 +121,8 @@ void BgDdanKd_CheckForExplosions(BgDdanKd* this, GlobalContext* globalCtx) {
}
}
static Vec3f velocity = { 0.0f, 5.0f, 0.0f };
static Vec3f accel = { 0.0f, -0.45f, 0.0f };
Vec3f sBgDdanKdVelocity = { 0.0f, 5.0f, 0.0f };
Vec3f sBgDdanKdAccel = { 0.0f, -0.45f, 0.0f };
void BgDdanKd_LowerStairs(BgDdanKd* this, GlobalContext* globalCtx) {
Vec3f pos1;
@ -158,11 +158,11 @@ void BgDdanKd_LowerStairs(BgDdanKd* this, GlobalContext* globalCtx) {
func_80033480(globalCtx, &pos1, 20.0f, 1, effectStrength * 135.0f, 60, 1);
func_80033480(globalCtx, &pos2, 20.0f, 1, effectStrength * 135.0f, 60, 1);
velocity.x = Rand_CenteredFloat(3.0f);
velocity.z = Rand_CenteredFloat(3.0f);
sBgDdanKdVelocity.x = Rand_CenteredFloat(3.0f);
sBgDdanKdVelocity.z = Rand_CenteredFloat(3.0f);
func_8003555C(globalCtx, &pos1, &velocity, &accel);
func_8003555C(globalCtx, &pos2, &velocity, &accel);
func_8003555C(globalCtx, &pos1, &sBgDdanKdVelocity, &sBgDdanKdAccel);
func_8003555C(globalCtx, &pos2, &sBgDdanKdVelocity, &sBgDdanKdAccel);
pos1 = this->dyna.actor.world.pos;
pos1.z += 560.0f + Rand_ZeroOne() * 5.0f;
@ -170,7 +170,7 @@ void BgDdanKd_LowerStairs(BgDdanKd* this, GlobalContext* globalCtx) {
pos1.y = Rand_ZeroOne() * 3.0f + (this->dyna.actor.floorHeight + 20.0f);
func_80033480(globalCtx, &pos1, 20.0f, 1, effectStrength * 135.0f, 60, 1);
func_8003555C(globalCtx, &pos1, &velocity, &accel);
func_8003555C(globalCtx, &pos1, &sBgDdanKdVelocity, &sBgDdanKdAccel);
}
Camera_AddQuake(&globalCtx->mainCamera, 0, effectStrength * 0.6f, 3);
Audio_PlaySoundGeneral(NA_SE_EV_PILLAR_SINK - SFX_FLAG, &this->dyna.actor.projectedPos, 4, &D_801333E0,
@ -192,11 +192,11 @@ void BgDdanKd_Draw(Actor* thisx, GlobalContext* globalCtx) {
}
void BgDdanKd_Reset(void) {
velocity.x = 0.0f;
velocity.y = 5.0f;
velocity.z = 0.0f;
sBgDdanKdVelocity.x = 0.0f;
sBgDdanKdVelocity.y = 5.0f;
sBgDdanKdVelocity.z = 0.0f;
accel.x = 0.0f;
accel.y = -0.45f;
accel.z = 0.0f;
sBgDdanKdAccel.x = 0.0f;
sBgDdanKdAccel.y = -0.45f;
sBgDdanKdAccel.z = 0.0f;
}

View file

@ -74,13 +74,13 @@ static ColliderCylinderInit sColCylinderInitLeftRight = {
{ 50, 60, 280, { 0, 0, 0 } },
};
static s16 sFirstExplosiveFlag = false;
s16 sBgDodoagoFirstExplosiveFlag = false;
static u8 sDisableBombCatcher;
u8 sBgDodoagoDisableBombCatcher;
static u8 sUnused[90]; // unknown length
//static u8 sUnused[90]; // unknown length
static s32 sTimer;
s32 sBgDodoagoTimer;
void BgDodoago_SetupAction(BgDodoago* this, BgDodoagoActionFunc actionFunc) {
this->actionFunc = actionFunc;
@ -135,7 +135,7 @@ void BgDodoago_Init(Actor* thisx, GlobalContext* globalCtx) {
Collider_SetCylinder(globalCtx, &this->colliderRight, &this->dyna.actor, &sColCylinderInitLeftRight);
BgDodoago_SetupAction(this, BgDodoago_WaitExplosives);
sDisableBombCatcher = false;
sBgDodoagoDisableBombCatcher = false;
}
void BgDodoago_Destroy(Actor* thisx, GlobalContext* globalCtx) {
@ -170,16 +170,16 @@ void BgDodoago_WaitExplosives(BgDodoago* this, GlobalContext* globalCtx) {
} else {
OnePointCutscene_Init(globalCtx, 3065, 20, &this->dyna.actor, MAIN_CAM);
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
sTimer += 30;
sBgDodoagoTimer += 30;
return;
}
// the flag is never set back to false, so this only runs once
if (!sFirstExplosiveFlag) {
if (!sBgDodoagoFirstExplosiveFlag) {
// this disables the bomb catcher (see BgDodoago_Update) for a few seconds
this->dyna.actor.parent = explosive;
sFirstExplosiveFlag = true;
sTimer = 50;
sBgDodoagoFirstExplosiveFlag = true;
sBgDodoagoTimer = 50;
}
} else if (Flags_GetEventChkInf(0xB0)) {
Collider_UpdateCylinder(&this->dyna.actor, &this->colliderMain);
@ -219,11 +219,11 @@ void BgDodoago_OpenJaw(BgDodoago* this, GlobalContext* globalCtx) {
}
if (globalCtx->roomCtx.unk_74[BGDODOAGO_EYE_LEFT] != 255 || globalCtx->roomCtx.unk_74[BGDODOAGO_EYE_RIGHT] != 255) {
sTimer--;
sBgDodoagoTimer--;
return;
}
if (sTimer == 108) {
if (sBgDodoagoTimer == 108) {
for (i = ARRAY_COUNT(dustOffsets) - 1; i >= 0; i--) {
pos.x = dustOffsets[i].x + this->dyna.actor.world.pos.x;
pos.y = dustOffsets[i].y + this->dyna.actor.world.pos.y;
@ -290,16 +290,16 @@ void BgDodoago_Update(Actor* thisx, GlobalContext* globalCtx) {
this->dyna.actor.parent = &bomb->actor;
bomb->timer = 50;
bomb->actor.speedXZ = 0.0f;
sTimer = 0;
sBgDodoagoTimer = 0;
}
}
} else {
sTimer++;
sBgDodoagoTimer++;
Flags_GetSwitch(globalCtx, this->dyna.actor.params & 0x3F);
if (!sDisableBombCatcher && sTimer > 140) {
if (!sBgDodoagoDisableBombCatcher && sBgDodoagoTimer > 140) {
if (Flags_GetSwitch(globalCtx, this->dyna.actor.params & 0x3F)) {
// this prevents clearing the actor's parent pointer, effectively disabling the bomb catcher
sDisableBombCatcher++;
sBgDodoagoDisableBombCatcher++;
} else {
this->dyna.actor.parent = NULL;
}
@ -322,7 +322,7 @@ void BgDodoago_Draw(Actor* thisx, GlobalContext* globalCtx) {
}
void BgDodoago_Reset(void) {
sFirstExplosiveFlag = false;
sDisableBombCatcher = 0;
sTimer = 0;
sBgDodoagoFirstExplosiveFlag = false;
sBgDodoagoDisableBombCatcher = 0;
sBgDodoagoTimer = 0;
}

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

@ -47,7 +47,7 @@ void BgHakaGate_SkullOfTruth(BgHakaGate* this, GlobalContext* globalCtx);
void BgHakaGate_FalseSkull(BgHakaGate* this, GlobalContext* globalCtx);
static s16 sSkullOfTruthRotY = 0x100;
static u8 sPuzzleState = 1;
static u8 sBgPoEventPuzzleState = 1;
static f32 sStatueDistToPlayer = 0;
static s16 sStatueRotY;
@ -82,7 +82,7 @@ void BgHakaGate_Init(Actor* thisx, GlobalContext* globalCtx) {
if (sSkullOfTruthRotY != 0x100) {
this->actionFunc = BgHakaGate_FalseSkull;
} else if (ABS(thisx->shape.rot.y) < 0x4000) {
if ((Rand_ZeroOne() * 3.0f) < sPuzzleState) {
if ((Rand_ZeroOne() * 3.0f) < sBgPoEventPuzzleState) {
this->vIsSkullOfTruth = true;
sSkullOfTruthRotY = thisx->shape.rot.y + 0x8000;
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
@ -91,7 +91,7 @@ void BgHakaGate_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actionFunc = BgHakaGate_SkullOfTruth;
}
} else {
sPuzzleState++;
sBgPoEventPuzzleState++;
this->actionFunc = BgHakaGate_FalseSkull;
}
} else {
@ -141,7 +141,7 @@ void BgHakaGate_Destroy(Actor* thisx, GlobalContext* globalCtx) {
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
if (this->dyna.actor.params == BGHAKAGATE_STATUE) {
sSkullOfTruthRotY = 0x100;
sPuzzleState = 1;
sBgPoEventPuzzleState = 1;
}
}
@ -178,7 +178,7 @@ void BgHakaGate_StatueIdle(BgHakaGate* this, GlobalContext* globalCtx) {
}
}
} else {
if (sPuzzleState == SKULL_OF_TRUTH_FOUND) {
if (sBgPoEventPuzzleState == SKULL_OF_TRUTH_FOUND) {
this->actionFunc = BgHakaGate_StatueInactive;
} else {
this->vTimer = 0;
@ -192,7 +192,12 @@ void BgHakaGate_StatueTurn(BgHakaGate* this, GlobalContext* globalCtx) {
s16 turnAngle;
this->vTurnRateDeg10++;
this->vTurnRateDeg10 = CLAMP_MAX(this->vTurnRateDeg10, 5);
if (CVar_GetS32("gFasterBlockPush", 0) != 0) {
this->vTurnRateDeg10 = 10;
CLAMP_MAX(this->vTurnRateDeg10, 5);
} else {
this->vTurnRateDeg10 = CLAMP_MAX(this->vTurnRateDeg10, 5);
}
turnFinished = Math_StepToS(&this->vTurnAngleDeg10, 600, this->vTurnRateDeg10);
turnAngle = this->vTurnAngleDeg10 * this->vTurnDirection;
this->dyna.actor.shape.rot.y = (this->vRotYDeg10 + turnAngle) * 0.1f * (0x10000 / 360.0f);
@ -212,7 +217,7 @@ void BgHakaGate_StatueTurn(BgHakaGate* this, GlobalContext* globalCtx) {
this->vRotYDeg10 = (this->vRotYDeg10 + turnAngle) % 3600;
this->vTurnRateDeg10 = 0;
this->vTurnAngleDeg10 = 0;
this->vTimer = 5;
this->vTimer = CVar_GetS32("gFasterBlockPush", 0) != 0 ? 2 : 5;
this->actionFunc = BgHakaGate_StatueIdle;
this->dyna.unk_150 = 0.0f;
}
@ -238,7 +243,7 @@ void BgHakaGate_FloorClosed(BgHakaGate* this, GlobalContext* globalCtx) {
sStatueDistToPlayer = 0.0f;
if (ABS(yawDiff) < 0x80) {
Flags_SetSwitch(globalCtx, this->switchFlag);
sPuzzleState = SKULL_OF_TRUTH_FOUND;
sBgPoEventPuzzleState = SKULL_OF_TRUTH_FOUND;
this->actionFunc = BgHakaGate_DoNothing;
} else {
func_80078884(NA_SE_SY_ERROR);

View file

@ -28,7 +28,7 @@ void func_80880AE8(BgHakaTrap* this, GlobalContext* globalCtx);
void func_80880C0C(BgHakaTrap* this, GlobalContext* globalCtx);
void func_80880D68(BgHakaTrap* this);
static UNK_TYPE D_80880F30 = 0;
UNK_TYPE D_80880F30 = 0;
const ActorInit Bg_Haka_Trap_InitVars = {
ACTOR_BG_HAKA_TRAP,
@ -107,7 +107,7 @@ static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
};
static UNK_TYPE D_80881014 = 0;
UNK_TYPE D_80881014 = 0;
void BgHakaTrap_Init(Actor* thisx, GlobalContext* globalCtx) {
BgHakaTrap* this = (BgHakaTrap*)thisx;
s32 pad;

View file

@ -120,7 +120,7 @@ void func_8088B24C(BgHidanRock* this) {
this->actionFunc = func_8088B990;
}
static f32 D_8088BFC0 = 0.0f;
f32 D_8088BFC0 = 0.0f;
void func_8088B268(BgHidanRock* this, GlobalContext* globalCtx) {
f32 sp2C;
s32 temp_v1;
@ -137,7 +137,7 @@ void func_8088B268(BgHidanRock* this, GlobalContext* globalCtx) {
}
}
this->dyna.actor.speedXZ += 0.05f;
this->dyna.actor.speedXZ += CVar_GetS32("gFasterBlockPush", 0) != 0 ? 0.5f : 0.05f;
this->dyna.actor.speedXZ = CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f);
if (D_8088BFC0 > 0.0f) {
@ -156,7 +156,7 @@ void func_8088B268(BgHidanRock* this, GlobalContext* globalCtx) {
this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z;
D_8088BFC0 = 0.0f;
this->dyna.actor.speedXZ = 0.0f;
this->timer = 5;
this->timer = CVar_GetS32("gFasterBlockPush", 0) != 0 ? 2 : 5;
}
func_8002F974(&this->dyna.actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG);

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

@ -23,7 +23,7 @@ void BgJya1flift_SetupDoNothing(BgJya1flift* this);
void BgJya1flift_ResetMoveDelay(BgJya1flift* this);
void BgJya1flift_DelayMove(BgJya1flift* this, GlobalContext* globalCtx);
static u8 sIsSpawned = false;
static u8 sKankyoIsSpawned = false;
const ActorInit Bg_Jya_1flift_InitVars = {
ACTOR_BG_JYA_1FLIFT,
@ -94,9 +94,9 @@ void BgJya1flift_InitCollision(Actor* thisx, GlobalContext* globalCtx) {
void BgJya1flift_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJya1flift* this = (BgJya1flift*)thisx;
// "1 F lift"
osSyncPrintf("(1Fリフト)(flag %d)(room %d)\n", sIsSpawned, globalCtx->roomCtx.curRoom.num);
osSyncPrintf("(1Fリフト)(flag %d)(room %d)\n", sKankyoIsSpawned, globalCtx->roomCtx.curRoom.num);
this->hasInitialized = false;
if (sIsSpawned) {
if (sKankyoIsSpawned) {
Actor_Kill(thisx);
return;
}
@ -109,7 +109,7 @@ void BgJya1flift_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJya1flift_SetupWaitForSwitch(this);
}
thisx->room = -1;
sIsSpawned = true;
sKankyoIsSpawned = true;
this->hasInitialized = true;
}
@ -117,7 +117,7 @@ void BgJya1flift_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgJya1flift* this = (BgJya1flift*)thisx;
if (this->hasInitialized) {
sIsSpawned = false;
sKankyoIsSpawned = false;
Collider_DestroyCylinder(globalCtx, &this->collider);
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
}

View file

@ -14,7 +14,7 @@ void BgJyaBigmirror_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgJyaBigmirror_Update(Actor* thisx, GlobalContext* globalCtx);
void BgJyaBigmirror_Draw(Actor* thisx, GlobalContext* globalCtx);
static u8 sIsSpawned = false;
static u8 sKankyoIsSpawned = false;
const ActorInit Bg_Jya_Bigmirror_InitVars = {
ACTOR_BG_JYA_BIGMIRROR,
@ -176,7 +176,7 @@ void BgJyaBigmirror_HandleMirRay(Actor* thisx, GlobalContext* globalCtx) {
void BgJyaBigmirror_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (sIsSpawned) {
if (sKankyoIsSpawned) {
Actor_Kill(&this->actor);
return;
}
@ -185,7 +185,7 @@ void BgJyaBigmirror_Init(Actor* thisx, GlobalContext* globalCtx) {
this->cobraInfo[0].rotY = sCobraSpawnData[0].initRotY;
this->cobraInfo[1].rotY = sCobraSpawnData[1].initRotY;
this->actor.room = -1;
sIsSpawned = true;
sKankyoIsSpawned = true;
this->spawned = true;
this->mirRayObjIndex = -1;
@ -197,7 +197,7 @@ void BgJyaBigmirror_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgJyaBigmirror* this = (BgJyaBigmirror*)thisx;
if (this->spawned) {
sIsSpawned = false;
sKankyoIsSpawned = false;
}
}

View file

@ -444,7 +444,7 @@ void func_80896950(BgJyaCobra* this, GlobalContext* globalCtx) {
if (this->dyna.unk_150 > 0.001f) {
this->unk_168++;
if (this->unk_168 >= 15) {
if (this->unk_168 >= CVar_GetS32("gFasterBlockPush", 0) != 0 ? 5 : 15) {
func_808969F8(this, globalCtx);
}
} else {
@ -484,9 +484,11 @@ void func_808969F8(BgJyaCobra* this, GlobalContext* globalCtx) {
void func_80896ABC(BgJyaCobra* this, GlobalContext* globalCtx) {
s16 temp_v0;
Player* player = GET_PLAYER(globalCtx);
if (CVar_GetS32("gFasterBlockPush", 0) != 0)
this->unk_16E = 150.0f;
temp_v0 = (s16)((this->unk_16C * 0x2000) + this->dyna.actor.home.rot.y) - this->dyna.actor.world.rot.y;
if (ABS(temp_v0) < 7424) {
if (ABS(temp_v0) < CVar_GetS32("gFasterBlockPush", 0) != 0 ? 3712 : 7424) {
Math_StepToS(&this->unk_16E, 106, 4);
} else {
Math_StepToS(&this->unk_16E, 21, 10);

View file

@ -20,7 +20,7 @@ void BgJyaLift_DelayMove(BgJyaLift* this, GlobalContext* globalCtx);
void BgJyaLift_SetupMove(BgJyaLift* this);
void BgJyaLift_Move(BgJyaLift* this, GlobalContext* globalCtx);
static s16 sIsSpawned = false;
static s16 sKankyoIsSpawned = false;
const ActorInit Bg_Jya_Lift_InitVars = {
ACTOR_BG_JYA_LIFT,
@ -55,7 +55,7 @@ void BgJyaLift_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJyaLift* this = (BgJyaLift*)thisx;
this->isSpawned = false;
if (sIsSpawned) {
if (sKankyoIsSpawned) {
Actor_Kill(thisx);
return;
}
@ -70,7 +70,7 @@ void BgJyaLift_Init(Actor* thisx, GlobalContext* globalCtx) {
BgJyaLift_SetInitPosY(this);
}
thisx->room = -1;
sIsSpawned = true;
sKankyoIsSpawned = true;
this->isSpawned = true;
}
@ -81,7 +81,7 @@ void BgJyaLift_Destroy(Actor* thisx, GlobalContext* globalCtx) {
// "Goddess Lift DT"
osSyncPrintf("女神リフト DT\n");
sIsSpawned = false;
sKankyoIsSpawned = false;
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
}
}

View file

@ -28,7 +28,7 @@ const ActorInit Bg_Menkuri_Eye_InitVars = {
(ActorResetFunc)BgMenkuriEye_Reset,
};
static s32 D_8089C1A0;
s32 D_8089C1A0;
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
{

View file

@ -17,7 +17,7 @@ void func_808A2008(BgMoriElevator* this, GlobalContext* globalCtx);
void BgMoriElevator_MoveIntoGround(BgMoriElevator* this, GlobalContext* globalCtx);
void BgMoriElevator_MoveAboveGround(BgMoriElevator* this, GlobalContext* globalCtx);
static s16 sIsSpawned = false;
static s16 sKankyoIsSpawned = false;
const ActorInit Bg_Mori_Elevator_InitVars = {
ACTOR_BG_MORI_ELEVATOR,
@ -87,18 +87,18 @@ void BgMoriElevator_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
CollisionHeader* colHeader = NULL;
this->unk_172 = sIsSpawned;
this->unk_172 = sKankyoIsSpawned;
this->moriTexObjIndex = Object_GetIndex(&globalCtx->objectCtx, OBJECT_MORI_TEX);
if (this->moriTexObjIndex < 0) {
Actor_Kill(thisx);
// "Forest Temple obj elevator Bank Danger!"
osSyncPrintf("Error : 森の神殿 obj elevator バンク危険!(%s %d)\n", "../z_bg_mori_elevator.c", 277);
} else {
switch (sIsSpawned) {
switch (sKankyoIsSpawned) {
case false:
// "Forest Temple elevator CT"
osSyncPrintf("森の神殿 elevator CT\n");
sIsSpawned = true;
sKankyoIsSpawned = true;
this->dyna.actor.room = -1;
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
DynaPolyActor_Init(&this->dyna, DPM_PLAYER);
@ -120,7 +120,7 @@ void BgMoriElevator_Destroy(Actor* thisx, GlobalContext* globalCtx) {
// "Forest Temple elevator DT"
osSyncPrintf("森の神殿 elevator DT\n");
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
sIsSpawned = false;
sKankyoIsSpawned = false;
}
}

View file

@ -28,7 +28,7 @@ void BgMoriHineri_SpawnBossKeyChest(BgMoriHineri* this, GlobalContext* globalCtx
void BgMoriHineri_DoNothing(BgMoriHineri* this, GlobalContext* globalCtx);
void func_808A3D58(BgMoriHineri* this, GlobalContext* globalCtx);
static s16 sNextCamIdx = SUBCAM_NONE;
s16 sBgMoriHineriNextCamIdx = SUBCAM_NONE;
const ActorInit Bg_Mori_Hineri_InitVars = {
ACTOR_BG_MORI_HINERI,
@ -194,28 +194,28 @@ void func_808A3D58(BgMoriHineri* this, GlobalContext* globalCtx) {
OnePointCutscene_EndCutscene(globalCtx, mainCamChildIdx);
}
OnePointCutscene_Init(globalCtx, 3260, 40, &this->dyna.actor, MAIN_CAM);
sNextCamIdx = OnePointCutscene_Init(globalCtx, 3261, 40, &this->dyna.actor, MAIN_CAM);
sBgMoriHineriNextCamIdx = OnePointCutscene_Init(globalCtx, 3261, 40, &this->dyna.actor, MAIN_CAM);
}
}
void func_808A3E54(BgMoriHineri* this, GlobalContext* globalCtx) {
s8 objBankIndex;
if (globalCtx->activeCamera == sNextCamIdx) {
if (sNextCamIdx != MAIN_CAM) {
if (globalCtx->activeCamera == sBgMoriHineriNextCamIdx) {
if (sBgMoriHineriNextCamIdx != MAIN_CAM) {
objBankIndex = this->dyna.actor.objBankIndex;
this->dyna.actor.objBankIndex = this->moriHineriObjIdx;
this->moriHineriObjIdx = objBankIndex;
this->dyna.actor.params ^= 1;
sNextCamIdx = MAIN_CAM;
sBgMoriHineriNextCamIdx = MAIN_CAM;
func_80078884(NA_SE_SY_TRE_BOX_APPEAR);
} else {
this->dyna.actor.draw = NULL;
this->actionFunc = func_808A3D58;
sNextCamIdx = SUBCAM_NONE;
sBgMoriHineriNextCamIdx = SUBCAM_NONE;
}
}
if ((sNextCamIdx >= SUBCAM_FIRST) &&
if ((sBgMoriHineriNextCamIdx >= SUBCAM_FIRST) &&
((GET_ACTIVE_CAM(globalCtx)->eye.z - this->dyna.actor.world.pos.z) < 1100.0f)) {
func_8002F948(&this->dyna.actor, NA_SE_EV_FLOOR_ROLLING - SFX_FLAG);
}
@ -283,5 +283,5 @@ void BgMoriHineri_DrawHallAndRoom(Actor* thisx, GlobalContext* globalCtx) {
}
void BgMoriHineri_Reset() {
sNextCamIdx = SUBCAM_NONE;
sBgMoriHineriNextCamIdx = SUBCAM_NONE;
}

View file

@ -19,7 +19,7 @@ void BgMoriIdomizu_WaitForMoriTex(BgMoriIdomizu* this, GlobalContext* globalCtx)
void BgMoriIdomizu_SetupMain(BgMoriIdomizu* this);
void BgMoriIdomizu_Main(BgMoriIdomizu* this, GlobalContext* globalCtx);
static s16 sIsSpawned = false;
static s16 sKankyoIsSpawned = false;
const ActorInit Bg_Mori_Idomizu_InitVars = {
ACTOR_BG_MORI_IDOMIZU,
@ -50,7 +50,7 @@ void BgMoriIdomizu_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
BgMoriIdomizu* this = (BgMoriIdomizu*)thisx;
if (sIsSpawned) {
if (sKankyoIsSpawned) {
Actor_Kill(&this->actor);
return;
}
@ -76,7 +76,7 @@ void BgMoriIdomizu_Init(Actor* thisx, GlobalContext* globalCtx) {
return;
}
BgMoriIdomizu_SetupWaitForMoriTex(this);
sIsSpawned = true;
sKankyoIsSpawned = true;
this->isLoaded = true;
this->actor.room = -1;
// "Forest Temple well water"
@ -88,7 +88,7 @@ void BgMoriIdomizu_Destroy(Actor* thisx, GlobalContext* globalCtx) {
BgMoriIdomizu* this = (BgMoriIdomizu*)thisx;
if (this->isLoaded) {
sIsSpawned = false;
sKankyoIsSpawned = false;
}
}

View file

@ -94,7 +94,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, GlobalContext* globalCtx) {
if (this->dyna.unk_150 > 0.001f) {
this->timer++;
if ((this->timer > 28) && !Player_InCsMode(globalCtx)) {
if ((this->timer > CVar_GetS32("gFasterBlockPush", 0) != 0 ? 14 : 28) && !Player_InCsMode(globalCtx)) {
BgMoriKaitenkabe_SetupRotate(this);
func_8002DF54(globalCtx, &this->dyna.actor, 8);
Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos);
@ -118,7 +118,7 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, GlobalContext* globalCtx) {
void BgMoriKaitenkabe_SetupRotate(BgMoriKaitenkabe* this) {
this->actionFunc = BgMoriKaitenkabe_Rotate;
this->rotSpeed = 0.0f;
this->rotSpeed = CVar_GetS32("gFasterBlockPush", 0) != 0 ? 0.5f : 0.0f;
this->rotYdeg = 0.0f;
}

View file

@ -80,11 +80,11 @@ static ColliderTrisInit sTrisInit = {
sTrisElementsInit,
};
static u8 sBlocksAtRest = 0;
u8 sBgPoEventBlocksAtRest = 0;
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
static u8 sPuzzleState;
u8 sBgPoEventPuzzleState;
void BgPoEvent_InitPaintings(BgPoEvent* this, GlobalContext* globalCtx) {
static s16 paintingPosX[] = { -1302, -866, 1421, 985 };
@ -142,10 +142,10 @@ void BgPoEvent_InitPaintings(BgPoEvent* this, GlobalContext* globalCtx) {
}
this->timer = 0;
if (this->type == 4) {
sPuzzleState = 0;
sBgPoEventPuzzleState = 0;
this->actionFunc = BgPoEvent_AmyWait;
} else {
sPuzzleState = (s32)(Rand_ZeroOne() * 3.0f) % 3;
sBgPoEventPuzzleState = (s32)(Rand_ZeroOne() * 3.0f) % 3;
this->actionFunc = BgPoEvent_PaintingEmpty;
}
}
@ -236,7 +236,7 @@ void BgPoEvent_Destroy(Actor* thisx, GlobalContext* globalCtx) {
void BgPoEvent_BlockWait(BgPoEvent* this, GlobalContext* globalCtx) {
this->dyna.actor.world.pos.y = 833.0f;
if (sPuzzleState == 0x3F) {
if (sBgPoEventPuzzleState == 0x3F) {
if (this->type == 1) {
OnePointCutscene_Init(globalCtx, 3150, 65, NULL, MAIN_CAM);
}
@ -244,14 +244,14 @@ void BgPoEvent_BlockWait(BgPoEvent* this, GlobalContext* globalCtx) {
this->actionFunc = BgPoEvent_BlockShake;
} else if (this->dyna.actor.xzDistToPlayer > 50.0f) {
if (this->type != 1) {
sPuzzleState |= (1 << this->index);
sBgPoEventPuzzleState |= (1 << this->index);
} else {
sPuzzleState |= 0x10;
sBgPoEventPuzzleState |= 0x10;
}
} else if (this->type != 1) {
sPuzzleState &= ~(1 << this->index);
sBgPoEventPuzzleState &= ~(1 << this->index);
} else {
sPuzzleState &= ~0x10;
sBgPoEventPuzzleState &= ~0x10;
}
}
@ -265,7 +265,7 @@ void BgPoEvent_BlockShake(BgPoEvent* this, GlobalContext* globalCtx) {
}
if (this->timer == 0) {
this->dyna.actor.world.pos.x = this->dyna.actor.home.pos.x;
sPuzzleState = 0;
sBgPoEventPuzzleState = 0;
this->timer = 60;
this->actionFunc = BgPoEvent_BlockFall;
}
@ -299,9 +299,9 @@ void BgPoEvent_CheckBlock(BgPoEvent* this) {
}
}
if ((phi_v1 == phi_a1) && ((phi_t0 - phi_a3) == 60)) {
sPuzzleState |= (1 << this->index);
sBgPoEventPuzzleState |= (1 << this->index);
} else {
sPuzzleState &= ~(1 << this->index);
sBgPoEventPuzzleState &= ~(1 << this->index);
}
}
@ -312,7 +312,7 @@ void BgPoEvent_BlockFall(BgPoEvent* this, GlobalContext* globalCtx) {
if (Math_StepToF(&this->dyna.actor.world.pos.y, 433.0f, this->dyna.actor.velocity.y)) {
this->dyna.actor.flags &= ~ACTOR_FLAG_5;
this->dyna.actor.velocity.y = 0.0f;
sBlocksAtRest++;
sBgPoEventBlocksAtRest++;
if (this->type != 1) {
BgPoEvent_CheckBlock(this);
} else {
@ -334,7 +334,7 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Actor* amy;
if (sPuzzleState == 0xF) {
if (sBgPoEventPuzzleState == 0xF) {
this->actionFunc = BgPoEvent_BlockSolved;
if ((this->type == 0) && (this->index == 0)) {
amy =
@ -348,23 +348,23 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, GlobalContext* globalCtx) {
gSaveContext.timer1State = 0xA;
}
} else {
if ((gSaveContext.timer1Value == 0) && (sBlocksAtRest == 5)) {
if ((gSaveContext.timer1Value == 0) && (sBgPoEventBlocksAtRest == 5)) {
player->stateFlags2 &= ~0x10;
sPuzzleState = 0x10;
sBlocksAtRest = 0;
sBgPoEventPuzzleState = 0x10;
sBgPoEventBlocksAtRest = 0;
}
if ((sPuzzleState == 0x40) || ((sPuzzleState == 0x10) && !Player_InCsMode(globalCtx))) {
if ((sBgPoEventPuzzleState == 0x40) || ((sBgPoEventPuzzleState == 0x10) && !Player_InCsMode(globalCtx))) {
this->dyna.actor.world.rot.z = this->dyna.actor.shape.rot.z;
this->actionFunc = BgPoEvent_BlockReset;
if (sPuzzleState == 0x10) {
sPuzzleState = 0x40;
if (sBgPoEventPuzzleState == 0x10) {
sBgPoEventPuzzleState = 0x40;
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EV_BLOCK_RISING);
func_8002DF54(globalCtx, &player->actor, 8);
}
} else if (this->dyna.unk_150 != 0.0f) {
if (this->direction == 0) {
if (func_800435D8(globalCtx, &this->dyna, 0x1E, 0x32, -0x14) != 0) {
sBlocksAtRest--;
sBgPoEventBlocksAtRest--;
this->direction = (this->dyna.unk_150 >= 0.0f) ? 1.0f : -1.0f;
this->actionFunc = BgPoEvent_BlockPush;
} else {
@ -382,16 +382,16 @@ void BgPoEvent_BlockIdle(BgPoEvent* this, GlobalContext* globalCtx) {
}
}
static f32 blockPushDist = 0.0f;
f32 sBgPoEventblockPushDist = 0.0f;
void BgPoEvent_BlockPush(BgPoEvent* this, GlobalContext* globalCtx) {
f32 displacement;
s32 blockStop;
Player* player = GET_PLAYER(globalCtx);
this->dyna.actor.speedXZ += 0.1f;
this->dyna.actor.speedXZ += CVar_GetS32("gFasterBlockPush", 0) != 0 ? 0.5f : 0.1f;
this->dyna.actor.speedXZ = CLAMP_MAX(this->dyna.actor.speedXZ, 2.0f);
blockStop = Math_StepToF(&blockPushDist, 20.0f, this->dyna.actor.speedXZ);
displacement = this->direction * blockPushDist;
blockStop = Math_StepToF(&sBgPoEventblockPushDist, 20.0f, this->dyna.actor.speedXZ);
displacement = this->direction * sBgPoEventblockPushDist;
this->dyna.actor.world.pos.x = (Math_SinS(this->dyna.unk_158) * displacement) + this->dyna.actor.home.pos.x;
this->dyna.actor.world.pos.z = (Math_CosS(this->dyna.unk_158) * displacement) + this->dyna.actor.home.pos.z;
if (blockStop) {
@ -402,10 +402,10 @@ void BgPoEvent_BlockPush(BgPoEvent* this, GlobalContext* globalCtx) {
this->dyna.unk_150 = 0.0f;
this->dyna.actor.home.pos.x = this->dyna.actor.world.pos.x;
this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z;
blockPushDist = 0.0f;
sBgPoEventblockPushDist = 0.0f;
this->dyna.actor.speedXZ = 0.0f;
this->direction = 5;
sBlocksAtRest++;
this->direction = CVar_GetS32("gFasterBlockPush", 0) != 0 ? 3 : 5;
sBgPoEventBlocksAtRest++;
this->actionFunc = BgPoEvent_BlockIdle;
if (this->type == 1) {
return;
@ -428,7 +428,7 @@ void BgPoEvent_BlockReset(BgPoEvent* this, GlobalContext* globalCtx) {
this->index = (this->index + 1) % 4;
this->actionFunc = BgPoEvent_BlockFall;
sPuzzleState = 0;
sBgPoEventPuzzleState = 0;
if (this->type == 1) {
this->timer += 10;
this->timer = CLAMP_MAX(this->timer, 120);
@ -443,14 +443,14 @@ void BgPoEvent_BlockSolved(BgPoEvent* this, GlobalContext* globalCtx) {
player->stateFlags2 &= ~0x10;
}
if (Math_StepToF(&this->dyna.actor.world.pos.y, 369.0f, 2.0f)) {
sPuzzleState = 0x20;
sBgPoEventPuzzleState = 0x20;
Actor_Kill(&this->dyna.actor);
}
}
void BgPoEvent_AmyWait(BgPoEvent* this, GlobalContext* globalCtx) {
if (this->collider.base.acFlags & AC_HIT) {
sPuzzleState |= 0x20;
sBgPoEventPuzzleState |= 0x20;
this->timer = 5;
Actor_SetColorFilter(&this->dyna.actor, 0x4000, 0xFF, 0, 5);
Audio_PlayActorSound2(&this->dyna.actor, NA_SE_EN_PO_LAUGH2);
@ -461,12 +461,12 @@ void BgPoEvent_AmyWait(BgPoEvent* this, GlobalContext* globalCtx) {
void BgPoEvent_AmyPuzzle(BgPoEvent* this, GlobalContext* globalCtx) {
Vec3f pos;
if (sPuzzleState == 0xF) {
if (sBgPoEventPuzzleState == 0xF) {
pos.x = this->dyna.actor.world.pos.x - 5.0f;
pos.y = Rand_CenteredFloat(120.0f) + this->dyna.actor.world.pos.y;
pos.z = Rand_CenteredFloat(120.0f) + this->dyna.actor.world.pos.z;
EffectSsDeadDb_Spawn(globalCtx, &pos, &sZeroVec, &sZeroVec, 170, 0, 200, 255, 100, 170, 0, 255, 0, 1, 9, true);
} else if (sPuzzleState == 0x20) {
} else if (sBgPoEventPuzzleState == 0x20) {
Actor_Kill(&this->dyna.actor);
} else {
DECR(this->timer);
@ -476,14 +476,14 @@ void BgPoEvent_AmyPuzzle(BgPoEvent* this, GlobalContext* globalCtx) {
s32 BgPoEvent_NextPainting(BgPoEvent* this) {
if ((this->dyna.actor.parent != NULL) && (this->dyna.actor.child != NULL)) {
if (Rand_ZeroOne() < 0.5f) {
sPuzzleState = ((BgPoEvent*)this->dyna.actor.parent)->index;
sBgPoEventPuzzleState = ((BgPoEvent*)this->dyna.actor.parent)->index;
} else {
sPuzzleState = ((BgPoEvent*)this->dyna.actor.child)->index;
sBgPoEventPuzzleState = ((BgPoEvent*)this->dyna.actor.child)->index;
}
} else if (this->dyna.actor.parent != NULL) {
sPuzzleState = ((BgPoEvent*)this->dyna.actor.parent)->index;
sBgPoEventPuzzleState = ((BgPoEvent*)this->dyna.actor.parent)->index;
} else if (this->dyna.actor.child != NULL) {
sPuzzleState = ((BgPoEvent*)this->dyna.actor.child)->index;
sBgPoEventPuzzleState = ((BgPoEvent*)this->dyna.actor.child)->index;
} else {
return false;
}
@ -491,7 +491,7 @@ s32 BgPoEvent_NextPainting(BgPoEvent* this) {
}
void BgPoEvent_PaintingEmpty(BgPoEvent* this, GlobalContext* globalCtx) {
if (sPuzzleState == this->index) {
if (sBgPoEventPuzzleState == this->index) {
this->timer = 255;
this->actionFunc = BgPoEvent_PaintingAppear;
}
@ -636,7 +636,7 @@ void BgPoEvent_Draw(Actor* thisx, GlobalContext* globalCtx) {
}
void BgPoEvent_Reset(void) {
sBlocksAtRest = 0;
sPuzzleState = 0;
blockPushDist = 0.0f;
sBgPoEventBlocksAtRest = 0;
sBgPoEventPuzzleState = 0;
sBgPoEventblockPushDist = 0.0f;
}

View file

@ -45,7 +45,7 @@ static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
};
static u32 D_808A9508 = 0;
u32 D_808A9508 = 0;
void BgRelayObjects_Init(Actor* thisx, GlobalContext* globalCtx) {
BgRelayObjects* this = (BgRelayObjects*)thisx;
s32 pad;

View file

@ -260,7 +260,7 @@ void func_808B4194(BgSpot15Rrbox* this, GlobalContext* globalCtx) {
s32 approxFResult;
Actor* actor = &this->dyna.actor;
this->unk_174 += 0.5f;
this->unk_174 += CVar_GetS32("gFasterBlockPush", 0) != 0 ? 1.0f : 0.5f;
this->unk_174 = CLAMP_MAX(this->unk_174, 2.0f);
@ -294,7 +294,7 @@ void func_808B4194(BgSpot15Rrbox* this, GlobalContext* globalCtx) {
this->dyna.unk_150 = 0.0f;
this->unk_178 = 0.0f;
this->unk_174 = 0.0f;
this->unk_168 = 10;
this->unk_168 = CVar_GetS32("gFasterBlockPush", 0) != 0 ? 3 : 10;
func_808B4084(this, globalCtx);
}
Audio_PlayActorSound2(actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG);

View file

@ -84,7 +84,7 @@ void func_808B7710(Actor* thisx, GlobalContext* globalCtx) {
this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE;
}
static s16 D_808B85D0 = 0;
s16 D_808B85D0 = 0;
void func_808B7770(BgSpot18Basket* this, GlobalContext* globalCtx, f32 arg2) {
Vec3f acceleration;
Vec3f velocity;

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)
@ -105,35 +107,17 @@ static ColliderCylinderInit sLightBallCylinderInit = {
static u8 D_808E4C58[] = { 0, 12, 10, 12, 14, 16, 12, 14, 16, 12, 14, 16, 12, 14, 16, 10, 16, 14 };
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
static EnGanonMant* sCape;
EnGanonMant* sBossGanonCape;
static s32 sSeed1;
static s32 sSeed2;
static s32 sSeed3;
s32 sBossGanonSeed1;
s32 sBossGanonSeed3;
s32 sBossGanonSeed2;
static BossGanon* sGanondorf;
BossGanon* sBossGanonGanondorf;
static EnZl3* sZelda;
EnZl3* sBossGanonZelda;
typedef struct {
/* 0x00 */ u8 type;
/* 0x01 */ u8 timer;
/* 0x04 */ Vec3f pos;
/* 0x10 */ Vec3f velocity;
/* 0x1C */ Vec3f accel;
/* 0x28 */ Color_RGB8 color;
/* 0x2C */ s16 alpha;
/* 0x2E */ s16 unk_2E;
/* 0x30 */ s16 unk_30;
/* 0x34 */ f32 scale;
/* 0x38 */ f32 unk_38; // scale target mostly, but used for other things
/* 0x3C */ f32 unk_3C; // mostly z rot
/* 0x40 */ f32 unk_40;
/* 0x44 */ f32 unk_44; // mostly x rot
/* 0x48 */ f32 unk_48; // mostly y rot
} GanondorfEffect; // size = 0x4C
GanondorfEffect sEffectBuf[200];
GanondorfEffect sBossGanonEffectBuf[200];
void BossGanonEff_SpawnWindowShard(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, f32 scale) {
static Color_RGB8 shardColors[] = { { 255, 175, 85 }, { 155, 205, 155 }, { 155, 125, 55 } };
@ -156,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;
}
}
@ -176,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;
}
}
@ -200,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;
}
}
@ -219,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;
}
}
@ -238,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;
}
}
@ -258,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;
}
}
@ -275,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) {
@ -293,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;
}
}
@ -313,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;
}
}
@ -348,13 +341,13 @@ void BossGanon_Init(Actor* thisx, GlobalContext* globalCtx2) {
if (thisx->params < 0x64) {
Flags_SetSwitch(globalCtx, 0x14);
globalCtx->specialEffects = sEffectBuf;
globalCtx->specialEffects = sBossGanonEffectBuf;
for (i = 0; i < ARRAY_COUNT(sEffectBuf); i++) {
sEffectBuf[i].type = GDF_EFF_NONE;
for (i = 0; i < ARRAY_COUNT(sBossGanonEffectBuf); i++) {
sBossGanonEffectBuf[i].type = GDF_EFF_NONE;
}
sGanondorf = this;
sBossGanonGanondorf = this;
thisx->colChkInfo.health = 40;
Actor_ProcessInitChain(thisx, sInitChain);
ActorShape_Init(&thisx->shape, 0, NULL, 0);
@ -381,7 +374,7 @@ void BossGanon_Init(Actor* thisx, GlobalContext* globalCtx2) {
BossGanon_SetupTowerCutscene(this, globalCtx);
}
sCape = (EnGanonMant*)Actor_SpawnAsChild(&globalCtx->actorCtx, thisx, globalCtx, ACTOR_EN_GANON_MANT, 0.0f,
sBossGanonCape = (EnGanonMant*)Actor_SpawnAsChild(&globalCtx->actorCtx, thisx, globalCtx, ACTOR_EN_GANON_MANT, 0.0f,
0.0f, 0.0f, 0, 0, 0, 1);
Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, thisx, ACTORCAT_BOSS);
} else {
@ -538,10 +531,10 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
gSegments[6] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[this->animBankIndex].segment);
sCape->backPush = -2.0f;
sCape->backSwayMagnitude = 0.25f;
sCape->sideSwayMagnitude = -1.0f;
sCape->minDist = 0.0f;
sBossGanonCape->backPush = -2.0f;
sBossGanonCape->backSwayMagnitude = 0.25f;
sBossGanonCape->sideSwayMagnitude = -1.0f;
sBossGanonCape->minDist = 0.0f;
this->csTimer++;
@ -584,13 +577,13 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
this->useOpenHand = true;
BossGanon_SetIntroCsCamera(this, 0);
this->csState = 1;
sZelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 0.0f,
sBossGanonZelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 0.0f,
220.0f, -150.0f, 0, 0, 0, 0x2000);
}
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_GANON_ORGAN, 0.0f, 0.0f, 0.0f, 0,
0, 0, 1);
sCape->minY = 57.0f;
sBossGanonCape->minY = 57.0f;
// fallthrough
case 1:
this->envLightMode = 3;
@ -736,7 +729,7 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
this->csState = 9;
this->csTimer = 0;
func_8002DF54(globalCtx, &this->actor, 8);
sZelda->unk_3C8 = 0;
sBossGanonZelda->unk_3C8 = 0;
this->triforceType = GDF_TRIFORCE_ZELDA;
this->fwork[GDF_TRIFORCE_SCALE] = 10.0f;
this->fwork[GDF_TRIFORCE_PRIM_A] = 0.0f;
@ -755,7 +748,7 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
Math_ApproachF(&this->fwork[GDF_TRIFORCE_ENV_G], 200.0f, 1.0f, 3.0f);
if (this->csTimer == 30) {
sZelda->unk_3C8 = 1;
sBossGanonZelda->unk_3C8 = 1;
}
if (this->csTimer >= 32) {
@ -847,7 +840,7 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
this->csTimer = 0;
BossGanon_SetIntroCsCamera(this, 11);
this->unk_198 = 2;
sZelda->unk_3C8 = 2;
sBossGanonZelda->unk_3C8 = 2;
this->timers[2] = 110;
this->envLightMode = 3;
}
@ -883,7 +876,7 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
if (this->csTimer > 10) {
if (this->csTimer == 62) {
sCape->attachRightArmTimer = 20.0f;
sBossGanonCape->attachRightArmTimer = 20.0f;
}
if (this->csTimer == 57) {
@ -1076,7 +1069,7 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfGetUp3Anim, 0.0f);
SkelAnime_Update(&this->skelAnime);
this->actor.shape.yOffset = 0.0f;
sCape->attachShouldersTimer = 18.0f;
sBossGanonCape->attachShouldersTimer = 18.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
this->unk_198 = 0;
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_GANONDORF_BOSS);
@ -1101,9 +1094,9 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
Math_ApproachF(&this->actor.world.pos.y, 228.0f, 0.05f, 2.0f);
Math_ApproachF(&this->actor.world.pos.z, -230.0f, 0.05f, 4.0f);
sCape->backPush = -3.0f;
sCape->backSwayMagnitude = 0.25f;
sCape->sideSwayMagnitude = -3.0f;
sBossGanonCape->backPush = -3.0f;
sBossGanonCape->backSwayMagnitude = 0.25f;
sBossGanonCape->sideSwayMagnitude = -3.0f;
sin = Math_SinS(this->csTimer * 1500);
this->actor.velocity.y = this->fwork[GDF_FWORK_0] * sin * 0.04f;
@ -1136,10 +1129,10 @@ void BossGanon_IntroCutscene(BossGanon* this, GlobalContext* globalCtx) {
BossGanon_SetupWait(this, globalCtx);
}
if (sZelda != NULL) {
sZelda->actor.world.pos.x = 0.0f;
sZelda->actor.world.pos.y = 350.0f;
sZelda->actor.world.pos.z = 0.0f;
if (sBossGanonZelda != NULL) {
sBossGanonZelda->actor.world.pos.x = 0.0f;
sBossGanonZelda->actor.world.pos.y = 350.0f;
sBossGanonZelda->actor.world.pos.z = 0.0f;
}
}
@ -1529,7 +1522,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->fwork[1] = Animation_GetLastFrame(&object_ganon_anime2_Anim_00EA00);
this->csState = 101;
this->skelAnime.playSpeed = 0.0f;
sZelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 0.0f,
sBossGanonZelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 0.0f,
6000.0f, 0.0f, 0, 0, 0, 0x2000);
player->actor.world.pos.x = -472.0f;
@ -1551,12 +1544,12 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->csCamAt.z = -100.0f;
sCape->backPush = -2.0f;
sCape->backSwayMagnitude = 0.25f;
sCape->sideSwayMagnitude = -1.0f;
sCape->minDist = 0.0f;
sCape->minY = 4104.0f;
sCape->tearTimer = 20;
sBossGanonCape->backPush = -2.0f;
sBossGanonCape->backSwayMagnitude = 0.25f;
sBossGanonCape->sideSwayMagnitude = -1.0f;
sBossGanonCape->minDist = 0.0f;
sBossGanonCape->minY = 4104.0f;
sBossGanonCape->tearTimer = 20;
this->whiteFillAlpha = 255.0f;
globalCtx->envCtx.unk_D8 = 1.0f;
@ -1620,27 +1613,27 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
if (this->csTimer == 90) {
this->csState = 103;
this->csTimer = 0;
sZelda->actor.world.pos.x = -472.0f;
sZelda->actor.world.pos.y = 4352.0f;
sZelda->actor.world.pos.z = -200.0f;
sZelda->unk_3C8 = 3;
sBossGanonZelda->actor.world.pos.x = -472.0f;
sBossGanonZelda->actor.world.pos.y = 4352.0f;
sBossGanonZelda->actor.world.pos.z = -200.0f;
sBossGanonZelda->unk_3C8 = 3;
}
break;
case 103:
Audio_PlayActorSound2(&sZelda->actor, NA_SE_EV_DOWN_TO_GROUND - SFX_FLAG);
Math_ApproachF(&sZelda->actor.world.pos.y, 4102.0f, 0.05f, 1.5f);
Audio_PlayActorSound2(&sBossGanonZelda->actor, NA_SE_EV_DOWN_TO_GROUND - SFX_FLAG);
Math_ApproachF(&sBossGanonZelda->actor.world.pos.y, 4102.0f, 0.05f, 1.5f);
this->csCamEye.x = -242.0f;
this->csCamEye.y = 4122.0f;
this->csCamEye.z = -190.0f;
this->csCamAt.x = sZelda->actor.world.pos.x;
this->csCamAt.y = sZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sZelda->actor.world.pos.z;
this->csCamAt.x = sBossGanonZelda->actor.world.pos.x;
this->csCamAt.y = sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sBossGanonZelda->actor.world.pos.z;
if (this->csTimer == 200) {
sZelda->actor.world.pos.y = 4102.0f;
sBossGanonZelda->actor.world.pos.y = 4102.0f;
this->csState = 104;
this->csTimer = 0;
} else {
@ -1652,20 +1645,20 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->csCamEye.y = 4147.0f;
this->csCamEye.z = -200.0f;
this->csCamAt.x = sZelda->actor.world.pos.x;
this->csCamAt.y = sZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sZelda->actor.world.pos.z;
this->csCamAt.x = sBossGanonZelda->actor.world.pos.x;
this->csCamAt.y = sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sBossGanonZelda->actor.world.pos.z;
if (this->csTimer >= 10) {
Math_ApproachZeroF(&globalCtx->envCtx.unk_D8, 1.0f, 0.05f);
}
if (this->csTimer == 10) {
sZelda->unk_3C8 = 8;
sBossGanonZelda->unk_3C8 = 8;
}
if (this->csTimer == 50) {
sZelda->unk_3C8 = 4;
sBossGanonZelda->unk_3C8 = 4;
}
if (this->csTimer == 100) {
@ -1679,9 +1672,9 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->csCamEye.y = 4154.0f;
this->csCamEye.z = -182.0f;
this->csCamAt.x = sZelda->actor.world.pos.x - 5.0f;
this->csCamAt.y = sZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sZelda->actor.world.pos.z - 25.0f;
this->csCamAt.x = sBossGanonZelda->actor.world.pos.x - 5.0f;
this->csCamAt.y = sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sBossGanonZelda->actor.world.pos.z - 25.0f;
if (this->csTimer == 10) {
Message_StartTextbox(globalCtx, 0x70D0, NULL);
@ -1698,7 +1691,7 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
func_80078884(NA_SE_EV_EARTHQUAKE - SFX_FLAG);
if (this->csTimer == 20) {
sZelda->unk_3C8 = 5;
sBossGanonZelda->unk_3C8 = 5;
func_8002DF54(globalCtx, &this->actor, 0x39);
}
@ -1747,15 +1740,15 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->csCamEye.y = 4154.0f;
this->csCamEye.z = -182.0f;
this->csCamAt.x = sZelda->actor.world.pos.x - 5.0f;
this->csCamAt.y = sZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sZelda->actor.world.pos.z - 25.0f;
this->csCamAt.x = sBossGanonZelda->actor.world.pos.x - 5.0f;
this->csCamAt.y = sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f;
this->csCamAt.z = sBossGanonZelda->actor.world.pos.z - 25.0f;
this->unk_70C = Math_SinS(this->csTimer * 0x6300) * 0.3f;
func_80078884(NA_SE_EV_EARTHQUAKE - SFX_FLAG);
if (this->csTimer == 70) {
sZelda->unk_3C8 = 6;
sBossGanonZelda->unk_3C8 = 6;
}
if (this->csTimer == 90) {
@ -1778,12 +1771,12 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->csCamEye.y = 4154.0f;
this->csCamEye.z = -242.0f;
this->csCamAt.x = (sZelda->actor.world.pos.x - 5.0f) - 30.0f;
this->csCamAt.y = (sZelda->actor.world.pos.y + 40.0f + 5.0f) - 20.0f;
this->csCamAt.z = (sZelda->actor.world.pos.z - 25.0f) + 80.0f;
this->csCamAt.x = (sBossGanonZelda->actor.world.pos.x - 5.0f) - 30.0f;
this->csCamAt.y = (sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f) - 20.0f;
this->csCamAt.z = (sBossGanonZelda->actor.world.pos.z - 25.0f) + 80.0f;
if ((this->csTimer > 50) && (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_NONE)) {
sZelda->unk_3C8 = 7;
sBossGanonZelda->unk_3C8 = 7;
this->csState = 108;
this->csTimer = 0;
}
@ -1793,9 +1786,9 @@ void BossGanon_DeathAndTowerCutscene(BossGanon* this, GlobalContext* globalCtx)
this->unk_70C = Math_SinS(this->csTimer * 0x6300) * 0.8f;
func_80078884(NA_SE_EV_EARTHQUAKE - SFX_FLAG);
this->csCamAt.x = (sZelda->actor.world.pos.x - 5.0f) - 30.0f;
this->csCamAt.y = (sZelda->actor.world.pos.y + 40.0f + 5.0f) - 20.0f;
this->csCamAt.z = (sZelda->actor.world.pos.z - 25.0f) + 80.0f;
this->csCamAt.x = (sBossGanonZelda->actor.world.pos.x - 5.0f) - 30.0f;
this->csCamAt.y = (sBossGanonZelda->actor.world.pos.y + 40.0f + 5.0f) - 20.0f;
this->csCamAt.z = (sBossGanonZelda->actor.world.pos.z - 25.0f) + 80.0f;
if (this->csTimer > 50) {
mainCam = Gameplay_GetCamera(globalCtx, MAIN_CAM);
@ -1905,7 +1898,7 @@ void BossGanon_PoundFloor(BossGanon* this, GlobalContext* globalCtx) {
break;
case 1:
sCape->gravity = -1.0f;
sBossGanonCape->gravity = -1.0f;
this->envLightMode = 1;
Math_ApproachF(&this->actor.velocity.y, -50.0f, 1.0f, 10.0f);
this->actor.world.pos.y += this->actor.velocity.y;
@ -1952,7 +1945,7 @@ void BossGanon_PoundFloor(BossGanon* this, GlobalContext* globalCtx) {
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(&gDorfGetUp3Anim);
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfGetUp3Anim, 0.0f);
SkelAnime_Update(&this->skelAnime);
sCape->attachShouldersTimer = 18.0f;
sBossGanonCape->attachShouldersTimer = 18.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
this->unk_1C2 = 4;
}
@ -2136,7 +2129,7 @@ void BossGanon_ChargeBigMagic(BossGanon* this, GlobalContext* globalCtx) {
}
if (this->timers[0] == 1) {
sCape->attachLeftArmTimer = 15.0f;
sBossGanonCape->attachLeftArmTimer = 15.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
}
@ -2174,7 +2167,7 @@ void BossGanon_ChargeBigMagic(BossGanon* this, GlobalContext* globalCtx) {
}
if (Animation_OnFrame(&this->skelAnime, 3.0f)) {
sCape->attachShouldersTimer = 26.0f;
sBossGanonCape->attachShouldersTimer = 26.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
}
@ -2202,7 +2195,7 @@ void BossGanon_SetupWait(BossGanon* this, GlobalContext* globalCtx) {
this->fwork[GDF_FWORK_0] = 0.0f;
this->timers[0] = (s16)Rand_ZeroFloat(64.0f) + 30;
this->unk_1C2 = 0;
sCape->minY = 2.0f;
sBossGanonCape->minY = 2.0f;
}
void BossGanon_Wait(BossGanon* this, GlobalContext* globalCtx) {
@ -2213,10 +2206,10 @@ void BossGanon_Wait(BossGanon* this, GlobalContext* globalCtx) {
this->legSwayEnabled = true;
sCape->backPush = -3.0f;
sCape->backSwayMagnitude = 0.25f;
sCape->sideSwayMagnitude = -3.0f;
sCape->minDist = 20.0f;
sBossGanonCape->backPush = -3.0f;
sBossGanonCape->backSwayMagnitude = 0.25f;
sBossGanonCape->sideSwayMagnitude = -3.0f;
sBossGanonCape->minDist = 20.0f;
SkelAnime_Update(&this->skelAnime);
@ -2271,10 +2264,10 @@ void BossGanon_SetupChargeLightBall(BossGanon* this, GlobalContext* globalCtx) {
void BossGanon_ChargeLightBall(BossGanon* this, GlobalContext* globalCtx) {
SkelAnime_Update(&this->skelAnime);
sCape->backPush = -3.0f;
sCape->backSwayMagnitude = 1.25f;
sCape->sideSwayMagnitude = -2.0f;
sCape->minDist = 10.0f;
sBossGanonCape->backPush = -3.0f;
sBossGanonCape->backSwayMagnitude = 1.25f;
sBossGanonCape->sideSwayMagnitude = -2.0f;
sBossGanonCape->minDist = 10.0f;
if (this->timers[0] < 17) {
this->envLightMode = 1;
@ -2355,7 +2348,7 @@ void BossGanon_PlayTennis(BossGanon* this, GlobalContext* globalCtx) {
rand = Rand_ZeroOne() * 1.99f;
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(volleyAnims[rand]);
Animation_MorphToPlayOnce(&this->skelAnime, volleyAnims[rand], 0.0f);
sCape->attachRightArmTimer = capeRightArmDurations[rand];
sBossGanonCape->attachRightArmTimer = capeRightArmDurations[rand];
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
this->startVolley = false;
}
@ -2383,7 +2376,7 @@ void BossGanon_SetupBlock(BossGanon* this, GlobalContext* globalCtx) {
}
this->unk_1C2 = 0;
sCape->attachLeftArmTimer = this->timers[0] = 10;
sBossGanonCape->attachLeftArmTimer = this->timers[0] = 10;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
this->handLightBallScale = 0.0f;
}
@ -2391,10 +2384,10 @@ void BossGanon_SetupBlock(BossGanon* this, GlobalContext* globalCtx) {
void BossGanon_Block(BossGanon* this, GlobalContext* globalCtx) {
this->collider.base.colType = 9;
SkelAnime_Update(&this->skelAnime);
sCape->backPush = -9.0f;
sCape->backSwayMagnitude = 0.25f;
sCape->sideSwayMagnitude = -2.0f;
sCape->minDist = 13.0f;
sBossGanonCape->backPush = -9.0f;
sBossGanonCape->backSwayMagnitude = 0.25f;
sBossGanonCape->sideSwayMagnitude = -2.0f;
sBossGanonCape->minDist = 13.0f;
if (this->unk_1C2 == 0) {
if (this->timers[0] == 0) {
@ -2402,11 +2395,11 @@ void BossGanon_Block(BossGanon* this, GlobalContext* globalCtx) {
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfBlockReleaseAnim, 0.0f);
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(&gDorfBlockReleaseAnim);
SkelAnime_Update(&this->skelAnime);
sCape->attachShouldersTimer = 15.0f;
sBossGanonCape->attachShouldersTimer = 15.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
}
} else {
sCape->sideSwayMagnitude = -13.0f;
sBossGanonCape->sideSwayMagnitude = -13.0f;
if (Animation_OnFrame(&this->skelAnime, this->fwork[GDF_FWORK_1])) {
BossGanon_SetupWait(this, globalCtx);
@ -2429,7 +2422,7 @@ void BossGanon_SetupHitByLightBall(BossGanon* this, GlobalContext* globalCtx) {
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(&gDorfBigMagicHitAnim);
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfBigMagicHitAnim, 0);
this->timers[0] = 70;
sCape->attachRightArmTimer = sCape->attachLeftArmTimer = 0;
sBossGanonCape->attachRightArmTimer = sBossGanonCape->attachLeftArmTimer = 0;
for (i = 1; i < 15; i++) {
this->unk_4E4[i] = D_808E4C58[i];
@ -2466,7 +2459,7 @@ void BossGanon_HitByLightBall(BossGanon* this, GlobalContext* globalCtx) {
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfGetUp3Anim, 0.0f);
this->unk_1C2 = 2;
SkelAnime_Update(&this->skelAnime);
sCape->attachShouldersTimer = 18.0f;
sBossGanonCape->attachShouldersTimer = 18.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_RESTORE);
this->timers[2] = 130;
@ -2500,7 +2493,7 @@ void BossGanon_SetupVulnerable(BossGanon* this, GlobalContext* globalCtx) {
BossGanon_SetAnimationObject(this, globalCtx, OBJECT_GANON_ANIME1);
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(&gDorfLightArrowHitAnim);
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfLightArrowHitAnim, 0.0f);
sCape->attachRightArmTimer = sCape->attachLeftArmTimer = 0;
sBossGanonCape->attachRightArmTimer = sBossGanonCape->attachLeftArmTimer = 0;
this->actionFunc = BossGanon_Vulnerable;
this->actor.velocity.x = 0.0f;
@ -2508,10 +2501,10 @@ void BossGanon_SetupVulnerable(BossGanon* this, GlobalContext* globalCtx) {
this->actor.velocity.z = 0.0f;
this->unk_1C2 = 0;
sCape->backPush = -4.0f;
sCape->backSwayMagnitude = 0.75f;
sCape->sideSwayMagnitude = -3.0f;
sCape->minDist = 20.0f;
sBossGanonCape->backPush = -4.0f;
sBossGanonCape->backSwayMagnitude = 0.75f;
sBossGanonCape->sideSwayMagnitude = -3.0f;
sBossGanonCape->minDist = 20.0f;
for (i = 0; i < 10; i++) {
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_BOSS_GANON, this->unk_1FC.x,
@ -2571,7 +2564,7 @@ void BossGanon_Vulnerable(BossGanon* this, GlobalContext* globalCtx) {
break;
case 2:
sCape->minDist = 0.0f;
sBossGanonCape->minDist = 0.0f;
this->actor.velocity.y = this->actor.velocity.y - 0.5f;
if (this->actor.world.pos.y < 40.0f) {
@ -2625,7 +2618,7 @@ void BossGanon_Vulnerable(BossGanon* this, GlobalContext* globalCtx) {
this->unk_1C2 = 6;
this->fwork[GDF_FWORK_1] = Animation_GetLastFrame(&gDorfGetUp2Anim);
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfGetUp2Anim, 0.0f);
sCape->minDist = 20.0f;
sBossGanonCape->minDist = 20.0f;
this->unk_19F = 1;
}
break;
@ -2646,7 +2639,7 @@ void BossGanon_Vulnerable(BossGanon* this, GlobalContext* globalCtx) {
Animation_MorphToPlayOnce(&this->skelAnime, &gDorfGetUp3Anim, 0.0f);
this->unk_1C2 = 8;
SkelAnime_Update(&this->skelAnime);
sCape->attachShouldersTimer = 18.0f;
sBossGanonCape->attachShouldersTimer = 18.0f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_MANTLE);
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_RESTORE);
break;
@ -2743,10 +2736,10 @@ void BossGanon_UpdateDamage(BossGanon* this, GlobalContext* globalCtx) {
this->actor.colChkInfo.health -= damage;
}
for (i = 0; i < ARRAY_COUNT(sCape->strands); i++) {
for (i = 0; i < ARRAY_COUNT(sBossGanonCape->strands); i++) {
for (j = 1; j < 12; j++) {
sCape->strands[i].velocities[j].x = Rand_CenteredFloat(15.0f);
sCape->strands[i].velocities[j].z = Rand_CenteredFloat(15.0f);
sBossGanonCape->strands[i].velocities[j].x = Rand_CenteredFloat(15.0f);
sBossGanonCape->strands[i].velocities[j].z = Rand_CenteredFloat(15.0f);
}
}
@ -2762,16 +2755,16 @@ void BossGanon_UpdateDamage(BossGanon* this, GlobalContext* globalCtx) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_CUTBODY);
BossGanon_SetupDamaged(this, globalCtx);
this->unk_1A6 = 15;
sCape->tearTimer = 1;
sBossGanonCape->tearTimer = 1;
}
}
} else if (acHitInfo->toucher.dmgFlags & 0x1F8A4) {
Audio_PlayActorSound2(&this->actor, 0);
for (i = 0; i < ARRAY_COUNT(sCape->strands); i++) {
for (i = 0; i < ARRAY_COUNT(sBossGanonCape->strands); i++) {
for (j = 1; j < 12; j++) {
sCape->strands[i].velocities[j].x = Rand_CenteredFloat(15.0f);
sCape->strands[i].velocities[j].z = Rand_CenteredFloat(15.0f);
sBossGanonCape->strands[i].velocities[j].x = Rand_CenteredFloat(15.0f);
sBossGanonCape->strands[i].velocities[j].z = Rand_CenteredFloat(15.0f);
}
}
}
@ -2841,7 +2834,7 @@ void BossGanon_Update(Actor* thisx, GlobalContext* globalCtx2) {
}
this->collider.base.colType = 3;
sCape->gravity = -3.0f;
sBossGanonCape->gravity = -3.0f;
this->shockGlow = false;
this->actor.flags &= ~ACTOR_FLAG_0;
this->unk_1A2++;
@ -3334,20 +3327,20 @@ void BossGanon_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList
}
void BossGanon_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) {
sSeed1 = seedInit0;
sSeed2 = seedInit1;
sSeed3 = seedInit2;
sBossGanonSeed1 = seedInit0;
sBossGanonSeed2 = seedInit1;
sBossGanonSeed3 = seedInit2;
}
f32 BossGanon_RandZeroOne(void) {
// Wichmann-Hill algorithm
f32 randFloat;
sSeed1 = (sSeed1 * 171) % 30269;
sSeed2 = (sSeed2 * 172) % 30307;
sSeed3 = (sSeed3 * 170) % 30323;
sBossGanonSeed1 = (sBossGanonSeed1 * 171) % 30269;
sBossGanonSeed2 = (sBossGanonSeed2 * 172) % 30307;
sBossGanonSeed3 = (sBossGanonSeed3 * 170) % 30323;
randFloat = (sSeed1 / 30269.0f) + (sSeed2 / 30307.0f) + (sSeed3 / 30323.0f);
randFloat = (sBossGanonSeed1 / 30269.0f) + (sBossGanonSeed2 / 30307.0f) + (sBossGanonSeed3 / 30323.0f);
while (randFloat >= 1.0f) {
randFloat -= 1.0f;
@ -3559,7 +3552,7 @@ void BossGanon_DrawTriforce(BossGanon* this, GlobalContext* globalCtx) {
this->triforcePos.y += 3.0f;
this->triforcePos.z += -2.0f;
} else if (this->triforceType == GDF_TRIFORCE_ZELDA) {
this->triforcePos = sZelda->unk_31C;
this->triforcePos = sBossGanonZelda->unk_31C;
this->triforcePos.y += 1.8f;
this->triforcePos.z += 4.0f;
@ -3734,9 +3727,9 @@ void BossGanon_GenShadowTexture(u8* tex, BossGanon* this, GlobalContext* globalC
for (i = 0; i < 12; i++) {
for (j = 0; j < 12; j++) {
sp7C.x = sCape->strands[i].joints[j].x - this->actor.world.pos.x;
sp7C.y = sCape->strands[i].joints[j].y - this->actor.world.pos.y + 76.0f + 100.0f + 30.0f;
sp7C.z = sCape->strands[i].joints[j].z - this->actor.world.pos.z;
sp7C.x = sBossGanonCape->strands[i].joints[j].x - this->actor.world.pos.x;
sp7C.y = sBossGanonCape->strands[i].joints[j].y - this->actor.world.pos.y + 76.0f + 100.0f + 30.0f;
sp7C.z = sBossGanonCape->strands[i].joints[j].z - this->actor.world.pos.z;
Matrix_MultVec3f(&sp7C, &sp70);
@ -3746,7 +3739,7 @@ void BossGanon_GenShadowTexture(u8* tex, BossGanon* this, GlobalContext* globalC
baseX = (s32)(sp70.x + 32.0f);
baseY = (s16)sp70.y * 0x40;
if (!sCape->strands[i].torn[j]) {
if (!sBossGanonCape->strands[i].torn[j]) {
for (y = -1, addY = -0x40; y <= 1; y++, addY += 0x40) {
for (x = -3; x <= 3; x++) {
index = baseX + x + baseY + addY;
@ -3827,13 +3820,13 @@ void BossGanon_Draw(Actor* thisx, GlobalContext* globalCtx) {
BossGanon_DrawEffects(globalCtx);
sCape->actor.world.pos = this->actor.world.pos;
sBossGanonCape->actor.world.pos = this->actor.world.pos;
sCape->rightForearmPos = this->unk_214;
sCape->leftForearmPos = this->unk_220;
sBossGanonCape->rightForearmPos = this->unk_214;
sBossGanonCape->leftForearmPos = this->unk_220;
sCape->rightShoulderPos = this->unk_22C;
sCape->leftShoulderPos = this->unk_238;
sBossGanonCape->rightShoulderPos = this->unk_22C;
sBossGanonCape->leftShoulderPos = this->unk_238;
BossGanon_DrawShock(this, globalCtx);
BossGanon_DrawHandLightBall(this, globalCtx);
@ -4628,7 +4621,7 @@ void BossGanon_UpdateEffects(GlobalContext* globalCtx) {
spA0.x = 0.0f;
spA0.y = 0.0f;
for (i = 0; i < ARRAY_COUNT(sEffectBuf); i++, eff++) {
for (i = 0; i < ARRAY_COUNT(sBossGanonEffectBuf); i++, eff++) {
if (eff->type != GDF_EFF_NONE) {
eff->pos.x += eff->velocity.x;
eff->pos.y += eff->velocity.y;
@ -4662,9 +4655,9 @@ void BossGanon_UpdateEffects(GlobalContext* globalCtx) {
eff->alpha = 255;
}
} else if (eff->type == GDF_EFF_BLACK_DOT) {
xDiff = sGanondorf->unk_278.x - eff->pos.x;
yDiff = sGanondorf->unk_278.y - eff->pos.y;
zDiff = sGanondorf->unk_278.z - eff->pos.z;
xDiff = sBossGanonGanondorf->unk_278.x - eff->pos.x;
yDiff = sBossGanonGanondorf->unk_278.y - eff->pos.y;
zDiff = sBossGanonGanondorf->unk_278.z - eff->pos.z;
yRot = Math_FAtan2F(xDiff, zDiff);
@ -4704,9 +4697,9 @@ void BossGanon_UpdateEffects(GlobalContext* globalCtx) {
if (eff->unk_2E == GDF_SHOCK_DORF_YELLOW) {
bodyPart = (s16)Rand_ZeroFloat(13.9f) + 1;
eff->pos.x = sGanondorf->unk_2EC[bodyPart].x + Rand_CenteredFloat(20.0f);
eff->pos.y = sGanondorf->unk_2EC[bodyPart].y + Rand_CenteredFloat(20.0f);
eff->pos.z = sGanondorf->unk_2EC[bodyPart].z + Rand_CenteredFloat(20.0f);
eff->pos.x = sBossGanonGanondorf->unk_2EC[bodyPart].x + Rand_CenteredFloat(20.0f);
eff->pos.y = sBossGanonGanondorf->unk_2EC[bodyPart].y + Rand_CenteredFloat(20.0f);
eff->pos.z = sBossGanonGanondorf->unk_2EC[bodyPart].z + Rand_CenteredFloat(20.0f);
} else {
bodyPart = (s16)Rand_ZeroFloat(17.9f);
@ -4799,7 +4792,7 @@ void BossGanon_UpdateEffects(GlobalContext* globalCtx) {
if (((eff->scale * 150.0f) < distToPlayer) && (distToPlayer < (eff->scale * 300.0f))) {
eff->timer = 150;
func_8002F6D4(globalCtx, &sGanondorf->actor, 7.0f, sGanondorf->actor.yawTowardsPlayer, 0.0f,
func_8002F6D4(globalCtx, &sBossGanonGanondorf->actor, 7.0f, sBossGanonGanondorf->actor.yawTowardsPlayer, 0.0f,
0x20);
}
}
@ -4838,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);
@ -4855,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();
}
}
@ -4863,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);
@ -4877,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();
}
}
@ -4885,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);
@ -4901,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();
}
}
@ -4909,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) {
@ -4927,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();
}
}
@ -4934,13 +4935,14 @@ 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],
255);
gDPSetEnvColor(POLY_XLU_DISP++, sLightningEnvColors[(eff->timer * 3) + 0],
sLightningEnvColors[(eff->timer * 3) + 1], sLightningEnvColors[(eff->timer * 3) + 2], 0);
Matrix_Translate(sGanondorf->unk_260.x, sGanondorf->unk_260.y, sGanondorf->unk_260.z, MTXMODE_NEW);
Matrix_Translate(sBossGanonGanondorf->unk_260.x, sBossGanonGanondorf->unk_260.y, sBossGanonGanondorf->unk_260.z, MTXMODE_NEW);
Matrix_RotateY(eff->unk_48, MTXMODE_APPLY);
Matrix_RotateZ(eff->unk_3C, MTXMODE_APPLY);
Matrix_Scale(eff->scale, eff->scale, eff->scale, MTXMODE_APPLY);
@ -4949,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();
}
}
@ -4956,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);
@ -4967,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();
}
}
@ -4974,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);
@ -4985,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();
}
}
@ -4992,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);
@ -5004,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();
}
}
@ -5011,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);
@ -5023,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();
}
}
@ -5032,16 +5043,11 @@ void BossGanon_DrawEffects(GlobalContext* globalCtx) {
#include "overlays/ovl_Boss_Ganon/ovl_Boss_Ganon.h"
void BossGanon_Reset(void) {
static EnGanonMant* sCape;
sSeed1 = 0;
sSeed2 = 0;
sSeed3 = 0;
sGanondorf = NULL;
sZelda = NULL;
sCape = NULL;
memset(sEffectBuf, 0, sizeof(sEffectBuf));
}
sBossGanonSeed1 = 0;
sBossGanonSeed2 = 0;
sBossGanonSeed3 = 0;
sBossGanonGanondorf = NULL;
sBossGanonZelda = NULL;
sBossGanonCape = NULL;
memset(sBossGanonEffectBuf, 0, sizeof(sBossGanonEffectBuf));
}

View file

@ -53,6 +53,25 @@ typedef enum {
/* 2 */ GDF_TRIFORCE_DORF
} GanondorfTriforceType;
typedef struct {
/* 0x00 */ u8 type;
/* 0x01 */ u8 timer;
/* 0x04 */ Vec3f pos;
/* 0x10 */ Vec3f velocity;
/* 0x1C */ Vec3f accel;
/* 0x28 */ Color_RGB8 color;
/* 0x2C */ s16 alpha;
/* 0x2E */ s16 unk_2E;
/* 0x30 */ s16 unk_30;
/* 0x34 */ f32 scale;
/* 0x38 */ f32 unk_38; // scale target mostly, but used for other things
/* 0x3C */ f32 unk_3C; // mostly z rot
/* 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 {
/* 0x0000 */ Actor actor;
/* 0x014C */ s32 animBankIndex;

View file

@ -49,21 +49,40 @@ const ActorInit Boss_Ganon2_InitVars = {
#include "z_boss_ganon2_data.c"
Vec3f D_8090EB20;
EnZl3* sBossGanon2Zelda;
Actor* D_8090EB30;
BossGanon2Effect sBossGanon2Particles[100];
s32 sBossGanon2Seed1;
s32 sBossGanon2Seed2;
s32 sBossGanon2Seed3;
Vec3f D_809105D8[4];
Vec3f D_80910608[4];
s8 D_80910638;
void BossGanon2_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) {
sSeed1 = seedInit0;
sSeed2 = seedInit1;
sSeed3 = seedInit2;
sBossGanon2Seed1 = seedInit0;
sBossGanon2Seed2 = seedInit1;
sBossGanon2Seed3 = seedInit2;
}
f32 BossGanon2_RandZeroOne(void) {
// Wichmann-Hill algorithm
f32 randFloat;
sSeed1 = (sSeed1 * 171) % 30269;
sSeed2 = (sSeed2 * 172) % 30307;
sSeed3 = (sSeed3 * 170) % 30323;
sBossGanon2Seed1 = (sBossGanon2Seed1 * 171) % 30269;
sBossGanon2Seed2 = (sBossGanon2Seed2 * 172) % 30307;
sBossGanon2Seed3 = (sBossGanon2Seed3 * 170) % 30323;
randFloat = (sSeed1 / 30269.0f) + (sSeed2 / 30307.0f) + (sSeed3 / 30323.0f);
randFloat = (sBossGanon2Seed1 / 30269.0f) + (sBossGanon2Seed2 / 30307.0f) + (sBossGanon2Seed3 / 30323.0f);
while (randFloat >= 1.0f) {
randFloat -= 1.0f;
}
@ -114,7 +133,7 @@ void func_808FD27C(GlobalContext* globalCtx, Vec3f* position, Vec3f* velocity, f
BossGanon2Effect* effect = globalCtx->specialEffects;
s16 i;
for (i = 0; i < ARRAY_COUNT(sParticles); i++, effect++) {
for (i = 0; i < ARRAY_COUNT(sBossGanon2Particles); i++, effect++) {
if (effect->type == 0) {
effect->type = 2;
effect->position = *position;
@ -136,10 +155,10 @@ void BossGanon2_Init(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
s16 i;
globalCtx->specialEffects = sParticles;
globalCtx->specialEffects = sBossGanon2Particles;
for (i = 0; i < ARRAY_COUNT(sParticles); i++) {
sParticles[i].type = 0;
for (i = 0; i < ARRAY_COUNT(sBossGanon2Particles); i++) {
sBossGanon2Particles[i].type = 0;
}
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
@ -204,13 +223,13 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_WAIT);
Gameplay_ChangeCameraStatus(globalCtx, this->unk_39E, CAM_STAT_ACTIVE);
this->unk_39C = 1;
sZelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 970.0f,
sBossGanon2Zelda = (EnZl3*)Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ZL3, 970.0f,
1086.0f, -200.0f, 0, 0, 0, 1);
sZelda->unk_3C8 = 0;
sZelda->actor.world.pos.x = 970.0f;
sZelda->actor.world.pos.y = 1086.0f;
sZelda->actor.world.pos.z = -214.0f;
sZelda->actor.shape.rot.y = -0x7000;
sBossGanon2Zelda->unk_3C8 = 0;
sBossGanon2Zelda->actor.world.pos.x = 970.0f;
sBossGanon2Zelda->actor.world.pos.y = 1086.0f;
sBossGanon2Zelda->actor.world.pos.z = -214.0f;
sBossGanon2Zelda->actor.shape.rot.y = -0x7000;
this->unk_3BC.x = 0.0f;
this->unk_3BC.y = 1.0f;
this->unk_3BC.z = 0.0f;
@ -258,20 +277,20 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
player->actor.world.pos.x = 970.0f;
player->actor.world.pos.y = 1086.0f;
player->actor.world.pos.z = -166.0f;
sZelda->actor.world.pos.x = 974.0f;
sZelda->actor.world.pos.y = 1086.0f;
sZelda->actor.world.pos.z = -186.0f;
sBossGanon2Zelda->actor.world.pos.x = 974.0f;
sBossGanon2Zelda->actor.world.pos.y = 1086.0f;
sBossGanon2Zelda->actor.world.pos.z = -186.0f;
player->actor.shape.rot.y = -0x5000;
sZelda->actor.shape.rot.y = -0x5000;
sBossGanon2Zelda->actor.shape.rot.y = -0x5000;
if (this->unk_398 == 60) {
Message_StartTextbox(globalCtx, 0x70D4, NULL);
}
if (this->unk_398 == 40) {
sZelda->unk_3C8 = 1;
sBossGanon2Zelda->unk_3C8 = 1;
func_8002DF54(globalCtx, &this->actor, 0x4E);
}
if (this->unk_398 == 85) {
sZelda->unk_3C8 = 2;
sBossGanon2Zelda->unk_3C8 = 2;
func_8002DF54(globalCtx, &this->actor, 0x4F);
}
this->unk_3A4.x = 930.0f;
@ -300,14 +319,14 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_STOP);
}
if (this->unk_398 == 20) {
sZelda->unk_3C8 = 3;
sBossGanon2Zelda->unk_3C8 = 3;
func_8002DF54(globalCtx, &this->actor, 0x50);
}
if (this->unk_398 == 55) {
this->unk_39C = 4;
this->unk_398 = 0;
this->unk_410.x = 0.0f;
sZelda->unk_3C8 = 4;
sBossGanon2Zelda->unk_3C8 = 4;
func_8002DF54(globalCtx, &this->actor, 0x50);
}
break;
@ -347,11 +366,11 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
player->actor.world.pos.x = 490.0f;
player->actor.world.pos.y = 1086.0f;
player->actor.world.pos.z = -166.0f;
sZelda->actor.world.pos.x = 724.0f;
sZelda->actor.world.pos.y = 1086.0f;
sZelda->actor.world.pos.z = -186.0f;
sBossGanon2Zelda->actor.world.pos.x = 724.0f;
sBossGanon2Zelda->actor.world.pos.y = 1086.0f;
sBossGanon2Zelda->actor.world.pos.z = -186.0f;
player->actor.shape.rot.y = -0x4000;
sZelda->actor.shape.rot.y = -0x5000;
sBossGanon2Zelda->actor.shape.rot.y = -0x5000;
this->unk_3A4.x = 410.0f;
this->unk_3A4.y = 1096.0f;
this->unk_3A4.z = -110.0f;
@ -370,7 +389,7 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
this->unk_339 = 4;
}
if (this->unk_398 == 30) {
sZelda->unk_3C8 = 5;
sBossGanon2Zelda->unk_3C8 = 5;
func_8002DF54(globalCtx, &this->actor, 0x51);
}
if (this->unk_398 == 50) {
@ -384,11 +403,11 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
player->actor.world.pos.x = 490.0f;
player->actor.world.pos.y = 1086.0f;
player->actor.world.pos.z = -166.0f;
sZelda->actor.world.pos.x = 724.0f;
sZelda->actor.world.pos.y = 1086.0f;
sZelda->actor.world.pos.z = -186.0f;
sBossGanon2Zelda->actor.world.pos.x = 724.0f;
sBossGanon2Zelda->actor.world.pos.y = 1086.0f;
sBossGanon2Zelda->actor.world.pos.z = -186.0f;
player->actor.shape.rot.y = -0x4000;
sZelda->actor.shape.rot.y = -0x5000;
sBossGanon2Zelda->actor.shape.rot.y = -0x5000;
this->unk_3A4.x = 450.0f;
this->unk_3A4.y = 1121.0f;
this->unk_3A4.z = -158.0f;
@ -457,9 +476,9 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
player->actor.world.pos.y = 1086.0f;
player->actor.world.pos.z = -266.0f;
player->actor.shape.rot.y = -0x4000;
sZelda->actor.world.pos.x = 724.0f;
sZelda->actor.world.pos.y = 1086.0f;
sZelda->actor.world.pos.z = -186.0f;
sBossGanon2Zelda->actor.world.pos.x = 724.0f;
sBossGanon2Zelda->actor.world.pos.y = 1086.0f;
sBossGanon2Zelda->actor.world.pos.z = -186.0f;
this->unk_3A4.x = this->actor.world.pos.x + -10.0f;
this->unk_3A4.y = this->actor.world.pos.y + 80.0f;
this->unk_3A4.z = this->actor.world.pos.z + 50.0f;
@ -770,9 +789,9 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
BossGanon2Effect* effect = globalCtx->specialEffects;
effect->unk_2E = 1;
effect->position.x = sZelda->actor.world.pos.x + 50.0f + 10.0f;
effect->position.y = sZelda->actor.world.pos.y + 350.0f;
effect->position.z = sZelda->actor.world.pos.z - 25.0f;
effect->position.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f;
effect->position.y = sBossGanon2Zelda->actor.world.pos.y + 350.0f;
effect->position.z = sBossGanon2Zelda->actor.world.pos.z - 25.0f;
effect->velocity.x = 0.0f;
effect->velocity.z = 0.0f;
effect->velocity.y = -30.0f;
@ -782,15 +801,15 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
break;
}
case 26:
this->unk_3A4.x = sZelda->actor.world.pos.x + 100.0f + 30.0f;
this->unk_3A4.y = sZelda->actor.world.pos.y + 10.0f;
this->unk_3A4.z = sZelda->actor.world.pos.z + 5.0f;
this->unk_3B0.x = sZelda->actor.world.pos.x;
this->unk_3B0.y = sZelda->actor.world.pos.y + 30.0f;
this->unk_3B0.z = sZelda->actor.world.pos.z - 20.0f;
this->unk_3A4.x = sBossGanon2Zelda->actor.world.pos.x + 100.0f + 30.0f;
this->unk_3A4.y = sBossGanon2Zelda->actor.world.pos.y + 10.0f;
this->unk_3A4.z = sBossGanon2Zelda->actor.world.pos.z + 5.0f;
this->unk_3B0.x = sBossGanon2Zelda->actor.world.pos.x;
this->unk_3B0.y = sBossGanon2Zelda->actor.world.pos.y + 30.0f;
this->unk_3B0.z = sBossGanon2Zelda->actor.world.pos.z - 20.0f;
this->unk_3BC.z = -0.5f;
if (this->unk_398 == 13) {
sZelda->unk_3C8 = 6;
sBossGanon2Zelda->unk_3C8 = 6;
}
if (this->unk_398 == 50) {
this->unk_39C = 27;
@ -879,7 +898,7 @@ void func_808FD5F4(BossGanon2* this, GlobalContext* globalCtx) {
func_808FFDB0(this, globalCtx);
this->unk_1A2[1] = 50;
this->actor.flags |= ACTOR_FLAG_0;
sZelda->unk_3C8 = 7;
sBossGanon2Zelda->unk_3C8 = 7;
}
break;
}
@ -1323,12 +1342,12 @@ void func_80900890(BossGanon2* this, GlobalContext* globalCtx) {
break;
case 2:
this->unk_1A2[0] = 300;
this->unk_3A4.x = sZelda->actor.world.pos.x - 100.0f;
this->unk_3A4.y = sZelda->actor.world.pos.y + 30.0f;
this->unk_3A4.z = (sZelda->actor.world.pos.z + 30.0f) - 60.0f;
this->unk_3B0.x = sZelda->actor.world.pos.x;
this->unk_3B0.y = sZelda->actor.world.pos.y + 30.0f;
this->unk_3B0.z = sZelda->actor.world.pos.z - 10.0f;
this->unk_3A4.x = sBossGanon2Zelda->actor.world.pos.x - 100.0f;
this->unk_3A4.y = sBossGanon2Zelda->actor.world.pos.y + 30.0f;
this->unk_3A4.z = (sBossGanon2Zelda->actor.world.pos.z + 30.0f) - 60.0f;
this->unk_3B0.x = sBossGanon2Zelda->actor.world.pos.x;
this->unk_3B0.y = sBossGanon2Zelda->actor.world.pos.y + 30.0f;
this->unk_3B0.z = sBossGanon2Zelda->actor.world.pos.z - 10.0f;
Math_ApproachZeroF(&this->unk_324, 1.0f, 5.0f);
Math_ApproachF(&globalCtx->envCtx.unk_D8, 1.0f, 1.0f, 1.0f / 51);
if (this->unk_1A2[1] == 80) {
@ -1356,8 +1375,8 @@ void func_80900890(BossGanon2* this, GlobalContext* globalCtx) {
func_8002DF54(globalCtx, &this->actor, 0x60);
this->unk_398 = 0;
case 11:
player->actor.world.pos.x = sZelda->actor.world.pos.x + 50.0f + 10.0f;
player->actor.world.pos.z = sZelda->actor.world.pos.z - 25.0f;
player->actor.world.pos.x = sBossGanon2Zelda->actor.world.pos.x + 50.0f + 10.0f;
player->actor.world.pos.z = sBossGanon2Zelda->actor.world.pos.z - 25.0f;
player->actor.shape.rot.y = -0x8000;
this->unk_3A4.x = (player->actor.world.pos.x + 100.0f) - 80.0f;
this->unk_3A4.y = (player->actor.world.pos.y + 60.0f) - 40.0f;
@ -1482,7 +1501,7 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
func_8002DF54(globalCtx, &this->actor, 8);
this->unk_39C = 1;
this->unk_398 = 0;
sZelda->unk_3C8 = 9;
sBossGanon2Zelda->unk_3C8 = 9;
this->unk_31C = 0;
this->unk_1A2[2] = 0;
this->unk_336 = 0;
@ -1522,9 +1541,9 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
player->actor.shape.rot.y = -0x4000;
player->actor.world.pos.x = 200.0f;
player->actor.world.pos.z = 30.0f;
sZelda->actor.world.pos.x = 340.0f;
sZelda->actor.world.pos.z = -250.0f;
sZelda->actor.world.rot.y = sZelda->actor.shape.rot.y = -0x2000;
sBossGanon2Zelda->actor.world.pos.x = 340.0f;
sBossGanon2Zelda->actor.world.pos.z = -250.0f;
sBossGanon2Zelda->actor.world.rot.y = sBossGanon2Zelda->actor.shape.rot.y = -0x2000;
this->unk_3A4.x = 250;
this->unk_3A4.y = 1150.0f;
this->unk_3A4.z = 0.0f;
@ -1543,9 +1562,9 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
this->unk_3A4.x = 250;
this->unk_3A4.y = 1150.0f;
this->unk_3A4.z = 0.0f;
Math_ApproachF(&this->unk_3B0.x, sZelda->actor.world.pos.x, 0.2f, 20.0f);
Math_ApproachF(&this->unk_3B0.y, sZelda->actor.world.pos.y + 50.0f, 0.2f, 10.0f);
Math_ApproachF(&this->unk_3B0.z, sZelda->actor.world.pos.z, 0.2f, 20.0f);
Math_ApproachF(&this->unk_3B0.x, sBossGanon2Zelda->actor.world.pos.x, 0.2f, 20.0f);
Math_ApproachF(&this->unk_3B0.y, sBossGanon2Zelda->actor.world.pos.y + 50.0f, 0.2f, 10.0f);
Math_ApproachF(&this->unk_3B0.z, sBossGanon2Zelda->actor.world.pos.z, 0.2f, 20.0f);
if (this->unk_398 == 50) {
this->unk_39C = 3;
this->unk_398 = 0;
@ -1557,9 +1576,9 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
this->unk_3A4.x = 330.0f;
this->unk_3A4.y = 1120.0f;
this->unk_3A4.z = -150.0f;
this->unk_3B0.x = sZelda->actor.world.pos.x;
this->unk_3B0.y = sZelda->actor.world.pos.y + 40.0f;
this->unk_3B0.z = sZelda->actor.world.pos.z;
this->unk_3B0.x = sBossGanon2Zelda->actor.world.pos.x;
this->unk_3B0.y = sBossGanon2Zelda->actor.world.pos.y + 40.0f;
this->unk_3B0.z = sBossGanon2Zelda->actor.world.pos.z;
if (this->unk_398 == 10) {
Message_StartTextbox(globalCtx, 0x70D8, NULL);
}
@ -1572,7 +1591,7 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
if (this->unk_398 > 10) {
Math_ApproachZeroF(&this->unk_37C, 1.0f, 10.0f);
if (this->unk_398 == 30) {
sZelda->unk_3C8 = 10;
sBossGanon2Zelda->unk_3C8 = 10;
}
this->unk_339 = 23;
Math_ApproachZeroF(&globalCtx->envCtx.unk_D8, 1.0f, 0.05f);
@ -1743,7 +1762,7 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
if (this->unk_398 == 40) {
this->unk_39C = 9;
this->unk_398 = 0;
sZelda->unk_3C8 = 11;
sBossGanon2Zelda->unk_3C8 = 11;
Message_StartTextbox(globalCtx, 0x70D9, NULL);
this->unk_336 = 0;
globalCtx->envCtx.unk_D8 = 0.0f;
@ -1754,9 +1773,9 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
this->unk_3A4.x = 330.0f;
this->unk_3A4.y = 1120.0f;
this->unk_3A4.z = -150.0f;
this->unk_3B0.x = sZelda->actor.world.pos.x;
this->unk_3B0.y = sZelda->actor.world.pos.y + 40.0f;
this->unk_3B0.z = sZelda->actor.world.pos.z;
this->unk_3B0.x = sBossGanon2Zelda->actor.world.pos.x;
this->unk_3B0.y = sBossGanon2Zelda->actor.world.pos.y + 40.0f;
this->unk_3B0.z = sBossGanon2Zelda->actor.world.pos.z;
if (this->unk_398 > 60) {
this->unk_39C = 10;
this->unk_398 = 0;
@ -1771,26 +1790,26 @@ void func_8090120C(BossGanon2* this, GlobalContext* globalCtx) {
if ((this->unk_398 >= 40) && (this->unk_398 <= 110)) {
Math_ApproachF(&globalCtx->envCtx.unk_D8, 1.0f, 1.0f, 0.02f);
Math_ApproachF(&this->unk_384, 10.0f, 0.1f, 0.2f);
Audio_PlayActorSound2(&sZelda->actor, NA_SE_EV_GOD_LIGHTBALL_2 - SFX_FLAG);
Audio_PlayActorSound2(&sBossGanon2Zelda->actor, NA_SE_EV_GOD_LIGHTBALL_2 - SFX_FLAG);
} else {
Math_ApproachZeroF(&this->unk_384, 1.0f, 0.2f);
}
if (this->unk_398 > 130) {
Math_ApproachF(&this->unk_3B0.y, (sZelda->actor.world.pos.y + 40.0f + 10.0f) - 20.0f, 0.1f,
Math_ApproachF(&this->unk_3B0.y, (sBossGanon2Zelda->actor.world.pos.y + 40.0f + 10.0f) - 20.0f, 0.1f,
this->unk_410.x);
} else {
Math_ApproachF(&this->unk_3B0.y, sZelda->actor.world.pos.y + 40.0f + 10.0f, 0.05f,
Math_ApproachF(&this->unk_3B0.y, sBossGanon2Zelda->actor.world.pos.y + 40.0f + 10.0f, 0.05f,
this->unk_410.x * 0.25f);
}
Math_ApproachF(&this->unk_410.x, 1.0f, 1.0f, 0.01f);
if (this->unk_398 == 10) {
sZelda->unk_3C8 = 12;
sBossGanon2Zelda->unk_3C8 = 12;
}
if (this->unk_398 == 110) {
sZelda->unk_3C8 = 13;
sBossGanon2Zelda->unk_3C8 = 13;
}
if (this->unk_398 == 140) {
Audio_PlayActorSound2(&sZelda->actor, NA_SE_EV_HUMAN_BOUND);
Audio_PlayActorSound2(&sBossGanon2Zelda->actor, NA_SE_EV_HUMAN_BOUND);
}
if (this->unk_398 < 160) {
break;
@ -1845,7 +1864,7 @@ void func_80902348(BossGanon2* this, GlobalContext* globalCtx) {
}
func_8002F6D4(globalCtx, &this->actor, 15.0f, this->actor.yawTowardsPlayer + phi_v0_2, 2.0f, 0);
sZelda->unk_3C8 = 8;
sBossGanon2Zelda->unk_3C8 = 8;
this->unk_316 = 10;
break;
}
@ -1864,7 +1883,7 @@ void func_80902348(BossGanon2* this, GlobalContext* globalCtx) {
player->isBurning = true;
func_8002F6D4(globalCtx, &this->actor, 10.0f, Math_Atan2S(temp_f12, temp_f2), 0.0f, 0x10);
sZelda->unk_3C8 = 8;
sBossGanon2Zelda->unk_3C8 = 8;
}
}
}
@ -2168,7 +2187,7 @@ void BossGanon2_Update(Actor* thisx, GlobalContext* globalCtx) {
if (D_80906D78 != 0) {
D_80906D78 = 0;
for (i2 = 0; i2 < ARRAY_COUNT(sParticles); i2++) {
for (i2 = 0; i2 < ARRAY_COUNT(sBossGanon2Particles); i2++) {
angle = Rand_ZeroFloat(2 * M_PI);
sp44 = Rand_ZeroFloat(40.0f) + 10.0f;
sp58 = this->actor.world.pos;
@ -2641,7 +2660,7 @@ void func_80904FC8(BossGanon2* this, GlobalContext* globalCtx) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 200);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 200, 0, 0);
gSPDisplayList(POLY_XLU_DISP++, ovl_Boss_Ganon2_DL_00B308);
Matrix_Translate(sZelda->actor.world.pos.x, sZelda->actor.world.pos.y + 80.0f, sZelda->actor.world.pos.z,
Matrix_Translate(sBossGanon2Zelda->actor.world.pos.x, sBossGanon2Zelda->actor.world.pos.y + 80.0f, sBossGanon2Zelda->actor.world.pos.z,
MTXMODE_NEW);
Matrix_ReplaceRotation(&globalCtx->billboardMtxF);
Matrix_Scale(this->unk_384, this->unk_384, this->unk_384, MTXMODE_APPLY);
@ -2728,8 +2747,8 @@ void func_80905674(BossGanon2* this, GlobalContext* globalCtx) {
this->unk_19C * -8, 32, 32));
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 170, (s16)this->unk_37C);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 200, 0, 128);
Matrix_Translate(sZelda->actor.world.pos.x + 100.0f, sZelda->actor.world.pos.y + 35.0f + 7.0f,
sZelda->actor.world.pos.z - 100.0f, MTXMODE_NEW);
Matrix_Translate(sBossGanon2Zelda->actor.world.pos.x + 100.0f, sBossGanon2Zelda->actor.world.pos.y + 35.0f + 7.0f,
sBossGanon2Zelda->actor.world.pos.z - 100.0f, MTXMODE_NEW);
Matrix_RotateY(-M_PI / 4.0f, MTXMODE_APPLY);
Matrix_Scale(0.040000003f, 0.040000003f, this->unk_380, MTXMODE_APPLY);
Matrix_RotateX(M_PI / 2.0f, MTXMODE_APPLY);
@ -2826,7 +2845,7 @@ void func_80905DA8(BossGanon2* this, GlobalContext* globalCtx) {
Vec3f sp78;
s16 i;
for (i = 0; i < ARRAY_COUNT(sParticles); i++, effect++) {
for (i = 0; i < ARRAY_COUNT(sBossGanon2Particles); i++, effect++) {
if (effect->type != 0) {
effect->position.x += effect->velocity.x;
effect->position.y += effect->velocity.y;
@ -2934,7 +2953,7 @@ void func_809060E8(GlobalContext* globalCtx) {
effect = effects;
for (i = 0; i < ARRAY_COUNT(sParticles); i++, effect++) {
for (i = 0; i < ARRAY_COUNT(sBossGanon2Particles); i++, effect++) {
if (effect->type == 2) {
if (!usingObjectGEff) {
BossGanon2_SetObjectSegment(NULL, globalCtx, OBJECT_GEFF, true);
@ -3080,12 +3099,12 @@ void BossGanon2_Reset(void) {
D_8090EB20.y = 0;
D_8090EB20.z = 0;
D_80910638 = 0;
sZelda = NULL;
sBossGanon2Zelda = NULL;
D_8090EB30 = NULL;
sSeed1 = 0;
sSeed2 = 0;
sSeed3 = 0;
sBossGanon2Seed1 = 0;
sBossGanon2Seed2 = 0;
sBossGanon2Seed3 = 0;
memset(D_809105D8, 0, sizeof(D_809105D8));
memset(D_80910608, 0, sizeof(D_80910608));
memset(sParticles, 0, sizeof(sParticles));
}
memset(sBossGanon2Particles, 0, sizeof(sBossGanon2Particles));
}

View file

@ -4,6 +4,20 @@
#include "ultra64.h"
#include "global.h"
typedef struct {
/* 0x00 */ u8 type;
/* 0x01 */ u8 unk_01;
/* 0x04 */ Vec3f position;
/* 0x10 */ Vec3f velocity;
/* 0x1C */ Vec3f accel;
/* 0x28 */ char unk_28[0x6];
/* 0x2E */ s16 unk_2E;
/* 0x30 */ char unk_30[0x4];
/* 0x34 */ f32 scale;
/* 0x38 */ Vec3f unk_38;
} BossGanon2Effect; // size = 0x44
struct BossGanon2;
typedef void (*BossGanon2ActionFunc)(struct BossGanon2*, GlobalContext*);

View file

@ -2,19 +2,6 @@
#include "overlays/actors/ovl_En_Zl3/z_en_zl3.h"
#include "objects/object_ganon2/object_ganon2.h"
typedef struct {
/* 0x00 */ u8 type;
/* 0x01 */ u8 unk_01;
/* 0x04 */ Vec3f position;
/* 0x10 */ Vec3f velocity;
/* 0x1C */ Vec3f accel;
/* 0x28 */ char unk_28[0x6];
/* 0x2E */ s16 unk_2E;
/* 0x30 */ char unk_30[0x4];
/* 0x34 */ f32 scale;
/* 0x38 */ Vec3f unk_38;
} BossGanon2Effect; // size = 0x44
static Vec3f D_80906D60 = { 0.0f, 0.0f, 0.0f };
static Vec3f D_80906D6C = { 0.0f, 0.0f, 500.0f };
@ -326,31 +313,7 @@ static s16 D_809071CC[] = { 1, -1, 1, 1, 3, 4, 1, 6, 7, 2, 9, 10, 2, 12, 13 };
static u8 D_809071EC[] = { 3, 2, 2, 1, 3, 3, 1, 3, 3, 1, 0, 3, 1, 0, 3 };
// padding
static u32 D_809071FC[2] = { 0 };
#include "overlays/ovl_Boss_Ganon2/ovl_Boss_Ganon2.h"
static Vec3f D_8090EB20;
static EnZl3* sZelda;
static Actor* D_8090EB30;
// unused
static UNK_TYPE D_8090EB34;
static BossGanon2Effect sParticles[100];
static s32 sSeed1;
static s32 sSeed2;
static s32 sSeed3;
// unused
static UNK_TYPE D_809105DC;
static Vec3f D_809105D8[4];
static Vec3f D_80910608[4];
static s8 D_80910638;
// padding
//static u32 D_809071FC[2] = { 0 };

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
@ -144,25 +147,25 @@ static f32 sFlatWidth[41] = {
#include "z_boss_mo_colchk.c"
static BossMoEffect sEffects[300];
static s32 sSeed1;
static s32 sSeed2;
static s32 sSeed3;
static s32 sBossGanonSeed1;
static s32 sBossGanonSeed2;
static s32 sBossGanonSeed3;
void BossMo_InitRand(s32 seedInit0, s32 seedInit1, s32 seedInit2) {
sSeed1 = seedInit0;
sSeed2 = seedInit1;
sSeed3 = seedInit2;
sBossGanonSeed1 = seedInit0;
sBossGanonSeed2 = seedInit1;
sBossGanonSeed3 = seedInit2;
}
f32 BossMo_RandZeroOne(void) {
// Wichmann-Hill algorithm
f32 randFloat;
sSeed1 = (sSeed1 * 171) % 30269;
sSeed2 = (sSeed2 * 172) % 30307;
sSeed3 = (sSeed3 * 170) % 30323;
sBossGanonSeed1 = (sBossGanonSeed1 * 171) % 30269;
sBossGanonSeed2 = (sBossGanonSeed2 * 172) % 30307;
sBossGanonSeed3 = (sBossGanonSeed3 * 170) % 30323;
randFloat = (sSeed1 / 30269.0f) + (sSeed2 / 30307.0f) + (sSeed3 / 30323.0f);
randFloat = (sBossGanonSeed1 / 30269.0f) + (sBossGanonSeed2 / 30307.0f) + (sBossGanonSeed3 / 30323.0f);
while (randFloat >= 1.0f) {
randFloat -= 1.0f;
}
@ -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();
}
}
@ -3588,7 +3605,7 @@ void BossMo_Reset(void) {
sMorphaTent1 = NULL;
sMorphaTent2 = NULL;
memset(sEffects, 0, sizeof(sEffects));
sSeed1 = 0;
sSeed2 = 0;
sSeed3 = 0;
}
sBossGanonSeed1 = 0;
sBossGanonSeed2 = 0;
sBossGanonSeed3 = 0;
}

View file

@ -7,34 +7,6 @@
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_2 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
typedef enum {
/* 0 */ TWEFF_NONE,
/* 1 */ TWEFF_DOT,
/* 2 */ TWEFF_2,
/* 3 */ TWEFF_3,
/* 4 */ TWEFF_RING,
/* 5 */ TWEFF_PLYR_FRZ,
/* 6 */ TWEFF_FLAME,
/* 7 */ TWEFF_MERGEFLAME,
/* 8 */ TWEFF_SHLD_BLST,
/* 9 */ TWEFF_SHLD_DEFL,
/* 10 */ TWEFF_SHLD_HIT
} TwEffType;
typedef enum {
/* 0 */ EFF_ARGS,
/* 1 */ EFF_UNKS1,
/* 2 */ EFF_WORK_MAX
} EffectWork;
typedef enum {
/* 0 */ EFF_SCALE,
/* 1 */ EFF_DIST,
/* 2 */ EFF_ROLL,
/* 3 */ EFF_YAW,
/* 4 */ EFF_FWORK_MAX
} EffectFWork;
typedef enum {
/* 0x00 */ TW_KOTAKE,
/* 0x01 */ TW_KOUME,
@ -47,19 +19,6 @@ typedef enum {
/* 0x69 */ TW_DEATHBALL_KOUME
} TwinrovaType;
typedef struct {
/* 0x0000 */ u8 type;
/* 0x0001 */ u8 frame;
/* 0x0004 */ Vec3f pos;
/* 0x0010 */ Vec3f curSpeed;
/* 0x001C */ Vec3f accel;
/* 0x0028 */ Color_RGB8 color;
/* 0x002C */ s16 alpha;
/* 0x002E */ s16 work[EFF_WORK_MAX];
/* 0x0034 */ f32 workf[EFF_FWORK_MAX];
/* 0x0044 */ Actor* target;
} BossTwEffect;
void BossTw_Init(Actor* thisx, GlobalContext* globalCtx);
void BossTw_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BossTw_Update(Actor* thisx, GlobalContext* globalCtx);
@ -200,7 +159,7 @@ static Vec3f sTwinrovaPillarPos[] = {
{ 0.0f, 380.0f, -580.0f },
};
static u8 sTwInitalized = false;
u8 sTwInitalized = false;
static InitChainEntry sInitChain[] = {
ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE),
@ -233,7 +192,7 @@ static u8 D_8094C878;
static s16 D_8094C87A;
static s16 D_8094C87C;
static u8 D_8094C87E;
static BossTwEffect sTwEffects[150];
BossTwEffect sTwEffects[150];
void BossTw_AddDotEffect(GlobalContext* globalCtx, Vec3f* initalPos, Vec3f* initalSpeed, Vec3f* accel, f32 scale,
s16 args, s16 countLimit) {

View file

@ -4,9 +4,46 @@
#include "ultra64.h"
#include "global.h"
struct BossTw;
typedef enum {
/* 0 */ TWEFF_NONE,
/* 1 */ TWEFF_DOT,
/* 2 */ TWEFF_2,
/* 3 */ TWEFF_3,
/* 4 */ TWEFF_RING,
/* 5 */ TWEFF_PLYR_FRZ,
/* 6 */ TWEFF_FLAME,
/* 7 */ TWEFF_MERGEFLAME,
/* 8 */ TWEFF_SHLD_BLST,
/* 9 */ TWEFF_SHLD_DEFL,
/* 10 */ TWEFF_SHLD_HIT
} TwEffType;
typedef void (*BossTwActionFunc)(struct BossTw* this, GlobalContext* globalCtx);
typedef enum {
/* 0 */ EFF_ARGS,
/* 1 */ EFF_UNKS1,
/* 2 */ EFF_WORK_MAX
} EffectWork;
typedef enum {
/* 0 */ EFF_SCALE,
/* 1 */ EFF_DIST,
/* 2 */ EFF_ROLL,
/* 3 */ EFF_YAW,
/* 4 */ EFF_FWORK_MAX
} EffectFWork;
typedef struct {
/* 0x0000 */ u8 type;
/* 0x0001 */ u8 frame;
/* 0x0004 */ Vec3f pos;
/* 0x0010 */ Vec3f curSpeed;
/* 0x001C */ Vec3f accel;
/* 0x0028 */ Color_RGB8 color;
/* 0x002C */ s16 alpha;
/* 0x002E */ s16 work[EFF_WORK_MAX];
/* 0x0034 */ f32 workf[EFF_FWORK_MAX];
/* 0x0044 */ Actor* target;
} BossTwEffect;
typedef enum {
/* 0 */ CS_TIMER_1,
@ -55,6 +92,10 @@ typedef enum {
/* 26 */ FWORK_MAX
} TwFwork;
struct BossTw;
typedef void (*BossTwActionFunc)(struct BossTw*, GlobalContext* globalCtx);
typedef struct BossTw {
/* 0x0000 */ Actor actor;
/* 0x014C */ BossTwActionFunc actionFunc;

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

@ -307,7 +307,7 @@ void func_8096712C(Demo6K* this, GlobalContext* globalCtx) {
}
}
static Vec3f velocity = { 0.0f, 0.0f, 0.0f };
Vec3f sDemo6kVelocity = { 0.0f, 0.0f, 0.0f };
void func_80967244(Demo6K* this, GlobalContext* globalCtx) {
static Vec3f accel = { 0.0f, 0.0f, 0.0f };
static Color_RGBA8 primColor = { 255, 255, 255, 0 };
@ -324,9 +324,9 @@ void func_80967244(Demo6K* this, GlobalContext* globalCtx) {
rand1 = Rand_ZeroFloat(0xFFFF);
rand2 = Rand_ZeroFloat(0xFFFF);
velocity.x = Math_SinS(rand2) * Math_CosS(rand1) * 20.0f;
velocity.z = Math_CosS(rand2) * Math_CosS(rand1) * 20.0f;
velocity.y = Math_SinS(rand1) * 20.0f;
sDemo6kVelocity.x = Math_SinS(rand2) * Math_CosS(rand1) * 20.0f;
sDemo6kVelocity.z = Math_CosS(rand2) * Math_CosS(rand1) * 20.0f;
sDemo6kVelocity.y = Math_SinS(rand1) * 20.0f;
accel.y = 0.0f;
@ -342,7 +342,7 @@ void func_80967244(Demo6K* this, GlobalContext* globalCtx) {
scale = 18000;
}
EffectSsKiraKira_SpawnFocused(globalCtx, &pos, &velocity, &accel, &primColor, &envColor, scale, 20);
EffectSsKiraKira_SpawnFocused(globalCtx, &pos, &sDemo6kVelocity, &accel, &primColor, &envColor, scale, 20);
}
void func_80967410(Demo6K* this, GlobalContext* globalCtx) {
@ -820,7 +820,7 @@ void func_809691BC(Demo6K* this, GlobalContext* globalCtx, s32 params) {
}
void Demo6K_Reset(void) {
velocity.x = 0.0f;
velocity.y = 0.0f;
velocity.z = 0.0f;
sDemo6kVelocity.x = 0.0f;
sDemo6kVelocity.y = 0.0f;
sDemo6kVelocity.z = 0.0f;
}

View file

@ -132,7 +132,7 @@ void DemoKekkai_Destroy(Actor* thisx, GlobalContext* globalCtx) {
Collider_DestroyCylinder(globalCtx, &this->collider2);
}
static Vec3f vel = { 0.0f, 0.0f, 0.0f };
Vec3f demoKekkaiVel = { 0.0f, 0.0f, 0.0f };
void DemoKekkai_SpawnParticles(DemoKekkai* this, GlobalContext* globalCtx) {
static Vec3f accel = { 0.0f, 0.0f, 0.0f };
static Color_RGBA8 lightYellow = { 255, 255, 170, 0 };
@ -144,15 +144,15 @@ void DemoKekkai_SpawnParticles(DemoKekkai* this, GlobalContext* globalCtx) {
s16 roll = Rand_ZeroFloat(65535.0f);
s16 yaw = Rand_ZeroFloat(65535.0f);
vel.x = Math_SinS(yaw) * Math_CosS(roll) * Rand_ZeroFloat(8.0f);
vel.z = Math_CosS(yaw) * Math_CosS(roll) * Rand_ZeroFloat(8.0f);
vel.y = Math_SinS(roll) * Rand_ZeroFloat(3.0f);
demoKekkaiVel.x = Math_SinS(yaw) * Math_CosS(roll) * Rand_ZeroFloat(8.0f);
demoKekkaiVel.z = Math_CosS(yaw) * Math_CosS(roll) * Rand_ZeroFloat(8.0f);
demoKekkaiVel.y = Math_SinS(roll) * Rand_ZeroFloat(3.0f);
pos.x = (vel.x * 7.0f) + this->actor.world.pos.x;
pos.y = (vel.y * 20.0f) + this->actor.world.pos.y + 120.0f;
pos.z = (vel.z * 7.0f) + this->actor.world.pos.z;
pos.x = (demoKekkaiVel.x * 7.0f) + this->actor.world.pos.x;
pos.y = (demoKekkaiVel.y * 20.0f) + this->actor.world.pos.y + 120.0f;
pos.z = (demoKekkaiVel.z * 7.0f) + this->actor.world.pos.z;
EffectSsKiraKira_SpawnFocused(globalCtx, &pos, &vel, &accel, &lightYellow, &darkRed, 3000,
EffectSsKiraKira_SpawnFocused(globalCtx, &pos, &demoKekkaiVel, &accel, &lightYellow, &darkRed, 3000,
(s32)Rand_ZeroFloat(40.0f) + 45);
}
}
@ -338,7 +338,7 @@ void DemoKekkai_DrawTowerBarrier(Actor* thisx, GlobalContext* globalCtx) {
}
void DemoKekkai_Reset(void) {
vel.x = 0.0f;
vel.y = 0.0f;
vel.z = 0.0f;
demoKekkaiVel.x = 0.0f;
demoKekkaiVel.y = 0.0f;
demoKekkaiVel.z = 0.0f;
}

View file

@ -53,7 +53,7 @@ static InitChainEntry sInitChain[] = {
ICHAIN_F32(uncullZoneDownward, 4000, ICHAIN_STOP),
};
static s16 sWarpTimerTarget;
s16 sWarpTimerTarget;
void DoorWarp1_SetupAction(DoorWarp1* this, DoorWarp1ActionFunc actionFunc) {
this->actionFunc = actionFunc;

View file

@ -122,7 +122,7 @@ static DamageTable sDamageTable = {
/* Unknown 2 */ DMG_ENTRY(0, 0x0),
};
static s32 sSlugGroup = 0;
s32 sSlugGroup = 0;
void EnBw_SetupAction(EnBw* this, EnBwActionFunc actionFunc) {
this->actionFunc = actionFunc;

View file

@ -35,7 +35,7 @@ const ActorInit En_Clear_Tag_InitVars = {
(ActorResetFunc)EnClearTag_Reset,
};
static u8 sIsEffectsInitialized = false;
u8 sClearTagIsEffectsInitialized = false;
static Vec3f sZeroVector = { 0.0f, 0.0f, 0.0f };
@ -79,10 +79,10 @@ static ColliderCylinderInit sLaserCylinderInit = {
{ 15, 30, 10, { 0, 0, 0 } },
};
static UNK_TYPE4 D_809D5C98 = 0; // unused
static UNK_TYPE4 D_809D5C9C = 0; // unused
//static UNK_TYPE4 D_809D5C98 = 0; // unused
//static UNK_TYPE4 D_809D5C9C = 0; // unused
static EnClearTagEffect sClearTagEffects[CLEAR_TAG_EFFECT_MAX_COUNT];
EnClearTagEffect sClearTagEffects[CLEAR_TAG_EFFECT_MAX_COUNT];
#include "overlays/ovl_En_Clear_Tag/ovl_En_Clear_Tag.h"
@ -273,8 +273,8 @@ void EnClearTag_Init(Actor* thisx, GlobalContext* globalCtx) {
}
// Initialize all effects to available if effects have not been initialized.
if (!sIsEffectsInitialized) {
sIsEffectsInitialized = true;
if (!sClearTagIsEffectsInitialized) {
sClearTagIsEffectsInitialized = true;
globalCtx->specialEffects = &sClearTagEffects[0];
for (i = 0; i < CLEAR_TAG_EFFECT_MAX_COUNT; i++) {
sClearTagEffects[i].type = CLEAR_TAG_EFFECT_AVAILABLE;
@ -1027,5 +1027,5 @@ void EnClearTag_DrawEffects(GlobalContext* globalCtx) {
void EnClearTag_Reset(void) {
memset(sClearTagEffects, 0, sizeof(sClearTagEffects));
sIsEffectsInitialized = false;
sClearTagIsEffectsInitialized = false;
}

View file

@ -84,18 +84,7 @@ sEnFrPointers.flags = 12
- Deactivate frogs, frogs will jump back into the water
*/
typedef struct {
u8 flags;
EnFr* frogs[5];
} EnFrPointers;
typedef struct {
f32 xzDist;
f32 yaw;
f32 yDist;
} LogSpotToFromWater;
static EnFrPointers sEnFrPointers = {
EnFrPointers sEnFrPointers = {
0x00,
{
NULL,
@ -106,6 +95,7 @@ static EnFrPointers sEnFrPointers = {
},
};
// Flags for gSaveContext.eventChkInf[13]
static u16 sSongIndex[] = {
0x0002, 0x0004, 0x0010, 0x0008, 0x0020, 0x0040, 0x0001, 0x0000,

View file

@ -28,6 +28,12 @@ typedef enum {
/* 07 */ FROG_NO_SONG
} FrogSongType;
typedef struct {
f32 xzDist;
f32 yaw;
f32 yDist;
} LogSpotToFromWater;
typedef struct EnFr {
/* 0x0000 */ Actor actor;
/* 0x014C */ SkelAnime skelAnime; // Frog Skeleton
@ -69,4 +75,9 @@ typedef struct EnFr {
/* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo()
} EnFr; // size = 0x03C4
typedef struct {
u8 flags;
EnFr* frogs[5];
} EnFrPointers;
#endif

Some files were not shown because too many files have changed in this diff Show more