From 61482629eebfbb7feacae722a552e8bb5e9520a2 Mon Sep 17 00:00:00 2001 From: Ilari Liusvaara Date: Tue, 3 Sep 2013 22:27:42 +0300 Subject: [PATCH] If loading movie/savestate without ROM, prompt for one --- include/core/emucore.hpp | 2 ++ include/core/mainloop.hpp | 1 + include/core/window.hpp | 5 +++ .../platform/wxwidgets/window_mainwindow.hpp | 1 + src/core/bsnes-legacy.cpp | 5 +++ src/core/gambatte.cpp | 10 ++++++ src/core/mainloop.cpp | 21 +++++++++++- src/core/moviedata.cpp | 33 +++++++++++++++++++ src/dummy/graphics.cpp | 5 +++ src/platform/sdl/graphicsfn.cpp | 6 ++++ src/platform/wxwidgets/main.cpp | 25 ++++++++++++++ src/platform/wxwidgets/mainwindow.cpp | 31 ++++++++++++++++- 12 files changed, 143 insertions(+), 2 deletions(-) diff --git a/include/core/emucore.hpp b/include/core/emucore.hpp index 029b11f9..39bb00cb 100644 --- a/include/core/emucore.hpp +++ b/include/core/emucore.hpp @@ -71,6 +71,8 @@ std::pair core_get_bus_map(); unsigned core_get_poll_flag(); //Set poll flag (set to 1 on each real poll, except if 2. void core_set_poll_flag(unsigned pflag); +//Is a cartridge loaded? +bool core_rom_loaded(); /** * Get name of logical button. diff --git a/include/core/mainloop.hpp b/include/core/mainloop.hpp index f043b742..42220c79 100644 --- a/include/core/mainloop.hpp +++ b/include/core/mainloop.hpp @@ -24,5 +24,6 @@ extern std::string msu1_base_path; void mainloop_signal_need_rewind(void* ptr); void set_stop_at_frame(uint64_t frame = 0); +void force_pause(); #endif diff --git a/include/core/window.hpp b/include/core/window.hpp index 21d101fc..0bb91a15 100644 --- a/include/core/window.hpp +++ b/include/core/window.hpp @@ -4,6 +4,7 @@ #include "core/keymapper.hpp" #include "core/messagebuffer.hpp" #include "core/status.hpp" +#include "core/romtype.hpp" #include "library/framebuffer.hpp" #include #include @@ -221,6 +222,10 @@ struct graphics_plugin * - The call can occur in any thread. */ static void fatal_error() throw(); +/** + * Request filename for ROM load. + */ + static std::string request_rom(core_type& coretype); /** * Identification for graphics plugin. */ diff --git a/include/platform/wxwidgets/window_mainwindow.hpp b/include/platform/wxwidgets/window_mainwindow.hpp index e3ccfda9..57f99869 100644 --- a/include/platform/wxwidgets/window_mainwindow.hpp +++ b/include/platform/wxwidgets/window_mainwindow.hpp @@ -41,6 +41,7 @@ public: void menu_check(int id, bool newstate); void menu_separator(); void handle_menu_click(wxCommandEvent& e); + void request_rom(std::string& filename, core_type& coretype); recent_menu* recent_roms; recent_menu* recent_movies; private: diff --git a/src/core/bsnes-legacy.cpp b/src/core/bsnes-legacy.cpp index 4f71b21f..23195697 100644 --- a/src/core/bsnes-legacy.cpp +++ b/src/core/bsnes-legacy.cpp @@ -1175,6 +1175,11 @@ void core_set_poll_flag(unsigned pflag) pollflag_active = (pflag < 2); } +bool core_rom_loaded() +{ + return (internal_rom != NULL); +} + emucore_callbacks::~emucore_callbacks() throw() { } diff --git a/src/core/gambatte.cpp b/src/core/gambatte.cpp index 57b77e8f..f3dd7a05 100644 --- a/src/core/gambatte.cpp +++ b/src/core/gambatte.cpp @@ -323,6 +323,11 @@ void core_power() void core_unload_cartridge() { + if(!internal_rom) + return; + instance->~GB(); + new(instance) gambatte::GB; + internal_rom = NULL; } void set_preload_settings() @@ -607,6 +612,11 @@ std::pair core_get_bus_map() return std::make_pair(0, 0); } +bool core_rom_loaded() +{ + return (internal_rom != NULL); +} + emucore_callbacks::~emucore_callbacks() throw() {} struct emucore_callbacks* ecore_callbacks; diff --git a/src/core/mainloop.cpp b/src/core/mainloop.cpp index a809f02b..d228a053 100644 --- a/src/core/mainloop.cpp +++ b/src/core/mainloop.cpp @@ -288,6 +288,11 @@ namespace } return true; } + + void close_rom() + { + our_rom->rtype = NULL; + } } void update_movie_state() @@ -731,6 +736,13 @@ namespace mark_pending_load("SOME NONBLANK NAME", LOAD_STATE_ROMRELOAD); }); + function_ptr_command<> close_rom2("close-rom", "Close the ROM image", + "Syntax: close-rom\nClose the ROM image\n", + []() throw(std::bad_alloc, std::runtime_error) { + close_rom(); + mark_pending_load("SOME NONBLANK NAME", LOAD_STATE_ROMRELOAD); + }); + function_ptr_command<> cancel_save("cancel-saves", "Cancel all pending saves", "Syntax: cancel-save\n" "Cancel pending saves\n", []() throw(std::bad_alloc, std::runtime_error) { @@ -1084,7 +1096,8 @@ void main_loop(struct loaded_rom& rom, struct moviefile& initial, bool load_has_ just_did_loadstate = false; } frame_irq_time = get_utime() - time_x; - core_emulate_frame(); + if(core_rom_loaded()) + core_emulate_frame(); time_x = get_utime(); if(amode == ADVANCE_AUTO) platform::wait(to_wait_frame(get_utime())); @@ -1103,3 +1116,9 @@ void set_stop_at_frame(uint64_t frame) amode = ADVANCE_AUTO; platform::set_paused(false); } + +void force_pause() +{ + amode = ADVANCE_PAUSE; + platform::set_paused(true); +} \ No newline at end of file diff --git a/src/core/moviedata.cpp b/src/core/moviedata.cpp index 5cb6030b..89ddf374 100644 --- a/src/core/moviedata.cpp +++ b/src/core/moviedata.cpp @@ -7,11 +7,14 @@ #include "core/framebuffer.hpp" #include "core/framerate.hpp" #include "lua/lua.hpp" +#include "core/mainloop.hpp" +#include "core/memorymanip.hpp" #include "core/misc.hpp" #include "core/moviedata.hpp" #include "core/rrdata.hpp" #include "core/settings.hpp" #include "library/string.hpp" +#include "library/zip.hpp" #include #include @@ -295,6 +298,14 @@ extern time_t random_seed_value; void do_load_beginning(bool reload) throw(std::bad_alloc, std::runtime_error) { + if(!our_rom->rtype) { + core_unload_cartridge(); + refresh_cart_mappings(); + redraw_framebuffer(screen_nosignal); + force_pause(); + messages << "ROM closed" << std::endl; + return; + } if(!our_movie.gametype && !reload) { messages << "Can't load movie without a ROM" << std::endl; return; @@ -346,6 +357,26 @@ void do_load_beginning(bool reload) throw(std::bad_alloc, std::runtime_error) messages << "Movie rewound to beginning." << std::endl; } +void try_request_rom(const std::string& moviefile) +{ + auto sysreg_content = read_file_relative(moviefile + "/gametype", ""); + std::string sysreg_name(sysreg_content.begin(), sysreg_content.end()); + size_t ptr = sysreg_name.find_first_of("\r\n"); + if(ptr < sysreg_name.size()) + sysreg_name = sysreg_name.substr(0, ptr); + core_sysregion* sysreg; + try { + sysreg = &core_sysregion::lookup(sysreg_name); + } catch(...) { + throw std::runtime_error("The movie is for unsupported system type"); + } + std::string rname = graphics_plugin::request_rom(sysreg->get_type()); + if(rname == "") + throw std::runtime_error("Canceled loading ROM"); + loaded_rom newrom(rname); + *our_rom = newrom; +} + //Load state from loaded movie file (does not catch errors). void do_load_state(struct moviefile& _movie, int lmode) { @@ -510,6 +541,8 @@ bool do_load_state(const std::string& filename, int lmode) lua_callback_pre_load(filename2); struct moviefile mfile; try { + if(!core_rom_loaded()) + try_request_rom(filename2); mfile = moviefile(filename2); } catch(std::bad_alloc& e) { OOM_panic(); diff --git a/src/dummy/graphics.cpp b/src/dummy/graphics.cpp index 28dc5588..2f6764c5 100644 --- a/src/dummy/graphics.cpp +++ b/src/dummy/graphics.cpp @@ -49,4 +49,9 @@ void graphics_plugin::fatal_error() throw() std::cerr << "Exiting on fatal error." << std::endl; } +std::string graphics_plugin::request_rom(core_type& coretype) +{ + throw std::runtime_error("Headless does not support ROM preloading"); +} + const char* graphics_plugin::name = "Dummy graphics plugin"; diff --git a/src/platform/sdl/graphicsfn.cpp b/src/platform/sdl/graphicsfn.cpp index b28d292b..10695460 100644 --- a/src/platform/sdl/graphicsfn.cpp +++ b/src/platform/sdl/graphicsfn.cpp @@ -613,4 +613,10 @@ void graphics_plugin::fatal_error() throw() } } +std::string graphics_plugin::request_rom(core_type& coretype) +{ + throw std::runtime_error("SDL version does not support ROM preloading"); +} + + const char* graphics_plugin::name = "SDL graphics plugin"; diff --git a/src/platform/wxwidgets/main.cpp b/src/platform/wxwidgets/main.cpp index 77920394..1245ac4d 100644 --- a/src/platform/wxwidgets/main.cpp +++ b/src/platform/wxwidgets/main.cpp @@ -16,6 +16,7 @@ #include "core/rrdata.hpp" #include "core/settings.hpp" #include "core/window.hpp" +#include "library/workthread.hpp" #include "library/string.hpp" #include "library/zip.hpp" @@ -533,6 +534,30 @@ void graphics_plugin::fatal_error() throw() } } +std::string graphics_plugin::request_rom(core_type& coretype) +{ + core_type* ctype = &coretype; + std::string outname; + mutex_class lock; + cv_class cv; + bool done = false; + umutex_class h(lock); + runuifun([ctype, &outname, &lock, &cv, &done]() -> void { + if(done) + return; + try { + main_window->request_rom(outname, *ctype); + } catch(...) { + } + umutex_class h(lock); + done = true; + cv.notify_all(); + }); + while(!done) + cv.wait(h); + return outname; +} + void _runuifun_async(void (*fn)(void*), void* arg) { mutex::holder h(*ui_mutex); diff --git a/src/platform/wxwidgets/mainwindow.cpp b/src/platform/wxwidgets/mainwindow.cpp index 48b687c3..8f0350a8 100644 --- a/src/platform/wxwidgets/mainwindow.cpp +++ b/src/platform/wxwidgets/mainwindow.cpp @@ -107,7 +107,8 @@ enum wxID_RROM_FIRST, wxID_RROM_LAST = wxID_RROM_FIRST + 16, wxID_VUDISPLAY, - wxID_MOVIE_EDIT + wxID_MOVIE_EDIT, + wxID_CLOSE_ROM }; @@ -867,6 +868,9 @@ wxwin_mainwindow::wxwin_mainwindow() menu_entry(wxID_SAVE_SUBTITLES, wxT("Subtitles...")); menu_entry(wxID_CANCEL_SAVES, wxT("Cancel pending saves")); menu_end_sub(); + menu_start_sub(wxT("Close")); + menu_entry(wxID_CLOSE_ROM, wxT("ROM")); + menu_end_sub(); menu_separator(); menu_entry(wxID_EXIT, wxT("Quit")); @@ -996,6 +1000,28 @@ void wxwin_mainwindow::notify_exit() throw() Destroy(); } +void wxwin_mainwindow::request_rom(std::string& filename, core_type& coretype) +{ + const std::list& exts = coretype.get_extensions(); + std::string filter = coretype.get_hname() + " ROMs|"; + bool first = true; + for(auto i : exts) { + if(!first) + filter = filter + ";"; + first = false; + filter = filter + "*." + i; + } + filter = filter + "|All files|*.*"; + wxFileDialog* fdiag = new wxFileDialog(this, wxT("Load ROM"), towxstring(rom_path()), "", towxstring(filter), + wxFD_OPEN); + if(fdiag->ShowModal() != wxID_OK) { + delete fdiag; + return; + } + filename = fdiag->GetPath(); + delete fdiag; +} + #define NEW_KEYBINDING "A new binding..." #define NEW_ALIAS "A new alias..." #define NEW_WATCH "A new watch..." @@ -1300,5 +1326,8 @@ void wxwin_mainwindow::handle_menu_click_cancelable(wxCommandEvent& e) case wxID_MOVIE_EDIT: wxeditor_movie_display(this); return; + case wxID_CLOSE_ROM: + platform::queue("close-rom"); + return; }; }