diff --git a/mupen64plus-core/data/mupen64plus.ini b/mupen64plus-core/data/mupen64plus.ini
index f1f0125..d86e3e0 100644
--- a/mupen64plus-core/data/mupen64plus.ini
+++ b/mupen64plus-core/data/mupen64plus.ini
@@ -17913,3 +17913,73 @@ GoodName=Zelda no Densetsu - Mujura no Kamen (J) (V1.1) [!]
CRC=69AE0438 2C63F3F3
RefMD5=15D1A2217CAD61C39CFECBFFA0703E25
+; 64DD Games
+;
+[8D3D9F294B6E174BC7B1D2FD1C727530]
+GoodName=64DD IPL (JPN)
+
+[37C36E4286D36892A9FC70EAFE4104BE]
+GoodName=64DD IPL (USA)
+
+[8485643E5830CD67ED4C0A5FD49E2491]
+GoodName=Mario Artist Paint Studio (J)
+
+[88228E990B58A94E9B3460BEFF632304]
+GoodName=Mario Artist Talent Studio (J)
+
+[114AF722029D6386C3BFEA4CC8FA603C]
+GoodName=Mario Artist Communication Kit (J)
+
+[DA23EE561578B7DAD77ED72728B46D30]
+GoodName=Mario Artist Polygon Studio (J)
+
+[EBBA03F20096FC2BC178FC3A1F4EC2B6]
+GoodName=Sim City 64 (J)
+
+[9F797A9C704B5EBD04D6A2B036309AF2]
+GoodName=Nihon Pro Golf Tour 64 (J)
+
+[E8EB810D996E12CD6C47445F87A94C72]
+GoodName=Kyojin no Doshin 1 (J)
+
+[AFE059AE1210751B6C849CFB482C99DD]
+GoodName=Kyojin no Doshin 1 (J) (Store Demo)
+
+[26087E0750FC6DA0F3DE2A431E34BDDF]
+GoodName=Randnet Disk (J) [Rev. 00]
+
+[33CBC59786063285DC3C090E0ED312E3]
+GoodName=Randnet Disk (J) [Rev. 01]
+
+[FCCA9AF8C1174C40B478EA0E02673B16]
+GoodName=Kyojin no Doshin - Kaihou Sensen Chibikkochikko Dai Shuugou (J)
+
+[CB2FB00C3921245AE04BB38BA01ABE92]
+GoodName=F-ZERO X Expansion Kit (J)
+
+[D9EA905727B44F2774926CB03C2300A7]
+GoodName=Super Mario 64 Disk Version (J) (Spaceworld 1996 Demo)
+
+[84706E10026BD2EE9654DA5E9821598D]
+GoodName=Dezaemon 3D Expansion Disk (J) (Proto)
+SaveType=SRAM
+
+[7BB3974754A54BA27A93F96691DC4695]
+GoodName=Dezaemon 3D Expansion Disk (J) (Proto)
+SaveType=SRAM
+
+[40AA8EC52C5E025D6C6AD94CEBC2218F]
+GoodName=Dezaemon 3D Expansion Disk (J) (Proto)
+SaveType=SRAM
+
+[C108A9B1EB024F0D2317C05976BA49F2]
+GoodName=Dezaemon 3D Expansion Disk (J) (Proto) [a1]
+SaveType=SRAM
+
+[4D02F5A719BD455F67721C64B16AE0CB]
+GoodName=Mario Artist Paint Studio (J) (1999-02-11 Proto)
+CountPerOp=1
+
+[A76B619EC832A7E2ABCFBDFEB5375E39]
+GoodName=Mario Artist Paint Studio (J) (1999-02-11 Proto)
+CountPerOp=1
diff --git a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-API-Versioning.mediawiki b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-API-Versioning.mediawiki
index e3f1300..dde33a8 100644
--- a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-API-Versioning.mediawiki
+++ b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-API-Versioning.mediawiki
@@ -131,5 +131,7 @@ This is the most complicated interface, because it involves 3 components: the vi
** add ConfigOverrideUserPaths() function to allow front-ends to override user paths.
* '''INPUT_API_VERSION''' version 2.1.1:
** add optional functions: SendVRUWord(), SetMicState(), ReadVRUResults(), ClearVRUWords(), SetVRUWordMask(). These functions add support for the VRU (Voice Recognition Unit). Also added a new int to the CONTROL struct: Type. Type can be CONT_TYPE_STANDARD (0) or CONT_TYPE_VRU (1).
+* '''FRONTEND_API_VERSION''' version 2.1.5:
+** added "M64CMD_DISK_OPEN" and "M64CMD_DISK_CLOSE" commands to allow booting 64DD disks without requiring a cartridge.
* '''VIDEO_API_VERSION''' version 2.2.1:
** add (optional) FullSync() function, which is called right before a DP interrupt
diff --git a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Core-Front-End.mediawiki b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Core-Front-End.mediawiki
index 36a12f4..3b77b39 100644
--- a/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Core-Front-End.mediawiki
+++ b/mupen64plus-core/doc/emuwiki-api-doc/Mupen64Plus-v2.0-Core-Front-End.mediawiki
@@ -89,13 +89,23 @@ Most libmupen64plus functions return an m64p_error return code, which i
|M64CMD_ROM_OPEN
|This will cause the core to read in a binary ROM image provided by the front-end.
|'''ParamPtr''' Pointer to the uncompressed ROM image in memory.
'''ParamInt''' The size in bytes of the ROM image.
-|The emulator cannot be currently running. A ROM image must not be currently opened.
+|The emulator cannot be currently running. A ROM image or disk must not be currently opened.
|-
|M64CMD_ROM_CLOSE
|This will close any currently open ROM. The current cheat code list will also be deleted.
|N/A
|The emulator cannot be currently running. A ROM image must have been previously opened. There should be no plugins currently attached.
|-
+|M64CMD_DISK_OPEN
+|This will cause the core to read in a disk using the medialoader API provided by the front-end.
+|N/A
+|The emulator cannot be currently running. A disk or ROM image must not be currently opened.
+|-
+|M64CMD_DISK_CLOSE
+|This will close any currently open disk. The current cheat code list will also be deleted.
+|N/A
+|The emulator cannot be currently running. A disk must have been previously opened. There should be no plugins currently attached.
+|-
|M64CMD_ROM_GET_HEADER
|This will retrieve the header data of the currently open ROM.
|'''ParamPtr''' Pointer to a rom_header struct to receive the data.
'''ParamInt''' The size in bytes of the rom_header struct.
diff --git a/mupen64plus-core/src/api/frontend.c b/mupen64plus-core/src/api/frontend.c
index 7e8a36c..107c7af 100644
--- a/mupen64plus-core/src/api/frontend.c
+++ b/mupen64plus-core/src/api/frontend.c
@@ -52,6 +52,7 @@
/* some local state variables */
static int l_CoreInit = 0;
static int l_ROMOpen = 0;
+static int l_DiskOpen = 0;
static int l_CallerUsingSDL = 0;
/* functions exported outside of libmupen64plus to front-end application */
@@ -140,7 +141,7 @@ EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type PluginType, m64p_dynlib
if (!l_CoreInit)
return M64ERR_NOT_INIT;
- if (g_EmulatorRunning || !l_ROMOpen)
+ if (g_EmulatorRunning || (!l_ROMOpen && !l_DiskOpen))
return M64ERR_INVALID_STATE;
rval = plugin_connect(PluginType, PluginLibHandle);
@@ -177,7 +178,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
case M64CMD_NOP:
return M64ERR_SUCCESS;
case M64CMD_ROM_OPEN:
- if (g_EmulatorRunning || l_ROMOpen)
+ if (g_EmulatorRunning || l_DiskOpen || l_ROMOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL || ParamInt < 4096)
return M64ERR_INPUT_ASSERT;
@@ -196,6 +197,26 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
cheat_delete_all(&g_cheat_ctx);
cheat_uninit(&g_cheat_ctx);
return close_rom();
+ case M64CMD_DISK_OPEN:
+ if (g_EmulatorRunning || l_DiskOpen || l_ROMOpen)
+ return M64ERR_INVALID_STATE;
+ if (ParamPtr != NULL)
+ return M64ERR_INPUT_INVALID;
+ rval = open_disk();
+ if (rval == M64ERR_SUCCESS)
+ {
+ l_DiskOpen = 1;
+ ScreenshotRomOpen();
+ cheat_init(&g_cheat_ctx);
+ }
+ return rval;
+ case M64CMD_DISK_CLOSE:
+ if (g_EmulatorRunning || !l_DiskOpen)
+ return M64ERR_INVALID_STATE;
+ l_DiskOpen = 0;
+ cheat_delete_all(&g_cheat_ctx);
+ cheat_uninit(&g_cheat_ctx);
+ return close_disk();
case M64CMD_PIF_OPEN:
if (g_EmulatorRunning)
return M64ERR_INVALID_STATE;
@@ -203,7 +224,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
return M64ERR_INPUT_ASSERT;
return open_pif((const unsigned char *) ParamPtr);
case M64CMD_ROM_GET_HEADER:
- if (!l_ROMOpen)
+ if (!l_ROMOpen && !l_DiskOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
@@ -219,7 +240,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
}
return M64ERR_SUCCESS;
case M64CMD_ROM_GET_SETTINGS:
- if (!l_ROMOpen)
+ if (!l_ROMOpen && !l_DiskOpen)
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
@@ -228,7 +249,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
memcpy(ParamPtr, &ROM_SETTINGS, ParamInt);
return M64ERR_SUCCESS;
case M64CMD_ROM_SET_SETTINGS:
- if (g_EmulatorRunning || !l_ROMOpen)
+ if (g_EmulatorRunning || (!l_ROMOpen && !l_DiskOpen))
return M64ERR_INVALID_STATE;
if (ParamPtr == NULL)
return M64ERR_INPUT_ASSERT;
@@ -237,7 +258,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P
memcpy(&ROM_SETTINGS, ParamPtr, ParamInt);
return M64ERR_SUCCESS;
case M64CMD_EXECUTE:
- if (g_EmulatorRunning || !l_ROMOpen)
+ if (g_EmulatorRunning || (!l_ROMOpen && !l_DiskOpen))
return M64ERR_INVALID_STATE;
/* print out plugin-related warning messages */
plugin_check();
diff --git a/mupen64plus-core/src/api/m64p_types.h b/mupen64plus-core/src/api/m64p_types.h
index 891f1a1..61a1072 100644
--- a/mupen64plus-core/src/api/m64p_types.h
+++ b/mupen64plus-core/src/api/m64p_types.h
@@ -168,7 +168,9 @@ typedef enum {
M64CMD_NETPLAY_GET_VERSION,
M64CMD_NETPLAY_CLOSE,
M64CMD_PIF_OPEN,
- M64CMD_ROM_SET_SETTINGS
+ M64CMD_ROM_SET_SETTINGS,
+ M64CMD_DISK_OPEN,
+ M64CMD_DISK_CLOSE
} m64p_command;
typedef struct {
diff --git a/mupen64plus-core/src/device/dd/dd_controller.c b/mupen64plus-core/src/device/dd/dd_controller.c
index 05b3301..c66b007 100644
--- a/mupen64plus-core/src/device/dd/dd_controller.c
+++ b/mupen64plus-core/src/device/dd/dd_controller.c
@@ -493,7 +493,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
cycles = 248250;
/* check if motor is active or not, if not, add more cycles */
if ((dd->regs[DD_ASIC_CMD_STATUS] & (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT)) != 0) {
- cycles += 50175000;
+ //divided by 100 because F-Zero X Expansion Kit really dislikes anything higher
+ cycles += 501750;
}
/* make motor active */
dd_dv_active(dd);
@@ -527,7 +528,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
cycles = 248250;
/* check if motor is active or not, if not, add more cycles */
if ((dd->regs[DD_ASIC_CMD_STATUS] & (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT)) != 0) {
- cycles += 50175000;
+ //divided by 100 because F-Zero X Expansion Kit really dislikes anything higher
+ cycles += 501750;
}
/* make motor active */
dd_dv_active(dd);
@@ -549,7 +551,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
/* Sleep / Brake */
case 0x04:
if ((dd->regs[DD_ASIC_CMD_STATUS] & (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT)) != 0) {
- cycles = 20750000;
+ //divided by 100 because F-Zero X Expansion Kit really dislikes anything higher
+ cycles = 207500;
}
dd_dv_sleep(dd);
if (dd->regs[DD_ASIC_DATA] == 0)
@@ -628,7 +631,8 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask
/* Standby */
case 0x0d:
if ((dd->regs[DD_ASIC_CMD_STATUS] & (DD_STATUS_MTR_N_SPIN | DD_STATUS_HEAD_RTRCT)) != 0) {
- cycles = 16000000;
+ //divided by 100 because F-Zero X Expansion Kit really dislikes anything higher
+ cycles = 160000;
}
dd_dv_standby(dd);
DebugMessage(M64MSG_VERBOSE, "Disk drive motor put to standby mode");
diff --git a/mupen64plus-core/src/device/device.c b/mupen64plus-core/src/device/device.c
index d3ed3da..8f2294b 100644
--- a/mupen64plus-core/src/device/device.c
+++ b/mupen64plus-core/src/device/device.c
@@ -191,12 +191,12 @@ void init_device(struct device* dev,
init_si(&dev->si, &dev->mi, &dev->pif, &dev->ri);
init_vi(&dev->vi, vi_clock, &dev->mi, &dev->dp);
- /* FIXME: should boot on cart, unless only a disk is present, but having no cart is not yet supported by ui/core,
- * so use another way of selecting boot device:
- * use CART unless DD is plugged and the plugged CART is not a combo media (cart+disk).
+ /*
+ * use CART unless DD is plugged and the plugged CART is not a combo media (cart+disk),
+ * or rom_size is 0 meaning there's no CART loaded
*/
uint8_t media = *((uint8_t*)mem_base_u32(base, MM_CART_ROM) + (0x3b ^ S8));
- uint32_t rom_base = (dd_rom_size > 0 && media != 'C')
+ uint32_t rom_base = (rom_size == 0 || (dd_rom_size > 0 && media != 'C'))
? MM_DD_ROM
: MM_CART_ROM;
diff --git a/mupen64plus-core/src/main/main.c b/mupen64plus-core/src/main/main.c
index ac4dd09..96c3aa9 100644
--- a/mupen64plus-core/src/main/main.c
+++ b/mupen64plus-core/src/main/main.c
@@ -1585,6 +1585,7 @@ m64p_error main_run(void)
struct file_storage sra;
size_t dd_rom_size;
struct dd_disk dd_disk;
+ m64p_error failure_rval;
int control_ids[GAME_CONTROLLERS_COUNT];
struct controller_input_compat cin_compats[GAME_CONTROLLERS_COUNT];
@@ -1722,6 +1723,13 @@ m64p_error main_run(void)
dd_rom_size = 0;
}
+ /* ensure the 64DD rom & disk are loaded,
+ * otherwise we have to bail right now */
+ if (g_rom_size == 0 && dd_rom_size == 0)
+ {
+ goto on_disk_failure;
+ }
+
/* setup pif channel devices */
void* joybus_devices[PIF_CHANNELS_COUNT];
const struct joybus_device_interface* ijoybus_devices[PIF_CHANNELS_COUNT];
@@ -1906,6 +1914,7 @@ m64p_error main_run(void)
&dd_disk, dd_idisk);
// Attach rom to plugins
+ failure_rval = M64ERR_PLUGIN_FAIL;
if (!gfx.romOpen())
{
goto on_gfx_open_failure;
@@ -1995,6 +2004,10 @@ m64p_error main_run(void)
return M64ERR_SUCCESS;
+on_disk_failure:
+ failure_rval = M64ERR_INVALID_STATE;
+ rsp.romClosed();
+ input.romClosed();
on_input_open_failure:
audio.romClosed();
on_audio_open_failure:
@@ -2018,7 +2031,7 @@ on_gfx_open_failure:
close_file_storage(&mpk);
close_dd_disk(&dd_disk);
- return M64ERR_PLUGIN_FAIL;
+ return failure_rval;
}
void main_stop(void)
diff --git a/mupen64plus-core/src/main/rom.c b/mupen64plus-core/src/main/rom.c
index 14b9caf..3998a92 100644
--- a/mupen64plus-core/src/main/rom.c
+++ b/mupen64plus-core/src/main/rom.c
@@ -36,6 +36,8 @@
#include "api/config.h"
#include "api/m64p_config.h"
#include "api/m64p_types.h"
+#include "device/dd/disk.h"
+#include "backends/file_storage.h"
#include "device/device.h"
#include "main.h"
#include "md5.h"
@@ -373,6 +375,126 @@ m64p_error close_rom(void)
return M64ERR_SUCCESS;
}
+m64p_error open_disk(void)
+{
+ md5_state_t state;
+ md5_byte_t digest[16];
+ romdatabase_entry* entry;
+ char buffer[256];
+ int i;
+
+ /* ask the core loader for DD disk filename */
+ char* dd_disk_filename = (g_media_loader.get_dd_disk == NULL)
+ ? NULL
+ : g_media_loader.get_dd_disk(g_media_loader.cb_data);
+
+ /* handle the no disk case */
+ if (dd_disk_filename == NULL || strlen(dd_disk_filename) == 0) {
+ goto no_disk;
+ }
+
+ /* Get DD Disk size */
+ size_t dd_size = 0;
+ if (get_file_size(dd_disk_filename, &dd_size) != file_ok) {
+ goto no_disk;
+ }
+
+ struct file_storage* fstorage = malloc(sizeof(struct file_storage));
+ if (fstorage == NULL) {
+ goto no_disk;
+ }
+
+ /* Try loading regular disk file */
+ if (open_rom_file_storage(fstorage, dd_disk_filename) != file_ok) {
+ goto free_fstorage;
+ }
+
+ /* Scan disk to deduce disk format and other parameters and expand its size for D64 */
+ unsigned int format = 0;
+ unsigned int development = 0;
+ size_t offset_sys = 0;
+ size_t offset_id = 0;
+ size_t offset_ram = 0;
+ size_t size_ram = 0;
+ uint8_t* new_data = scan_and_expand_disk_format(fstorage->data, fstorage->size, &format, &development, &offset_sys, &offset_id, &offset_ram, &size_ram);
+ if (new_data == NULL) {
+ goto wrong_disk_format;
+ }
+ else {
+ fstorage->data = new_data;
+ }
+
+ /* Calculate MD5 hash */
+ md5_init(&state);
+ md5_append(&state, (const md5_byte_t*)(fstorage->data), fstorage->size);
+ md5_finish(&state, digest);
+ for ( i = 0; i < 16; ++i )
+ sprintf(buffer+i*2, "%02X", digest[i]);
+ buffer[32] = '\0';
+ strcpy(ROM_SETTINGS.MD5, buffer);
+
+ /* Look up this disk in the .ini file and fill in goodname, etc */
+ if ((entry=ini_search_by_md5(digest)) != NULL)
+ {
+ strncpy(ROM_SETTINGS.goodname, entry->goodname, 255);
+ ROM_SETTINGS.goodname[255] = '\0';
+ ROM_SETTINGS.savetype = entry->savetype;
+ ROM_SETTINGS.status = entry->status;
+ ROM_SETTINGS.players = entry->players;
+ ROM_SETTINGS.rumble = entry->rumble;
+ ROM_SETTINGS.transferpak = entry->transferpak;
+ ROM_SETTINGS.mempak = entry->mempak;
+ ROM_SETTINGS.biopak = entry->biopak;
+ ROM_SETTINGS.disableextramem = entry->disableextramem;
+ ROM_PARAMS.cheats = entry->cheats;
+ }
+ else
+ {
+ strcpy(ROM_SETTINGS.goodname, "(unknown disk)");
+ /* There's no way to guess the save type, but 4K EEPROM is better than nothing */
+ ROM_SETTINGS.savetype = SAVETYPE_EEPROM_4K;
+ ROM_SETTINGS.status = 0;
+ ROM_SETTINGS.players = 4;
+ ROM_SETTINGS.rumble = 1;
+ ROM_SETTINGS.transferpak = 0;
+ ROM_SETTINGS.mempak = 1;
+ ROM_SETTINGS.biopak = 0;
+ ROM_SETTINGS.disableextramem = DEFAULT_DISABLE_EXTRA_MEM;
+ ROM_PARAMS.cheats = NULL;
+ }
+
+ /* set system type */
+ ROM_PARAMS.systemtype = SYSTEM_NTSC;
+
+ /* clear rom header & size */
+ memset(&ROM_HEADER, 0, sizeof(m64p_rom_header));
+ memset(ROM_PARAMS.headername, 0, 20);
+ g_rom_size = 0;
+
+ close_file_storage(fstorage);
+ free(fstorage);
+ return M64ERR_SUCCESS;
+
+wrong_disk_format:
+ close_file_storage(fstorage);
+ dd_disk_filename = NULL; /* already freed in close_file_storage */
+free_fstorage:
+ free(fstorage);
+no_disk:
+ if (dd_disk_filename != NULL) {
+ free(dd_disk_filename);
+ }
+
+ DebugMessage(M64MSG_ERROR, "open_disk(): not a valid disk image");
+ return M64ERR_INPUT_INVALID;
+}
+
+m64p_error close_disk(void)
+{
+ DebugMessage(M64MSG_STATUS, "Disk closed.");
+ return M64ERR_SUCCESS;
+}
+
/********************************************************************************************/
/* ROM utility functions */
diff --git a/mupen64plus-core/src/main/rom.h b/mupen64plus-core/src/main/rom.h
index e88a9b9..9aa22aa 100644
--- a/mupen64plus-core/src/main/rom.h
+++ b/mupen64plus-core/src/main/rom.h
@@ -41,6 +41,9 @@
m64p_error open_rom(const unsigned char* romimage, unsigned int size);
m64p_error close_rom(void);
+m64p_error open_disk(void);
+m64p_error close_disk(void);
+
extern int g_rom_size;
typedef struct _rom_params
diff --git a/mupen64plus-core/src/main/version.h b/mupen64plus-core/src/main/version.h
index 2e1974a..4dcbcdf 100644
--- a/mupen64plus-core/src/main/version.h
+++ b/mupen64plus-core/src/main/version.h
@@ -27,7 +27,7 @@
#define MUPEN_CORE_NAME "Mupen64Plus Core"
#define MUPEN_CORE_VERSION 0x020509
-#define FRONTEND_API_VERSION 0x020104
+#define FRONTEND_API_VERSION 0x020105
#define CONFIG_API_VERSION 0x020302
#define DEBUG_API_VERSION 0x020001
#define VIDEXT_API_VERSION 0x030200
diff --git a/mupen64plus-core/src/plugin/plugin.c b/mupen64plus-core/src/plugin/plugin.c
index fd5944f..4047e65 100644
--- a/mupen64plus-core/src/plugin/plugin.c
+++ b/mupen64plus-core/src/plugin/plugin.c
@@ -246,7 +246,7 @@ static m64p_error plugin_start_gfx(void)
? NULL
: g_media_loader.get_dd_rom(g_media_loader.cb_data);
- uint32_t rom_base = (dd_ipl_rom_filename != NULL && strlen(dd_ipl_rom_filename) != 0 && media != 'C')
+ uint32_t rom_base = (g_rom_size == 0 || (dd_ipl_rom_filename != NULL && strlen(dd_ipl_rom_filename) != 0 && media != 'C'))
? MM_DD_ROM
: MM_CART_ROM;