Better background game loader

Pass LoadProgress object to report load progress and cancel
Better UI
Cancel with exception
Fix issues when stopping/exiting in !threaded
dx9: call gui_term on shutdown
This commit is contained in:
Flyinghead 2021-10-02 11:30:40 +02:00
parent c1bcf91dd6
commit 5bcfa35737
25 changed files with 192 additions and 182 deletions

View File

@ -37,9 +37,9 @@
#include "network/ggpo.h"
#include "hw/mem/mem_watch.h"
#include "network/net_handshake.h"
#include "rend/gui.h"
#include <chrono>
std::atomic<bool> loading_canceled;
settings_t settings;
static void loadSpecialSettings()
@ -396,7 +396,7 @@ static int getGamePlatform(const char *path)
return DC_PLATFORM_DREAMCAST;
}
void Emulator::loadGame(const char *path)
void Emulator::loadGame(const char *path, LoadProgress *progress)
{
init();
try {
@ -458,9 +458,7 @@ void Emulator::loadGame(const char *path)
else if (settings.platform.system == DC_PLATFORM_NAOMI || settings.platform.system == DC_PLATFORM_ATOMISWAVE)
{
LoadRomFiles();
naomi_cart_LoadRom(path);
if (loading_canceled)
return;
naomi_cart_LoadRom(path, progress);
loadGameSpecificSettings();
// Reload the BIOS in case a game-specific region is set
naomi_cart_LoadBios(path);
@ -641,7 +639,8 @@ bool dc_loadstate(const void **data, u32 size)
void Emulator::setNetworkState(bool online)
{
DEBUG_LOG(NETWORK, "Network state %d", online);
if (settings.online != online)
DEBUG_LOG(NETWORK, "Network state %d", online);
settings.online = online;
settings.input.fastForwardMode &= !online;
}

View File

@ -25,25 +25,19 @@
#include <vector>
#include <future>
#include <string>
#include <memory>
void loadGameSpecificSettings();
void SaveSettings();
extern std::atomic<bool> loading_canceled;
int flycast_init(int argc, char* argv[]);
void dc_reset(bool hard);
void dc_term();
void flycast_term();
void dc_exit();
void dc_savestate(int index = 0);
void dc_loadstate(int index = 0);
bool dc_loadstate(const void **data, unsigned size);
void dc_load_game(const std::string& path);
bool dc_is_load_done();
void dc_cancel_load();
void dc_get_load_status();
enum class Event {
Start,
Pause,
@ -80,6 +74,19 @@ private:
std::map<Event, std::vector<Callback>> callbacks;
};
struct LoadProgress
{
void reset()
{
cancelled = false;
label = nullptr;
progress = 0.f;
}
std::atomic<bool> cancelled;
std::atomic<const char *> label;
std::atomic<float> progress;
};
class Emulator
{
public:
@ -96,7 +103,7 @@ public:
* May throw if the game cannot be loaded.
* If a game is already loaded, or the emulator is in the error state, unloadGame() must be called first.
*/
void loadGame(const char *path);
void loadGame(const char *path, LoadProgress *progress = nullptr);
/**
* Reset the emulator in order to load another game. After calling this method, only loadGame() and term() can be called.
* Does nothing if no game is loaded.

View File

@ -333,7 +333,7 @@ u16 AWCartridge::decrypt(u16 cipherText, u32 address, const u8 key)
}
void AWCartridge::Init()
void AWCartridge::Init(LoadProgress *progress)
{
mpr_offset = decrypt16(0x58/2) | (decrypt16(0x5a/2) << 16);
INFO_LOG(NAOMI, "AWCartridge::SetKey rombd_key %02x mpr_offset %08x", rombd_key, mpr_offset);

View File

@ -19,7 +19,7 @@ class AWCartridge: public Cartridge
public:
AWCartridge(u32 size) : Cartridge(size) {}
void Init() override;
void Init(LoadProgress *progress = nullptr) override;
u32 ReadMem(u32 address, u32 size) override;
void WriteMem(u32 address, u32 data, u32 size) override;

View File

@ -13,7 +13,6 @@
#include "gdcartridge.h"
#include "stdclass.h"
#include "emulator.h"
#include "rend/gui.h"
/*
@ -436,12 +435,12 @@ void GDCartridge::find_file(const char *name, const u8 *dir_sector, u32 &file_st
}
}
void GDCartridge::read_gdrom(Disc *gdrom, u32 sector, u8* dst, u32 count)
void GDCartridge::read_gdrom(Disc *gdrom, u32 sector, u8* dst, u32 count, LoadProgress *progress)
{
gdrom->ReadSectors(sector + 150, count, dst, 2048);
gdrom->ReadSectors(sector + 150, count, dst, 2048, progress);
}
void GDCartridge::device_start()
void GDCartridge::device_start(LoadProgress *progress)
{
if (dimm_data != NULL)
{
@ -494,15 +493,15 @@ void GDCartridge::device_start()
u8 buffer[2048];
std::string gdrom_path = get_game_basename() + "/" + gdrom_name;
Disc *gdrom = OpenDisc(gdrom_path + ".chd");
std::unique_ptr<Disc> gdrom = std::unique_ptr<Disc>(OpenDisc(gdrom_path + ".chd"));
if (gdrom == nullptr)
gdrom = OpenDisc(gdrom_path + ".gdi");
gdrom = std::unique_ptr<Disc>(OpenDisc(gdrom_path + ".gdi"));
if (gdrom_parent_name != nullptr && gdrom == nullptr)
{
std::string gdrom_parent_path = get_game_dir() + "/" + gdrom_parent_name + "/" + gdrom_name;
gdrom = OpenDisc(gdrom_parent_path + ".chd");
gdrom = std::unique_ptr<Disc>(OpenDisc(gdrom_parent_path + ".chd"));
if (gdrom == nullptr)
gdrom = OpenDisc(gdrom_parent_path + ".gdi");
gdrom = std::unique_ptr<Disc>(OpenDisc(gdrom_parent_path + ".gdi"));
}
if (gdrom == nullptr)
throw NaomiCartException("Naomi GDROM: Cannot open " + gdrom_path + ".chd or " + gdrom_path + ".gdi");
@ -510,13 +509,13 @@ void GDCartridge::device_start()
// primary volume descriptor
// read frame 0xb06e (frame=sector+150)
// dimm board firmware starts straight from this frame
read_gdrom(gdrom, (netpic ? 0 : 45000) + 16, buffer);
read_gdrom(gdrom.get(), (netpic ? 0 : 45000) + 16, buffer);
u32 path_table = ((buffer[0x8c+0] << 0) |
(buffer[0x8c+1] << 8) |
(buffer[0x8c+2] << 16) |
(buffer[0x8c+3] << 24));
// path table
read_gdrom(gdrom, path_table, buffer);
read_gdrom(gdrom.get(), path_table, buffer);
// directory
u8 dir_sector[2048];
@ -529,12 +528,12 @@ void GDCartridge::device_start()
(buffer[0x2 + 2] << 16) |
(buffer[0x2 + 3] << 24));
read_gdrom(gdrom, dir, dir_sector);
read_gdrom(gdrom.get(), dir, dir_sector);
find_file(name, dir_sector, file_start, file_size);
if (file_start && (file_size == 0x100)) {
// read file
read_gdrom(gdrom, file_start, buffer);
read_gdrom(gdrom.get(), file_start, buffer);
// get "rom" file name
memset(name, '\0', 128);
memcpy(name, buffer + 0xc0, FILENAME_LENGTH - 1);
@ -550,7 +549,7 @@ void GDCartridge::device_start()
(buffer[i + 4] << 16) |
(buffer[i + 5] << 24));
memcpy(name, "ROM.BIN", 7);
read_gdrom(gdrom, dir, dir_sector);
read_gdrom(gdrom.get(), dir, dir_sector);
break;
}
i += buffer[i] + 8 + (buffer[i] & 1);
@ -570,31 +569,25 @@ void GDCartridge::device_start()
// read encrypted data into dimm_data
u32 sectors = file_rounded_size / 2048;
read_gdrom(gdrom, file_start, dimm_data, sectors);
read_gdrom(gdrom.get(), file_start, dimm_data, sectors, progress);
// decrypt loaded data
u32 des_subkeys[32];
des_generate_subkeys(rev64(key), des_subkeys);
u32 progress = ~0;
for (u32 i = 0; i < file_rounded_size; i += 8)
{
const u32 new_progress = (u32)(((u64)i + 8) * 100 / file_rounded_size);
if (progress != new_progress)
if (progress != nullptr)
{
if (loading_canceled)
break;
progress = new_progress;
char status_str[16];
sprintf(status_str, "Decrypting %d%%", progress);
gui_display_notification(status_str, 2000);
if (progress->cancelled)
throw LoadCancelledException();
progress->label = "Decrypting...";
progress->progress = (float)(i + 8) / file_rounded_size;
}
*(u64 *)(dimm_data + i) = des_encrypt_decrypt<true>(*(u64 *)(dimm_data + i), des_subkeys);
}
}
delete gdrom;
if (!dimm_data)
throw NaomiCartException("Naomi GDROM: Could not find the file to decrypt.");
}

View File

@ -25,9 +25,9 @@ public:
{
free(dimm_data);
}
void Init() override
void Init(LoadProgress *progress = nullptr) override
{
device_start();
device_start(progress);
device_reset();
}
void* GetDmaPtr(u32 &size) override;
@ -61,7 +61,7 @@ private:
static const u32 DES_MASK_TABLE[];
static const u8 DES_ROTATE_TABLE[16];
void device_start();
void device_start(LoadProgress *progress);
void device_reset();
void find_file(const char *name, const u8 *dir_sector, u32 &file_start, u32 &file_size);
@ -70,7 +70,7 @@ private:
template<bool decrypt>
u64 des_encrypt_decrypt(u64 src, const u32 *des_subkeys);
u64 rev64(u64 src);
void read_gdrom(Disc *gdrom, u32 sector, u8* dst, u32 count = 1);
void read_gdrom(Disc *gdrom, u32 sector, u8* dst, u32 count = 1, LoadProgress *progress = nullptr);
};
#endif /* CORE_HW_NAOMI_GDCARTRIDGE_H_ */

View File

@ -20,7 +20,7 @@ public:
M4Cartridge(u32 size) : NaomiCartridge(size) { }
~M4Cartridge() override;
void Init() override
void Init(LoadProgress *progress = nullptr) override
{
device_start();
device_reset();

View File

@ -34,7 +34,6 @@
#include "archive/archive.h"
#include "stdclass.h"
#include "emulator.h"
#include "rend/gui.h"
#include "cfg/option.h"
#include "oslib/oslib.h"
@ -197,7 +196,7 @@ void naomi_cart_LoadBios(const char *filename)
bios_loaded = true;
}
static void naomi_cart_LoadZip(const char *filename)
static void naomi_cart_LoadZip(const char *filename, LoadProgress *progress)
{
Game *game = FindGame(filename);
if (game == NULL)
@ -257,12 +256,22 @@ static void naomi_cart_LoadZip(const char *filename)
CurrentCartridge->SetKey(game->key);
NaomiGameInputs = game->inputs;
for (int romid = 0; game->blobs[romid].filename != NULL && !loading_canceled; romid++)
int romCount = 0;
while (game->blobs[romCount].filename != nullptr)
romCount++;
for (int romid = 0; romid < romCount; romid++)
{
if (game->cart_type != GD)
if (progress != nullptr)
{
std::string progress = "ROM " + std::to_string(romid + 1);
gui_display_notification(progress.c_str(), 1000);
if (progress->cancelled)
throw LoadCancelledException();
if (game->cart_type != GD)
{
static std::string label;
label = "ROM " + std::to_string(romid + 1);
progress->label = label.c_str();
progress->progress = (float)(romid + 1) / romCount;
}
}
u32 len = game->blobs[romid].length;
@ -350,31 +359,26 @@ static void naomi_cart_LoadZip(const char *filename)
}
}
}
if (loading_canceled)
return;
if (naomi_default_eeprom == NULL && game->eeprom_dump != NULL)
naomi_default_eeprom = game->eeprom_dump;
if (game->rotation_flag == ROT270)
config::Rotate90.override(true);
CurrentCartridge->Init();
if (loading_canceled)
return;
CurrentCartridge->Init(progress);
strcpy(naomi_game_id, CurrentCartridge->GetGameId().c_str());
if (naomi_game_id[0] == '\0')
strcpy(naomi_game_id, game->name);
NOTICE_LOG(NAOMI, "NAOMI GAME ID [%s]", naomi_game_id);
} catch (const FlycastException& ex) {
} catch (...) {
delete CurrentCartridge;
CurrentCartridge = NULL;
throw ex;
throw;
}
}
void naomi_cart_LoadRom(const char* file)
void naomi_cart_LoadRom(const char* file, LoadProgress *progress)
{
naomi_cart_Close();
@ -382,7 +386,7 @@ void naomi_cart_LoadRom(const char* file)
if (extension == "zip" || extension == "7z")
{
naomi_cart_LoadZip(file);
naomi_cart_LoadZip(file, progress);
return;
}
@ -609,6 +613,11 @@ std::string Cartridge::GetGameId() {
}
while (!game_id.empty() && game_id.back() == ' ')
game_id.pop_back();
if (RomSize < 0x138)
printf("GAME EEPROM ID: (ROM too small)\n");
else
printf("GAME EEPROM ID: %c%c%c%c\n", RomPtr[0x134], RomPtr[0x135], RomPtr[0x136], RomPtr[0x137]);
return game_id;
}
@ -918,6 +927,10 @@ std::string M2Cartridge::GetGameId()
game_id = std::string((char *)RomPtr + 0x800030, 0x20);
while (!game_id.empty() && game_id.back() == ' ')
game_id.pop_back();
if (RomSize < 0x800138)
printf("m2 GAME EEPROM ID: (ROM too small)\n");
else
printf("m2 GAME EEPROM ID: %c%c%c%c\n", RomPtr[0x800134], RomPtr[0x800135], RomPtr[0x800136], RomPtr[0x800137]);
}
return game_id;
}

