Add support for emulated Game Genie add-on

This commit is contained in:
jdgleaver 2021-10-21 15:52:40 +01:00
parent 98b2ae09ab
commit 1a961ff6be
12 changed files with 240 additions and 84 deletions

View File

@ -23,6 +23,7 @@
#include <stdio.h>
#include <string/stdstring.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include "fceu-types.h"
@ -353,20 +354,25 @@ void FCEU_OpenGenie(void) {
fn = FCEU_MakeFName(FCEUMKF_GGROM, 0, 0);
if (!string_is_empty(fn))
if (!string_is_empty(fn) && path_is_valid(fn))
fp = filestream_open(fn,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);
free(fn);
fn = NULL;
if (!fp) {
FCEU_PrintError("Error opening Game Genie ROM image!");
FCEU_PrintError("Error opening Game Genie ROM image!\n");
FCEUD_DispMessage(RETRO_LOG_WARN, 3000, "Game Genie ROM image (gamegenie.nes) missing");
free(GENIEROM);
GENIEROM = 0;
return;
}
if (filestream_read(fp, GENIEROM, 16) != 16) {
grerr:
FCEU_PrintError("Error reading from Game Genie ROM image!");
FCEU_PrintError("Error reading from Game Genie ROM image!\n");
FCEUD_DispMessage(RETRO_LOG_WARN, 3000, "Failed to read Game Genie ROM image (gamegenie.nes)");
free(GENIEROM);
GENIEROM = 0;
filestream_close(fp);

View File

@ -114,7 +114,6 @@ void RebuildSubCheats(void) {
if (c->type == 1 && c->status) {
if (GetReadHandler(c->addr) == SubCheatsRead) {
/* Prevent a catastrophe by this check. */
/* FCEU_DispMessage("oops"); */
} else {
SubCheats[numsubcheats].PrevRead = GetReadHandler(c->addr);
SubCheats[numsubcheats].addr = c->addr;

View File

@ -2,6 +2,7 @@
#define _FCEU_DRIVER_H
#include <stdio.h>
#include <libretro.h>
#ifdef __cplusplus
extern "C" {
@ -37,7 +38,9 @@ void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b);
/* Displays an error. Can block or not. */
void FCEUD_PrintError(char *s);
void FCEUD_Message(char *s);
void FCEUD_DispMessage(char *m);
void FCEUD_DispMessage(enum retro_log_level level, unsigned duration, char *str);
void FCEU_DispMessage(enum retro_log_level level, unsigned duration, char *format, ...);
int FCEUI_BeginWaveRecord(char *fn);
int FCEUI_EndWaveRecord(void);
@ -99,7 +102,14 @@ void FCEUI_DisableSpriteLimitation(int a);
/* -1 = no change, 0 = show, 1 = hide, 2 = internal toggle */
void FCEUI_SetRenderDisable(int sprites, int bg);
FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *buf, size_t bufsize);
/* frontend_post_load_init_cb() is called immediately
* after loading the ROM, allowing any frontend
* initialisation that is dependent on ROM type to
* be performed before the regular internal post-load
* initialisation */
typedef void (*frontend_post_load_init_cb_t)(void);
FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufsize,
frontend_post_load_init_cb_t frontend_post_load_init_cb);
#ifdef COPYFAMI
/* Fake UNIF board to start new CFHI instance */
@ -168,8 +178,6 @@ void FCEUI_LoadMovie(char *fname);
int32 FCEUI_GetDesiredFPS(void);
void FCEUI_SaveSnapshot(void);
void FCEU_DispMessage(char *format, ...);
#define FCEUI_DispMessage FCEU_DispMessage
int FCEUI_DecodePAR(const char *code, uint16 *a, uint8 *v, int *c, int *type);
int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c);

View File

@ -65,6 +65,9 @@
#define NES_4_3 ((width / (height * (256.0 / 240.0))) * 4.0 / 3.0)
#define NES_PP ((width / (height * (256.0 / 240.0))) * 16.0 / 15.0)
#define NES_PAL_FPS (838977920.0 / 16777215.0)
#define NES_NTSC_FPS (1008307711.0 / 16777215.0)
#if defined(_3DS)
void* linearMemAlign(size_t size, size_t alignment);
void linearFree(void* mem);
@ -148,6 +151,7 @@ static enum RetroZapperInputModes zappermode = RetroLightgun;
static bool libretro_supports_bitmasks = false;
static bool libretro_supports_option_categories = false;
static unsigned libretro_msg_interface_version = 0;
/* emulator-specific variables */
@ -282,11 +286,54 @@ void FCEUD_Message(char *s)
log_cb.log(RETRO_LOG_INFO, "%s", s);
}
void FCEUD_DispMessage(char *m)
{ struct retro_message msg;
msg.msg = m;
msg.frames = 180;
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
void FCEUD_DispMessage(enum retro_log_level level, unsigned duration, char *str)
{
if (!environ_cb)
return;
if (libretro_msg_interface_version >= 1)
{
struct retro_message_ext msg;
unsigned priority;
switch (level)
{
case RETRO_LOG_ERROR:
priority = 5;
break;
case RETRO_LOG_WARN:
priority = 4;
break;
case RETRO_LOG_INFO:
priority = 3;
break;
case RETRO_LOG_DEBUG:
default:
priority = 1;
break;
}
msg.msg = str;
msg.duration = duration;
msg.priority = priority;
msg.level = level;
msg.target = RETRO_MESSAGE_TARGET_OSD;
msg.type = RETRO_MESSAGE_TYPE_NOTIFICATION_ALT;
msg.progress = -1;
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE_EXT, &msg);
}
else
{
float fps = (FSettings.PAL || dendy) ? NES_PAL_FPS : NES_NTSC_FPS;
unsigned frames = (unsigned)(((float)duration * fps / 1000.0f) + 0.5f);
struct retro_message msg;
msg.msg = str;
msg.frames = frames;
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, &msg);
}
}
void FCEUD_SoundToggle (void)
@ -1024,6 +1071,40 @@ static void set_variables(void)
}
}
/* Game Genie add-on must be enabled before
* loading content, so we cannot parse this
* option inside check_variables() */
static void check_game_genie_variable(void)
{
struct retro_variable var = {0};
int game_genie_enabled = 0;
var.key = "fceumm_game_genie";
/* Game Genie is only enabled for regular
* cartridges (excludes arcade content,
* FDS games, etc.) */
if ((GameInfo->type == GIT_CART) &&
(iNESCart.mapper != 105) && /* Nintendo World Championship cart (Mapper 105)*/
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) &&
var.value &&
!strcmp(var.value, "enabled"))
game_genie_enabled = 1;
FCEUI_SetGameGenie(game_genie_enabled);
}
/* Callback passed to FCEUI_LoadGame()
* > Required since we must set and check
* core options immediately after ROM
* is loaded, before FCEUI_LoadGame()
* returns */
static void frontend_post_load_init()
{
set_variables();
check_game_genie_variable();
}
void retro_set_environment(retro_environment_t cb)
{
struct retro_vfs_interface_info vfs_iface_info;
@ -1140,9 +1221,9 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
info->geometry.aspect_ratio = get_aspect_ratio(width, height);
info->timing.sample_rate = (float)sndsamplerate;
if (FSettings.PAL || dendy)
info->timing.fps = 838977920.0/16777215.0;
info->timing.fps = NES_PAL_FPS;
else
info->timing.fps = 1008307711.0/16777215.0;
info->timing.fps = NES_NTSC_FPS;
}
static void check_system_specs(void)
@ -1162,6 +1243,9 @@ void retro_init(void)
if (environ_cb(RETRO_ENVIRONMENT_GET_INPUT_BITMASKS, NULL))
libretro_supports_bitmasks = true;
environ_cb(RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION,
&libretro_msg_interface_version);
}
static void retro_set_custom_palette(void)
@ -1232,15 +1316,15 @@ static void FCEUD_RegionOverride(unsigned region)
pal = systemRegion & 1;
break;
case 1: /* ntsc */
FCEU_DispMessage("System: NTSC");
FCEUD_DispMessage(RETRO_LOG_INFO, 2000, "System: NTSC");
break;
case 2: /* pal */
pal = 1;
FCEU_DispMessage("System: PAL");
FCEUD_DispMessage(RETRO_LOG_INFO, 2000, "System: PAL");
break;
case 3: /* dendy */
d = 1;
FCEU_DispMessage("System: Dendy");
FCEUD_DispMessage(RETRO_LOG_INFO, 2000, "System: Dendy");
break;
}
@ -1265,6 +1349,7 @@ void retro_deinit (void)
ps2 = NULL;
#endif
libretro_supports_bitmasks = false;
libretro_msg_interface_version = 0;
DPSW_Cleanup();
#ifdef HAVE_NTSC_FILTER
NTSCFilter_Cleanup();
@ -1456,9 +1541,6 @@ static void check_variables(bool startup)
FCEU_ZapperSetTolerance(atoi(var.value));
}
var.key = "fceumm_region";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
var.key = "fceumm_show_crosshair";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@ -1479,7 +1561,6 @@ static void check_variables(bool startup)
audio_video_updated = 1;
}
}
#else
var.key = "fceumm_overscan_h";
@ -1505,6 +1586,7 @@ static void check_variables(bool startup)
}
}
#endif
var.key = "fceumm_aspect";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
@ -1545,6 +1627,7 @@ static void check_variables(bool startup)
nes_input.turbo_delay = atoi(var.value);
var.key = "fceumm_region";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
unsigned oldval = opt_region;
@ -2060,6 +2143,11 @@ size_t retro_serialize_size(void)
bool retro_serialize(void *data, size_t size)
{
/* Cannot save state while Game Genie
* screen is open */
if (geniestage == 1)
return false;
if (size != retro_serialize_size())
return false;
@ -2070,6 +2158,11 @@ bool retro_serialize(void *data, size_t size)
bool retro_unserialize(const void * data, size_t size)
{
/* Cannot load state while Game Genie
* screen is open */
if (geniestage == 1)
return false;
if (size != retro_serialize_size())
return false;
@ -2581,17 +2674,16 @@ bool retro_load_game(const struct retro_game_info *info)
FCEUI_SetSoundVolume(sndvolume);
FCEUI_Sound(sndsamplerate);
GameInfo = (FCEUGI*)FCEUI_LoadGame(content_path, content_data, content_size);
GameInfo = (FCEUGI*)FCEUI_LoadGame(content_path, content_data, content_size,
frontend_post_load_init);
if (!GameInfo)
{
struct retro_message msg;
char msg_local[256];
sprintf(msg_local, "ROM loading failed...");
msg.msg = msg_local;
msg.frames = 360;
if (environ_cb)
environ_cb(RETRO_ENVIRONMENT_SET_MESSAGE, (void*)&msg);
#if 0
/* An error message here is superfluous - the frontend
* will report that content loading has failed */
FCEUD_DispMessage(RETRO_LOG_ERROR, 3000, "ROM loading failed...");
#endif
return false;
}
@ -2612,7 +2704,6 @@ bool retro_load_game(const struct retro_game_info *info)
ResetPalette();
FCEUD_SoundToggle();
set_variables();
check_variables(true);
PowerNES();

View File

@ -17,7 +17,7 @@ extern "C" {
********************************
*/
#define MAX_CORE_OPTIONS 34
#define MAX_CORE_OPTIONS 35
/* RETRO_LANGUAGE_ENGLISH */
@ -29,6 +29,11 @@ extern "C" {
* frontend language definition */
struct retro_core_option_v2_category option_cats_us[] = {
{
"system",
"System",
"Configure region / hardware add-on parameters."
},
{
"video",
"Video",
@ -68,16 +73,30 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
NULL,
"Force core to use NTSC, PAL or Dendy region timings.",
NULL,
NULL,
"system",
{
{ "Auto", NULL },
{ "NTSC", NULL },
{ "PAL", NULL },
{ "Dendy", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"Auto",
},
{
"fceumm_game_genie",
"Game Genie Add-On (Restart)",
NULL,
"Enable emulation of a Game Genie add-on cartridge, allowing cheat codes to be entered when launching games. The Game Genie ROM file 'gamegenie.nes' must be present in the frontend's system directory. Does not apply to FDS or arcade content.",
NULL,
"system",
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL },
},
"disabled",
},
{
"fceumm_show_adv_system_options",
"Show Advanced System Options",
@ -117,7 +136,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "8:7 PAR", NULL },
{ "4:3", NULL },
{ "PP", "Pixel Perfect" },
{ NULL, NULL},
{ NULL, NULL },
},
"8:7 PAR",
},
@ -132,7 +151,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -147,7 +166,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"disabled",
},
@ -161,7 +180,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -193,7 +212,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "wavebeam", "nakedarthur's Wavebeam" },
{ "raw", "Raw" },
{ "custom", "Custom" },
{ NULL, NULL},
{ NULL, NULL },
},
"default",
},
@ -227,7 +246,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "Low", NULL },
{ "High", NULL },
{ "Very High", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"Low",
},
@ -241,7 +260,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"disabled",
},
@ -264,7 +283,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "8", "80%" },
{ "9", "90%" },
{ "10", "100%" },
{ NULL, NULL},
{ NULL, NULL },
},
"7",
},
@ -278,7 +297,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -292,7 +311,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -306,7 +325,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -320,7 +339,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -334,7 +353,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -350,7 +369,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "Player 1", NULL },
{ "Player 2", NULL },
{ "Both", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"None",
},
@ -370,7 +389,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "15", NULL },
{ "30", NULL },
{ "60", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"3",
},
@ -385,7 +404,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "lightgun", "Lightgun" },
{ "touchscreen", "Touchscreen" },
{ "mouse", "Mouse" },
{ NULL, NULL},
{ NULL, NULL },
},
"lightgun",
},
@ -399,7 +418,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "enabled", NULL },
{ "disabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"enabled",
},
@ -446,7 +465,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"disabled",
},
@ -460,7 +479,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{
{ "disabled", NULL },
{ "enabled", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"disabled",
},
@ -475,7 +494,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "disabled", NULL },
{ "2x-Postrender", NULL },
{ "2x-VBlank", NULL },
{ NULL, NULL},
{ NULL, NULL },
},
"disabled",
},
@ -490,7 +509,7 @@ struct retro_core_option_v2_definition option_defs_us_common[] = {
{ "fill $ff", "$FF" },
{ "fill $00", "$00" },
{ "random", "Random" },
{ NULL, NULL},
{ NULL, NULL },
},
"fill $ff",
},

