Merge develop into zelda64

This commit is contained in:
Kevin Alexis Contreras 2022-05-31 17:49:39 -05:00
commit 0067a69795
52 changed files with 2214 additions and 919 deletions

View File

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

View File

@ -12,13 +12,15 @@ The Ship does not include assets and as such requires a prior copy of the game t
4) Launch `soh.exe`
### Supported Games
Ocarina of Time Debug (not Master Quest)
#### Ocarina of Time Debug (not Master Quest)
> Currently the recommended option
```
Build team: `zelda@srd022j`
Build date: `03-02-21 00:49:18` (year-month-day)
sha1: cee6bc3c2a634b41728f2af8da54d9bf8cc14099
```
Ocarina of Time PAL GameCube
#### Ocarina of Time PAL GameCube
> May lead to crashes and instability
```
sha1: 0227d7c0074f2d0ac935631990da8ec5914597b4
```
@ -64,6 +66,9 @@ Refer to the [building instructions](BUILDING.md) to compile SoH.
- Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe
- Affirm that `zapd.exe` exists in the `/assets/extractor` folder
## Nightly Builds
Nightly builds of Ship of Harkinian are available [here](https://builds.shipofharkinian.com/job/SoH_Multibranch/job/develop)
## The Harbour Masters Are...
@ -108,4 +113,4 @@ Refer to the [building instructions](BUILDING.md) to compile SoH.
Amphibibro | Link
AceHeart | Zelda
###### Lemons
###### Lemons

View File

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

View File

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

View File

@ -54,14 +54,12 @@ namespace Game {
}
void InitSettings() {
ModInternal::registerHookListener({ AUDIO_INIT, [](HookEvent ev) {
UpdateAudio();
}});
ModInternal::registerHookListener({ GFX_INIT, [](HookEvent ev) {
ModInternal::RegisterHook<ModInternal::AudioInit>(UpdateAudio);
ModInternal::RegisterHook<ModInternal::GfxInit>([] {
gfx_get_current_rendering_api()->set_texture_filter((FilteringMode) CVar_GetS32("gTextureFilter", THREE_POINT));
SohImGui::console->opened = CVar_GetS32("gConsoleEnabled", 0);
UpdateAudio();
}});
});
}
void SetSeqPlayerVolume(SeqPlayers playerId, float volume) {

View File

@ -96,7 +96,6 @@ static struct {
uint32_t msaa_num_quality_levels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT];
ComPtr<ID3D11Device> device;
ComPtr<IDXGISwapChain1> swap_chain;
ComPtr<ID3D11DeviceContext> context;
ComPtr<ID3D11RasterizerState> rasterizer_state;
ComPtr<ID3D11DepthStencilState> depth_stencil_state;
@ -252,7 +251,24 @@ static void gfx_d3d11_init(void) {
});
// Create the swap chain
d3d.swap_chain = gfx_dxgi_create_swap_chain(d3d.device.Get());
gfx_dxgi_create_swap_chain(d3d.device.Get(), []() {
d3d.framebuffers[0].render_target_view.Reset();
d3d.textures[d3d.framebuffers[0].texture_id].texture.Reset();
d3d.context->ClearState();
d3d.context->Flush();
d3d.last_shader_program = nullptr;
d3d.last_vertex_buffer_stride = 0;
d3d.last_blend_state.Reset();
d3d.last_resource_views[0].Reset();
d3d.last_resource_views[1].Reset();
d3d.last_sampler_states[0].Reset();
d3d.last_sampler_states[1].Reset();
d3d.last_depth_test = -1;
d3d.last_depth_mask = -1;
d3d.last_zmode_decal = -1;
d3d.last_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
});
// Create D3D Debug device if in debug mode
@ -266,7 +282,7 @@ static void gfx_d3d11_init(void) {
// Check the size of the window
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc;
ThrowIfFailed(d3d.swap_chain->GetDesc1(&swap_chain_desc));
ThrowIfFailed(gfx_dxgi_get_swap_chain()->GetDesc1(&swap_chain_desc));
d3d.textures[fb.texture_id].width = swap_chain_desc.Width;
d3d.textures[fb.texture_id].height = swap_chain_desc.Height;
fb.msaa_level = 1;
@ -303,8 +319,6 @@ static void gfx_d3d11_init(void) {
ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_frame_cb.GetAddressOf()),
gfx_dxgi_get_h_wnd(), "Failed to create per-frame constant buffer.");
d3d.context->PSSetConstantBuffers(0, 1, d3d.per_frame_cb.GetAddressOf());
// Create per-draw constant buffer
constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC;
@ -316,8 +330,6 @@ static void gfx_d3d11_init(void) {
ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_draw_cb.GetAddressOf()),
gfx_dxgi_get_h_wnd(), "Failed to create per-draw constant buffer.");
d3d.context->PSSetConstantBuffers(1, 1, d3d.per_draw_cb.GetAddressOf());
// Create compute shader that can be used to retrieve depth buffer values
const char* shader_source = R"(
@ -737,6 +749,8 @@ static void gfx_d3d11_on_resize(void) {
static void gfx_d3d11_start_frame(void) {
// Set per-frame constant buffer
ID3D11Buffer* buffers[2] = { d3d.per_frame_cb.Get(), d3d.per_draw_cb.Get() };
d3d.context->PSSetConstantBuffers(0, 2, buffers);
d3d.per_frame_cb_data.noise_frame++;
if (d3d.per_frame_cb_data.noise_frame > 150) {
@ -803,15 +817,16 @@ static void gfx_d3d11_update_framebuffer_parameters(int fb_id, uint32_t width, u
if (msaa_level <= 1) {
ThrowIfFailed(d3d.device->CreateShaderResourceView(tex.texture.Get(), nullptr, tex.resource_view.ReleaseAndGetAddressOf()));
}
} else if (diff) {
} else if (diff || (render_target && tex.texture.Get() == nullptr)) {
DXGI_SWAP_CHAIN_DESC1 desc1;
ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1));
IDXGISwapChain1* swap_chain = gfx_dxgi_get_swap_chain();
ThrowIfFailed(swap_chain->GetDesc1(&desc1));
if (desc1.Width != width || desc1.Height != height) {
fb.render_target_view.Reset();
tex.texture.Reset();
ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags));
ThrowIfFailed(swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags));
}
ThrowIfFailed(d3d.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)tex.texture.ReleaseAndGetAddressOf()));
ThrowIfFailed(swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *)tex.texture.ReleaseAndGetAddressOf()));
}
if (render_target) {
ThrowIfFailed(d3d.device->CreateRenderTargetView(tex.texture.Get(), nullptr, fb.render_target_view.ReleaseAndGetAddressOf()));

View File

@ -34,15 +34,8 @@
#define WINCLASS_NAME L"N64GAME"
#define GFX_API_NAME "DirectX"
#ifdef VERSION_EU
#define FRAME_INTERVAL_US_NUMERATOR_ 60000
#define FRAME_INTERVAL_US_DENOMINATOR 3
#else
#define FRAME_INTERVAL_US_NUMERATOR_ 50000
#define FRAME_INTERVAL_US_DENOMINATOR 3
#endif
#define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * dxgi.frame_divisor)
#define FRAME_INTERVAL_NS_NUMERATOR 1000000000
#define FRAME_INTERVAL_NS_DENOMINATOR (dxgi.target_fps)
using namespace Microsoft::WRL; // For ComPtr
@ -66,14 +59,19 @@ static struct {
ComPtr<IDXGIFactory2> factory;
ComPtr<IDXGISwapChain1> swap_chain;
HANDLE waitable_object;
ComPtr<IUnknown> swap_chain_device; // D3D11 Device or D3D12 Command Queue
std::function<void()> before_destroy_swap_chain_fn;
uint64_t qpc_init, qpc_freq;
uint64_t frame_timestamp; // in units of 1/FRAME_INTERVAL_US_DENOMINATOR microseconds
uint64_t frame_timestamp; // in units of 1/FRAME_INTERVAL_NS_DENOMINATOR nanoseconds
std::map<UINT, DXGI_FRAME_STATISTICS> frame_stats;
std::set<std::pair<UINT, UINT>> pending_frame_stats;
bool dropped_frame;
bool zero_latency;
float detected_hz;
UINT length_in_vsync_frames;
uint32_t frame_divisor;
uint32_t target_fps;
uint32_t maximum_frame_latency;
uint32_t applied_maximum_frame_latency;
HANDLE timer;
bool use_timer;
LARGE_INTEGER previous_present_time;
@ -143,6 +141,22 @@ static void run_as_dpi_aware(Fun f) {
}
}
static void apply_maximum_frame_latency(bool first) {
ComPtr<IDXGISwapChain2> swap_chain2;
if (dxgi.swap_chain->QueryInterface(__uuidof(IDXGISwapChain2), &swap_chain2) == S_OK) {
ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(dxgi.maximum_frame_latency));
if (first) {
dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject();
WaitForSingleObject(dxgi.waitable_object, INFINITE);
}
} else {
ComPtr<IDXGIDevice1> device1;
ThrowIfFailed(dxgi.swap_chain->GetDevice(__uuidof(IDXGIDevice1), &device1));
ThrowIfFailed(device1->SetMaximumFrameLatency(dxgi.maximum_frame_latency));
}
dxgi.applied_maximum_frame_latency = dxgi.maximum_frame_latency;
}
static void toggle_borderless_window_full_screen(bool enable, bool call_callback) {
// Windows 7 + flip mode + waitable object can't go to exclusive fullscreen,
// so do borderless instead. If DWM is enabled, this means we get one monitor
@ -271,7 +285,8 @@ void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen) {
dxgi.qpc_init = qpc_init.QuadPart;
dxgi.qpc_freq = qpc_freq.QuadPart;
dxgi.frame_divisor = 1;
dxgi.target_fps = 60;
dxgi.maximum_frame_latency = 1;
dxgi.timer = CreateWaitableTimer(nullptr, false, nullptr);
// Prepare window title
@ -367,8 +382,8 @@ static void gfx_dxgi_handle_events(void) {
}*/
}
static uint64_t qpc_to_us(uint64_t qpc) {
return qpc / dxgi.qpc_freq * 1000000 + qpc % dxgi.qpc_freq * 1000000 / dxgi.qpc_freq;
static uint64_t qpc_to_ns(uint64_t qpc) {
return qpc / dxgi.qpc_freq * 1000000000 + qpc % dxgi.qpc_freq * 1000000000 / dxgi.qpc_freq;
}
static uint64_t qpc_to_100ns(uint64_t qpc) {
@ -406,7 +421,7 @@ static bool gfx_dxgi_start_frame(void) {
dxgi.use_timer = false;
dxgi.frame_timestamp += FRAME_INTERVAL_US_NUMERATOR;
dxgi.frame_timestamp += FRAME_INTERVAL_NS_NUMERATOR;
if (dxgi.frame_stats.size() >= 2) {
DXGI_FRAME_STATISTICS *first = &dxgi.frame_stats.begin()->second;
@ -421,14 +436,16 @@ static bool gfx_dxgi_start_frame(void) {
}
double estimated_vsync_interval = (double)sync_qpc_diff / (double)sync_vsync_diff;
uint64_t estimated_vsync_interval_us = qpc_to_us(estimated_vsync_interval);
//printf("Estimated vsync_interval: %d\n", (int)estimated_vsync_interval_us);
if (estimated_vsync_interval_us < 2 || estimated_vsync_interval_us > 1000000) {
uint64_t estimated_vsync_interval_ns = qpc_to_ns(estimated_vsync_interval);
//printf("Estimated vsync_interval: %d\n", (int)estimated_vsync_interval_ns);
if (estimated_vsync_interval_ns < 2000 || estimated_vsync_interval_ns > 1000000000) {
// Unreasonable, maybe a monitor change
estimated_vsync_interval_us = 16666;
estimated_vsync_interval = estimated_vsync_interval_us * dxgi.qpc_freq / 1000000;
estimated_vsync_interval_ns = 16666666;
estimated_vsync_interval = estimated_vsync_interval_ns * dxgi.qpc_freq / 1000000000;
}
dxgi.detected_hz = (float)((double)1000000000 / (double)estimated_vsync_interval_ns);
UINT queued_vsyncs = 0;
bool is_first = true;
for (const std::pair<UINT, UINT>& p : dxgi.pending_frame_stats) {
@ -440,21 +457,21 @@ static bool gfx_dxgi_start_frame(void) {
}
uint64_t last_frame_present_end_qpc = (last->SyncQPCTime.QuadPart - dxgi.qpc_init) + estimated_vsync_interval * queued_vsyncs;
uint64_t last_end_us = qpc_to_us(last_frame_present_end_qpc);
uint64_t last_end_ns = qpc_to_ns(last_frame_present_end_qpc);
double vsyncs_to_wait = (double)(int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) / estimated_vsync_interval_us;
//printf("ts: %llu, last_end_us: %llu, Init v: %f\n", dxgi.frame_timestamp / 3, last_end_us, vsyncs_to_wait);
double vsyncs_to_wait = (double)(int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR - last_end_ns) / estimated_vsync_interval_ns;
//printf("ts: %llu, last_end_ns: %llu, Init v: %f\n", dxgi.frame_timestamp / 3, last_end_ns, vsyncs_to_wait);
if (vsyncs_to_wait <= 0) {
// Too late
if ((int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) < -66666) {
if ((int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR - last_end_ns) < -66666666) {
// The application must have been paused or similar
vsyncs_to_wait = round(((double)FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) / estimated_vsync_interval_us);
vsyncs_to_wait = round(((double)FRAME_INTERVAL_NS_NUMERATOR / FRAME_INTERVAL_NS_DENOMINATOR) / estimated_vsync_interval_ns);
if (vsyncs_to_wait < 1) {
vsyncs_to_wait = 1;
}
dxgi.frame_timestamp = FRAME_INTERVAL_US_DENOMINATOR * (last_end_us + vsyncs_to_wait * estimated_vsync_interval_us);
dxgi.frame_timestamp = FRAME_INTERVAL_NS_DENOMINATOR * (last_end_ns + vsyncs_to_wait * estimated_vsync_interval_ns);
} else {
// Drop frame
//printf("Dropping frame\n");
@ -464,9 +481,9 @@ static bool gfx_dxgi_start_frame(void) {
}
double orig_wait = vsyncs_to_wait;
if (floor(vsyncs_to_wait) != vsyncs_to_wait) {
uint64_t left = last_end_us + floor(vsyncs_to_wait) * estimated_vsync_interval_us;
uint64_t right = last_end_us + ceil(vsyncs_to_wait) * estimated_vsync_interval_us;
uint64_t adjusted_desired_time = dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR + (last_end_us + (FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) > dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR ? 2000 : -2000);
uint64_t left = last_end_ns + floor(vsyncs_to_wait) * estimated_vsync_interval_ns;
uint64_t right = last_end_ns + ceil(vsyncs_to_wait) * estimated_vsync_interval_ns;
uint64_t adjusted_desired_time = dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR + (last_end_ns + (FRAME_INTERVAL_NS_NUMERATOR / FRAME_INTERVAL_NS_DENOMINATOR) > dxgi.frame_timestamp / FRAME_INTERVAL_NS_DENOMINATOR ? 2000000 : -2000000);
int64_t diff_left = adjusted_desired_time - left;
int64_t diff_right = right - adjusted_desired_time;
if (diff_left < 0) {
@ -506,7 +523,7 @@ static void gfx_dxgi_swap_buffers_begin(void) {
LARGE_INTEGER t;
if (dxgi.use_timer) {
QueryPerformanceCounter(&t);
int64_t next = qpc_to_100ns(dxgi.previous_present_time.QuadPart) + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR;
int64_t next = qpc_to_100ns(dxgi.previous_present_time.QuadPart) + FRAME_INTERVAL_NS_NUMERATOR / (FRAME_INTERVAL_NS_DENOMINATOR * 100);
int64_t left = next - qpc_to_100ns(t.QuadPart);
if (left > 0) {
LARGE_INTEGER li;
@ -531,6 +548,32 @@ static void gfx_dxgi_swap_buffers_end(void) {
QueryPerformanceCounter(&t0);
QueryPerformanceCounter(&t1);
if (dxgi.applied_maximum_frame_latency > dxgi.maximum_frame_latency) {
// There seems to be a bug that if latency is decreased, there is no effect of that operation, so recreate swap chain
if (dxgi.waitable_object != nullptr) {
if (!dxgi.dropped_frame) {
// Wait the last time on this swap chain
WaitForSingleObject(dxgi.waitable_object, INFINITE);
}
CloseHandle(dxgi.waitable_object);
dxgi.waitable_object = nullptr;
}
dxgi.before_destroy_swap_chain_fn();
dxgi.swap_chain.Reset();
gfx_dxgi_create_swap_chain(dxgi.swap_chain_device.Get(), move(dxgi.before_destroy_swap_chain_fn));
dxgi.frame_timestamp = 0;
dxgi.frame_stats.clear();
dxgi.pending_frame_stats.clear();
return; // Make sure we don't wait a second time on the waitable object, since that would hang the program
} else if (dxgi.applied_maximum_frame_latency != dxgi.maximum_frame_latency) {
apply_maximum_frame_latency(false);
}
if (!dxgi.dropped_frame) {
if (dxgi.waitable_object != nullptr) {
WaitForSingleObject(dxgi.waitable_object, INFINITE);
@ -554,8 +597,20 @@ static double gfx_dxgi_get_time(void) {
return (double)(t.QuadPart - dxgi.qpc_init) / dxgi.qpc_freq;
}
static void gfx_dxgi_set_frame_divisor(int divisor) {
dxgi.frame_divisor = divisor;
static void gfx_dxgi_set_target_fps(int fps) {
uint32_t old_fps = dxgi.target_fps;
uint64_t t0 = dxgi.frame_timestamp / old_fps;
uint32_t t1 = dxgi.frame_timestamp % old_fps;
dxgi.target_fps = fps;
dxgi.frame_timestamp = t0 * dxgi.target_fps + t1 * dxgi.target_fps / old_fps;
}
static void gfx_dxgi_set_maximum_frame_latency(int latency) {
dxgi.maximum_frame_latency = latency;
}
static float gfx_dxgi_get_detected_hz() {
return dxgi.detected_hz;
}
void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)) {
@ -592,12 +647,12 @@ void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*crea
SetWindowTextW(dxgi.h_wnd, w_title);
}
ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
void gfx_dxgi_create_swap_chain(IUnknown *device, std::function<void()>&& before_destroy_fn) {
bool win8 = IsWindows8OrGreater(); // DXGI_SCALING_NONE is only supported on Win8 and beyond
bool dxgi_13 = dxgi.CreateDXGIFactory2 != nullptr; // DXGI 1.3 introduced waitable object
DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {};
swap_chain_desc.BufferCount = 2;
swap_chain_desc.BufferCount = 3;
swap_chain_desc.Width = 0;
swap_chain_desc.Height = 0;
swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
@ -617,28 +672,24 @@ ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
});
ThrowIfFailed(dxgi.factory->MakeWindowAssociation(dxgi.h_wnd, DXGI_MWA_NO_ALT_ENTER));
ComPtr<IDXGISwapChain2> swap_chain2;
if (dxgi.swap_chain->QueryInterface(__uuidof(IDXGISwapChain2), &swap_chain2) == S_OK) {
ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(1));
dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject();
WaitForSingleObject(dxgi.waitable_object, INFINITE);
} else {
ComPtr<IDXGIDevice1> device1;
ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&device1)));
ThrowIfFailed(device1->SetMaximumFrameLatency(1));
}
apply_maximum_frame_latency(true);
ThrowIfFailed(dxgi.swap_chain->GetDesc1(&swap_chain_desc));
dxgi.current_width = swap_chain_desc.Width;
dxgi.current_height = swap_chain_desc.Height;
return dxgi.swap_chain;
dxgi.swap_chain_device = device;
dxgi.before_destroy_swap_chain_fn = std::move(before_destroy_fn);
}
HWND gfx_dxgi_get_h_wnd(void) {
return dxgi.h_wnd;
}
IDXGISwapChain1* gfx_dxgi_get_swap_chain() {
return dxgi.swap_chain.Get();
}
void ThrowIfFailed(HRESULT res) {
if (FAILED(res)) {
fprintf(stderr, "Error: 0x%08X\n", res);
@ -668,7 +719,9 @@ extern "C" struct GfxWindowManagerAPI gfx_dxgi_api = {
gfx_dxgi_swap_buffers_begin,
gfx_dxgi_swap_buffers_end,
gfx_dxgi_get_time,
gfx_dxgi_set_frame_divisor,
gfx_dxgi_set_target_fps,
gfx_dxgi_set_maximum_frame_latency,
gfx_dxgi_get_detected_hz,
};
#endif

View File

@ -4,9 +4,15 @@
#include "gfx_rendering_api.h"
#ifdef DECLARE_GFX_DXGI_FUNCTIONS
#include <functional>
#include <dxgi1_2.h>
void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only));
Microsoft::WRL::ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device);
void gfx_dxgi_create_swap_chain(IUnknown *device, std::function<void()>&& before_destroy_fn);
HWND gfx_dxgi_get_h_wnd(void);
IDXGISwapChain1* gfx_dxgi_get_swap_chain();
void ThrowIfFailed(HRESULT res);
void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message);
#endif

View File

@ -36,7 +36,7 @@
// OTRTODO: fix header files for these
extern "C" {
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc);
const char* ResourceMgr_GetNameByCRC(uint64_t crc);
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc);
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc);
@ -88,7 +88,7 @@ struct LoadedVertex {
static struct {
TextureCacheMap map;
list<TextureCacheMap::iterator> lru;
list<TextureCacheMapIter> lru;
vector<uint32_t> free_texture_ids;
} gfx_texture_cache;
@ -134,14 +134,14 @@ static struct RDP {
const uint8_t *addr;
uint8_t siz;
uint32_t width;
char* otr_path;
const char* otr_path;
} texture_to_load;
struct {
const uint8_t *addr;
uint32_t size_bytes;
uint32_t full_image_line_size_bytes;
uint32_t line_size_bytes;
char* otr_path;
const char* otr_path;
} loaded_texture[2];
struct {
uint8_t fmt;
@ -527,18 +527,18 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
key = { orig_addr, { }, fmt, siz, palette_index };
}
auto it = gfx_texture_cache.map.find(key);
TextureCacheMap::iterator it = gfx_texture_cache.map.find(key);
if (it != gfx_texture_cache.map.end()) {
gfx_rapi->select_texture(i, it->second.texture_id);
*n = &*it;
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, *(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location); // move to back
gfx_texture_cache.lru.splice(gfx_texture_cache.lru.end(), gfx_texture_cache.lru, it->second.lru_location); // move to back
return true;
}
if (gfx_texture_cache.map.size() >= TEXTURE_CACHE_MAX_SIZE) {
// Remove the texture that was least recently used
it = gfx_texture_cache.lru.front();
it = gfx_texture_cache.lru.front().it;
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
gfx_texture_cache.map.erase(it);
gfx_texture_cache.lru.pop_front();
@ -555,7 +555,7 @@ static bool gfx_texture_cache_lookup(int i, int tile) {
it = gfx_texture_cache.map.insert(make_pair(key, TextureCacheValue())).first;
TextureCacheNode* node = &*it;
node->second.texture_id = texture_id;
*(list<TextureCacheMap::iterator>::iterator*)&node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), it);
node->second.lru_location = gfx_texture_cache.lru.insert(gfx_texture_cache.lru.end(), { it });
gfx_rapi->select_texture(i, texture_id);
gfx_rapi->set_sampler_parameters(i, false, 0, 0);
@ -571,7 +571,7 @@ static void gfx_texture_cache_delete(const uint8_t* orig_addr)
bool again = false;
for (auto it = gfx_texture_cache.map.begin(bucket); it != gfx_texture_cache.map.end(bucket); ++it) {
if (it->first.texture_addr == orig_addr) {
gfx_texture_cache.lru.erase(*(list<TextureCacheMap::iterator>::iterator*)&it->second.lru_location);
gfx_texture_cache.lru.erase(it->second.lru_location);
gfx_texture_cache.free_texture_ids.push_back(it->second.texture_id);
gfx_texture_cache.map.erase(it->first);
again = true;
@ -1636,11 +1636,11 @@ static void gfx_dp_set_scissor(uint32_t mode, uint32_t ulx, uint32_t uly, uint32
rdp.viewport_or_scissor_changed = true;
}
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, char* otr_path) {
static void gfx_dp_set_texture_image(uint32_t format, uint32_t size, uint32_t width, const void* addr, const char* otr_path) {
rdp.texture_to_load.addr = (const uint8_t*)addr;
rdp.texture_to_load.siz = size;
rdp.texture_to_load.width = width;
if ( otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
if (otr_path != nullptr && !strncmp(otr_path, "__OTR__", 7)) otr_path = otr_path + 7;
rdp.texture_to_load.otr_path = otr_path;
}
@ -2114,7 +2114,7 @@ static void gfx_run_dl(Gfx* cmd) {
//puts("dl");
int dummy = 0;
char dlName[128];
char fileName[128];
const char* fileName;
Gfx* dListStart = cmd;
uint64_t ourHash = -1;
@ -2437,7 +2437,7 @@ static void gfx_run_dl(Gfx* cmd) {
uintptr_t addr = cmd->words.w1;
cmd++;
uint64_t hash = ((uint64_t)cmd->words.w0 << 32) + (uint64_t)cmd->words.w1;
ResourceMgr_GetNameByCRC(hash, fileName);
fileName = ResourceMgr_GetNameByCRC(hash);
#if _DEBUG && 0
char* tex = ResourceMgr_LoadTexByCRC(hash);
ResourceMgr_GetNameByCRC(hash, fileName);
@ -2710,9 +2710,7 @@ void gfx_init(struct GfxWindowManagerAPI *wapi, struct GfxRenderingAPI *rapi, co
//gfx_lookup_or_create_shader_program(precomp_shaders[i]);
}
ModInternal::bindHook(GFX_INIT);
ModInternal::initBindHook(0);
ModInternal::callBindHook(0);
ModInternal::ExecuteHooks<ModInternal::GfxInit>();
}
struct GfxRenderingAPI *gfx_get_current_rendering_api(void) {
@ -2791,6 +2789,9 @@ void gfx_run(Gfx *commands, const std::unordered_map<Mtx *, MtxF>& mtx_replaceme
gfx_rapi->start_frame();
gfx_rapi->start_draw_to_framebuffer(game_renders_to_framebuffer ? game_framebuffer : 0, (float)gfx_current_dimensions.height / SCREEN_HEIGHT);
gfx_rapi->clear_framebuffer();
rdp.viewport_or_scissor_changed = true;
rendering_state.viewport = {};
rendering_state.scissor = {};
gfx_run_dl(commands);
gfx_flush();
SohUtils::saveEnvironmentVar("framebuffer", string());
@ -2827,8 +2828,16 @@ void gfx_end_frame(void) {
}
}
void gfx_set_framedivisor(int divisor) {
gfx_wapi->set_frame_divisor(divisor);
void gfx_set_target_fps(int fps) {
gfx_wapi->set_target_fps(fps);
}
void gfx_set_maximum_frame_latency(int latency) {
gfx_wapi->set_maximum_frame_latency(latency);
}
float gfx_get_detected_hz(void) {
return gfx_wapi->get_detected_hz();
}
int gfx_create_framebuffer(uint32_t width, uint32_t height) {

View File

@ -46,12 +46,11 @@ struct TextureCacheValue {
uint8_t cms, cmt;
bool linear_filter;
// Old versions of libstdc++ fail to compile this
#ifdef _MSC_VER
std::list<TextureCacheMap::iterator>::iterator lru_location;
#else
std::list<int>::iterator lru_location;
#endif
std::list<struct TextureCacheMapIter>::iterator lru_location;
};
struct TextureCacheMapIter {
TextureCacheMap::iterator it;
};
extern "C" {
@ -68,7 +67,9 @@ struct GfxRenderingAPI* gfx_get_current_rendering_api(void);
void gfx_start_frame(void);
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_set_target_fps(int);
void gfx_set_maximum_frame_latency(int latency);
float gfx_get_detected_hz(void);
void gfx_texture_cache_clear();
extern "C" int gfx_create_framebuffer(uint32_t width, uint32_t height);
void gfx_get_pixel_depth_prepare(float x, float y);

View File

@ -123,11 +123,10 @@ static uint64_t previous_time;
static HANDLE timer;
#endif
static int frameDivisor = 1;
static int target_fps = 60;
#define FRAME_INTERVAL_US_NUMERATOR_ 50000
#define FRAME_INTERVAL_US_DENOMINATOR 3
#define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * frameDivisor)
#define FRAME_INTERVAL_US_NUMERATOR 1000000
#define FRAME_INTERVAL_US_DENOMINATOR (target_fps)
static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) {
SDL_Init(SDL_INIT_VIDEO);
@ -250,6 +249,7 @@ static void gfx_sdl_handle_events(void) {
}
break;
case SDL_QUIT:
SDL_Quit(); // bandaid fix for linux window closing issue
exit(0);
}
}
@ -266,15 +266,16 @@ static uint64_t qpc_to_100ns(uint64_t qpc) {
static inline void sync_framerate_with_timer(void) {
uint64_t t;
t = SDL_GetPerformanceCounter();
t = qpc_to_100ns(SDL_GetPerformanceCounter());
const int64_t next = qpc_to_100ns(previous_time) + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR;
const int64_t left = next - qpc_to_100ns(t);
const int64_t next = previous_time + 10 * FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR;
const int64_t left = next - t;
if (left > 0) {
#ifdef __linux__
const timespec spec = { 0, left * 100 };
nanosleep(&spec, nullptr);
#else
// The accuracy of this timer seems to usually be within +- 1.0 ms
LARGE_INTEGER li;
li.QuadPart = -left;
SetWaitableTimer(timer, &li, 0, nullptr, nullptr, false);
@ -282,7 +283,13 @@ static inline void sync_framerate_with_timer(void) {
#endif
}
t = SDL_GetPerformanceCounter();
t = qpc_to_100ns(SDL_GetPerformanceCounter());
if (left > 0 && t - next < 10000) {
// In case it takes some time for the application to wake up after sleep,
// or inaccurate timer,
// don't let that slow down the framerate.
t = next;
}
previous_time = t;
}
@ -299,9 +306,16 @@ static double gfx_sdl_get_time(void) {
return 0.0;
}
static void gfx_sdl_set_framedivisor(int divisor)
{
frameDivisor = divisor;
static void gfx_sdl_set_target_fps(int fps) {
target_fps = fps;
}
static void gfx_sdl_set_maximum_frame_latency(int latency) {
// Not supported by SDL :(
}
static float gfx_sdl_get_detected_hz(void) {
return 0;
}
struct GfxWindowManagerAPI gfx_sdl = {
@ -317,7 +331,9 @@ struct GfxWindowManagerAPI gfx_sdl = {
gfx_sdl_swap_buffers_begin,
gfx_sdl_swap_buffers_end,
gfx_sdl_get_time,
gfx_sdl_set_framedivisor
gfx_sdl_set_target_fps,
gfx_sdl_set_maximum_frame_latency,
gfx_sdl_get_detected_hz
};
#endif

View File

@ -17,7 +17,9 @@ struct GfxWindowManagerAPI {
void (*swap_buffers_begin)(void);
void (*swap_buffers_end)(void);
double (*get_time)(void); // For debug
void (*set_frame_divisor)(int);
void (*set_target_fps)(int fps);
void (*set_maximum_frame_latency)(int latency);
float (*get_detected_hz)(void);
};
#endif

View File

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

View File

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

View File

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

View File

@ -5,121 +5,6 @@
#include <stdarg.h>
#include <iostream>
std::map<std::string, std::vector<HookFunc>> listeners;
std::string hookName;
std::map<std::string, void*> initArgs;
std::map<std::string, void*> hookArgs;
/*
#############################
Module: Hook C++ Handle
#############################
*/
namespace ModInternal {
void registerHookListener(HookListener listener) {
listeners[listener.hookName].push_back(listener.callback);
}
bool handleHook(std::shared_ptr<HookCall> call) {
std::string hookName = std::string(call->name);
for (size_t l = 0; l < listeners[hookName].size(); l++) {
(listeners[hookName][l])(call);
}
return call->cancelled;
}
void bindHook(std::string name) {
hookName = name;
}
void initBindHook(int length, ...) {
if (length > 0) {
va_list args;
va_start(args, length);
for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter);
initArgs[currentParam.name] = currentParam.parameter;
}
va_end(args);
}
}
bool callBindHook(int length, ...) {
if (length > 0) {
va_list args;
va_start(args, length);
for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter);
hookArgs[currentParam.name] = currentParam.parameter;
}
va_end(args);
}
HookCall call = {
.name = hookName,
.baseArgs = initArgs,
.hookedArgs = hookArgs
};
const bool cancelled = handleHook(std::make_shared<HookCall>(call));
hookName = "";
initArgs.clear();
hookArgs.clear();
return cancelled;
}
void ModInternal_ExecuteAudioInitHooks() {
ModInternal::ExecuteHooks<ModInternal::AudioInit>();
}
/*
#############################
Module: Hook C Handle
#############################
*/
extern "C" {
void bind_hook(char* name) {
hookName = std::string(name);
}
void init_hook(int length, ...) {
if (length > 0) {
va_list args;
va_start(args, length);
for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter);
initArgs[currentParam.name] = currentParam.parameter;
}
va_end(args);
}
}
bool call_hook(int length, ...) {
if (length > 0) {
va_list args;
va_start(args, length);
for (int i = 0; i < length; i++) {
HookParameter currentParam = va_arg(args, struct HookParameter);
hookArgs[currentParam.name] = currentParam.parameter;
}
va_end(args);
}
HookCall call = {
.name = hookName,
.baseArgs = initArgs,
.hookedArgs = hookArgs
};
const bool cancelled = ModInternal::handleHook(std::make_shared<HookCall>(call));
hookName = "";
initArgs.clear();
hookArgs.clear();
return cancelled;
}
}

View File

@ -1,80 +1,50 @@
#pragma once
struct HookParameter {
const char* name;
void* parameter;
};
#define LOOKUP_TEXTURE "F3D::LookupCacheTexture"
#define GRAYOUT_TEXTURE "Kaleido::GrayOutTexture"
#define INVALIDATE_TEXTURE "GBI::gSPInvalidateTexCache"
#define CONTROLLER_READ "N64::ControllerRead"
#define AUDIO_INIT "AudioMgr::Init"
#define LOAD_TEXTURE "ResourceMgr::LoadTexByName"
#define UPDATE_VOLUME "AudioVolume::Bind"
#define IMGUI_API_INIT "ImGuiApiInit"
#define IMGUI_API_DRAW "ImGuiApiDraw"
#define WINDOW_API_INIT "WApiInit"
#define WINDOW_API_HANDLE_EVENTS "WApiHandleEvents"
#define WINDOW_API_START_FRAME "WApiStartFrame"
// Graphics API Hooks
#define GFX_PRE_START_FRAME "GFXApiPreStartFrame"
#define GFX_POST_START_FRAME "GFXApiPostStartFrame"
#define GFX_PRE_END_FRAME "GFXApiPreEndFrame"
#define GFX_POST_END_FRAME "GFXApiPostEndFrame"
#define GFX_ON_REZISE "GFXApiOnResize"
#define GFX_INIT "GFXApiInit"
#define GFX_SHUTDOWN "GFXApiShutdown"
// End
#ifdef __cplusplus
#define HOOK_PARAMETER(name, ptr) HookParameter({ name, static_cast<void*>(ptr) })
#define BIND_HOOK(name, func) ModInternal::registerHookListener({ name, [this](HookEvent call) { func(call); }})
#define BIND_PTR(name, type) static_cast<type>(call->baseArgs[name])
#define BIND_VAR(name, type) *BIND_PTR(name, type)
#include <functional>
#include <string>
#include <map>
#include <memory>
struct HookCall {
std::string name;
std::map<std::string, void*> baseArgs;
std::map<std::string, void*> hookedArgs;
bool cancelled = false;
};
#include "UltraController.h"
typedef std::shared_ptr<HookCall> HookEvent;
typedef std::function<void(HookEvent)> HookFunc;
struct HookListener {
std::string hookName;
HookFunc callback;
int priority = 0;
};
#define DEFINE_HOOK(name, type) struct name { typedef std::function<type> fn; }
namespace ModInternal {
void registerHookListener(HookListener listener);
void bindHook(std::string name);
void initBindHook(int length, ...);
bool callBindHook(int length, ...);
template <typename H>
struct RegisteredHooks {
inline static std::vector<typename H::fn> functions;
};
template <typename H>
void RegisterHook(typename H::fn h) {
RegisteredHooks<H>::functions.push_back(h);
}
template <typename H, typename... Args>
void ExecuteHooks(Args&&... args) {
for (auto& fn : RegisteredHooks<H>::functions) {
fn(std::forward<Args>(args)...);
}
}
DEFINE_HOOK(ControllerRead, void(OSContPad* cont_pad));
DEFINE_HOOK(AudioInit, void());
DEFINE_HOOK(LoadTexture, void(const char* path, uint8_t** texture));
DEFINE_HOOK(GfxInit, void());
}
#else
#endif
void bind_hook(char* name);
void init_hook(int length, ...);
bool call_hook(int length, ...);
#ifdef __cplusplus
extern "C" {
#endif
#endif
void ModInternal_ExecuteAudioInitHooks();
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -63,11 +63,14 @@ namespace SohImGui {
extern bool needs_save;
void Init(WindowImpl window_impl);
void Update(EventImpl event);
void EnhancementRadioButton(std::string text, std::string cvarName, int value);
void EnhancementCheckbox(std::string text, std::string cvarName);
void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format);
void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue);
void Tooltip(const char* text);
void EnhancementRadioButton(const char* text, const char* cvarName, int id);
void EnhancementCheckbox(const char* text, const char* cvarName);
void EnhancementButton(const char* text, const char* cvarName);
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format);
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage);
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow = true, bool has_alpha=false, bool TitleSameLine=false);
void DrawMainMenuAndCalculateGameSize(void);
@ -78,6 +81,10 @@ namespace SohImGui {
void BindCmd(const std::string& cmd, CommandEntry entry);
void AddWindow(const std::string& category, const std::string& name, WindowDrawFunc drawFunc);
void LoadResource(const std::string& name, const std::string& path, const ImVec4& tint = ImVec4(1, 1, 1, 1));
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha=false);
void RandomizeColor(const char* cvarName, ImVec4* colors);
void RainbowColor(const char* cvarName, ImVec4* colors);
void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha);
ImTextureID GetTextureByID(int id);
ImTextureID GetTextureByName(const std::string& name);
}

View File

@ -1,5 +1,7 @@
#include "TextureMod.h"
#if 0
#include <map>
#include <string>
#include <iostream>
@ -121,4 +123,6 @@ namespace Ship {
TexturePool.clear();
LoadedOTRS.clear();
}
}
}
#endif

View File

@ -3,6 +3,8 @@
#include <PR/ultra64/gbi.h>
#include "Lib/Fast3D/gfx_pc.h"
#if 0
namespace Ship {
enum TextureMod {
GRAYSCALE,
@ -48,4 +50,6 @@ namespace Ship {
data[x + 2] = gray;
}
}
}
}
#endif

View File

@ -112,24 +112,19 @@ extern "C" {
}
}
ModInternal::bindHook(CONTROLLER_READ);
ModInternal::initBindHook(1,
HookParameter({ .name = "cont_pad", .parameter = (void*)pad })
);
ModInternal::callBindHook(0);
ModInternal::ExecuteHooks<ModInternal::ControllerRead>(pad);
}
char* ResourceMgr_GetNameByCRC(uint64_t crc, char* alloc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
strcpy(alloc, hashStr.c_str());
return (char*)hashStr.c_str();
const char* ResourceMgr_GetNameByCRC(uint64_t crc) {
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
return hashStr != nullptr ? hashStr->c_str() : nullptr;
}
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Array>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
//if (res != nullptr)
return (Vtx*)res->vertices.data();
@ -142,10 +137,10 @@ extern "C" {
}
int32_t* ResourceMgr_LoadMtxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::Matrix>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (int32_t*)res->mtx.data();
} else {
return nullptr;
@ -153,10 +148,10 @@ extern "C" {
}
Gfx* ResourceMgr_LoadGfxByCRC(uint64_t crc) {
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (hashStr != "") {
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr));
if (hashStr != nullptr) {
auto res = std::static_pointer_cast<Ship::DisplayList>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()));
return (Gfx*)&res->instructions[0];
} else {
return nullptr;
@ -164,17 +159,12 @@ extern "C" {
}
char* ResourceMgr_LoadTexByCRC(uint64_t crc) {
const std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(crc);
if (!hashStr.empty()) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get());
if (hashStr != nullptr) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get());
ModInternal::bindHook(LOAD_TEXTURE);
ModInternal::initBindHook(2,
HookParameter({.name = "path", .parameter = (void*)hashStr.c_str() }),
HookParameter({.name = "texture", .parameter = static_cast<void*>(&res->imageData) })
);
ModInternal::callBindHook(0);
ModInternal::ExecuteHooks<ModInternal::LoadTexture>(hashStr->c_str(), &res->imageData);
return reinterpret_cast<char*>(res->imageData);
} else {
@ -184,11 +174,11 @@ extern "C" {
void ResourceMgr_RegisterResourcePatch(uint64_t hash, uint32_t instrIndex, uintptr_t origData)
{
std::string hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
const std::string* hashStr = Ship::GlobalCtx2::GetInstance()->GetResourceManager()->HashToString(hash);
if (hashStr != "")
if (hashStr != nullptr)
{
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr).get();
auto res = (Ship::Texture*)Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(hashStr->c_str()).get();
Ship::Patch patch;
patch.crc = hash;
@ -201,12 +191,7 @@ extern "C" {
char* ResourceMgr_LoadTexByName(char* texPath) {
const auto res = static_cast<Ship::Texture*>(Ship::GlobalCtx2::GetInstance()->GetResourceManager()->LoadResource(texPath).get());
ModInternal::bindHook(LOAD_TEXTURE);
ModInternal::initBindHook(2,
HookParameter({ .name = "path", .parameter = (void*)texPath }),
HookParameter({ .name = "texture", .parameter = static_cast<void*>(&res->imageData) })
);
ModInternal::callBindHook(0);
ModInternal::ExecuteHooks<ModInternal::LoadTexture>(texPath, &res->imageData);
return (char*)res->imageData;
}
@ -287,13 +272,14 @@ namespace Ship {
gfx_run(Commands, m);
gfx_end_frame();
}
gfx_run(Commands, {});
gfx_end_frame();
}
void Window::SetFrameDivisor(int divisor) {
gfx_set_framedivisor(divisor);
//gfx_set_framedivisor(0);
void Window::SetTargetFps(int fps) {
gfx_set_target_fps(fps);
}
void Window::SetMaximumFrameLatency(int latency) {
gfx_set_maximum_frame_latency(latency);
}
void Window::GetPixelDepthPrepare(float x, float y) {

View File

@ -20,7 +20,8 @@ namespace Ship {
void Init();
void StartFrame();
void RunCommands(Gfx* Commands, const std::vector<std::unordered_map<Mtx*, MtxF>>& mtx_replacements);
void SetFrameDivisor(int divisor);
void SetTargetFps(int fps);
void SetMaximumFrameLatency(int latency);
void GetPixelDepthPrepare(float x, float y);
uint16_t GetPixelDepth(float x, float y);
void ToggleFullscreen();

View File

@ -18,8 +18,8 @@ WARN := \
-funsigned-char \
-m32 -mhard-float -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-strict-aliasing -fno-inline-functions -fno-inline-small-functions -fno-toplevel-reorder -ffreestanding -fwrapv \
CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -march=i386
CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -march=i386
CXXFLAGS := $(WARN) -std=c++20 -D_GNU_SOURCE -fpermissive -no-pie -nostdlib -march=i386 -msse2 -mfpmath=sse
CFLAGS := $(WARN) -std=c99 -D_GNU_SOURCE -no-pie -nostdlib -march=i386 -msse2 -mfpmath=sse
LDFLAGS := -m32
CPPFLAGS := -MMD

View File

@ -1,6 +1,6 @@
<Root>
<File Name="object_triforce_spot" Segment="6">
<Array Name="gTriforceVtx" Count="32" Offset="0x0000">
<Array Name="gTriforceVtx" Count="96" Offset="0x0000">
<Vtx/>
</Array>

View File

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

View File

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

View File

@ -28,9 +28,13 @@ void BootCommands_Init()
CVar_RegisterS32("gRumbleEnabled", 0);
CVar_RegisterS32("gUniformLR", 1);
CVar_RegisterS32("gTwoHandedIdle", 0);
CVar_RegisterS32("gDekuNutUpgradeFix", 1);
CVar_RegisterS32("gNewDrops", 0);
CVar_RegisterS32("gVisualAgony", 0);
CVar_RegisterS32("gLanguages", 0); //0 = English / 1 = German / 2 = French
CVar_RegisterS32("gHudColors", 1); //0 = N64 / 1 = NGC / 2 = Custom
CVar_RegisterS32("gUseNaviCol", 0);
CVar_RegisterS32("gUseTunicsCol", 0);
}
//void BootCommands_ParseBootArgs(char* str)

View File

@ -175,8 +175,6 @@ extern "C" void Graph_StartFrame() {
// C->C++ Bridge
extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
OTRGlobals::Instance->context->GetWindow()->SetFrameDivisor(CVar_GetS32("g60FPS", 0) == 0 ? R_UPDATE_RATE : 1);
if (!audio.initialized && 0) {
audio.initialized = true;
std::thread([]() {
@ -226,15 +224,45 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) {
audio.cv_to_thread.notify_one();
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));
int target_fps = CVar_GetS32("gInterpolationFPS", 20);
static int last_fps;
static int last_update_rate;
static int time;
int fps = target_fps;
int original_fps = 60 / R_UPDATE_RATE;
if (target_fps == 20 || original_fps > target_fps) {
fps = original_fps;
}
if (last_fps != fps || last_update_rate != R_UPDATE_RATE) {
time = 0;
}
// time_base = fps * original_fps (one second)
int next_original_frame = fps;
while (time + original_fps <= next_original_frame) {
time += original_fps;
if (time != next_original_frame) {
mtx_replacements.push_back(FrameInterpolation_Interpolate((float)time / next_original_frame));
} else {
mtx_replacements.emplace_back();
}
}
time -= fps;
OTRGlobals::Instance->context->GetWindow()->SetTargetFps(fps);
int threshold = CVar_GetS32("gExtraLatencyThreshold", 80);
OTRGlobals::Instance->context->GetWindow()->SetMaximumFrameLatency(threshold > 0 && target_fps >= threshold ? 2 : 1);
OTRGlobals::Instance->context->GetWindow()->RunCommands(commands, mtx_replacements);
last_fps = fps;
last_update_rate = R_UPDATE_RATE;
if (0) {
std::unique_lock<std::mutex> Lock(audio.mutex);
while (audio.processing) {

View File

@ -451,7 +451,7 @@ void FrameInterpolation_StartRecord(void) {
current_recording = {};
current_path.clear();
current_path.push_back(&current_recording.root_path);
if (CVar_GetS32("g60FPS", 0) != 0) {
if (CVar_GetS32("gInterpolationFPS", 20) != 20) {
is_recording = true;
}
}

View File

@ -19,9 +19,50 @@ MessageTableEntry* OTRMessage_LoadTable(const char* filePath, bool isNES) {
if (file == nullptr)
return nullptr;
MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * file->messages.size());
// Allocate room for an additional message
MessageTableEntry* table = (MessageTableEntry*)malloc(sizeof(MessageTableEntry) * (file->messages.size() + 1));
for (int i = 0; i < file->messages.size(); i++) {
// Look for Owl Text
if (file->messages[i].id == 0x2066) {
// Create a new message based on the Owl Text
char* kaeporaPatch = (char*)malloc(sizeof(char) * file->messages[i].msg.size());
file->messages[i].msg.copy(kaeporaPatch, file->messages[i].msg.size(), 0);
// Swap the order of yes and no in this new message
if (filePath == "text/nes_message_data_static/nes_message_data_static") {
kaeporaPatch[26] = 'Y';
kaeporaPatch[27] = 'e';
kaeporaPatch[28] = 's';
kaeporaPatch[29] = 1;
kaeporaPatch[30] = 'N';
kaeporaPatch[31] = 'o';
} else if (filePath == "text/ger_message_data_static/ger_message_data_static") {
kaeporaPatch[30] = 'J';
kaeporaPatch[31] = 'a';
kaeporaPatch[32] = '!';
kaeporaPatch[33] = 1;
kaeporaPatch[34] = 'N';
kaeporaPatch[35] = 'e';
kaeporaPatch[36] = 'i';
kaeporaPatch[37] = 'n';
} else {
kaeporaPatch[26] = 'O';
kaeporaPatch[27] = 'u';
kaeporaPatch[28] = 'i';
kaeporaPatch[29] = 1;
kaeporaPatch[30] = 'N';
kaeporaPatch[31] = 'o';
kaeporaPatch[32] = 'n';
}
// load data into message
table[file->messages.size()].textId = 0x71B3;
table[file->messages.size()].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
table[file->messages.size()].segment = kaeporaPatch;
table[file->messages.size()].msgSize = file->messages[i].msg.size();
}
table[i].textId = file->messages[i].id;
table[i].typePos = (file->messages[i].textboxType << 4) | file->messages[i].textboxYPos;
table[i].segment = file->messages[i].msg.c_str();

View File

@ -109,9 +109,7 @@ void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedCon
AudioLoad_SetDmaHandler(DmaMgr_DmaHandler);
Audio_InitSound();
osSendMesg(&audioMgr->unk_C8, NULL, OS_MESG_BLOCK);
bind_hook(AUDIO_INIT);
init_hook(0);
call_hook(0);
ModInternal_ExecuteAudioInitHooks();
// Removed due to crash
//IrqMgr_AddClient(audioMgr->irqMgr, &irqClient, &audioMgr->unk_74);
hasInitialized = true;

View File

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

View File

@ -335,38 +335,59 @@ void func_8002BE98(TargetContext* targetCtx, s32 actorCategory, GlobalContext* g
void func_8002BF60(TargetContext* targetCtx, Actor* actor, s32 actorCategory, GlobalContext* globalCtx) {
NaviColor* naviColor = &sNaviColorList[actorCategory];
if (actorCategory == ACTORCAT_PLAYER) {
naviColor->inner.r = CVar_GetS32("gNavi_Idle_Inner_Red", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Idle_Inner_Green", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Idle_Inner_Blue", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Idle_Outer_Red", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Idle_Outer_Green", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Idle_Outer_Blue", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_NPC) {
naviColor->inner.r = CVar_GetS32("gNavi_NPC_Inner_Red", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_NPC_Inner_Green", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_NPC_Inner_Blue", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_NPC_Outer_Red", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_NPC_Outer_Green", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_NPC_Outer_Blue", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) {
naviColor->inner.r = CVar_GetS32("gNavi_Enemy_Inner_Red", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Enemy_Inner_Green", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Enemy_Inner_Blue", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Enemy_Outer_Red", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Enemy_Outer_Green", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Enemy_Outer_Blue", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_PROP) {
naviColor->inner.r = CVar_GetS32("gNavi_Prop_Inner_Red", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Prop_Inner_Green", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Prop_Inner_Blue", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Prop_Outer_Red", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Prop_Outer_Green", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Prop_Outer_Blue", naviColor->outer.b);
if (CVar_GetS32("gUseNaviCol",0) != 1 ) {
if (actorCategory == ACTORCAT_PLAYER) {
naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 255;
naviColor->outer.r = 115; naviColor->outer.g = 230; naviColor->outer.b = 255;
}
if (actorCategory == ACTORCAT_NPC) {
naviColor->inner.r = 100; naviColor->inner.g = 100; naviColor->inner.b = 255;
naviColor->outer.r = 90; naviColor->outer.g = 90; naviColor->outer.b = 255;
}
if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) {
naviColor->inner.r = 255; naviColor->inner.g = 255; naviColor->inner.b = 0;
naviColor->outer.r = 220; naviColor->outer.g = 220; naviColor->outer.b = 0;
}
if (actorCategory == ACTORCAT_PROP) {
naviColor->inner.r = 0; naviColor->inner.g = 255; naviColor->inner.b = 90;
naviColor->outer.r = 0; naviColor->outer.g = 220; naviColor->outer.b = 0;
}
} else {
if (actorCategory == ACTORCAT_PLAYER) {
naviColor->inner.r = CVar_GetS32("gNavi_Idle_Inner_R", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Idle_Inner_G", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Idle_Inner_B", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Idle_Outer_R", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Idle_Outer_G", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Idle_Outer_B", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_NPC) {
naviColor->inner.r = CVar_GetS32("gNavi_NPC_Inner_R", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_NPC_Inner_G", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_NPC_Inner_B", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_NPC_Outer_R", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_NPC_Outer_G", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_NPC_Outer_B", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_BOSS || actorCategory == ACTORCAT_ENEMY) {
naviColor->inner.r = CVar_GetS32("gNavi_Enemy_Inner_R", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Enemy_Inner_G", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Enemy_Inner_B", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Enemy_Outer_R", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Enemy_Outer_G", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Enemy_Outer_B", naviColor->outer.b);
}
if (actorCategory == ACTORCAT_PROP) {
naviColor->inner.r = CVar_GetS32("gNavi_Prop_Inner_R", naviColor->inner.r);
naviColor->inner.g = CVar_GetS32("gNavi_Prop_Inner_G", naviColor->inner.g);
naviColor->inner.b = CVar_GetS32("gNavi_Prop_Inner_B", naviColor->inner.b);
naviColor->outer.r = CVar_GetS32("gNavi_Prop_Outer_R", naviColor->outer.r);
naviColor->outer.g = CVar_GetS32("gNavi_Prop_Outer_G", naviColor->outer.g);
naviColor->outer.b = CVar_GetS32("gNavi_Prop_Outer_B", naviColor->outer.b);
}
}
targetCtx->naviRefPos.x = actor->focus.pos.x;
targetCtx->naviRefPos.y = actor->focus.pos.y + (actor->targetArrowOffset * actor->scale.y);
targetCtx->naviRefPos.z = actor->focus.pos.z;
@ -2269,8 +2290,8 @@ void Actor_DrawFaroresWindPointer(GlobalContext* globalCtx) {
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.y) + yOffset,
((void)0, gSaveContext.respawn[RESPAWN_MODE_TOP].pos.z), 255, 255, 255, lightRadius);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 5474);
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_actor.c", 5474);
}
void func_80030488(GlobalContext* globalCtx) {

View File

@ -1,6 +1,11 @@
#include "global.h"
#include "textures/parameter_static/parameter_static.h"
s16 Top_LM_Margin = 0;
s16 Left_LM_Margin = 0;
s16 Right_LM_Margin = 0;
s16 Bottom_LM_Margin = 0;
static s16 sHeartsPrimColors[3][3] = {
{ HEARTS_PRIM_R, HEARTS_PRIM_G, HEARTS_PRIM_B },
{ HEARTS_BURN_PRIM_R, HEARTS_BURN_PRIM_G, HEARTS_BURN_PRIM_B }, // unused
@ -106,6 +111,9 @@ static s16 sHeartsDDEnvFactors[3][3] = {
};
// Current colors for the double defense hearts
s16 HeartInner[3] = {HEARTS_PRIM_R,HEARTS_PRIM_G,HEARTS_PRIM_B};
s16 HeartDDOutline[3] = {HEARTS_DD_PRIM_R,HEARTS_DD_PRIM_G,HEARTS_DD_PRIM_B};
s16 HeartDDInner[3] = {HEARTS_DD_ENV_R,HEARTS_DD_ENV_G,HEARTS_DD_ENV_B};
s16 sBeatingHeartsDDPrim[3];
s16 sBeatingHeartsDDEnv[3];
s16 sHeartsDDPrim[2][3];
@ -113,35 +121,54 @@ s16 sHeartsDDEnv[2][3];
void HealthMeter_Init(GlobalContext* globalCtx) {
InterfaceContext* interfaceCtx = &globalCtx->interfaceCtx;
if (CVar_GetS32("gHudColors", 1) == 2) {
HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", 90);
HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", 90);
HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", 90);
HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", 90);
HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", 90);
HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", 90);
} else {
HeartInner[0] = HEARTS_PRIM_R;
HeartInner[1] = HEARTS_PRIM_G;
HeartInner[2] = HEARTS_PRIM_B;
HeartDDOutline[0] = HEARTS_DD_PRIM_R;
HeartDDOutline[1] = HEARTS_DD_PRIM_G;
HeartDDOutline[2] = HEARTS_DD_PRIM_B;
}
interfaceCtx->unk_228 = 0x140;
interfaceCtx->unk_226 = gSaveContext.health;
interfaceCtx->unk_22A = interfaceCtx->unk_1FE = 0;
interfaceCtx->unk_22C = interfaceCtx->unk_200 = 0;
interfaceCtx->heartsPrimR[0] = HEARTS_PRIM_R;
interfaceCtx->heartsPrimG[0] = HEARTS_PRIM_G;
interfaceCtx->heartsPrimB[0] = HEARTS_PRIM_B;
interfaceCtx->heartsPrimR[0] = HeartInner[0];
interfaceCtx->heartsPrimG[0] = HeartInner[1];
interfaceCtx->heartsPrimB[0] = HeartInner[2];
interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B;
interfaceCtx->heartsPrimR[1] = HEARTS_PRIM_R;
interfaceCtx->heartsPrimG[1] = HEARTS_PRIM_G;
interfaceCtx->heartsPrimB[1] = HEARTS_PRIM_B;
interfaceCtx->heartsPrimR[1] = HeartInner[0];
interfaceCtx->heartsPrimG[1] = HeartInner[1];
interfaceCtx->heartsPrimB[1] = HeartInner[2];
interfaceCtx->heartsEnvR[1] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[1] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[1] = HEARTS_ENV_B;
sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HEARTS_DD_PRIM_R;
sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HEARTS_DD_PRIM_G;
sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HEARTS_DD_PRIM_B;
sHeartsDDPrim[0][0] = sHeartsDDPrim[1][0] = HeartDDOutline[0];
sHeartsDDPrim[0][1] = sHeartsDDPrim[1][1] = HeartDDOutline[1];
sHeartsDDPrim[0][2] = sHeartsDDPrim[1][2] = HeartDDOutline[2];
sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HEARTS_DD_ENV_R;
sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HEARTS_DD_ENV_G;
sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HEARTS_DD_ENV_B;
sHeartsDDPrim[2][0] = HeartInner[0];
sHeartsDDPrim[2][1] = HeartInner[1];
sHeartsDDPrim[2][2] = HeartInner[2];
sHeartsDDEnv[0][0] = sHeartsDDEnv[1][0] = HeartDDInner[0];
sHeartsDDEnv[0][1] = sHeartsDDEnv[1][1] = HeartDDInner[1];
sHeartsDDEnv[0][2] = sHeartsDDEnv[1][2] = HeartDDInner[2];
}
void HealthMeter_Update(GlobalContext* globalCtx) {
@ -154,7 +181,33 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
s16 gFactor;
s16 bFactor;
if (interfaceCtx) {}
if (CVar_GetS32("gHUDMargins", 0) != 0) {
Top_LM_Margin = CVar_GetS32("gHUDMargin_T", 0);
Left_LM_Margin = CVar_GetS32("gHUDMargin_L", 0);
Right_LM_Margin = CVar_GetS32("gHUDMargin_R", 0);
Bottom_LM_Margin = CVar_GetS32("gHUDMargin_B", 0);
} else {
Top_LM_Margin = 0;
Left_LM_Margin = 0;
Right_LM_Margin = 0;
Bottom_LM_Margin = 0;
}
if (CVar_GetS32("gHudColors", 1) == 2) {
HeartInner[0] = CVar_GetS32("gCCHeartsPrimR", sHeartsPrimColors[0][0]);
HeartInner[1] = CVar_GetS32("gCCHeartsPrimG", sHeartsPrimColors[0][1]);
HeartInner[2] = CVar_GetS32("gCCHeartsPrimB", sHeartsPrimColors[0][2]);
HeartDDOutline[0] = CVar_GetS32("gDDCCHeartsPrimR", sHeartsDDPrim[0][0]);
HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", sHeartsDDPrim[0][1]);
HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", sHeartsDDPrim[0][2]);
} else {
HeartInner[0] = HEARTS_PRIM_R;
HeartInner[1] = HEARTS_PRIM_G;
HeartInner[2] = HEARTS_PRIM_B;
HeartDDOutline[0] = HEARTS_DD_PRIM_R;
HeartDDOutline[1] = HEARTS_DD_PRIM_G;
HeartDDOutline[2] = HEARTS_DD_PRIM_B;
}
if (interfaceCtx->unk_200 != 0) {
interfaceCtx->unk_1FE--;
@ -172,17 +225,23 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
ddFactor = factor;
interfaceCtx->heartsPrimR[0] = HEARTS_PRIM_R;
interfaceCtx->heartsPrimG[0] = HEARTS_PRIM_G;
interfaceCtx->heartsPrimB[0] = HEARTS_PRIM_B;
interfaceCtx->heartsPrimR[0] = HeartInner[0];
interfaceCtx->heartsPrimG[0] = HeartInner[1];
interfaceCtx->heartsPrimB[0] = HeartInner[2];
interfaceCtx->heartsEnvR[0] = HEARTS_ENV_R;
interfaceCtx->heartsEnvG[0] = HEARTS_ENV_G;
interfaceCtx->heartsEnvB[0] = HEARTS_ENV_B;
interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0];
interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1];
interfaceCtx->heartsPrimB[1] = sHeartsPrimColors[type][2];
if (CVar_GetS32("gHudColors", 1) == 2) {
interfaceCtx->heartsPrimR[1] = HeartInner[0];
interfaceCtx->heartsPrimG[1] = HeartInner[1];
interfaceCtx->heartsPrimB[1] = HeartInner[2];
} else {
interfaceCtx->heartsPrimR[1] = sHeartsPrimColors[type][0];
interfaceCtx->heartsPrimG[1] = sHeartsPrimColors[type][1];
interfaceCtx->heartsPrimB[1] = sHeartsPrimColors[type][2];
}
interfaceCtx->heartsEnvR[1] = sHeartsEnvColors[type][0];
interfaceCtx->heartsEnvG[1] = sHeartsEnvColors[type][1];
@ -192,52 +251,90 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
gFactor = sHeartsPrimFactors[0][1] * factor;
bFactor = sHeartsPrimFactors[0][2] * factor;
interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HEARTS_PRIM_R) & 0xFF;
interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HEARTS_PRIM_G) & 0xFF;
interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HEARTS_PRIM_B) & 0xFF;
interfaceCtx->beatingHeartPrim[0] = (u8)(rFactor + HeartInner[0]) & 0xFF;
interfaceCtx->beatingHeartPrim[1] = (u8)(gFactor + HeartInner[1]) & 0xFF;
interfaceCtx->beatingHeartPrim[2] = (u8)(bFactor + HeartInner[2]) & 0xFF;
rFactor = sHeartsEnvFactors[0][0] * factor;
gFactor = sHeartsEnvFactors[0][1] * factor;
bFactor = sHeartsEnvFactors[0][2] * factor;
if (1) {}
ddType = type;
interfaceCtx->beatingHeartEnv[0] = (u8)(rFactor + HEARTS_ENV_R) & 0xFF;
interfaceCtx->beatingHeartEnv[1] = (u8)(gFactor + HEARTS_ENV_G) & 0xFF;
interfaceCtx->beatingHeartEnv[2] = (u8)(bFactor + HEARTS_ENV_B) & 0xFF;
sHeartsDDPrim[0][0] = HEARTS_DD_PRIM_R;
sHeartsDDPrim[0][1] = HEARTS_DD_PRIM_G;
sHeartsDDPrim[0][2] = HEARTS_DD_PRIM_B;
ddType = type;
sHeartsDDEnv[0][0] = HEARTS_DD_ENV_R;
sHeartsDDEnv[0][1] = HEARTS_DD_ENV_G;
sHeartsDDEnv[0][2] = HEARTS_DD_ENV_B;
sHeartsDDPrim[0][0] = HeartDDOutline[0];
sHeartsDDPrim[0][1] = HeartDDOutline[1];
sHeartsDDPrim[0][2] = HeartDDOutline[2];
sHeartsDDPrim[1][0] = sHeartsDDPrimColors[ddType][0];
sHeartsDDPrim[1][1] = sHeartsDDPrimColors[ddType][1];
sHeartsDDPrim[1][2] = sHeartsDDPrimColors[ddType][2];
sHeartsDDEnv[0][0] = HeartDDInner[0];
sHeartsDDEnv[0][1] = HeartDDInner[1];
sHeartsDDEnv[0][2] = HeartDDInner[2];
sHeartsDDEnv[1][0] = sHeartsDDEnvColors[ddType][0];
sHeartsDDEnv[1][1] = sHeartsDDEnvColors[ddType][1];
sHeartsDDEnv[1][2] = sHeartsDDEnvColors[ddType][2];
if (CVar_GetS32("gHudColors", 1) == 2) {
sHeartsDDPrim[2][0] = HeartInner[0];
sHeartsDDPrim[2][1] = HeartInner[1];
sHeartsDDPrim[2][2] = HeartInner[2];
rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor;
sHeartsDDPrim[1][0] = HeartDDOutline[0];
sHeartsDDPrim[1][1] = HeartDDOutline[1];
sHeartsDDPrim[1][2] = HeartDDOutline[2];
sBeatingHeartsDDPrim[0] = (u8)(rFactor + HEARTS_DD_PRIM_R) & 0xFF;
sBeatingHeartsDDPrim[1] = (u8)(gFactor + HEARTS_DD_PRIM_G) & 0xFF;
sBeatingHeartsDDPrim[2] = (u8)(bFactor + HEARTS_DD_PRIM_B) & 0xFF;
sHeartsDDEnv[1][0] = HeartDDInner[0];
sHeartsDDEnv[1][1] = HeartDDInner[1];
sHeartsDDEnv[1][2] = HeartDDInner[2];
rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor;
HeartDDInner[0] = HeartInner[0];
HeartDDInner[1] = HeartInner[1];
HeartDDInner[2] = HeartInner[2];
rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor;
sBeatingHeartsDDPrim[0] = (u8)(rFactor + HeartDDOutline[0]) & 0xFF;
sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF;
sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF;
rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor;
sBeatingHeartsDDEnv[0] = (u8)(rFactor + HeartDDInner[0]) & 0xFF;
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF;
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF;
} else {
sHeartsDDPrim[2][0] = HEARTS_PRIM_R;
sHeartsDDPrim[2][1] = HEARTS_PRIM_G;
sHeartsDDPrim[2][2] = HEARTS_PRIM_B;
sHeartsDDPrim[1][0] = HEARTS_DD_PRIM_R;
sHeartsDDPrim[1][1] = HEARTS_DD_PRIM_G;
sHeartsDDPrim[1][2] = HEARTS_DD_PRIM_B;
sHeartsDDEnv[1][0] = HEARTS_PRIM_R;
sHeartsDDEnv[1][1] = HEARTS_PRIM_G;
sHeartsDDEnv[1][2] = HEARTS_PRIM_B;
rFactor = sHeartsDDPrimFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDPrimFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDPrimFactors[ddType][2] * ddFactor;
sBeatingHeartsDDPrim[0] = (u8)(rFactor + HEARTS_DD_PRIM_R) & 0xFF;
sBeatingHeartsDDPrim[1] = (u8)(gFactor + HEARTS_DD_PRIM_G) & 0xFF;
sBeatingHeartsDDPrim[2] = (u8)(bFactor + HEARTS_DD_PRIM_B) & 0xFF;
rFactor = sHeartsDDEnvFactors[ddType][0] * ddFactor;
gFactor = sHeartsDDEnvFactors[ddType][1] * ddFactor;
bFactor = sHeartsDDEnvFactors[ddType][2] * ddFactor;
sBeatingHeartsDDEnv[0] = (u8)(rFactor + HEARTS_PRIM_R) & 0xFF;
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HEARTS_PRIM_G) & 0xFF;
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HEARTS_PRIM_B) & 0xFF;
}
sBeatingHeartsDDEnv[0] = (u8)(rFactor + HEARTS_DD_ENV_R) & 0xFF;
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HEARTS_DD_ENV_G) & 0xFF;
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HEARTS_DD_ENV_B) & 0xFF;
}
s32 func_80078E18(GlobalContext* globalCtx) {
@ -322,8 +419,8 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
}
curColorSet = -1;
offsetY = 0.0f;
offsetX = OTRGetDimensionFromLeftEdge(0.0f);
offsetY = 0.0f+(Top_LM_Margin*-1);
offsetX = OTRGetDimensionFromLeftEdge(0.0f)+(Left_LM_Margin*-1);
for (i = 0; i < totalHeartCount; i++) {
if ((ddHeartCountMinusOne < 0) || (i > ddHeartCountMinusOne)) {
@ -483,7 +580,7 @@ void HealthMeter_Draw(GlobalContext* globalCtx) {
offsetX += 10.0f;
if (i == 9) {
offsetY += 10.0f;
offsetX = OTRGetDimensionFromLeftEdge(0.0f);
offsetX = OTRGetDimensionFromLeftEdge(0.0f)+(Left_LM_Margin*-1);
}
}
@ -498,8 +595,8 @@ void HealthMeter_HandleCriticalAlarm(GlobalContext* globalCtx) {
if (interfaceCtx->unk_22A <= 0) {
interfaceCtx->unk_22A = 0;
interfaceCtx->unk_22C = 0;
if (!Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
if (CVar_GetS32("gLowHpAlarm", 0) == 0 && !Player_InCsMode(globalCtx) && (globalCtx->pauseCtx.state == 0) &&
(globalCtx->pauseCtx.debugState == 0) && HealthMeter_IsCritical() && !Gameplay_InCsMode(globalCtx)) {
func_80078884(NA_SE_SY_HITPOINT_ALARM);
}
}
@ -530,4 +627,4 @@ u32 HealthMeter_IsCritical(void) {
} else {
return false;
}
}
}

View File

@ -12,6 +12,11 @@ s16 sPlayerInitialPosZ = 0;
s16 sPlayerInitialDirection = 0;
s16 sEntranceIconMapIndex = 0;
s16 Top_MM_Margin = 0;
s16 Left_MM_Margin = 0;
s16 Right_MM_Margin = 0;
s16 Bottom_MM_Margin = 0;
void Map_SavePlayerInitialInfo(GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
@ -604,11 +609,11 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) {
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_PRIMITIVE, G_CC_PRIMITIVE);
tempX = player->actor.world.pos.x;
tempZ = player->actor.world.pos.z;
tempX = player->actor.world.pos.x+Right_MM_Margin;
tempZ = player->actor.world.pos.z+Bottom_MM_Margin;
tempX /= R_COMPASS_SCALE_X;
tempZ /= R_COMPASS_SCALE_Y;
Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + tempX) / 10.0f), (R_COMPASS_OFFSET_Y - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(Right_MM_Margin*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Bottom_MM_Margin*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
Matrix_Scale(0.4f, 0.4f, 0.4f, MTXMODE_APPLY);
Matrix_RotateX(-1.6f, MTXMODE_APPLY);
tempX = (0x7FFF - player->actor.shape.rot.y) / 0x400;
@ -619,11 +624,11 @@ void Minimap_DrawCompassIcons(GlobalContext* globalCtx) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 255, 0, 255);
gSPDisplayList(OVERLAY_DISP++, gCompassArrowDL);
tempX = sPlayerInitialPosX;
tempZ = sPlayerInitialPosZ;
tempX = sPlayerInitialPosX+Right_MM_Margin;
tempZ = sPlayerInitialPosZ+Bottom_MM_Margin;
tempX /= R_COMPASS_SCALE_X;
tempZ /= R_COMPASS_SCALE_Y;
Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X + tempX) / 10.0f), (R_COMPASS_OFFSET_Y - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
Matrix_Translate(OTRGetDimensionFromRightEdge((R_COMPASS_OFFSET_X+(Right_MM_Margin*10) + tempX) / 10.0f), (R_COMPASS_OFFSET_Y+((Bottom_MM_Margin*10)*-1) - tempZ) / 10.0f, 0.0f, MTXMODE_NEW);
Matrix_Scale(VREG(9) / 100.0f, VREG(9) / 100.0f, VREG(9) / 100.0f, MTXMODE_APPLY);
Matrix_RotateX(VREG(52) / 10.0f, MTXMODE_APPLY);
Matrix_RotateY(sPlayerInitialDirection / 10.0f, MTXMODE_APPLY);
@ -662,17 +667,22 @@ void Minimap_Draw(GlobalContext* globalCtx) {
TEXEL0, 0, PRIMITIVE, 0);
if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, mapIndex)) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 100, 255, 255, interfaceCtx->minimapAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) { //Dungeon minimap
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 100, 255, 255, interfaceCtx->minimapAlpha);
}
gSPInvalidateTexCache(OVERLAY_DISP++, interfaceCtx->mapSegment);
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_I, 96, 85, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
const s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X);
const s16 dgnMiniMapX = OTRGetRectDimensionFromRightEdge(R_DGN_MINIMAP_X + Right_MM_Margin);
const s16 dgnMiniMapY = R_DGN_MINIMAP_Y + Bottom_MM_Margin;
gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, R_DGN_MINIMAP_Y << 2,
(dgnMiniMapX + 96) << 2, (R_DGN_MINIMAP_Y + 85) << 2, G_TX_RENDERTILE,
gSPWideTextureRectangle(OVERLAY_DISP++, dgnMiniMapX << 2, dgnMiniMapY << 2,
(dgnMiniMapX + 96) << 2, (dgnMiniMapY + 85) << 2, G_TX_RENDERTILE,
0, 0, 1 << 10, 1 << 10);
}
@ -719,27 +729,35 @@ void Minimap_Draw(GlobalContext* globalCtx) {
func_80094520(globalCtx->state.gfxCtx);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2),
interfaceCtx->minimapAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {//Overworld minimap
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMinimapPrimR", R_MINIMAP_COLOR(0)), CVar_GetS32("gCCMinimapPrimG", R_MINIMAP_COLOR(1)), CVar_GetS32("gCCMinimapPrimB", R_MINIMAP_COLOR(2)), interfaceCtx->minimapAlpha);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha);
}
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->mapSegment, G_IM_FMT_IA,
gMapData->owMinimapWidth[mapIndex], gMapData->owMinimapHeight[mapIndex], 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
const s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X);
const s16 oWMiniMapX = OTRGetRectDimensionFromRightEdge(R_OW_MINIMAP_X + Right_MM_Margin);
const s16 oWMiniMapY = R_OW_MINIMAP_Y + Bottom_MM_Margin;
gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, R_OW_MINIMAP_Y << 2,
gSPWideTextureRectangle(OVERLAY_DISP++, oWMiniMapX << 2, oWMiniMapY << 2,
(oWMiniMapX + gMapData->owMinimapWidth[mapIndex]) << 2,
(R_OW_MINIMAP_Y + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, 0,
(oWMiniMapY + gMapData->owMinimapHeight[mapIndex]) << 2, G_TX_RENDERTILE, 0,
0, 1 << 10, 1 << 10);
if (CVar_GetS32("gHudColors", 1) != 2) {//This need to be added else it will color dungeon entrance icon too. (it re-init prim color to default color)
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MINIMAP_COLOR(0), R_MINIMAP_COLOR(1), R_MINIMAP_COLOR(2), interfaceCtx->minimapAlpha);
}
if (((globalCtx->sceneNum != SCENE_SPOT01) && (globalCtx->sceneNum != SCENE_SPOT04) &&
(globalCtx->sceneNum != SCENE_SPOT08)) ||
(LINK_AGE_IN_YEARS != YEARS_ADULT)) {
s16 IconSize = 8;
s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex];
s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex];
s16 PosX = gMapData->owEntranceIconPosX[sEntranceIconMapIndex]+Right_MM_Margin;
s16 PosY = gMapData->owEntranceIconPosY[sEntranceIconMapIndex]+Bottom_MM_Margin;
//gFixDungeonMinimapIcon fix both Y position of visible icon and hide these non needed.
if (CVar_GetS32("gFixDungeonMinimapIcon", 1) != 0){
//No idea why and how Original value work but this does actually fix them all.
@ -766,14 +784,20 @@ void Minimap_Draw(GlobalContext* globalCtx) {
}
}
const s16 entranceX = OTRGetRectDimensionFromRightEdge(270 + Right_MM_Margin);
const s16 entranceY = 154 + Bottom_MM_Margin;
if ((globalCtx->sceneNum == SCENE_SPOT08) && (gSaveContext.infTable[26] & gBitFlags[9])) {
gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8,
8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2,
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
} else if ((globalCtx->sceneNum == SCENE_SPOT08) && CVar_GetS32("gAlwaysShowDungeonMinimapIcon", 0) != 0){
gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b, 8,
8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
const s16 entranceX = OTRGetRectDimensionFromRightEdge(270);
gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, 154 << 2, (entranceX + 32) << 2, (154 + 8) << 2,
gSPWideTextureRectangle(OVERLAY_DISP++, entranceX << 2, entranceY << 2, (entranceX + 32) << 2, (entranceY + 8) << 2,
G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
}
@ -809,6 +833,18 @@ void Map_Update(GlobalContext* globalCtx) {
s16 floor;
s16 i;
if (CVar_GetS32("gHUDMargins", 0) != 0) {
Top_MM_Margin = CVar_GetS32("gHUDMargin_T", 0);
Left_MM_Margin = CVar_GetS32("gHUDMargin_L", 0);
Right_MM_Margin = CVar_GetS32("gHUDMargin_R", 0);
Bottom_MM_Margin = CVar_GetS32("gHUDMargin_B", 0);
} else {
Top_MM_Margin = 0;
Left_MM_Margin = 0;
Right_MM_Margin = 0;
Bottom_MM_Margin = 0;
}
if ((globalCtx->pauseCtx.state == 0) && (globalCtx->pauseCtx.debugState == 0)) {
switch (globalCtx->sceneNum) {
case SCENE_YDAN:

View File

@ -108,6 +108,22 @@ void MapMark_DrawForDungeon(GlobalContext* globalCtx) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->minimapAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, interfaceCtx->minimapAlpha);
s16 Top_MC_Margin = 0;
s16 Left_MC_Margin = 0;
s16 Right_MC_Margin = 0;
s16 Bottom_MC_Margin = 0;
if (CVar_GetS32("gHUDMargins", 0) != 0) {
Top_MC_Margin = CVar_GetS32("gHUDMargin_T", 0);
Left_MC_Margin = CVar_GetS32("gHUDMargin_L", 0);
Right_MC_Margin = CVar_GetS32("gHUDMargin_R", 0);
Bottom_MC_Margin = CVar_GetS32("gHUDMargin_B", 0);
} else {
Top_MC_Margin = 0;
Left_MC_Margin = 0;
Right_MC_Margin = 0;
Bottom_MC_Margin = 0;
}
markPoint = &mapMarkIconData->points[0];
for (i = 0; i < mapMarkIconData->count; i++) {
if ((mapMarkIconData->markType != MAP_MARK_CHEST) || !Flags_GetTreasure(globalCtx, markPoint->chestFlag)) {
@ -118,8 +134,8 @@ void MapMark_DrawForDungeon(GlobalContext* globalCtx) {
markInfo->textureWidth, markInfo->textureHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
rectLeft = (GREG(94) + OTRGetRectDimensionFromRightEdge(markPoint->x) + 204) << 2;
rectTop = (GREG(95) + markPoint->y + 140) << 2;
rectLeft = (GREG(94) + OTRGetRectDimensionFromRightEdge(markPoint->x+Right_MC_Margin) + 204) << 2;
rectTop = (GREG(95) + markPoint->y + Bottom_MC_Margin + 140) << 2;
gSPTextureRectangle(OVERLAY_DISP++, rectLeft, rectTop, markInfo->rectWidth + rectLeft,
rectTop + markInfo->rectHeight, G_TX_RENDERTILE, 0, 0, markInfo->dsdx,
markInfo->dtdy);

View File

@ -272,6 +272,13 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) {
const char** languageSegmentTable;
Font* font;
const char* seg;
u16 bufferId = textId;
// Use the better owl message if better owl is enabled
if (CVar_GetS32("gBetterOwl", 0) != 0 && (bufferId == 0x2066 || bufferId == 0x607B ||
bufferId == 0x10C2 || bufferId == 0x10C6 || bufferId == 0x206A))
{
bufferId = 0x71B3;
}
if (gSaveContext.language == LANGUAGE_GER)
messageTableEntry = sGerMessageEntryTablePtr;
@ -287,7 +294,7 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) {
while (messageTableEntry->textId != 0xFFFF) {
font = &globalCtx->msgCtx.font;
if (messageTableEntry->textId == textId) {
if (messageTableEntry->textId == bufferId) {
foundSeg = messageTableEntry->segment;
font->charTexBuf[0] = messageTableEntry->typePos;
@ -298,14 +305,14 @@ void Message_FindMessage(GlobalContext* globalCtx, u16 textId) {
// "Message found!!!"
osSyncPrintf(" メッセージが,見つかった!!! = %x "
"(data=%x) (data0=%x) (data1=%x) (data2=%x) (data3=%x)\n",
textId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg);
bufferId, font->msgOffset, font->msgLength, foundSeg, seg, nextSeg);
return;
}
messageTableEntry++;
}
// "Message not found!!!"
osSyncPrintf(" メッセージが,見つからなかった!!! = %x\n", textId);
osSyncPrintf(" メッセージが,見つからなかった!!! = %x\n", bufferId);
font = &globalCtx->msgCtx.font;
messageTableEntry = sNesMessageEntryTablePtr;
@ -446,6 +453,46 @@ void Message_DrawTextboxIcon(GlobalContext* globalCtx, Gfx** p, s16 x, s16 y) {
static s16 sIconEnvR = 0;
static s16 sIconEnvG = 0;
static s16 sIconEnvB = 0;
if (CVar_GetS32("gHudColors", 1) == 0) {
sIconPrimColors[0][0] = 4;
sIconPrimColors[0][1] = 84;
sIconPrimColors[0][2] = 204;
sIconPrimColors[1][0] = 45;
sIconPrimColors[1][1] = 125;
sIconPrimColors[1][2] = 255;
sIconEnvColors[0][0] = 0;
sIconEnvColors[0][1] = 0;
sIconEnvColors[0][2] = 0;
sIconEnvColors[1][0] = 0;
sIconEnvColors[1][1] = 70;
sIconEnvColors[1][2] = 255;
} else if (CVar_GetS32("gHudColors", 1) == 1) {
sIconPrimColors[0][0] = 4;
sIconPrimColors[0][1] = 200;
sIconPrimColors[0][2] = 80;
sIconPrimColors[1][0] = 50;
sIconPrimColors[1][1] = 255;
sIconPrimColors[1][2] = 130;
sIconEnvColors[0][0] = 0;
sIconEnvColors[0][1] = 0;
sIconEnvColors[0][2] = 0;
sIconEnvColors[1][0] = 0;
sIconEnvColors[1][1] = 255;
sIconEnvColors[1][2] = 130;
} else if (CVar_GetS32("gHudColors", 1) == 2) {
sIconPrimColors[0][0] = (CVar_GetS32("gCCABtnPrimR", 50)/255)*95;
sIconPrimColors[0][1] = (CVar_GetS32("gCCABtnPrimG", 255)/255)*95;
sIconPrimColors[0][2] = (CVar_GetS32("gCCABtnPrimB", 130)/255)*95;
sIconPrimColors[1][0] = CVar_GetS32("gCCABtnPrimR", 50);
sIconPrimColors[1][1] = CVar_GetS32("gCCABtnPrimG", 255);
sIconPrimColors[1][2] = CVar_GetS32("gCCABtnPrimB", 130);
sIconEnvColors[0][0] = 0;
sIconEnvColors[0][1] = 0;
sIconEnvColors[0][2] = 0;
sIconEnvColors[1][0] = 10;
sIconEnvColors[1][1] = 10;
sIconEnvColors[1][2] = 10;
}
MessageContext* msgCtx = &globalCtx->msgCtx;
Font* font = &msgCtx->font;
Gfx* gfx = *p;
@ -1843,6 +1890,7 @@ void Message_DrawTextBox(GlobalContext* globalCtx, Gfx** p) {
MessageContext* msgCtx = &globalCtx->msgCtx;
Gfx* gfx = *p;
gSPInvalidateTexCache(gfx++, msgCtx->textboxSegment);
gDPPipeSync(gfx++);
gDPSetPrimColor(gfx++, 0, 0, msgCtx->textboxColorRed, msgCtx->textboxColorGreen, msgCtx->textboxColorBlue,
msgCtx->textboxColorAlphaCurrent);
@ -2828,12 +2876,22 @@ void Message_DrawMain(GlobalContext* globalCtx, Gfx** p) {
gDPPipeSync(gfx++);
if (sOcarinaNoteBuf[i] == OCARINA_NOTE_A) {
gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteAPrimR, sOcarinaNoteAPrimG, sOcarinaNoteAPrimB,
sOcarinaNotesAlphaValues[i]);
if (CVar_GetS32("gHudColors", 1) == 0) { //A buttons :)
gDPSetPrimColor(gfx++, 0, 0, 80, 150, 255, sOcarinaNotesAlphaValues[i]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteAPrimR, sOcarinaNoteAPrimG, sOcarinaNoteAPrimB, sOcarinaNotesAlphaValues[i]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(gfx++, 0, 0, CVar_GetS32("gCCABtnPrimR", 0), CVar_GetS32("gCCABtnPrimG", 0), CVar_GetS32("gCCABtnPrimB", 0), sOcarinaNotesAlphaValues[i]);
}
gDPSetEnvColor(gfx++, sOcarinaNoteAEnvR, sOcarinaNoteAEnvG, sOcarinaNoteAEnvB, 0);
} else {
gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB,
sOcarinaNotesAlphaValues[i]);
if (CVar_GetS32("gHudColors", 1) == 0) { //C buttons :)
gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB, sOcarinaNotesAlphaValues[i]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(gfx++, 0, 0, sOcarinaNoteCPrimR, sOcarinaNoteCPrimG, sOcarinaNoteCPrimB, sOcarinaNotesAlphaValues[i]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(gfx++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 0), CVar_GetS32("gCCCBtnPrimG", 0), CVar_GetS32("gCCCBtnPrimB", 0), sOcarinaNotesAlphaValues[i]);
}
gDPSetEnvColor(gfx++, sOcarinaNoteCEnvR, sOcarinaNoteCEnvG, sOcarinaNoteCEnvB, 0);
}

View File

@ -15,6 +15,11 @@
#define DO_ACTION_TEX_HEIGHT 16
#define DO_ACTION_TEX_SIZE ((DO_ACTION_TEX_WIDTH * DO_ACTION_TEX_HEIGHT) / 2) // (sizeof(gCheckDoActionENGTex))
s16 Top_HUD_Margin = 0;
s16 Left_HUD_Margin = 0;
s16 Right_HUD_Margin = 0;
s16 Bottom_HUD_Margin = 0;
typedef struct {
/* 0x00 */ u8 scene;
/* 0x01 */ u8 flags1;
@ -753,7 +758,15 @@ void func_80083108(GlobalContext* globalCtx) {
gSaveContext.buttonStatus[0] = BTN_DISABLED;
for (i = 1; i < 4; i++) {
if (func_8008F2F8(globalCtx) == 2) {
if ((gSaveContext.equips.buttonItems[i] >= ITEM_SHIELD_DEKU) &&
(gSaveContext.equips.buttonItems[i] <= ITEM_BOOTS_HOVER)) {
// Equipment on c-buttons is always enabled
if (gSaveContext.buttonStatus[i] == BTN_DISABLED) {
sp28 = 1;
}
gSaveContext.buttonStatus[i] = BTN_ENABLED;
} else if (func_8008F2F8(globalCtx) == 2) {
if ((gSaveContext.equips.buttonItems[i] != ITEM_HOOKSHOT) &&
(gSaveContext.equips.buttonItems[i] != ITEM_LONGSHOT)) {
if (gSaveContext.buttonStatus[i] == BTN_ENABLED) {
@ -1795,7 +1808,7 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
}
}
} else if ((item >= ITEM_WEIRD_EGG) && (item <= ITEM_CLAIM_CHECK)) {
if (item == ITEM_SAW) {
if ((item == ITEM_SAW) && CVar_GetS32("gDekuNutUpgradeFix", 0) == 0) {
gSaveContext.itemGetInf[1] |= 0x8000;
}
@ -2151,13 +2164,15 @@ void Interface_SetNaviCall(GlobalContext* globalCtx, u16 naviCallState) {
if (((naviCallState == 0x1D) || (naviCallState == 0x1E)) && !interfaceCtx->naviCalling &&
(globalCtx->csCtx.state == CS_STATE_IDLE)) {
// clang-format off
if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
// clang-format on
if (!CVar_GetS32("gDisableNaviCallAudio", 0)) {
// clang-format off
if (naviCallState == 0x1E) { Audio_PlaySoundGeneral(NA_SE_VO_NAVY_CALL, &D_801333D4, 4,
&D_801333E0, &D_801333E0, &D_801333E8); }
// clang-format on
if (naviCallState == 0x1D) {
func_800F4524(&D_801333D4, NA_SE_VO_NA_HELLO_2, 32);
if (naviCallState == 0x1D) {
func_800F4524(&D_801333D4, NA_SE_VO_NA_HELLO_2, 32);
}
}
interfaceCtx->naviCalling = 1;
@ -2433,6 +2448,25 @@ void Interface_UpdateMagicBar(GlobalContext* globalCtx) {
{ 255, 255, 150 },
{ 255, 255, 50 },
};
if (CVar_GetS32("gHudColors", 1) == 2) { //This will make custom color based on users selected colors.
sMagicBorderColors[0][0] = CVar_GetS32("gCCMagicBorderPrimR", 255);
sMagicBorderColors[0][1] = CVar_GetS32("gCCMagicBorderPrimG", 255);
sMagicBorderColors[0][2] = CVar_GetS32("gCCMagicBorderPrimB", 255);
sMagicBorderColors[1][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2;
sMagicBorderColors[1][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2;
sMagicBorderColors[1][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2;
sMagicBorderColors[2][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/3;
sMagicBorderColors[2][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/3;
sMagicBorderColors[2][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/3;
sMagicBorderColors[3][0] = CVar_GetS32("gCCMagicBorderPrimR", 255)/2;
sMagicBorderColors[3][1] = CVar_GetS32("gCCMagicBorderPrimG", 255)/2;
sMagicBorderColors[3][2] = CVar_GetS32("gCCMagicBorderPrimB", 255)/2;
}
static s16 sMagicBorderIndexes[] = { 0, 1, 1, 0 };
static s16 sMagicBorderRatio = 2;
static s16 sMagicBorderStep = 1;
@ -2623,27 +2657,31 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
if (gSaveContext.magicLevel != 0) {
if (gSaveContext.healthCapacity > 0xA0) {
magicBarY = R_MAGIC_BAR_LARGE_Y;
magicBarY = R_MAGIC_BAR_LARGE_Y + (Top_HUD_Margin*-1);
} else {
magicBarY = R_MAGIC_BAR_SMALL_Y;
magicBarY = R_MAGIC_BAR_SMALL_Y + (Top_HUD_Margin*-1);
}
func_80094520(globalCtx->state.gfxCtx);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, sMagicBorderR, sMagicBorderG, sMagicBorderB, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255);
if (CVar_GetS32("gHudColors", 1) == 2) {//Original game add color there so to prevent miss match we make it all white :)
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
} else {
gDPSetEnvColor(OVERLAY_DISP++, 100, 50, 50, 255);
}
OVERLAY_DISP =
Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X),
Gfx_TextureIA8(OVERLAY_DISP, gMagicBarEndTex, 8, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1)),
magicBarY, 8, 16, 1 << 10, 1 << 10);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarMidTex, 24, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X) + 8, magicBarY,
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gMagicBarMidTex, 24, 16, OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1)) + 8, magicBarY,
gSaveContext.unk_13F4, 16, 1 << 10, 1 << 10);
gDPLoadTextureBlock(OVERLAY_DISP++, gMagicBarEndTex, G_IM_FMT_IA, G_IM_SIZ_8b, 8, 16, 0,
G_TX_MIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 3, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
const s16 rMagicBarX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X);
const s16 rMagicBarX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_BAR_X + (Left_HUD_Margin*-1));
gSPWideTextureRectangle(OVERLAY_DISP++, ((rMagicBarX + gSaveContext.unk_13F4) + 8) << 2, magicBarY << 2,
((rMagicBarX + gSaveContext.unk_13F4) + 16) << 2, (magicBarY + 16) << 2, G_TX_RENDERTILE,
@ -2654,11 +2692,15 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, PRIMITIVE);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
const s16 rMagicFillX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_FILL_X);
const s16 rMagicFillX = OTRGetRectDimensionFromLeftEdge(R_MAGIC_FILL_X + (Left_HUD_Margin*-1));
if (gSaveContext.unk_13F0 == 4) {
// Yellow part of the bar indicating the amount of magic to be subtracted
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicUsePrimR", 250), CVar_GetS32("gCCMagicUsePrimG", 250), CVar_GetS32("gCCMagicUsePrimB", 0), interfaceCtx->magicAlpha);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 250, 250, 0, interfaceCtx->magicAlpha);
}
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
@ -2670,16 +2712,22 @@ void Interface_DrawMagicBar(GlobalContext* globalCtx) {
// Fill the rest of the bar with the normal magic color
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2),
interfaceCtx->magicAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha);
}
gSPWideTextureRectangle(OVERLAY_DISP++, rMagicFillX << 2, (magicBarY + 3) << 2,
(rMagicFillX + gSaveContext.unk_13F8) << 2, (magicBarY + 10) << 2, G_TX_RENDERTILE,
0, 0, 1 << 10, 1 << 10);
} else {
// Fill the whole bar with the normal magic color
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2),
interfaceCtx->magicAlpha);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCMagicPrimR", 0), CVar_GetS32("gCCMagicPrimG", 200), CVar_GetS32("gCCMagicPrimB", 0), interfaceCtx->magicAlpha);
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_MAGIC_FILL_COLOR(0), R_MAGIC_FILL_COLOR(1), R_MAGIC_FILL_COLOR(2), interfaceCtx->magicAlpha);
}
gDPLoadMultiBlock_4b(OVERLAY_DISP++, gMagicBarFillTex, 0, G_TX_RENDERTILE, G_IM_FMT_I, 16, 16, 0,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
@ -2753,58 +2801,109 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
s16 width;
s16 height;
s16 C_Left_BTN_Pos[] = { C_LEFT_BUTTON_X+Right_HUD_Margin, C_LEFT_BUTTON_Y+(Top_HUD_Margin*-1) }; //(X,Y)
s16 C_Right_BTN_Pos[] = { C_RIGHT_BUTTON_X+Right_HUD_Margin, C_RIGHT_BUTTON_Y+(Top_HUD_Margin*-1) };
s16 C_Up_BTN_Pos[] = { C_UP_BUTTON_X+Right_HUD_Margin, C_UP_BUTTON_Y+(Top_HUD_Margin*-1) };
s16 C_Down_BTN_Pos[] = { C_DOWN_BUTTON_X+Right_HUD_Margin, C_DOWN_BUTTON_Y+(Top_HUD_Margin*-1) };
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 2900);
// B Button Color & Texture
// Also loads the Item Button Texture reused by other buttons afterwards
gDPPipeSync(OVERLAY_DISP++);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2), interfaceCtx->bAlpha);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 150, 0, interfaceCtx->bAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_B_BTN_COLOR(0), R_B_BTN_COLOR(1), R_B_BTN_COLOR(2), interfaceCtx->bAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCBBtnPrimR", R_B_BTN_COLOR(0)), CVar_GetS32("gCCBBtnPrimG", R_B_BTN_COLOR(1)), CVar_GetS32("gCCBBtnPrimB", R_B_BTN_COLOR(2)), interfaceCtx->bAlpha);
}
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255);
OVERLAY_DISP =
Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, 32, 32, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(0)), R_ITEM_BTN_Y(0),
Gfx_TextureIA8(OVERLAY_DISP, gButtonBackgroundTex, 32, 32, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(0)+Right_HUD_Margin), R_ITEM_BTN_Y(0)+(Top_HUD_Margin*-1),
R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_WIDTH(0), R_ITEM_BTN_DD(0) << 1, R_ITEM_BTN_DD(0) << 1);
// C-Left Button Color & Texture
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2),
interfaceCtx->cLeftAlpha);
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(1)) << 2, R_ITEM_BTN_Y(1) << 2,
(OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(1)) + R_ITEM_BTN_WIDTH(1)) << 2,
(R_ITEM_BTN_Y(1) + R_ITEM_BTN_WIDTH(1)) << 2,
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cLeftAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cLeftAlpha);
}
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos[0]) << 2, C_Left_BTN_Pos[1] << 2,
(OTRGetRectDimensionFromRightEdge(C_Left_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(1)) << 2,
(C_Left_BTN_Pos[1] + R_ITEM_BTN_WIDTH(1)) << 2,
G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(1) << 1, R_ITEM_BTN_DD(1) << 1);
// C-Down Button Color & Texture
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2),
interfaceCtx->cDownAlpha);
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(2)) << 2, R_ITEM_BTN_Y(2) << 2,
(OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(2)) + R_ITEM_BTN_WIDTH(2)) << 2,
(R_ITEM_BTN_Y(2) + R_ITEM_BTN_WIDTH(2)) << 2,
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cDownAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cDownAlpha);
}
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Down_BTN_Pos[0]) << 2, C_Down_BTN_Pos[1] << 2,
(OTRGetRectDimensionFromRightEdge(C_Down_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(2)) << 2,
(C_Down_BTN_Pos[1] + R_ITEM_BTN_WIDTH(2)) << 2,
G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(2) << 1, R_ITEM_BTN_DD(2) << 1);
// C-Right Button Color & Texture
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2),
interfaceCtx->cRightAlpha);
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(3)) << 2, R_ITEM_BTN_Y(3) << 2,
(OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(3)) + R_ITEM_BTN_WIDTH(3)) << 2,
(R_ITEM_BTN_Y(3) + R_ITEM_BTN_WIDTH(3)) << 2,
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), interfaceCtx->cRightAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha);
}
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos[0]) << 2, C_Right_BTN_Pos[1] << 2,
(OTRGetRectDimensionFromRightEdge(C_Right_BTN_Pos[0]) + R_ITEM_BTN_WIDTH(3)) << 2,
(C_Right_BTN_Pos[1] + R_ITEM_BTN_WIDTH(3)) << 2,
G_TX_RENDERTILE, 0, 0, R_ITEM_BTN_DD(3) << 1, R_ITEM_BTN_DD(3) << 1);
if ((pauseCtx->state < 8) || (pauseCtx->state >= 18)) {
if ((globalCtx->pauseCtx.state != 0) || (globalCtx->pauseCtx.debugState != 0)) {
// Start Button Texture, Color & Label
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 120, 120, interfaceCtx->startAlpha);
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]) << 2, 68,
(OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]) + 22) << 2, 156,
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 0, 0, interfaceCtx->startAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 120, 120, 120, interfaceCtx->startAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCStartBtnPrimR", 120), CVar_GetS32("gCCStartBtnPrimG", 120), CVar_GetS32("gCCStartBtnPrimB", 120), interfaceCtx->startAlpha);
}
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+Right_HUD_Margin) << 2, 68+((Top_HUD_Margin*-1)*4),
(OTRGetRectDimensionFromRightEdge(startButtonLeftPos[gSaveContext.language]+Right_HUD_Margin) + 22) << 2, 156+((Top_HUD_Margin*-1)*4),
G_TX_RENDERTILE, 0, 0, 1462, 1462);
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->startAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0);
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
//There is probably a more elegant way to do it.
char* doAction = actionsTbl[3];
char newName[512];
if (gSaveContext.language != LANGUAGE_ENG) {
size_t length = strlen(doAction);
strcpy(newName, doAction);
if (gSaveContext.language == LANGUAGE_FRA) {
newName[length - 6] = 'F';
newName[length - 5] = 'R';
newName[length - 4] = 'A';
} else if (gSaveContext.language == LANGUAGE_GER) {
newName[length - 6] = 'G';
newName[length - 5] = 'E';
newName[length - 4] = 'R';
}
doAction = newName;
}
memcpy(interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE * 2, ResourceMgr_LoadTexByName(doAction), DO_ACTION_TEX_SIZE);
gDPLoadTextureBlock_4b(OVERLAY_DISP++, interfaceCtx->doActionSegment + DO_ACTION_TEX_SIZE * 2, G_IM_FMT_IA,
DO_ACTION_TEX_WIDTH, DO_ACTION_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
@ -2812,11 +2911,11 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
dxdy = (1 << 10) / (R_START_LABEL_DD(gSaveContext.language) / 100.0f);
width = DO_ACTION_TEX_WIDTH / (R_START_LABEL_DD(gSaveContext.language) / 100.0f);
height = DO_ACTION_TEX_HEIGHT / (R_START_LABEL_DD(gSaveContext.language) / 100.0f);
const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language));
const s16 rStartLabelX = OTRGetRectDimensionFromRightEdge(R_START_LABEL_X(gSaveContext.language)+Right_HUD_Margin);
gSPWideTextureRectangle(
OVERLAY_DISP++, rStartLabelX << 2,
R_START_LABEL_Y(gSaveContext.language) << 2, (rStartLabelX + width) << 2,
(R_START_LABEL_Y(gSaveContext.language) + height) << 2, G_TX_RENDERTILE, 0, 0, dxdy, dxdy);
R_START_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) << 2, (rStartLabelX + width) << 2,
(R_START_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) + height) << 2, G_TX_RENDERTILE, 0, 0, dxdy, dxdy);
}
}
@ -2835,12 +2934,18 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
temp = interfaceCtx->healthAlpha;
}
const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X);
const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp);
const s16 rCUpBtnX = OTRGetRectDimensionFromRightEdge(R_C_UP_BTN_X+Right_HUD_Margin);
const s16 rCUPIconX = OTRGetRectDimensionFromRightEdge(R_C_UP_ICON_X+Right_HUD_Margin);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), temp);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), temp);
}
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gSPWideTextureRectangle(OVERLAY_DISP++, rCUpBtnX << 2, R_C_UP_BTN_Y << 2, (rCUpBtnX + 16) << 2,
(R_C_UP_BTN_Y + 16) << 2, G_TX_RENDERTILE, 0, 0, 2 << 10, 2 << 10);
gSPWideTextureRectangle(OVERLAY_DISP++, rCUpBtnX << 2, R_C_UP_BTN_Y+(Top_HUD_Margin*-1) << 2, (rCUpBtnX + 16) << 2,
(R_C_UP_BTN_Y+(Top_HUD_Margin*-1) + 16) << 2, G_TX_RENDERTILE, 0, 0, 2 << 10, 2 << 10);
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, temp);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0);
@ -2851,8 +2956,8 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
G_TX_NOLOD, G_TX_NOLOD);
gSPWideTextureRectangle(OVERLAY_DISP++, rCUPIconX << 2, R_C_UP_ICON_Y << 2, (rCUPIconX + 32) << 2,
(R_C_UP_ICON_Y + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
gSPWideTextureRectangle(OVERLAY_DISP++, rCUPIconX << 2, R_C_UP_ICON_Y+(Top_HUD_Margin*-1) << 2, (rCUPIconX + 32) << 2,
(R_C_UP_ICON_Y+(Top_HUD_Margin*-1) + 8) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
}
sCUpTimer--;
@ -2878,8 +2983,13 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
interfaceCtx->cRightAlpha);
}
if (CVar_GetS32("gHudColors", 1) == 2) {
//This later will feature color per C button right now that it.
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), interfaceCtx->cRightAlpha);
}
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, ((u8*)gButtonBackgroundTex), 32, 32,
OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)), R_ITEM_BTN_Y(temp), R_ITEM_BTN_WIDTH(temp),
OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)+Right_HUD_Margin), R_ITEM_BTN_Y(temp)+(Top_HUD_Margin*-1), R_ITEM_BTN_WIDTH(temp),
R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1);
const char* cButtonIcons[] = { gButtonBackgroundTex, gEquippedItemOutlineTex, gEmptyCLeftArrowTex,
@ -2887,7 +2997,7 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
};
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, cButtonIcons[(temp + 1)], 32, 32,
OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)), R_ITEM_BTN_Y(temp), R_ITEM_BTN_WIDTH(temp),
OTRGetRectDimensionFromRightEdge(R_ITEM_BTN_X(temp)+Right_HUD_Margin), R_ITEM_BTN_Y(temp)+(Top_HUD_Margin*-1), R_ITEM_BTN_WIDTH(temp),
R_ITEM_BTN_WIDTH(temp), R_ITEM_BTN_DD(temp) << 1, R_ITEM_BTN_DD(temp) << 1);
}
}
@ -2901,9 +3011,9 @@ void Interface_DrawItemIconTexture(GlobalContext* globalCtx, void* texture, s16
gDPLoadTextureBlock(OVERLAY_DISP++, texture, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)) << 2, R_ITEM_ICON_Y(button) << 2,
(OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)) + R_ITEM_ICON_WIDTH(button)) << 2,
(R_ITEM_ICON_Y(button) + R_ITEM_ICON_WIDTH(button)) << 2, G_TX_RENDERTILE, 0, 0,
gSPWideTextureRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)+Right_HUD_Margin) << 2, R_ITEM_ICON_Y(button)+(Top_HUD_Margin*-1) << 2,
(OTRGetRectDimensionFromRightEdge(R_ITEM_ICON_X(button)+Right_HUD_Margin) + R_ITEM_ICON_WIDTH(button)) << 2,
(R_ITEM_ICON_Y(button)+(Top_HUD_Margin*-1) + R_ITEM_ICON_WIDTH(button)) << 2, G_TX_RENDERTILE, 0, 0,
R_ITEM_ICON_DD(button) << 1, R_ITEM_ICON_DD(button) << 1);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 3094);
@ -2964,11 +3074,11 @@ void Interface_DrawAmmoCount(GlobalContext* globalCtx, s16 button, s16 alpha) {
if (i != 0) {
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[i], 8, 8,
OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)), R_ITEM_AMMO_Y(button), 8, 8, 1 << 10, 1 << 10);
OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)+Right_HUD_Margin), R_ITEM_AMMO_Y(button)+(Top_HUD_Margin*-1), 8, 8, 1 << 10, 1 << 10);
}
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, (u8*)_gAmmoDigit0Tex[ammo], 8, 8,
OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)) + 6, R_ITEM_AMMO_Y(button), 8, 8, 1 << 10, 1 << 10);
OTRGetRectDimensionFromRightEdge(R_ITEM_AMMO_X(button)+Right_HUD_Margin) + 6, R_ITEM_AMMO_Y(button)+(Top_HUD_Margin*-1), 8, 8, 1 << 10, 1 << 10);
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_parameter.c", 3158);
@ -3187,10 +3297,16 @@ void Interface_Draw(GlobalContext* globalCtx) {
rColor = &rupeeWalletColors[0];
}
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor[0], rColor[1], rColor[2], interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 80, 0, 255);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26),
206, 16, 16, 1 << 10, 1 << 10);
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCRupeePrimR", rColor[0]), CVar_GetS32("gCCRupeePrimG", rColor[1]), CVar_GetS32("gCCRupeePrimB", rColor[2]), interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :)
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, rColor[0], rColor[1], rColor[2], interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 80, 0, 255);
}
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gRupeeCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26+(Left_HUD_Margin*-1)),
206+(Bottom_HUD_Margin), 16, 16, 1 << 10, 1 << 10);
switch (globalCtx->sceneNum) {
case SCENE_BMORI1:
@ -3210,9 +3326,15 @@ void Interface_Draw(GlobalContext* globalCtx) {
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] >= 0) {
// Small Key Icon
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 230, 255, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255);
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26), 190, 16, 16,
if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCKeysPrimR", 200), CVar_GetS32("gCCKeysPrimG", 230), CVar_GetS32("gCCKeysPrimB", 255), interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 255); //We reset this here so it match user color :)
} else {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 200, 230, 255, interfaceCtx->magicAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 20, 255);
}
OVERLAY_DISP = Gfx_TextureIA8(OVERLAY_DISP, gSmallKeyCounterIconTex, 16, 16, OTRGetRectDimensionFromLeftEdge(26+(Left_HUD_Margin*-1)), 190+(Bottom_HUD_Margin), 16, 16,
1 << 10, 1 << 10);
// Small Key Counter
@ -3229,17 +3351,17 @@ void Interface_Draw(GlobalContext* globalCtx) {
interfaceCtx->counterDigits[3] -= 10;
}
svar3 = OTRGetRectDimensionFromLeftEdge(42);
svar3 = OTRGetRectDimensionFromLeftEdge(42+(Left_HUD_Margin*-1));
if (interfaceCtx->counterDigits[2] != 0) {
OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP, ((u8*)((u8*)digitTextures[interfaceCtx->counterDigits[2]])), 8,
16, svar3, 190, 8, 16, 1 << 10, 1 << 10);
16, svar3, 190+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10);
svar3 += 8;
}
OVERLAY_DISP = Gfx_TextureI8(OVERLAY_DISP,
((u8*)digitTextures[interfaceCtx->counterDigits[3]]), 8, 16,
svar3, 190, 8, 16, 1 << 10, 1 << 10);
svar3, 190+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10);
}
break;
default:
@ -3283,7 +3405,7 @@ void Interface_Draw(GlobalContext* globalCtx) {
for (svar1 = 0, svar3 = 42; svar1 < svar5; svar1++, svar2++, svar3 += 8) {
OVERLAY_DISP =
Gfx_TextureI8(OVERLAY_DISP, ((u8*)digitTextures[interfaceCtx->counterDigits[svar2]]), 8, 16,
OTRGetRectDimensionFromLeftEdge(svar3), 206, 8, 16, 1 << 10, 1 << 10);
OTRGetRectDimensionFromLeftEdge(svar3+(Left_HUD_Margin*-1)), 206+(Bottom_HUD_Margin), 8, 16, 1 << 10, 1 << 10);
}
}
else {
@ -3345,8 +3467,8 @@ void Interface_Draw(GlobalContext* globalCtx) {
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
R_B_LABEL_DD = (1 << 10) / (WREG(37 + gSaveContext.language) / 100.0f);
const s16 rBLabelX = OTRGetRectDimensionFromRightEdge(R_B_LABEL_X(gSaveContext.language));
gSPWideTextureRectangle(OVERLAY_DISP++, rBLabelX << 2, R_B_LABEL_Y(gSaveContext.language) << 2,
const s16 rBLabelX = OTRGetRectDimensionFromRightEdge(R_B_LABEL_X(gSaveContext.language)+Right_HUD_Margin);
gSPWideTextureRectangle(OVERLAY_DISP++, rBLabelX << 2, R_B_LABEL_Y(gSaveContext.language)+(Top_HUD_Margin*-1) << 2,
(rBLabelX + DO_ACTION_TEX_WIDTH) << 2,
(R_B_LABEL_Y(gSaveContext.language) + DO_ACTION_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0, 0,
R_B_LABEL_DD, R_B_LABEL_DD);
@ -3393,24 +3515,29 @@ void Interface_Draw(GlobalContext* globalCtx) {
// A Button
func_80094A14(globalCtx->state.gfxCtx);
const f32 rABtnX = OTRGetDimensionFromRightEdge(R_A_BTN_X);
const f32 rABtnX = OTRGetDimensionFromRightEdge(R_A_BTN_X+Right_HUD_Margin);
//func_8008A8B8(globalCtx, R_A_BTN_Y, R_A_BTN_Y + 45, rABtnX, rABtnX + 45);
gSPClearGeometryMode(OVERLAY_DISP++, G_CULL_BOTH);
gDPSetCombineMode(OVERLAY_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2),
interfaceCtx->aAlpha);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 90, 90, 255, interfaceCtx->aAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, R_A_BTN_COLOR(0), R_A_BTN_COLOR(1), R_A_BTN_COLOR(2), interfaceCtx->aAlpha);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", R_A_BTN_COLOR(0)), CVar_GetS32("gCCABtnPrimG", R_A_BTN_COLOR(1)), CVar_GetS32("gCCABtnPrimB", R_A_BTN_COLOR(2)), interfaceCtx->aAlpha);
}
if (fullUi) {
Interface_DrawActionButton(globalCtx, rABtnX, R_A_BTN_Y);
Interface_DrawActionButton(globalCtx, rABtnX, R_A_BTN_Y+(Top_HUD_Margin*-1));
}
gDPPipeSync(OVERLAY_DISP++);
const f32 rAIconX = OTRGetDimensionFromRightEdge(R_A_ICON_X);
const f32 rAIconX = OTRGetDimensionFromRightEdge(R_A_ICON_X+Right_HUD_Margin);
//func_8008A8B8(globalCtx, R_A_ICON_Y, R_A_ICON_Y + 45, rAIconX, rAIconX + 45);
gSPSetGeometryMode(OVERLAY_DISP++, G_CULL_BACK);
gDPSetCombineLERP(OVERLAY_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, interfaceCtx->aAlpha);
gDPSetEnvColor(OVERLAY_DISP++, 0, 0, 0, 0);
Matrix_Translate(-138.0f + rAIconX, 98.0f - R_A_ICON_Y, WREG(46 + gSaveContext.language) / 10.0f, MTXMODE_NEW);
Matrix_Translate(-138.0f + rAIconX, 98.0f - (R_A_ICON_Y+(Top_HUD_Margin*-1)), WREG(46 + gSaveContext.language) / 10.0f, MTXMODE_NEW);
Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
Matrix_RotateX(interfaceCtx->unk_1F4 / 10000.0f, MTXMODE_APPLY);
gSPMatrix(OVERLAY_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_parameter.c", 3701),
@ -3979,6 +4106,18 @@ void Interface_Update(GlobalContext* globalCtx) {
u16 action;
Input* debugInput = &globalCtx->state.input[2];
if (CVar_GetS32("gHUDMargins", 0) != 0) {
Top_HUD_Margin = CVar_GetS32("gHUDMargin_T", 0);
Left_HUD_Margin = CVar_GetS32("gHUDMargin_L", 0);
Right_HUD_Margin = CVar_GetS32("gHUDMargin_R", 0);
Bottom_HUD_Margin = CVar_GetS32("gHUDMargin_B", 0);
} else {
Top_HUD_Margin = 0;
Left_HUD_Margin = 0;
Right_HUD_Margin = 0;
Bottom_HUD_Margin = 0;
}
if (CHECK_BTN_ALL(debugInput->press.button, BTN_DLEFT)) {
gSaveContext.language = LANGUAGE_ENG;
osSyncPrintf("J_N=%x J_N=%x\n", gSaveContext.language, &gSaveContext.language);

View File

@ -29,7 +29,8 @@ s16 sBootData[PLAYER_BOOTS_MAX][17] = {
// Used to map action params to model groups
u8 sActionModelGroups[] = {
3, 15, 10, 2, 2, 5, 10, 11, 6, 6, 6, 6, 6, 6, 6, 6, 9, 9, 7, 7, 8, 3, 3, 6, 3, 3, 3, 3, 12, 13, 14, 14, 14, 14,
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
14, 14, 14, 14, 14, 14, 14, 14, 14, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3
};
TextTriggerEntry sTextTriggers[] = {
@ -743,25 +744,38 @@ void func_8008F470(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable,
#else
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[eyeIndex]));
#endif
Color_RGB8 sTemp;
Color_RGB8 sOriginalTunicColors[] = {
{ 30, 105, 27 },
{ 100, 20, 0 },
{ 0, 60, 100 },
};
color = &sTemp;
if (tunic == PLAYER_TUNIC_KOKIRI) {
color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r);
color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g);
color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b);
} else if (tunic == PLAYER_TUNIC_GORON) {
color->r = CVar_GetS32("gTunic_Goron_Red", sTunicColors[PLAYER_TUNIC_GORON].r);
color->g = CVar_GetS32("gTunic_Goron_Green", sTunicColors[PLAYER_TUNIC_GORON].g);
color->b = CVar_GetS32("gTunic_Goron_Blue", sTunicColors[PLAYER_TUNIC_GORON].b);
} else if (tunic == PLAYER_TUNIC_ZORA) {
color->r = CVar_GetS32("gTunic_Zora_Red", sTunicColors[PLAYER_TUNIC_ZORA].r);
color->g = CVar_GetS32("gTunic_Zora_Green", sTunicColors[PLAYER_TUNIC_ZORA].g);
color->b = CVar_GetS32("gTunic_Zora_Blue", sTunicColors[PLAYER_TUNIC_ZORA].b);
} else {
color->r = CVar_GetS32("gTunic_Kokiri_Red", sTunicColors[PLAYER_TUNIC_KOKIRI].r);
color->g = CVar_GetS32("gTunic_Kokiri_Green", sTunicColors[PLAYER_TUNIC_KOKIRI].g);
color->b = CVar_GetS32("gTunic_Kokiri_Blue", sTunicColors[PLAYER_TUNIC_KOKIRI].b);
if (tunic == PLAYER_TUNIC_KOKIRI && CVar_GetS32("gUseTunicsCol",0)) {
color->r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r);
color->g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g);
color->b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b);
} else if (tunic == PLAYER_TUNIC_GORON && CVar_GetS32("gUseTunicsCol",0)) {
color->r = CVar_GetS32("gTunic_Goron_R", sTunicColors[PLAYER_TUNIC_GORON].r);
color->g = CVar_GetS32("gTunic_Goron_G", sTunicColors[PLAYER_TUNIC_GORON].g);
color->b = CVar_GetS32("gTunic_Goron_B", sTunicColors[PLAYER_TUNIC_GORON].b);
} else if (tunic == PLAYER_TUNIC_ZORA && CVar_GetS32("gUseTunicsCol",0)) {
color->r = CVar_GetS32("gTunic_Zora_R", sTunicColors[PLAYER_TUNIC_ZORA].r);
color->g = CVar_GetS32("gTunic_Zora_G", sTunicColors[PLAYER_TUNIC_ZORA].g);
color->b = CVar_GetS32("gTunic_Zora_B", sTunicColors[PLAYER_TUNIC_ZORA].b);
} else if (!CVar_GetS32("gUseTunicsCol",0)){
if (tunic >= 3) {
color->r = sOriginalTunicColors[0].r;
color->g = sOriginalTunicColors[0].g;
color->b = sOriginalTunicColors[0].b;
} else {
color->r = sOriginalTunicColors[tunic].r;
color->g = sOriginalTunicColors[tunic].g;
color->b = sOriginalTunicColors[tunic].b;
}
}
gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0);
sDListsLodOffset = lod * 2;
@ -1648,26 +1662,118 @@ void func_80091A24(GlobalContext* globalCtx, void* seg04, void* seg06, SkelAnime
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_player_lib.c", 3288);
}
uintptr_t SelectedAnim = 0; // Current Animaiton on the menu
s16 EquipedStance; // Link's current mode (Two handed, One handed...)
s16 FrameCountSinceLastAnim = 0; // Time since last animation
s16 MinFrameCount; // Frame to wait before checking if we need to change the animation
void func_8009214C(GlobalContext* globalCtx, u8* segment, SkelAnime* skelAnime, Vec3f* pos, Vec3s* rot, f32 scale,
s32 sword, s32 tunic, s32 shield, s32 boots) {
Input* p1Input = &globalCtx->state.input[0];
Vec3f eye = { 0.0f, 0.0f, -400.0f };
Vec3f at = { 0.0f, 0.0f, 0.0f };
Vec3s* destTable;
Vec3s* srcTable;
s32 i;
bool canswitchrnd = false;
s16 SelectedMode = CVar_GetS32("gPauseLiveLink", 1);
MinFrameCount = CVar_GetS32("gMinFrameCount", 200);
gSegments[4] = VIRTUAL_TO_PHYSICAL(segment + 0x3800);
gSegments[6] = VIRTUAL_TO_PHYSICAL(segment + 0x8800);
if (CVar_GetS32("gPauseLiveLink", 0) || CVar_GetS32("gPauseTriforce", 0)) {
uintptr_t anim = gPlayerAnim_003238; // idle
uintptr_t* PauseMenuAnimSet[15][4] = {
{ 0, 0, 0, 0 }, // 0 = none
// IDLE // Two Handed // No shield // Kid Hylian Shield
{ gPlayerAnim_003238, gPlayerAnim_002BE0, gPlayerAnim_003240, gPlayerAnim_003240 }, // Idle
{ gPlayerAnim_003200, gPlayerAnim_003200, gPlayerAnim_003200, gPlayerAnim_003200 }, // Idle look around
{ gPlayerAnim_0033E0, gPlayerAnim_0033E0, gPlayerAnim_0033E0, gPlayerAnim_0033E0 }, // Idle Belt
{ gPlayerAnim_003418, gPlayerAnim_003418, gPlayerAnim_003418, gPlayerAnim_003418 }, // Idle shield adjust
{ gPlayerAnim_003420, gPlayerAnim_003428, gPlayerAnim_003420, gPlayerAnim_003420 }, // Idle test sword
{ gPlayerAnim_0033F0, gPlayerAnim_0033F0, gPlayerAnim_0033F0, gPlayerAnim_0033F0 }, // Idle yawn
{ gPlayerAnim_0025D0, gPlayerAnim_002BD0, gPlayerAnim_0025D0, gPlayerAnim_0025D0 }, // Battle Stance
{ gPlayerAnim_003290, gPlayerAnim_002BF8, gPlayerAnim_003290, gPlayerAnim_003290 }, // Walking (No shield)
{ gPlayerAnim_003268, gPlayerAnim_002BF8, gPlayerAnim_003268, gPlayerAnim_003268 }, // Walking (Holding shield)
{ gPlayerAnim_003138, gPlayerAnim_002B40, gPlayerAnim_003138, gPlayerAnim_003138 }, // Running (No shield)
{ gPlayerAnim_003140, gPlayerAnim_002B40, gPlayerAnim_003140, gPlayerAnim_003140 }, // Running (Holding shield)
{ gPlayerAnim_0031A8, gPlayerAnim_0031A8, gPlayerAnim_0031A8, gPlayerAnim_0031A8 }, // Hand on hip
{ gPlayerAnim_002AF0, gPlayerAnim_002928, gPlayerAnim_002AF0, gPlayerAnim_002AF0 }, // Spin Charge
{ gPlayerAnim_002820, gPlayerAnim_002820, gPlayerAnim_002820, gPlayerAnim_002820 }, // Look at hand
};
s16 AnimArraySize = ARRAY_COUNT(PauseMenuAnimSet);
if (CUR_EQUIP_VALUE(EQUIP_SWORD) >= 3)
anim = gPlayerAnim_002BE0; // Two Handed Anim
else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 0)
anim = gPlayerAnim_003240;
else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 2 && LINK_AGE_IN_YEARS == YEARS_CHILD)
anim = gPlayerAnim_003240;
if (CVar_GetS32("gPauseLiveLink", !0) || CVar_GetS32("gPauseTriforce", 0)) {
uintptr_t anim = 0; // Initialise anim
if (CUR_EQUIP_VALUE(EQUIP_SWORD) >= 3) {
EquipedStance = 1;
} else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 0) {
EquipedStance = 2;
} else if (CUR_EQUIP_VALUE(EQUIP_SHIELD) == 2 && LINK_AGE_IN_YEARS == YEARS_CHILD) {
EquipedStance = 3;
} else {
// Link is idle so revert to 0
EquipedStance = 0;
}
if (SelectedMode == 16) {
// Apply Random function
s16 SwitchAtFrame = 0;
s16 CurAnimDuration = 0;
if (FrameCountSinceLastAnim == 0) {
// When opening Kaleido this will be passed one time
SelectedAnim = rand() % (AnimArraySize - 0);
if (SelectedAnim == 0) {
// prevent loading 0 that would result to a crash.
SelectedAnim = 1;
}
} else if (FrameCountSinceLastAnim >= 1) {
SwitchAtFrame = Animation_GetLastFrame(PauseMenuAnimSet[SelectedAnim][EquipedStance]);
CurAnimDuration = Animation_GetLastFrame(PauseMenuAnimSet[SelectedAnim][EquipedStance]);
if (SwitchAtFrame < MinFrameCount) {
// Animation frame count is lower than minimal wait time then we wait for another round.
// This will be looped to always add current animation time if that still lower than minimum time
while (SwitchAtFrame < MinFrameCount) {
SwitchAtFrame = SwitchAtFrame + CurAnimDuration;
}
} else if (CurAnimDuration >= MinFrameCount) {
// Since we have more (or same) animation time than min duration we set the wait time to animation
// time.
SwitchAtFrame = CurAnimDuration;
}
if (FrameCountSinceLastAnim >= SwitchAtFrame) {
SelectedAnim = rand() % (AnimArraySize - 0);
if (SelectedAnim == 0) {
// prevent loading 0 that would result to a crash.
SelectedAnim = 1;
}
FrameCountSinceLastAnim = 1;
}
anim = PauseMenuAnimSet[SelectedAnim][EquipedStance];
}
FrameCountSinceLastAnim++;
} else if (SelectedMode == 15) {
// When opening Kaleido this will be passed one time
if (FrameCountSinceLastAnim < 1) {
SelectedAnim = rand() % (AnimArraySize - 0);
FrameCountSinceLastAnim++;
if (SelectedAnim == 0) {
// prevent loading 0 that would result to a crash.
SelectedAnim = 1;
}
FrameCountSinceLastAnim = 1;
}
if (CHECK_BTN_ALL(p1Input->press.button, BTN_B) || CHECK_BTN_ALL(p1Input->press.button, BTN_START)) {
FrameCountSinceLastAnim = 0;
}
anim = PauseMenuAnimSet[SelectedAnim][EquipedStance];
} else if (SelectedMode < 16) {
// Not random so we place our CVar as SelectedAnim
SelectedAnim = SelectedMode;
anim = PauseMenuAnimSet[SelectedAnim][EquipedStance];
}
anim = PauseMenuAnimSet[SelectedAnim][EquipedStance];
//anim = gPlayerAnim_003428; // Use for biggoron sword?

