Use exception when load content fails. ui: graceful stop on fatal error
libretro: catch/detect fatal errors and shutdown
This commit is contained in:
parent
2dd7717128
commit
951e70328f
|
@ -13,7 +13,7 @@ TA_context* read_frame(const char* file, u8* vram_ref = NULL);
|
|||
void rend_set_fb_scale(float x,float y);
|
||||
|
||||
#ifdef TARGET_DISPFRAME
|
||||
void *dc_run(void*)
|
||||
void dc_run()
|
||||
{
|
||||
struct sigaction act, segv_oact;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
@ -58,6 +58,5 @@ void *dc_run(void*)
|
|||
|
||||
os_DoEvents();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -42,8 +42,10 @@ extern int screen_width, screen_height;
|
|||
std::atomic<bool> loading_canceled;
|
||||
settings_t settings;
|
||||
|
||||
static cThread emuThread(&dc_run, nullptr);
|
||||
static void *dc_run_thread(void *);
|
||||
static cThread emuThread(&dc_run_thread, nullptr);
|
||||
static bool initDone;
|
||||
static std::string lastError;
|
||||
|
||||
static s32 devicesInit()
|
||||
{
|
||||
|
@ -521,11 +523,27 @@ bool dc_is_running()
|
|||
return sh4_cpu.IsCpuRunning();
|
||||
}
|
||||
|
||||
#ifndef TARGET_DISPFRAME
|
||||
void* dc_run(void*)
|
||||
static void *dc_run_thread(void*)
|
||||
{
|
||||
InitAudio();
|
||||
|
||||
try {
|
||||
dc_run();
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(COMMON, "%s", e.what());
|
||||
sh4_cpu.Stop();
|
||||
lastError = e.what();
|
||||
}
|
||||
|
||||
TermAudio();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifndef TARGET_DISPFRAME
|
||||
|
||||
void dc_run()
|
||||
{
|
||||
#if FEAT_SHREC != DYNAREC_NONE
|
||||
if (config::DynarecEnabled)
|
||||
{
|
||||
|
@ -557,10 +575,6 @@ void* dc_run(void*)
|
|||
}
|
||||
} while (resetRequested);
|
||||
}
|
||||
|
||||
TermAudio();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -583,8 +597,6 @@ void dc_term_emulator()
|
|||
dc_term_game();
|
||||
debugger::term();
|
||||
sh4_cpu.Term();
|
||||
if (settings.platform.system != DC_PLATFORM_DREAMCAST)
|
||||
naomi_cart_Close();
|
||||
custom_texture.Terminate(); // lr: avoid deadlock on exit (win32)
|
||||
devicesTerm();
|
||||
mem_Term();
|
||||
|
@ -711,6 +723,13 @@ bool dc_loadstate(const void **data, u32 size)
|
|||
return true;
|
||||
}
|
||||
|
||||
std::string dc_get_last_error()
|
||||
{
|
||||
std::string error(lastError);
|
||||
lastError.clear();
|
||||
return error;
|
||||
}
|
||||
|
||||
EventManager EventManager::Instance;
|
||||
|
||||
void EventManager::registerEvent(Event event, Callback callback)
|
||||
|
|
|
@ -31,7 +31,7 @@ extern std::atomic<bool> loading_canceled;
|
|||
int flycast_init(int argc, char* argv[]);
|
||||
void dc_reset(bool hard);
|
||||
void dc_init();
|
||||
void* dc_run(void*);
|
||||
void dc_run();
|
||||
void dc_term();
|
||||
void dc_stop();
|
||||
void dc_term_game();
|
||||
|
@ -50,6 +50,7 @@ void dc_cancel_load();
|
|||
void dc_get_load_status();
|
||||
bool dc_is_running();
|
||||
void dc_resize_renderer();
|
||||
std::string dc_get_last_error();
|
||||
|
||||
enum class Event {
|
||||
Start,
|
||||
|
|
|
@ -1,25 +1,24 @@
|
|||
#include "common.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
#include "deps/chdpsr/cdipsr.h"
|
||||
|
||||
Disc* cdi_parse(const char* file)
|
||||
{
|
||||
// Only try to open .cdi files
|
||||
size_t len = strlen(file);
|
||||
if (len > 4 && stricmp( &file[len - 4], ".cdi"))
|
||||
if (get_file_extension(file) != "cdi")
|
||||
return nullptr;
|
||||
|
||||
FILE *fsource = nowide::fopen(file, "rb");
|
||||
|
||||
if (!fsource)
|
||||
return nullptr;
|
||||
if (fsource == nullptr)
|
||||
throw FlycastException(std::string("Cannot open CDI file ") + file);
|
||||
|
||||
image_s image = { 0 };
|
||||
track_s track = { 0 };
|
||||
if (!CDI_init(fsource, &image, file))
|
||||
{
|
||||
std::fclose(fsource);
|
||||
return nullptr;
|
||||
throw FlycastException(std::string("Invalid CDI file ") + file);
|
||||
}
|
||||
|
||||
CDI_get_sessions(fsource,&image);
|
||||
|
@ -41,8 +40,6 @@ Disc* cdi_parse(const char* file)
|
|||
|
||||
image.header_position = std::ftell(fsource);
|
||||
|
||||
//printf("\nSession %d has %d track(s)\n",image.global_current_session,image.tracks);
|
||||
|
||||
if (image.tracks == 0)
|
||||
INFO_LOG(GDROM, "Open session");
|
||||
else
|
||||
|
@ -96,8 +93,6 @@ Disc* cdi_parse(const char* file)
|
|||
if (track.mode==0)
|
||||
CD_DA=true;
|
||||
|
||||
|
||||
|
||||
t.ADDR=1;//hmm is that ok ?
|
||||
|
||||
t.CTRL=track.mode==0?0:4;
|
||||
|
@ -107,55 +102,30 @@ Disc* cdi_parse(const char* file)
|
|||
|
||||
rv->tracks.push_back(t);
|
||||
|
||||
//printf("\n");
|
||||
|
||||
// if (track.pregap_length != 150) printf("Warning! This track seems to have a non-standard pregap...\n");
|
||||
|
||||
if (track.length < 0)
|
||||
WARN_LOG(GDROM, "Negative track size found. You must extract image with /pregap option");
|
||||
|
||||
//if (!opts.showinfo)
|
||||
std::fseek(fsource, track.position, SEEK_SET);
|
||||
if (track.total_length < track.length + track.pregap_length)
|
||||
{
|
||||
if (track.total_length < track.length + track.pregap_length)
|
||||
{
|
||||
WARN_LOG(GDROM, "This track seems truncated. Skipping...");
|
||||
std::fseek(fsource, track.position, SEEK_SET);
|
||||
std::fseek(fsource, track.total_length, SEEK_CUR);
|
||||
track.position = std::ftell(fsource);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//printf("Track position: %lu\n",track.position + track.pregap_length * track.sector_size);
|
||||
std::fseek(fsource, track.position, SEEK_SET);
|
||||
// fseek(fsource, track->pregap_length * track->sector_size, SEEK_CUR);
|
||||
// fseek(fsource, track->length * track->sector_size, SEEK_CUR);
|
||||
std::fseek(fsource, track.total_length * track.sector_size, SEEK_CUR);
|
||||
|
||||
//savetrack(fsource, &image, &track, &opts, &flags);
|
||||
track.position = std::ftell(fsource);
|
||||
|
||||
rv->EndFAD=track.start_lba +track.total_length;
|
||||
// Generate cuesheet entries
|
||||
|
||||
//if (flags.create_cuesheet && !(track.mode == 2 && flags.do_convert)) // Do not generate input if converted (obsolete)
|
||||
// savecuesheet(fcuesheet, &image, &track, &opts, &flags);
|
||||
|
||||
}
|
||||
WARN_LOG(GDROM, "This track seems truncated. Skipping...");
|
||||
// FIXME that can't be right
|
||||
std::fseek(fsource, track.total_length, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fseek(fsource, track.total_length * track.sector_size, SEEK_CUR);
|
||||
rv->EndFAD=track.start_lba +track.total_length;
|
||||
}
|
||||
track.position = std::ftell(fsource);
|
||||
|
||||
std::fseek(fsource, image.header_position, SEEK_SET);
|
||||
|
||||
|
||||
// Close loops
|
||||
|
||||
image.remaining_tracks--;
|
||||
}
|
||||
|
||||
//if (flags.create_cuesheet) fclose(fcuesheet);
|
||||
}
|
||||
|
||||
CDI_skip_next_session (fsource, &image);
|
||||
CDI_skip_next_session(fsource, &image);
|
||||
|
||||
image.remaining_sessions--;
|
||||
}
|
||||
|
@ -167,8 +137,6 @@ Disc* cdi_parse(const char* file)
|
|||
rv->LeadOut.ADDR=0;
|
||||
rv->LeadOut.CTRL=0;
|
||||
|
||||
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include "common.h"
|
||||
#include "stdclass.h"
|
||||
|
||||
#include <libchdr/chd.h>
|
||||
|
||||
/* tracks are padded to a multiple of this many frames */
|
||||
const uint32_t CD_TRACK_PADDING = 4;
|
||||
constexpr uint32_t CD_TRACK_PADDING = 4;
|
||||
|
||||
struct CHDDisc : Disc
|
||||
{
|
||||
|
@ -15,7 +16,7 @@ struct CHDDisc : Disc
|
|||
u32 hunkbytes = 0;
|
||||
u32 sph = 0;
|
||||
|
||||
bool TryOpen(const char* file);
|
||||
void tryOpen(const char* file);
|
||||
|
||||
~CHDDisc() override
|
||||
{
|
||||
|
@ -38,20 +39,21 @@ struct CHDTrack : TrackFile
|
|||
|
||||
CHDTrack(CHDDisc* disc, u32 StartFAD, s32 Offset, u32 fmt, bool swap_bytes)
|
||||
{
|
||||
this->disc=disc;
|
||||
this->StartFAD=StartFAD;
|
||||
this->disc = disc;
|
||||
this->StartFAD = StartFAD;
|
||||
this->Offset = Offset;
|
||||
this->fmt=fmt;
|
||||
this->fmt = fmt;
|
||||
this->swap_bytes = swap_bytes;
|
||||
}
|
||||
|
||||
void Read(u32 FAD, u8* dst, SectorFormat* sector_type, u8* subcode, SubcodeFormat* subcode_type) override
|
||||
bool Read(u32 FAD, u8* dst, SectorFormat* sector_type, u8* subcode, SubcodeFormat* subcode_type) override
|
||||
{
|
||||
u32 fad_offs = FAD + Offset;
|
||||
u32 hunk=(fad_offs)/disc->sph;
|
||||
if (disc->old_hunk!=hunk)
|
||||
{
|
||||
chd_read(disc->chd,hunk,disc->hunk_mem); //CHDERR_NONE
|
||||
if (chd_read(disc->chd,hunk,disc->hunk_mem) != CHDERR_NONE)
|
||||
return false;
|
||||
disc->old_hunk = hunk;
|
||||
}
|
||||
|
||||
|
@ -73,24 +75,21 @@ struct CHDTrack : TrackFile
|
|||
//While space is reserved for it, the images contain no actual subcodes
|
||||
//memcpy(subcode,disc->hunk_mem+hunk_ofs*(2352+96)+2352,96);
|
||||
*subcode_type=SUBFMT_NONE;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
bool CHDDisc::TryOpen(const char* file)
|
||||
void CHDDisc::tryOpen(const char* file)
|
||||
{
|
||||
fp = nowide::fopen(file, "rb");
|
||||
if (fp == nullptr)
|
||||
{
|
||||
INFO_LOG(GDROM, "chd: fopen failed for file %s: %d", file, errno);
|
||||
return false;
|
||||
}
|
||||
throw FlycastException(std::string("Cannot open CHD file ") + file);
|
||||
|
||||
chd_error err = chd_open_file(fp, CHD_OPEN_READ, 0, &chd);
|
||||
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
INFO_LOG(GDROM, "chd: chd_open_file failed for file %s: %d", file, err);
|
||||
return false;
|
||||
}
|
||||
throw FlycastException(std::string("Invalid CHD file ") + file);
|
||||
|
||||
INFO_LOG(GDROM, "chd: parsing file %s", file);
|
||||
|
||||
|
@ -102,11 +101,8 @@ bool CHDDisc::TryOpen(const char* file)
|
|||
|
||||
sph = hunkbytes/(2352+96);
|
||||
|
||||
if (hunkbytes%(2352+96)!=0)
|
||||
{
|
||||
INFO_LOG(GDROM, "chd: hunkbytes is invalid, %d\n",hunkbytes);
|
||||
return false;
|
||||
}
|
||||
if (hunkbytes % (2352 + 96) != 0)
|
||||
throw FlycastException(std::string("Invalid hunkbytes for CHD file ") + file);
|
||||
|
||||
u32 tag;
|
||||
u8 flags;
|
||||
|
@ -156,15 +152,13 @@ bool CHDDisc::TryOpen(const char* file)
|
|||
|| pregap != 0
|
||||
|| postgap != 0)
|
||||
{
|
||||
INFO_LOG(GDROM, "chd: track type %s is not supported", type);
|
||||
return false;
|
||||
throw FlycastException((std::string("chd: track type ") + type) + " is not supported");
|
||||
}
|
||||
DEBUG_LOG(GDROM, "%s", temp);
|
||||
Track t;
|
||||
t.StartFAD = total_frames;
|
||||
total_frames += frames;
|
||||
t.EndFAD = total_frames - 1;
|
||||
t.ADDR = 0;
|
||||
t.CTRL = strcmp(type,"AUDIO") == 0 ? 0 : 4;
|
||||
|
||||
t.file = new CHDTrack(this, t.StartFAD, Offset - t.StartFAD, strcmp(type, "MODE1") ? 2352 : 2048,
|
||||
|
@ -182,25 +176,21 @@ bool CHDDisc::TryOpen(const char* file)
|
|||
WARN_LOG(GDROM, "WARNING: chd: Total frames is wrong: %u frames (549300 expected) in %zu tracks", total_frames, tracks.size());
|
||||
|
||||
FillGDSession();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Disc* chd_parse(const char* file)
|
||||
{
|
||||
// Only try to open .chd files
|
||||
size_t len = strlen(file);
|
||||
if (len > 4 && stricmp( &file[len - 4], ".chd"))
|
||||
if (get_file_extension(file) != "chd")
|
||||
return nullptr;
|
||||
|
||||
CHDDisc* rv = new CHDDisc();
|
||||
|
||||
if (rv->TryOpen(file))
|
||||
try {
|
||||
rv->tryOpen(file);
|
||||
return rv;
|
||||
else
|
||||
{
|
||||
} catch (...) {
|
||||
delete rv;
|
||||
return 0;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,37 +87,29 @@ struct Session
|
|||
|
||||
struct TrackFile
|
||||
{
|
||||
virtual void Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,SubcodeFormat* subcode_type)=0;
|
||||
virtual ~TrackFile() = default;;
|
||||
virtual bool Read(u32 FAD, u8 *dst, SectorFormat *sector_type, u8 *subcode, SubcodeFormat *subcode_type) = 0;
|
||||
virtual ~TrackFile() = default;
|
||||
};
|
||||
|
||||
struct Track
|
||||
{
|
||||
TrackFile* file; //handler for actual IO
|
||||
u32 StartFAD; //Start FAD
|
||||
u32 EndFAD; //End FAD
|
||||
u8 CTRL;
|
||||
u8 ADDR;
|
||||
TrackFile* file = nullptr; // handler for actual IO
|
||||
u32 StartFAD = 0; // Start FAD
|
||||
u32 EndFAD = 0; // End FAD
|
||||
u8 CTRL = 0;
|
||||
u8 ADDR = 0;
|
||||
|
||||
Track()
|
||||
bool Read(u32 FAD, u8 *dst, SectorFormat *sector_type, u8 *subcode, SubcodeFormat *subcode_type)
|
||||
{
|
||||
file = 0;
|
||||
StartFAD = 0;
|
||||
EndFAD = 0;
|
||||
CTRL = 0;
|
||||
ADDR = 0;
|
||||
}
|
||||
bool Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,SubcodeFormat* subcode_type)
|
||||
{
|
||||
if (FAD>=StartFAD && (FAD<=EndFAD || EndFAD==0) && file)
|
||||
{
|
||||
file->Read(FAD,dst,sector_type,subcode,subcode_type);
|
||||
return true;
|
||||
}
|
||||
if (FAD >= StartFAD && (FAD <= EndFAD || EndFAD == 0) && file != nullptr)
|
||||
return file->Read(FAD, dst, sector_type, subcode, subcode_type);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
void Destroy() { delete file; file=0; }
|
||||
void Destroy() {
|
||||
delete file;
|
||||
file = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct Disc
|
||||
|
@ -196,7 +188,7 @@ struct Disc
|
|||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(GDROM, "Sector Read miss FAD: %d", FAD);
|
||||
WARN_LOG(GDROM, "Sector Read miss FAD: %d", FAD);
|
||||
}
|
||||
dst+=fmt;
|
||||
FAD++;
|
||||
|
@ -261,18 +253,16 @@ struct RawTrackFile : TrackFile
|
|||
FILE *file;
|
||||
s32 offset;
|
||||
u32 fmt;
|
||||
bool cleanup;
|
||||
|
||||
RawTrackFile(FILE *file, u32 file_offs, u32 first_fad, u32 secfmt)
|
||||
{
|
||||
verify(file!=0);
|
||||
this->file=file;
|
||||
this->offset=file_offs-first_fad*secfmt;
|
||||
this->fmt=secfmt;
|
||||
this->cleanup=true;
|
||||
verify(file != nullptr);
|
||||
this->file = file;
|
||||
this->offset = file_offs - first_fad * secfmt;
|
||||
this->fmt = secfmt;
|
||||
}
|
||||
|
||||
void Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,SubcodeFormat* subcode_type) override
|
||||
bool Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,SubcodeFormat* subcode_type) override
|
||||
{
|
||||
//for now hackish
|
||||
if (fmt==2352)
|
||||
|
@ -290,12 +280,16 @@ struct RawTrackFile : TrackFile
|
|||
|
||||
std::fseek(file, offset + FAD * fmt, SEEK_SET);
|
||||
if (std::fread(dst, 1, fmt, file) != fmt)
|
||||
{
|
||||
WARN_LOG(GDROM, "Failed or truncated GD-Rom read");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
~RawTrackFile() override
|
||||
{
|
||||
if (cleanup && file)
|
||||
std::fclose(file);
|
||||
std::fclose(file);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "stdclass.h"
|
||||
#include <sstream>
|
||||
|
||||
extern std::string OS_dirname(std::string file);
|
||||
|
@ -46,15 +47,13 @@ static u32 getSectorSize(const std::string& type) {
|
|||
|
||||
Disc* cue_parse(const char* file)
|
||||
{
|
||||
// Only try to open .cue files
|
||||
size_t len = strlen(file);
|
||||
if (len > 4 && stricmp( &file[len - 4], ".cue"))
|
||||
if (get_file_extension(file) != "cue")
|
||||
return nullptr;
|
||||
|
||||
FILE *fsource = nowide::fopen(file, "rb");
|
||||
|
||||
if (fsource == nullptr)
|
||||
return nullptr;
|
||||
throw FlycastException(std::string("Cannot open CUE file ") + file);
|
||||
|
||||
size_t cue_len = flycast::fsize(fsource);
|
||||
|
||||
|
@ -62,9 +61,8 @@ Disc* cue_parse(const char* file)
|
|||
|
||||
if (cue_len >= sizeof(cue_data))
|
||||
{
|
||||
WARN_LOG(GDROM, "CUE parse error: CUE file too big");
|
||||
std::fclose(fsource);
|
||||
return nullptr;
|
||||
throw FlycastException("CUE parse error: CUE file too big");
|
||||
}
|
||||
|
||||
if (std::fread(cue_data, 1, cue_len, fsource) != cue_len)
|
||||
|
@ -163,24 +161,21 @@ Disc* cue_parse(const char* file)
|
|||
if (index_num == 1)
|
||||
{
|
||||
Track t;
|
||||
t.ADDR = 0;
|
||||
t.StartFAD = current_fad;
|
||||
t.CTRL = (track_type == "AUDIO" || track_type == "CDG") ? 0 : 4;
|
||||
std::string path = basepath + normalize_path_separator(track_filename);
|
||||
FILE *track_file = nowide::fopen(path.c_str(), "rb");
|
||||
if (track_file == nullptr)
|
||||
{
|
||||
WARN_LOG(GDROM, "CUE file: cannot open track %d: %s", track_number, path.c_str());
|
||||
delete disc;
|
||||
return nullptr;
|
||||
throw FlycastException("CUE file: cannot open track " + path);
|
||||
}
|
||||
u32 sector_size = getSectorSize(track_type);
|
||||
if (sector_size == 0)
|
||||
{
|
||||
WARN_LOG(GDROM, "CUE file: track %d has unknown sector type: %s", track_number, track_type.c_str());
|
||||
std::fclose(track_file);
|
||||
delete disc;
|
||||
return nullptr;
|
||||
throw FlycastException("CUE file: track has unknown sector type: " + track_type);
|
||||
}
|
||||
if (flycast::fsize(track_file) % sector_size != 0)
|
||||
WARN_LOG(GDROM, "Warning: Size of track %s is not multiple of sector size %d", track_filename.c_str(), sector_size);
|
||||
|
@ -199,9 +194,8 @@ Disc* cue_parse(const char* file)
|
|||
}
|
||||
if (disc->tracks.empty())
|
||||
{
|
||||
WARN_LOG(GDROM, "CUE parse error: failed to parse or invalid file with 0 tracks");
|
||||
delete disc;
|
||||
return nullptr;
|
||||
throw FlycastException("CUE parse error: failed to parse or invalid file with 0 tracks");
|
||||
}
|
||||
|
||||
if (session_number == 0)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "common.h"
|
||||
#include "stdclass.h"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
|
@ -62,8 +63,8 @@ namespace {
|
|||
Disc* load_gdi(const char* file)
|
||||
{
|
||||
FILE *t = nowide::fopen(file, "rb");
|
||||
if (!t)
|
||||
return nullptr;
|
||||
if (t == nullptr)
|
||||
throw FlycastException(std::string("Cannot open GDI file ") + file);
|
||||
|
||||
size_t gdi_len = flycast::fsize(t);
|
||||
|
||||
|
@ -71,9 +72,8 @@ Disc* load_gdi(const char* file)
|
|||
|
||||
if (gdi_len >= sizeof(gdi_data))
|
||||
{
|
||||
WARN_LOG(GDROM, "GDI: file too big");
|
||||
std::fclose(t);
|
||||
return nullptr;
|
||||
throw FlycastException("GDI file too big");
|
||||
}
|
||||
|
||||
if (std::fread(gdi_data, 1, gdi_len, t) != gdi_len)
|
||||
|
@ -85,10 +85,8 @@ Disc* load_gdi(const char* file)
|
|||
u32 iso_tc = 0;
|
||||
gdi >> iso_tc;
|
||||
if (iso_tc == 0)
|
||||
{
|
||||
WARN_LOG(GDROM, "GDI: empty or invalid GDI file");
|
||||
return nullptr;
|
||||
}
|
||||
throw FlycastException("GDI: empty or invalid GDI file");
|
||||
|
||||
INFO_LOG(GDROM, "GDI : %d tracks", iso_tc);
|
||||
|
||||
std::string basepath = OS_dirname(file);
|
||||
|
@ -134,16 +132,19 @@ Disc* load_gdi(const char* file)
|
|||
DEBUG_LOG(GDROM, "file[%d] \"%s\": FAD:%d, CTRL:%d, SSIZE:%d, OFFSET:%d", TRACK, track_filename.c_str(), FADS, CTRL, SSIZE, OFFSET);
|
||||
|
||||
Track t;
|
||||
t.ADDR=0;
|
||||
t.StartFAD=FADS+150;
|
||||
t.EndFAD=0; //fill it in
|
||||
t.file=0;
|
||||
t.StartFAD = FADS + 150;
|
||||
t.CTRL = CTRL;
|
||||
|
||||
if (SSIZE!=0)
|
||||
{
|
||||
std::string path = basepath + normalize_path_separator(track_filename);
|
||||
t.file = new RawTrackFile(nowide::fopen(path.c_str(), "rb"), OFFSET, t.StartFAD,SSIZE);
|
||||
FILE *file = nowide::fopen(path.c_str(), "rb");
|
||||
if (file == nullptr)
|
||||
{
|
||||
delete disc;
|
||||
throw FlycastException("GDI file: Cannot open track " + path);
|
||||
}
|
||||
t.file = new RawTrackFile(file, OFFSET, t.StartFAD, SSIZE);
|
||||
}
|
||||
if (!disc->tracks.empty())
|
||||
disc->tracks.back().EndFAD = t.StartFAD - 1;
|
||||
|
@ -158,13 +159,8 @@ Disc* load_gdi(const char* file)
|
|||
|
||||
Disc* gdi_parse(const char* file)
|
||||
{
|
||||
size_t len=strlen(file);
|
||||
if (len>4)
|
||||
{
|
||||
if (stricmp( &file[len-4],".gdi")==0)
|
||||
{
|
||||
return load_gdi(file);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (get_file_extension(file) != "gdi")
|
||||
return nullptr;
|
||||
|
||||
return load_gdi(file);
|
||||
}
|
||||
|
|
|
@ -394,6 +394,7 @@ static void reios_sys_misc()
|
|||
|
||||
case 1: // Exit to BIOS menu
|
||||
WARN_LOG(REIOS, "SYS_MISC 1");
|
||||
throw FlycastException("Reboot to BIOS");
|
||||
break;
|
||||
|
||||
case 2: // check disk
|
||||
|
@ -645,9 +646,8 @@ static void reios_boot()
|
|||
std::string extension = get_file_extension(settings.imgread.ImagePath);
|
||||
if (extension == "elf")
|
||||
{
|
||||
if (!reios_loadElf(settings.imgread.ImagePath)) {
|
||||
msgboxf("Failed to open %s", MBX_ICONERROR, settings.imgread.ImagePath);
|
||||
}
|
||||
if (!reios_loadElf(settings.imgread.ImagePath))
|
||||
throw FlycastException(std::string("Failed to open ELF ") + settings.imgread.ImagePath);
|
||||
reios_setup_state(0x8C010000);
|
||||
}
|
||||
else {
|
||||
|
@ -656,7 +656,7 @@ static void reios_boot()
|
|||
char bootfile[sizeof(ip_meta.boot_filename) + 1] = {0};
|
||||
memcpy(bootfile, ip_meta.boot_filename, sizeof(ip_meta.boot_filename));
|
||||
if (bootfile[0] == '\0' || !reios_locate_bootfile(bootfile))
|
||||
msgboxf("Failed to locate bootfile %s", MBX_ICONERROR, bootfile);
|
||||
throw FlycastException(std::string("Failed to locate bootfile ") + bootfile);
|
||||
reios_setup_state(0xac008300);
|
||||
}
|
||||
else {
|
||||
|
@ -668,14 +668,14 @@ static void reios_boot()
|
|||
}
|
||||
u32 data_size = 4;
|
||||
u32* sz = (u32*)CurrentCartridge->GetPtr(0x368, data_size);
|
||||
if (!sz || data_size != 4) {
|
||||
msgboxf("Naomi boot failure", MBX_ICONERROR);
|
||||
}
|
||||
if (sz == nullptr || data_size != 4)
|
||||
throw FlycastException("Naomi boot failure");
|
||||
|
||||
const u32 size = *sz;
|
||||
|
||||
data_size = 1;
|
||||
verify(size < RAM_SIZE && CurrentCartridge->GetPtr(size - 1, data_size) && "Invalid cart size");
|
||||
if (size > RAM_SIZE || CurrentCartridge->GetPtr(size - 1, data_size) == nullptr)
|
||||
throw FlycastException("Invalid cart size");
|
||||
|
||||
data_size = size;
|
||||
WriteMemBlock_nommu_ptr(0x0c020000, (u32*)CurrentCartridge->GetPtr(0, data_size), size);
|
||||
|
|
|
@ -432,6 +432,26 @@ static void gui_start_game(const std::string& path)
|
|||
dc_load_game(path.empty() ? NULL : path_copy.c_str());
|
||||
}
|
||||
|
||||
void gui_stop_game(const std::string& message)
|
||||
{
|
||||
if (!commandLineStart)
|
||||
{
|
||||
// Exit to main menu
|
||||
dc_term_game();
|
||||
gui_state = GuiState::Main;
|
||||
game_started = false;
|
||||
settings.imgread.ImagePath[0] = '\0';
|
||||
reset_vmus();
|
||||
if (!message.empty())
|
||||
error_msg = "Flycast has stopped.\n\n" + message;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exit emulator
|
||||
dc_exit();
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_display_commands()
|
||||
{
|
||||
if (dc_is_running())
|
||||
|
@ -515,20 +535,7 @@ static void gui_display_commands()
|
|||
if (ImGui::Button("Exit", ImVec2(300 * scaling + ImGui::GetStyle().ColumnsMinSpacing + ImGui::GetStyle().FramePadding.x * 2 - 1,
|
||||
50 * scaling)))
|
||||
{
|
||||
if (!commandLineStart)
|
||||
{
|
||||
// Exit to main menu
|
||||
dc_term_game();
|
||||
gui_state = GuiState::Main;
|
||||
game_started = false;
|
||||
settings.imgread.ImagePath[0] = '\0';
|
||||
reset_vmus();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Exit emulator
|
||||
dc_exit();
|
||||
}
|
||||
gui_stop_game();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
@ -909,6 +916,9 @@ static void error_popup()
|
|||
{
|
||||
if (!error_msg.empty())
|
||||
{
|
||||
ImVec2 padding = ImVec2(20 * scaling, 20 * scaling);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, padding);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, padding);
|
||||
ImGui::OpenPopup("Error");
|
||||
if (ImGui::BeginPopupModal("Error", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
|
@ -924,8 +934,11 @@ static void error_popup()
|
|||
}
|
||||
ImGui::SetItemDefaultFocus();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopTextWrapPos();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1918,8 +1931,12 @@ static void gui_display_content()
|
|||
if (gui_state == GuiState::SelectDisk)
|
||||
{
|
||||
strcpy(settings.imgread.ImagePath, game.path.c_str());
|
||||
DiscSwap();
|
||||
gui_state = GuiState::Closed;
|
||||
try {
|
||||
DiscSwap();
|
||||
gui_state = GuiState::Closed;
|
||||
} catch (const FlycastException& e) {
|
||||
error_msg = e.what();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -36,6 +36,7 @@ void gui_set_mouse_position(int x, int y);
|
|||
void gui_set_mouse_button(int button, bool pressed);
|
||||
void gui_set_mouse_wheel(float delta);
|
||||
void gui_set_insets(int left, int right, int top, int bottom);
|
||||
void gui_stop_game(const std::string& message = "");
|
||||
|
||||
extern int screen_dpi;
|
||||
extern float scaling;
|
||||
|
|
|
@ -49,6 +49,11 @@ bool mainui_rend_frame()
|
|||
if (!rend_single_frame(mainui_enabled))
|
||||
{
|
||||
UpdateInputState();
|
||||
if (!dc_is_running())
|
||||
{
|
||||
dc_stop();
|
||||
gui_stop_game(dc_get_last_error());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -845,12 +845,26 @@ void retro_run()
|
|||
// Render
|
||||
is_dupe = true;
|
||||
for (int i = 0; i < 5 && is_dupe; i++)
|
||||
{
|
||||
is_dupe = !rend_single_frame(true);
|
||||
if (!dc_is_running()) {
|
||||
std::string error = dc_get_last_error();
|
||||
if (!error.empty())
|
||||
gui_display_notification(error.c_str(), 5000);
|
||||
environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
startTime = sh4_sched_now64();
|
||||
dc_run(nullptr);
|
||||
try {
|
||||
dc_run();
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(COMMON, "%s", e.what());
|
||||
gui_display_notification(e.what(), 5000);
|
||||
environ_cb(RETRO_ENVIRONMENT_SHUTDOWN, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (config::RendererType.isOpenGL())
|
||||
|
@ -870,7 +884,7 @@ static bool loadGame(const char *path)
|
|||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(BOOT, "%s", e.what());
|
||||
mute_messages = false;
|
||||
gui_display_notification(e.what(), 2000);
|
||||
gui_display_notification(e.what(), 5000);
|
||||
return false;
|
||||
}
|
||||
mute_messages = false;
|
||||
|
@ -2751,7 +2765,12 @@ static bool retro_set_eject_state(bool ejected)
|
|||
}
|
||||
else
|
||||
{
|
||||
return DiscSwap();
|
||||
try {
|
||||
return DiscSwap();
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(GDROM, "%s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2779,8 +2798,13 @@ static bool retro_set_image_index(unsigned index)
|
|||
|
||||
if (disc_tray_open)
|
||||
return true;
|
||||
else
|
||||
|
||||
try {
|
||||
return DiscSwap();
|
||||
} catch (const FlycastException& e) {
|
||||
ERROR_LOG(GDROM, "%s", e.what());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned retro_get_num_images()
|
||||
|
|
Loading…
Reference in New Issue