View File

@ -56,8 +56,8 @@ void (*GameStateRestore)(int version);
readfunc ARead[0x10000];
writefunc BWrite[0x10000];
static readfunc *AReadG;
static writefunc *BWriteG;
static readfunc *AReadG = NULL;
static writefunc *BWriteG = NULL;
static int RWWrap = 0;
static DECLFW(BNull)
@ -71,12 +71,24 @@ static DECLFR(ANull)
int AllocGenieRW(void)
{
if (!(AReadG = (readfunc*)FCEU_malloc(0x8000 * sizeof(readfunc))))
return 0;
if (!(BWriteG = (writefunc*)FCEU_malloc(0x8000 * sizeof(writefunc))))
return 0;
RWWrap = 1;
return 1;
if (!AReadG)
{
if (!(AReadG = (readfunc*)FCEU_malloc(0x8000 * sizeof(readfunc))))
return 0;
}
else
memset(AReadG, 0, 0x8000 * sizeof(readfunc));
if (!BWriteG)
{
if (!(BWriteG = (writefunc*)FCEU_malloc(0x8000 * sizeof(writefunc))))
return 0;
}
else
memset(BWriteG, 0, 0x8000 * sizeof(writefunc));
RWWrap = 1;
return 1;
}
void FlushGenieRW(void)
@ -92,8 +104,8 @@ void FlushGenieRW(void)
}
free(AReadG);
free(BWriteG);
AReadG = 0;
BWriteG = 0;
AReadG = NULL;
BWriteG = NULL;
}
RWWrap = 0;
}
@ -226,7 +238,8 @@ int iNESLoad(const char *name, FCEUFILE *fp);
int FDSLoad(const char *name, FCEUFILE *fp);
int NSFLoad(FCEUFILE *fp);
FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufsize)
FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufsize,
frontend_post_load_init_cb_t frontend_post_load_init_cb)
{
FCEUFILE *fp;
@ -248,7 +261,11 @@ FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufs
if (!fp) {
FCEU_PrintError("Error opening \"%s\"!", name);
return 0;
free(GameInfo);
GameInfo = NULL;
return NULL;
}
if (iNESLoad(name, fp))
@ -262,11 +279,21 @@ FCEUGI *FCEUI_LoadGame(const char *name, const uint8_t *databuf, size_t databufs
FCEU_PrintError("An error occurred while loading the file.\n");
FCEU_fclose(fp);
return 0;
if (GameInfo->name)
free(GameInfo->name);
GameInfo->name = NULL;
free(GameInfo);
GameInfo = NULL;
return NULL;
endlseq:
FCEU_fclose(fp);
if (frontend_post_load_init_cb)
(*frontend_post_load_init_cb)();
FCEU_ResetVidSys();
if (GameInfo->type != GIT_NSF)
if (FSettings.GameGenie)

View File

@ -107,7 +107,6 @@ extern FCEUS FSettings;
void FCEU_PrintError(char *format, ...);
void FCEU_printf(char *format, ...);
void FCEU_DispMessage(char *format, ...);
void SetNESDeemph(uint8 d, int force);
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);

View File

@ -179,12 +179,12 @@ static void FDSInit(void) {
void FCEU_FDSInsert(int oride) {
if (InDisk == 255) {
FCEU_DispMessage("Disk %d of %d Side %s Inserted",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
FCEU_DispMessage(RETRO_LOG_INFO, 2000, "Disk %d of %d Side %s Inserted",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = SelectDisk;
} else {
FCEU_DispMessage("Disk %d of %d Side %s Ejected",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
FCEU_DispMessage(RETRO_LOG_INFO, 2000, "Disk %d of %d Side %s Ejected",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
InDisk = 255;
}
}
@ -195,12 +195,12 @@ void FCEU_FDSEject(void) {
void FCEU_FDSSelect(void) {
if (InDisk != 255) {
FCEU_DispMessage("Eject disk before selecting.");
FCEUD_DispMessage(RETRO_LOG_WARN, 2000, "Eject disk before selecting");
return;
}
SelectDisk = ((SelectDisk + 1) % TotalSides) & 3;
FCEU_DispMessage("Disk %d of %d Side %s Selected",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
FCEU_DispMessage(RETRO_LOG_INFO, 2000, "Disk %d of %d Side %s Selected",
1 + (SelectDisk >> 1), (TotalSides + 1) >> 1, (SelectDisk & 1) ? "B" : "A");
}
/* 2018/12/15 - update irq timings */
@ -710,6 +710,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
if (!(zp = FCEU_fopen(fn, NULL, 0))) {
FCEU_PrintError("FDS BIOS ROM image missing!\n");
FCEUD_DispMessage(RETRO_LOG_ERROR, 3000, "FDS BIOS image (disksys.rom) missing");
free(fn);
return 0;
}
@ -730,6 +731,7 @@ int FDSLoad(const char *name, FCEUFILE *fp) {
FDSBIOS = NULL;
FCEU_fclose(zp);
FCEU_PrintError("Error reading FDS BIOS ROM image.\n");
FCEUD_DispMessage(RETRO_LOG_ERROR, 3000, "Error reading FDS BIOS image (disksys.rom)");
return 0;
}

View File

@ -28,6 +28,7 @@
#endif
#include <string/stdstring.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include "fceu-types.h"
@ -88,7 +89,7 @@ FCEUFILE * FCEU_fopen(const char *path, const uint8 *buffer, size_t bufsize)
{
RFILE *t = NULL;
if (!string_is_empty(path))
if (!string_is_empty(path) && path_is_valid(path))
t = filestream_open(path,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);

View File

@ -67,7 +67,7 @@ char *FCEU_MakeFName(int type, int id1, char *cd1)
{
case FCEUMKF_GGROM:
fill_pathname_join(tmp, BaseDirectory,
"gg.rom", sizeof(tmp));
"gamegenie.nes", sizeof(tmp));
break;
case FCEUMKF_FDSROM:
fill_pathname_join(tmp, BaseDirectory,

View File

@ -23,6 +23,7 @@
#include <math.h>
#include <string/stdstring.h>
#include <file/file_path.h>
#include <streams/file_stream.h>
#include "fceu-types.h"
@ -197,7 +198,7 @@ void FCEU_LoadGamePalette(void) {
fn = FCEU_MakeFName(FCEUMKF_PALETTE, 0, 0);
if (!string_is_empty(fn))
if (!string_is_empty(fn) && path_is_valid(fn))
fp = filestream_open(fn,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);

View File

@ -86,16 +86,19 @@ void FCEU_PutImageDummy(void)
{
}
void FCEU_DispMessage(char *format, ...)
void FCEU_DispMessage(enum retro_log_level level, unsigned duration, char *format, ...)
{
static char msg[512] = {0};
va_list ap;
static char errmsg[65];
if (!format || (*format == '\0'))
return;
va_start(ap, format);
vsprintf(errmsg, format, ap);
vsprintf(msg, format, ap);
va_end(ap);
FCEUD_DispMessage(errmsg);
FCEUD_DispMessage(level, duration, msg);
}
void FCEU_ResetMessages(void)