View File

@ -836,7 +836,7 @@ void Sram_InitSram(GameState* gameState, SramContext* sramCtx) {
for (i = 0; i < ARRAY_COUNTU(sZeldaMagic) - 3; i++) {
if (sZeldaMagic[i + SRAM_HEADER_MAGIC] != sramCtx->readBuff[i + SRAM_HEADER_MAGIC]) {
osSyncPrintf("SRAM破壊!!!!!!\n"); // "SRAM destruction! ! ! ! ! !"
gSaveContext.language = sramCtx->readBuff[SRAM_HEADER_LANGUAGE];
gSaveContext.language = CVar_GetS32("gLanguages", 0);
memcpy(sramCtx->readBuff, sZeldaMagic, sizeof(sZeldaMagic));
sramCtx->readBuff[SRAM_HEADER_LANGUAGE] = gSaveContext.language;
Sram_WriteSramHeader(sramCtx);
@ -845,7 +845,7 @@ void Sram_InitSram(GameState* gameState, SramContext* sramCtx) {
gSaveContext.audioSetting = sramCtx->readBuff[SRAM_HEADER_SOUND] & 3;
gSaveContext.zTargetSetting = sramCtx->readBuff[SRAM_HEADER_ZTARGET] & 1;
gSaveContext.language = sramCtx->readBuff[SRAM_HEADER_LANGUAGE];
gSaveContext.language = CVar_GetS32("gLanguages", 0);
if (gSaveContext.language >= LANGUAGE_MAX) {
gSaveContext.language = LANGUAGE_ENG;

View File

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

View File

@ -1887,9 +1887,19 @@ void EnOssan_UpdateCursorAnim(EnOssan* this) {
this->cursorAnimState = 0;
}
}
this->cursorColorR = ColChanMix(0, 0.0f, t);
this->cursorColorG = ColChanMix(255, 80.0f, t);
this->cursorColorB = ColChanMix(80, 0.0f, t);
if (CVar_GetS32("gHudColors", 1) == 0) {
this->cursorColorR = ColChanMix(0, 0.0f, t);
this->cursorColorG = ColChanMix(80, 80.0f, t);
this->cursorColorB = ColChanMix(255, 0.0f, t);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
this->cursorColorR = ColChanMix(0, 0.0f, t);
this->cursorColorG = ColChanMix(255, 80.0f, t);
this->cursorColorB = ColChanMix(80, 0.0f, t);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
this->cursorColorR = ColChanMix(CVar_GetS32("gCCABtnPrimR", 90), ((CVar_GetS32("gCCABtnPrimR", 90)/255)*100), t);
this->cursorColorG = ColChanMix(CVar_GetS32("gCCABtnPrimG", 90), ((CVar_GetS32("gCCABtnPrimG", 90)/255)*100), t);
this->cursorColorB = ColChanMix(CVar_GetS32("gCCABtnPrimB", 90), ((CVar_GetS32("gCCABtnPrimB", 90)/255)*100), t);
}
this->cursorColorA = ColChanMix(255, 0.0f, t);
this->cursorAnimTween = t;
}

View File

@ -366,7 +366,9 @@ void func_80ACA7E0(EnOwl* this, GlobalContext* globalCtx) {
void EnOwl_ConfirmKokiriMessage(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x2065);
break;
@ -393,7 +395,9 @@ void EnOwl_WaitOutsideKokiri(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACA998(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x2069);
this->actionFunc = func_80ACAA54;
@ -437,7 +441,9 @@ void EnOwl_WaitHyruleCastle(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACAB88(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
// obtained zelda's letter
if (gSaveContext.eventChkInf[4] & 1) {
@ -478,7 +484,9 @@ void EnOwl_WaitKakariko(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACAD34(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x206F);
this->actionFunc = func_80ACADF0;
@ -514,7 +522,9 @@ void EnOwl_WaitGerudo(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACAEB8(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x2071);
this->actionFunc = func_80ACAF74;
@ -634,7 +644,9 @@ void EnOwl_WaitDeathMountainShortcut(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACB344(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x607A);
break;
@ -657,7 +669,9 @@ void func_80ACB3E0(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACB440(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x10C1);
this->actionFunc = func_80ACB4FC;
@ -692,7 +706,9 @@ void EnOwl_WaitLWPreSaria(EnOwl* this, GlobalContext* globalCtx) {
void func_80ACB5C4(EnOwl* this, GlobalContext* globalCtx) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CHOICE && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
// swap the order of the responses if better owl is enabled
uint8_t index = CVar_GetS32("gBetterOwl", 0) == 0 ? globalCtx->msgCtx.choiceIndex : (1 - globalCtx->msgCtx.choiceIndex);
switch (index) {
case OWL_REPEAT:
Message_ContinueTextbox(globalCtx, 0x10C5);
this->actionFunc = func_80ACB680;

View File

@ -898,6 +898,15 @@ static s8 sItemActionParams[] = {
PLAYER_AP_SWORD_KOKIRI,
PLAYER_AP_SWORD_MASTER,
PLAYER_AP_SWORD_BGS,
PLAYER_AP_SHIELD_DEKU,
PLAYER_AP_SHIELD_HYLIAN,
PLAYER_AP_SHIELD_MIRROR,
PLAYER_AP_TUNIC_KOKIRI,
PLAYER_AP_TUNIC_GORON,
PLAYER_AP_TUNIC_ZORA,
PLAYER_AP_BOOTS_KOKIRI,
PLAYER_AP_BOOTS_IRON,
PLAYER_AP_BOOTS_HOVER,
};
static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
@ -910,7 +919,8 @@ static s32(*D_80853EDC[])(Player* this, GlobalContext* globalCtx) = {
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C, func_8083485C,
};
static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
@ -923,7 +933,8 @@ static void (*D_80853FE8[])(GlobalContext* globalCtx, Player* this) = {
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
func_80833770, func_80833770, func_80833770, func_80833770, func_80833770, func_80833770,
};
typedef enum {
@ -2752,7 +2763,8 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
if ((actionParam == PLAYER_AP_NONE) || !(this->stateFlags1 & PLAYER_STATE1_27) ||
((this->actor.bgCheckFlags & 1) &&
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT)))) {
((actionParam == PLAYER_AP_HOOKSHOT) || (actionParam == PLAYER_AP_LONGSHOT))) ||
((actionParam >= PLAYER_AP_SHIELD_DEKU) && (actionParam <= PLAYER_AP_BOOTS_HOVER))) {
if ((globalCtx->bombchuBowlingStatus == 0) &&
(((actionParam == PLAYER_AP_STICK) && (AMMO(ITEM_STICK) == 0)) ||
@ -2764,6 +2776,33 @@ void func_80835F44(GlobalContext* globalCtx, Player* this, s32 item) {
return;
}
if (actionParam >= PLAYER_AP_BOOTS_KOKIRI) {
u16 bootsValue = actionParam - PLAYER_AP_BOOTS_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_BOOTS) == bootsValue) {
Inventory_ChangeEquipment(EQUIP_BOOTS, 1);
} else {
Inventory_ChangeEquipment(EQUIP_BOOTS, bootsValue);
}
Player_SetEquipmentData(globalCtx, this);
return;
}
if (actionParam >= PLAYER_AP_TUNIC_KOKIRI) {
u16 tunicValue = actionParam - PLAYER_AP_TUNIC_KOKIRI + 1;
if (CUR_EQUIP_VALUE(EQUIP_TUNIC) == tunicValue) {
Inventory_ChangeEquipment(EQUIP_TUNIC, 1);
} else {
Inventory_ChangeEquipment(EQUIP_TUNIC, tunicValue);
}
Player_SetEquipmentData(globalCtx, this);
return;
}
if (actionParam >= PLAYER_AP_SHIELD_DEKU) {
// Changing shields through action commands is unimplemented
return;
}
if (actionParam == PLAYER_AP_LENS) {
if (func_80087708(globalCtx, 0, 3)) {
if (globalCtx->actorCtx.unk_03 != 0) {
@ -10285,6 +10324,14 @@ void func_80848EF8(Player* this, GlobalContext* globalCtx) {
int rectHeight = 24; //Texture Heigh
int DefaultIconA= 50; //Default icon alphe (55 on 255)
if (CVar_GetS32("gHUDMargins", 0) != 0) {
rectLeft = OTRGetRectDimensionFromLeftEdge(26+(CVar_GetS32("gHUDMargin_L", 0)*-1));
rectTop = 60+(CVar_GetS32("gHUDMargin_T", 0)*-1);
} else {
rectTop = 60;
rectLeft = OTRGetRectDimensionFromLeftEdge(26);
}
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_player.c", 2824);
gDPPipeSync(OVERLAY_DISP++);
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 255, 255, 255, DefaultIconA);

View File

@ -5,6 +5,8 @@
#include "textures/title_static/title_static.h"
#include "textures/parameter_static/parameter_static.h"
#include "soh/frame_interpolation.h"
static s16 sUnused = 106;
static s16 sScreenFillAlpha = 255;
@ -1136,6 +1138,8 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
FileChoose_SetWindowVtx(&this->state);
FileChoose_SetWindowContentVtx(&this->state);
FrameInterpolation_RecordOpenChild(this, this->configMode);
if ((this->configMode != CM_NAME_ENTRY) && (this->configMode != CM_START_NAME_ENTRY)) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
@ -1227,6 +1231,8 @@ void FileChoose_ConfigModeDraw(GameState* thisx) {
gDPPipeSync(POLY_OPA_DISP++);
FileChoose_SetView(this, 0.0f, 0.0f, 64.0f);
FrameInterpolation_RecordCloseChild();
CLOSE_DISPS(this->state.gfxCtx, "../z_file_choose.c", 2352);
}
@ -1669,7 +1675,9 @@ void FileChoose_Main(GameState* thisx) {
FileChoose_PulsateCursor(&this->state);
gFileSelectUpdateFuncs[this->menuMode](&this->state);
FrameInterpolation_StartRecord();
gFileSelectDrawFuncs[this->menuMode](&this->state);
FrameInterpolation_StopRecord();
// do not draw controls text in the options menu
if ((this->configMode <= CM_NAME_ENTRY_TO_MAIN) || (this->configMode >= CM_UNUSED_DELAY)) {

View File

@ -222,6 +222,72 @@ void Title_Draw(TitleContext* this) {
void Title_Main(GameState* thisx) {
TitleContext* this = (TitleContext*)thisx;
if (CVar_GetS32("gSkipLogoTitle",0)!=0) {
gSaveContext.language = CVar_GetS32("gLanguages", 0);
Sram_InitSram(&this->state, &this->sramCtx);
s16 selectedfile = CVar_GetS32("gSaveFileID", 0);
if (selectedfile == 4) {
selectedfile = 0xFF;
} else if(selectedfile == 0){
gSaveContext.fileNum = selectedfile;
gSaveContext.gameMode = 0;
this->state.running = false;
SET_NEXT_GAMESTATE(&this->state, FileChoose_Init, SelectContext);
return;
} else {
selectedfile--;
if (selectedfile < 0) {
selectedfile = 0xFF;
}
}
if (selectedfile == 0xFF) {
gSaveContext.fileNum = selectedfile;
Sram_OpenSave(&this->sramCtx);
gSaveContext.gameMode = 0;
this->state.running = false;
SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext);
} else {
gSaveContext.fileNum = selectedfile;
Sram_OpenSave(&this->sramCtx);
gSaveContext.gameMode = 0;
this->state.running = false;
//return;
SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext);
}
gSaveContext.respawn[0].entranceIndex = -1;
gSaveContext.respawnFlag = 0;
gSaveContext.seqId = (u8)NA_BGM_DISABLED;
gSaveContext.natureAmbienceId = 0xFF;
gSaveContext.showTitleCard = true;
gSaveContext.dogParams = 0;
gSaveContext.timer1State = 0;
gSaveContext.timer2State = 0;
gSaveContext.eventInf[0] = 0;
gSaveContext.eventInf[1] = 0;
gSaveContext.eventInf[2] = 0;
gSaveContext.eventInf[3] = 0;
gSaveContext.unk_13EE = 0x32;
gSaveContext.nayrusLoveTimer = 0;
gSaveContext.healthAccumulator = 0;
gSaveContext.unk_13F0 = 0;
gSaveContext.unk_13F2 = 0;
gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX;
gSaveContext.skyboxTime = 0;
gSaveContext.nextTransition = 0xFF;
gSaveContext.nextCutsceneIndex = 0xFFEF;
gSaveContext.cutsceneTrigger = 0;
gSaveContext.chamberCutsceneNum = 0;
gSaveContext.nextDayTime = 0xFFFF;
gSaveContext.unk_13C3 = 0;
gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] = gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[4] = BTN_ENABLED;
gSaveContext.unk_13E7 = gSaveContext.unk_13E8 = gSaveContext.unk_13EA = gSaveContext.unk_13EC = gSaveContext.unk_13F4 = 0;
gSaveContext.unk_13F6 = gSaveContext.magic;
gSaveContext.magic = 0;
gSaveContext.magicLevel = gSaveContext.magic;
gSaveContext.naviTimer = 0;
return;
}
OPEN_DISPS(this->state.gfxCtx, "../z_title.c", 494);
gSPSegment(POLY_OPA_DISP++, 0, NULL);

View File

@ -494,9 +494,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx
gDPPipeSync(POLY_KAL_DISP++);
if (D_8082A124[sp218] == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[sp218]);
if (CVar_GetS32("gHudColors", 1) == 0) { // A Button notes
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, D_8082A150[sp218]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[sp218]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), D_8082A150[sp218]);
}
} else {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]);
if (CVar_GetS32("gHudColors", 1) == 0) { // C Buttons notes
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[sp218]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 255), CVar_GetS32("gCCCBtnPrimB", 50), D_8082A150[sp218]);
}
}
gDPSetEnvColor(POLY_KAL_DISP++, 10, 10, 10, 0);
@ -524,9 +536,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx
if (pauseCtx->unk_1E4 == 8) {
if (gOcarinaSongNotes[sp224].notesIdx[phi_s3] == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, 200);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, 200);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, 200);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), 200);
}
} else {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, 200);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 255), CVar_GetS32("gCCCBtnPrimB", 50), 200);
}
}
} else {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 150, 150, 150, 150);
@ -579,9 +603,21 @@ void KaleidoScope_DrawQuestStatus(GlobalContext* globalCtx, GraphicsContext* gfx
gDPPipeSync(POLY_KAL_DISP++);
if (D_8082A124[phi_s3] == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[phi_s3]);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 150, 255, D_8082A150[phi_s3]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 80, 255, 150, D_8082A150[phi_s3]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 80), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 150), D_8082A150[phi_s3]);
}
} else {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]);
if (CVar_GetS32("gHudColors", 1) == 0) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 50, D_8082A150[phi_s3]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", 255), CVar_GetS32("gCCCBtnPrimG", 160), CVar_GetS32("gCCCBtnPrimB", 0), D_8082A150[phi_s3]);
}
}
gDPSetEnvColor(POLY_KAL_DISP++, 10, 10, 10, 0);

