Merge branch 'testing-out-item-replacement' of github.com:briaguya-ai/Shipwright into testing-out-item-replacement

This commit is contained in:
briaguya 2022-05-29 13:45:17 -04:00
commit 8d392c5d07
19 changed files with 494 additions and 203 deletions

View file

@ -54,8 +54,8 @@ static struct {
std::string game_name; std::string game_name;
HMODULE dxgi_module; HMODULE dxgi_module;
HRESULT (__stdcall *CreateDXGIFactory1)(REFIID riid, void **factory); HRESULT(__stdcall* CreateDXGIFactory1)(REFIID riid, void** factory);
HRESULT (__stdcall *CreateDXGIFactory2)(UINT flags, REFIID iid, void **factory); HRESULT(__stdcall* CreateDXGIFactory2)(UINT flags, REFIID iid, void** factory);
bool process_dpi_awareness_done; bool process_dpi_awareness_done;
@ -87,8 +87,8 @@ static struct {
static void load_dxgi_library(void) { static void load_dxgi_library(void) {
dxgi.dxgi_module = LoadLibraryW(L"dxgi.dll"); dxgi.dxgi_module = LoadLibraryW(L"dxgi.dll");
*(FARPROC *)&dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory1"); *(FARPROC*)&dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory1");
*(FARPROC *)&dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory2"); *(FARPROC*)&dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory2");
} }
template <typename Fun> template <typename Fun>
@ -106,25 +106,26 @@ static void run_as_dpi_aware(Fun f) {
// From windef.h, missing in MinGW. // From windef.h, missing in MinGW.
DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); DECLARE_HANDLE(DPI_AWARENESS_CONTEXT);
#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) #define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1)
#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) #define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3)
#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4) #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4)
#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5) #define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5)
DPI_AWARENESS_CONTEXT (WINAPI *SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext); DPI_AWARENESS_CONTEXT(WINAPI * SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext);
*(FARPROC *)&SetThreadDpiAwarenessContext = GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetThreadDpiAwarenessContext"); *(FARPROC*)&SetThreadDpiAwarenessContext = GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetThreadDpiAwarenessContext");
DPI_AWARENESS_CONTEXT old_awareness_context = nullptr; DPI_AWARENESS_CONTEXT old_awareness_context = nullptr;
if (SetThreadDpiAwarenessContext != nullptr) { if (SetThreadDpiAwarenessContext != nullptr) {
old_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); old_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
} else { }
else {
// Solution for Windows 8.1 and newer, but before Windows 10 1607. // Solution for Windows 8.1 and newer, but before Windows 10 1607.
// SetProcessDpiAwareness must be called before any drawing related API is called. // SetProcessDpiAwareness must be called before any drawing related API is called.
if (!dxgi.process_dpi_awareness_done) { if (!dxgi.process_dpi_awareness_done) {
HMODULE shcore_module = LoadLibraryW(L"SHCore.dll"); HMODULE shcore_module = LoadLibraryW(L"SHCore.dll");
if (shcore_module != nullptr) { if (shcore_module != nullptr) {
HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); HRESULT(WINAPI * SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value);
*(FARPROC *)&SetProcessDpiAwareness = GetProcAddress(shcore_module, "SetProcessDpiAwareness"); *(FARPROC*)&SetProcessDpiAwareness = GetProcAddress(shcore_module, "SetProcessDpiAwareness");
if (SetProcessDpiAwareness != nullptr) { if (SetProcessDpiAwareness != nullptr) {
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
// Ignore result, will fail if already called or manifest already specifies dpi awareness. // Ignore result, will fail if already called or manifest already specifies dpi awareness.
@ -162,13 +163,15 @@ static void toggle_borderless_window_full_screen(bool enable, bool call_callback
if (dxgi.last_maximized_state) { if (dxgi.last_maximized_state) {
SetWindowPos(dxgi.h_wnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); SetWindowPos(dxgi.h_wnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
ShowWindow(dxgi.h_wnd, SW_MAXIMIZE); ShowWindow(dxgi.h_wnd, SW_MAXIMIZE);
} else { }
else {
SetWindowPos(dxgi.h_wnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED); SetWindowPos(dxgi.h_wnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED);
ShowWindow(dxgi.h_wnd, SW_RESTORE); ShowWindow(dxgi.h_wnd, SW_RESTORE);
} }
dxgi.is_full_screen = false; dxgi.is_full_screen = false;
} else { }
else {
// Save if window is maximized or not // Save if window is maximized or not
WINDOWPLACEMENT window_placement; WINDOWPLACEMENT window_placement;
window_placement.length = sizeof(WINDOWPLACEMENT); window_placement.length = sizeof(WINDOWPLACEMENT);
@ -212,59 +215,68 @@ static void onkeyup(WPARAM w_param, LPARAM l_param) {
} }
} }
extern "C" void LoadItemLocations(const char* spoilerFileName);
static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) { static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) {
SohImGui::EventImpl event_impl; SohImGui::EventImpl event_impl;
event_impl.win32 = { h_wnd, static_cast<int>(message), static_cast<int>(w_param), static_cast<int>(l_param) }; event_impl.win32 = { h_wnd, static_cast<int>(message), static_cast<int>(w_param), static_cast<int>(l_param) };
SohImGui::Update(event_impl); SohImGui::Update(event_impl);
switch (message) { switch (message) {
case WM_SIZE: case WM_SIZE:
dxgi.current_width = (uint32_t)(l_param & 0xffff); dxgi.current_width = (uint32_t)(l_param & 0xffff);
dxgi.current_height = (uint32_t)(l_param >> 16); dxgi.current_height = (uint32_t)(l_param >> 16);
break; break;
case WM_DESTROY: case WM_DESTROY:
exit(0); exit(0);
case WM_PAINT: case WM_PAINT:
if (dxgi.in_paint) { if (dxgi.in_paint) {
dxgi.recursive_paint_detected = true; dxgi.recursive_paint_detected = true;
return DefWindowProcW(h_wnd, message, w_param, l_param); return DefWindowProcW(h_wnd, message, w_param, l_param);
} else { }
if (dxgi.run_one_game_iter != nullptr) { else {
dxgi.in_paint = true; if (dxgi.run_one_game_iter != nullptr) {
dxgi.run_one_game_iter(); dxgi.in_paint = true;
dxgi.in_paint = false; dxgi.run_one_game_iter();
if (dxgi.recursive_paint_detected) { dxgi.in_paint = false;
dxgi.recursive_paint_detected = false; if (dxgi.recursive_paint_detected) {
InvalidateRect(h_wnd, nullptr, false); dxgi.recursive_paint_detected = false;
UpdateWindow(h_wnd); InvalidateRect(h_wnd, nullptr, false);
} UpdateWindow(h_wnd);
} }
} }
}
break;
case WM_ACTIVATEAPP:
if (dxgi.on_all_keys_up != nullptr) {
dxgi.on_all_keys_up();
}
break;
case WM_KEYDOWN:
onkeydown(w_param, l_param);
break;
case WM_KEYUP:
onkeyup(w_param, l_param);
break;
case WM_DROPFILES:
char fileName[256];
DragQueryFileA((HDROP)w_param, 0, fileName, 256);
LoadItemLocations(fileName);
break;
case WM_SYSKEYDOWN:
if ((w_param == VK_RETURN) && ((l_param & 1 << 30) == 0)) {
toggle_borderless_window_full_screen(!dxgi.is_full_screen, true);
break; break;
case WM_ACTIVATEAPP: }
if (dxgi.on_all_keys_up != nullptr) { else {
dxgi.on_all_keys_up();
}
break;
case WM_KEYDOWN:
onkeydown(w_param, l_param);
break;
case WM_KEYUP:
onkeyup(w_param, l_param);
break;
case WM_SYSKEYDOWN:
if ((w_param == VK_RETURN) && ((l_param & 1 << 30) == 0)) {
toggle_borderless_window_full_screen(!dxgi.is_full_screen, true);
break;
} else {
return DefWindowProcW(h_wnd, message, w_param, l_param);
}
default:
return DefWindowProcW(h_wnd, message, w_param, l_param); return DefWindowProcW(h_wnd, message, w_param, l_param);
}
default:
return DefWindowProcW(h_wnd, message, w_param, l_param);
} }
return 0; return 0;
} }
void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen) { void gfx_dxgi_init(const char* game_name, bool start_in_fullscreen) {
LARGE_INTEGER qpc_init, qpc_freq; LARGE_INTEGER qpc_init, qpc_freq;
QueryPerformanceCounter(&qpc_init); QueryPerformanceCounter(&qpc_init);
QueryPerformanceFrequency(&qpc_freq); QueryPerformanceFrequency(&qpc_freq);
@ -287,29 +299,29 @@ void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen) {
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = gfx_dxgi_wnd_proc; wcex.lpfnWndProc = gfx_dxgi_wnd_proc;
wcex.cbClsExtra = 0; wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0; wcex.cbWndExtra = 0;
wcex.hInstance = nullptr; wcex.hInstance = nullptr;
wcex.hIcon = nullptr; wcex.hIcon = nullptr;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wcex.lpszMenuName = nullptr; wcex.lpszMenuName = nullptr;
wcex.lpszClassName = WINCLASS_NAME; wcex.lpszClassName = WINCLASS_NAME;
wcex.hIconSm = nullptr; wcex.hIconSm = nullptr;
ATOM winclass = RegisterClassExW(&wcex); ATOM winclass = RegisterClassExW(&wcex);
run_as_dpi_aware([&] () { run_as_dpi_aware([&]() {
// We need to be dpi aware when calculating the size // We need to be dpi aware when calculating the size
RECT wr = {0, 0, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT}; RECT wr = { 0, 0, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT };
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
dxgi.h_wnd = CreateWindowW(WINCLASS_NAME, w_title, WS_OVERLAPPEDWINDOW, dxgi.h_wnd = CreateWindowW(WINCLASS_NAME, w_title, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, wr.right - wr.left, wr.bottom - wr.top, nullptr, nullptr, nullptr, nullptr); CW_USEDEFAULT, 0, wr.right - wr.left, wr.bottom - wr.top, nullptr, nullptr, nullptr, nullptr);
}); });
load_dxgi_library(); load_dxgi_library();
@ -319,6 +331,8 @@ void gfx_dxgi_init(const char *game_name, bool start_in_fullscreen) {
if (start_in_fullscreen) { if (start_in_fullscreen) {
toggle_borderless_window_full_screen(true, false); toggle_borderless_window_full_screen(true, false);
} }
DragAcceptFiles(dxgi.h_wnd, TRUE);
} }
static void gfx_dxgi_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) { static void gfx_dxgi_set_fullscreen_changed_callback(void (*on_fullscreen_changed)(bool is_now_fullscreen)) {
@ -354,7 +368,7 @@ static void gfx_dxgi_main_loop(void (*run_one_game_iter)(void)) {
} }
} }
static void gfx_dxgi_get_dimensions(uint32_t *width, uint32_t *height) { static void gfx_dxgi_get_dimensions(uint32_t* width, uint32_t* height) {
*width = dxgi.current_width; *width = dxgi.current_width;
*height = dxgi.current_height; *height = dxgi.current_height;
} }
@ -409,8 +423,8 @@ static bool gfx_dxgi_start_frame(void) {
dxgi.frame_timestamp += FRAME_INTERVAL_US_NUMERATOR; dxgi.frame_timestamp += FRAME_INTERVAL_US_NUMERATOR;
if (dxgi.frame_stats.size() >= 2) { if (dxgi.frame_stats.size() >= 2) {
DXGI_FRAME_STATISTICS *first = &dxgi.frame_stats.begin()->second; DXGI_FRAME_STATISTICS* first = &dxgi.frame_stats.begin()->second;
DXGI_FRAME_STATISTICS *last = &dxgi.frame_stats.rbegin()->second; DXGI_FRAME_STATISTICS* last = &dxgi.frame_stats.rbegin()->second;
uint64_t sync_qpc_diff = last->SyncQPCTime.QuadPart - first->SyncQPCTime.QuadPart; uint64_t sync_qpc_diff = last->SyncQPCTime.QuadPart - first->SyncQPCTime.QuadPart;
UINT sync_vsync_diff = last->SyncRefreshCount - first->SyncRefreshCount; UINT sync_vsync_diff = last->SyncRefreshCount - first->SyncRefreshCount;
UINT present_vsync_diff = last->PresentRefreshCount - first->PresentRefreshCount; UINT present_vsync_diff = last->PresentRefreshCount - first->PresentRefreshCount;
@ -455,7 +469,8 @@ static bool gfx_dxgi_start_frame(void) {
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_US_DENOMINATOR * (last_end_us + vsyncs_to_wait * estimated_vsync_interval_us);
} else { }
else {
// Drop frame // Drop frame
//printf("Dropping frame\n"); //printf("Dropping frame\n");
dxgi.dropped_frame = true; dxgi.dropped_frame = true;
@ -477,7 +492,8 @@ static bool gfx_dxgi_start_frame(void) {
} }
if (diff_left < diff_right) { if (diff_left < diff_right) {
vsyncs_to_wait = floor(vsyncs_to_wait); vsyncs_to_wait = floor(vsyncs_to_wait);
} else { }
else {
vsyncs_to_wait = ceil(vsyncs_to_wait); vsyncs_to_wait = ceil(vsyncs_to_wait);
} }
if (vsyncs_to_wait == 0) { if (vsyncs_to_wait == 0) {
@ -493,7 +509,8 @@ static bool gfx_dxgi_start_frame(void) {
dxgi.use_timer = true; dxgi.use_timer = true;
} }
dxgi.length_in_vsync_frames = vsyncs_to_wait; dxgi.length_in_vsync_frames = vsyncs_to_wait;
} else { }
else {
dxgi.length_in_vsync_frames = 1; dxgi.length_in_vsync_frames = 1;
dxgi.use_timer = true; dxgi.use_timer = true;
} }
@ -558,10 +575,11 @@ static void gfx_dxgi_set_frame_divisor(int divisor) {
dxgi.frame_divisor = divisor; dxgi.frame_divisor = divisor;
} }
void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)) { void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1* adapter, bool test_only)) {
if (dxgi.CreateDXGIFactory2 != nullptr) { if (dxgi.CreateDXGIFactory2 != nullptr) {
ThrowIfFailed(dxgi.CreateDXGIFactory2(debug ? DXGI_CREATE_FACTORY_DEBUG : 0, __uuidof(IDXGIFactory2), &dxgi.factory)); ThrowIfFailed(dxgi.CreateDXGIFactory2(debug ? DXGI_CREATE_FACTORY_DEBUG : 0, __uuidof(IDXGIFactory2), &dxgi.factory));
} else { }
else {
ThrowIfFailed(dxgi.CreateDXGIFactory1(__uuidof(IDXGIFactory2), &dxgi.factory)); ThrowIfFailed(dxgi.CreateDXGIFactory1(__uuidof(IDXGIFactory2), &dxgi.factory));
} }
@ -592,7 +610,7 @@ void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*crea
SetWindowTextW(dxgi.h_wnd, w_title); SetWindowTextW(dxgi.h_wnd, w_title);
} }
ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) { ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown* device) {
bool win8 = IsWindows8OrGreater(); // DXGI_SCALING_NONE is only supported on Win8 and beyond 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 bool dxgi_13 = dxgi.CreateDXGIFactory2 != nullptr; // DXGI 1.3 introduced waitable object
@ -609,12 +627,12 @@ ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
swap_chain_desc.Flags = dxgi_13 ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; swap_chain_desc.Flags = dxgi_13 ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0;
swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Count = 1;
run_as_dpi_aware([&] () { run_as_dpi_aware([&]() {
// When setting size for the buffers, the values that DXGI puts into the desc (that can later be retrieved by GetDesc1) // When setting size for the buffers, the values that DXGI puts into the desc (that can later be retrieved by GetDesc1)
// have been divided by the current scaling factor. By making this call dpi aware, no division will be performed. // have been divided by the current scaling factor. By making this call dpi aware, no division will be performed.
// The same goes for IDXGISwapChain::ResizeBuffers(), however that function is currently only called from the message handler. // The same goes for IDXGISwapChain::ResizeBuffers(), however that function is currently only called from the message handler.
ThrowIfFailed(dxgi.factory->CreateSwapChainForHwnd(device, dxgi.h_wnd, &swap_chain_desc, nullptr, nullptr, &dxgi.swap_chain)); ThrowIfFailed(dxgi.factory->CreateSwapChainForHwnd(device, dxgi.h_wnd, &swap_chain_desc, nullptr, nullptr, &dxgi.swap_chain));
}); });
ThrowIfFailed(dxgi.factory->MakeWindowAssociation(dxgi.h_wnd, DXGI_MWA_NO_ALT_ENTER)); ThrowIfFailed(dxgi.factory->MakeWindowAssociation(dxgi.h_wnd, DXGI_MWA_NO_ALT_ENTER));
ComPtr<IDXGISwapChain2> swap_chain2; ComPtr<IDXGISwapChain2> swap_chain2;
@ -622,7 +640,8 @@ ComPtr<IDXGISwapChain1> gfx_dxgi_create_swap_chain(IUnknown *device) {
ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(1)); ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(1));
dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject(); dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject();
WaitForSingleObject(dxgi.waitable_object, INFINITE); WaitForSingleObject(dxgi.waitable_object, INFINITE);
} else { }
else {
ComPtr<IDXGIDevice1> device1; ComPtr<IDXGIDevice1> device1;
ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&device1))); ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&device1)));
ThrowIfFailed(device1->SetMaximumFrameLatency(1)); ThrowIfFailed(device1->SetMaximumFrameLatency(1));
@ -646,7 +665,7 @@ void ThrowIfFailed(HRESULT res) {
} }
} }
void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message) { void ThrowIfFailed(HRESULT res, HWND h_wnd, const char* message) {
if (FAILED(res)) { if (FAILED(res)) {
char full_message[256]; char full_message[256];
sprintf(full_message, "%s\n\nHRESULT: 0x%08X", message, res); sprintf(full_message, "%s\n\nHRESULT: 0x%08X", message, res);

View file

@ -30,7 +30,7 @@
#define GFX_API_NAME "SDL2 - OpenGL" #define GFX_API_NAME "SDL2 - OpenGL"
static SDL_Window *wnd; static SDL_Window* wnd;
static SDL_GLContext ctx; static SDL_GLContext ctx;
static int inverted_scancode_table[512]; static int inverted_scancode_table[512];
static int vsync_enabled = 0; static int vsync_enabled = 0;
@ -105,7 +105,8 @@ static void set_fullscreen(bool on, bool call_callback) {
window_width = mode.w; window_width = mode.w;
window_height = mode.h; window_height = mode.h;
SDL_ShowCursor(false); SDL_ShowCursor(false);
} else { }
else {
window_width = DESIRED_SCREEN_WIDTH; window_width = DESIRED_SCREEN_WIDTH;
window_height = DESIRED_SCREEN_HEIGHT; window_height = DESIRED_SCREEN_HEIGHT;
} }
@ -129,9 +130,11 @@ static int frameDivisor = 1;
#define FRAME_INTERVAL_US_DENOMINATOR 3 #define FRAME_INTERVAL_US_DENOMINATOR 3
#define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * frameDivisor) #define FRAME_INTERVAL_US_NUMERATOR (FRAME_INTERVAL_US_NUMERATOR_ * frameDivisor)
static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) { static void gfx_sdl_init(const char* game_name, bool start_in_fullscreen) {
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
@ -146,7 +149,7 @@ static void gfx_sdl_init(const char *game_name, bool start_in_fullscreen) {
int len = sprintf(title, "%s (%s)", game_name, GFX_API_NAME); int len = sprintf(title, "%s (%s)", game_name, GFX_API_NAME);
wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, wnd = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); window_width, window_height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (start_in_fullscreen) { if (start_in_fullscreen) {
set_fullscreen(true, false); set_fullscreen(true, false);
@ -200,7 +203,7 @@ static void gfx_sdl_main_loop(void (*run_one_game_iter)(void)) {
} }
} }
static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) { static void gfx_sdl_get_dimensions(uint32_t* width, uint32_t* height) {
*width = window_width; *width = window_width;
*height = window_height; *height = window_height;
} }
@ -208,7 +211,8 @@ static void gfx_sdl_get_dimensions(uint32_t *width, uint32_t *height) {
static int translate_scancode(int scancode) { static int translate_scancode(int scancode) {
if (scancode < 512) { if (scancode < 512) {
return inverted_scancode_table[scancode]; return inverted_scancode_table[scancode];
} else { }
else {
return 0; return 0;
} }
} }
@ -227,8 +231,11 @@ static void gfx_sdl_onkeyup(int scancode) {
} }
} }
extern "C" void LoadItemLocations(const char* spoilerFileName);
static void gfx_sdl_handle_events(void) { static void gfx_sdl_handle_events(void) {
SDL_Event event; SDL_Event event;
char* dropped_filedir;
while (SDL_PollEvent(&event)) { while (SDL_PollEvent(&event)) {
SohImGui::EventImpl event_impl; SohImGui::EventImpl event_impl;
event_impl.sdl = { &event }; event_impl.sdl = { &event };
@ -236,21 +243,26 @@ static void gfx_sdl_handle_events(void) {
switch (event.type) { switch (event.type) {
#ifndef TARGET_WEB #ifndef TARGET_WEB
// Scancodes are broken in Emscripten SDL2: https://bugzilla.libsdl.org/show_bug.cgi?id=3259 // Scancodes are broken in Emscripten SDL2: https://bugzilla.libsdl.org/show_bug.cgi?id=3259
case SDL_KEYDOWN: case SDL_KEYDOWN:
gfx_sdl_onkeydown(event.key.keysym.scancode); gfx_sdl_onkeydown(event.key.keysym.scancode);
break; break;
case SDL_KEYUP: case SDL_KEYUP:
gfx_sdl_onkeyup(event.key.keysym.scancode); gfx_sdl_onkeyup(event.key.keysym.scancode);
break; break;
#endif #endif
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
window_width = event.window.data1; window_width = event.window.data1;
window_height = event.window.data2; window_height = event.window.data2;
} }
break; break;
case SDL_QUIT: case SDL_DROPFILE:
exit(0); {
LoadItemLocations(event.drop.file);
break;
}
case SDL_QUIT:
exit(0);
} }
} }
} }

