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;