View File

@ -89,11 +89,17 @@ void KaleidoScope_DrawEquipmentImage(GlobalContext* globalCtx, void* source, u32
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kaleido_equipment.c", 122);
}
Vec3s link_kaleido_rot = { 0, 32300, 0 }; // Default rotation link face us.
void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) {
PauseContext* pauseCtx = &globalCtx->pauseCtx;
Vec3f pos;
Vec3s rot;
//Vec3s rot; // Removed for not having it use din the function
f32 scale;
Input* input = &globalCtx->state.input[0];
s16 RotationSpeed = 150 * CVar_GetS32("gPauseLiveLinkRotationSpeed", 0);
bool AllowCRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 2) ? true : false;
bool AllowDPadRotation = (CVar_GetS32("gPauseLiveLinkRotation", 0) == 1) ? true : false;
if (LINK_AGE_IN_YEARS == YEARS_CHILD) {
pos.x = 2.0f;
@ -112,11 +118,29 @@ void KaleidoScope_DrawPlayerWork(GlobalContext* globalCtx) {
scale = 0.047f;
}
rot.y = 32300;
rot.x = rot.z = 0;
link_kaleido_rot.x = link_kaleido_rot.z = 0;
if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DLEFT) ||
AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CLEFT)) {
link_kaleido_rot.y = link_kaleido_rot.y - RotationSpeed;
} else if (AllowDPadRotation && CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT) ||
AllowCRotation && CHECK_BTN_ALL(input->cur.button, BTN_CRIGHT)) {
link_kaleido_rot.y = link_kaleido_rot.y + RotationSpeed;
}
if (AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DUP) ||
AllowDPadRotation && CHECK_BTN_ALL(input->press.button, BTN_DDOWN)) {
link_kaleido_rot.y = 32300;
} else if (AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CUP) ||
AllowCRotation && CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) {
link_kaleido_rot.y = 32300;
}
link_kaleido_rot.x = 0;
extern int fbTest;
gsSPSetFB(globalCtx->state.gfxCtx->polyOpa.p++, fbTest);
func_8009214C(globalCtx, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &rot, scale,
func_8009214C(globalCtx, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &link_kaleido_rot, scale,
CUR_EQUIP_VALUE(EQUIP_SWORD), CUR_EQUIP_VALUE(EQUIP_TUNIC) - 1, CUR_EQUIP_VALUE(EQUIP_SHIELD),
CUR_EQUIP_VALUE(EQUIP_BOOTS) - 1);
gsSPResetFB(globalCtx->state.gfxCtx->polyOpa.p++);
@ -471,39 +495,76 @@ void KaleidoScope_DrawEquipment(GlobalContext* globalCtx) {
KaleidoScope_SetCursorVtx(pauseCtx, cursorSlot * 4, pauseCtx->equipVtx);
if ((pauseCtx->cursorSpecialPos == 0) && (cursorItem != PAUSE_ITEM_NONE) && (pauseCtx->state == 6) &&
(pauseCtx->unk_1E4 == 0) && CHECK_BTN_ALL(input->press.button, BTN_A) &&
(pauseCtx->unk_1E4 == 0) &&
CHECK_BTN_ANY(input->press.button, BTN_A | BTN_CLEFT | BTN_CDOWN | BTN_CRIGHT) &&
(pauseCtx->cursorX[PAUSE_EQUIP] != 0)) {
if ((gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] == 9) ||
(gEquipAgeReqs[pauseCtx->cursorY[PAUSE_EQUIP]][pauseCtx->cursorX[PAUSE_EQUIP]] ==
((void)0, gSaveContext.linkAge))) {
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
Inventory_ChangeEquipment(pauseCtx->cursorY[PAUSE_EQUIP], pauseCtx->cursorX[PAUSE_EQUIP]);
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
gSaveContext.infTable[29] = 0;
gSaveContext.equips.buttonItems[0] = cursorItem;
if (pauseCtx->cursorY[PAUSE_EQUIP] == 0) {
gSaveContext.infTable[29] = 0;
gSaveContext.equips.buttonItems[0] = cursorItem;
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
gSaveContext.swordHealth = 8;
} else {
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
if ((pauseCtx->cursorX[PAUSE_EQUIP] == 3) && (gSaveContext.bgsFlag != 0)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
gSaveContext.swordHealth = 8;
} else {
if (gSaveContext.equips.buttonItems[0] == ITEM_HEART_PIECE_2) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS;
}
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
}
}
if ((gSaveContext.equips.buttonItems[0] == ITEM_SWORD_BGS) && (gSaveContext.bgsFlag == 0) &&
(gBitFlags[3] & gSaveContext.inventory.equipment)) {
gSaveContext.equips.buttonItems[0] = ITEM_SWORD_KNIFE;
}
Interface_LoadItemIcon1(globalCtx, 0);
}
Interface_LoadItemIcon1(globalCtx, 0);
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
pauseCtx->unk_1E4 = 7;
sEquipTimer = 10;
} else if (CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) {
// Only allow assigning tunic and boots to c-buttons
if (pauseCtx->cursorY[PAUSE_EQUIP] > 1) {
u16 slot = 0;
switch (cursorItem) {
case ITEM_TUNIC_KOKIRI:
slot = SLOT_TUNIC_KOKIRI;
break;
case ITEM_TUNIC_GORON:
slot = SLOT_TUNIC_GORON;
break;
case ITEM_TUNIC_ZORA:
slot = SLOT_TUNIC_ZORA;
break;
case ITEM_BOOTS_KOKIRI:
slot = SLOT_BOOTS_KOKIRI;
break;
case ITEM_BOOTS_IRON:
slot = SLOT_BOOTS_IRON;
break;
case ITEM_BOOTS_HOVER:
slot = SLOT_BOOTS_HOVER;
break;
default:
break;
}
KaleidoScope_SetupItemEquip(globalCtx, cursorItem, slot,
pauseCtx->equipVtx[cursorSlot * 4].v.ob[0] * 10,
pauseCtx->equipVtx[cursorSlot * 4].v.ob[1] * 10);
}
}
Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
pauseCtx->unk_1E4 = 7;
sEquipTimer = 10;
} else {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
} else if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->cursorY[PAUSE_EQUIP] > 1)) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
}
}
}

