diff --git a/data/mupen64plus.ini b/data/mupen64plus.ini index 78c15776..a83be182 100644 --- a/data/mupen64plus.ini +++ b/data/mupen64plus.ini @@ -11,7 +11,6 @@ CRC=B2242748 FFBD61DA Status=1 Rumble=Yes Players=4 -CountPerOp=1 [34AB1DEA3111A233A8B5C5679DE22E83] GoodName=007 - The World is Not Enough (E) (M3) [!] @@ -12886,7 +12885,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [55A789C553827114306E29D71E26E5DC] GoodName=Quake II (E) [h1C] @@ -12900,7 +12898,6 @@ Players=4 SaveType=None Mempak=Yes Rumble=Yes -CountPerOp=1 [920FAACCE1F8A80022433ACFD5CD2BC3] GoodName=Quake II (U) [f1] (PAL) diff --git a/src/api/frontend.c b/src/api/frontend.c index d9cc1523..ce76e60f 100644 --- a/src/api/frontend.c +++ b/src/api/frontend.c @@ -19,20 +19,18 @@ * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - + /* This file contains the Core front-end functions which will be exported * outside of the core library. */ -#include #include #include #include -#include #define M64P_CORE_PROTOTYPES 1 #include "callbacks.h" -#include "config.h" +#include "api/config.h" #include "m64p_config.h" #include "m64p_frontend.h" #include "m64p_types.h" @@ -43,8 +41,8 @@ #include "main/savestates.h" #include "main/util.h" #include "main/version.h" +#include "main/cheat.h" #include "main/workqueue.h" -#include "main/screenshot.h" #include "main/netplay.h" #include "plugin/plugin.h" #include "vidext.h" @@ -64,7 +62,7 @@ EXPORT m64p_error CALL CoreStartup(int APIVersion, const char *ConfigPath, const return M64ERR_ALREADY_INIT; /* check wether the caller has already initialized SDL */ - l_CallerUsingSDL = (SDL_WasInit(0) != 0); + l_CallerUsingSDL = 1; //(SDL_WasInit(0) != 0); /* very first thing is to set the callback functions for debug info and state changing*/ SetDebugCallback(DebugCallback, Context); @@ -81,25 +79,6 @@ EXPORT m64p_error CALL CoreStartup(int APIVersion, const char *ConfigPath, const /* Initialize the main device structure to all zeros */ memset(&g_dev, 0, sizeof(struct device)); - /* set up the default (dummy) plugins */ - plugin_connect(M64PLUGIN_GFX, NULL); - plugin_connect(M64PLUGIN_AUDIO, NULL); - plugin_connect(M64PLUGIN_INPUT, NULL); - plugin_connect(M64PLUGIN_CORE, NULL); - - savestates_init(); - - /* next, start up the configuration handling code by loading and parsing the config file */ - if (ConfigInit(ConfigPath, DataPath) != M64ERR_SUCCESS) - return M64ERR_INTERNAL; - - /* set default configuration parameter values for Core */ - if (ConfigOpenSection("Core", &g_CoreConfig) != M64ERR_SUCCESS || g_CoreConfig == NULL) - return M64ERR_INTERNAL; - - if (!main_set_core_defaults()) - return M64ERR_INTERNAL; - /* allocate base memory */ g_mem_base = init_mem_base(); if (g_mem_base == NULL) { @@ -126,10 +105,6 @@ EXPORT m64p_error CALL CoreShutdown(void) workqueue_shutdown(); savestates_deinit(); - /* if the calling code is using SDL, don't shut it down */ - if (!l_CallerUsingSDL) - SDL_Quit(); - /* deallocate base memory */ release_mem_base(g_mem_base); g_mem_base = NULL; @@ -143,32 +118,12 @@ EXPORT m64p_error CALL CoreShutdown(void) EXPORT m64p_error CALL CoreAttachPlugin(m64p_plugin_type PluginType, m64p_dynlib_handle PluginLibHandle) { - m64p_error rval; - - if (!l_CoreInit) - return M64ERR_NOT_INIT; - if (g_EmulatorRunning || (!l_ROMOpen && !l_DiskOpen)) - return M64ERR_INVALID_STATE; - - rval = plugin_connect(PluginType, PluginLibHandle); - if (rval != M64ERR_SUCCESS) - return rval; - - rval = plugin_start(PluginType); - if (rval != M64ERR_SUCCESS) - return rval; - return M64ERR_SUCCESS; } EXPORT m64p_error CALL CoreDetachPlugin(m64p_plugin_type PluginType) { - if (!l_CoreInit) - return M64ERR_NOT_INIT; - if (g_EmulatorRunning) - return M64ERR_INVALID_STATE; - - return plugin_connect(PluginType, NULL); + return M64ERR_SUCCESS; } EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *ParamPtr) @@ -193,7 +148,6 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P if (rval == M64ERR_SUCCESS) { l_ROMOpen = 1; - ScreenshotRomOpen(); cheat_init(&g_cheat_ctx); } return rval; @@ -235,7 +189,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P return M64ERR_INVALID_STATE; if (ParamPtr == NULL) return M64ERR_INPUT_ASSERT; - if ((int)sizeof(m64p_rom_header) < ParamInt) + if (sizeof(m64p_rom_header) < ParamInt) ParamInt = sizeof(m64p_rom_header); memcpy(ParamPtr, &ROM_HEADER, ParamInt); // Mupen64Plus used to keep a m64p_rom_header with a clean ROM name @@ -251,7 +205,7 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P return M64ERR_INVALID_STATE; if (ParamPtr == NULL) return M64ERR_INPUT_ASSERT; - if ((int)sizeof(m64p_rom_settings) < ParamInt) + if (sizeof(m64p_rom_settings) < ParamInt) ParamInt = sizeof(m64p_rom_settings); memcpy(ParamPtr, &ROM_SETTINGS, ParamInt); return M64ERR_SUCCESS; @@ -267,8 +221,6 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P case M64CMD_EXECUTE: if (g_EmulatorRunning || (!l_ROMOpen && !l_DiskOpen)) return M64ERR_INVALID_STATE; - /* print out plugin-related warning messages */ - plugin_check(); /* the main_run() function will not return until the player has quit the game */ rval = main_run(); return rval; @@ -294,14 +246,12 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P return M64ERR_INPUT_ASSERT; return main_core_state_set((m64p_core_param) ParamInt, *((int *)ParamPtr)); case M64CMD_STATE_LOAD: - main_state_load((char *) ParamPtr); return M64ERR_SUCCESS; case M64CMD_STATE_SAVE: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; if (ParamPtr != NULL && (ParamInt < 1 || ParamInt > 3)) return M64ERR_INPUT_INVALID; - main_state_save(ParamInt, (char *) ParamPtr); return M64ERR_SUCCESS; case M64CMD_STATE_SET_SLOT: if (ParamInt < 0 || ParamInt > 9) @@ -312,31 +262,20 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P return M64ERR_INVALID_STATE; keysym = ParamInt & 0xffff; keymod = (ParamInt >> 16) & 0xffff; - event_sdl_keydown(keysym, keymod); return M64ERR_SUCCESS; case M64CMD_SEND_SDL_KEYUP: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; keysym = ParamInt & 0xffff; keymod = (ParamInt >> 16) & 0xffff; - event_sdl_keyup(keysym, keymod); return M64ERR_SUCCESS; case M64CMD_SET_FRAME_CALLBACK: - *(void**)&g_FrameCallback = ParamPtr; + g_FrameCallback = (m64p_frame_callback) ParamPtr; return M64ERR_SUCCESS; case M64CMD_TAKE_NEXT_SCREENSHOT: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; - main_take_next_screenshot(); return M64ERR_SUCCESS; - case M64CMD_READ_SCREEN: - if (!g_EmulatorRunning) - return M64ERR_INVALID_STATE; - if (ParamPtr == NULL) - return M64ERR_INPUT_ASSERT; - if (ParamInt < 0 || ParamInt > 1) - return M64ERR_INPUT_INVALID; - return main_read_screen(ParamPtr, ParamInt); case M64CMD_RESET: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; @@ -346,12 +285,6 @@ EXPORT m64p_error CALL CoreDoCommand(m64p_command Command, int ParamInt, void *P case M64CMD_ADVANCE_FRAME: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; - main_advance_one(); - return M64ERR_SUCCESS; - case M64CMD_SET_MEDIA_LOADER: - if (ParamInt != sizeof(m64p_media_loader) || ParamPtr == NULL) - return M64ERR_INPUT_INVALID; - g_media_loader = *(m64p_media_loader*)ParamPtr; return M64ERR_SUCCESS; case M64CMD_NETPLAY_INIT: if (ParamInt < 1 || ParamPtr == NULL) @@ -433,7 +366,7 @@ EXPORT m64p_error CALL CoreGetRomSettings(m64p_rom_settings *RomSettings, int Ro return M64ERR_NOT_INIT; if (RomSettings == NULL) return M64ERR_INPUT_ASSERT; - if (RomSettingsLength < (int)sizeof(m64p_rom_settings)) + if (RomSettingsLength < sizeof(m64p_rom_settings)) return M64ERR_INPUT_INVALID; /* Look up this ROM in the .ini file and fill in goodname, etc */ diff --git a/src/api/vidext.c b/src/api/vidext.c index 82cc1088..9566876d 100644 --- a/src/api/vidext.c +++ b/src/api/vidext.c @@ -23,15 +23,6 @@ * outside of the core library. */ -#include -/* we need at least SDL 2.0.6 for vulkan */ -#if !SDL_VERSION_ATLEAST(2,0,6) - #undef VIDEXT_VULKAN -#endif -#ifdef VIDEXT_VULKAN -#include -#include -#endif #include #include diff --git a/src/backends/file_storage.c b/src/backends/file_storage.c index 0b5d4a83..313102fe 100644 --- a/src/backends/file_storage.c +++ b/src/backends/file_storage.c @@ -30,6 +30,9 @@ #include "main/util.h" #include "main/netplay.h" +#include +#include + int open_file_storage(struct file_storage* fstorage, size_t size, const char* filename) { /* ! Take ownership of filename ! */ @@ -73,8 +76,17 @@ int open_rom_file_storage(struct file_storage* fstorage, const char* filename) void close_file_storage(struct file_storage* fstorage) { - free((void*)fstorage->data); - free((void*)fstorage->filename); + if(fstorage->data) + { + free((void*)fstorage->data); + fstorage->data = NULL; + } + + if(fstorage->filename) + { + free((void*)fstorage->filename); + fstorage->filename = NULL; + } } @@ -94,7 +106,7 @@ static void file_storage_save(void* storage, size_t start, size_t size) { if (netplay_is_init() && netplay_get_controller(0) == -1) return; - + struct file_storage* fstorage = (struct file_storage*)storage; file_status_t err; @@ -112,10 +124,10 @@ static void file_storage_save(void* storage, size_t start, size_t size) switch(err) { case file_open_error: - DebugMessage(M64MSG_WARNING, "couldn't open storage file '%s' for writing", fstorage->filename); + log_cb(RETRO_LOG_WARN, "Couldn't open storage file '%s' for writing\n", fstorage->filename); break; case file_write_error: - DebugMessage(M64MSG_WARNING, "failed to write storage file '%s'", fstorage->filename); + log_cb(RETRO_LOG_WARN, "Failed to write storage file '%s'\n", fstorage->filename); break; default: break; diff --git a/src/backends/plugins_compat/audio_plugin_compat.c b/src/backends/plugins_compat/audio_plugin_compat.c index 327a4048..14287f1a 100644 --- a/src/backends/plugins_compat/audio_plugin_compat.c +++ b/src/backends/plugins_compat/audio_plugin_compat.c @@ -20,6 +20,17 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include +#include "plugins_compat.h" + +#include "api/m64p_plugin.h" +#include "plugin/plugin.h" + +#include "main/main.h" + +#include +#include +#include +#include #include "backends/api/audio_out_backend.h" #include "device/rcp/ai/ai_controller.h" @@ -27,7 +38,7 @@ #include "device/rcp/vi/vi_controller.h" #include "device/rdram/rdram.h" #include "main/rom.h" -#include "plugin/plugin.h" + static void audio_plugin_set_frequency(void* aout, unsigned int frequency) { diff --git a/src/backends/plugins_compat/input_plugin_compat.c b/src/backends/plugins_compat/input_plugin_compat.c index ceb1128a..8ebdd059 100644 --- a/src/backends/plugins_compat/input_plugin_compat.c +++ b/src/backends/plugins_compat/input_plugin_compat.c @@ -33,6 +33,7 @@ #include #include #include +#include /* XXX: this is an abuse of the Zilmar Spec normally this value is reserved */ enum { @@ -90,7 +91,6 @@ static m64p_error input_plugin_get_input(void* opaque, uint32_t* input_) return M64ERR_SYSTEM_FAIL; } - /* has Controls[i].Plugin changed since last call */ if (cin_compat->last_pak_type != Controls[cin_compat->control_id].Plugin) { pak_change_requested = 1; @@ -114,18 +114,25 @@ static m64p_error input_plugin_get_input(void* opaque, uint32_t* input_) if (cin_compat->pak_switch_delay > 0 && --cin_compat->pak_switch_delay == 0) { cin_compat->main_switch_pak(cin_compat->control_id); cin_compat->main_switch_pak = NULL; + // If switching to Transfer Pak and if a rom path is set, Switch it + if(Controls[cin_compat->control_id].Plugin == PLUGIN_TRANSFER_PAK && retro_transferpak_rom_path) + { + cin_compat->gb_cart_switch_enabled = 1; + } } if (cin_compat->gb_cart_switch_enabled) { - /* disconnect current GB cart (if any) immediately after "GB cart switch" button is released */ - if (is_button_released(keys.Value, cin_compat->last_input, GB_CART_SWITCH_BUTTON)) { + // disconnect current GB cart (if any) immediately after "GB cart switch" button is released + if (!cin_compat->gb_switch_delay) { change_gb_cart(cin_compat->tpk, NULL); cin_compat->gb_switch_delay = GB_CART_SWITCH_DELAY; } - /* switch to new GB cart after switch delay has expired */ + // switch to new GB cart after switch delay has expired if (cin_compat->gb_switch_delay > 0 && --cin_compat->gb_switch_delay == 0) { main_change_gb_cart(cin_compat->control_id); + cin_compat->gb_cart_switch_enabled = 0; + cin_compat->gb_switch_delay = 0; } } diff --git a/src/device/controllers/paks/biopak.c b/src/device/controllers/paks/biopak.c index 6f5e743a..d08ed149 100644 --- a/src/device/controllers/paks/biopak.c +++ b/src/device/controllers/paks/biopak.c @@ -28,8 +28,11 @@ #include "api/m64p_types.h" #include "api/callbacks.h" -#include +#ifdef HAVE_LIBNX +#include +#endif +#include #include void init_biopak(struct biopak* bpk, @@ -51,7 +54,7 @@ static void read_biopak(void* pak, uint16_t address, uint8_t* data, size_t size) struct biopak* bpk = (struct biopak*)pak; if (address == 0xc000) { - uint32_t now = SDL_GetTicks(); + time_t now = time(NULL) * 1000; uint32_t period = UINT32_C(60*1000) / bpk->bpm; uint32_t k = now % period; diff --git a/src/device/dd/dd_controller.c b/src/device/dd/dd_controller.c index d27172e2..33fafe5a 100644 --- a/src/device/dd/dd_controller.c +++ b/src/device/dd/dd_controller.c @@ -204,8 +204,8 @@ static void read_C2(struct dd_controller* dd) sector %= 90; size_t offset = 0x40 * (sector - SECTORS_PER_BLOCK); - DebugMessage(M64MSG_VERBOSE, "read C2: length=%08x, offset=%08x", - (uint32_t)length, (uint32_t)offset); + //DebugMessage(M64MSG_VERBOSE, "read C2: length=%08x, offset=%08x", + // (uint32_t)length, (uint32_t)offset); for (i = 0; i < length; ++i) { dd->c2s_buf[(offset + i) ^ 3] = 0; @@ -431,7 +431,7 @@ void read_dd_regs(void* opaque, uint32_t address, uint32_t* value) } *value = dd->regs[reg]; - DebugMessage(M64MSG_VERBOSE, "DD REG: %08X -> %08x", address, *value); + //DebugMessage(M64MSG_VERBOSE, "DD REG: %08X -> %08x", address, *value); /* post read update. Not part of the returned value */ switch(reg) @@ -462,7 +462,7 @@ void write_dd_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask assert(mask == ~UINT32_C(0)); - DebugMessage(M64MSG_VERBOSE, "DD REG: %08X <- %08x", address, value); + //DebugMessage(M64MSG_VERBOSE, "DD REG: %08X <- %08x", address, value); switch (reg) { @@ -787,12 +787,12 @@ void read_dd_rom(void* opaque, uint32_t address, uint32_t* value) *value = dd->rom[addr]; - DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X -> %08x", address, *value); + //DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X -> %08x", address, *value); } void write_dd_rom(void* opaque, uint32_t address, uint32_t value, uint32_t mask) { - DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X <- %08x & %08x", address, value, mask); + //DebugMessage(M64MSG_VERBOSE, "DD ROM: %08X <- %08x & %08x", address, value, mask); } unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_addr, uint32_t cart_addr, uint32_t length) @@ -801,8 +801,8 @@ unsigned int dd_dom_dma_read(void* opaque, const uint8_t* dram, uint32_t dram_ad uint8_t* mem; size_t i; - DebugMessage(M64MSG_VERBOSE, "DD DMA read dram=%08x cart=%08x length=%08x", - dram_addr, cart_addr, length); + //DebugMessage(M64MSG_VERBOSE, "DD DMA read dram=%08x cart=%08x length=%08x", + // dram_addr, cart_addr, length); if (cart_addr == MM_DD_DS_BUFFER) { cart_addr = (cart_addr - MM_DD_DS_BUFFER) & 0x3fffff; @@ -836,8 +836,8 @@ unsigned int dd_dom_dma_write(void* opaque, uint8_t* dram, uint32_t dram_addr, u const uint8_t* mem; size_t i; - DebugMessage(M64MSG_VERBOSE, "DD DMA write dram=%08x cart=%08x length=%08x", - dram_addr, cart_addr, length); + //DebugMessage(M64MSG_VERBOSE, "DD DMA write dram=%08x cart=%08x length=%08x", + // dram_addr, cart_addr, length); if (cart_addr < MM_DD_ROM) { if (cart_addr == MM_DD_C2S_BUFFER) { diff --git a/src/device/dd/disk.c b/src/device/dd/disk.c index 7f5e9454..405d28fd 100644 --- a/src/device/dd/disk.c +++ b/src/device/dd/disk.c @@ -330,8 +330,8 @@ static uint8_t* get_sector_base_sdk(const struct dd_disk* disk, } } - if (lba <= MAX_LBA && sector == 0) - DebugMessage(M64MSG_VERBOSE, "LBA %d - Offset %08X - Size %04X", lba, offset, sector_size * SECTORS_PER_BLOCK); + //if (lba <= MAX_LBA && sector == 0) + // DebugMessage(M64MSG_VERBOSE, "LBA %d - Offset %08X - Size %04X", lba, offset, sector_size * SECTORS_PER_BLOCK); return disk->istorage->data(disk->storage) + offset; } @@ -376,8 +376,8 @@ static uint8_t* get_sector_base_d64(const struct dd_disk* disk, return NULL; } - if (lba <= MAX_LBA && sector == 0) - DebugMessage(M64MSG_VERBOSE, "LBA %d - Offset %08X - Size %04X", lba, offset, sector_size * SECTORS_PER_BLOCK); + //if (lba <= MAX_LBA && sector == 0) + // DebugMessage(M64MSG_VERBOSE, "LBA %d - Offset %08X - Size %04X", lba, offset, sector_size * SECTORS_PER_BLOCK); return disk->istorage->data(disk->storage) + offset; } @@ -530,7 +530,7 @@ uint8_t* scan_and_expand_disk_format(uint8_t* data, size_t size, size_t d64_size = D64_OFFSET_DATA + rom_size + ram_size; size_t full_d64_size = D64_OFFSET_DATA + rom_size + RAM_SIZES[disk_type]; - DebugMessage(M64MSG_INFO, "D64 Disk Areas - ROM: 0000 - %04X / RAM: %04X - %04X", rom_lba_end, ram_lba_start, ram_lba_end); + //DebugMessage(M64MSG_INFO, "D64 Disk Areas - ROM: 0000 - %04X / RAM: %04X - %04X", rom_lba_end, ram_lba_start, ram_lba_end); if (ram_lba_start != (RAM_START_LBA[disk_type] - 24) && ram_lba_start != 0xFFFF) { diff --git a/src/device/memory/memory.c b/src/device/memory/memory.c index 715a67ab..6625d198 100644 --- a/src/device/memory/memory.c +++ b/src/device/memory/memory.c @@ -42,10 +42,11 @@ #include #include -#ifdef _WIN32 +#if defined(_WIN32) || defined(HAVE_LIBNX) #include #endif + #ifdef DBG enum { @@ -246,9 +247,14 @@ void* init_mem_base(void) /* First try the full mem base alloc */ #ifdef _WIN32 mem_base = _aligned_malloc(MB_MAX_SIZE_FULL, MB_RDRAM_DRAM_ALIGNMENT_REQUIREMENT); +#else +#ifdef HAVE_LIBNX + if (!(mem_base = memalign(MB_RDRAM_DRAM_ALIGNMENT_REQUIREMENT, MB_MAX_SIZE_FULL))) + mem_base = NULL; #else if (posix_memalign(&mem_base, MB_RDRAM_DRAM_ALIGNMENT_REQUIREMENT, MB_MAX_SIZE_FULL) != 0) mem_base = NULL; +#endif // HAVE_LIBNX #endif if (mem_base == NULL) { /* if it failed, try the compressed mem base alloc */ diff --git a/src/device/r4300/fpu.h b/src/device/r4300/fpu.h index 14c23bba..6d175531 100644 --- a/src/device/r4300/fpu.h +++ b/src/device/r4300/fpu.h @@ -40,7 +40,9 @@ static __inline float truncf(float x) { return (float)(int)x; } #else #define M64P_FPU_INLINE static inline -#include +#if !defined(VITA) && !defined(__SWITCH__) + #include +#endif #endif #define FCR31_CMP_BIT UINT32_C(0x800000) @@ -69,6 +71,7 @@ static __inline float truncf(float x) { return (float)(int)x; } M64P_FPU_INLINE void set_rounding(uint32_t fcr31) { +#if !defined(VITA) && !defined(__SWITCH__) switch(fcr31 & 3) { case 0: /* Round to nearest, or to even if equidistant */ fesetround(FE_TONEAREST); @@ -83,6 +86,7 @@ M64P_FPU_INLINE void set_rounding(uint32_t fcr31) fesetround(FE_DOWNWARD); break; } +#endif } #ifdef ACCURATE_FPU_BEHAVIOR diff --git a/src/device/r4300/new_dynarec/arm/asm_defines_gas.h b/src/device/r4300/new_dynarec/arm/asm_defines_gas.h new file mode 100644 index 00000000..b137e36c --- /dev/null +++ b/src/device/r4300/new_dynarec/arm/asm_defines_gas.h @@ -0,0 +1,35 @@ +#define offsetof_struct_device_r4300 (0x00000000) +#define offsetof_struct_r4300_core_cp0 (0x029014cc) +#define offsetof_struct_cp0_last_addr (0x0000017c) +#define offsetof_struct_cp0_count_per_op (0x00000180) +#define offsetof_struct_cp0_tlb (0x00000188) +#define offsetof_struct_tlb_entries (0x00000000) +#define offsetof_struct_tlb_LUT_r (0x00000680) +#define offsetof_struct_tlb_LUT_w (0x00400680) +#define offsetof_struct_r4300_core_cached_interp (0x00000098) +#define offsetof_struct_cached_interp_invalid_code (0x00000000) +#define offsetof_struct_r4300_core_new_dynarec_hot_state (0x02501000) +#define offsetof_struct_r4300_core_extra_memory (0x00501000) +#define offsetof_struct_new_dynarec_hot_state_dynarec_local (0x00000000) +#define offsetof_struct_new_dynarec_hot_state_cycle_count (0x00000040) +#define offsetof_struct_new_dynarec_hot_state_pending_exception (0x00000044) +#define offsetof_struct_new_dynarec_hot_state_pcaddr (0x00000048) +#define offsetof_struct_new_dynarec_hot_state_stop (0x0000004c) +#define offsetof_struct_new_dynarec_hot_state_invc_ptr (0x00000050) +#define offsetof_struct_new_dynarec_hot_state_fcr0 (0x0000006c) +#define offsetof_struct_new_dynarec_hot_state_fcr31 (0x00000070) +#define offsetof_struct_new_dynarec_hot_state_regs (0x00000078) +#define offsetof_struct_new_dynarec_hot_state_hi (0x00000178) +#define offsetof_struct_new_dynarec_hot_state_lo (0x00000180) +#define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000188) +#define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x00000208) +#define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x00000288) +#define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x00000308) +#define offsetof_struct_new_dynarec_hot_state_branch_target (0x00000318) +#define offsetof_struct_new_dynarec_hot_state_pc (0x0000031c) +#define offsetof_struct_new_dynarec_hot_state_fake_pc (0x00000320) +#define offsetof_struct_new_dynarec_hot_state_rs (0x000003a8) +#define offsetof_struct_new_dynarec_hot_state_rt (0x000003b0) +#define offsetof_struct_new_dynarec_hot_state_rd (0x000003b8) +#define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000003c4) +#define offsetof_struct_new_dynarec_hot_state_memory_map (0x000004c4) diff --git a/src/device/r4300/new_dynarec/arm/asm_defines_nasm.h b/src/device/r4300/new_dynarec/arm/asm_defines_nasm.h new file mode 100644 index 00000000..508dc99b --- /dev/null +++ b/src/device/r4300/new_dynarec/arm/asm_defines_nasm.h @@ -0,0 +1,35 @@ +%define offsetof_struct_device_r4300 (0x00000000) +%define offsetof_struct_r4300_core_cp0 (0x029014cc) +%define offsetof_struct_cp0_last_addr (0x0000017c) +%define offsetof_struct_cp0_count_per_op (0x00000180) +%define offsetof_struct_cp0_tlb (0x00000188) +%define offsetof_struct_tlb_entries (0x00000000) +%define offsetof_struct_tlb_LUT_r (0x00000680) +%define offsetof_struct_tlb_LUT_w (0x00400680) +%define offsetof_struct_r4300_core_cached_interp (0x00000098) +%define offsetof_struct_cached_interp_invalid_code (0x00000000) +%define offsetof_struct_r4300_core_new_dynarec_hot_state (0x02501000) +%define offsetof_struct_r4300_core_extra_memory (0x00501000) +%define offsetof_struct_new_dynarec_hot_state_dynarec_local (0x00000000) +%define offsetof_struct_new_dynarec_hot_state_cycle_count (0x00000040) +%define offsetof_struct_new_dynarec_hot_state_pending_exception (0x00000044) +%define offsetof_struct_new_dynarec_hot_state_pcaddr (0x00000048) +%define offsetof_struct_new_dynarec_hot_state_stop (0x0000004c) +%define offsetof_struct_new_dynarec_hot_state_invc_ptr (0x00000050) +%define offsetof_struct_new_dynarec_hot_state_fcr0 (0x0000006c) +%define offsetof_struct_new_dynarec_hot_state_fcr31 (0x00000070) +%define offsetof_struct_new_dynarec_hot_state_regs (0x00000078) +%define offsetof_struct_new_dynarec_hot_state_hi (0x00000178) +%define offsetof_struct_new_dynarec_hot_state_lo (0x00000180) +%define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000188) +%define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x00000208) +%define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x00000288) +%define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x00000308) +%define offsetof_struct_new_dynarec_hot_state_branch_target (0x00000318) +%define offsetof_struct_new_dynarec_hot_state_pc (0x0000031c) +%define offsetof_struct_new_dynarec_hot_state_fake_pc (0x00000320) +%define offsetof_struct_new_dynarec_hot_state_rs (0x000003a8) +%define offsetof_struct_new_dynarec_hot_state_rt (0x000003b0) +%define offsetof_struct_new_dynarec_hot_state_rd (0x000003b8) +%define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000003c4) +%define offsetof_struct_new_dynarec_hot_state_memory_map (0x000004c4) diff --git a/src/device/r4300/new_dynarec/arm64/asm_defines_gas.h b/src/device/r4300/new_dynarec/arm64/asm_defines_gas.h new file mode 100644 index 00000000..15fc3f6b --- /dev/null +++ b/src/device/r4300/new_dynarec/arm64/asm_defines_gas.h @@ -0,0 +1,35 @@ +#define offsetof_struct_device_r4300 (0x00000000) +#define offsetof_struct_r4300_core_cp0 (0x031017d8) +#define offsetof_struct_cp0_last_addr (0x00000278) +#define offsetof_struct_cp0_count_per_op (0x0000027c) +#define offsetof_struct_cp0_tlb (0x00000284) +#define offsetof_struct_tlb_entries (0x00000000) +#define offsetof_struct_tlb_LUT_r (0x00000680) +#define offsetof_struct_tlb_LUT_w (0x00400680) +#define offsetof_struct_r4300_core_cached_interp (0x000000e0) +#define offsetof_struct_cached_interp_invalid_code (0x00000000) +#define offsetof_struct_r4300_core_new_dynarec_hot_state (0x02901000) +#define offsetof_struct_r4300_core_extra_memory (0x00901000) +#define offsetof_struct_new_dynarec_hot_state_dynarec_local (0x00000000) +#define offsetof_struct_new_dynarec_hot_state_cycle_count (0x00000100) +#define offsetof_struct_new_dynarec_hot_state_pending_exception (0x00000104) +#define offsetof_struct_new_dynarec_hot_state_pcaddr (0x00000108) +#define offsetof_struct_new_dynarec_hot_state_stop (0x0000010c) +#define offsetof_struct_new_dynarec_hot_state_invc_ptr (0x00000110) +#define offsetof_struct_new_dynarec_hot_state_fcr0 (0x00000134) +#define offsetof_struct_new_dynarec_hot_state_fcr31 (0x00000138) +#define offsetof_struct_new_dynarec_hot_state_regs (0x00000140) +#define offsetof_struct_new_dynarec_hot_state_hi (0x00000240) +#define offsetof_struct_new_dynarec_hot_state_lo (0x00000248) +#define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000250) +#define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x000002d0) +#define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x000003d0) +#define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x000004d0) +#define offsetof_struct_new_dynarec_hot_state_branch_target (0x000004e0) +#define offsetof_struct_new_dynarec_hot_state_pc (0x000004e8) +#define offsetof_struct_new_dynarec_hot_state_fake_pc (0x000004f0) +#define offsetof_struct_new_dynarec_hot_state_rs (0x000005b0) +#define offsetof_struct_new_dynarec_hot_state_rt (0x000005b8) +#define offsetof_struct_new_dynarec_hot_state_rd (0x000005c0) +#define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000005d0) +#define offsetof_struct_new_dynarec_hot_state_memory_map (0x000007d0) diff --git a/src/device/r4300/new_dynarec/arm64/asm_defines_nasm.h b/src/device/r4300/new_dynarec/arm64/asm_defines_nasm.h new file mode 100644 index 00000000..a1a12ebd --- /dev/null +++ b/src/device/r4300/new_dynarec/arm64/asm_defines_nasm.h @@ -0,0 +1,35 @@ +%define offsetof_struct_device_r4300 (0x00000000) +%define offsetof_struct_r4300_core_cp0 (0x031017d8) +%define offsetof_struct_cp0_last_addr (0x00000278) +%define offsetof_struct_cp0_count_per_op (0x0000027c) +%define offsetof_struct_cp0_tlb (0x00000284) +%define offsetof_struct_tlb_entries (0x00000000) +%define offsetof_struct_tlb_LUT_r (0x00000680) +%define offsetof_struct_tlb_LUT_w (0x00400680) +%define offsetof_struct_r4300_core_cached_interp (0x000000e0) +%define offsetof_struct_cached_interp_invalid_code (0x00000000) +%define offsetof_struct_r4300_core_new_dynarec_hot_state (0x02901000) +%define offsetof_struct_r4300_core_extra_memory (0x00901000) +%define offsetof_struct_new_dynarec_hot_state_dynarec_local (0x00000000) +%define offsetof_struct_new_dynarec_hot_state_cycle_count (0x00000100) +%define offsetof_struct_new_dynarec_hot_state_pending_exception (0x00000104) +%define offsetof_struct_new_dynarec_hot_state_pcaddr (0x00000108) +%define offsetof_struct_new_dynarec_hot_state_stop (0x0000010c) +%define offsetof_struct_new_dynarec_hot_state_invc_ptr (0x00000110) +%define offsetof_struct_new_dynarec_hot_state_fcr0 (0x00000134) +%define offsetof_struct_new_dynarec_hot_state_fcr31 (0x00000138) +%define offsetof_struct_new_dynarec_hot_state_regs (0x00000140) +%define offsetof_struct_new_dynarec_hot_state_hi (0x00000240) +%define offsetof_struct_new_dynarec_hot_state_lo (0x00000248) +%define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000250) +%define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x000002d0) +%define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x000003d0) +%define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x000004d0) +%define offsetof_struct_new_dynarec_hot_state_branch_target (0x000004e0) +%define offsetof_struct_new_dynarec_hot_state_pc (0x000004e8) +%define offsetof_struct_new_dynarec_hot_state_fake_pc (0x000004f0) +%define offsetof_struct_new_dynarec_hot_state_rs (0x000005b0) +%define offsetof_struct_new_dynarec_hot_state_rt (0x000005b8) +%define offsetof_struct_new_dynarec_hot_state_rd (0x000005c0) +%define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000005d0) +%define offsetof_struct_new_dynarec_hot_state_memory_map (0x000007d0) diff --git a/src/device/r4300/new_dynarec/arm64/assem_arm64.c b/src/device/r4300/new_dynarec/arm64/assem_arm64.c index 84097657..98dea54f 100644 --- a/src/device/r4300/new_dynarec/arm64/assem_arm64.c +++ b/src/device/r4300/new_dynarec/arm64/assem_arm64.c @@ -302,6 +302,9 @@ static void set_jump_target(intptr_t addr,uintptr_t target) intptr_t offset=target-(intptr_t)addr; if(ptr==NULL) return; + if(!ptr) // Indiana Jones is weird + return; + if((*ptr&0xFC000000)==0x14000000) { assert(offset>=-134217728LL&&offset<134217728LL); *ptr=(*ptr&0xFC000000)|((offset>>2)&0x3ffffff); @@ -354,6 +357,9 @@ static void *kill_pointer(void *stub) int *i_ptr=(int*)((intptr_t)ptr+offset); assert((*i_ptr&0xfc000000)==0x14000000); //b set_jump_target((intptr_t)i_ptr,(intptr_t)stub); + + intptr_t ptr_rx=((intptr_t)i_ptr-(intptr_t)base_addr)+(intptr_t)base_addr_rx; + cache_flush((void*)ptr_rx, (void*)(ptr_rx+4)); return i_ptr; } @@ -2994,7 +3000,7 @@ static void emit_adr(intptr_t addr, int rt) intptr_t offset=addr-(intptr_t)out_rx; assert(offset>=-1048576LL&&offset<1048576LL); - assem_debug("adr %d,#%d",regname64[rt],offset); + assem_debug("adr %s,#%d",regname64[rt],offset); output_w32(0x10000000|(offset&0x3)<<29|((offset>>2)&0x7ffff)<<5|rt); } static void emit_adrp(intptr_t addr, int rt) @@ -3007,7 +3013,7 @@ static void emit_adrp(intptr_t addr, int rt) assert(offset>=-4294967296LL&&offset<4294967296LL); offset>>=12; assert((((intptr_t)out_rx&~0xfffLL)+(offset<<12))==(addr&~0xfffLL)); - assem_debug("adrp %d,#%d",regname64[rt],offset); + assem_debug("adrp %s,#%d",regname64[rt],offset); output_w32(0x90000000|(offset&0x3)<<29|((offset>>2)&0x7ffff)<<5|rt); } #if 0 @@ -4484,7 +4490,8 @@ static void multdiv_assemble_arm64(int i,struct regstat *i_regs) assert(r1l>=0); assert(r2l>=0); - for(int hr=0;hrregmap[hr]>=0) reglist|=1< #include // needed for u_int, u_char, etc #include +#include #if defined(WIN32) #ifndef WIN32_LEAN_AND_MEAN @@ -55,7 +56,11 @@ #include "device/rcp/rsp/rsp_core.h" #if !defined(WIN32) +#ifndef HAVE_LIBNX #include +#else +#include "../../../../../switch/mman.h" +#endif // HAVE_LIBNX #endif #if defined(RECOMPILER_DEBUG) && !defined(RECOMP_DBG) @@ -149,6 +154,8 @@ static void ensure_dynarec_cache_alignment(void) #define assem_debug(...) DebugMessage(M64MSG_VERBOSE, __VA_ARGS__) #else #define assem_debug(...) + // Cleanup debug copies + #define strcpy(...) #endif #if INV_DEBUG #define inv_debug(...) DebugMessage(M64MSG_VERBOSE, __VA_ARGS__) @@ -2520,7 +2527,7 @@ static void ll_kill_pointers(struct ll_entry *head,intptr_t addr,int shift) { inv_debug("EXP: Kill pointer at %x (%x)\n",(intptr_t)head->addr,head->vaddr); uintptr_t host_addr=(intptr_t)kill_pointer(head->addr); - #if NEW_DYNAREC >= NEW_DYNAREC_ARM + #if NEW_DYNAREC == NEW_DYNAREC_ARM needs_clear_cache[(host_addr-(uintptr_t)base_addr)>>17]|=1<<(((host_addr-(uintptr_t)base_addr)>>12)&31); #else /* avoid unused variable warning */ @@ -2861,7 +2868,7 @@ static void invalidate_page(u_int page) while(head!=NULL) { inv_debug("INVALIDATE: kill pointer to %x (%x)\n",head->vaddr,(intptr_t)head->addr); uintptr_t host_addr=(intptr_t)kill_pointer(head->addr); - #if NEW_DYNAREC >= NEW_DYNAREC_ARM + #if NEW_DYNAREC == NEW_DYNAREC_ARM needs_clear_cache[(host_addr-(uintptr_t)base_addr)>>17]|=1<<(((host_addr-(uintptr_t)base_addr)>>12)&31); #else /* avoid unused variable warning */ @@ -8696,6 +8703,9 @@ static void pagespan_ds(void) } /**** Recompiler ****/ +#ifdef HAVE_LIBNX +ALIGN(4096, char jit_memory[33554432]) __attribute__((section(".text"))); +#endif void new_dynarec_init(void) { DebugMessage(M64MSG_INFO, "Init new dynarec"); @@ -8713,9 +8723,17 @@ void new_dynarec_init(void) #define DOUBLE_CACHE_ADDR 3 // Put the dynarec cache at random address with RW address != RX address // Default to fixed cache address +#ifdef HAVE_LIBNX +#define CACHE_ADDR DOUBLE_CACHE_ADDR +#else #define CACHE_ADDR FIXED_CACHE_ADDR +#endif #if CACHE_ADDR==DOUBLE_CACHE_ADDR +#ifdef HAVE_LIBNX + base_addr = mmap((u_char *)jit_memory, 1< #include #include @@ -8736,6 +8754,7 @@ void new_dynarec_init(void) assert(base_addr_rx!=(void*)-1); close(fd); +#endif // HAVE_LIBNX #elif CACHE_ADDR==FIXED_CACHE_ADDR mprotect ((u_char *)g_dev.r4300.extra_memory, 1<=0x80&&ptr[1]<=0x8f); diff --git a/src/device/r4300/new_dynarec/x86/linkage_x86.asm b/src/device/r4300/new_dynarec/x86/linkage_x86.asm index 17c14bb3..379feeed 100644 --- a/src/device/r4300/new_dynarec/x86/linkage_x86.asm +++ b/src/device/r4300/new_dynarec/x86/linkage_x86.asm @@ -55,14 +55,21 @@ section .note.GNU-stack noalloc noexec nowrite progbits add ebx,_GLOBAL_OFFSET_TABLE_+$$-%%getgot wrt ..gotpc %endmacro +%macro get_delta 0 + call %%getdelta + %%getdelta: + pop ebx + sub ebx, %%getdelta +%endmacro + %ifdef PIC %define get_got_address get_GOT %define find_local_data(a) ebx + a wrt ..gotoff %define find_external_data(a) ebx + a wrt ..got %else - %define get_got_address - %define find_local_data(a) a - %define find_extern_data(a) a + %define get_got_address get_delta + %define find_local_data(a) ebx + a + %define find_external_data(a) ebx + a %endif %define g_dev_r4300_new_dynarec_hot_state_stop (g_dev + offsetof_struct_device_r4300 + offsetof_struct_r4300_core_new_dynarec_hot_state + offsetof_struct_new_dynarec_hot_state_stop) diff --git a/src/device/r4300/tlb.c b/src/device/r4300/tlb.c index b7a29e8d..35d3b902 100644 --- a/src/device/r4300/tlb.c +++ b/src/device/r4300/tlb.c @@ -20,6 +20,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "tlb.h" +#include #include "api/m64p_types.h" #include "device/r4300/r4300_core.h" @@ -140,7 +141,35 @@ uint32_t virtual_to_physical_address(struct r4300_core* r4300, uint32_t address, //printf("tlb exception !!! @ %x, %x, add:%x\n", address, w, r4300->pc->addr); //getchar(); - TLB_refill_exception(r4300, address, w); +#ifdef NEW_DYNAREC + if(IgnoreTLBExceptions == 0) { + /* False, Default Behaviour */ + TLB_refill_exception(r4300, address, w); + } else if(IgnoreTLBExceptions == 1) { + /* OnlyNotEnabled */ + if(r4300->emumode == EMUMODE_DYNAREC) + { + if(using_tlb) + { + TLB_refill_exception(r4300, address, w); + } + } else { + TLB_refill_exception(r4300, address, w); + } + } else if(IgnoreTLBExceptions == 2) + { + /* AlwaysIgnoreTLB */ + /* Use-case GdbStub... */ + } +#else + if(IgnoreTLBExceptions == 2) + { + /* AlwaysIgnoreTLB */ + /* Use-case for Interpreter-only GdbStub... */ + } else { + TLB_refill_exception(r4300, address, w); + } +#endif // NEW_DYNAREC //return 0x80000000; return 0x00000000; diff --git a/src/device/rcp/vi/vi_controller.c b/src/device/rcp/vi/vi_controller.c index b644fcd7..e3b035d8 100644 --- a/src/device/rcp/vi/vi_controller.c +++ b/src/device/rcp/vi/vi_controller.c @@ -29,6 +29,7 @@ #include "device/rcp/mi/mi_controller.h" #include "main/main.h" #include "plugin/plugin.h" +#include unsigned int vi_clock_from_tv_standard(m64p_system_type tv_standard) { @@ -79,8 +80,13 @@ void poweron_vi(struct vi_controller* vi) { memset(vi->regs, 0, VI_REGS_COUNT*sizeof(uint32_t)); vi->field = 0; - vi->delay = 0; - vi->count_per_scanline = 0; + if(!CountPerScanlineOverride) { + vi->delay = 0; + vi->count_per_scanline = 0; + } else { + vi->delay = 5000; + vi->count_per_scanline = CountPerScanlineOverride; + } } void read_vi_regs(void* opaque, uint32_t address, uint32_t* value) @@ -142,7 +148,11 @@ void write_vi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask if ((vi->regs[VI_V_SYNC_REG] & mask) != (value & mask)) { masked_write(&vi->regs[VI_V_SYNC_REG], value, mask); - vi->count_per_scanline = (vi->clock / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1); + if(!CountPerScanlineOverride) { + vi->count_per_scanline = (vi->clock / vi->expected_refresh_rate) / (vi->regs[VI_V_SYNC_REG] + 1); + } else { + vi->count_per_scanline = CountPerScanlineOverride; + } vi->delay = (vi->regs[VI_V_SYNC_REG] + 1) * vi->count_per_scanline; set_vi_vertical_interrupt(vi); } @@ -175,6 +185,13 @@ void vi_vertical_interrupt_event(void* opaque) vi->field ^= (vi->regs[VI_STATUS_REG] >> 6) & 0x1; /* schedule next vertical interrupt */ + if(CountPerScanlineOverride) { + if (vi->regs[VI_V_SYNC_REG] == 0) + vi->delay = 500000; + else + vi->delay = (vi->regs[VI_V_SYNC_REG] + 1) * vi->count_per_scanline; + } + uint32_t next_vi = *get_event(&vi->mi->r4300->cp0.q, VI_INT) + vi->delay; remove_interrupt_event(&vi->mi->r4300->cp0); add_interrupt_event_count(&vi->mi->r4300->cp0, VI_INT, next_vi); diff --git a/src/main/cheat.c b/src/main/cheat.c index 8058afad..eb41b782 100644 --- a/src/main/cheat.c +++ b/src/main/cheat.c @@ -22,8 +22,6 @@ /* gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html */ -#include -#include #define __STDC_FORMAT_MACROS #include @@ -193,14 +191,14 @@ static cheat_t *find_or_create_cheat(struct cheat_ctx* ctx, const char *name) /* public functions */ void cheat_init(struct cheat_ctx* ctx) { - ctx->mutex = SDL_CreateMutex(); + ctx->mutex = NULL; //SDL_CreateMutex(); INIT_LIST_HEAD(&ctx->active_cheats); } void cheat_uninit(struct cheat_ctx* ctx) { if (ctx->mutex != NULL) { - SDL_DestroyMutex(ctx->mutex); + //SDL_DestroyMutex(ctx->mutex); } ctx->mutex = NULL; } @@ -210,16 +208,10 @@ void cheat_apply_cheats(struct cheat_ctx* ctx, struct r4300_core* r4300, int ent cheat_t *cheat; cheat_code_t *code; int cond_failed; - + if (list_empty(&ctx->active_cheats)) return; - if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0) - { - DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_apply_cheats()"); - return; - } - list_for_each_entry_t(cheat, &ctx->active_cheats, cheat_t, list) { if (cheat->enabled) { @@ -312,8 +304,6 @@ void cheat_apply_cheats(struct cheat_ctx* ctx, struct r4300_core* r4300, int ent } } } - - SDL_UnlockMutex(ctx->mutex); } @@ -325,12 +315,6 @@ void cheat_delete_all(struct cheat_ctx* ctx) if (list_empty(&ctx->active_cheats)) return; - if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0) - { - DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_delete_all()"); - return; - } - list_for_each_entry_safe_t(cheat, safe_cheat, &ctx->active_cheats, cheat_t, list) { free(cheat->name); @@ -341,8 +325,6 @@ void cheat_delete_all(struct cheat_ctx* ctx) list_del(&cheat->list); free(cheat); } - - SDL_UnlockMutex(ctx->mutex); } int cheat_set_enabled(struct cheat_ctx* ctx, const char* name, int enabled) @@ -352,22 +334,14 @@ int cheat_set_enabled(struct cheat_ctx* ctx, const char* name, int enabled) if (list_empty(&ctx->active_cheats)) return 0; - if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0) - { - DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_set_enabled()"); - return 0; - } - list_for_each_entry_t(cheat, &ctx->active_cheats, cheat_t, list) { if (strcmp(name, cheat->name) == 0) { cheat->enabled = enabled; - SDL_UnlockMutex(ctx->mutex); return 1; } } - SDL_UnlockMutex(ctx->mutex); return 0; } @@ -376,17 +350,10 @@ int cheat_add_new(struct cheat_ctx* ctx, const char* name, m64p_cheat_code* code cheat_t *cheat; int i, j; - if (ctx->mutex == NULL || SDL_LockMutex(ctx->mutex) != 0) - { - DebugMessage(M64MSG_ERROR, "Internal error: failed to lock mutex in cheat_add_new()"); - return 0; - } - /* create a new cheat function or erase the codes in an existing cheat function */ cheat = find_or_create_cheat(ctx, name); if (cheat == NULL) { - SDL_UnlockMutex(ctx->mutex); return 0; } @@ -426,7 +393,6 @@ int cheat_add_new(struct cheat_ctx* ctx, const char* name, m64p_cheat_code* code } } - SDL_UnlockMutex(ctx->mutex); return 1; } diff --git a/src/main/eventloop.c b/src/main/eventloop.c index eb0fd191..2522e6e0 100644 --- a/src/main/eventloop.c +++ b/src/main/eventloop.c @@ -20,13 +20,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include #include #include #include -SDL_JoystickID l_iJoyInstanceID[10]; - #define M64P_CORE_PROTOTYPES 1 #include "api/callbacks.h" #include "api/config.h" diff --git a/src/main/main.c b/src/main/main.c index 87dab35c..06ba0016 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -28,7 +28,6 @@ * if you want to implement an interface, you should look here */ -#include #include #include #include @@ -66,9 +65,7 @@ #include "device/pif/bootrom_hle.h" #include "eventloop.h" #include "main.h" -#include "osal/files.h" -#include "osal/preproc.h" -#include "osd/osd.h" +#include "callbacks.h" #include "plugin/plugin.h" #if defined(PROFILE) #include "profile.h" @@ -79,6 +76,25 @@ #include "util.h" #include "netplay.h" +#include +#include + +#ifdef M64P_NETPLAY +#undef SDL_GetTicks +#include +#endif // M64P_NETPLAY + +#ifdef HAVE_LIBNX +#include +#include +#endif + +#ifdef __LIBRETRO__ +#include +#include +#include +#endif // __LIBRETRO__ + #ifdef DBG #include "debugger/dbg_debugger.h" #endif @@ -124,10 +140,6 @@ static int l_SpeedFactor = 100; // percentage of nominal game speed at static int l_FrameAdvance = 0; // variable to check if we pause on next frame static int l_MainSpeedLimit = 1; // insert delay during vi_interrupt to keep speed at real-time -static osd_message_t *l_msgVol = NULL; -static osd_message_t *l_msgFF = NULL; -static osd_message_t *l_msgPause = NULL; - /* compatible paks */ enum { PAK_MAX_SIZE = 5 }; static size_t l_paks_idx[GAME_CONTROLLERS_COUNT]; @@ -144,20 +156,7 @@ static struct xoshiro256pp_state l_mpk_idgen; static const char *get_savepathdefault(const char *configpath) { - static char path[1024]; - - if (!configpath || (strlen(configpath) == 0)) { - snprintf(path, 1024, "%ssave%c", ConfigGetUserDataPath(), OSAL_DIR_SEPARATORS[0]); - path[1023] = 0; - } else { - snprintf(path, 1024, "%s%c", configpath, OSAL_DIR_SEPARATORS[0]); - path[1023] = 0; - } - - /* create directory if it doesn't exist */ - osal_mkdirp(path, 0700); - - return path; + return ""; } static char *get_save_filename(void) @@ -186,174 +185,50 @@ static char *get_save_filename(void) static char *get_mempaks_path(void) { - char *path; - size_t size = 0; - - /* check if old file path exists, if it does then use that */ - path = formatstr("%s%s.mpk", get_savesrampath(), ROM_SETTINGS.goodname); - if (get_file_size(path, &size) == file_ok && size > 0) - { - return path; - } - free(path); - - /* else use new path */ - return formatstr("%s%s.mpk", get_savesrampath(), get_save_filename()); + return ""; } static char *get_eeprom_path(void) { - char *path; - size_t size = 0; - - /* check if old file path exists, if it does then use that */ - path = formatstr("%s%s.eep", get_savesrampath(), ROM_SETTINGS.goodname); - if (get_file_size(path, &size) == file_ok && size > 0) - { - return path; - } - free(path); - - /* else use new path */ - return formatstr("%s%s.eep", get_savesrampath(), get_save_filename()); + return ""; } static char *get_sram_path(void) { - char *path; - size_t size = 0; - - /* check if old file path exists, if it does then use that */ - path = formatstr("%s%s.sra", get_savesrampath(), ROM_SETTINGS.goodname); - if (get_file_size(path, &size) == file_ok && size > 0) - { - return path; - } - free(path); - - /* else use new path */ - return formatstr("%s%s.sra", get_savesrampath(), get_save_filename()); + return ""; } static char *get_flashram_path(void) { - char *path; - size_t size = 0; - - /* check if old file path exists, if it does then use that */ - path = formatstr("%s%s.fla", get_savesrampath(), ROM_SETTINGS.goodname); - if (get_file_size(path, &size) == file_ok && size > 0) - { - return path; - } - free(path); - - /* else use new path */ - return formatstr("%s%s.fla", get_savesrampath(), get_save_filename()); + return ""; } static char *get_gb_ram_path(const char* gbrom, unsigned int control_id) { - return formatstr("%s%s.%u.sav", get_savesrampath(), gbrom, control_id); + return ""; } -static char *get_dd_disk_save_path(const char* disk, int format) -{ - char* filename = NULL; - - int len = strlen(disk); - int has_expected_ext = (len >= 4 && (strcmp(disk + len - 4, ".ndd") == 0 || strcmp(disk + len - 4, ".d64") == 0)); - - switch (format) { - case 0: /* *.ndr,*.d6r, full disk content */ - if (has_expected_ext) { - /* file has .ndd / .d64, so adjust existing extension */ - filename = formatstr("%s%s", get_savesrampath(), disk); - len = strlen(filename); - filename[len-1] = 'r'; - } - else { - /* file doesn't have .ndd / .d64 extension, so fallback to .ndr */ - filename = formatstr("%s%s.ndr", get_savesrampath(), disk); - } - break; - case 1: /* *.ram, only RAM part is persisted */ - if (has_expected_ext) { - /* file has .ndd / .d64, so adjust existing extension */ - filename = formatstr("%s%s", get_savesrampath(), disk); - len = strlen(filename); - filename[len-3] = 'r'; - filename[len-2] = 'a'; - filename[len-1] = 'm'; - } - else { - /* file doesn't have .ndd / .d64 extension, so fallback to .ram */ - filename = formatstr("%s%s.ram", get_savesrampath(), disk); - } - break; - default: - DebugMessage(M64MSG_WARNING, "Unexpected DD save format: %d", format); - break; - } - return filename; -} - - -static m64p_error init_video_capture_backend(const struct video_capture_backend_interface** ivcap, void** vcap, m64p_handle config, const char* key) -{ - m64p_error err; - - const char* name = ConfigGetParamString(config, key); - if (name == NULL) { - DebugMessage(M64MSG_WARNING, "Couldn't get %s value. Using NULL value instead.", key); - } - - /* try to find desired backend (by name) */ - *ivcap = get_video_capture_backend(name); - - /* handle not found case */ - if (*ivcap == NULL) { - /* default to dummy backend */ - *ivcap = get_video_capture_backend(NULL); - - DebugMessage(M64MSG_WARNING, "Could not find %s video_capture_backend_interface. Using %s instead.", - name, (*ivcap)->name); - } - - /* build section name */ - char* section = formatstr("%s:%s", key, (*ivcap)->name); - - /* init backend */ - err = (*ivcap)->init(vcap, section); - - if (err == M64ERR_SUCCESS) { - DebugMessage(M64MSG_INFO, "Using video capture backend: %s", (*ivcap)->name); - } - else { - DebugMessage(M64MSG_ERROR, "Failed to initialize video capture backend %s: %s", (*ivcap)->name, CoreErrorMessage(err)); - *ivcap = NULL; - } - - free(section); - - return err; -} - -/********************************************************************************************************* -* helper functions -*/ - - const char *get_savestatepath(void) { - /* try to get the SaveStatePath string variable in the Core configuration section */ - return get_savepathdefault(ConfigGetParamString(g_CoreConfig, "SaveStatePath")); + return ""; } const char *get_savesrampath(void) { - /* try to get the SaveSRAMPath string variable in the Core configuration section */ - return get_savepathdefault(ConfigGetParamString(g_CoreConfig, "SaveSRAMPath")); + return ""; +} + +const char *get_dd_disk_save_path(const char* diskname, int save_format) +{ + char* newPath = (char*)malloc(PATH_MAX); + strcpy(newPath, diskname); + + if(save_format == 0) + strcat(newPath, ".disk_save"); + else + strcat(newPath, ".ram"); + + return newPath; } const char *get_savestatefilename(void) @@ -371,88 +246,31 @@ void main_message(m64p_msg_level level, unsigned int corner, const char *format, buffer[2048]='\0'; va_end(ap); - /* send message to on-screen-display if enabled */ - if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay")) - osd_new_message((enum osd_corner) corner, "%s", buffer); /* send message to front-end */ DebugMessage(level, "%s", buffer); } +extern retro_input_poll_t poll_cb; static void main_check_inputs(void) { #ifdef WITH_LIRC lircCheckInput(); #endif - SDL_PumpEvents(); + if(!(current_rdp_type == RDP_PLUGIN_GLIDEN64 && EnableThreadedRenderer)) + { + // Input Polling will be forced to early if Threaded GLideN64 + poll_cb(); + } } /********************************************************************************************************* * global functions, for adjusting the core emulator behavior */ - +extern void Config_LoadConfig(); int main_set_core_defaults(void) { - float fConfigParamsVersion; - int bUpgrade = 0; - - if (ConfigGetParameter(g_CoreConfig, "Version", M64TYPE_FLOAT, &fConfigParamsVersion, sizeof(float)) != M64ERR_SUCCESS) - { - DebugMessage(M64MSG_WARNING, "No version number in 'Core' config section. Setting defaults."); - ConfigDeleteSection("Core"); - ConfigOpenSection("Core", &g_CoreConfig); - } - else if (((int) fConfigParamsVersion) != ((int) CONFIG_PARAM_VERSION)) - { - DebugMessage(M64MSG_WARNING, "Incompatible version %.2f in 'Core' config section: current is %.2f. Setting defaults.", fConfigParamsVersion, (float) CONFIG_PARAM_VERSION); - ConfigDeleteSection("Core"); - ConfigOpenSection("Core", &g_CoreConfig); - } - else if ((CONFIG_PARAM_VERSION - fConfigParamsVersion) >= 0.0001f) - { - float fVersion = (float) CONFIG_PARAM_VERSION; - ConfigSetParameter(g_CoreConfig, "Version", M64TYPE_FLOAT, &fVersion); - DebugMessage(M64MSG_INFO, "Updating parameter set version in 'Core' config section to %.2f", fVersion); - bUpgrade = 1; - } - - /* parameters controlling the operation of the core */ - ConfigSetDefaultFloat(g_CoreConfig, "Version", (float) CONFIG_PARAM_VERSION, "Mupen64Plus Core config parameter set version number. Please don't change this version number."); - ConfigSetDefaultBool(g_CoreConfig, "OnScreenDisplay", 1, "Draw on-screen display if True, otherwise don't draw OSD"); -#if defined(DYNAREC) - ConfigSetDefaultInt(g_CoreConfig, "R4300Emulator", 2, "Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more"); -#else - ConfigSetDefaultInt(g_CoreConfig, "R4300Emulator", 1, "Use Pure Interpreter if 0, Cached Interpreter if 1, or Dynamic Recompiler if 2 or more"); -#endif - ConfigSetDefaultBool(g_CoreConfig, "NoCompiledJump", 0, "Disable compiled jump commands in dynamic recompiler (should be set to False) "); - ConfigSetDefaultBool(g_CoreConfig, "DisableExtraMem", 0, "Disable 4MB expansion RAM pack. May be necessary for some games"); - ConfigSetDefaultInt(g_CoreConfig, "CountPerOp", 0, "Force number of cycles per emulated instruction"); - ConfigSetDefaultInt(g_CoreConfig, "CountPerOpDenomPot", 0, "Reduce number of cycles per update by power of two when set greater than 0 (overclock)"); - ConfigSetDefaultBool(g_CoreConfig, "AutoStateSlotIncrement", 0, "Increment the save state slot after each save operation"); - ConfigSetDefaultInt(g_CoreConfig, "CurrentStateSlot", 0, "Save state slot (0-9) to use when saving/loading the emulator state"); - ConfigSetDefaultBool(g_CoreConfig, "EnableDebugger", 0, "Activate the R4300 debugger when ROM execution begins, if core was built with Debugger support"); - ConfigSetDefaultString(g_CoreConfig, "ScreenshotPath", "", "Path to directory where screenshots are saved. If this is blank, the default value of ${UserDataPath}/screenshot will be used"); - ConfigSetDefaultString(g_CoreConfig, "SaveStatePath", "", "Path to directory where emulator save states (snapshots) are saved. If this is blank, the default value of ${UserDataPath}/save will be used"); - ConfigSetDefaultString(g_CoreConfig, "SaveSRAMPath", "", "Path to directory where SRAM/EEPROM data (in-game saves) are stored. If this is blank, the default value of ${UserDataPath}/save will be used"); - ConfigSetDefaultString(g_CoreConfig, "SharedDataPath", "", "Path to a directory to search when looking for shared data files"); - ConfigSetDefaultBool(g_CoreConfig, "RandomizeInterrupt", 1, "Randomize PI/SI Interrupt Timing"); - ConfigSetDefaultInt(g_CoreConfig, "SiDmaDuration", -1, "Duration of SI DMA (-1: use per game settings)"); - ConfigSetDefaultString(g_CoreConfig, "GbCameraVideoCaptureBackend1", DEFAULT_VIDEO_CAPTURE_BACKEND, "Gameboy Camera Video Capture backend"); - ConfigSetDefaultInt(g_CoreConfig, "SaveDiskFormat", 1, "Disk Save Format (0: Full Disk Copy (*.ndr/*.d6r), 1: RAM Area Only (*.ram))"); - ConfigSetDefaultInt(g_CoreConfig, "SaveFilenameFormat", 1, "Save (SRAM/State) Filename Format (0: ROM Header Name, 1: Automatic (including partial MD5 hash))"); - - /* handle upgrades */ - if (bUpgrade) - { - if (fConfigParamsVersion < 1.01f) - { // added separate SaveSRAMPath parameter in v1.01 - const char *pccSaveStatePath = ConfigGetParamString(g_CoreConfig, "SaveStatePath"); - if (pccSaveStatePath != NULL) - ConfigSetParameter(g_CoreConfig, "SaveSRAMPath", M64TYPE_STRING, pccSaveStatePath); - } - } - - /* set config parameters for keyboard and joystick commands */ - return event_set_core_defaults(); + Config_LoadConfig(); + return 1; } void main_speeddown(int percent) @@ -463,7 +281,6 @@ void main_speeddown(int percent) if (l_SpeedFactor - percent > 10) /* 10% minimum speed */ { l_SpeedFactor -= percent; - main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor); audio.setSpeedFactor(l_SpeedFactor); StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor); } @@ -477,7 +294,6 @@ void main_speedup(int percent) if (l_SpeedFactor + percent < 300) /* 300% maximum speed */ { l_SpeedFactor += percent; - main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor); audio.setSpeedFactor(l_SpeedFactor); StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor); } @@ -497,7 +313,6 @@ static void main_speedset(int percent) main_set_fastforward(0); // set speed l_SpeedFactor = percent; - main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "%s %d%%", "Playback speed:", l_SpeedFactor); audio.setSpeedFactor(l_SpeedFactor); StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor); } @@ -517,10 +332,6 @@ void main_set_fastforward(int enable) l_SpeedFactor = 250; audio.setSpeedFactor(l_SpeedFactor); StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor); - // set fast-forward indicator - l_msgFF = osd_new_message(OSD_TOP_RIGHT, "Fast Forward"); - osd_message_set_static(l_msgFF); - osd_message_set_user_managed(l_msgFF); } else if (!enable && ff_state) { @@ -528,9 +339,6 @@ void main_set_fastforward(int enable) l_SpeedFactor = SavedSpeedFactor; audio.setSpeedFactor(l_SpeedFactor); StateChanged(M64CORE_SPEED_FACTOR, l_SpeedFactor); - // remove message - osd_delete_message(l_msgFF); - l_msgFF = NULL; } } @@ -579,22 +387,11 @@ void main_toggle_pause(void) if (g_rom_pause) { DebugMessage(M64MSG_STATUS, "Emulation continued."); - if(l_msgPause) - { - osd_delete_message(l_msgPause); - l_msgPause = NULL; - } StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING); } else { - if(l_msgPause) - osd_delete_message(l_msgPause); - DebugMessage(M64MSG_STATUS, "Emulation paused."); - l_msgPause = osd_new_message(OSD_MIDDLE_CENTER, "Paused"); - osd_message_set_static(l_msgPause); - osd_message_set_user_managed(l_msgPause); StateChanged(M64CORE_EMU_STATE, M64EMU_PAUSED); } @@ -611,27 +408,7 @@ void main_advance_one(void) static void main_draw_volume_osd(void) { - char msgString[64]; - const char *volString; - - // this calls into the audio plugin - volString = audio.volumeGetString(); - if (volString == NULL) - { - strcpy(msgString, "Volume Not Supported."); - } - else - { - sprintf(msgString, "%s: %s", "Volume", volString); - } - - // create a new message or update an existing one - if (l_msgVol != NULL) - osd_update_message(l_msgVol, "%s", msgString); - else { - l_msgVol = osd_new_message(OSD_MIDDLE_CENTER, "%s", msgString); - osd_message_set_user_managed(l_msgVol); - } + return; } /* this function could be called as a result of a keypress, joystick/button movement, @@ -692,12 +469,7 @@ m64p_error main_core_state_query(m64p_core_param param, int *rval) *rval = M64EMU_RUNNING; break; case M64CORE_VIDEO_MODE: - if (!VidExt_VideoRunning()) - *rval = M64VIDEO_NONE; - else if (VidExt_InFullscreenMode()) *rval = M64VIDEO_FULLSCREEN; - else - *rval = M64VIDEO_WINDOWED; break; case M64CORE_SAVESTATE_SLOT: *rval = savestates_get_slot(); @@ -770,19 +542,8 @@ m64p_error main_core_state_set(m64p_core_param param, int val) case M64CORE_VIDEO_MODE: if (!g_EmulatorRunning) return M64ERR_INVALID_STATE; - if (val == M64VIDEO_WINDOWED) - { - if (VidExt_InFullscreenMode()) - gfx.changeWindow(); - return M64ERR_SUCCESS; - } - else if (val == M64VIDEO_FULLSCREEN) - { - if (!VidExt_InFullscreenMode()) - gfx.changeWindow(); - return M64ERR_SUCCESS; - } - return M64ERR_INPUT_INVALID; + gfx.changeWindow(); + return M64ERR_SUCCESS; case M64CORE_SAVESTATE_SLOT: if (val < 0 || val > 9) return M64ERR_INPUT_INVALID; @@ -851,7 +612,6 @@ m64p_error main_volume_up(void) { int level = 0; audio.volumeUp(); - main_draw_volume_osd(); main_volume_get_level(&level); StateChanged(M64CORE_AUDIO_VOLUME, level); return M64ERR_SUCCESS; @@ -861,7 +621,6 @@ m64p_error main_volume_down(void) { int level = 0; audio.volumeDown(); - main_draw_volume_osd(); main_volume_get_level(&level); StateChanged(M64CORE_AUDIO_VOLUME, level); return M64ERR_SUCCESS; @@ -876,7 +635,6 @@ m64p_error main_volume_get_level(int *level) m64p_error main_volume_set_level(int level) { audio.volumeSetLevel(level); - main_draw_volume_osd(); level = audio.volumeGetLevel(); StateChanged(M64CORE_AUDIO_VOLUME, level); return M64ERR_SUCCESS; @@ -885,7 +643,6 @@ m64p_error main_volume_set_level(int level) m64p_error main_volume_mute(void) { audio.volumeMute(); - main_draw_volume_osd(); StateChanged(M64CORE_AUDIO_MUTE, main_volume_get_muted()); return M64ERR_SUCCESS; } @@ -913,32 +670,6 @@ m64p_error main_reset(int do_hard_reset) static void video_plugin_render_callback(int bScreenRedrawn) { -#ifdef M64P_OSD - int bOSD = ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay"); -#endif /* M64P_OSD */ - - // if the flag is set to take a screenshot, then grab it now - if (l_TakeScreenshot != 0) - { - // if the OSD is enabled, and the screen has not been recently redrawn, then we cannot take a screenshot now because - // it contains the OSD text. Wait until the next redraw -#ifdef M64P_OSD - if (!bOSD || bScreenRedrawn) -#endif /* M64P_OSD */ - { - TakeScreenshot(l_TakeScreenshot - 1); // current frame number +1 is in l_TakeScreenshot - l_TakeScreenshot = 0; // reset flag - } - } - -#ifdef M64P_OSD - // if the OSD is enabled, then draw it now - if (bOSD) - { - osd_render(); - } -#endif /* M64P_OSD */ - // if the input plugin specified a render callback, call it now if(input.renderCallback) { @@ -961,6 +692,8 @@ void new_frame(void) } } +/* +#define SAMPLE_COUNT 1 static void apply_speed_limiter(void) { static unsigned long totalVIs = 0; @@ -968,13 +701,19 @@ static void apply_speed_limiter(void) static int lastSpeedFactor = 100; static unsigned int StartFPSTime = 0; static const double defaultSpeedFactor = 100.0; +#ifdef HAVE_LIBNX + unsigned int CurrentFPSTime = armTicksToNs(armGetSystemTick()) / 1000000; +#else unsigned int CurrentFPSTime = SDL_GetTicks(); +#endif // HAVE_LIBNX + static double sleepTimes[SAMPLE_COUNT]; + static unsigned int sleepTimesIndex = 0; // calculate frame duration based upon ROM setting (50/60hz) and mupen64plus speed adjustment const double VILimitMilliseconds = 1000.0 / g_dev.vi.expected_refresh_rate; const double SpeedFactorMultiple = defaultSpeedFactor/l_SpeedFactor; const double AdjustedLimit = VILimitMilliseconds * SpeedFactorMultiple; - + //if this is the first time or we are resuming from pause if(StartFPSTime == 0 || !resetOnce || lastSpeedFactor != l_SpeedFactor) { @@ -1009,19 +748,31 @@ static void apply_speed_limiter(void) resetOnce = 0; } - if (sleepTime < minSleepNeeded) { - totalVIs += (unsigned long)(minSleepNeeded/AdjustedLimit); + sleepTimes[sleepTimesIndex%SAMPLE_COUNT] = sleepTime; + sleepTimesIndex++; + + unsigned int elementsForAverage = sleepTimesIndex > SAMPLE_COUNT ? SAMPLE_COUNT : sleepTimesIndex; + + // compute the average sleepTime + double sum = 0; + unsigned int index; + for(index = 0; index < elementsForAverage; index++) + { + sum += sleepTimes[index]; } - if(l_MainSpeedLimit && sleepTime > 0 && sleepTime < maxSleepNeeded*SpeedFactorMultiple) - { - while(sleepTime >= 0) { - SDL_Delay((unsigned int) sleepTime); + double averageSleep = sum/elementsForAverage; - CurrentFPSTime = SDL_GetTicks(); - elapsedRealTime = CurrentFPSTime - StartFPSTime; - sleepTime = totalElapsedGameTime - elapsedRealTime; - } + int sleepMs = (int)averageSleep; + + if(sleepMs > 0 && l_MainSpeedLimit) + { + //DebugMessage(M64MSG_VERBOSE, " apply_speed_limiter(): Waiting %ims", sleepMs); +#ifdef HAVE_LIBNX + svcSleepThread(sleepMs * 1000000); +#else + SDL_Delay(sleepMs); +#endif // HAVE_LIBNX } @@ -1029,6 +780,7 @@ static void apply_speed_limiter(void) timed_section_end(TIMED_SECTION_IDLE); #endif } +*/ /* TODO: make a GameShark module and move that there */ static void gs_apply_cheats(struct cheat_ctx* ctx) @@ -1051,11 +803,8 @@ static void pause_loop(void) { if(g_rom_pause) { - osd_render(); // draw Paused message in case gfx.updateScreen didn't do it - VidExt_GL_SwapBuffers(); while(g_rom_pause) { - SDL_Delay(10); main_check_inputs(); } } @@ -1071,12 +820,11 @@ void new_vi(void) gs_apply_cheats(&g_cheat_ctx); - apply_speed_limiter(); + // apply_speed_limiter(); main_check_inputs(); - pause_loop(); - netplay_check_sync(&g_dev.r4300.cp0); + retro_return(); } static void main_switch_pak(int control_id) @@ -1115,68 +863,75 @@ void main_switch_plugin_pak(int control_id) main_switch_pak(control_id); } -static void open_mpk_file(struct file_storage* fstorage) +void save_storage_file_libretro(void* storage) { - unsigned int i; - int ret = open_file_storage(fstorage, GAME_CONTROLLERS_COUNT*MEMPAK_SIZE, get_mempaks_path()); +} - if (ret == (int)file_open_error) { - /* if file doesn't exists provide default content */ - for(i = 0; i < GAME_CONTROLLERS_COUNT; ++i) { - - /* Generate a random serial ID */ - uint32_t serial[6]; - size_t k; - for (k = 0; k < 6; ++k) { - serial[k] = xoshiro256pp_next(&l_mpk_idgen); - } - - format_mempak(fstorage->data + i * MEMPAK_SIZE, - serial, - DEFAULT_MEMPAK_DEVICEID, - DEFAULT_MEMPAK_BANKS, - DEFAULT_MEMPAK_VERSION); - } +static void open_mpk_file(struct file_storage* storage) +{ + if (!netplay_is_init()) + { + storage->data = saved_memory.mempack; + storage->size = MEMPAK_SIZE * 4; + } + else + { + // First we save them with what we have + storage->data = saved_memory.mempack; + storage->size = MEMPAK_SIZE * 4; + // If player 1 we send, otherwise we recieve + netplay_read_storage("MPK.bin", storage->data, storage->size); } } -static void open_fla_file(struct file_storage* fstorage) +static void open_fla_file(struct file_storage* storage) { - int ret = open_file_storage(fstorage, FLASHRAM_SIZE, get_flashram_path()); - - if (ret == (int)file_open_error) { - /* if file doesn't exists provide default content */ - format_flashram(fstorage->data); + if (!netplay_is_init()) + { + storage->data = saved_memory.flashram; + storage->size = FLASHRAM_SIZE; + } + else + { + // First we save them with what we have + storage->data = saved_memory.flashram; + storage->size = FLASHRAM_SIZE; + // If player 1 we send, otherwise we recieve + netplay_read_storage("FLA.bin", storage->data, storage->size); } } -static void open_sra_file(struct file_storage* fstorage) +static void open_sra_file(struct file_storage* storage) { - int ret = open_file_storage(fstorage, SRAM_SIZE, get_sram_path()); - - if (ret == (int)file_open_error) { - /* if file doesn't exists provide default content */ - format_sram(fstorage->data); + if (!netplay_is_init()) + { + storage->data = saved_memory.sram; + storage->size = SRAM_SIZE; + } + else + { + // First we save them with what we have + storage->data = saved_memory.sram; + storage->size = SRAM_SIZE; + // If player 1 we send, otherwise we recieve + netplay_read_storage("SRA.bin", storage->data, storage->size); } } -static void open_eep_file(struct file_storage* fstorage) +static void open_eep_file(struct file_storage* storage) { - /* Note: EEP files are all EEPROM_MAX_SIZE bytes long, - * whatever the real EEPROM size is. - */ - enum { EEPROM_MAX_SIZE = 0x800 }; - - int ret = open_file_storage(fstorage, EEPROM_MAX_SIZE, get_eeprom_path()); - - if (ret == (int)file_open_error) { - /* if file doesn't exists provide default content */ - format_eeprom(fstorage->data, EEPROM_MAX_SIZE); + if (!netplay_is_init()) + { + storage->data = saved_memory.eeprom; + storage->size = EEPROM_MAX_SIZE; } - - /* Truncate to 4k bit if necessary */ - if (ROM_SETTINGS.savetype != SAVETYPE_EEPROM_16K) { - fstorage->size = 0x200; + else + { + // First we save them with what we have + storage->data = saved_memory.eeprom; + storage->size = EEPROM_MAX_SIZE; + // If player 1 we send, otherwise we recieve + netplay_read_storage("EEP.bin", storage->data, storage->size); } } @@ -1193,6 +948,25 @@ static void load_dd_rom(uint8_t* rom, size_t* rom_size, uint8_t* disk_region) ? NULL : g_media_loader.get_dd_rom(g_media_loader.cb_data); + char* sys_pathname; + environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &sys_pathname); + char* pathname = (char*)malloc(2048); + strncpy(pathname, sys_pathname, 2048 - 1); + if (pathname[(strlen(pathname)-1)] != '/' && pathname[(strlen(pathname)-1)] != '\\') + strcat(pathname, PATH_DEFAULT_SLASH()); + strcat(pathname, "Mupen64plus"); + strcat(pathname, PATH_DEFAULT_SLASH()); + strcat(pathname, "IPL.n64"); + + if(retro_dd_path_img) + { + dd_ipl_rom_filename = pathname; + } + else + { + dd_ipl_rom_filename = NULL; + } + if ((dd_ipl_rom_filename == NULL) || (strlen(dd_ipl_rom_filename) == 0)) { goto no_dd; } @@ -1247,13 +1021,18 @@ no_dd: *rom_size = 0; } +extern char* retro_dd_path_img; +extern char* retro_dd_path_rom; static int load_dd_disk(struct dd_disk* dd_disk, const struct storage_backend_interface** dd_idisk) { /* ask the core loader for DD disk filename */ char* dd_disk_filename = (g_media_loader.get_dd_disk == NULL) - ? NULL + ? (retro_dd_path_img ? strdup(retro_dd_path_img) : NULL) : g_media_loader.get_dd_disk(g_media_loader.cb_data); + //printf("Load DD disk %s\n", dd_disk_filename); + //fflush(stdout); + /* handle the no disk case */ if (dd_disk_filename == NULL || strlen(dd_disk_filename) == 0) { goto no_disk; @@ -1276,7 +1055,7 @@ static int load_dd_disk(struct dd_disk* dd_disk, const struct storage_backend_in } /* Determine disk save format */ - int save_format = ConfigGetParamInt(g_CoreConfig, "SaveDiskFormat"); + int save_format = 0; //ConfigGetParamInt(g_CoreConfig, "SaveDiskFormat"); /* MAME disks only support full disk save */ if (dd_size == MAME_FORMAT_DUMP_SIZE && save_format != 0) { DebugMessage(M64MSG_WARNING, "MAME disks only support full disk save format, switching to full disk format !"); @@ -1284,7 +1063,7 @@ static int load_dd_disk(struct dd_disk* dd_disk, const struct storage_backend_in } /* Determine save file name */ - char* save_filename = get_dd_disk_save_path(namefrompath(dd_disk_filename), save_format); + char* save_filename = get_dd_disk_save_path(dd_disk_filename, save_format); if (save_filename == NULL) { DebugMessage(M64MSG_ERROR, "Failed to get DD save path, DD will be read-only."); save_format = -1; @@ -1454,7 +1233,7 @@ static void init_gb_rom(void* opaque, void** storage, const struct storage_backe /* Ask the core loader for rom filename */ char* rom_filename = (g_media_loader.get_gb_cart_rom == NULL) - ? NULL + ? (retro_transferpak_rom_path ? strdup(retro_transferpak_rom_path) : NULL) : g_media_loader.get_gb_cart_rom(g_media_loader.cb_data, data->control_id); /* Handle the no cart case */ @@ -1464,11 +1243,11 @@ static void init_gb_rom(void* opaque, void** storage, const struct storage_backe /* Open ROM file */ if (open_rom_file_storage(&data->rom_fstorage, rom_filename) != file_ok) { - DebugMessage(M64MSG_ERROR, "Failed to load ROM file: %s", rom_filename); + log_cb(RETRO_LOG_ERROR, "Failed to load ROM file: %s\n", rom_filename); goto no_cart; } - DebugMessage(M64MSG_INFO, "GB Loader ROM: %s - %zu", + log_cb(RETRO_LOG_INFO, "GB Loader ROM: %s - %zu\n", data->rom_fstorage.filename, data->rom_fstorage.size); @@ -1498,7 +1277,7 @@ static void init_gb_ram(void* opaque, size_t ram_size, void** storage, const str /* Ask the core loader for ram filename */ char* ram_filename = (g_media_loader.get_gb_cart_ram == NULL) - ? NULL + ? (retro_transferpak_ram_path ? strdup(retro_transferpak_ram_path) : NULL) : g_media_loader.get_gb_cart_ram(g_media_loader.cb_data, data->control_id); /* Handle the no RAM case @@ -1514,13 +1293,13 @@ static void init_gb_ram(void* opaque, size_t ram_size, void** storage, const str int err = open_file_storage(&data->ram_fstorage, ram_size, ram_filename); if (err == file_open_error) { memset(data->ram_fstorage.data, 0, data->ram_fstorage.size); - DebugMessage(M64MSG_INFO, "Providing default RAM content"); + log_cb(RETRO_LOG_INFO, "Providing default RAM content\n"); } else if (err == file_read_error) { - DebugMessage(M64MSG_WARNING, "Size mismatch between expected RAM size and effective file size"); + log_cb(RETRO_LOG_WARN, "Size mismatch between expected RAM size and effective file size\n"); } - DebugMessage(M64MSG_INFO, "GB Loader RAM: %s - %zu", + log_cb(RETRO_LOG_INFO, "GB Loader RAM: %s - %zu\n", data->ram_fstorage.filename, data->ram_fstorage.size); @@ -1563,10 +1342,10 @@ void main_change_gb_cart(int control_id) if (tpk->gb_cart != NULL) { const uint8_t* rom_data = gb_cart->irom_storage->data(gb_cart->rom_storage); - DebugMessage(M64MSG_INFO, "Inserting GB cart %s into transferpak %u", rom_data + 0x134, control_id); + log_cb(RETRO_LOG_INFO, "Inserting GB cart %s into transferpak %u\n", rom_data + 0x134, control_id); } else { - DebugMessage(M64MSG_INFO, "Removing GB cart from transferpak %u", control_id); + log_cb(RETRO_LOG_WARN, "Removing GB cart from transferpak %u\n", control_id); } } @@ -1574,12 +1353,17 @@ void main_change_gb_cart(int control_id) /********************************************************************************************************* * emulation thread - runs the core */ +extern gfx_plugin_functions gfx_gln64; +extern rsp_plugin_functions rsp_hle; +extern input_plugin_functions dummy_input; +extern audio_plugin_functions dummy_audio; +unsigned int r4300_emumode; +size_t rdram_size; m64p_error main_run(void) { size_t i, k; - size_t rdram_size; uint32_t count_per_op; uint32_t count_per_op_denom_pot; uint32_t emumode; @@ -1593,6 +1377,7 @@ m64p_error main_run(void) size_t dd_rom_size; struct dd_disk dd_disk; m64p_error failure_rval; + struct audio_out_backend_interface audio_out_backend_libretro; int control_ids[GAME_CONTROLLERS_COUNT]; struct controller_input_compat cin_compats[GAME_CONTROLLERS_COUNT]; @@ -1605,6 +1390,13 @@ m64p_error main_run(void) /* XXX: select type of flashram from db */ uint32_t flashram_type = MX29L1100_ID; + + emumode = r4300_emumode; + randomize_interrupt = 0; // We don't want this right now + no_compiled_jump = 0; + count_per_op = CountPerOp; + count_per_op_denom_pot = CountPerOpDenomPot; + disable_extra_mem = ROM_SETTINGS.disableextramem; uint16_t eeprom_type = JDT_NONE; switch (ROM_SETTINGS.savetype) { @@ -1620,22 +1412,14 @@ m64p_error main_run(void) uint64_t mpk_seed = !netplay_is_init() ? (uint64_t)time(NULL) : 0; l_mpk_idgen = xoshiro256pp_seed(mpk_seed); - /* take the r4300 emulator mode from the config file at this point and cache it in a global variable */ - emumode = ConfigGetParamInt(g_CoreConfig, "R4300Emulator"); - - /* set some other core parameters based on the config file values */ - savestates_set_autoinc_slot(ConfigGetParamBool(g_CoreConfig, "AutoStateSlotIncrement")); - savestates_select_slot(ConfigGetParamInt(g_CoreConfig, "CurrentStateSlot")); no_compiled_jump = ConfigGetParamBool(g_CoreConfig, "NoCompiledJump"); //We disable any randomness for netplay - randomize_interrupt = !netplay_is_init() ? ConfigGetParamBool(g_CoreConfig, "RandomizeInterrupt") : 0; - count_per_op = ConfigGetParamInt(g_CoreConfig, "CountPerOp"); - count_per_op_denom_pot = ConfigGetParamInt(g_CoreConfig, "CountPerOpDenomPot"); + //randomize_interrupt = !netplay_is_init() ? ConfigGetParamBool(g_CoreConfig, "RandomizeInterrupt") : 0; if (ROM_SETTINGS.disableextramem) disable_extra_mem = ROM_SETTINGS.disableextramem; else - disable_extra_mem = ConfigGetParamInt(g_CoreConfig, "DisableExtraMem"); + disable_extra_mem = ForceDisableExtraMem; if (count_per_op <= 0) count_per_op = ROM_SETTINGS.countperop; @@ -1643,9 +1427,7 @@ m64p_error main_run(void) if (count_per_op_denom_pot > 20) count_per_op_denom_pot = 20; - si_dma_duration = ConfigGetParamInt(g_CoreConfig, "SiDmaDuration"); - if (si_dma_duration < 0) - si_dma_duration = ROM_SETTINGS.sidmaduration; + si_dma_duration = ROM_SETTINGS.sidmaduration; //During netplay, player 1 is the source of truth for these settings netplay_sync_settings(&count_per_op, &count_per_op_denom_pot, &disable_extra_mem, &si_dma_duration, &emumode, &no_compiled_jump); @@ -1663,6 +1445,11 @@ m64p_error main_run(void) } #endif + /* setup backends */ + extern void set_audio_format_via_libretro(void* user_data, unsigned int frequency); + extern void push_audio_samples_via_libretro(void* user_data, const void* buffer, size_t size); + audio_out_backend_libretro = (struct audio_out_backend_interface){ set_audio_format_via_libretro, push_audio_samples_via_libretro }; + /* Fill-in l_pak_type_idx and l_ipaks according to game compatibility */ k = 0; if (ROM_SETTINGS.biopak) { @@ -1698,13 +1485,6 @@ m64p_error main_run(void) l_pak_type_idx[PLUGIN_TRANSFER_PAK] = k; } - /* init GbCamera backend specified in the configuration file */ - init_video_capture_backend(&igbcam_backend, &gbcam_backend, - g_CoreConfig, "GbCameraVideoCaptureBackend1"); - - /* open GB cam video device */ - igbcam_backend->open(gbcam_backend, M64282FP_SENSOR_W, M64282FP_SENSOR_H); - /* open storage files, provide default content if not present */ open_mpk_file(&mpk); open_eep_file(&eep); @@ -1826,7 +1606,7 @@ m64p_error main_run(void) mpk_storages[i].offset = i * MEMPAK_SIZE; mpk_storages[i].filename = (void*)&mpk; /* OK for isubfile_storage */ - init_mempak(&g_dev.mempaks[i], &mpk_storages[i], &g_isubfile_storage); + init_mempak(&g_dev.mempaks[i], &mpk_storages[i], &g_ifile_storage_ro); l_paks[i][k] = &g_dev.mempaks[i]; if (Controls[i].Plugin == PLUGIN_MEMPAK) { @@ -1862,7 +1642,7 @@ m64p_error main_run(void) } /* enable GB cart switch */ - cin_compats[i].gb_cart_switch_enabled = 1; + // cin_compats[i].gb_cart_switch_enabled = 1; } /* No Pak */ else { @@ -1892,6 +1672,7 @@ m64p_error main_run(void) } } } + for (i = GAME_CONTROLLERS_COUNT; i < PIF_CHANNELS_COUNT; ++i) { joybus_devices[i] = &g_dev.cart; ijoybus_devices[i] = &g_ijoybus_device_cart; @@ -1899,13 +1680,13 @@ m64p_error main_run(void) init_device(&g_dev, g_mem_base, - emumode, + r4300_emumode, count_per_op, count_per_op_denom_pot, no_compiled_jump, randomize_interrupt, g_start_address, - &g_dev.ai, &g_iaudio_out_backend_plugin_compat, ((float)ROM_SETTINGS.aidmamodifier / 100.0), + &g_dev.ai, &audio_out_backend_libretro, ((float)ROM_SETTINGS.aidmamodifier / 100.0), si_dma_duration, rdram_size, joybus_devices, ijoybus_devices, @@ -1913,10 +1694,10 @@ m64p_error main_run(void) NULL, &g_iclock_ctime_plus_delta, g_rom_size, eeprom_type, - &eep, &g_ifile_storage, + &eep, &g_ifile_storage_ro, flashram_type, - &fla, &g_ifile_storage, - &sra, &g_ifile_storage, + &fla, &g_ifile_storage_ro, + &sra, &g_ifile_storage_ro, NULL, dd_rtc_iclock, dd_rom_size, &dd_disk, dd_idisk); @@ -1936,52 +1717,17 @@ m64p_error main_run(void) goto on_input_open_failure; } - /* set up the SDL key repeat and event filter to catch keyboard/joystick commands for the core */ - event_initialize(); - - /* initialize frame counter */ - l_CurrentFrame = 0; - - /* initialize the on-screen display */ - if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay")) - { - // init on-screen display - int width = 640, height = 480; - gfx.readScreen(NULL, &width, &height, 0); // read screen to get width and height - osd_init(width, height); - } - // setup rendering callback from video plugin to the core, for screenshots and On-Screen-Display gfx.setRenderingCallback(video_plugin_render_callback); -#ifdef WITH_LIRC - lircStart(); -#endif // WITH_LIRC - -#ifdef DBG - if (ConfigGetParamBool(g_CoreConfig, "EnableDebugger")) - init_debugger(); -#endif - - /* Startup message on the OSD */ - osd_new_message(OSD_MIDDLE_CENTER, "Mupen64Plus Started..."); - g_EmulatorRunning = 1; StateChanged(M64CORE_EMU_STATE, M64EMU_RUNNING); poweron_device(&g_dev); pif_bootrom_hle_execute(&g_dev.r4300); + run_device(&g_dev); - /* now begin to shut down */ -#ifdef WITH_LIRC - lircStop(); -#endif // WITH_LIRC - -#ifdef DBG - if (g_DebuggerActive) - destroy_debugger(); -#endif /* release gb_carts */ for(i = 0; i < GAME_CONTROLLERS_COUNT; ++i) { if (!Controls[i].RawData && (Controls[i].Type == CONT_TYPE_STANDARD) && g_dev.gb_carts[i].read_gb_cart != NULL) { @@ -1990,6 +1736,7 @@ m64p_error main_run(void) } } +#if 0 igbcam_backend->close(gbcam_backend); igbcam_backend->release(gbcam_backend); @@ -1997,16 +1744,13 @@ m64p_error main_run(void) close_file_storage(&fla); close_file_storage(&eep); close_file_storage(&mpk); - close_dd_disk(&dd_disk); +#endif /* reset pif */ close_pif(); + close_dd_disk(&dd_disk); - if (ConfigGetParamBool(g_CoreConfig, "OnScreenDisplay")) - { - osd_exit(); - } - + /* Emulation stopped */ rsp.romClosed(); input.romClosed(); audio.romClosed(); @@ -2016,6 +1760,18 @@ m64p_error main_run(void) g_EmulatorRunning = 0; StateChanged(M64CORE_EMU_STATE, M64EMU_STOPPED); + /** + * Actually never returns. + * Jump back to frontend for deinit + */ + extern cothread_t retro_thread; + + // For GLN64 Threaded GL we just sanely return, exit sync is handled elsewhere + if(!(current_rdp_type == RDP_PLUGIN_GLIDEN64 && EnableThreadedRenderer)) + { + co_switch(retro_thread); + } + return M64ERR_SUCCESS; on_disk_failure: @@ -2035,6 +1791,7 @@ on_gfx_open_failure: } } +#if 0 igbcam_backend->close(gbcam_backend); igbcam_backend->release(gbcam_backend); @@ -2044,6 +1801,7 @@ on_gfx_open_failure: close_file_storage(&eep); close_file_storage(&mpk); close_dd_disk(&dd_disk); +#endif /* reset pif */ close_pif(); @@ -2059,21 +1817,7 @@ void main_stop(void) return; DebugMessage(M64MSG_STATUS, "Stopping emulation."); - if(l_msgPause) - { - osd_delete_message(l_msgPause); - l_msgPause = NULL; - } - if(l_msgFF) - { - osd_delete_message(l_msgFF); - l_msgFF = NULL; - } - if(l_msgVol) - { - osd_delete_message(l_msgVol); - l_msgVol = NULL; - } + if (g_rom_pause) { g_rom_pause = 0; @@ -2081,13 +1825,6 @@ void main_stop(void) } stop_device(&g_dev); - -#ifdef DBG - if(g_DebuggerActive) - { - debugger_step(); - } -#endif } m64p_error open_pif(const unsigned char* pifimage, unsigned int size) diff --git a/src/main/netplay.c b/src/main/netplay.c index 5ec92992..7d35a189 100644 --- a/src/main/netplay.c +++ b/src/main/netplay.c @@ -29,11 +29,20 @@ #include "backends/plugins_compat/plugins_compat.h" #include "netplay.h" -#include +#include + +#include #if !defined(WIN32) -#include +#include #endif +#ifndef HAVE_LIBNX +#include +#else +#include +#include +#endif // HAVE_LIBNX + static int l_canFF; static int l_netplay_controller; static int l_netplay_control[4]; @@ -84,14 +93,14 @@ m64p_error netplay_start(const char* host, int port) { if (SDLNet_Init() < 0) { - DebugMessage(M64MSG_ERROR, "Netplay: Could not initialize SDL Net library"); + log_cb(RETRO_LOG_INFO, "Netplay: Could not initialize SDL Net library\n"); return M64ERR_SYSTEM_FAIL; } l_udpSocket = SDLNet_UDP_Open(0); if (l_udpSocket == NULL) { - DebugMessage(M64MSG_ERROR, "Netplay: UDP socket creation failed"); + log_cb(RETRO_LOG_INFO, "Netplay: UDP socket creation failed\n"); return M64ERR_SYSTEM_FAIL; } @@ -107,7 +116,7 @@ m64p_error netplay_start(const char* host, int port) l_udpChannel = SDLNet_UDP_Bind(l_udpSocket, -1, &dest); if (l_udpChannel < 0) { - DebugMessage(M64MSG_ERROR, "Netplay: could not bind to UDP socket"); + log_cb(RETRO_LOG_INFO, "Netplay: could not bind to UDP socket\n"); SDLNet_UDP_Close(l_udpSocket); l_udpSocket = NULL; return M64ERR_SYSTEM_FAIL; @@ -116,7 +125,7 @@ m64p_error netplay_start(const char* host, int port) l_tcpSocket = SDLNet_TCP_Open(&dest); if (l_tcpSocket == NULL) { - DebugMessage(M64MSG_ERROR, "Netplay: could not bind to TCP socket"); + log_cb(RETRO_LOG_INFO, "Netplay: could not bind to TCP socket\n"); SDLNet_UDP_Close(l_udpSocket); l_udpSocket = NULL; return M64ERR_SYSTEM_FAIL; @@ -297,11 +306,11 @@ static void netplay_process() if (current_status != l_status) { if (((current_status & 0x1) ^ (l_status & 0x1)) != 0) - DebugMessage(M64MSG_ERROR, "Netplay: players have de-synced at VI %u", l_vi_counter); + log_cb(RETRO_LOG_INFO, "Netplay: players have de-synced at VI %u\n", l_vi_counter); for (int dis = 1; dis < 5; ++dis) { if (((current_status & (0x1 << dis)) ^ (l_status & (0x1 << dis))) != 0) - DebugMessage(M64MSG_ERROR, "Netplay: player %u has disconnected", dis); + log_cb(RETRO_LOG_INFO, "Netplay: player %u has disconnected\n", dis); } l_status = current_status; } @@ -334,7 +343,7 @@ static void netplay_process() } break; default: - DebugMessage(M64MSG_ERROR, "Netplay: received unknown message from server"); + log_cb(RETRO_LOG_INFO, "Netplay: received unknown message from server\n"); break; } } @@ -380,6 +389,8 @@ static void netplay_delete_event(struct netplay_event* current, uint8_t control_ static uint32_t netplay_get_input(uint8_t control_id) { uint32_t keys; + struct retro_fastforwarding_override ff_override; + netplay_process(); netplay_request_input(control_id); @@ -390,10 +401,23 @@ static uint32_t netplay_get_input(uint8_t control_id) { l_canFF = 1; main_core_state_set(M64CORE_SPEED_LIMITER, 0); + + // Enable Fast Forward + ff_override.fastforward = true; + // Prevent user toggling Fast Forward + ff_override.inhibit_toggle = true; + environ_cb(RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE, &ff_override); } else { main_core_state_set(M64CORE_SPEED_LIMITER, 1); + + // Disable Fast Forward + ff_override.fastforward = false; + // Prevent user toggling Fast Forward + ff_override.inhibit_toggle = true; + environ_cb(RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE, &ff_override); + l_canFF = 0; } @@ -411,7 +435,7 @@ static uint32_t netplay_get_input(uint8_t control_id) } else { - DebugMessage(M64MSG_ERROR, "Netplay: lost connection to server"); + log_cb(RETRO_LOG_INFO, "Netplay: lost connection to server\n"); main_core_state_set(M64CORE_EMU_STATE, M64EMU_STOPPED); keys = 0; } @@ -494,9 +518,10 @@ file_status_t netplay_read_storage(const char *filename, void *data, size_t size memcpy(&output_data[buffer_pos], file_extension, strlen(file_extension) + 1); buffer_pos += strlen(file_extension) + 1; - ret = read_from_file(filename, data, size); - if (ret == file_open_error) - memset(data, 0, size); //all zeros means there is no save file + // Not wanted for libretro + //ret = read_from_file(filename, data, size); + //if (ret == file_open_error) + // memset(data, 0, size); //all zeros means there is no save file SDLNet_Write32((int32_t)size, &output_data[buffer_pos]); //file data size buffer_pos += 4; memcpy(&output_data[buffer_pos], data, size); //file data diff --git a/src/main/netplay.h b/src/main/netplay.h index 088d4a39..92b1681e 100644 --- a/src/main/netplay.h +++ b/src/main/netplay.h @@ -93,7 +93,7 @@ static osal_inline int netplay_get_controller(uint8_t player) static osal_inline file_status_t netplay_read_storage(const char *filename, void *data, size_t size) { - return 0; + return file_open_error; } static osal_inline void netplay_sync_settings(uint32_t *count_per_op, uint32_t *count_per_op_denom_pot, uint32_t *disable_extra_mem, int32_t *si_dma_duration, uint32_t *emumode, int32_t *no_compiled_jump) diff --git a/src/main/savestates.c b/src/main/savestates.c index 86adbb7f..ef318709 100644 --- a/src/main/savestates.c +++ b/src/main/savestates.c @@ -22,8 +22,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#ifdef USE_SDL #include #include +#else +#include +#endif #include #include #include @@ -31,8 +35,6 @@ #include #include #include -#include -#include #define M64P_CORE_PROTOTYPES 1 #include "api/callbacks.h" @@ -51,6 +53,9 @@ #include "util.h" #include "workqueue.h" +#include +#include + enum { GB_CART_FINGERPRINT_SIZE = 0x1c }; enum { GB_CART_FINGERPRINT_OFFSET = 0x134 }; @@ -62,18 +67,28 @@ static const unsigned char pj64_magic[4] = { 0xC8, 0xA6, 0xD8, 0x23 }; static savestates_job job = savestates_job_nothing; static savestates_type type = savestates_type_unknown; + +// Libretro will re-use fname for the ptr +// This avoids ifdef shenanigans static char *fname = NULL; static unsigned int slot = 0; static int autoinc_save_slot = 0; +#ifdef USE_SDL static SDL_mutex *savestates_lock; +#else +static pthread_mutex_t savestates_lock; +#endif struct savestate_work { char *filepath; char *data; size_t size; struct work_struct work; +#ifdef __LIBRETRO__ + void *mempointer; +#endif }; /* Returns the malloc'd full path of the currently selected savestate. */ @@ -152,16 +167,23 @@ savestates_job savestates_get_job(void) void savestates_set_job(savestates_job j, savestates_type t, const char *fn) { +#ifndef __LIBRETRO__ if (fname != NULL) { free(fname); fname = NULL; } - +#endif // __LIBRETRO__ job = j; type = t; +#ifndef __LIBRETRO__ if (fn != NULL) fname = strdup(fn); +#else + pthread_mutex_lock(&savestates_lock); + fname = (char*)fn; + pthread_mutex_unlock(&savestates_lock); +#endif // __LIBRETRO__ } static void savestates_clear_job(void) @@ -184,10 +206,13 @@ static void savestates_clear_job(void) #define PUTDATA(buff, type, value) \ do { type x = value; PUTARRAY(&x, buff, type, 1); } while(0) -static int savestates_load_m64p(struct device* dev, char *filepath) +#ifndef __LIBRETRO__ +int savestates_load_m64p(struct device* dev, char *filepath) +#else +int savestates_load_m64p(struct device* dev, const void *data) +#endif { unsigned char header[44]; - gzFile f; unsigned int version; int i; uint32_t FCR31; @@ -200,13 +225,21 @@ static int savestates_load_m64p(struct device* dev, char *filepath) uint32_t* cp0_regs = r4300_cp0_regs(&dev->r4300.cp0); +#ifdef USE_SDL SDL_LockMutex(savestates_lock); +#else + pthread_mutex_lock(&savestates_lock); +#endif +#ifndef __LIBRETRO__ + gzFile f; f = gzopen(filepath, "rb"); if(f==NULL) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not open state file: %s", filepath); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } @@ -215,7 +248,9 @@ static int savestates_load_m64p(struct device* dev, char *filepath) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read header from state file %s", filepath); gzclose(f); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } curr = header; @@ -224,9 +259,21 @@ static int savestates_load_m64p(struct device* dev, char *filepath) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State file: %s is not a valid Mupen64plus savestate.", filepath); gzclose(f); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } +#else + memcpy(header, data, 44); + curr = header; + if(strncmp((char *)curr, savestate_magic, 8)!=0) + { + main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Savestate is not a valid Mupen64plus savestate."); + return 0; + } +#endif + curr += 8; version = *curr++; @@ -236,16 +283,28 @@ static int savestates_load_m64p(struct device* dev, char *filepath) if((version >> 16) != (savestate_latest_version >> 16)) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State version (%08x) isn't compatible. Please update Mupen64Plus.", version); +#ifndef __LIBRETRO__ gzclose(f); +#endif +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#else + pthread_mutex_unlock(&savestates_lock); +#endif return 0; } if(memcmp((char *)curr, ROM_SETTINGS.MD5, 32)) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State ROM MD5 does not match current ROM."); +#ifndef __LIBRETRO__ gzclose(f); +#endif +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#else + pthread_mutex_unlock(&savestates_lock); +#endif return 0; } curr += 32; @@ -256,37 +315,59 @@ static int savestates_load_m64p(struct device* dev, char *filepath) if (savestateData == NULL) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Insufficient memory to load state."); +#ifndef __LIBRETRO__ gzclose(f); +#endif +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#else + pthread_mutex_unlock(&savestates_lock); +#endif return 0; } if (version == 0x00010000) /* original savestate version */ { - if (gzread(f, savestateData, savestateSize) != (int)savestateSize || +#ifndef __LIBRETRO__ + if (gzread(f, savestateData, savestateSize) != savestateSize || (gzread(f, queue, sizeof(queue)) % 4) != 0) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read Mupen64Plus savestate 1.0 data from %s", filepath); free(savestateData); gzclose(f); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } +#else + memcpy(savestateData, data + 44, savestateSize); + memcpy(queue, data + 44 + savestateSize, sizeof(queue)); +#endif } else if (version == 0x00010100) // saves entire eventqueue plus 4-byte using_tlb flags { - if (gzread(f, savestateData, savestateSize) != (int)savestateSize || +#ifndef __LIBRETRO__ + if (gzread(f, savestateData, savestateSize) != savestateSize || gzread(f, queue, sizeof(queue)) != sizeof(queue) || gzread(f, using_tlb_data, sizeof(using_tlb_data)) != sizeof(using_tlb_data)) { main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read Mupen64Plus savestate 1.1 data from %s", filepath); free(savestateData); gzclose(f); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } +#else + memcpy(savestateData, data + 44, savestateSize); + memcpy(queue, data + 44 + savestateSize, sizeof(queue)); + memcpy(using_tlb_data, data + 44 + savestateSize + sizeof(queue), sizeof(using_tlb_data)); +#endif } else // version >= 0x00010200 saves entire eventqueue, 4-byte using_tlb flags and extra state { +#ifndef __LIBRETRO__ if (gzread(f, savestateData, savestateSize) != (int)savestateSize || gzread(f, queue, sizeof(queue)) != sizeof(queue) || gzread(f, using_tlb_data, sizeof(using_tlb_data)) != sizeof(using_tlb_data) || @@ -295,13 +376,27 @@ static int savestates_load_m64p(struct device* dev, char *filepath) main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read Mupen64Plus savestate 1.2+ data from %s", filepath); free(savestateData); gzclose(f); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#endif return 0; } +#else + memcpy(savestateData, data + 44, savestateSize); + memcpy(queue, data + 44 + savestateSize, sizeof(queue)); + memcpy(using_tlb_data, data + 44 + savestateSize + sizeof(queue), sizeof(using_tlb_data)); + memcpy(data_0001_0200, data + 44 + savestateSize + sizeof(queue) + sizeof(using_tlb_data), sizeof(data_0001_0200)); +#endif } +#ifndef __LIBRETRO__ gzclose(f); +#endif +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#else + pthread_mutex_unlock(&savestates_lock); +#endif // Parse savestate dev->rdram.regs[0][RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t); @@ -954,7 +1049,10 @@ static int savestates_load_m64p(struct device* dev, char *filepath) *r4300_cp0_last_addr(&dev->r4300.cp0) = *r4300_pc(&dev->r4300); free(savestateData); + +#ifndef __LIBRETRO__ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State loaded from: %s", namefrompath(filepath)); +#endif return 1; } @@ -1399,9 +1497,12 @@ static savestates_type savestates_detect_type(char *filepath) int savestates_load(void) { + int ret = 0; + struct device* dev = &g_dev; + +#ifndef __LIBRETRO__ FILE *fPtr = NULL; char *filepath = NULL; - int ret = 0; if (fname == NULL) // For slots, autodetect the savestate type { @@ -1457,8 +1558,6 @@ int savestates_load(void) if (filepath != NULL) { - struct device* dev = &g_dev; - switch (type) { case savestates_type_m64p: ret = savestates_load_m64p(dev, filepath); break; @@ -1469,6 +1568,15 @@ int savestates_load(void) free(filepath); filepath = NULL; } +#else + if(fname) + { + ret = savestates_load_m64p(dev, fname); + fname = NULL; + } else { + ret = 0; + } +#endif // __LIBRETRO__ // deliver callback to indicate completion of state loading operation StateChanged(M64CORE_STATE_LOADCOMPLETE, ret); @@ -1480,13 +1588,18 @@ int savestates_load(void) static void savestates_save_m64p_work(struct work_struct *work) { - gzFile f; - int gzres; struct savestate_work *save = container_of(work, struct savestate_work, work); +#ifdef USE_SDL SDL_LockMutex(savestates_lock); +#else + pthread_mutex_lock(&savestates_lock); +#endif +#ifndef __LIBRETRO__ // Write the state to a GZIP file + gzFile f; + int gzres; f = gzopen(save->filepath, "wb"); if (f==NULL) @@ -1509,15 +1622,28 @@ static void savestates_save_m64p_work(struct work_struct *work) gzclose(f); main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Saved state to: %s", namefrompath(save->filepath)); +#else + memcpy(save->mempointer, save->data, save->size); +#endif free(save->data); +#ifndef __LIBRETRO__ free(save->filepath); +#endif free(save); +#ifdef USE_SDL SDL_UnlockMutex(savestates_lock); +#else StateChanged(M64CORE_STATE_SAVECOMPLETE, 1); + pthread_mutex_unlock(&savestates_lock); +#endif } -static int savestates_save_m64p(const struct device* dev, char *filepath) +#ifndef __LIBRETRO__ +int savestates_save_m64p(const struct device* dev, char *filepath) +#else +int savestates_save_m64p(const struct device* dev, void *data) +#endif { unsigned char outbuf[4]; int i; @@ -1537,7 +1663,11 @@ static int savestates_save_m64p(const struct device* dev, char *filepath) return 0; } +#ifndef __LIBRETRO__ save->filepath = strdup(filepath); +#else + save->mempointer = data; +#endif if(autoinc_save_slot) savestates_inc_slot(); @@ -2162,10 +2292,12 @@ static int savestates_save_pj64_unc(const struct device* dev, char *filepath) int savestates_save(void) { - char *filepath; int ret = 0; const struct device* dev = &g_dev; +#ifndef __LIBRETRO__ + char *filepath; + /* Can only save PJ64 savestates on VI / COMPARE interrupt. Otherwise try again in a little while. */ if ((type == savestates_type_pj64_zip || @@ -2194,22 +2326,39 @@ int savestates_save(void) { StateChanged(M64CORE_STATE_SAVECOMPLETE, ret); } +#else + if(fname) + { + ret = savestates_save_m64p(dev, fname); + fname = NULL; + } else { + ret = 0; + } + + // deliver callback to indicate completion of state saving operation + StateChanged(M64CORE_STATE_SAVECOMPLETE, ret); +#endif // __LIBRETRO__ savestates_clear_job(); + return ret; } void savestates_init(void) { +#ifdef USE_SDL savestates_lock = SDL_CreateMutex(); if (!savestates_lock) { DebugMessage(M64MSG_ERROR, "Could not create savestates list lock"); return; } +#endif } void savestates_deinit(void) { +#ifdef USE_SDL SDL_DestroyMutex(savestates_lock); +#endif savestates_clear_job(); } diff --git a/src/main/savestates.h b/src/main/savestates.h index ae10352a..f74b3b6b 100644 --- a/src/main/savestates.h +++ b/src/main/savestates.h @@ -53,5 +53,13 @@ unsigned int savestates_get_slot(void); void savestates_set_autoinc_slot(int b); void savestates_inc_slot(void); +#ifndef __LIBRETRO__ +int savestates_save_m64p(const struct device* dev, char *filepath); +int savestates_load_m64p(struct device* dev, char *filepath); +#else +int savestates_save_m64p(const struct device* dev, void *data); +int savestates_load_m64p(struct device* dev, const void *data); +#endif + #endif /* __SAVESTAVES_H__ */ diff --git a/src/main/sdl_key_converter.h b/src/main/sdl_key_converter.h index 84fce4de..19d3274e 100644 --- a/src/main/sdl_key_converter.h +++ b/src/main/sdl_key_converter.h @@ -19,7 +19,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#include #include #include "osal/preproc.h" @@ -29,10 +28,10 @@ uint16_t sdl_scancode2keysym(uint16_t scancode); static osal_inline uint16_t sdl_keysym2native(uint16_t keysym) { - return sdl_keysym2scancode(keysym); + return keysym; } static osal_inline uint16_t sdl_native2keysym(uint16_t native) { - return sdl_scancode2keysym(native); + return native; } diff --git a/src/plugin/plugin.c b/src/plugin/plugin.c index 86e119ff..e0246bbc 100644 --- a/src/plugin/plugin.c +++ b/src/plugin/plugin.c @@ -36,45 +36,79 @@ #include "device/rcp/vi/vi_controller.h" #include "dummy_audio.h" #include "dummy_input.h" -#include "dummy_rsp.h" -#include "dummy_video.h" #include "main/main.h" #include "main/rom.h" #include "main/version.h" #include "osal/dynamiclib.h" #include "plugin.h" +#ifdef __LIBRETRO__ +#include "mupen64plus-next_common.h" +#endif + +#include CONTROL Controls[4]; +void ResizeVideoOutput(int width, int height){ + +} +/* local data structures and functions */ +#define DEFINE_GFX(X) \ + EXPORT m64p_error CALL X##PluginGetVersion(m64p_plugin_type *, int *, int *, const char **, int *); \ + EXPORT void CALL X##ChangeWindow(void); \ + EXPORT int CALL X##InitiateGFX(GFX_INFO Gfx_Info); \ + EXPORT void CALL X##MoveScreen(int x, int y); \ + EXPORT void CALL X##ProcessDList(void); \ + EXPORT void CALL X##ProcessRDPList(void); \ + EXPORT void CALL X##RomClosed(void); \ + EXPORT int CALL X##RomOpen(void); \ + EXPORT void CALL X##ShowCFB(void); \ + EXPORT void CALL X##UpdateScreen(void); \ + EXPORT void CALL X##ViStatusChanged(void); \ + EXPORT void CALL X##ViWidthChanged(void); \ + EXPORT void CALL X##ReadScreen2(void *dest, int *width, int *height, int front); \ + EXPORT void CALL X##SetRenderingCallback(void (*callback)(int)); \ + EXPORT void CALL X##ResizeVideoOutput(int width, int height); \ + EXPORT void CALL X##FBRead(unsigned int addr); \ + EXPORT void CALL X##FBWrite(unsigned int addr, unsigned int size); \ + EXPORT void CALL X##FBGetFrameBufferInfo(void *p); \ + \ + gfx_plugin_functions gfx_##X = { \ + X##PluginGetVersion, \ + X##ChangeWindow, \ + X##InitiateGFX, \ + X##MoveScreen, \ + X##ProcessDList, \ + X##ProcessRDPList, \ + X##RomClosed, \ + X##RomOpen, \ + X##ShowCFB, \ + X##UpdateScreen, \ + X##ViStatusChanged, \ + X##ViWidthChanged, \ + X##ReadScreen2, \ + X##SetRenderingCallback, \ + ResizeVideoOutput, \ + X##FBRead, \ + X##FBWrite, \ + X##FBGetFrameBufferInfo \ + } + +DEFINE_GFX(gln64); +#if defined(HAVE_THR_AL) +DEFINE_GFX(angrylion); +#endif +#if defined(HAVE_PARALLEL_RDP) +DEFINE_GFX(parallel); +#endif -/* global function pointers - initialized on core startup */ gfx_plugin_functions gfx; +GFX_INFO gfx_info; audio_plugin_functions audio; input_plugin_functions input; rsp_plugin_functions rsp; +RSP_INFO rsp_info; -/* local data structures and functions */ -static const gfx_plugin_functions dummy_gfx = { - dummyvideo_PluginGetVersion, - dummyvideo_ChangeWindow, - dummyvideo_InitiateGFX, - dummyvideo_MoveScreen, - dummyvideo_ProcessDList, - dummyvideo_ProcessRDPList, - dummyvideo_RomClosed, - dummyvideo_RomOpen, - dummyvideo_ShowCFB, - dummyvideo_UpdateScreen, - dummyvideo_ViStatusChanged, - dummyvideo_ViWidthChanged, - dummyvideo_ReadScreen2, - dummyvideo_SetRenderingCallback, - dummyvideo_ResizeVideoOutput, - dummyvideo_FBRead, - dummyvideo_FBWrite, - dummyvideo_FBGetFrameBufferInfo -}; - -static const audio_plugin_functions dummy_audio = { +const audio_plugin_functions dummy_audio = { dummyaudio_PluginGetVersion, dummyaudio_AiDacrateChanged, dummyaudio_AiLenChanged, @@ -91,14 +125,26 @@ static const audio_plugin_functions dummy_audio = { dummyaudio_VolumeGetString }; -static const input_plugin_functions dummy_input = { - dummyinput_PluginGetVersion, - dummyinput_ControllerCommand, - dummyinput_GetKeys, - dummyinput_InitiateControllers, - dummyinput_ReadController, - dummyinput_RomClosed, - dummyinput_RomOpen, + +extern m64p_error inputPluginGetVersion(m64p_plugin_type *PluginType, int *PluginVersion, + int *APIVersion, const char **PluginNamePtr, int *Capabilities); +extern void inputInitiateControllers (CONTROL_INFO ControlInfo); +extern void inputGetKeys_default(int Control, BUTTONS * Keys ); +extern void inputControllerCommand(int Control, unsigned char *Command); +extern void inputInitiateControllers(CONTROL_INFO ControlInfo); +extern void inputReadController(int Control, unsigned char *Command); +extern int inputRomOpen(void); +extern void inputRomClosed(void); + + +const input_plugin_functions dummy_input = { + inputPluginGetVersion, + inputControllerCommand, + inputGetKeys_default, + inputInitiateControllers, + inputReadController, + inputRomClosed, + inputRomOpen, dummyinput_SDL_KeyDown, dummyinput_SDL_KeyUp, dummyinput_RenderCallback, @@ -109,18 +155,8 @@ static const input_plugin_functions dummy_input = { dummyinput_SetVRUWordMask }; -static const rsp_plugin_functions dummy_rsp = { - dummyrsp_PluginGetVersion, - dummyrsp_DoRspCycles, - dummyrsp_InitiateRSP, - dummyrsp_RomClosed -}; - -static GFX_INFO gfx_info; static AUDIO_INFO audio_info; static CONTROL_INFO control_info; -static RSP_INFO rsp_info; - static int l_RspAttached = 0; static int l_InputAttached = 0; static int l_AudioAttached = 0; @@ -132,14 +168,31 @@ static unsigned int dummy; static void EmptyFunc(void) { } +/* RSP */ +#define DEFINE_RSP(X) \ + EXPORT m64p_error CALL X##PluginGetVersion(m64p_plugin_type *, int *, int *, const char **, int *); \ + EXPORT unsigned int CALL X##DoRspCycles(unsigned int Cycles); \ + EXPORT void CALL X##InitiateRSP(RSP_INFO Rsp_Info, unsigned int *CycleCount); \ + EXPORT void CALL X##RomClosed(void); \ + \ + const rsp_plugin_functions rsp_##X = { \ + X##PluginGetVersion, \ + X##DoRspCycles, \ + X##InitiateRSP, \ + X##RomClosed \ + } -// Handy macro to avoid code bloat when loading symbols -#define GET_FUNC(type, field, name) \ - ((field = (type)osal_dynlib_getproc(plugin_handle, name)) != NULL) +// Define RSP Interfaces +DEFINE_RSP(hle); + +#ifdef HAVE_PARALLEL_RSP +DEFINE_RSP(parallelRSP); +#endif // HAVE_PARALLEL_RSP + +#if HAVE_LLE +DEFINE_RSP(cxd4); +#endif // HAVE_LLE -// code to handle backwards-compatibility to video plugins with API_VERSION < 02.1.0. This API version introduced a boolean -// flag in the rendering callback, which told the core whether or not the current screen has been freshly redrawn since the -// last time the callback was called. static void (*l_mainRenderCallback)(int) = NULL; static ptr_SetRenderingCallback l_old1SetRenderingCallback = NULL; @@ -154,85 +207,10 @@ static void backcompat_setRenderCallbackIntercept(void (*callback)(int)) l_mainRenderCallback = callback; } -static void plugin_disconnect_gfx(void) +m64p_error plugin_start_gfx(void) { - gfx = dummy_gfx; - l_GfxAttached = 0; - l_mainRenderCallback = NULL; -} + printf("plugin_start_gfx\n"); -static m64p_error plugin_connect_gfx(m64p_dynlib_handle plugin_handle) -{ - /* attach the Video plugin function pointers */ - if (plugin_handle != NULL) - { - m64p_plugin_type PluginType; - int PluginVersion, APIVersion; - - if (l_GfxAttached) - return M64ERR_INVALID_STATE; - - /* set function pointers for required functions */ - if (!GET_FUNC(ptr_PluginGetVersion, gfx.getVersion, "PluginGetVersion") || - !GET_FUNC(ptr_ChangeWindow, gfx.changeWindow, "ChangeWindow") || - !GET_FUNC(ptr_InitiateGFX, gfx.initiateGFX, "InitiateGFX") || - !GET_FUNC(ptr_MoveScreen, gfx.moveScreen, "MoveScreen") || - !GET_FUNC(ptr_ProcessDList, gfx.processDList, "ProcessDList") || - !GET_FUNC(ptr_ProcessRDPList, gfx.processRDPList, "ProcessRDPList") || - !GET_FUNC(ptr_RomClosed, gfx.romClosed, "RomClosed") || - !GET_FUNC(ptr_RomOpen, gfx.romOpen, "RomOpen") || - !GET_FUNC(ptr_ShowCFB, gfx.showCFB, "ShowCFB") || - !GET_FUNC(ptr_UpdateScreen, gfx.updateScreen, "UpdateScreen") || - !GET_FUNC(ptr_ViStatusChanged, gfx.viStatusChanged, "ViStatusChanged") || - !GET_FUNC(ptr_ViWidthChanged, gfx.viWidthChanged, "ViWidthChanged") || - !GET_FUNC(ptr_ReadScreen2, gfx.readScreen, "ReadScreen2") || - !GET_FUNC(ptr_SetRenderingCallback, gfx.setRenderingCallback, "SetRenderingCallback") || - !GET_FUNC(ptr_FBRead, gfx.fBRead, "FBRead") || - !GET_FUNC(ptr_FBWrite, gfx.fBWrite, "FBWrite") || - !GET_FUNC(ptr_FBGetFrameBufferInfo, gfx.fBGetFrameBufferInfo, "FBGetFrameBufferInfo")) - { - DebugMessage(M64MSG_ERROR, "broken Video plugin; function(s) not found."); - plugin_disconnect_gfx(); - return M64ERR_INPUT_INVALID; - } - - /* set function pointers for optional functions */ - gfx.resizeVideoOutput = (ptr_ResizeVideoOutput)osal_dynlib_getproc(plugin_handle, "ResizeVideoOutput"); - - /* check the version info */ - (*gfx.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL); - if (PluginType != M64PLUGIN_GFX || (APIVersion & 0xffff0000) != (GFX_API_VERSION & 0xffff0000)) - { - DebugMessage(M64MSG_ERROR, "incompatible Video plugin"); - plugin_disconnect_gfx(); - return M64ERR_INCOMPATIBLE; - } - - /* handle backwards-compatibility */ - if (APIVersion < 0x020100) - { - DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.1.0. Screenshots may contain On Screen Display text", VERSION_PRINTF_SPLIT(APIVersion)); - // tell the video plugin to make its rendering callback to me (it's old, and doesn't have the bScreenRedrawn flag) - gfx.setRenderingCallback(backcompat_videoRenderCallback); - l_old1SetRenderingCallback = gfx.setRenderingCallback; // save this just for future use - gfx.setRenderingCallback = (ptr_SetRenderingCallback) backcompat_setRenderCallbackIntercept; - } - if (APIVersion < 0x20200 || gfx.resizeVideoOutput == NULL) - { - DebugMessage(M64MSG_WARNING, "Fallback for Video plugin API (%02i.%02i.%02i) < 2.2.0. Resizable video will not work", VERSION_PRINTF_SPLIT(APIVersion)); - gfx.resizeVideoOutput = dummyvideo_ResizeVideoOutput; - } - - l_GfxAttached = 1; - } - else - plugin_disconnect_gfx(); - - return M64ERR_SUCCESS; -} - -static m64p_error plugin_start_gfx(void) -{ uint8_t media = g_rom_size == 0 ? 0 : *((uint8_t*)mem_base_u32(g_mem_base, MM_CART_ROM) + (0x3b ^ S8)); /* Here we feed 64DD IPL ROM header to GFX plugin if 64DD is present. @@ -279,7 +257,7 @@ static m64p_error plugin_start_gfx(void) gfx_info.VI_X_SCALE_REG = &(g_dev.vi.regs[VI_X_SCALE_REG]); gfx_info.VI_Y_SCALE_REG = &(g_dev.vi.regs[VI_Y_SCALE_REG]); gfx_info.CheckInterrupts = EmptyFunc; - + gfx_info.version = 2; //Version 2 added SP_STATUS_REG and RDRAM_SIZE gfx_info.SP_STATUS_REG = &g_dev.sp.regs[SP_STATUS_REG]; gfx_info.RDRAM_SIZE = (unsigned int*) &g_dev.rdram.dram_size; @@ -297,54 +275,6 @@ static void plugin_disconnect_audio(void) l_AudioAttached = 0; } -static m64p_error plugin_connect_audio(m64p_dynlib_handle plugin_handle) -{ - /* attach the Audio plugin function pointers */ - if (plugin_handle != NULL) - { - m64p_plugin_type PluginType; - int PluginVersion, APIVersion; - - if (l_AudioAttached) - return M64ERR_INVALID_STATE; - - if (!GET_FUNC(ptr_PluginGetVersion, audio.getVersion, "PluginGetVersion") || - !GET_FUNC(ptr_AiDacrateChanged, audio.aiDacrateChanged, "AiDacrateChanged") || - !GET_FUNC(ptr_AiLenChanged, audio.aiLenChanged, "AiLenChanged") || - !GET_FUNC(ptr_InitiateAudio, audio.initiateAudio, "InitiateAudio") || - !GET_FUNC(ptr_ProcessAList, audio.processAList, "ProcessAList") || - !GET_FUNC(ptr_RomOpen, audio.romOpen, "RomOpen") || - !GET_FUNC(ptr_RomClosed, audio.romClosed, "RomClosed") || - !GET_FUNC(ptr_SetSpeedFactor, audio.setSpeedFactor, "SetSpeedFactor") || - !GET_FUNC(ptr_VolumeUp, audio.volumeUp, "VolumeUp") || - !GET_FUNC(ptr_VolumeDown, audio.volumeDown, "VolumeDown") || - !GET_FUNC(ptr_VolumeGetLevel, audio.volumeGetLevel, "VolumeGetLevel") || - !GET_FUNC(ptr_VolumeSetLevel, audio.volumeSetLevel, "VolumeSetLevel") || - !GET_FUNC(ptr_VolumeMute, audio.volumeMute, "VolumeMute") || - !GET_FUNC(ptr_VolumeGetString, audio.volumeGetString, "VolumeGetString")) - { - DebugMessage(M64MSG_ERROR, "broken Audio plugin; function(s) not found."); - plugin_disconnect_audio(); - return M64ERR_INPUT_INVALID; - } - - /* check the version info */ - (*audio.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL); - if (PluginType != M64PLUGIN_AUDIO || (APIVersion & 0xffff0000) != (AUDIO_API_VERSION & 0xffff0000)) - { - DebugMessage(M64MSG_ERROR, "incompatible Audio plugin"); - plugin_disconnect_audio(); - return M64ERR_INCOMPATIBLE; - } - - l_AudioAttached = 1; - } - else - plugin_disconnect_audio(); - - return M64ERR_SUCCESS; -} - static m64p_error plugin_start_audio(void) { /* fill in the AUDIO_INFO data structure */ @@ -373,63 +303,6 @@ static void plugin_disconnect_input(void) l_InputAttached = 0; } -static m64p_error plugin_connect_input(m64p_dynlib_handle plugin_handle) -{ - /* attach the Input plugin function pointers */ - if (plugin_handle != NULL) - { - m64p_plugin_type PluginType; - int PluginVersion, APIVersion; - - if (l_InputAttached) - return M64ERR_INVALID_STATE; - - if (!GET_FUNC(ptr_PluginGetVersion, input.getVersion, "PluginGetVersion") || - !GET_FUNC(ptr_ControllerCommand, input.controllerCommand, "ControllerCommand") || - !GET_FUNC(ptr_GetKeys, input.getKeys, "GetKeys") || - !GET_FUNC(ptr_InitiateControllers, input.initiateControllers, "InitiateControllers") || - !GET_FUNC(ptr_ReadController, input.readController, "ReadController") || - !GET_FUNC(ptr_RomOpen, input.romOpen, "RomOpen") || - !GET_FUNC(ptr_RomClosed, input.romClosed, "RomClosed") || - !GET_FUNC(ptr_SDL_KeyDown, input.keyDown, "SDL_KeyDown") || - !GET_FUNC(ptr_SDL_KeyUp, input.keyUp, "SDL_KeyUp")) - { - DebugMessage(M64MSG_ERROR, "broken Input plugin; function(s) not found."); - plugin_disconnect_input(); - return M64ERR_INPUT_INVALID; - } - - if (!GET_FUNC(ptr_SendVRUWord, input.sendVRUWord, "SendVRUWord") || - !GET_FUNC(ptr_SetMicState, input.setMicState, "SetMicState") || - !GET_FUNC(ptr_ReadVRUResults, input.readVRUResults, "ReadVRUResults") || - !GET_FUNC(ptr_ClearVRUWords, input.clearVRUWords, "ClearVRUWords") || - !GET_FUNC(ptr_SetVRUWordMask, input.setVRUWordMask, "SetVRUWordMask")) - { - DebugMessage(M64MSG_WARNING, "Input plugin does not contain VRU support."); - } - - /* check the version info */ - (*input.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL); - if (PluginType != M64PLUGIN_INPUT || (APIVersion & 0xffff0000) != (INPUT_API_VERSION & 0xffff0000) || APIVersion < 0x020100) - { - DebugMessage(M64MSG_ERROR, "incompatible Input plugin"); - plugin_disconnect_input(); - return M64ERR_INCOMPATIBLE; - } - - if (!GET_FUNC(ptr_RenderCallback, input.renderCallback, "RenderCallback")) - { - DebugMessage(M64MSG_INFO, "input plugin did not specify a render callback; there will be no on screen display by the input plugin."); - } - - l_InputAttached = 1; - } - else - plugin_disconnect_input(); - - return M64ERR_SUCCESS; -} - static m64p_error plugin_start_input(void) { int i; @@ -450,50 +323,6 @@ static m64p_error plugin_start_input(void) return M64ERR_SUCCESS; } -static void plugin_disconnect_rsp(void) -{ - rsp = dummy_rsp; - l_RspAttached = 0; -} - -static m64p_error plugin_connect_rsp(m64p_dynlib_handle plugin_handle) -{ - /* attach the RSP plugin function pointers */ - if (plugin_handle != NULL) - { - m64p_plugin_type PluginType; - int PluginVersion, APIVersion; - - if (l_RspAttached) - return M64ERR_INVALID_STATE; - - if (!GET_FUNC(ptr_PluginGetVersion, rsp.getVersion, "PluginGetVersion") || - !GET_FUNC(ptr_DoRspCycles, rsp.doRspCycles, "DoRspCycles") || - !GET_FUNC(ptr_InitiateRSP, rsp.initiateRSP, "InitiateRSP") || - !GET_FUNC(ptr_RomClosed, rsp.romClosed, "RomClosed")) - { - DebugMessage(M64MSG_ERROR, "broken RSP plugin; function(s) not found."); - plugin_disconnect_rsp(); - return M64ERR_INPUT_INVALID; - } - - /* check the version info */ - (*rsp.getVersion)(&PluginType, &PluginVersion, &APIVersion, NULL, NULL); - if (PluginType != M64PLUGIN_RSP || (APIVersion & 0xffff0000) != (RSP_API_VERSION & 0xffff0000)) - { - DebugMessage(M64MSG_ERROR, "incompatible RSP plugin"); - plugin_disconnect_rsp(); - return M64ERR_INCOMPATIBLE; - } - - l_RspAttached = 1; - } - else - plugin_disconnect_rsp(); - - return M64ERR_SUCCESS; -} - static m64p_error plugin_start_rsp(void) { /* fill in the RSP_INFO data structure */ @@ -530,32 +359,6 @@ static m64p_error plugin_start_rsp(void) return M64ERR_SUCCESS; } -/* global functions */ -m64p_error plugin_connect(m64p_plugin_type type, m64p_dynlib_handle plugin_handle) -{ - switch(type) - { - case M64PLUGIN_GFX: - if (plugin_handle != NULL && (l_AudioAttached || l_InputAttached || l_RspAttached)) - DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order."); - return plugin_connect_gfx(plugin_handle); - case M64PLUGIN_AUDIO: - if (plugin_handle != NULL && (l_InputAttached || l_RspAttached)) - DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order."); - return plugin_connect_audio(plugin_handle); - case M64PLUGIN_INPUT: - if (plugin_handle != NULL && (l_RspAttached)) - DebugMessage(M64MSG_WARNING, "Front-end bug: plugins are attached in wrong order."); - return plugin_connect_input(plugin_handle); - case M64PLUGIN_RSP: - return plugin_connect_rsp(plugin_handle); - default: - return M64ERR_INPUT_INVALID; - } - - return M64ERR_INTERNAL; -} - m64p_error plugin_start(m64p_plugin_type type) { switch(type) @@ -589,3 +392,116 @@ m64p_error plugin_check(void) return M64ERR_SUCCESS; } +#ifdef __LIBRETRO__ +enum rdp_plugin_type current_rdp_type = RDP_PLUGIN_NONE; +enum rsp_plugin_type current_rsp_type = RSP_PLUGIN_NONE; + +void plugin_connect_rdp_api(enum rdp_plugin_type type) +{ + switch (type) + { + case RDP_PLUGIN_GLIDEN64: + case RDP_PLUGIN_ANGRYLION: + case RDP_PLUGIN_PARALLEL: + current_rdp_type = type; + break; + case RSP_PLUGIN_NONE: + default: + break; + } +} + +void plugin_connect_rsp_api(enum rsp_plugin_type type) +{ + switch (type) + { + case RSP_PLUGIN_HLE: + case RSP_PLUGIN_CXD4: + case RSP_PLUGIN_PARALLEL: + current_rsp_type = type; + break; + case RSP_PLUGIN_NONE: + default: + break; + } +} + +/* global functions */ +void plugin_connect_all() +{ + switch (current_rdp_type) + { + case RDP_PLUGIN_ANGRYLION: +#ifdef HAVE_THR_AL + gfx = gfx_angrylion; +#endif + break; + case RDP_PLUGIN_PARALLEL: +#ifdef HAVE_PARALLEL_RDP + gfx = gfx_parallel; +#endif + break; + case RDP_PLUGIN_GLIDEN64: + gfx = gfx_gln64; + break; + case RDP_PLUGIN_NONE: + default: + break; + } + + l_GfxAttached = 1; + plugin_start_gfx(); + + switch (current_rsp_type) + { + case RSP_PLUGIN_HLE: + rsp = rsp_hle; + break; + case RSP_PLUGIN_CXD4: +#ifdef HAVE_LLE + rsp = rsp_cxd4; +#endif // HAVE_LLE + break; + case RSP_PLUGIN_PARALLEL: +#ifdef HAVE_PARALLEL_RSP + rsp = rsp_parallelRSP; +#endif // HAVE_PARALLEL_RSP + break; + case RSP_PLUGIN_NONE: + default: + break; + } + + l_RspAttached = 1; + plugin_start_rsp(); + + audio = dummy_audio; + l_AudioAttached = 1; + //plugin_start_audio(); + + input = dummy_input; + l_InputAttached = 1; + plugin_start_input(); +} +#else +/* global functions */ +void plugin_connect_all() +{ + gfx = gfx_gln64; + l_GfxAttached = 1; + plugin_start_gfx(); + + rsp = rsp_hle; + l_RspAttached = 1; + plugin_start_rsp(); + + audio = dummy_audio; + l_AudioAttached = 1; + //plugin_start_audio(); + + input = dummy_input; + l_InputAttached = 1; + plugin_start_input(); +} +#endif + diff --git a/src/plugin/plugin.h b/src/plugin/plugin.h index c5be095b..69836d28 100644 --- a/src/plugin/plugin.h +++ b/src/plugin/plugin.h @@ -26,6 +26,11 @@ #include "api/m64p_common.h" #include "api/m64p_plugin.h" #include "api/m64p_types.h" +#include "mupen64plus-next_common.h" + +extern GFX_INFO gfx_info; + +extern CONTROL Controls[4]; extern m64p_error plugin_connect(m64p_plugin_type, m64p_dynlib_handle plugin_handle); extern m64p_error plugin_start(m64p_plugin_type);