View file

@ -240,6 +240,11 @@ namespace SohImGui {
stbi_image_free(img_data); stbi_image_free(img_data);
} }
// thought this might be a way to work around the LoadItemLocations not defined issue
// void LoadItemLocations(const char* spoilerFileName) {
// CVar_SetString("gSpoilerFileName", spoilerFileName);
// }
void LoadInterfaceEditor(){//This function is necessary as without it IMGui wont load the updated float array. 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[0] = (float)CVar_GetS32("gCCHeartsPrimR", 255)/255;
hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 70)/255; hearts_colors[1] = (float)CVar_GetS32("gCCHeartsPrimG", 70)/255;

View file

@ -82,4 +82,5 @@ namespace SohImGui {
void LoadInterfaceEditor(); void LoadInterfaceEditor();
ImTextureID GetTextureByID(int id); ImTextureID GetTextureByID(int id);
ImTextureID GetTextureByName(const std::string& name); ImTextureID GetTextureByName(const std::string& name);
// void LoadItemLocations(const char* spoilerFileName);
} }

View file

@ -179,7 +179,8 @@ typedef struct {
/* 0x1420 */ s16 worldMapArea; /* 0x1420 */ s16 worldMapArea;
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song /* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator; /* 0x1424 */ s16 healthAccumulator;
ItemLocation itemLocations[512]; ItemLocation itemLocations[266];
Sprite seedIcons[5];
} SaveContext; // size = 0x1428 } SaveContext; // size = 0x1428
typedef enum { typedef enum {

View file

@ -1,5 +1,12 @@
#pragma once #pragma once
typedef struct {
char tex[512];
uint16_t width;
uint16_t height;
uint8_t im_fmt;
uint8_t im_siz;
} Sprite;
typedef enum { typedef enum {
LINKS_POCKET, LINKS_POCKET,

View file

@ -4,14 +4,83 @@
#include <variables.h> #include <variables.h>
#include <macros.h> #include <macros.h>
#include <objects/gameplay_keep/gameplay_keep.h> #include <objects/gameplay_keep/gameplay_keep.h>
#include <objects/object_gi_bomb_1/object_gi_bomb_1.h> #include <functions.h>
#include <objects/object_gi_letter/object_gi_letter.h> #include <Cvar.h>
#include <textures/icon_item_static/icon_item_static.h>
#include <textures/icon_item_24_static/icon_item_24_static.h>
using json = nlohmann::json; using json = nlohmann::json;
std::unordered_map<std::string, Sprite> gSeedTextures;
Randomizer::Randomizer() { Randomizer::Randomizer() {
//todo something? // this isn't as clean as i'd like it to be but it's working
Sprite dekuStickSprite = { gHookshotIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Deku Stick"] = dekuStickSprite;
Sprite dekuNutSprite = { gDekuNutIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Deku Nut"] = dekuNutSprite;
Sprite bowSprite = { gFairyBowIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Bow"] = bowSprite;
Sprite slingshotSprite = { gFairySlingshotIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Slingshot"] = slingshotSprite;
Sprite fairyOcarinaSprite = { gFairyOcarinaIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Fairy Ocarina"] = fairyOcarinaSprite;
Sprite bombchuSprite = { gBombchuIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Bombchu"] = bombchuSprite;
Sprite longshotSprite = { gLongshotIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Longshot"] = longshotSprite;
Sprite boomerangSprite = { gBoomerangIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Boomerang"] = boomerangSprite;
Sprite lensOfTruthSprite = { gLensofTruthIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Lens of Truth"] = lensOfTruthSprite;
Sprite magicBeansSprite = { gMagicBeansIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Beans"] = magicBeansSprite;
Sprite megatonHammerSprite = { gMegatonHammerIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Megaton Hammer"] = megatonHammerSprite;
Sprite fishSprite = { gFishIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Bottled Fish"] = fishSprite;
Sprite milkSprite = { gMilkFullIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Bottled Milk"] = milkSprite;
Sprite maskOfTruthSprite = { gMaskofTruthIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Mask of Truth"] = maskOfTruthSprite;
Sprite soldOutSprite = { gSoldOutIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["SOLD OUT"] = soldOutSprite;
Sprite cuccoSprite = { gCuccoIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Cucco"] = cuccoSprite;
Sprite oddMushroomSprite = { gOddMushroomIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Mushroom"] = oddMushroomSprite;
Sprite sawSprite = { gPoachersSawIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Saw"] = sawSprite;
Sprite frogSprite = { gEyeBallFrogIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Frog"] = frogSprite;
Sprite masterSwordSprite = { gMasterSwordIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Master Sword"] = masterSwordSprite;
Sprite mirrorShieldSprite = { gMirrorShieldIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Mirror Shield"] = mirrorShieldSprite;
Sprite kokiriTunicSprite = { gKokiriTunicIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Kokiri Tunic"] = kokiriTunicSprite;
Sprite hoverBootsSprite = { gHoverBootsIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Hover Boots"] = hoverBootsSprite;
Sprite silverGauntletsSprite = { gSilverGauntletsIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Silver Gauntlets"] = silverGauntletsSprite;
Sprite goldenScaleSprite = { gGoldenScaleIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Gold Scale"] = goldenScaleSprite;
Sprite stoneOfAgonySprite = { gStoneOfAgonyIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Stone of Agony"] = stoneOfAgonySprite;
Sprite skullTokenSprite = { gGoldSkulltulaIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Skull Token"] = skullTokenSprite;
Sprite heartContainerSprite = { gHeartContainerIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Heart Container"] = heartContainerSprite;
Sprite bossKeySprite = { gBossKeyIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Boss Key"] = bossKeySprite;
Sprite compassSprite = { gCompassIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Compass"] = compassSprite;
Sprite mapSprite = { gDungeonMapIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Map"] = mapSprite;
Sprite bigMagicSprite = { gBigMagicJarIconTex, 24, 24, G_IM_FMT_RGBA, G_IM_SIZ_32b };
gSeedTextures["Big Magic"] = bigMagicSprite;
} }
Randomizer::~Randomizer() { Randomizer::~Randomizer() {
this->itemLocations.clear(); this->itemLocations.clear();
} }
@ -643,41 +712,83 @@ s16 Randomizer::GetItemModelFromId(s16 itemId) {
return itemIdToModel[itemId]; return itemIdToModel[itemId];
} }
void Randomizer::LoadItemLocations() { void Randomizer::LoadItemLocations(const char* spoilerFileName) {
// bandaid until new save stuff happens if (strcmp(spoilerFileName, "") != 0) {
ParseItemLocations(""); // bandaid until new save stuff happens
ParseItemLocations(spoilerFileName);
for(auto itemLocation : gSaveContext.itemLocations) { for (auto itemLocation : gSaveContext.itemLocations) {
this->itemLocations[itemLocation.check] = itemLocation.get; this->itemLocations[itemLocation.check] = itemLocation.get;
}
} else {
u16 index = 0;
for (auto itemLocation : this->itemLocations) {
gSaveContext.itemLocations[index].check = itemLocation.first;
gSaveContext.itemLocations[index].get = itemLocation.second;
index++;
}
} }
} }
void Randomizer::ParseItemLocations(std::string spoilerFileName) { void Randomizer::ParseItemLocations(const char* spoilerFileName) {
// todo pull this in from cvar or something // todo pull this in from cvar or something
std::ifstream spoilerFileStream("spoiler.json"); std::ifstream spoilerFileStream(spoilerFileName);
if (!spoilerFileStream) if (!spoilerFileStream)
return; return;
json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
json locationsJson = spoilerFileJson["locations"];
int index = 0;
for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) {
if (it->is_structured()) {
json itemJson = *it;
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
// todo handle prices
if (itemit.key() == "item") {
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()]; bool success = false;
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()];
} try {
} json spoilerFileJson;
} else { spoilerFileStream >> spoilerFileJson;
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()]; json locationsJson = spoilerFileJson["locations"];
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[it.value()]; json hashJson = spoilerFileJson["file_hash"];
int index = 0;
for (auto it = hashJson.begin(); it != hashJson.end(); ++it) {
gSaveContext.seedIcons[index] = gSeedTextures[it.value()];
index++;
} }
index++; index = 0;
for (auto it = locationsJson.begin(); it != locationsJson.end(); ++it) {
if (it->is_structured()) {
json itemJson = *it;
for (auto itemit = itemJson.begin(); itemit != itemJson.end(); ++itemit) {
// todo handle prices
if (itemit.key() == "item") {
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()];
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[itemit.value()];
}
}
} else {
gSaveContext.itemLocations[index].check = SpoilerfileCheckNameToEnum[it.key()];
gSaveContext.itemLocations[index].get = SpoilerfileGetNameToEnum[it.value()];
}
index++;
}
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
success = true;
} catch (const std::exception& e) {
Audio_PlaySoundGeneral(NA_SE_SY_ERROR, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
return;
}
if (success) {
CVar_SetS32("gRandomizer", 1);
}
}
s32 Randomizer::GetRandomizedItemId(GetItemID ogId, s16 actorId, s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ) {
if (actorId != -1) {
s32 itemId = GetItemFromActor(actorId, ogId);
return itemId;
} else {
s32 itemId = GetItemFromSceneParamsAndHomePos(sceneNum, actorParams, homePosX, homePosY, homePosZ, ogId);
return itemId;
} }
} }
@ -685,10 +796,6 @@ GetItemID Randomizer::GetItemFromActor(s16 actorId, GetItemID ogItemId) {
return GetItemFromGet(this->itemLocations[GetCheckFromActor(actorId, ogItemId)], ogItemId); return GetItemFromGet(this->itemLocations[GetCheckFromActor(actorId, ogItemId)], ogItemId);
} }
GetItemID Randomizer::GetItemFromSceneAndParams(s16 sceneNum, s16 actorParams, GetItemID ogItemId) {
return GetItemFromGet(this->itemLocations[GetCheckFromSceneAndParams(sceneNum, actorParams)], ogItemId);
}
GetItemID Randomizer::GetItemFromSceneParamsAndHomePos(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ, GetItemID ogItemId) { GetItemID Randomizer::GetItemFromSceneParamsAndHomePos(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ, GetItemID ogItemId) {
return GetItemFromGet(this->itemLocations[GetCheckFromSceneAndParams(sceneNum, actorParams, homePosX, homePosY, homePosZ)], ogItemId); return GetItemFromGet(this->itemLocations[GetCheckFromSceneAndParams(sceneNum, actorParams, homePosX, homePosY, homePosZ)], ogItemId);
} }
@ -915,6 +1022,11 @@ RandomizerCheck Randomizer::GetCheckFromSceneAndParams(s16 sceneNum, s16 actorPa
} }
switch(sceneNum) { switch(sceneNum) {
case 17:
switch (actorParams) {
case 0x1F:
return DEKU_TREE_QUEEN_GOHMA_HEART;
}
case 40: case 40:
switch(actorParams) { switch(actorParams) {
case 22944: case 22944:
@ -928,8 +1040,10 @@ RandomizerCheck Randomizer::GetCheckFromSceneAndParams(s16 sceneNum, s16 actorPa
} }
case 84: case 84:
switch (actorParams) { switch (actorParams) {
case 0x0406: case 1030:
return ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH; return ZR_NEAR_OPEN_GROTTO_FREESTANDING_POH;
case 2822:
return ZR_NEAR_DOMAIN_FREESTANDING_POH;
} }
case 85: case 85:
switch(actorParams) { switch(actorParams) {
@ -983,7 +1097,7 @@ RandomizerCheck Randomizer::GetCheckFromSceneAndParams(s16 sceneNum, s16 actorPa
} }
case 96: case 96:
switch(actorParams) { switch(actorParams) {
case 6: case 7686:
return DMT_FREESTANDING_POH; return DMT_FREESTANDING_POH;
case 23201: case 23201:
return DMT_CHEST; return DMT_CHEST;

View file

@ -12,18 +12,18 @@ class Randomizer {
std::unordered_map<RandomizerCheck, RandomizerGet> itemLocations; std::unordered_map<RandomizerCheck, RandomizerGet> itemLocations;
GetItemID GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId); GetItemID GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId);
RandomizerCheck GetCheckFromActor(s16 actorId, GetItemID ogItemId); RandomizerCheck GetCheckFromActor(s16 actorId, GetItemID ogItemId);
RandomizerCheck GetCheckFromSceneAndParams(s16 sceneNum, s16 actorParams, s32 homePosX = 0, s32 homePosY = 0, s32 homePosZ = 0); RandomizerCheck GetCheckFromSceneAndParams(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ);
GetItemID GetItemFromActor(s16 actorId, GetItemID ogItemId);
GetItemID GetItemFromSceneParamsAndHomePos(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ, GetItemID ogItemId);
public: public:
Randomizer(); Randomizer();
~Randomizer(); ~Randomizer();
s16 GetItemModelFromId(s16 itemId); s16 GetItemModelFromId(s16 itemId);
void LoadItemLocations(); void LoadItemLocations(const char* spoilerFileName);
void ParseItemLocations(std::string spoilerfilename); void ParseItemLocations(const char* spoilerFileName);
GetItemID GetItemFromActor(s16 actorId, GetItemID ogItemId); s32 GetRandomizedItemId(GetItemID ogId, s16 actorId = -1, s16 sceneNum = -1, s16 actorParams = -1, s32 homePosX = 0, s32 homePosY = 0, s32 homePosZ = 0);
GetItemID GetItemFromSceneAndParams(s16 sceneNum, s16 actorParams, GetItemID ogItemId);
GetItemID GetItemFromSceneParamsAndHomePos(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ, GetItemID ogItemId);
}; };
#endif #endif

View file

@ -1000,23 +1000,24 @@ extern "C" s16 GetItemModelFromId(s16 itemId) {
return OTRGlobals::Instance->gRandomizer->GetItemModelFromId(itemId); return OTRGlobals::Instance->gRandomizer->GetItemModelFromId(itemId);
} }
extern "C" void LoadItemLocations() { extern "C" void LoadItemLocations(const char* spoilerFileName) {
OTRGlobals::Instance->gRandomizer->LoadItemLocations(); OTRGlobals::Instance->gRandomizer->LoadItemLocations(spoilerFileName);
} }
extern "C" void ParseItemLocations(const char* spoilerfilename) { extern "C" void ParseItemLocations(const char* spoilerFileName) {
OTRGlobals::Instance->gRandomizer->ParseItemLocations(spoilerfilename); OTRGlobals::Instance->gRandomizer->ParseItemLocations(spoilerFileName);
} }
extern "C" GetItemID GetItemFromActor(s16 actorId, GetItemID ogItemId) { extern "C" s32 GetRandomizedItemId(GetItemID ogId, s16 sceneNum, s16 actorParams) {
return OTRGlobals::Instance->gRandomizer->GetItemFromActor(actorId, ogItemId); return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, -1, sceneNum, actorParams);
} }
extern "C" GetItemID GetItemFromSceneAndParams(s16 sceneNum, s16 actorParams, GetItemID ogItemId) { // the lack of optional params in c is frustrating
return OTRGlobals::Instance->gRandomizer->GetItemFromSceneAndParams(sceneNum, actorParams, ogItemId); extern "C" s32 GetRandomizedItemIdFromActor(GetItemID ogId, s16 actorId ) {
return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, actorId);
} }
// use an explicit (s32) cast on the position values from the Vec3f when calling // use an explicit (s32) cast on the position values from the Vec3f when calling
extern "C" GetItemID GetItemFromSceneParamsAndHomePos(s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ, GetItemID ogItemId) { extern "C" s32 GetRandomizedItemIdFromPosition(GetItemID ogId, s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ) {
return OTRGlobals::Instance->gRandomizer->GetItemFromSceneParamsAndHomePos(sceneNum, actorParams, homePosX, homePosY, homePosZ, ogItemId); return OTRGlobals::Instance->gRandomizer->GetRandomizedItemId(ogId, -1, sceneNum, actorParams, homePosX, homePosY, homePosZ);
} }

View file

@ -74,9 +74,12 @@ int AudioPlayer_GetDesiredBuffered(void);
void AudioPlayer_Play(const uint8_t* buf, uint32_t len); void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples); void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
int Controller_ShouldRumble(size_t i); int Controller_ShouldRumble(size_t i);
void LoadItemLocations(const char* spoilerFileName);
void ParseItemLocations(const char* spoilerfilename); void ParseItemLocations(const char* spoilerfilename);
GetItemID GetItemFromActor(s16 actorId, GetItemID ogItemId); s32 GetRandomizedItemId(GetItemID ogId, s16 sceneNum, s16 actorParams);
GetItemID GetItemFromSceneAndParams(s16 sceneNum, s16 actorParams, GetItemID ogItemId); s32 GetRandomizedItemIdFromActor(GetItemID ogId, s16 actorId);
s32 GetRandomizedItemIdFromPosition(GetItemID ogId, s16 sceneNum, s16 actorParams, s32 homePosX, s32 homePosY, s32 homePosZ);
#endif #endif
#endif #endif

View file

@ -4,7 +4,7 @@ void TitleSetup_InitImpl(GameState* gameState) {
osSyncPrintf("ゼルダ共通データ初期化\n"); // "Zelda common data initalization" osSyncPrintf("ゼルダ共通データ初期化\n"); // "Zelda common data initalization"
SaveContext_Init(); SaveContext_Init();
gameState->running = false; gameState->running = false;
SET_NEXT_GAMESTATE(gameState, FileChoose_Init, TitleContext); SET_NEXT_GAMESTATE(gameState, Title_Init, TitleContext);
} }
void TitleSetup_Destroy(GameState* gameState) { void TitleSetup_Destroy(GameState* gameState) {

View file

@ -332,11 +332,6 @@ void EnItem00_SetupAction(EnItem00* this, EnItem00ActionFunc actionFunc) {
this->actionFunc = actionFunc; this->actionFunc = actionFunc;
} }
s32 Item00_GetRandomizedItemId(EnItem00* this, s16 sceneNum, s16 actorParams) {
s32 itemId = GetItemFromSceneAndParams(sceneNum, this->actor.params, this->getItemId);
return itemId;
}
void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
EnItem00* this = (EnItem00*)thisx; EnItem00* this = (EnItem00*)thisx;
s32 pad; s32 pad;
@ -697,7 +692,7 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) {
} }
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) { if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) {
getItemId = Item00_GetRandomizedItemId(this, globalCtx->sceneNum, this->ogParams); getItemId = GetRandomizedItemId(this->getItemId, globalCtx->sceneNum, this->ogParams);
func_8002F554(&this->actor, globalCtx, getItemId); func_8002F554(&this->actor, globalCtx, getItemId);
} }
@ -1058,7 +1053,7 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) {
if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) { if ((getItemId != GI_NONE) && !Actor_HasParent(&this->actor, globalCtx)) {
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
getItemId = Item00_GetRandomizedItemId(this, globalCtx->sceneNum, this->ogParams); getItemId = GetRandomizedItemId(this->getItemId, globalCtx->sceneNum, this->ogParams);
} }
func_8002F554(&this->actor, globalCtx, getItemId); func_8002F554(&this->actor, globalCtx, getItemId);
} }
@ -1330,7 +1325,7 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) { if (gSaveContext.n64ddFlag) {
f32 mtxScale = 16.0f; f32 mtxScale = 16.0f;
Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY);
GetItem_Draw(globalCtx, GetItemModelFromId(Item00_GetRandomizedItemId(this, gGlobalCtx->sceneNum, this->actor.params))); GetItem_Draw(globalCtx, GetItemModelFromId(GetRandomizedItemId(this->getItemId, globalCtx->sceneNum, this->ogParams)));
} else { } else {
s32 pad; s32 pad;

View file

@ -193,11 +193,67 @@ void Gameplay_Destroy(GameState* thisx) {
gGlobalCtx = NULL; gGlobalCtx = NULL;
} }
void GiveLinksPocketMedallion(GlobalContext* globalCtx) {
if (gSaveContext.n64ddFlag) {
RandomizerGet get = gSaveContext.itemLocations[LINKS_POCKET].get;
s16 item;
u8 medallion = 0;
switch (get) {
case FOREST_MEDALLION:
item = ITEM_MEDALLION_FOREST;
medallion = 1;
break;
case FIRE_MEDALLION:
item = ITEM_MEDALLION_FIRE;
medallion = 1;
break;
case WATER_MEDALLION:
item = ITEM_MEDALLION_WATER;
medallion = 1;
break;
case SHADOW_MEDALLION:
item = ITEM_MEDALLION_SHADOW;
medallion = 1;
break;
case SPIRIT_MEDALLION:
item = ITEM_MEDALLION_SPIRIT;
medallion = 1;
break;
case LIGHT_MEDALLION:
item = ITEM_MEDALLION_LIGHT;
medallion = 1;
break;
case KOKIRI_EMERALD:
item = ITEM_KOKIRI_EMERALD;
break;
case GORON_RUBY:
item = ITEM_GORON_RUBY;
break;
case ZORA_SAPPHIRE:
item = ITEM_ZORA_SAPPHIRE;
break;
}
if (medallion == 1) {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST];
if (item == ITEM_MEDALLION_WATER) {
func_8006D0AC(globalCtx);
}
} else {
gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD];
}
}
}
void Gameplay_Init(GameState* thisx) { void Gameplay_Init(GameState* thisx) {
GlobalContext* globalCtx = (GlobalContext*)thisx; GlobalContext* globalCtx = (GlobalContext*)thisx;
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx; GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
gGlobalCtx = globalCtx; gGlobalCtx = globalCtx;
//globalCtx->state.gfxCtx = NULL; // globalCtx->state.gfxCtx = NULL;
u32 zAlloc; u32 zAlloc;
u32 zAllocAligned; u32 zAllocAligned;
size_t zAllocSize; size_t zAllocSize;
@ -207,6 +263,8 @@ void Gameplay_Init(GameState* thisx) {
u8 tempSetupIndex; u8 tempSetupIndex;
s32 pad[2]; s32 pad[2];
GiveLinksPocketMedallion(globalCtx);
if (gSaveContext.entranceIndex == -1) { if (gSaveContext.entranceIndex == -1) {
gSaveContext.entranceIndex = 0; gSaveContext.entranceIndex = 0;
globalCtx->state.running = false; globalCtx->state.running = false;

View file

@ -515,8 +515,13 @@ void DoorWarp1_ChildWarpOut(DoorWarp1* this, GlobalContext* globalCtx) {
Flags_SetEventChkInf(7); Flags_SetEventChkInf(7);
Flags_SetEventChkInf(9); Flags_SetEventChkInf(9);
Item_Give(globalCtx, ITEM_KOKIRI_EMERALD); Item_Give(globalCtx, ITEM_KOKIRI_EMERALD);
globalCtx->nextEntranceIndex = 0xEE; if (gSaveContext.n64ddFlag) {
gSaveContext.nextCutsceneIndex = 0xFFF1; globalCtx->nextEntranceIndex = 0x0457;
gSaveContext.nextCutsceneIndex = 0;
} else {
globalCtx->nextEntranceIndex = 0xEE;
gSaveContext.nextCutsceneIndex = 0xFFF1;
}
} else { } else {
globalCtx->nextEntranceIndex = 0x457; globalCtx->nextEntranceIndex = 0x457;
gSaveContext.nextCutsceneIndex = 0; gSaveContext.nextCutsceneIndex = 0;

View file

@ -383,11 +383,6 @@ void EnBox_AppearAnimation(EnBox* this, GlobalContext* globalCtx) {
} }
} }
s32 EnBox_GetRandomizedItemId(s16 actorParams, s16 sceneNum) {
s32 itemId = GetItemFromSceneAndParams(sceneNum, actorParams, actorParams >> 5 & 0x7F);
return 0 - itemId;
}
/** /**
* Chest is ready to be open * Chest is ready to be open
*/ */
@ -429,8 +424,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos); func_8002DBD0(&this->dyna.actor, &sp4C, &player->actor.world.pos);
if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f && if (sp4C.z > -50.0f && sp4C.z < 0.0f && fabsf(sp4C.y) < 10.0f && fabsf(sp4C.x) < 20.0f &&
Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) { Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) {
func_8002F554(&this->dyna.actor, globalCtx, func_8002F554(&this->dyna.actor, globalCtx, 0 - GetRandomizedItemId(this->dyna.actor.params >> 5 & 0x7F, globalCtx->sceneNum, this->dyna.actor.params));
EnBox_GetRandomizedItemId(this->dyna.actor.params, globalCtx->sceneNum));
} }
if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) { if (Flags_GetTreasure(globalCtx, this->dyna.actor.params & 0x1F)) {
EnBox_SetupAction(this, EnBox_Open); EnBox_SetupAction(this, EnBox_Open);

View file

@ -294,11 +294,6 @@ void func_80ABA244(EnNiwLady* this, GlobalContext* globalCtx) {
} }
} }
s32 NiwLady_GetRandomizedItemId(EnNiwLady* this, GetItemID ogId) {
s32 itemId = GetItemFromActor(this->actor.id, ogId);
return itemId;
}
void func_80ABA654(EnNiwLady* this, GlobalContext* globalCtx) { void func_80ABA654(EnNiwLady* this, GlobalContext* globalCtx) {
if (this->unk_262 == Message_GetState(&globalCtx->msgCtx) && Message_ShouldAdvance(globalCtx)) { if (this->unk_262 == Message_GetState(&globalCtx->msgCtx) && Message_ShouldAdvance(globalCtx)) {
Message_CloseTextbox(globalCtx); Message_CloseTextbox(globalCtx);
@ -309,9 +304,8 @@ void func_80ABA654(EnNiwLady* this, GlobalContext* globalCtx) {
if (!(gSaveContext.itemGetInf[0] & 0x1000)) { if (!(gSaveContext.itemGetInf[0] & 0x1000)) {
this->actor.parent = NULL; this->actor.parent = NULL;
this->getItemId = NiwLady_GetRandomizedItemId(this, GI_BOTTLE); this->getItemId = GetRandomizedItemIdFromActor(GI_BOTTLE, this->actor.id);
func_8002F434(&this->actor, globalCtx, GetRandomizedItemIdFromActor(GI_BOTTLE, this->actor.id), 100.0f, 50.0f); //not sure if calling again makes sense here or if we should just use this->getItemId
func_8002F434(&this->actor, globalCtx, NiwLady_GetRandomizedItemId(this, GI_BOTTLE), 100.0f, 50.0f);
this->actionFunc = func_80ABAC00; this->actionFunc = func_80ABAC00;
return; return;
} }
@ -393,7 +387,7 @@ void func_80ABA9B8(EnNiwLady* this, GlobalContext* globalCtx) {
case 0: case 0:
Message_CloseTextbox(globalCtx); Message_CloseTextbox(globalCtx);
this->actor.parent = NULL; this->actor.parent = NULL;
func_8002F434(&this->actor, globalCtx, NiwLady_GetRandomizedItemId(this, GI_POCKET_EGG), 200.0f, func_8002F434(&this->actor, globalCtx, GetRandomizedItemIdFromActor(GI_POCKET_EGG, this->actor.id), 200.0f,
100.0f); 100.0f);
this->actionFunc = func_80ABAC00; this->actionFunc = func_80ABAC00;
break; break;
@ -447,7 +441,7 @@ void func_80ABAC00(EnNiwLady* this, GlobalContext* globalCtx) {
getItemId = this->getItemId; getItemId = this->getItemId;
if (LINK_IS_ADULT) { if (LINK_IS_ADULT) {
getItemId = getItemId =
!(gSaveContext.itemGetInf[2] & 0x1000) ? NiwLady_GetRandomizedItemId(this, GI_POCKET_EGG) : GI_COJIRO; !(gSaveContext.itemGetInf[2] & 0x1000) ? GetRandomizedItemIdFromActor(GI_POCKET_EGG, this->actor.id) : GI_COJIRO;
} }
func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f); func_8002F434(&this->actor, globalCtx, getItemId, 200.0f, 100.0f);
} }

View file

@ -59,7 +59,12 @@ void ItemBHeart_Update(Actor* thisx, GlobalContext* globalCtx) {
Flags_SetCollectible(globalCtx, 0x1F); Flags_SetCollectible(globalCtx, 0x1F);
Actor_Kill(&this->actor); Actor_Kill(&this->actor);
} else { } else {
func_8002F434(&this->actor, globalCtx, GI_HEART_CONTAINER_2, 30.0f, 40.0f); if (gSaveContext.n64ddFlag) {
s16 getItemId = GetRandomizedItemId(GI_HEART_CONTAINER_2, globalCtx->sceneNum, 0x1F);
func_8002F434(&this->actor, globalCtx, getItemId, 30.0f, 40.0f);
} else {
func_8002F434(&this->actor, globalCtx, GI_HEART_CONTAINER_2, 30.0f, 40.0f);
}
} }
} }
@ -93,18 +98,23 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) {
actorIt = actorIt->next; actorIt = actorIt->next;
} }
if (flag) { if (gSaveContext.n64ddFlag) {
func_80093D84(globalCtx->state.gfxCtx); GetItem_Draw(globalCtx,
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 551), GetItemModelFromId(GetRandomizedItemId(GI_HEART_CONTAINER_2, globalCtx->sceneNum, 0x1F)));
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL);
gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL);
} else { } else {
func_80093D18(globalCtx->state.gfxCtx); if (flag) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 557), func_80093D84(globalCtx->state.gfxCtx);
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 551),
gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL); G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL); gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL);
gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL);
} else {
func_80093D18(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 557),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL);
gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL);
}
} }
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 561); CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 561);