View File

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

View File

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

View File

@ -916,6 +916,13 @@ void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) {
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex + pt][3];
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex + pt][4];
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (D_8082ABEC[pauseCtx->mode] == PAUSE_EQUIP)) {
gSaveContext.buttonStatus[1] = BTN_ENABLED;
gSaveContext.buttonStatus[2] = BTN_ENABLED;
gSaveContext.buttonStatus[3] = BTN_ENABLED;
gSaveContext.buttonStatus[4] = BTN_ENABLED;
}
osSyncPrintf("kscope->kscp_pos+pt = %d\n", pauseCtx->pageIndex + pt);
gSaveContext.unk_13EA = 0;
@ -968,6 +975,29 @@ void KaleidoScope_DrawCursor(GlobalContext* globalCtx, u16 pageIndex) {
temp = pauseCtx->unk_1E4;
if (CVar_GetS32("gHudColors", 1) == 0) {
sCursorColors[1][0] = 255;
sCursorColors[1][1] = 255;
sCursorColors[1][2] = 0;
sCursorColors[2][0] = 0;
sCursorColors[2][1] = 50;
sCursorColors[2][2] = 255;
} else if (CVar_GetS32("gHudColors", 1) == 1) {
sCursorColors[1][0] = 255;
sCursorColors[1][1] = 255;
sCursorColors[1][2] = 0;
sCursorColors[2][0] = 0;
sCursorColors[2][1] = 255;
sCursorColors[2][2] = 50;
} else if (CVar_GetS32("gHudColors", 1) == 2) {
sCursorColors[1][0] = CVar_GetS32("gCCCBtnPrimR", 255);
sCursorColors[1][1] = CVar_GetS32("gCCCBtnPrimG", 255);
sCursorColors[1][2] = CVar_GetS32("gCCCBtnPrimB", 0);
sCursorColors[2][0] = CVar_GetS32("gCCABtnPrimR", 0);
sCursorColors[2][1] = CVar_GetS32("gCCABtnPrimG", 255);
sCursorColors[2][2] = CVar_GetS32("gCCABtnPrimB", 50);
}
if ((((pauseCtx->unk_1E4 == 0) || (temp == 8)) && (pauseCtx->state == 6)) ||
((pauseCtx->pageIndex == PAUSE_QUEST) && ((temp < 3) || (temp == 5) || (temp == 8)))) {
@ -1038,6 +1068,46 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 255, 255, 0 }, { 0, 0, 0 },
{ 0, 0, 0 }, { 255, 255, 0 }, { 0, 255, 50 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 255, 50 },
};
if (CVar_GetS32("gHudColors", 1) == 0) {
D_8082ACF4[4][0] = 255;
D_8082ACF4[4][1] = 255;
D_8082ACF4[4][2] = 0;
D_8082ACF4[7][0] = 255;
D_8082ACF4[7][1] = 255;
D_8082ACF4[7][2] = 0;
D_8082ACF4[8][0] = 0;
D_8082ACF4[8][1] = 50;
D_8082ACF4[8][2] = 255;
D_8082ACF4[11][0] = 0;
D_8082ACF4[11][1] = 50;
D_8082ACF4[11][2] = 255;
} else if (CVar_GetS32("gHudColors", 1) == 1) {
D_8082ACF4[4][0] = 255;
D_8082ACF4[4][1] = 255;
D_8082ACF4[4][2] = 0;
D_8082ACF4[7][0] = 255;
D_8082ACF4[7][1] = 255;
D_8082ACF4[7][2] = 0;
D_8082ACF4[8][0] = 0;
D_8082ACF4[8][1] = 255;
D_8082ACF4[8][2] = 50;
D_8082ACF4[11][0] = 0;
D_8082ACF4[11][1] = 255;
D_8082ACF4[11][2] = 50;
} else if (CVar_GetS32("gHudColors", 1) == 2) {
D_8082ACF4[4][0] = CVar_GetS32("gCCCBtnPrimR", 255);
D_8082ACF4[4][1] = CVar_GetS32("gCCCBtnPrimG", 255);
D_8082ACF4[4][2] = CVar_GetS32("gCCCBtnPrimB", 0);
D_8082ACF4[7][0] = CVar_GetS32("gCCCBtnPrimR", 255);
D_8082ACF4[7][1] = CVar_GetS32("gCCCBtnPrimG", 255);
D_8082ACF4[7][2] = CVar_GetS32("gCCCBtnPrimB", 0);
D_8082ACF4[8][0] = CVar_GetS32("gCCABtnPrimR", 0);
D_8082ACF4[8][1] = CVar_GetS32("gCCABtnPrimG", 255);
D_8082ACF4[8][2] = CVar_GetS32("gCCABtnPrimB", 50);
D_8082ACF4[11][0] = CVar_GetS32("gCCABtnPrimR", 0);
D_8082ACF4[11][1] = CVar_GetS32("gCCABtnPrimG", 255);
D_8082ACF4[11][2] = CVar_GetS32("gCCABtnPrimB", 50);
}
static s16 D_8082AD3C = 20;
static s16 D_8082AD40 = 0;
static s16 D_8082AD44 = 0;
@ -1366,7 +1436,13 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
gDPSetCombineLERP(POLY_KAL_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0,
0, PRIMITIVE, 0);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 255, 100, VREG(61));
if (CVar_GetS32("gHudColors", 1) == 0) {//Save prompt cursor colour
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 100, 255, VREG(61));
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 100, 255, 100, VREG(61));
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", 100), CVar_GetS32("gCCABtnPrimG", 255), CVar_GetS32("gCCABtnPrimB", 100), VREG(61)); //Save prompt cursor colour
}
if (pauseCtx->promptChoice == 0) {
gSPDisplayList(POLY_KAL_DISP++, gPromptCursorLeftDL);
@ -1425,6 +1501,10 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
}
void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
static s16 gABtnTexColour[][4] = { //A button colors
{ 0, 255, 100, 255 },//Gamecube
{ 0, 100, 255, 255 },//Original N64
};
static void* D_8082AD54[3] = {
gPauseToEquipENGTex,
gPauseToEquipGERTex,
@ -1750,8 +1830,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = D_8082ADE0[gSaveContext.language]
<< 5;
gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);
if (CVar_GetS32("gHudColors", 1) == 0) {//A icon to decide in save prompt
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]);
}
//gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);//This is changed to load the texture only so we can prim color it.
gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
gDPPipeSync(POLY_KAL_DISP++);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255);
@ -1797,7 +1885,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] =
D_8082ADD8[gSaveContext.language] << 5;
gSPDisplayList(POLY_KAL_DISP++, gCButtonIconsDL);
if (CVar_GetS32("gHudColors", 1) == 0) {//To equip text C button icon
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), 255);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, R_C_BTN_COLOR(0), R_C_BTN_COLOR(1), R_C_BTN_COLOR(2), 255);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCCBtnPrimR", R_C_BTN_COLOR(0)), CVar_GetS32("gCCCBtnPrimG", R_C_BTN_COLOR(1)), CVar_GetS32("gCCCBtnPrimB", R_C_BTN_COLOR(2)), 255);
}
//gSPDisplayList(POLY_KAL_DISP++, gCButtonIconsDL); //Same reason for every A button, to be able to recolor them.
gDPLoadTextureBlock(POLY_KAL_DISP++, gCBtnSymbolsTex, G_IM_FMT_IA, G_IM_SIZ_8b, 48, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
gDPPipeSync(POLY_KAL_DISP++);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255);
@ -1831,7 +1928,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] =
D_8082ADE8[gSaveContext.language] << 5;
gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);
if (CVar_GetS32("gHudColors", 1) == 0) {//To play melody A button
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]);
}
//gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);
gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
gDPPipeSync(POLY_KAL_DISP++);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255);
@ -1857,7 +1963,16 @@ void KaleidoScope_DrawInfoPanel(GlobalContext* globalCtx) {
pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] =
D_8082ADD8[gSaveContext.language] << 5;
gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);
//gSPDisplayList(POLY_KAL_DISP++, gAButtonIconDL);
if (CVar_GetS32("gHudColors", 1) == 0) {//To equip A button
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[1][0], gABtnTexColour[1][1], gABtnTexColour[1][2], gABtnTexColour[1][3]);
} else if (CVar_GetS32("gHudColors", 1) == 1) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, gABtnTexColour[0][0], gABtnTexColour[0][1], gABtnTexColour[0][2], gABtnTexColour[0][3]);
} else if (CVar_GetS32("gHudColors", 1) == 2) {
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, CVar_GetS32("gCCABtnPrimR", gABtnTexColour[0][0]), CVar_GetS32("gCCABtnPrimG", gABtnTexColour[0][1]), CVar_GetS32("gCCABtnPrimB", gABtnTexColour[0][2]), gABtnTexColour[0][3]);
}
gDPLoadTextureBlock(POLY_KAL_DISP++, gABtnSymbolTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 4, 4, G_TX_NOLOD, G_TX_NOLOD);
gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0);
gDPPipeSync(POLY_KAL_DISP++);
gDPSetPrimColor(POLY_KAL_DISP++, 0, 0, 255, 255, 255, 255);
@ -2860,14 +2975,6 @@ void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) {
u16 gray;
u16 i;
bind_hook( GRAYOUT_TEXTURE);
init_hook(2,
(struct HookParameter){ .name = "texture", .parameter = &texture },
(struct HookParameter){ .name = "pixelCount", .parameter = &pixelCount }
);
if (!call_hook(0))
return;
texture = ResourceMgr_LoadTexByName(texture);
for (i = 0; i < pixelCount; i++) {
@ -2902,7 +3009,16 @@ void func_808265BC(GlobalContext* globalCtx) {
gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex][2];
gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex][3];
gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex][4];
pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode];
if ((CVar_GetS32("gAssignableTunicsAndBoots", 0) != 0) && (pauseCtx->pageIndex == PAUSE_EQUIP)) {
gSaveContext.buttonStatus[1] = BTN_ENABLED;
gSaveContext.buttonStatus[2] = BTN_ENABLED;
gSaveContext.buttonStatus[3] = BTN_ENABLED;
gSaveContext.buttonStatus[4] = BTN_ENABLED;
}
pauseCtx->unk_1E4 = 0;
pauseCtx->state++;
pauseCtx->alpha = 255;