mirror of
https://github.com/libretro/mupen64plus-core.git
synced 2026-11-07 04:16:02 -10:00
[WIP] Add mupen64plus-core minimal changes
Platform buildfix - is this accurate enough? WIP Dynarec Speed workaround at perf cost C89 fix Remove dummy_rsp Fix awk Fix savestates, some ground work for cheats cleanup Transition fixes (CBFD etc) Fix cheats Fix Savefiles [LIBNX] Small dynarec perf hack ASM defines for android, currently not generated. Libnx transition cleanup Add Fullspeed Core option (simliar to ParaLLEl) Add CountPerScanlineOverride (VI Refresh Overclock) Similar to ParaLLEl new_dynarec: add assembler defines for ARM platform * Right now if the platform generates them they will pop up in `asm_defines` and that takes priority over the backend folders, so lets just commit them for the time being (m4xw). Fix deinit Potential mitigation for Indiana Jones (aarch64) Only relevant with new GLideN64 Check inputs using poll callback. [NXJIT] Cleanup, use RW/RX bases Still missing Horizon ver. detection GLideN64 needed changes (WIP) Minor cleanup stop_after_jal for all but libnx Added core option: ForceDisableExtraMem N64DD Support via Subsystems Fix new_dynarec uncached code execution Add alternative loading of DD image files - Relevant for broken Subsystem on static Platforms, like Switch Add CXD4. ParallelRSP Preperations Implement angrylion core-options and multi-plugin handling Co-authored-by: twinaphex <[email protected]> First revision of new Core options - Deprecated GLN header for Core options - Add Hybrid Filter Core option - Add Dithering Pattern Core option - Add Dithering Quantization Core option - Add RDRAM Image Dithering Mode Core option - Additional thanks to Tatsuya79 and dmrlawson Update & Revert to Stock INI Headers - Removes OoT Subscreen fix, might've caused Issues [GLN64] Implement Threaded Renderer [NX] Test JIT Changes - Lowers platform requirements [Core] Remove CountPerOp=1 for Quake 2 and Goldfinger - This cripples perf on Switch and Android with GLN64 - No regression has been found so far Remove Bone displacement fix after testing for DK64, update INI headers Add IgnoreTLBExceptions Options - Current workaround for the tricky Dynarec Issue for OoT - Added 3 Modes, one only skips if the game doesn't use TLB, one always skips (useful for GdbStub) and one is upstream behaviour Integrate paraLLEl-RDP. Fix build without new_dynarec Better handling for dynarec tlb exception filter Add GET_CLEAR_ALL_THREAD_WAITS_CB, fixes all freezes with thr on several platforms. Also force early polling instead of late for it. Update pre-created asm defines for aarch64 Only relevant for Android Backport 07f09151 to arm/x64/x86 dynarec backends Add asm defines for Android x86 / x86_64 and allow Android x86_64 core to be built Fix macro after libretro-common rebase [Fixme] Remove all baked headers Liberate rdram_size after rebase again [Squash me] Fixes after rebase Experimental transferpak Experimental netplay Hacky expose fast fwd w/o env cb (needs v/a sync off) Fix storage sharing for netplay Fast fwd extension (unreleased, amend and remove libretro.h later) Fix PIC for x86 new_dynarec, enable Android x86 TODO: Try ndk bump Trivial perf improvement on initial recompilation Use original delta method for android, fallback to new method for nasm Explicitly declare fPIC flags Misc fixes & disable netplay support Add asm_defines headers for Android Add sys/types.h for u_int declaration Fixes after rebase Cleanup & Update INI Headers Placeholder for DD disk saves Update asm_defines for Android Fix file_storage_save Strdup all globals and let the inner core handle their lifetime Cleanup global paths garbage collection, add cleanup_global_paths Use ifile_storage_ro handler for save types Lower logs in dd_controller Note: Maybe causes netplay shenanigans as-is, verify DD disk name shenanigans Move mempak filestorage to readonly (handled via libretro) Sanity checks Add CountPerOpDenomPot (Overclock) Cache flush optimization for pointer invalidation TODO: Port to ARMv7 Update asm_defines headers for Android Build on OSX arm64
This commit is contained in:
1 parent
0926b5fed5
commit
66ea86b46a
36 files changed
+1129
-993
No files matched your search
@@ -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)
|
||||
|
||||
+9
-76
@@ -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 <SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <md5.h>
|
||||
|
||||
#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 */
|
||||
|
||||
@@ -23,15 +23,6 @@
|
||||
* outside of the core library.
|
||||
*/
|
||||
|
||||
#include <SDL.h>
|
||||
/* 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 <SDL_vulkan.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#include "main/util.h"
|
||||
#include "main/netplay.h"
|
||||
|
||||
#include <libretro_private.h>
|
||||
#include <mupen64plus-next_common.h>
|
||||
|
||||
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;
|
||||
|
||||
@@ -20,6 +20,17 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <stdint.h>
|
||||
#include "plugins_compat.h"
|
||||
|
||||
#include "api/m64p_plugin.h"
|
||||
#include "plugin/plugin.h"
|
||||
|
||||
#include "main/main.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <api/m64p_plugin.h>
|
||||
#include <api/callbacks.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <string.h>
|
||||
#include <api/m64p_plugin.h>
|
||||
#include <api/callbacks.h>
|
||||
#include <mupen64plus-next_common.h>
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,11 @@
|
||||
#include "api/m64p_types.h"
|
||||
#include "api/callbacks.h"
|
||||
|
||||
#include <SDL_timer.h>
|
||||
#ifdef HAVE_LIBNX
|
||||
#include <switch.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -42,10 +42,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) || defined(HAVE_LIBNX)
|
||||
#include <malloc.h>
|
||||
#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 */
|
||||
|
||||
@@ -40,7 +40,9 @@ static __inline float truncf(float x) { return (float)(int)x; }
|
||||
|
||||
#else
|
||||
#define M64P_FPU_INLINE static inline
|
||||
#include <fenv.h>
|
||||
#if !defined(VITA) && !defined(__SWITCH__)
|
||||
#include <fenv.h>
|
||||
#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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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;hr<HOST_REGS;hr++) {
|
||||
int hr;
|
||||
for(hr=0;hr<HOST_REGS;hr++) {
|
||||
if(i_regs->regmap[hr]>=0) reglist|=1<<hr;
|
||||
}
|
||||
|
||||
@@ -4658,4 +4665,6 @@ static void arch_init(void) {
|
||||
ptr2++;
|
||||
ptr3+=2;
|
||||
}
|
||||
|
||||
__clear_cache((char *)base_addr+(1<<TARGET_SIZE_2)-JUMP_TABLE_SIZE,(char *)base_addr+(1<<TARGET_SIZE_2));
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
#define HOST_BTREG 19 /* callee-save */
|
||||
#define EXCLUDE_REG 29 /* FP */
|
||||
|
||||
//#define DISABLE_BLOCK_LINKING 1
|
||||
#define NATIVE_64 1
|
||||
#define HOST_IMM8 1
|
||||
//#define HAVE_CMOV_IMM 1
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h> // needed for u_int, u_char, etc
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#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 <sys/mman.h>
|
||||
#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<<TARGET_SIZE_2, 0,0,0,0);
|
||||
base_addr_rx = (void*)jit_memory;
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
@@ -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<<TARGET_SIZE_2,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
@@ -8791,7 +8810,11 @@ void new_dynarec_init(void)
|
||||
// Copy this into local area so we don't have to put it in every literal pool
|
||||
g_dev.r4300.new_dynarec_hot_state.invc_ptr=g_dev.r4300.cached_interp.invalid_code;
|
||||
#endif
|
||||
#ifdef HAVE_LIBNX
|
||||
stop_after_jal=0;
|
||||
#else
|
||||
stop_after_jal=1;
|
||||
#endif
|
||||
// TLB
|
||||
using_tlb=0;
|
||||
for(n=0;n<524288;n++) // 0 .. 0x7FFFFFFF
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#define offsetof_struct_device_r4300 (0x00000000)
|
||||
#define offsetof_struct_r4300_core_cp0 (0x031017e8)
|
||||
#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 (0x000000f0)
|
||||
#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 (0x000005c0)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rt (0x000005c8)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rd (0x000005d0)
|
||||
#define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000005e0)
|
||||
#define offsetof_struct_new_dynarec_hot_state_memory_map (0x000007e0)
|
||||
@@ -0,0 +1,35 @@
|
||||
%define offsetof_struct_device_r4300 (0x00000000)
|
||||
%define offsetof_struct_r4300_core_cp0 (0x031017e8)
|
||||
%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 (0x000000f0)
|
||||
%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 (0x000005c0)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rt (0x000005c8)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rd (0x000005d0)
|
||||
%define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000005e0)
|
||||
%define offsetof_struct_new_dynarec_hot_state_memory_map (0x000007e0)
|
||||
@@ -0,0 +1,35 @@
|
||||
#define offsetof_struct_device_r4300 (0x00000000)
|
||||
#define offsetof_struct_r4300_core_cp0 (0x029014c0)
|
||||
#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 (0x00000074)
|
||||
#define offsetof_struct_new_dynarec_hot_state_hi (0x00000174)
|
||||
#define offsetof_struct_new_dynarec_hot_state_lo (0x0000017c)
|
||||
#define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000184)
|
||||
#define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x00000204)
|
||||
#define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x00000284)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x00000304)
|
||||
#define offsetof_struct_new_dynarec_hot_state_branch_target (0x00000314)
|
||||
#define offsetof_struct_new_dynarec_hot_state_pc (0x00000318)
|
||||
#define offsetof_struct_new_dynarec_hot_state_fake_pc (0x0000031c)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rs (0x000003a0)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rt (0x000003a8)
|
||||
#define offsetof_struct_new_dynarec_hot_state_rd (0x000003b0)
|
||||
#define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000003bc)
|
||||
#define offsetof_struct_new_dynarec_hot_state_memory_map (0x000004bc)
|
||||
@@ -0,0 +1,35 @@
|
||||
%define offsetof_struct_device_r4300 (0x00000000)
|
||||
%define offsetof_struct_r4300_core_cp0 (0x029014c0)
|
||||
%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 (0x00000074)
|
||||
%define offsetof_struct_new_dynarec_hot_state_hi (0x00000174)
|
||||
%define offsetof_struct_new_dynarec_hot_state_lo (0x0000017c)
|
||||
%define offsetof_struct_new_dynarec_hot_state_cp0_regs (0x00000184)
|
||||
%define offsetof_struct_new_dynarec_hot_state_cp1_regs_simple (0x00000204)
|
||||
%define offsetof_struct_new_dynarec_hot_state_cp1_regs_double (0x00000284)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rounding_modes (0x00000304)
|
||||
%define offsetof_struct_new_dynarec_hot_state_branch_target (0x00000314)
|
||||
%define offsetof_struct_new_dynarec_hot_state_pc (0x00000318)
|
||||
%define offsetof_struct_new_dynarec_hot_state_fake_pc (0x0000031c)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rs (0x000003a0)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rt (0x000003a8)
|
||||
%define offsetof_struct_new_dynarec_hot_state_rd (0x000003b0)
|
||||
%define offsetof_struct_new_dynarec_hot_state_mini_ht (0x000003bc)
|
||||
%define offsetof_struct_new_dynarec_hot_state_memory_map (0x000004bc)
|
||||
@@ -60,6 +60,10 @@ static const u_int invalidate_block_reg[8] = {
|
||||
static void set_jump_target(int addr,int target)
|
||||
{
|
||||
u_char *ptr=(u_char *)addr;
|
||||
|
||||
if(!ptr) // Indiana Jones is weird
|
||||
return;
|
||||
|
||||
if(*ptr==0x0f)
|
||||
{
|
||||
assert(ptr[1]>=0x80&&ptr[1]<=0x8f);
|
||||
|
||||
@@ -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)
|
||||
|
||||
+30
-1
@@ -20,6 +20,7 @@
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include "tlb.h"
|
||||
#include <mupen64plus-next_common.h>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "device/rcp/mi/mi_controller.h"
|
||||
#include "main/main.h"
|
||||
#include "plugin/plugin.h"
|
||||
#include <mupen64plus-next_common.h>
|
||||
|
||||
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);
|
||||
|
||||
+3
-37
@@ -22,8 +22,6 @@
|
||||
|
||||
/* gameshark and xploder64 reference: http://doc.kodewerx.net/hacking_n64.html */
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,13 +20,10 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <SDL.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
SDL_JoystickID l_iJoyInstanceID[10];
|
||||
|
||||
#define M64P_CORE_PROTOTYPES 1
|
||||
#include "api/callbacks.h"
|
||||
#include "api/config.h"
|
||||
|
||||
+227
-490
File diff suppressed because it is too large.
Load diff
+38
-13
@@ -29,11 +29,20 @@
|
||||
#include "backends/plugins_compat/plugins_compat.h"
|
||||
#include "netplay.h"
|
||||
|
||||
#include <SDL_net.h>
|
||||
#include <mupen64plus-next_common.h>
|
||||
|
||||
#include <SDL2/SDL_net.h>
|
||||
#if !defined(WIN32)
|
||||
#include <netinet/ip.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LIBNX
|
||||
#include <netinet/ip.h>
|
||||
#else
|
||||
#include <switch.h>
|
||||
#include <netinet/in.h>
|
||||
#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
|
||||
|
||||
+1
-1
@@ -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)
|
||||
|
||||
+163
-14
@@ -22,8 +22,12 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#ifdef USE_SDL
|
||||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -31,8 +35,6 @@
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <zlib.h>
|
||||
#include <minizip/unzip.h>
|
||||
#include <minizip/zip.h>
|
||||
|
||||
#define M64P_CORE_PROTOTYPES 1
|
||||
#include "api/callbacks.h"
|
||||
@@ -51,6 +53,9 @@
|
||||
#include "util.h"
|
||||
#include "workqueue.h"
|
||||
|
||||
#include <unzip.h>
|
||||
#include <zip.h>
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -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__ */
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
#include <SDL.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
+219
-303
@@ -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 <stdio.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user