diff --git a/include/recomp_config.h b/include/recomp_config.h index 9310d53..5ed7820 100644 --- a/include/recomp_config.h +++ b/include/recomp_config.h @@ -7,6 +7,7 @@ namespace recomp { constexpr std::u8string_view program_id = u8"Zelda64Recompiled"; + constexpr std::u8string_view mm_game_id = u8"mm.n64.us.1.0"; void load_config(); void save_config(); diff --git a/include/recomp_ui.h b/include/recomp_ui.h index 715574a..cb850c0 100644 --- a/include/recomp_ui.h +++ b/include/recomp_ui.h @@ -56,6 +56,7 @@ namespace recomp { void destroy_ui(); void apply_color_hack(); void get_window_size(int& width, int& height); + void set_cursor_visible(bool visible); } #endif diff --git a/patches/input.c b/patches/input.c index 3fe479b..e7c6029 100644 --- a/patches/input.c +++ b/patches/input.c @@ -216,7 +216,6 @@ EquipSlot func_8082FDC4(void) { for (int extra_slot_index = 0; extra_slot_index < ARRAY_COUNT(buttons_to_extra_slot); extra_slot_index++) { if (CHECK_BTN_ALL(sPlayerControlInput_reloc->press.button, buttons_to_extra_slot[extra_slot_index].button)) { - recomp_printf("Pressed extra item button %d\n", extra_slot_index); return (EquipSlot)buttons_to_extra_slot[extra_slot_index].slot; } } @@ -237,7 +236,6 @@ ItemId Player_GetItemOnButton(PlayState* play, Player* player, EquipSlot slot) { // @recomp Check for extra item slots. if (slot <= -EQUIP_SLOT_EX_START) { - recomp_printf("Checking extra item slot %d\n", -slot); ItemId item = EXTRA_BTN_ITEM(-slot); // Ensure the item was valid and has been obtained. diff --git a/src/game/input.cpp b/src/game/input.cpp index d649003..a1f8aa4 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -66,6 +66,12 @@ void queue_if_enabled(SDL_Event* event) { } } +static std::atomic_bool cursor_enabled = true; + +void recomp::set_cursor_visible(bool visible) { + cursor_enabled.store(visible); +} + bool sdl_event_filter(void* userdata, SDL_Event* event) { switch (event->type) { case SDL_EventType::SDL_KEYDOWN: @@ -185,6 +191,7 @@ void recomp::handle_events() { static bool exited = false; while (SDL_PollEvent(&cur_event) && !exited) { exited = sdl_event_filter(nullptr, &cur_event); + SDL_ShowCursor(cursor_enabled ? SDL_ENABLE : SDL_DISABLE); } } diff --git a/src/recomp/pi.cpp b/src/recomp/pi.cpp index 5ee5796..ab0e4a0 100644 --- a/src/recomp/pi.cpp +++ b/src/recomp/pi.cpp @@ -2,8 +2,10 @@ #include #include #include +#include #include "recomp.h" #include "recomp_game.h" +#include "recomp_config.h" #include "../ultramodern/ultra64.h" #include "../ultramodern/ultramodern.hpp" @@ -59,10 +61,15 @@ void recomp::do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr } std::array save_buffer; -const char save_filename[] = "save.bin"; +const std::u8string save_folder = u8"saves"; +const std::u8string save_filename = std::u8string{recomp::mm_game_id} + u8".bin"; + +std::filesystem::path get_save_file_path() { + return recomp::get_app_folder_path() / save_folder / save_filename; +} void update_save_file() { - std::ofstream save_file{ save_filename, std::ios_base::binary }; + std::ofstream save_file{ get_save_file_path(), std::ios_base::binary }; if (save_file.good()) { save_file.write(save_buffer.data(), save_buffer.size()); @@ -92,7 +99,7 @@ void save_read(uint8_t* rdram, gpr rdram_address, uint32_t offset, uint32_t coun void save_clear(uint32_t start, uint32_t size, char value) { std::fill_n(save_buffer.begin() + start, size, value); - std::ofstream save_file{ save_filename, std::ios_base::binary }; + std::ofstream save_file{ get_save_file_path(), std::ios_base::binary }; if (save_file.good()) { save_file.write(save_buffer.data(), save_buffer.size()); @@ -103,11 +110,17 @@ void save_clear(uint32_t start, uint32_t size, char value) { } void ultramodern::save_init() { - std::ifstream save_file{ save_filename, std::ios_base::binary }; + std::filesystem::path save_file_path = get_save_file_path(); + // Ensure the save file directory exists. + std::filesystem::create_directories(save_file_path.parent_path()); + + // Read the save file if it exists. + std::ifstream save_file{ save_file_path, std::ios_base::binary }; if (save_file.good()) { save_file.read(save_buffer.data(), save_buffer.size()); } else { + // Otherwise clear the save file to all zeroes. save_buffer.fill(0); } } diff --git a/src/recomp/recomp.cpp b/src/recomp/recomp.cpp index 00435f8..fc75098 100644 --- a/src/recomp/recomp.cpp +++ b/src/recomp/recomp.cpp @@ -39,7 +39,7 @@ struct RomEntry { }; const std::unordered_map game_roms { - { recomp::Game::MM, { 0xEF18B4A9E2386169ULL, u8"mm.n64.us.1.0.z64", "ZELDA MAJORA'S MASK" }}, + { recomp::Game::MM, { 0xEF18B4A9E2386169ULL, std::u8string{recomp::mm_game_id} + u8".z64", "ZELDA MAJORA'S MASK" }}, }; bool check_hash(const std::vector& rom_data, uint64_t expected_hash) { diff --git a/src/ui/ui_renderer.cpp b/src/ui/ui_renderer.cpp index a94e68e..6685bfd 100644 --- a/src/ui/ui_renderer.cpp +++ b/src/ui/ui_renderer.cpp @@ -900,8 +900,7 @@ struct UIContext { } if (mouse_is_active_initialized) { - // TODO: Figure out why this only works if the mouse is moving - SDL_ShowCursor(mouse_is_active ? SDL_ENABLE : SDL_DISABLE); + recomp::set_cursor_visible(mouse_is_active); } if (current_document == nullptr) {