View File

@ -3,6 +3,7 @@
#include <algorithm>
#include <string>
#include "types.h"
#include "emulator.h"
class Cartridge
{
@ -10,7 +11,7 @@ public:
Cartridge(u32 size);
virtual ~Cartridge();
virtual void Init() {}
virtual void Init(LoadProgress *progress = nullptr) {}
virtual u32 ReadMem(u32 address, u32 size) = 0;
virtual void WriteMem(u32 address, u32 data, u32 size) = 0;
@ -83,7 +84,7 @@ public:
NaomiCartException(const std::string& reason) : FlycastException(reason) {}
};
void naomi_cart_LoadRom(const char* file);
void naomi_cart_LoadRom(const char* file, LoadProgress *progress);
void naomi_cart_Close();
int naomi_cart_GetPlatform(const char *path);
void naomi_cart_LoadBios(const char *filename);

View File

@ -275,28 +275,20 @@ DiscType GuessDiscType(bool m1, bool m2, bool da)
return CdRom;
}
void Disc::ReadSectors(u32 FAD, u32 count, u8* dst, u32 fmt)
void Disc::ReadSectors(u32 FAD, u32 count, u8* dst, u32 fmt, LoadProgress *progress)
{
u8 temp[2448];
SectorFormat secfmt;
SubcodeFormat subfmt;
u32 progress = ~0;
for (u32 i = 1; i <= count; i++)
{
if (count >= 1000)
if (progress != nullptr)
{
if (loading_canceled)
break;
// Progress report when loading naomi gd-rom games
const u32 new_progress = i * 100 / count;
if (progress != new_progress)
{
progress = new_progress;
char status_str[16];
sprintf(status_str, "%d%%", progress);
gui_display_notification(status_str, 2000);
}
if (progress->cancelled)
throw LoadCancelledException();
progress->label = "Loading...";
progress->progress = (float)i / count;
}
if (ReadSector(FAD,temp,&secfmt,q_subchannel,&subfmt))
{

View File

@ -4,7 +4,6 @@
#include "emulator.h"
#include "hw/gdrom/gdrom_if.h"
#include "rend/gui.h"
/*
Mode2 Subheader:
@ -119,7 +118,7 @@ struct Disc
return false;
}
void ReadSectors(u32 FAD,u32 count,u8* dst,u32 fmt);
void ReadSectors(u32 FAD, u32 count, u8 *dst, u32 fmt, LoadProgress *progress = nullptr);
virtual ~Disc()
{

View File

@ -391,7 +391,7 @@ int main(int argc, char* argv[])
mainui_loop();
emu.term();
flycast_term();
os_UninstallFaultHandler();

View File

@ -1,7 +1,5 @@
#ifndef LIBRETRO
#include "types.h"
#include <future>
#include "emulator.h"
#include "hw/mem/_vmem.h"
#include "cfg/cfg.h"
@ -9,14 +7,11 @@
#include "log/LogManager.h"
#include "rend/gui.h"
#include "oslib/oslib.h"
#include "hw/sh4/sh4_if.h"
#include "debug/gdb_server.h"
#include "archive/rzip.h"
#include "rend/mainui.h"
#include "input/gamepad_device.h"
static std::future<void> loadingDone;
int flycast_init(int argc, char* argv[])
{
#if defined(TEST_AUTOMATION)
@ -58,7 +53,7 @@ int flycast_init(int argc, char* argv[])
void dc_exit()
{
emu.term();
emu.stop();
mainui_stop();
}
@ -73,11 +68,10 @@ void SaveSettings()
#endif
}
void dc_term()
void flycast_term()
{
dc_cancel_load();
gui_cancel_load();
emu.term();
SaveSettings();
}
void dc_savestate(int index)
@ -215,38 +209,4 @@ void dc_loadstate(int index)
INFO_LOG(SAVESTATE, "Loaded state from %s size %d", filename.c_str(), total_size) ;
}
void dc_load_game(const std::string& path)
{
loading_canceled = false;
loadingDone = std::async(std::launch::async, [path] {
emu.loadGame(path.c_str());
});
}
bool dc_is_load_done()
{
if (!loadingDone.valid())
return true;
if (loadingDone.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready)
return true;
return false;
}
void dc_cancel_load()
{
if (loadingDone.valid())
{
loading_canceled = true;
loadingDone.get();
}
settings.content.path.clear();
}
void dc_get_load_status()
{
if (loadingDone.valid())
loadingDone.get();
}
#endif

View File

@ -63,6 +63,7 @@ bool DXContext::Init(bool keepCurrentWindow)
void DXContext::Term()
{
overlay.term();
gui_term();
ImGui_ImplDX9_Shutdown();
pDevice.reset();
pD3D.reset();

View File

@ -69,6 +69,7 @@ static void term_vmus();
static void displayCrosshairs();
GameScanner scanner;
static BackgroundGameLoader gameLoader;
static void emuEventCallback(Event event)
{
@ -409,7 +410,7 @@ void gui_open_settings()
}
else if (gui_state == GuiState::Loading)
{
dc_cancel_load();
gameLoader.cancel();
gui_state = GuiState::Main;
}
else if (gui_state == GuiState::Commands)
@ -427,7 +428,7 @@ void gui_start_game(const std::string& path)
scanner.stop();
gui_state = GuiState::Loading;
dc_load_game(path);
gameLoader.load(path);
}
void gui_stop_game(const std::string& message)
@ -2076,10 +2077,7 @@ static void gui_display_content()
ImGui::PushID("bios");
if (ImGui::Selectable("Dreamcast BIOS"))
{
gui_state = GuiState::Closed;
gui_start_game("");
}
ImGui::PopID();
{
@ -2113,7 +2111,6 @@ static void gui_display_content()
{
std::string gamePath(game.path);
scanner.get_mutex().unlock();
gui_state = GuiState::Closed;
gui_start_game(gamePath);
scanner.get_mutex().lock();
ImGui::PopID();
@ -2197,7 +2194,7 @@ static void gui_network_start()
if (networkStatus.get())
{
gui_state = GuiState::Closed;
ImGui::Text("STARTING...");
ImGui::Text("Starting...");
}
else
{
@ -2213,7 +2210,7 @@ static void gui_network_start()
}
else
{
ImGui::Text("STARTING NETWORK...");
ImGui::Text("Starting Network...");
if (NetworkHandshake::instance->canStartNow())
ImGui::Text("Press Start to start the game now.");
}
@ -2250,10 +2247,9 @@ static void gui_display_loadscreen()
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 10 * scaling));
ImGui::AlignTextToFramePadding();
ImGui::SetCursorPosX(20.f * scaling);
if (dc_is_load_done())
{
try {
dc_get_load_status();
try {
if (gameLoader.ready())
{
if (NetworkHandshake::instance != nullptr)
{
networkStatus = NetworkHandshake::instance->start();
@ -2262,32 +2258,36 @@ static void gui_display_loadscreen()
else
{
gui_state = GuiState::Closed;
ImGui::Text("STARTING...");
ImGui::Text("Starting...");
}
} catch (const FlycastException& ex) {
ERROR_LOG(BOOT, "%s", ex.what());
error_msg = ex.what();
#ifdef TEST_AUTOMATION
die("Game load failed");
#endif
emu.unloadGame();
gui_state = GuiState::Main;
}
}
else
{
ImGui::Text("LOADING... ");
ImGui::SameLine();
ImGui::Text("%s", get_notification().c_str());
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * scaling);
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
else
{
dc_cancel_load();
gui_state = GuiState::Main;
const char *label = gameLoader.getProgress().label;
if (label == nullptr)
label = "Loading...";
ImGui::Text("%s", label);
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, ImVec4(0.557f, 0.268f, 0.965f, 1.f));
ImGui::ProgressBar(gameLoader.getProgress().progress, ImVec2(-1, 20.f * scaling), "");
ImGui::PopStyleColor();
float currentwidth = ImGui::GetContentRegionAvail().x;
ImGui::SetCursorPosX((currentwidth - 100.f * scaling) / 2.f + ImGui::GetStyle().WindowPadding.x);
ImGui::SetCursorPosY(126.f * scaling);
if (ImGui::Button("Cancel", ImVec2(100.f * scaling, 0.f)))
{
gameLoader.cancel();
gui_state = GuiState::Main;
}
}
} catch (const FlycastException& ex) {
ERROR_LOG(BOOT, "%s", ex.what());
error_msg = ex.what();
#ifdef TEST_AUTOMATION
die("Game load failed");
#endif
emu.unloadGame();
gui_state = GuiState::Main;
}
ImGui::PopStyleVar();
@ -2426,6 +2426,11 @@ void gui_open_onboarding()
gui_state = GuiState::Onboarding;
}
void gui_cancel_load()
{
gameLoader.cancel();
}
void gui_term()
{
if (inited)
@ -2436,6 +2441,8 @@ void gui_term()
ImGui_ImplOpenGL3_Shutdown();
ImGui::DestroyContext();
EventManager::unlisten(Event::Resume, emuEventCallback);
EventManager::unlisten(Event::Start, emuEventCallback);
EventManager::unlisten(Event::Terminate, emuEventCallback);
}
}

View File

@ -27,6 +27,7 @@ void gui_display_notification(const char *msg, int duration);
void gui_display_osd();
void gui_open_onboarding();
void gui_term();
void gui_cancel_load();
void gui_refresh_files();
void gui_cheats();
void gui_keyboard_input(u16 wc);

View File

@ -27,6 +27,7 @@
#include "vulkan/vulkan_context.h"
#include "dx9/dxcontext.h"
#include "gui.h"
#include "emulator.h"
typedef void (*StringCallback)(bool cancelled, std::string selection);
@ -82,3 +83,46 @@ static inline bool operator!=(const ImVec2& l, const ImVec2& r)
void fullScreenWindow(bool modal);
void windowDragScroll();
class BackgroundGameLoader
{
public:
void load(const std::string& path)
{
progress.reset();
future = std::async(std::launch::async, [this, path] {
emu.loadGame(path.c_str(), &progress);
});
}
void cancel()
{
progress.cancelled = true;
if (future.valid())
try {
future.get();
} catch (const FlycastException& e) {
}
emu.unloadGame();
}
bool ready()
{
if (!future.valid())
return true;
if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready)
{
future.get();
return true;
}
return false;
}
const LoadProgress& getProgress() const {
return progress;
}
private:
LoadProgress progress;
std::future<void> future;
};

View File

@ -453,6 +453,12 @@ public:
FlycastException(const std::string& reason) : std::runtime_error(reason) {}
};
class LoadCancelledException : public FlycastException
{
public:
LoadCancelledException() : FlycastException("") {}
};
enum serialize_version_enum {
V1,
V2,

View File

@ -758,7 +758,7 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi
mainui_loop();
emu.term();
flycast_term();
os_UninstallFaultHandler();

View File

@ -88,7 +88,7 @@ static bool emulatorRunning;
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
dc_term();
flycast_term();
LogManager::Shutdown();
}

View File

@ -24,7 +24,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
func applicationWillTerminate(_ aNotification: Notification) {
emu_dc_term()
emu_flycast_term()
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {

View File

@ -71,7 +71,7 @@ class EmuGLView: NSOpenGLView, NSWindowDelegate {
let rect = convertToBacking(frame)
emu_gles_init(Int32(rect.width), Int32(rect.height))
if (emu_reicast_init() != 0) {
if (emu_flycast_init() != 0) {
let alert = NSAlert()
alert.alertStyle = .critical
alert.messageText = "Flycast initialization failed"

View File

@ -14,15 +14,14 @@
extern "C" {
#endif
void emu_dc_exit();
void emu_dc_term();
void emu_flycast_term();
void emu_gui_open_settings();
bool emu_renderer_enabled();
bool emu_fast_forward();
bool emu_vsync_enabled();
bool emu_single_frame(int w, int h);
void emu_gles_init(int width, int height);
int emu_reicast_init();
int emu_flycast_init();
void emu_key_input(UInt16 keyCode, bool pressed, UInt32 modifierFlags);
void emu_character_input(const char *characters);
void emu_mouse_buttons(int button, bool pressed);

View File

@ -90,16 +90,9 @@ void os_SetupInput()
void common_linux_setup();
void emu_dc_exit()
void emu_flycast_term()
{
dc_exit();
}
void emu_dc_term()
{
if (emu.running())
dc_exit();
dc_term();
flycast_term();
LogManager::Shutdown();
}
@ -238,7 +231,7 @@ void emu_gles_init(int width, int height)
mainui_enabled = true;
}
int emu_reicast_init()
int emu_flycast_init()
{
LogManager::Init();
common_linux_setup();

View File

@ -125,7 +125,6 @@ static double vib_delta[4];
unsigned per_content_vmus = 0;
static bool first_run = true;
static bool mute_messages;
static bool rotate_screen;
static bool rotate_game;
static int framebufferWidth;
@ -151,6 +150,7 @@ static void refresh_devices(bool first_startup);
static void init_disk_control_interface();
static bool read_m3u(const char *file);
void UpdateInputState();
void gui_display_notification(const char *msg, int duration);
static std::string game_data;
static char g_base_name[128];
@ -867,16 +867,13 @@ void retro_run()
static bool loadGame()
{
mute_messages = true;
try {
emu.loadGame(game_data.c_str());
} catch (const FlycastException& e) {
ERROR_LOG(BOOT, "%s", e.what());
mute_messages = false;
gui_display_notification(e.what(), 5000);
return false;
}
mute_messages = false;
return true;
}
@ -2923,8 +2920,6 @@ static bool read_m3u(const char *file)
void gui_display_notification(const char *msg, int duration)
{
if (mute_messages)
return;
retro_message retromsg;
retromsg.msg = msg;
retromsg.frames = duration / 17;