View file

@ -4,6 +4,7 @@
#include "textures/title_static/title_static.h" #include "textures/title_static/title_static.h"
#include "textures/parameter_static/parameter_static.h" #include "textures/parameter_static/parameter_static.h"
#include <textures/icon_item_static/icon_item_static.h>
static s16 sUnused = 106; static s16 sUnused = 106;
@ -63,6 +64,7 @@ void FileChoose_InitModeUpdate(GameState* thisx) {
this->configMode = CM_FADE_IN_START; this->configMode = CM_FADE_IN_START;
this->nextTitleLabel = FS_TITLE_OPEN_FILE; this->nextTitleLabel = FS_TITLE_OPEN_FILE;
osSyncPrintf(" Start─Load 》》》》》 "); osSyncPrintf(" Start─Load 》》》》》 ");
CVar_SetS32("gRandomizer", 0);
Sram_VerifyAndLoadAllSaves(this, &this->sramCtx); Sram_VerifyAndLoadAllSaves(this, &this->sramCtx);
osSyncPrintf("終了!!!\n"); osSyncPrintf("終了!!!\n");
} }
@ -163,6 +165,63 @@ void FileChoose_FinishFadeIn(GameState* thisx) {
} }
} }
Sprite sprDPad = { gHookshotIconTex, 32, 32, G_IM_FMT_RGBA, G_IM_SIZ_32b };
void SpriteLoad(FileChooseContext* this, Sprite* sprite) {
OPEN_DISPS(this->state.gfxCtx, "gfx.c", 12);
if (sprite->im_siz == G_IM_SIZ_16b) {
gDPLoadTextureBlock(POLY_OPA_DISP++, sprite->tex, sprite->im_fmt,
G_IM_SIZ_16b, // @TEMP until I figure out how to use sprite->im_siz
sprite->width, sprite->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);
} else {
gDPLoadTextureBlock(POLY_OPA_DISP++, sprite->tex, sprite->im_fmt,
G_IM_SIZ_32b, // @TEMP until I figure out how to use sprite->im_siz
sprite->width, sprite->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);
}
CLOSE_DISPS(this->state.gfxCtx, "gfx.c", 40);
}
void SpriteDraw(FileChooseContext* this, Sprite* sprite, int left, int top, int width, int height) {
int width_factor = (1 << 10) * sprite->width / width;
int height_factor = (1 << 10) * sprite->height / height;
OPEN_DISPS(this->state.gfxCtx, "gfx.c", 51);
gSPWideTextureRectangle(POLY_OPA_DISP++, left << 2, top << 2, (left + width) << 2, (top + height) << 2,
G_TX_RENDERTILE,
0, 0, width_factor, height_factor);
CLOSE_DISPS(this->state.gfxCtx, "gfx.c", 62);
}
void DrawSeedHashSprites(FileChooseContext* this) {
OPEN_DISPS(this->state.gfxCtx, "dpad.c", 60);
gDPPipeSync(POLY_OPA_DISP++);
gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF);
// Draw Seed Icons
u16 xStart = 64;
for (u8 i = 0; i < 5; i++) {
// gSaveContext.seedIcons[i];
// hacky check to make sure we leaded the icons
if(gSaveContext.seedIcons[i].height) {
SpriteLoad(this, &gSaveContext.seedIcons[i]);
SpriteDraw(this, &gSaveContext.seedIcons[i], xStart + (40 * i), 10, 24, 24);
}
// SpriteLoad(this, &sprDPad);
// SpriteDraw(this, &sprDPad, xStart + (40 * i), 10, 24, 24);
}
gDPPipeSync(POLY_OPA_DISP++);
CLOSE_DISPS(this->state.gfxCtx, "dpad.c", 113);
}
/** /**
* Update the cursor and wait for the player to select a button to change menus accordingly. * Update the cursor and wait for the player to select a button to change menus accordingly.
* If an empty file is selected, enter the name entry config mode. * If an empty file is selected, enter the name entry config mode.
@ -814,6 +873,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
s16 j; s16 j;
s16 deathCountSplit[3]; s16 deathCountSplit[3];
DrawSeedHashSprites(this);
if (1) {} if (1) {}
OPEN_DISPS(this->state.gfxCtx, "../z_file_choose.c", 1709); OPEN_DISPS(this->state.gfxCtx, "../z_file_choose.c", 1709);
@ -1458,7 +1519,6 @@ void FileChoose_LoadGame(GameState* thisx) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSaveContext.fileNum = this->buttonIndex; gSaveContext.fileNum = this->buttonIndex;
Sram_OpenSave(&this->sramCtx); Sram_OpenSave(&this->sramCtx);
LoadItemLocations();
gSaveContext.gameMode = 0; gSaveContext.gameMode = 0;
SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext); SET_NEXT_GAMESTATE(&this->state, Select_Init, SelectContext);
this->state.running = false; this->state.running = false;
@ -1466,12 +1526,14 @@ void FileChoose_LoadGame(GameState* thisx) {
Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); Audio_PlaySoundGeneral(NA_SE_SY_FSEL_DECIDE_L, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
gSaveContext.fileNum = this->buttonIndex; gSaveContext.fileNum = this->buttonIndex;
Sram_OpenSave(&this->sramCtx); Sram_OpenSave(&this->sramCtx);
LoadItemLocations();
gSaveContext.gameMode = 0; gSaveContext.gameMode = 0;
SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext); SET_NEXT_GAMESTATE(&this->state, Gameplay_Init, GlobalContext);
this->state.running = false; this->state.running = false;
} }
LoadItemLocations("");
gSaveContext.respawn[0].entranceIndex = -1; gSaveContext.respawn[0].entranceIndex = -1;
gSaveContext.respawnFlag = 0; gSaveContext.respawnFlag = 0;
gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.seqId = (u8)NA_BGM_DISABLED;

View file

@ -449,7 +449,17 @@ void FileChoose_DrawNameEntry(GameState* thisx) {
dayTime = ((void)0, gSaveContext.dayTime); dayTime = ((void)0, gSaveContext.dayTime);
ParseItemLocations("blarg"); // hacky function for testing
// while drag and drop is broken on linux
// enter "rando" as file name
if(this->fileNames[1][0] == '5' &&
this->fileNames[1][1] == '$' &&
this->fileNames[1][2] == '1' &&
this->fileNames[1][3] == '\'' &&
this->fileNames[1][4] == '2')
{
ParseItemLocations("spoiler.json");
}
Sram_InitSave(this, &this->sramCtx); Sram_InitSave(this, &this->sramCtx);