mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-11 12:05:09 -05:00
Merge branch 'develop' into 3DProjectiles
This commit is contained in:
commit
ea0ea0366b
@ -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()));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2789,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());
|
||||
@ -2825,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) {
|
||||
|
@ -67,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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -46,9 +46,9 @@ bool oldCursorState = true;
|
||||
|
||||
#define EXPERIMENTAL() \
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 50, 50, 255)); \
|
||||
ImGui::Text("Experimental"); \
|
||||
ImGui::PopStyleColor(); \
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Experimental"); \
|
||||
ImGui::PopStyleColor(); \
|
||||
ImGui::Separator();
|
||||
#define TOGGLE_BTN ImGuiKey_F1
|
||||
#define HOOK(b) if(b) needs_save = true;
|
||||
OSContPad* pads;
|
||||
@ -66,29 +66,38 @@ namespace SohImGui {
|
||||
std::vector<const char*> CustomTexts;
|
||||
int SelectedLanguage = CVar_GetS32("gLanguages", 0); //Default Language to 0=English 1=German 2=French
|
||||
int SelectedHUD = CVar_GetS32("gHudColors", 1); //Default colors to Gamecube.
|
||||
float hearts_colors[3] = {0,0,0};
|
||||
float hearts_dd_colors[3] = {0,0,0};
|
||||
float a_btn_colors[3] = {0,0,0};
|
||||
float b_btn_colors[3] = {0,0,0};
|
||||
float c_btn_colors[3] = {0,0,0};
|
||||
float start_btn_colors[3] = {0,0,0};
|
||||
float magic_border_colors[3] = {0,0,0};
|
||||
float magic_remaining_colors[3] = {0,0,0};
|
||||
float magic_use_colors[3] = {0,0,0};
|
||||
float minimap_colors[3] = {0,0,0};
|
||||
float rupee_colors[3] = {0,0,0};
|
||||
float smolekey_colors[3] = {0,0,0};
|
||||
float kokiri_col[3] = { 0.118f, 0.41f, 0.106f };
|
||||
float goron_col[3] = { 0.392f, 0.078f, 0.0f };
|
||||
float zora_col[3] = { 0.0f, 0.235f, 0.392f };
|
||||
float navi_idle_i_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_idle_o_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_npc_i_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_npc_o_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_enemy_i_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_enemy_o_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_prop_i_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
float navi_prop_o_col[3] = { 0.0f, 0.0f, 0.0f };
|
||||
ImVec4 hearts_colors;
|
||||
ImVec4 hearts_dd_colors;
|
||||
ImVec4 a_btn_colors;
|
||||
ImVec4 b_btn_colors;
|
||||
ImVec4 c_btn_colors;
|
||||
ImVec4 start_btn_colors;
|
||||
ImVec4 magic_border_colors;
|
||||
ImVec4 magic_remaining_colors;
|
||||
ImVec4 magic_use_colors;
|
||||
ImVec4 minimap_colors;
|
||||
ImVec4 rupee_colors;
|
||||
ImVec4 smolekey_colors;
|
||||
ImVec4 kokiri_col;
|
||||
ImVec4 goron_col;
|
||||
ImVec4 zora_col;
|
||||
ImVec4 navi_idle_i_col;
|
||||
ImVec4 navi_idle_o_col;
|
||||
ImVec4 navi_npc_i_col;
|
||||
ImVec4 navi_npc_o_col;
|
||||
ImVec4 navi_enemy_i_col;
|
||||
ImVec4 navi_enemy_o_col;
|
||||
ImVec4 navi_prop_i_col;
|
||||
ImVec4 navi_prop_o_col;
|
||||
|
||||
const char* RainbowColorCvarList[] = {
|
||||
//This is the list of possible CVars that has rainbow effect.
|
||||
"gTunic_Kokiri_","gTunic_Goron_","gTunic_Zora_",
|
||||
"gCCHeartsPrim","gDDCCHeartsPrim",
|
||||
"gCCABtnPrim","gCCBBtnPrim","gCCCBtnPrim","gCCStartBtnPrim",
|
||||
"gCCMagicBorderPrim","gCCMagicPrim","gCCMagicUsePrim",
|
||||
"gCCMinimapPrim","gCCRupeePrim","gCCKeysPrim"
|
||||
};
|
||||
|
||||
const char* filters[3] = {
|
||||
"Three-Point",
|
||||
@ -99,6 +108,15 @@ namespace SohImGui {
|
||||
std::map<std::string, std::vector<std::string>> windowCategories;
|
||||
std::map<std::string, CustomWindow> customWindows;
|
||||
|
||||
int ClampFloatToInt(float value, int min, int max){
|
||||
return fmin(fmax(value,min),max);
|
||||
}
|
||||
|
||||
void Tooltip(const char* text) {
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", text);
|
||||
}
|
||||
|
||||
void ImGuiWMInit() {
|
||||
switch (impl.backend) {
|
||||
case Backend::SDL:
|
||||
@ -240,82 +258,64 @@ namespace SohImGui {
|
||||
stbi_image_free(img_data);
|
||||
}
|
||||
|
||||
void LoadInterfaceEditor(){//This function is necessary as without it IMGui wont load the updated float array.
|
||||
hearts_colors[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255;
|
||||
hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 70)/255;
|
||||
hearts_colors[2] = (float)CVar_GetS32("gCCHeartsPrimB", 50)/255;
|
||||
hearts_dd_colors[0] = (float)CVar_GetS32("gDDCCHeartsPrimR", 255)/255;
|
||||
hearts_dd_colors[1] = (float)CVar_GetS32("gDDCCHeartsPrimG", 255)/255;
|
||||
hearts_dd_colors[2] = (float)CVar_GetS32("gDDCCHeartsPrimB", 255)/255;
|
||||
a_btn_colors[0] = (float)CVar_GetS32("gCCABtnPrimR", 90)/255;
|
||||
a_btn_colors[1] = (float)CVar_GetS32("gCCABtnPrimG", 90)/255;
|
||||
a_btn_colors[2] = (float)CVar_GetS32("gCCABtnPrimB", 255)/255;
|
||||
b_btn_colors[0] = (float)CVar_GetS32("gCCBBtnPrimR", 0)/255;
|
||||
b_btn_colors[1] = (float)CVar_GetS32("gCCBBtnPrimG", 150)/255;
|
||||
b_btn_colors[2] = (float)CVar_GetS32("gCCBBtnPrimB", 0)/255;
|
||||
c_btn_colors[0] = (float)CVar_GetS32("gCCCBtnPrimR", 255)/255;
|
||||
c_btn_colors[1] = (float)CVar_GetS32("gCCCBtnPrimG", 160)/255;
|
||||
c_btn_colors[2] = (float)CVar_GetS32("gCCCBtnPrimB", 0)/255;
|
||||
start_btn_colors[0] = (float)CVar_GetS32("gCCStartBtnPrimR", 120)/255;
|
||||
start_btn_colors[1] = (float)CVar_GetS32("gCCStartBtnPrimG", 120)/255;
|
||||
start_btn_colors[2] = (float)CVar_GetS32("gCCStartBtnPrimB", 120)/255;
|
||||
magic_border_colors[0] = (float)CVar_GetS32("gCCMagicBorderPrimR", 255)/255;
|
||||
magic_border_colors[1] = (float)CVar_GetS32("gCCMagicBorderPrimG", 255)/255;
|
||||
magic_border_colors[2] = (float)CVar_GetS32("gCCMagicBorderPrimB", 255)/255;
|
||||
magic_use_colors[0] = (float)CVar_GetS32("gCCMagicPrimR", 250)/255;
|
||||
magic_use_colors[1] = (float)CVar_GetS32("gCCMagicPrimG", 250)/255;
|
||||
magic_use_colors[2] = (float)CVar_GetS32("gCCMagicPrimB", 0)/255;
|
||||
magic_remaining_colors[0] = (float)CVar_GetS32("gCCMagicUsePrimR", 0)/255;
|
||||
magic_remaining_colors[1] = (float)CVar_GetS32("gCCMagicUsePrimG", 200)/255;
|
||||
magic_remaining_colors[2] = (float)CVar_GetS32("gCCMagicUsePrimB", 0)/255;
|
||||
minimap_colors[0] = (float)CVar_GetS32("gCCMinimapPrimR", 0)/255;
|
||||
minimap_colors[1] = (float)CVar_GetS32("gCCMinimapPrimG", 255)/255;
|
||||
minimap_colors[2] = (float)CVar_GetS32("gCCMinimapPrimB", 255)/255;
|
||||
rupee_colors[0] = (float)CVar_GetS32("gCCRupeePrimR", 200)/255;
|
||||
rupee_colors[1] = (float)CVar_GetS32("gCCRupeePrimG", 255)/255;
|
||||
rupee_colors[2] = (float)CVar_GetS32("gCCRupeePrimB", 100)/255;
|
||||
smolekey_colors[0] = (float)CVar_GetS32("gCCKeysPrimR", 200)/255;
|
||||
smolekey_colors[1] = (float)CVar_GetS32("gCCKeysPrimG", 230)/255;
|
||||
smolekey_colors[2] = (float)CVar_GetS32("gCCKeysPrimB", 255)/255;
|
||||
kokiri_col[0] = (float)CVar_GetS32("gTunic_Kokiri_R", 30)/255;
|
||||
kokiri_col[1] = (float)CVar_GetS32("gTunic_Kokiri_G", 105)/255;
|
||||
kokiri_col[2] = (float)CVar_GetS32("gTunic_Kokiri_B", 27)/255;
|
||||
goron_col[0] = (float)CVar_GetS32("gTunic_Goron_R", 100)/255;
|
||||
goron_col[1] = (float)CVar_GetS32("gTunic_Goron_G", 20)/255;
|
||||
goron_col[2] = (float)CVar_GetS32("gTunic_Goron_B", 0)/255;
|
||||
zora_col[0] = (float)CVar_GetS32("gTunic_Zora_R", 0)/255;
|
||||
zora_col[1] = (float)CVar_GetS32("gTunic_Zora_G", 60)/255;
|
||||
zora_col[2] = (float)CVar_GetS32("gTunic_Zora_B", 100)/255;
|
||||
navi_idle_i_col[0] = (float)CVar_GetS32("gNavi_Idle_Inner_R", 255)/255;
|
||||
navi_idle_i_col[1] = (float)CVar_GetS32("gNavi_Idle_Inner_G", 255)/255;
|
||||
navi_idle_i_col[2] = (float)CVar_GetS32("gNavi_Idle_Inner_B", 255)/255;
|
||||
navi_idle_o_col[0] = (float)CVar_GetS32("gNavi_Idle_Outer_R", 115)/255;
|
||||
navi_idle_o_col[1] = (float)CVar_GetS32("gNavi_Idle_Outer_G", 230)/255;
|
||||
navi_idle_o_col[2] = (float)CVar_GetS32("gNavi_Idle_Outer_B", 255)/255;
|
||||
navi_npc_i_col[0] = (float)CVar_GetS32("gNavi_NPC_Inner_R", 100)/255;
|
||||
navi_npc_i_col[1] = (float)CVar_GetS32("gNavi_NPC_Inner_G", 100)/255;
|
||||
navi_npc_i_col[2] = (float)CVar_GetS32("gNavi_NPC_Inner_B", 255)/255;
|
||||
navi_npc_o_col[0] = (float)CVar_GetS32("gNavi_NPC_Outer_R", 90)/255;
|
||||
navi_npc_o_col[1] = (float)CVar_GetS32("gNavi_NPC_Outer_G", 90)/255;
|
||||
navi_npc_o_col[2] = (float)CVar_GetS32("gNavi_NPC_Outer_B", 255)/255;
|
||||
navi_enemy_i_col[0] = (float)CVar_GetS32("gNavi_Enemy_Inner_R", 255)/255;
|
||||
navi_enemy_i_col[1] = (float)CVar_GetS32("gNavi_Enemy_Inner_G", 255)/255;
|
||||
navi_enemy_i_col[2] = (float)CVar_GetS32("gNavi_Enemy_Inner_B", 0)/255;
|
||||
navi_enemy_o_col[0] = (float)CVar_GetS32("gNavi_Enemy_Outer_R", 220)/255;
|
||||
navi_enemy_o_col[1] = (float)CVar_GetS32("gNavi_Enemy_Outer_G", 220)/255;
|
||||
navi_enemy_o_col[2] = (float)CVar_GetS32("gNavi_Enemy_Outer_B", 0)/255;
|
||||
navi_prop_i_col[0] = (float)CVar_GetS32("gNavi_Prop_Inner_R", 0)/255;
|
||||
navi_prop_i_col[1] = (float)CVar_GetS32("gNavi_Prop_Inner_G", 255)/255;
|
||||
navi_prop_i_col[2] = (float)CVar_GetS32("gNavi_Prop_Inner_B", 0)/255;
|
||||
navi_prop_o_col[0] = (float)CVar_GetS32("gNavi_Prop_Outer_R", 0)/255;
|
||||
navi_prop_o_col[1] = (float)CVar_GetS32("gNavi_Prop_Outer_G", 220)/255;
|
||||
navi_prop_o_col[2] = (float)CVar_GetS32("gNavi_Prop_Outer_B", 0)/255;
|
||||
if (CVar_GetS32("gHudColors", 1) ==0) {
|
||||
SelectedHUD = 0;
|
||||
} else if (CVar_GetS32("gHudColors", 1) == 1) {
|
||||
SelectedHUD = 1;
|
||||
} else if (CVar_GetS32("gHudColors", 1) == 2) {
|
||||
SelectedHUD = 2;
|
||||
void LoadRainbowColor() {
|
||||
for (uint16_t s=0; s <= sizeof(RainbowColorCvarList); s++) {
|
||||
std::string cvarName = RainbowColorCvarList[s];
|
||||
std::string Cvar_Red = cvarName;
|
||||
Cvar_Red += "R";
|
||||
std::string Cvar_Green = cvarName;
|
||||
Cvar_Green += "G";
|
||||
std::string Cvar_Blue = cvarName;
|
||||
Cvar_Blue += "B";
|
||||
std::string Cvar_RBM = cvarName;
|
||||
Cvar_RBM += "RBM";
|
||||
std::string RBM_HUE = cvarName;
|
||||
RBM_HUE+="Hue";
|
||||
f32 Canon = 10.f*s;
|
||||
ImVec4 NewColor;
|
||||
const f32 deltaTime = 1.0f / ImGui::GetIO().Framerate;
|
||||
f32 hue = CVar_GetFloat(RBM_HUE.c_str(), 0.0f);
|
||||
f32 newHue = hue + CVar_GetS32("gColorRainbowSpeed", 1) * 36.0f * deltaTime;
|
||||
if (newHue >= 360)
|
||||
newHue = 0;
|
||||
CVar_SetFloat(RBM_HUE.c_str(), newHue);
|
||||
f32 current_hue = CVar_GetFloat(RBM_HUE.c_str(), 0);
|
||||
u8 i = current_hue / 60 + 1;
|
||||
u8 a = (-current_hue / 60.0f + i) * 255;
|
||||
u8 b = (current_hue / 60.0f + (1 - i)) * 255;
|
||||
|
||||
switch (i) {
|
||||
case 1: NewColor.x = 255; NewColor.y = b; NewColor.z = 0; break;
|
||||
case 2: NewColor.x = a; NewColor.y = 255; NewColor.z = 0; break;
|
||||
case 3: NewColor.x = 0; NewColor.y = 255; NewColor.z = b; break;
|
||||
case 4: NewColor.x = 0; NewColor.y = a; NewColor.z = 255; break;
|
||||
case 5: NewColor.x = b; NewColor.y = 0; NewColor.z = 255; break;
|
||||
case 6: NewColor.x = 255; NewColor.y = 0; NewColor.z = a; break;
|
||||
}
|
||||
|
||||
if(CVar_GetS32(Cvar_RBM.c_str(), 0) != 0) {
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(NewColor.x,0,255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(NewColor.y,0,255));
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(NewColor.z,0,255));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadPickersColors(ImVec4& ColorArray, const char* cvarname, const ImVec4& default_colors, bool has_alpha) {
|
||||
std::string Cvar_Red = cvarname;
|
||||
Cvar_Red += "R";
|
||||
std::string Cvar_Green = cvarname;
|
||||
Cvar_Green += "G";
|
||||
std::string Cvar_Blue = cvarname;
|
||||
Cvar_Blue += "B";
|
||||
std::string Cvar_Alpha = cvarname;
|
||||
Cvar_Alpha += "A";
|
||||
|
||||
ColorArray.x = (float)CVar_GetS32(Cvar_Red.c_str(), default_colors.x)/255;
|
||||
ColorArray.y = (float)CVar_GetS32(Cvar_Green.c_str(), default_colors.y)/255;
|
||||
ColorArray.z = (float)CVar_GetS32(Cvar_Blue.c_str(), default_colors.z)/255;
|
||||
if (has_alpha) {
|
||||
ColorArray.w = (float)CVar_GetS32(Cvar_Alpha.c_str(), default_colors.w)/255;
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,10 +348,10 @@ namespace SohImGui {
|
||||
}
|
||||
|
||||
for (size_t pixel = 0; pixel < texBuffer.size() / 4; pixel++) {
|
||||
texBuffer[pixel * 4 + 0] *= tint.x;
|
||||
texBuffer[pixel * 4 + 1] *= tint.y;
|
||||
texBuffer[pixel * 4 + 2] *= tint.z;
|
||||
texBuffer[pixel * 4 + 3] *= tint.w;
|
||||
texBuffer[pixel * 4 + 0] *= (uint8_t)tint.x;
|
||||
texBuffer[pixel * 4 + 1] *= (uint8_t)tint.y;
|
||||
texBuffer[pixel * 4 + 2] *= (uint8_t)tint.z;
|
||||
texBuffer[pixel * 4 + 3] *= (uint8_t)tint.w;
|
||||
}
|
||||
|
||||
const auto asset = new GameAsset{ api->new_texture() };
|
||||
@ -436,7 +436,7 @@ namespace SohImGui {
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementRadioButton(std::string text, std::string cvarName, int id) {
|
||||
void EnhancementRadioButton(const char* text, const char* cvarName, int id) {
|
||||
/*Usage :
|
||||
EnhancementRadioButton("My Visible Name","gMyCVarName", MyID);
|
||||
First arg is the visible name of the Radio button
|
||||
@ -447,118 +447,219 @@ namespace SohImGui {
|
||||
EnhancementRadioButton("German", "gLanguages", 1);
|
||||
EnhancementRadioButton("French", "gLanguages", 2);
|
||||
*/
|
||||
int val = CVar_GetS32(cvarName.c_str(), 0);
|
||||
if (ImGui::RadioButton(text.c_str(), id == val)) {
|
||||
CVar_SetS32(cvarName.c_str(), (int)id);
|
||||
std::string make_invisible = "##";
|
||||
make_invisible += text;
|
||||
make_invisible += cvarName;
|
||||
|
||||
int val = CVar_GetS32(cvarName, 0);
|
||||
if (ImGui::RadioButton(make_invisible.c_str(), id == val)) {
|
||||
CVar_SetS32(cvarName, id);
|
||||
needs_save = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("%s", text);
|
||||
}
|
||||
|
||||
void EnhancementCheckbox(const char* text, const char* cvarName)
|
||||
{
|
||||
bool val = (bool)CVar_GetS32(cvarName, 0);
|
||||
if (ImGui::Checkbox(text, &val)) {
|
||||
CVar_SetS32(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementCheckbox(std::string text, std::string cvarName)
|
||||
void EnhancementButton(const char* text, const char* cvarName)
|
||||
{
|
||||
bool val = (bool)CVar_GetS32(cvarName.c_str(), 0);
|
||||
if (ImGui::Checkbox(text.c_str(), &val)) {
|
||||
CVar_SetS32(cvarName.c_str(), val);
|
||||
bool val = (bool)CVar_GetS32(cvarName, 0);
|
||||
if (ImGui::Button(text)) {
|
||||
CVar_SetS32(cvarName, !val);
|
||||
CVar_SetS32(cvarName, !val);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementButton(std::string text, std::string cvarName)
|
||||
void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format)
|
||||
{
|
||||
bool val = (bool)CVar_GetS32(cvarName.c_str(), 0);
|
||||
if (ImGui::Button(text.c_str())) {
|
||||
CVar_SetS32(cvarName.c_str(), !val);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
int val = CVar_GetS32(cvarName, 0);
|
||||
|
||||
void EnhancementSliderInt(std::string text, std::string id, std::string cvarName, int min, int max, std::string format)
|
||||
{
|
||||
int val = CVar_GetS32(cvarName.c_str(), 0);
|
||||
ImGui::Text(text, val);
|
||||
|
||||
ImGui::Text(text.c_str(), val);
|
||||
|
||||
if (ImGui::SliderInt(id.c_str(), &val, min, max, format.c_str()))
|
||||
if (ImGui::SliderInt(id, &val, min, max, format))
|
||||
{
|
||||
CVar_SetS32(cvarName.c_str(), val);
|
||||
CVar_SetS32(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
if (val < min)
|
||||
{
|
||||
val = min;
|
||||
CVar_SetS32(cvarName.c_str(), val);
|
||||
CVar_SetS32(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
if (val > max)
|
||||
{
|
||||
val = max;
|
||||
CVar_SetS32(cvarName.c_str(), val);
|
||||
CVar_SetS32(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
|
||||
void EnhancementSliderFloat(std::string text, std::string id, std::string cvarName, float min, float max, std::string format, float defaultValue, bool isPercentage)
|
||||
void EnhancementSliderFloat(const char* text, const char* id, const char* cvarName, float min, float max, const char* format, float defaultValue, bool isPercentage)
|
||||
{
|
||||
float val = CVar_GetFloat(cvarName.c_str(), defaultValue);
|
||||
float val = CVar_GetFloat(cvarName, defaultValue);
|
||||
|
||||
if (!isPercentage)
|
||||
ImGui::Text(text.c_str(), val);
|
||||
ImGui::Text(text, val);
|
||||
else
|
||||
ImGui::Text(text.c_str(), static_cast<int>(100 * val));
|
||||
ImGui::Text(text, static_cast<int>(100 * val));
|
||||
|
||||
if (ImGui::SliderFloat(id.c_str(), &val, min, max, format.c_str()))
|
||||
if (ImGui::SliderFloat(id, &val, min, max, format))
|
||||
{
|
||||
CVar_SetFloat(cvarName.c_str(), val);
|
||||
CVar_SetFloat(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
if (val < min)
|
||||
{
|
||||
val = min;
|
||||
CVar_SetFloat(cvarName.c_str(), val);
|
||||
CVar_SetFloat(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
if (val > max)
|
||||
{
|
||||
val = max;
|
||||
CVar_SetFloat(cvarName.c_str(), val);
|
||||
CVar_SetFloat(cvarName, val);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
|
||||
int ClampFloatToInt(float value, int min, int max){
|
||||
return fmin(fmax(value,min),max);
|
||||
void RandomizeColor(const char* cvarName, ImVec4* colors) {
|
||||
std::string Cvar_Red = cvarName;
|
||||
Cvar_Red += "R";
|
||||
std::string Cvar_Green = cvarName;
|
||||
Cvar_Green += "G";
|
||||
std::string Cvar_Blue = cvarName;
|
||||
Cvar_Blue += "B";
|
||||
std::string Cvar_RBM = cvarName;
|
||||
Cvar_RBM += "RBM";
|
||||
std::string MakeInvisible = "##";
|
||||
MakeInvisible += cvarName;
|
||||
MakeInvisible += "Random";
|
||||
std::string FullName = "Random";
|
||||
FullName+=MakeInvisible;
|
||||
if (ImGui::Button(FullName.c_str())) {
|
||||
s16 RND_R = rand() % (255 - 0);
|
||||
s16 RND_G = rand() % (255 - 0);
|
||||
s16 RND_B = rand() % (255 - 0);
|
||||
colors->x = (float)RND_R/255;
|
||||
colors->y = (float)RND_G/255;
|
||||
colors->z = (float)RND_B/255;
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(colors->x*255,0,255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(colors->y*255,0,255));
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(colors->z*255,0,255));
|
||||
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
|
||||
needs_save = true;
|
||||
}
|
||||
Tooltip("Clicking this button will make a random color for the colors at it's right.\nPrevious color will be overwrite and will not be recoverable");
|
||||
}
|
||||
|
||||
void EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine) {
|
||||
//Simplified.
|
||||
void RainbowColor(const char* cvarName, ImVec4* colors) {
|
||||
std::string Cvar_RBM = cvarName;
|
||||
Cvar_RBM += "RBM";
|
||||
std::string MakeInvisible = "Rainbow";
|
||||
MakeInvisible += "##";
|
||||
MakeInvisible += cvarName;
|
||||
MakeInvisible += "Rainbow";
|
||||
|
||||
EnhancementCheckbox(MakeInvisible.c_str(), Cvar_RBM.c_str());
|
||||
Tooltip("Clicking this button will make color cycling\nPrevious color will be overwrite and will not be recoverable");
|
||||
}
|
||||
|
||||
void ResetColor(const char* cvarName, ImVec4* colors, ImVec4 defaultcolors, bool has_alpha) {
|
||||
std::string Cvar_Red = cvarName;
|
||||
Cvar_Red += "R";
|
||||
std::string Cvar_Green = cvarName;
|
||||
Cvar_Green += "G";
|
||||
std::string Cvar_Blue = cvarName;
|
||||
Cvar_Blue += "B";
|
||||
std::string Cvar_Alpha = cvarName;
|
||||
Cvar_Alpha += "A";
|
||||
std::string Cvar_RBM = cvarName;
|
||||
Cvar_RBM += "RBM";
|
||||
std::string MakeInvisible = "Reset";
|
||||
MakeInvisible += "##";
|
||||
MakeInvisible += cvarName;
|
||||
MakeInvisible += "Reset";
|
||||
if (ImGui::Button(MakeInvisible.c_str())) {
|
||||
colors->x = defaultcolors.x/255;
|
||||
colors->y = defaultcolors.y/255;
|
||||
colors->z = defaultcolors.z/255;
|
||||
if (has_alpha) { colors->w = defaultcolors.w/255;};
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(colors->x*255,0,255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(colors->y*255,0,255));
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(colors->z*255,0,255));
|
||||
if (has_alpha) { CVar_SetS32(Cvar_Alpha.c_str(), ClampFloatToInt(colors->w*255,0,255)); };
|
||||
CVar_SetS32(Cvar_RBM.c_str(), 0); //On click disable rainbow mode.
|
||||
needs_save = true;
|
||||
}
|
||||
Tooltip("Clicking this button will to the game original color (GameCube version)\nPrevious color will be overwrite and will not be recoverable");
|
||||
}
|
||||
|
||||
void EnhancementColor(const char* text, const char* cvarName, ImVec4 ColorRGBA, ImVec4 default_colors, bool allow_rainbow, bool has_alpha, bool TitleSameLine) {
|
||||
std::string Cvar_Red = cvarName;
|
||||
Cvar_Red += "R";
|
||||
std::string Cvar_Green = cvarName;
|
||||
Cvar_Green += "G";
|
||||
std::string Cvar_Blue = cvarName;
|
||||
Cvar_Blue += "B";
|
||||
std::string Cvar_Alpha = cvarName;
|
||||
Cvar_Alpha += "A";
|
||||
std::string Cvar_RBM = cvarName;
|
||||
Cvar_RBM += "RBM";
|
||||
|
||||
LoadPickersColors(ColorRGBA, cvarName, default_colors, has_alpha);
|
||||
ImGuiColorEditFlags flags = ImGuiColorEditFlags_None;
|
||||
|
||||
if (!TitleSameLine){
|
||||
ImGui::Text("%s", text.c_str());
|
||||
ImGui::Text("%s", text);
|
||||
flags = ImGuiColorEditFlags_NoLabel;
|
||||
}
|
||||
if (ImGui::ColorEdit3(text.c_str(), ColorRGB, flags)) {
|
||||
CVar_SetS32((cvarName+"R").c_str(), ClampFloatToInt(ColorRGB[0]*255,0,255));
|
||||
CVar_SetS32((cvarName+"G").c_str(), ClampFloatToInt(ColorRGB[1]*255,0,255));
|
||||
CVar_SetS32((cvarName+"B").c_str(), ClampFloatToInt(ColorRGB[2]*255,0,255));
|
||||
needs_save = true;
|
||||
if (!has_alpha) {
|
||||
if (ImGui::ColorEdit3(text, (float *)&ColorRGBA, flags)) {
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(ColorRGBA.x*255,0,255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(ColorRGBA.y*255,0,255));
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(ColorRGBA.z*255,0,255));
|
||||
needs_save = true;
|
||||
}
|
||||
} else {
|
||||
if (ImGui::ColorEdit4(text, (float *)&ColorRGBA, flags)) {
|
||||
CVar_SetS32(Cvar_Red.c_str(), ClampFloatToInt(ColorRGBA.x*255,0,255));
|
||||
CVar_SetS32(Cvar_Green.c_str(), ClampFloatToInt(ColorRGBA.y*255,0,255));
|
||||
CVar_SetS32(Cvar_Blue.c_str(), ClampFloatToInt(ColorRGBA.z*255,0,255));
|
||||
CVar_SetS32(Cvar_Alpha.c_str(), ClampFloatToInt(ColorRGBA.w*255,0,255));
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ResetColor(cvarName, &ColorRGBA, default_colors, has_alpha);
|
||||
ImGui::SameLine();
|
||||
RandomizeColor(cvarName, &ColorRGBA);
|
||||
if (allow_rainbow) {
|
||||
//Not all draw support rainbow, like Navi.
|
||||
ImGui::SameLine();
|
||||
RainbowColor(cvarName, &ColorRGBA);
|
||||
}
|
||||
}
|
||||
|
||||
void Tooltip(std::string text) {
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("%s", text.c_str());
|
||||
}
|
||||
|
||||
void DrawMainMenuAndCalculateGameSize() {
|
||||
void DrawMainMenuAndCalculateGameSize(void) {
|
||||
console->Update();
|
||||
ImGuiBackendNewFrame();
|
||||
ImGuiWMNewFrame();
|
||||
ImGui::NewFrame();
|
||||
LoadInterfaceEditor();
|
||||
|
||||
const std::shared_ptr<Window> wnd = GlobalCtx2::GetInstance()->GetWindow();
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoBackground |
|
||||
@ -633,7 +734,7 @@ namespace SohImGui {
|
||||
auto menuLabel = "Controller " + std::to_string(i + 1);
|
||||
if (ImGui::BeginMenu(menuLabel.c_str()))
|
||||
{
|
||||
EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i), 0.0f, 1.0f, "", 1.0f, true);
|
||||
EnhancementSliderFloat("Gyro Sensitivity: %d %%", "##GYROSCOPE", StringHelper::Sprintf("gCont%i_GyroSensitivity", i).c_str(), 0.0f, 1.0f, "", 1.0f, true);
|
||||
|
||||
if (ImGui::Button("Recalibrate Gyro"))
|
||||
{
|
||||
@ -644,7 +745,7 @@ namespace SohImGui {
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i), 0.0f, 1.0f, "", 1.0f, true);
|
||||
EnhancementSliderFloat("Rumble Strength: %d %%", "##RUMBLE", StringHelper::Sprintf("gCont%i_RumbleStrength", i).c_str(), 0.0f, 1.0f, "", 1.0f, true);
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@ -676,6 +777,34 @@ namespace SohImGui {
|
||||
Tooltip("Activates anti-aliasing when above 1, up to 8x for 8 samples for every pixel");
|
||||
gfx_msaa_level = CVar_GetS32("gMSAAValue", 1);
|
||||
|
||||
if (impl.backend == Backend::DX11)
|
||||
{
|
||||
const char* cvar = "gExtraLatencyThreshold";
|
||||
int val = CVar_GetS32(cvar, 80);
|
||||
val = MAX(MIN(val, 250), 0);
|
||||
int fps = val;
|
||||
|
||||
if (fps == 0)
|
||||
{
|
||||
ImGui::Text("Jitter fix: Off");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Jitter fix: >= %d FPS", fps);
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("##ExtraLatencyThreshold", &val, 0, 250, "", ImGuiSliderFlags_AlwaysClamp))
|
||||
{
|
||||
CVar_SetS32(cvar, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
Tooltip("When Interpolation FPS setting is at least this threshold,\n"
|
||||
"add one frame of input lag (e.g. 16.6 ms for 60 FPS) in order to avoid jitter.\n"
|
||||
"This setting allows the CPU to work on one frame while GPU works on the previous frame.\n"
|
||||
"This setting should be used when your computer is too slow to do CPU + GPU work in time.");
|
||||
}
|
||||
|
||||
EXPERIMENTAL();
|
||||
ImGui::Text("Texture Filter (Needs reload)");
|
||||
GfxRenderingAPI* gapi = gfx_get_current_rendering_api();
|
||||
@ -723,17 +852,57 @@ namespace SohImGui {
|
||||
Tooltip("Allows equiping the tunic and boots to c-buttons");
|
||||
EnhancementCheckbox("MM Bunny Hood", "gMMBunnyHood");
|
||||
Tooltip("Wearing the Bunny Hood grants a speed increase like in Majora's Mask");
|
||||
EnhancementCheckbox("Better Owl", "gBetterOwl");
|
||||
Tooltip("The default response to Kaepora Gaebora is always that you understood what he said");
|
||||
EnhancementCheckbox("Disable Navi Call Audio", "gDisableNaviCallAudio");
|
||||
Tooltip("Disables the voice audio when Navi calls you");
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Graphics"))
|
||||
{
|
||||
if (ImGui::BeginMenu("Animated Link in Pause Menu")) {
|
||||
ImGui::Text("Rotation");
|
||||
EnhancementRadioButton("Disabled", "gPauseLiveRotation", 0);
|
||||
EnhancementRadioButton("Rotate Link with D-pad", "gPauseLiveRotation", 1);
|
||||
Tooltip("Allow you to rotate Link on the Equipment menu with the DPAD\nUse DPAD-Up or DPAD-Down to reset Link's rotation");
|
||||
EnhancementRadioButton("Rotate Link with C-buttons", "gPauseLiveRotation", 2);
|
||||
Tooltip("Allow you to rotate Link on the Equipment menu with the C-buttons\nUse C-Up or C-Down to reset Link's rotation");
|
||||
|
||||
if (CVar_GetS32("gPauseLiveRotation", 0) != 0) {
|
||||
EnhancementSliderInt("Rotation Speed: %d", "##MinRotationSpeed", "gPauseLiveLinkRotationSpeed", 1, 20, "");
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Static loop");
|
||||
EnhancementRadioButton("Disabled", "gPauseLiveLink", 0);
|
||||
EnhancementRadioButton("Idle (standing)", "gPauseLiveLink", 1);
|
||||
EnhancementRadioButton("Idle (look around)", "gPauseLiveLink", 2);
|
||||
EnhancementRadioButton("Idle (belt)", "gPauseLiveLink", 3);
|
||||
EnhancementRadioButton("Idle (shield)", "gPauseLiveLink", 4);
|
||||
EnhancementRadioButton("Idle (test sword)", "gPauseLiveLink", 5);
|
||||
EnhancementRadioButton("Idle (yawn)", "gPauseLiveLink", 6);
|
||||
EnhancementRadioButton("Battle Stance", "gPauseLiveLink", 7);
|
||||
EnhancementRadioButton("Walking (no shield)", "gPauseLiveLink", 8);
|
||||
EnhancementRadioButton("Walking (holding shield)", "gPauseLiveLink", 9);
|
||||
EnhancementRadioButton("Running (no shield)", "gPauseLiveLink", 10);
|
||||
EnhancementRadioButton("Running (holding shield)", "gPauseLiveLink", 11);
|
||||
EnhancementRadioButton("Hand on hip", "gPauseLiveLink", 12);
|
||||
EnhancementRadioButton("Spin attack charge", "gPauseLiveLink", 13);
|
||||
EnhancementRadioButton("Look at hand", "gPauseLiveLink", 14);
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Randomize");
|
||||
EnhancementRadioButton("Random", "gPauseLiveLink", 15);
|
||||
Tooltip("Randomize the animation played each time you open the menu");
|
||||
EnhancementRadioButton("Random cycle", "gPauseLiveLink", 16);
|
||||
Tooltip("andomize the animation played on hte menu after a certain time");
|
||||
if (CVar_GetS32("gPauseLiveLink", 0) >= 16) {
|
||||
EnhancementSliderInt("Frame to wait: %d", "##MinFrameCount", "gMinFrameCount", 1, 1000, "");
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
EnhancementCheckbox("N64 Mode", "gN64Mode");
|
||||
Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution");
|
||||
EnhancementCheckbox("Animated Link in Pause Menu", "gPauseLiveLink");
|
||||
EnhancementCheckbox("Enable 3D Dropped items/projectiles", "gNewDrops");
|
||||
Tooltip("Change most 2D items & projectiles to their a 3D version");
|
||||
EnhancementCheckbox("Dynamic Wallet Icon", "gDynamicWalletIcon");
|
||||
@ -760,7 +929,46 @@ namespace SohImGui {
|
||||
|
||||
EXPERIMENTAL();
|
||||
|
||||
EnhancementCheckbox("60FPS Interpolation", "g60FPS");
|
||||
const char* fps_cvar = "gInterpolationFPS";
|
||||
{
|
||||
int val = CVar_GetS32(fps_cvar, 20);
|
||||
val = MAX(MIN(val, 250), 20);
|
||||
int fps = val;
|
||||
|
||||
if (fps == 20)
|
||||
{
|
||||
ImGui::Text("Frame interpolation: Off");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Frame interpolation: %d FPS", fps);
|
||||
}
|
||||
|
||||
if (ImGui::SliderInt("##FPSInterpolation", &val, 20, 250, "", ImGuiSliderFlags_AlwaysClamp))
|
||||
{
|
||||
CVar_SetS32(fps_cvar, val);
|
||||
needs_save = true;
|
||||
}
|
||||
|
||||
Tooltip("Interpolate extra frames to get smoother graphics.\n"
|
||||
"Set to match your monitor's refresh rate, or a divisor of it.\n"
|
||||
"A higher target FPS than your monitor's refresh rate will just waste resources,\n"
|
||||
"and might give a worse result.\n"
|
||||
"For consistent input lag, set this value and your monitor's refresh rate to a multiple of 20.\n"
|
||||
"Ctrl+Click for keyboard input.");
|
||||
}
|
||||
if (impl.backend == Backend::DX11)
|
||||
{
|
||||
if (ImGui::Button("Match Refresh Rate"))
|
||||
{
|
||||
int hz = roundf(gfx_get_detected_hz());
|
||||
if (hz >= 20 && hz <= 250)
|
||||
{
|
||||
CVar_SetS32(fps_cvar, hz);
|
||||
needs_save = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
EnhancementCheckbox("Disable LOD", "gDisableLOD");
|
||||
Tooltip("Turns off the level of detail setting, making models always use their higher poly variants");
|
||||
|
||||
@ -867,36 +1075,36 @@ namespace SohImGui {
|
||||
if (ImGui::BeginTabBar("Cosmetics Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
|
||||
if (ImGui::BeginTabItem("Navi")) {
|
||||
EnhancementCheckbox("Custom colors for Navi", "gUseNaviCol");
|
||||
Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets");
|
||||
EnhancementColor3("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, false);
|
||||
Tooltip("Enable/Disable custom Navi's colors. \nIf disabled you will have original colors for Navi.\nColors are refreshed when Navi goes back in your pockets.");
|
||||
EnhancementColor("Navi Idle Inner", "gNavi_Idle_Inner_", navi_idle_i_col, ImVec4(255,255,255,255), false);
|
||||
Tooltip("Inner color for Navi (idle flying around)");
|
||||
EnhancementColor3("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, false);
|
||||
EnhancementColor("Navi Idle Outer", "gNavi_Idle_Outer_", navi_idle_o_col, ImVec4(115,230,255,255), false);
|
||||
Tooltip("Outer color for Navi (idle flying around)");
|
||||
ImGui::Separator();
|
||||
EnhancementColor3("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, false);
|
||||
EnhancementColor("Navi NPC Inner", "gNavi_NPC_Inner_", navi_npc_i_col, ImVec4(100,100,255,255), false);
|
||||
Tooltip("Inner color for Navi (when Navi fly around NPCs)");
|
||||
EnhancementColor3("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, false);
|
||||
EnhancementColor("Navi NPC Outer", "gNavi_NPC_Outer_", navi_npc_o_col, ImVec4(90,90,255,255), false);
|
||||
Tooltip("Outer color for Navi (when Navi fly around NPCs)");
|
||||
ImGui::Separator();
|
||||
EnhancementColor3("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, false);
|
||||
EnhancementColor("Navi Enemy Inner", "gNavi_Enemy_Inner_", navi_enemy_i_col, ImVec4(255,255,0,255), false);
|
||||
Tooltip("Inner color for Navi (when Navi fly around Enemies or Bosses)");
|
||||
EnhancementColor3("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, false);
|
||||
EnhancementColor("Navi Enemy Outer", "gNavi_Enemy_Outer_", navi_enemy_o_col, ImVec4(220,220,0,255), false);
|
||||
Tooltip("Outer color for Navi (when Navi fly around Enemies or Bosses)");
|
||||
ImGui::Separator();
|
||||
EnhancementColor3("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, false);
|
||||
EnhancementColor("Navi Prop Inner", "gNavi_Prop_Inner_", navi_prop_i_col, ImVec4(0,255,0,255), false);
|
||||
Tooltip("Inner color for Navi (when Navi fly around props (signs etc))");
|
||||
EnhancementColor3("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, false);
|
||||
EnhancementColor("Navi Prop Outer", "gNavi_Prop_Outer_", navi_prop_o_col, ImVec4(0,220,0,255), false);
|
||||
Tooltip("Outer color for Navi (when Navi fly around props (signs etc))");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Tunics")) {
|
||||
EnhancementCheckbox("Custom colors on tunics", "gUseTunicsCol");
|
||||
Tooltip("Enable/Disable custom Link's tunics colors. \nIf disabled you will have original colors for Link's tunics");
|
||||
EnhancementColor3("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col, false);
|
||||
Tooltip("Enable/Disable custom Link's tunics colors. \nIf disabled you will have original colors for Link's tunics.");
|
||||
EnhancementColor("Kokiri Tunic", "gTunic_Kokiri_", kokiri_col, ImVec4(30,105,27,255));
|
||||
ImGui::Separator();
|
||||
EnhancementColor3("Goron Tunic", "gTunic_Goron_", goron_col, false);
|
||||
EnhancementColor("Goron Tunic", "gTunic_Goron_", goron_col, ImVec4(100,20,0,255));
|
||||
ImGui::Separator();
|
||||
EnhancementColor3("Zora Tunic", "gTunic_Zora_", zora_col, false);
|
||||
EnhancementColor("Zora Tunic", "gTunic_Zora_", zora_col, ImVec4(0,60,100,255));
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
@ -912,39 +1120,39 @@ namespace SohImGui {
|
||||
ImGui::Begin("Interface Editor", nullptr, ImGuiWindowFlags_NoFocusOnAppearing);
|
||||
if (ImGui::BeginTabBar("Interface Editor", ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)) {
|
||||
if (ImGui::BeginTabItem("Hearts")) {
|
||||
EnhancementColor3("Hearts inner", "gCCHeartsPrim", hearts_colors, false);
|
||||
EnhancementColor("Hearts inner", "gCCHeartsPrim", hearts_colors, ImVec4(255,70,50,255));
|
||||
Tooltip("Hearts inner color (red in original)\nAffect both Normal Hearts and the ones in Double Defense");
|
||||
EnhancementColor3("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors, false);
|
||||
Tooltip("Hearts outline color (white in original)\nAffect Double Defense outline only");
|
||||
EnhancementColor("Hearts double def", "gDDCCHeartsPrim", hearts_dd_colors, ImVec4(255,255,255,255));
|
||||
Tooltip("Hearts outline color (white in original)\nAffect Double Defense outline only.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Buttons")) {
|
||||
EnhancementColor3("A Buttons", "gCCABtnPrim", a_btn_colors, false);
|
||||
Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors");
|
||||
EnhancementColor3("B Buttons", "gCCBBtnPrim", b_btn_colors, false);
|
||||
EnhancementColor("A Buttons", "gCCABtnPrim", a_btn_colors, ImVec4(90,90,255,255));
|
||||
Tooltip("A Buttons colors (Green in original Gamecube)\nAffect A buttons colors on interface, in shops, messages boxes, ocarina notes and inventory cursors.");
|
||||
EnhancementColor("B Buttons", "gCCBBtnPrim", b_btn_colors, ImVec4(0,150,0,255));
|
||||
Tooltip("B Button colors (Red in original Gamecube)\nAffect B button colors on interface");
|
||||
EnhancementColor3("C Buttons", "gCCCBtnPrim", c_btn_colors, false);
|
||||
EnhancementColor("C Buttons", "gCCCBtnPrim", c_btn_colors, ImVec4(255,160,0,255));
|
||||
Tooltip("C Buttons colors (Yellowish / Oranges in originals)\nAffect C buttons colors on interface, in inventory and ocarina notes");
|
||||
EnhancementColor3("Start Buttons", "gCCStartBtnPrim", start_btn_colors, false);
|
||||
EnhancementColor("Start Buttons", "gCCStartBtnPrim", start_btn_colors, ImVec4(120,120,120,255));
|
||||
Tooltip("Start Button colors (gray in Gamecube)\nAffect Start button colors in inventory");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Magic Bar")) {
|
||||
EnhancementColor3("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors, false);
|
||||
Tooltip("Affect the border of the magic bar when being used\nWhite flash in original game");
|
||||
EnhancementColor3("Magic bar main color", "gCCMagicPrim", magic_remaining_colors, false);
|
||||
Tooltip("Affect the magic bar color\nGreen in original game");
|
||||
EnhancementColor3("Magic bar being used", "gCCMagicUsePrim", magic_use_colors, false);
|
||||
Tooltip("Affect the magic bar when being used\nYellow in original game");
|
||||
EnhancementColor("Magic bar borders", "gCCMagicBorderPrim", magic_border_colors, ImVec4(255,255,255,255));
|
||||
Tooltip("Affect the border of the magic bar when being used\nWhite flash in original game.");
|
||||
EnhancementColor("Magic bar main color", "gCCMagicPrim", magic_remaining_colors, ImVec4(0,200,0,255));
|
||||
Tooltip("Affect the magic bar color\nGreen in original game.");
|
||||
EnhancementColor("Magic bar being used", "gCCMagicUsePrim", magic_use_colors, ImVec4(250,250,0,255));
|
||||
Tooltip("Affect the magic bar when being used\nYellow in original game.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Misc")) {
|
||||
EnhancementColor3("Minimap color", "gCCMinimapPrim", minimap_colors, false);
|
||||
Tooltip("Affect the Dungeon and Overworld minimaps");
|
||||
EnhancementColor3("Rupee icon color", "gCCRupeePrim", rupee_colors, false);
|
||||
Tooltip("Affect the Rupee icon on interface\nGreen by default");
|
||||
EnhancementColor3("Small Keys icon color", "gCCKeysPrim", smolekey_colors, false);
|
||||
Tooltip("Affect the Small keys icon on interface\nGray by default");
|
||||
EnhancementColor("Minimap color", "gCCMinimapPrim", minimap_colors, ImVec4(0,255,255,255));
|
||||
Tooltip("Affect the Dungeon and Overworld minimaps.");
|
||||
EnhancementColor("Rupee icon color", "gCCRupeePrim", rupee_colors, ImVec4(120,120,120,255));
|
||||
Tooltip("Affect the Rupee icon on interface\nGreen by default.");
|
||||
EnhancementColor("Small Keys icon color", "gCCKeysPrim", smolekey_colors, ImVec4(200,230,255,255));
|
||||
Tooltip("Affect the Small keys icon on interface\nGray by default.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
@ -960,7 +1168,7 @@ namespace SohImGui {
|
||||
varName.erase(std::ranges::remove_if(varName, isspace).begin(), varName.end());
|
||||
std::string toggleName = "g" + varName + "Enabled";
|
||||
|
||||
EnhancementCheckbox(name, toggleName);
|
||||
EnhancementCheckbox(name.c_str(), toggleName.c_str());
|
||||
customWindows[name].enabled = CVar_GetS32(toggleName.c_str(), 0);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
@ -1011,19 +1219,19 @@ namespace SohImGui {
|
||||
main_pos.y -= top_left_pos.y;
|
||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||
ImVec2 pos = ImVec2(0, 0);
|
||||
gfx_current_dimensions.width = size.x * gfx_current_dimensions.internal_mul;
|
||||
gfx_current_dimensions.height = size.y * gfx_current_dimensions.internal_mul;
|
||||
gfx_current_game_window_viewport.x = main_pos.x;
|
||||
gfx_current_game_window_viewport.y = main_pos.y;
|
||||
gfx_current_game_window_viewport.width = size.x;
|
||||
gfx_current_game_window_viewport.height = size.y;
|
||||
gfx_current_dimensions.width = (uint32_t)(size.x * gfx_current_dimensions.internal_mul);
|
||||
gfx_current_dimensions.height = (uint32_t)(size.y * gfx_current_dimensions.internal_mul);
|
||||
gfx_current_game_window_viewport.x = (int16_t)main_pos.x;
|
||||
gfx_current_game_window_viewport.y = (int16_t)main_pos.y;
|
||||
gfx_current_game_window_viewport.width = (int16_t)size.x;
|
||||
gfx_current_game_window_viewport.height = (int16_t)size.y;
|
||||
|
||||
if (CVar_GetS32("gN64Mode", 0))
|
||||
{
|
||||
gfx_current_dimensions.width = 320;
|
||||
gfx_current_dimensions.height = 240;
|
||||
const int sw = size.y * 320 / 240;
|
||||
gfx_current_game_window_viewport.x += (size.x - sw) / 2;
|
||||
gfx_current_game_window_viewport.x += ((int)size.x - sw) / 2;
|
||||
gfx_current_game_window_viewport.width = sw;
|
||||
pos = ImVec2(size.x / 2 - sw / 2, 0);
|
||||
size = ImVec2(sw, size.y);
|
||||
@ -1032,12 +1240,12 @@ namespace SohImGui {
|
||||
overlay->Draw();
|
||||
}
|
||||
|
||||
void DrawFramebufferAndGameInput() {
|
||||
ImVec2 main_pos = ImGui::GetWindowPos();
|
||||
void DrawFramebufferAndGameInput(void) {
|
||||
const ImVec2 main_pos = ImGui::GetWindowPos();
|
||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||
ImVec2 pos = ImVec2(0, 0);
|
||||
if (CVar_GetS32("gN64Mode", 0)) {
|
||||
const int sw = size.y * 320 / 240;
|
||||
const float sw = size.y * 320.0f / 240.0f;
|
||||
pos = ImVec2(size.x / 2 - sw / 2, 0);
|
||||
size = ImVec2(sw, size.y);
|
||||
}
|
||||
@ -1109,6 +1317,8 @@ namespace SohImGui {
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
}
|
||||
//Placed here so it does the rainbow effects even if menu is not on.
|
||||
LoadRainbowColor();
|
||||
}
|
||||
|
||||
void CancelFrame() {
|
||||
|
@ -63,12 +63,14 @@ namespace SohImGui {
|
||||
extern bool needs_save;
|
||||
void Init(WindowImpl window_impl);
|
||||
void Update(EventImpl event);
|
||||
void Tooltip(const char* text);
|
||||
|
||||
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 EnhancementColor3(std::string text, std::string cvarName, float ColorRGB[3], bool TitleSameLine);
|
||||
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);
|
||||
|
||||
@ -79,7 +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 LoadInterfaceEditor();
|
||||
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);
|
||||
}
|
||||
|
@ -272,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) {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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) {
|
||||
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;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
while (audio.processing) {
|
||||
|
@ -451,7 +451,7 @@ void FrameInterpolation_StartRecord(void) {
|
||||
current_recording = {};
|
||||
current_path.clear();
|
||||
current_path.push_back(¤t_recording.root_path);
|
||||
if (CVar_GetS32("g60FPS", 0) != 0) {
|
||||
if (CVar_GetS32("gInterpolationFPS", 20) != 20) {
|
||||
is_recording = true;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -2290,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) {
|
||||
|
@ -128,6 +128,13 @@ void HealthMeter_Init(GlobalContext* globalCtx) {
|
||||
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;
|
||||
@ -194,12 +201,12 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
|
||||
HeartDDOutline[1] = CVar_GetS32("gDDCCHeartsPrimG", sHeartsDDPrim[0][1]);
|
||||
HeartDDOutline[2] = CVar_GetS32("gDDCCHeartsPrimB", sHeartsDDPrim[0][2]);
|
||||
} else {
|
||||
HeartInner[0] = sHeartsPrimColors[0][0];
|
||||
HeartInner[1] = sHeartsPrimColors[0][1];
|
||||
HeartInner[2] = sHeartsPrimColors[0][2];
|
||||
HeartDDOutline[0] = sHeartsDDPrim[0][0];
|
||||
HeartDDOutline[1] = sHeartsDDPrim[0][1];
|
||||
HeartDDOutline[2] = sHeartsDDPrim[0][2];
|
||||
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) {
|
||||
@ -299,33 +306,33 @@ void HealthMeter_Update(GlobalContext* globalCtx) {
|
||||
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF;
|
||||
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF;
|
||||
} else {
|
||||
sHeartsDDPrim[2][0] = HeartInner[0];
|
||||
sHeartsDDPrim[2][1] = HeartInner[1];
|
||||
sHeartsDDPrim[2][2] = HeartInner[2];
|
||||
sHeartsDDPrim[2][0] = HEARTS_PRIM_R;
|
||||
sHeartsDDPrim[2][1] = HEARTS_PRIM_G;
|
||||
sHeartsDDPrim[2][2] = HEARTS_PRIM_B;
|
||||
|
||||
sHeartsDDPrim[1][0] = sHeartsDDPrimColors[ddType][0];
|
||||
sHeartsDDPrim[1][1] = sHeartsDDPrimColors[ddType][1];
|
||||
sHeartsDDPrim[1][2] = sHeartsDDPrimColors[ddType][2];
|
||||
sHeartsDDPrim[1][0] = HEARTS_DD_PRIM_R;
|
||||
sHeartsDDPrim[1][1] = HEARTS_DD_PRIM_G;
|
||||
sHeartsDDPrim[1][2] = HEARTS_DD_PRIM_B;
|
||||
|
||||
sHeartsDDEnv[1][0] = sHeartsDDEnvColors[ddType][0];
|
||||
sHeartsDDEnv[1][1] = sHeartsDDEnvColors[ddType][1];
|
||||
sHeartsDDEnv[1][2] = sHeartsDDEnvColors[ddType][2];
|
||||
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 + HeartDDOutline[0]) & 0xFF;
|
||||
sBeatingHeartsDDPrim[1] = (u8)(gFactor + HeartDDOutline[1]) & 0xFF;
|
||||
sBeatingHeartsDDPrim[2] = (u8)(bFactor + HeartDDOutline[2]) & 0xFF;
|
||||
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 + HeartDDInner[0]) & 0xFF;
|
||||
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HeartDDInner[1]) & 0xFF;
|
||||
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HeartDDInner[2]) & 0xFF;
|
||||
sBeatingHeartsDDEnv[0] = (u8)(rFactor + HEARTS_PRIM_R) & 0xFF;
|
||||
sBeatingHeartsDDEnv[1] = (u8)(gFactor + HEARTS_PRIM_G) & 0xFF;
|
||||
sBeatingHeartsDDEnv[2] = (u8)(bFactor + HEARTS_PRIM_B) & 0xFF;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -2885,6 +2885,25 @@ void Interface_DrawItemButtons(GlobalContext* globalCtx) {
|
||||
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);
|
||||
|
@ -744,26 +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 NewColor[3];
|
||||
color = &sTunicColors[tunic];
|
||||
if (CVar_GetS32("gUseTunicsCol",0) == 1) {
|
||||
if (tunic == PLAYER_TUNIC_KOKIRI || tunic == PLAYER_TUNIC_GORON || tunic == PLAYER_TUNIC_ZORA) {
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r);
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g);
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b);
|
||||
NewColor[PLAYER_TUNIC_GORON].r = CVar_GetS32("gTunic_Goron_R", sTunicColors[PLAYER_TUNIC_GORON].r);
|
||||
NewColor[PLAYER_TUNIC_GORON].g = CVar_GetS32("gTunic_Goron_G", sTunicColors[PLAYER_TUNIC_GORON].g);
|
||||
NewColor[PLAYER_TUNIC_GORON].b = CVar_GetS32("gTunic_Goron_B", sTunicColors[PLAYER_TUNIC_GORON].b);
|
||||
NewColor[PLAYER_TUNIC_ZORA].r = CVar_GetS32("gTunic_Zora_R", sTunicColors[PLAYER_TUNIC_ZORA].r);
|
||||
NewColor[PLAYER_TUNIC_ZORA].g = CVar_GetS32("gTunic_Zora_G", sTunicColors[PLAYER_TUNIC_ZORA].g);
|
||||
NewColor[PLAYER_TUNIC_ZORA].b = CVar_GetS32("gTunic_Zora_B", sTunicColors[PLAYER_TUNIC_ZORA].b);
|
||||
|
||||
Color_RGB8 sTemp;
|
||||
Color_RGB8 sOriginalTunicColors[] = {
|
||||
{ 30, 105, 27 },
|
||||
{ 100, 20, 0 },
|
||||
{ 0, 60, 100 },
|
||||
};
|
||||
color = &sTemp;
|
||||
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 {
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].r = CVar_GetS32("gTunic_Kokiri_R", sTunicColors[PLAYER_TUNIC_KOKIRI].r);
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].g = CVar_GetS32("gTunic_Kokiri_G", sTunicColors[PLAYER_TUNIC_KOKIRI].g);
|
||||
NewColor[PLAYER_TUNIC_KOKIRI].b = CVar_GetS32("gTunic_Kokiri_B", sTunicColors[PLAYER_TUNIC_KOKIRI].b);
|
||||
color->r = sOriginalTunicColors[tunic].r;
|
||||
color->g = sOriginalTunicColors[tunic].g;
|
||||
color->b = sOriginalTunicColors[tunic].b;
|
||||
}
|
||||
color = NewColor;
|
||||
}
|
||||
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, color->r, color->g, color->b, 0);
|
||||
|
||||
sDListsLodOffset = lod * 2;
|
||||
@ -1649,26 +1661,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?
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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++);
|
||||
|
@ -976,14 +976,23 @@ 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);
|
||||
@ -1060,6 +1069,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
|
||||
{ 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;
|
||||
@ -1067,6 +1082,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
|
||||
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;
|
||||
@ -1074,6 +1095,12 @@ void KaleidoScope_DrawPages(GlobalContext* globalCtx, GraphicsContext* gfxCtx) {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user