2013-12-19 17:10:14 +00:00
|
|
|
// nullDC.cpp : Makes magic cookies
|
|
|
|
//
|
|
|
|
|
|
|
|
//initialse Emu
|
|
|
|
#include "types.h"
|
|
|
|
#include "oslib/oslib.h"
|
2015-07-17 21:58:46 +00:00
|
|
|
#include "oslib/audiostream.h"
|
2013-12-19 17:10:14 +00:00
|
|
|
#include "hw/mem/_vmem.h"
|
|
|
|
#include "stdclass.h"
|
|
|
|
#include "cfg/cfg.h"
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
#include "hw/maple/maple_cfg.h"
|
|
|
|
#include "hw/sh4/sh4_mem.h"
|
|
|
|
|
2014-04-22 14:32:04 +00:00
|
|
|
#include "webui/server.h"
|
2015-08-09 20:39:32 +00:00
|
|
|
#include "hw/naomi/naomi_cart.h"
|
2018-05-22 13:20:37 +00:00
|
|
|
#include "reios/reios.h"
|
2018-10-29 14:11:34 +00:00
|
|
|
#include "hw/sh4/sh4_sched.h"
|
2018-09-23 14:18:35 +00:00
|
|
|
#include "hw/pvr/Renderer_if.h"
|
2018-10-29 14:11:34 +00:00
|
|
|
#include "hw/pvr/spg.h"
|
2014-04-22 14:32:04 +00:00
|
|
|
|
2018-10-29 15:53:26 +00:00
|
|
|
void FlushCache();
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
settings_t settings;
|
2018-11-11 22:49:41 +00:00
|
|
|
static bool continue_running = false;
|
2018-09-02 13:49:23 +00:00
|
|
|
static cMutex mtx_serialization ;
|
|
|
|
static cMutex mtx_mainloop ;
|
2018-11-11 22:49:41 +00:00
|
|
|
static int new_dynarec_setting = -1;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
libndc
|
|
|
|
|
|
|
|
//initialise (and parse the command line)
|
|
|
|
ndc_init(argc,argv);
|
|
|
|
|
|
|
|
...
|
|
|
|
//run a dreamcast slice
|
|
|
|
//either a frame, or up to 25 ms of emulation
|
|
|
|
//returns 1 if the frame is ready (fb needs to be flipped -- i'm looking at you android)
|
|
|
|
ndc_step();
|
|
|
|
|
|
|
|
...
|
|
|
|
//terminate (and free everything)
|
|
|
|
ndc_term()
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if HOST_OS==OS_WINDOWS
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2018-09-02 13:49:23 +00:00
|
|
|
/**
|
|
|
|
* cpu_features_get_time_usec:
|
|
|
|
*
|
|
|
|
* Gets time in microseconds.
|
|
|
|
*
|
|
|
|
* Returns: time in microseconds.
|
|
|
|
**/
|
|
|
|
int64_t get_time_usec(void)
|
|
|
|
{
|
|
|
|
#if HOST_OS==OS_WINDOWS
|
|
|
|
static LARGE_INTEGER freq;
|
|
|
|
LARGE_INTEGER count;
|
|
|
|
|
|
|
|
/* Frequency is guaranteed to not change. */
|
|
|
|
if (!freq.QuadPart && !QueryPerformanceFrequency(&freq))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!QueryPerformanceCounter(&count))
|
|
|
|
return 0;
|
|
|
|
return count.QuadPart * 1000000 / freq.QuadPart;
|
|
|
|
#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__) || HOST_OS==OS_LINUX
|
|
|
|
struct timespec tv = {0};
|
|
|
|
if (clock_gettime(CLOCK_MONOTONIC, &tv) < 0)
|
|
|
|
return 0;
|
|
|
|
return tv.tv_sec * INT64_C(1000000) + (tv.tv_nsec + 500) / 1000;
|
|
|
|
#elif defined(EMSCRIPTEN)
|
|
|
|
return emscripten_get_now() * 1000;
|
|
|
|
#elif defined(__mips__) || defined(DJGPP)
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv,NULL);
|
|
|
|
return (1000000 * tv.tv_sec + tv.tv_usec);
|
|
|
|
#else
|
|
|
|
#error "Your platform does not have a timer function implemented in cpu_features_get_time_usec(). Cannot continue."
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-08-28 17:38:11 +00:00
|
|
|
int GetFile(char *szFileName, char *szParse=0, u32 flags=0)
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
cfgLoadStr("config","image",szFileName,"null");
|
|
|
|
if (strcmp(szFileName,"null")==0)
|
|
|
|
{
|
|
|
|
#if HOST_OS==OS_WINDOWS
|
|
|
|
OPENFILENAME ofn;
|
|
|
|
ZeroMemory( &ofn , sizeof( ofn));
|
|
|
|
ofn.lStructSize = sizeof ( ofn );
|
|
|
|
ofn.hwndOwner = NULL ;
|
|
|
|
ofn.lpstrFile = szFileName ;
|
|
|
|
ofn.lpstrFile[0] = '\0';
|
|
|
|
ofn.nMaxFile = MAX_PATH;
|
|
|
|
ofn.lpstrFilter = "All\0*.*\0\0";
|
|
|
|
ofn.nFilterIndex =1;
|
|
|
|
ofn.lpstrFileTitle = NULL ;
|
|
|
|
ofn.nMaxFileTitle = 0 ;
|
|
|
|
ofn.lpstrInitialDir=NULL ;
|
|
|
|
ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;
|
|
|
|
|
|
|
|
if (GetOpenFileNameA(&ofn))
|
|
|
|
{
|
|
|
|
//already there
|
|
|
|
//strcpy(szFileName,ofn.lpstrFile);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-08-28 17:38:11 +00:00
|
|
|
return 1;
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
s32 plugins_Init()
|
|
|
|
{
|
|
|
|
|
|
|
|
if (s32 rv = libPvr_Init())
|
|
|
|
return rv;
|
|
|
|
|
2018-07-16 15:19:45 +00:00
|
|
|
#ifndef TARGET_DISPFRAME
|
2013-12-19 17:10:14 +00:00
|
|
|
if (s32 rv = libGDR_Init())
|
|
|
|
return rv;
|
2018-07-16 15:19:45 +00:00
|
|
|
#endif
|
2018-11-05 21:53:38 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
2015-08-09 20:39:32 +00:00
|
|
|
if (!naomi_cart_SelectFile(libPvr_GetRenderTarget()))
|
2013-12-19 17:10:14 +00:00
|
|
|
return rv_serror;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (s32 rv = libAICA_Init())
|
|
|
|
return rv;
|
2018-08-20 11:36:34 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
if (s32 rv = libARM_Init())
|
|
|
|
return rv;
|
2018-08-20 11:36:34 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
//if (s32 rv = libExtDevice_Init())
|
|
|
|
// return rv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return rv_ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
void plugins_Term()
|
|
|
|
{
|
|
|
|
//term all plugins
|
|
|
|
//libExtDevice_Term();
|
|
|
|
libARM_Term();
|
|
|
|
libAICA_Term();
|
|
|
|
libGDR_Term();
|
|
|
|
libPvr_Term();
|
|
|
|
}
|
|
|
|
|
|
|
|
void plugins_Reset(bool Manual)
|
|
|
|
{
|
|
|
|
libPvr_Reset(Manual);
|
|
|
|
libGDR_Reset(Manual);
|
|
|
|
libAICA_Reset(Manual);
|
|
|
|
libARM_Reset(Manual);
|
|
|
|
//libExtDevice_Reset(Manual);
|
|
|
|
}
|
|
|
|
|
2018-09-04 16:47:12 +00:00
|
|
|
#if !defined(TARGET_NO_WEBUI) && !defined(TARGET_NO_THREADS)
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2014-04-22 14:32:04 +00:00
|
|
|
void* webui_th(void* p)
|
|
|
|
{
|
2015-02-16 22:55:11 +00:00
|
|
|
webui_start();
|
2014-04-22 14:32:04 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cThread webui_thd(&webui_th,0);
|
2015-02-16 22:55:11 +00:00
|
|
|
#endif
|
2014-04-22 14:32:04 +00:00
|
|
|
|
2018-05-22 13:20:37 +00:00
|
|
|
void LoadSpecialSettings()
|
|
|
|
{
|
2018-10-17 11:18:24 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
2018-06-29 15:10:35 +00:00
|
|
|
// Tony Hawk's Pro Skater 2
|
|
|
|
if (!strncmp("T13008D", reios_product_number, 7) || !strncmp("T13006N", reios_product_number, 7)
|
|
|
|
// Tony Hawk's Pro Skater 1
|
2018-09-05 13:32:25 +00:00
|
|
|
|| !strncmp("T40205N", reios_product_number, 7)
|
|
|
|
// Tony Hawk's Skateboarding
|
|
|
|
|| !strncmp("T40204D", reios_product_number, 7))
|
2018-05-22 13:34:33 +00:00
|
|
|
settings.rend.RenderToTextureBuffer = 1;
|
2018-06-29 15:10:35 +00:00
|
|
|
if (!strncmp("HDR-0176", reios_product_number, 8) || !strncmp("RDC-0057", reios_product_number, 8))
|
2018-05-22 13:47:02 +00:00
|
|
|
// Cosmic Smash
|
|
|
|
settings.rend.TranslucentPolygonDepthMask = 1;
|
2018-07-12 17:41:02 +00:00
|
|
|
// Pro Pinball Trilogy
|
|
|
|
if (!strncmp("T30701D", reios_product_number, 7)
|
|
|
|
// Demolition Racer
|
2018-07-13 21:24:47 +00:00
|
|
|
|| !strncmp("T15112N", reios_product_number, 7)
|
|
|
|
// Star Wars - Episode I - Racer (United Kingdom)
|
2018-08-14 07:17:22 +00:00
|
|
|
|| !strncmp("T23001D", reios_product_number, 7)
|
|
|
|
// Record of Lodoss War (EU)
|
|
|
|
|| !strncmp("T7012D", reios_product_number, 6)
|
|
|
|
// Record of Lodoss War (USA)
|
2018-09-20 11:42:48 +00:00
|
|
|
|| !strncmp("T40218N", reios_product_number, 7)
|
|
|
|
// Surf Rocket Racers
|
|
|
|
|| !strncmp("T40216N", reios_product_number, 7))
|
|
|
|
{
|
2018-09-20 15:28:41 +00:00
|
|
|
printf("Enabling Dynarec safe mode for game %s\n", reios_product_number);
|
|
|
|
settings.dynarec.safemode = 1;
|
2018-09-20 11:42:48 +00:00
|
|
|
}
|
2018-11-05 21:53:38 +00:00
|
|
|
#elif DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
2018-10-17 11:18:24 +00:00
|
|
|
if (!strcmp("METAL SLUG 6", naomi_game_id) || !strcmp("WAVE RUNNER GP", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling Dynarec safe mode for game %s\n", naomi_game_id);
|
|
|
|
settings.dynarec.safemode = 1;
|
|
|
|
}
|
|
|
|
if (!strcmp("SAMURAI SPIRITS 6", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling Extra depth scaling for game %s\n", naomi_game_id);
|
|
|
|
settings.rend.ExtraDepthScale = 1e26;
|
|
|
|
|
|
|
|
}
|
2018-10-28 11:35:19 +00:00
|
|
|
if (!strcmp("DYNAMIC GOLF", naomi_game_id)
|
|
|
|
|| !strcmp("SHOOTOUT POOL", naomi_game_id)
|
2018-11-05 21:53:38 +00:00
|
|
|
|| !strcmp("OUTTRIGGER JAPAN", naomi_game_id)
|
|
|
|
|| !strcmp("CRACKIN'DJ ver JAPAN", naomi_game_id)
|
|
|
|
|| !strcmp("CRACKIN'DJ PART2 ver JAPAN", naomi_game_id))
|
2018-10-17 11:18:24 +00:00
|
|
|
{
|
|
|
|
printf("Enabling JVS rotary encoders for game %s\n", naomi_game_id);
|
|
|
|
settings.input.JammaSetup = 2;
|
|
|
|
}
|
|
|
|
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling 4-player setup for game %s\n", naomi_game_id);
|
|
|
|
settings.input.JammaSetup = 1;
|
|
|
|
}
|
|
|
|
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
|
|
|
settings.input.JammaSetup = 3;
|
|
|
|
}
|
2018-11-06 13:01:54 +00:00
|
|
|
else if (!strcmp("RINGOUT 4X4 JAPAN", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling specific JVS setup for game %s\n", naomi_game_id);
|
|
|
|
settings.input.JammaSetup = 4;
|
|
|
|
}
|
2018-10-21 00:48:24 +00:00
|
|
|
if (!strcmp("COSMIC SMASH IN JAPAN", naomi_game_id))
|
|
|
|
{
|
|
|
|
printf("Enabling translucent depth multipass for game %s\n", naomi_game_id);
|
|
|
|
settings.rend.TranslucentPolygonDepthMask = true;
|
|
|
|
|
|
|
|
}
|
2018-10-17 11:18:24 +00:00
|
|
|
#endif
|
2018-05-22 13:20:37 +00:00
|
|
|
}
|
|
|
|
|
2018-10-28 11:35:19 +00:00
|
|
|
void dc_reset()
|
|
|
|
{
|
|
|
|
plugins_Reset(false);
|
|
|
|
mem_Reset(false);
|
|
|
|
|
|
|
|
sh4_cpu.Reset(false);
|
|
|
|
}
|
|
|
|
|
2018-08-26 11:39:32 +00:00
|
|
|
#if defined(_ANDROID)
|
|
|
|
int reios_init_value;
|
|
|
|
|
|
|
|
void reios_init(int argc,wchar* argv[])
|
|
|
|
#else
|
2013-12-19 17:10:14 +00:00
|
|
|
int dc_init(int argc,wchar* argv[])
|
2018-08-26 11:39:32 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
|
|
|
setbuf(stdin,0);
|
|
|
|
setbuf(stdout,0);
|
|
|
|
setbuf(stderr,0);
|
|
|
|
if (!_vmem_reserve())
|
|
|
|
{
|
|
|
|
printf("Failed to alloc mem\n");
|
2018-08-26 11:39:32 +00:00
|
|
|
#if defined(_ANDROID)
|
|
|
|
reios_init_value = -1;
|
|
|
|
return;
|
|
|
|
#else
|
2013-12-19 17:10:14 +00:00
|
|
|
return -1;
|
2018-08-26 11:39:32 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-04 16:47:12 +00:00
|
|
|
#if !defined(TARGET_NO_WEBUI) && !defined(TARGET_NO_THREADS)
|
2014-04-22 14:32:04 +00:00
|
|
|
webui_thd.Start();
|
2015-02-16 22:55:11 +00:00
|
|
|
#endif
|
2014-04-22 14:32:04 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
if(ParseCommandLine(argc,argv))
|
|
|
|
{
|
2018-08-26 11:39:32 +00:00
|
|
|
#if defined(_ANDROID)
|
|
|
|
reios_init_value = 69;
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
return 69;
|
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
if(!cfgOpen())
|
|
|
|
{
|
|
|
|
msgboxf("Unable to open config file",MBX_ICONERROR);
|
2018-08-26 11:39:32 +00:00
|
|
|
#if defined(_ANDROID)
|
|
|
|
reios_init_value = -4;
|
|
|
|
return;
|
|
|
|
#else
|
2013-12-19 17:10:14 +00:00
|
|
|
return -4;
|
2018-08-26 11:39:32 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
LoadSettings();
|
2014-02-16 02:31:31 +00:00
|
|
|
#ifndef _ANDROID
|
2013-12-19 17:10:14 +00:00
|
|
|
os_CreateWindow();
|
|
|
|
#endif
|
|
|
|
|
2018-08-26 11:39:32 +00:00
|
|
|
int rv = 0;
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2015-05-16 08:04:30 +00:00
|
|
|
#if HOST_OS != OS_DARWIN
|
|
|
|
#define DATA_PATH "/data/"
|
|
|
|
#else
|
|
|
|
#define DATA_PATH "/"
|
|
|
|
#endif
|
2018-08-20 11:36:34 +00:00
|
|
|
|
2015-08-28 23:28:51 +00:00
|
|
|
if (settings.bios.UseReios || !LoadRomFiles(get_readonly_data_path(DATA_PATH)))
|
2013-12-19 17:10:14 +00:00
|
|
|
{
|
2015-08-28 23:28:51 +00:00
|
|
|
if (!LoadHle(get_readonly_data_path(DATA_PATH)))
|
2018-08-26 11:39:32 +00:00
|
|
|
{
|
|
|
|
#if defined(_ANDROID)
|
|
|
|
reios_init_value = -4;
|
|
|
|
return;
|
|
|
|
#else
|
2014-12-29 21:05:35 +00:00
|
|
|
return -3;
|
2018-08-26 11:39:32 +00:00
|
|
|
#endif
|
|
|
|
}
|
2014-12-29 21:05:35 +00:00
|
|
|
else
|
2018-08-26 11:39:32 +00:00
|
|
|
{
|
2014-12-29 21:05:35 +00:00
|
|
|
printf("Did not load bios, using reios\n");
|
2018-08-26 11:39:32 +00:00
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-10-17 11:18:24 +00:00
|
|
|
if (plugins_Init())
|
|
|
|
{
|
|
|
|
#if defined(_ANDROID)
|
|
|
|
reios_init_value = -4;
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
return -3;
|
|
|
|
#endif
|
|
|
|
}
|
2018-08-26 11:39:32 +00:00
|
|
|
|
|
|
|
#if defined(_ANDROID)
|
|
|
|
}
|
|
|
|
|
|
|
|
int dc_init()
|
|
|
|
{
|
|
|
|
int rv = 0;
|
|
|
|
if (reios_init_value != 0)
|
|
|
|
return reios_init_value;
|
|
|
|
#else
|
|
|
|
LoadCustom();
|
|
|
|
#endif
|
|
|
|
|
2015-07-25 06:39:35 +00:00
|
|
|
#if FEAT_SHREC != DYNAREC_NONE
|
2018-11-11 22:49:41 +00:00
|
|
|
Get_Sh4Recompiler(&sh4_cpu);
|
|
|
|
sh4_cpu.Init(); // Also initialize the interpreter
|
2013-12-19 17:10:14 +00:00
|
|
|
if(settings.dynarec.Enable)
|
|
|
|
{
|
|
|
|
printf("Using Recompiler\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
Get_Sh4Interpreter(&sh4_cpu);
|
2018-11-11 22:49:41 +00:00
|
|
|
#if FEAT_SHREC == DYNAREC_NONE
|
|
|
|
sh4_cpu.Init();
|
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
printf("Using Interpreter\n");
|
|
|
|
}
|
2018-08-20 16:28:16 +00:00
|
|
|
|
|
|
|
InitAudio();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
mem_Init();
|
|
|
|
|
|
|
|
mem_map_default();
|
|
|
|
|
2018-08-20 11:36:34 +00:00
|
|
|
os_SetupInput();
|
2018-09-20 15:28:41 +00:00
|
|
|
|
2018-11-07 22:27:32 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_NAOMI
|
2018-08-20 11:36:34 +00:00
|
|
|
mcfg_CreateNAOMIJamma();
|
2018-11-07 22:27:32 +00:00
|
|
|
#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
|
|
|
mcfg_CreateAtomisWaveControllers();
|
2015-06-28 15:29:04 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-10-28 11:35:19 +00:00
|
|
|
dc_reset();
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2018-09-02 13:49:23 +00:00
|
|
|
bool dc_is_running()
|
|
|
|
{
|
|
|
|
return sh4_cpu.IsCpuRunning();
|
|
|
|
}
|
|
|
|
|
2018-10-02 16:29:29 +00:00
|
|
|
#ifndef TARGET_DISPFRAME
|
2013-12-19 17:10:14 +00:00
|
|
|
void dc_run()
|
|
|
|
{
|
2018-09-02 13:49:23 +00:00
|
|
|
while ( true )
|
|
|
|
{
|
2018-11-11 22:49:41 +00:00
|
|
|
continue_running = false ;
|
2018-09-02 13:49:23 +00:00
|
|
|
mtx_mainloop.Lock() ;
|
|
|
|
sh4_cpu.Run();
|
|
|
|
mtx_mainloop.Unlock() ;
|
|
|
|
|
|
|
|
mtx_serialization.Lock() ;
|
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
|
2018-11-11 22:49:41 +00:00
|
|
|
if (new_dynarec_setting != -1 && new_dynarec_setting != settings.dynarec.Enable)
|
|
|
|
{
|
|
|
|
settings.dynarec.Enable = new_dynarec_setting;
|
|
|
|
if (settings.dynarec.Enable)
|
|
|
|
{
|
|
|
|
Get_Sh4Recompiler(&sh4_cpu);
|
|
|
|
printf("Using Recompiler\n");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Get_Sh4Interpreter(&sh4_cpu);
|
|
|
|
printf("Using Interpreter\n");
|
|
|
|
}
|
|
|
|
sh4_cpu.ResetCache();
|
|
|
|
}
|
|
|
|
if (!continue_running)
|
2018-09-02 13:49:23 +00:00
|
|
|
break ;
|
|
|
|
}
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2018-07-16 15:19:45 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
|
|
|
|
void dc_term()
|
|
|
|
{
|
|
|
|
sh4_cpu.Term();
|
|
|
|
plugins_Term();
|
|
|
|
_vmem_release();
|
|
|
|
|
2018-10-29 15:31:44 +00:00
|
|
|
mcfg_DestroyDevices();
|
|
|
|
|
2014-02-16 19:02:35 +00:00
|
|
|
#ifndef _ANDROID
|
2013-12-19 17:10:14 +00:00
|
|
|
SaveSettings();
|
2014-02-16 19:02:35 +00:00
|
|
|
#endif
|
2015-08-28 23:28:51 +00:00
|
|
|
SaveRomFiles(get_writable_data_path("/data/"));
|
2018-08-20 11:36:34 +00:00
|
|
|
|
2018-07-24 12:27:58 +00:00
|
|
|
TermAudio();
|
2018-09-07 10:57:26 +00:00
|
|
|
|
|
|
|
#if !defined(TARGET_NO_WEBUI) && !defined(TARGET_NO_THREADS)
|
|
|
|
extern void sighandler(int sig);
|
|
|
|
sighandler(0);
|
|
|
|
webui_thd.WaitToEnd();
|
|
|
|
#endif
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-08-08 15:22:15 +00:00
|
|
|
#if defined(_ANDROID)
|
|
|
|
void dc_pause()
|
|
|
|
{
|
|
|
|
SaveRomFiles(get_writable_data_path("/data/"));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-07-23 17:47:24 +00:00
|
|
|
void dc_stop()
|
|
|
|
{
|
|
|
|
sh4_cpu.Stop();
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-02 13:49:23 +00:00
|
|
|
void dc_start()
|
|
|
|
{
|
|
|
|
sh4_cpu.Start();
|
|
|
|
}
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
void LoadSettings()
|
|
|
|
{
|
2014-02-16 19:02:35 +00:00
|
|
|
#ifndef _ANDROID
|
2013-12-19 17:10:14 +00:00
|
|
|
settings.dynarec.Enable = cfgLoadInt("config","Dynarec.Enabled", 1)!=0;
|
|
|
|
settings.dynarec.idleskip = cfgLoadInt("config","Dynarec.idleskip",1)!=0;
|
|
|
|
settings.dynarec.unstable_opt = cfgLoadInt("config","Dynarec.unstable-opt",0);
|
2018-09-20 15:28:41 +00:00
|
|
|
settings.dynarec.safemode = cfgLoadInt("config", "Dynarec.safe-mode", 0);
|
2015-08-11 22:58:50 +00:00
|
|
|
//disable_nvmem can't be loaded, because nvmem init is before cfg load
|
2014-01-27 15:52:23 +00:00
|
|
|
settings.dreamcast.cable = cfgLoadInt("config","Dreamcast.Cable",3);
|
2013-12-19 17:10:14 +00:00
|
|
|
settings.dreamcast.RTC = cfgLoadInt("config","Dreamcast.RTC",GetRTC_now());
|
|
|
|
settings.dreamcast.region = cfgLoadInt("config","Dreamcast.Region",3);
|
|
|
|
settings.dreamcast.broadcast = cfgLoadInt("config","Dreamcast.Broadcast",4);
|
|
|
|
settings.aica.LimitFPS = cfgLoadInt("config","aica.LimitFPS",1);
|
|
|
|
settings.aica.NoBatch = cfgLoadInt("config","aica.NoBatch",0);
|
2014-03-01 12:37:37 +00:00
|
|
|
settings.aica.NoSound = cfgLoadInt("config","aica.NoSound",0);
|
2013-12-19 17:10:14 +00:00
|
|
|
settings.rend.UseMipmaps = cfgLoadInt("config","rend.UseMipmaps",1);
|
|
|
|
settings.rend.WideScreen = cfgLoadInt("config","rend.WideScreen",0);
|
2018-05-13 14:01:08 +00:00
|
|
|
settings.rend.ShowFPS = cfgLoadInt("config", "rend.ShowFPS", 0);
|
2018-05-22 13:34:33 +00:00
|
|
|
settings.rend.RenderToTextureBuffer = cfgLoadInt("config", "rend.RenderToTextureBuffer", 0);
|
2018-07-16 14:28:48 +00:00
|
|
|
settings.rend.RenderToTextureUpscale = cfgLoadInt("config", "rend.RenderToTextureUpscale", 1);
|
2018-05-22 13:47:02 +00:00
|
|
|
settings.rend.TranslucentPolygonDepthMask = cfgLoadInt("config", "rend.TranslucentPolygonDepthMask", 0);
|
2018-06-09 15:22:01 +00:00
|
|
|
settings.rend.ModifierVolumes = cfgLoadInt("config","rend.ModifierVolumes",1);
|
2018-05-02 13:41:42 +00:00
|
|
|
settings.rend.Clipping = cfgLoadInt("config","rend.Clipping",1);
|
2018-08-01 17:43:01 +00:00
|
|
|
settings.rend.TextureUpscale = cfgLoadInt("config","rend.TextureUpscale", 1);
|
|
|
|
settings.rend.MaxFilteredTextureSize = cfgLoadInt("config","rend.MaxFilteredTextureSize", 256);
|
2018-09-04 16:37:59 +00:00
|
|
|
char extra_depth_scale_str[128];
|
|
|
|
cfgLoadStr("config","rend.ExtraDepthScale", extra_depth_scale_str, "1");
|
|
|
|
settings.rend.ExtraDepthScale = atof(extra_depth_scale_str);
|
|
|
|
if (settings.rend.ExtraDepthScale == 0)
|
|
|
|
settings.rend.ExtraDepthScale = 1.f;
|
2018-08-01 17:43:01 +00:00
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
settings.pvr.subdivide_transp = cfgLoadInt("config","pvr.Subdivide",0);
|
|
|
|
|
|
|
|
settings.pvr.ta_skip = cfgLoadInt("config","ta.skip",0);
|
|
|
|
settings.pvr.rend = cfgLoadInt("config","pvr.rend",0);
|
2015-02-25 19:56:58 +00:00
|
|
|
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.pvr.MaxThreads = cfgLoadInt("config", "pvr.MaxThreads", 3);
|
2018-08-20 16:28:16 +00:00
|
|
|
settings.pvr.SynchronousRender = cfgLoadInt("config", "pvr.SynchronousRendering", 0);
|
2015-08-07 23:36:58 +00:00
|
|
|
|
2018-08-20 16:28:16 +00:00
|
|
|
settings.debug.SerialConsole = cfgLoadInt("config", "Debug.SerialConsoleEnabled", 0) != 0;
|
2015-03-22 00:16:28 +00:00
|
|
|
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.bios.UseReios = cfgLoadInt("config", "bios.UseReios", 0);
|
|
|
|
settings.reios.ElfFile = cfgLoadStr("reios", "ElfFile", "");
|
2015-04-12 20:48:16 +00:00
|
|
|
|
|
|
|
settings.validate.OpenGlChecks = cfgLoadInt("validate", "OpenGlChecks", 0) != 0;
|
2018-09-18 07:27:16 +00:00
|
|
|
|
2018-09-24 18:53:21 +00:00
|
|
|
settings.input.DCKeyboard = cfgLoadInt("input", "DCKeyboard", 0);
|
2018-09-18 07:27:16 +00:00
|
|
|
settings.input.DCMouse = cfgLoadInt("input", "DCMouse", 0);
|
|
|
|
settings.input.MouseSensitivity = cfgLoadInt("input", "MouseSensitivity", 100);
|
2018-10-17 11:18:24 +00:00
|
|
|
settings.input.JammaSetup = cfgLoadInt("input", "JammaSetup", 0);
|
2018-08-07 07:44:52 +00:00
|
|
|
#else
|
|
|
|
// TODO Expose this with JNI
|
|
|
|
settings.rend.Clipping = 1;
|
2018-08-27 10:09:53 +00:00
|
|
|
|
|
|
|
// Configured on a per-game basis
|
2018-10-17 11:18:24 +00:00
|
|
|
settings.rend.ExtraDepthScale = 1.f;
|
2018-08-27 10:09:53 +00:00
|
|
|
settings.dynarec.safemode = 0;
|
2018-10-17 11:18:24 +00:00
|
|
|
settings.input.JammaSetup = 0;
|
2014-02-16 19:02:35 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.pvr.HashLogFile = cfgLoadStr("testing", "ta.HashLogFile", "");
|
|
|
|
settings.pvr.HashCheckFile = cfgLoadStr("testing", "ta.HashCheckFile", "");
|
2014-12-29 21:05:35 +00:00
|
|
|
|
2016-03-02 05:48:34 +00:00
|
|
|
#if SUPPORT_DISPMANX
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.dispmanx.Width = cfgLoadInt("dispmanx","width",640);
|
|
|
|
settings.dispmanx.Height = cfgLoadInt("dispmanx","height",480);
|
2018-08-20 16:28:16 +00:00
|
|
|
settings.dispmanx.Keep_Aspect = cfgLoadBool("dispmanx","maintain_aspect",true);
|
2016-03-02 05:48:34 +00:00
|
|
|
#endif
|
|
|
|
|
2013-12-20 15:24:38 +00:00
|
|
|
#if (HOST_OS != OS_LINUX || defined(_ANDROID) || defined(TARGET_PANDORA))
|
2013-12-19 17:10:14 +00:00
|
|
|
settings.aica.BufferSize=2048;
|
|
|
|
#else
|
|
|
|
settings.aica.BufferSize=1024;
|
|
|
|
#endif
|
|
|
|
|
2016-03-02 05:48:34 +00:00
|
|
|
#if USE_OMX
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.omx.Audio_Latency = cfgLoadInt("omx","audio_latency",100);
|
|
|
|
settings.omx.Audio_HDMI = cfgLoadBool("omx","audio_hdmi",true);
|
2016-03-02 05:48:34 +00:00
|
|
|
#endif
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
/*
|
|
|
|
//make sure values are valid
|
|
|
|
settings.dreamcast.cable = min(max(settings.dreamcast.cable, 0),3);
|
|
|
|
settings.dreamcast.region = min(max(settings.dreamcast.region, 0),3);
|
|
|
|
settings.dreamcast.broadcast= min(max(settings.dreamcast.broadcast,0),4);
|
|
|
|
*/
|
|
|
|
}
|
2018-08-19 03:40:26 +00:00
|
|
|
|
2018-08-20 16:28:16 +00:00
|
|
|
void LoadCustom()
|
2018-08-19 03:40:26 +00:00
|
|
|
{
|
2018-10-17 11:18:24 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
2018-08-20 16:28:16 +00:00
|
|
|
char *reios_id = reios_disk_id();
|
|
|
|
|
2018-09-21 15:47:21 +00:00
|
|
|
char *p = reios_id + strlen(reios_id) - 1;
|
|
|
|
while (p >= reios_id && *p == ' ')
|
|
|
|
*p-- = '\0';
|
|
|
|
if (*p == '\0')
|
|
|
|
return;
|
2018-11-05 21:53:38 +00:00
|
|
|
#elif DC_PLATFORM == DC_PLATFORM_NAOMI || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE
|
2018-10-17 11:18:24 +00:00
|
|
|
char *reios_id = naomi_game_id;
|
|
|
|
char *reios_software_name = naomi_game_id;
|
|
|
|
#endif
|
2018-09-21 15:47:21 +00:00
|
|
|
|
2018-09-20 15:28:41 +00:00
|
|
|
LoadSpecialSettings(); // Default per-game settings
|
|
|
|
|
|
|
|
if (reios_software_name[0] != '\0')
|
|
|
|
cfgSaveStr(reios_id, "software.name", reios_software_name);
|
|
|
|
settings.dynarec.Enable = cfgGameInt(reios_id,"Dynarec.Enabled", settings.dynarec.Enable ? 1 : 0) != 0;
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.dynarec.idleskip = cfgGameInt(reios_id,"Dynarec.idleskip", settings.dynarec.idleskip ? 1 : 0) != 0;
|
2018-08-20 18:21:23 +00:00
|
|
|
settings.dynarec.unstable_opt = cfgGameInt(reios_id,"Dynarec.unstable-opt", settings.dynarec.unstable_opt);
|
2018-09-21 08:19:57 +00:00
|
|
|
settings.dynarec.safemode = cfgGameInt(reios_id,"Dynarec.safe-mode", settings.dynarec.safemode);
|
2018-08-20 18:21:23 +00:00
|
|
|
settings.rend.ModifierVolumes = cfgGameInt(reios_id,"rend.ModifierVolumes", settings.rend.ModifierVolumes);
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.rend.Clipping = cfgGameInt(reios_id,"rend.Clipping", settings.rend.Clipping);
|
2018-08-20 16:28:16 +00:00
|
|
|
|
2018-08-20 18:21:23 +00:00
|
|
|
settings.pvr.subdivide_transp = cfgGameInt(reios_id,"pvr.Subdivide", settings.pvr.subdivide_transp);
|
2018-08-20 16:28:16 +00:00
|
|
|
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.pvr.ta_skip = cfgGameInt(reios_id,"ta.skip", settings.pvr.ta_skip);
|
|
|
|
settings.pvr.rend = cfgGameInt(reios_id,"pvr.rend", settings.pvr.rend);
|
2018-08-20 16:28:16 +00:00
|
|
|
|
2018-08-27 03:41:30 +00:00
|
|
|
settings.pvr.MaxThreads = cfgGameInt(reios_id, "pvr.MaxThreads", settings.pvr.MaxThreads);
|
2018-08-20 18:21:23 +00:00
|
|
|
settings.pvr.SynchronousRender = cfgGameInt(reios_id, "pvr.SynchronousRendering", settings.pvr.SynchronousRender);
|
2018-10-17 11:18:24 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
2018-09-21 15:47:21 +00:00
|
|
|
settings.dreamcast.cable = cfgGameInt(reios_id, "Dreamcast.Cable", settings.dreamcast.cable);
|
|
|
|
settings.dreamcast.region = cfgGameInt(reios_id, "Dreamcast.Region", settings.dreamcast.region);
|
|
|
|
settings.dreamcast.broadcast = cfgGameInt(reios_id, "Dreamcast.Broadcast", settings.dreamcast.broadcast);
|
2018-10-17 11:18:24 +00:00
|
|
|
#endif
|
2018-08-19 03:40:26 +00:00
|
|
|
}
|
|
|
|
|
2013-12-19 17:10:14 +00:00
|
|
|
void SaveSettings()
|
|
|
|
{
|
2018-08-20 16:28:16 +00:00
|
|
|
cfgSaveInt("config","Dynarec.Enabled", settings.dynarec.Enable);
|
2018-10-17 11:18:24 +00:00
|
|
|
#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
|
2018-08-20 16:28:16 +00:00
|
|
|
cfgSaveInt("config","Dreamcast.Cable", settings.dreamcast.cable);
|
|
|
|
cfgSaveInt("config","Dreamcast.RTC", settings.dreamcast.RTC);
|
|
|
|
cfgSaveInt("config","Dreamcast.Region", settings.dreamcast.region);
|
|
|
|
cfgSaveInt("config","Dreamcast.Broadcast", settings.dreamcast.broadcast);
|
2018-10-17 11:18:24 +00:00
|
|
|
#endif
|
2013-12-19 17:10:14 +00:00
|
|
|
}
|
2018-09-02 13:49:23 +00:00
|
|
|
|
|
|
|
bool wait_until_dc_running()
|
|
|
|
{
|
|
|
|
int64_t start_time = get_time_usec() ;
|
|
|
|
const int64_t FIVE_SECONDS = 5*1000000 ;
|
|
|
|
while(!dc_is_running())
|
|
|
|
{
|
|
|
|
if ( start_time+FIVE_SECONDS < get_time_usec() )
|
|
|
|
{
|
|
|
|
//timeout elapsed - dc not getting a chance to run - just bail
|
|
|
|
return false ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool acquire_mainloop_lock()
|
|
|
|
{
|
|
|
|
bool result = false ;
|
|
|
|
int64_t start_time = get_time_usec() ;
|
|
|
|
const int64_t FIVE_SECONDS = 5*1000000 ;
|
|
|
|
|
2018-09-23 14:18:35 +00:00
|
|
|
while ( ( start_time+FIVE_SECONDS > get_time_usec() ) && !(result = mtx_mainloop.TryLock()) )
|
|
|
|
{
|
|
|
|
rend_cancel_emu_wait() ;
|
|
|
|
}
|
2018-09-02 13:49:23 +00:00
|
|
|
|
2018-09-23 14:18:35 +00:00
|
|
|
return result ;
|
2018-09-02 13:49:23 +00:00
|
|
|
}
|
|
|
|
|
2018-11-11 22:49:41 +00:00
|
|
|
void dc_enable_dynarec(bool enable)
|
|
|
|
{
|
|
|
|
#if FEAT_SHREC != DYNAREC_NONE
|
|
|
|
continue_running = true;
|
|
|
|
new_dynarec_setting = enable;
|
|
|
|
dc_stop();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-09-02 13:49:23 +00:00
|
|
|
void cleanup_serialize(void *data)
|
|
|
|
{
|
|
|
|
if ( data != NULL )
|
|
|
|
free(data) ;
|
|
|
|
|
2018-11-11 22:49:41 +00:00
|
|
|
continue_running = true ;
|
2018-09-02 13:49:23 +00:00
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
mtx_mainloop.Unlock() ;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-09-20 20:41:10 +00:00
|
|
|
static string get_savestate_file_path()
|
|
|
|
{
|
|
|
|
char image_path[512];
|
|
|
|
cfgLoadStr("config", "image", image_path, "./");
|
|
|
|
string state_file = image_path;
|
|
|
|
size_t lastindex = state_file.find_last_of("/");
|
|
|
|
if (lastindex != -1)
|
|
|
|
state_file = state_file.substr(lastindex + 1);
|
|
|
|
lastindex = state_file.find_last_of(".");
|
|
|
|
if (lastindex != -1)
|
|
|
|
state_file = state_file.substr(0, lastindex);
|
|
|
|
state_file = state_file + ".state";
|
|
|
|
return get_writable_data_path("/data/") + state_file;
|
|
|
|
}
|
|
|
|
|
2018-09-02 13:49:23 +00:00
|
|
|
void* dc_savestate_thread(void* p)
|
|
|
|
{
|
2018-09-20 20:41:10 +00:00
|
|
|
string filename;
|
2018-09-02 13:49:23 +00:00
|
|
|
unsigned int total_size = 0 ;
|
|
|
|
void *data = NULL ;
|
|
|
|
void *data_ptr = NULL ;
|
|
|
|
FILE *f ;
|
|
|
|
|
|
|
|
mtx_serialization.Lock() ;
|
|
|
|
if ( !wait_until_dc_running()) {
|
|
|
|
printf("Failed to save state - dc loop kept running\n") ;
|
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
dc_stop() ;
|
|
|
|
|
|
|
|
if ( !acquire_mainloop_lock() )
|
|
|
|
{
|
|
|
|
printf("Failed to save state - could not acquire main loop lock\n") ;
|
2018-11-11 22:49:41 +00:00
|
|
|
continue_running = true ;
|
2018-09-02 13:49:23 +00:00
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! dc_serialize(&data, &total_size) )
|
|
|
|
{
|
|
|
|
printf("Failed to save state - could not initialize total size\n") ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = malloc(total_size) ;
|
|
|
|
if ( data == NULL )
|
|
|
|
{
|
|
|
|
printf("Failed to save state - could not malloc %d bytes", total_size) ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data_ptr = data ;
|
|
|
|
|
|
|
|
if ( ! dc_serialize(&data_ptr, &total_size) )
|
|
|
|
{
|
|
|
|
printf("Failed to save state - could not serialize data\n") ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-09-20 20:41:10 +00:00
|
|
|
filename = get_savestate_file_path();
|
|
|
|
f = fopen(filename.c_str(), "wb") ;
|
2018-09-02 13:49:23 +00:00
|
|
|
|
|
|
|
if ( f == NULL )
|
|
|
|
{
|
2018-09-20 20:41:10 +00:00
|
|
|
printf("Failed to save state - could not open %s for writing\n", filename.c_str()) ;
|
2018-09-02 13:49:23 +00:00
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fwrite(data, 1, total_size, f) ;
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
cleanup_serialize(data) ;
|
2018-09-20 20:41:10 +00:00
|
|
|
printf("Saved state to %s\n size %d", filename.c_str(), total_size) ;
|
2018-09-02 13:49:23 +00:00
|
|
|
|
2018-09-23 14:18:35 +00:00
|
|
|
return NULL;
|
2018-09-02 13:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void* dc_loadstate_thread(void* p)
|
|
|
|
{
|
2018-09-20 20:41:10 +00:00
|
|
|
string filename;
|
2018-09-02 13:49:23 +00:00
|
|
|
unsigned int total_size = 0 ;
|
|
|
|
void *data = NULL ;
|
|
|
|
void *data_ptr = NULL ;
|
|
|
|
FILE *f ;
|
|
|
|
|
|
|
|
mtx_serialization.Lock() ;
|
|
|
|
if ( !wait_until_dc_running()) {
|
|
|
|
printf("Failed to load state - dc loop kept running\n") ;
|
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
dc_stop() ;
|
|
|
|
|
|
|
|
if ( !acquire_mainloop_lock() )
|
|
|
|
{
|
|
|
|
printf("Failed to load state - could not acquire main loop lock\n") ;
|
2018-11-11 22:49:41 +00:00
|
|
|
continue_running = true ;
|
2018-09-02 13:49:23 +00:00
|
|
|
mtx_serialization.Unlock() ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( ! dc_serialize(&data, &total_size) )
|
|
|
|
{
|
|
|
|
printf("Failed to load state - could not initialize total size\n") ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = malloc(total_size) ;
|
|
|
|
if ( data == NULL )
|
|
|
|
{
|
|
|
|
printf("Failed to load state - could not malloc %d bytes", total_size) ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-09-20 20:41:10 +00:00
|
|
|
filename = get_savestate_file_path();
|
|
|
|
f = fopen(filename.c_str(), "rb") ;
|
2018-09-02 13:49:23 +00:00
|
|
|
|
|
|
|
if ( f == NULL )
|
|
|
|
{
|
2018-09-20 20:41:10 +00:00
|
|
|
printf("Failed to load state - could not open %s for reading\n", filename.c_str()) ;
|
2018-09-02 13:49:23 +00:00
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
fread(data, 1, total_size, f) ;
|
|
|
|
fclose(f);
|
|
|
|
|
|
|
|
|
|
|
|
data_ptr = data ;
|
|
|
|
|
2018-10-29 14:11:34 +00:00
|
|
|
sh4_cpu.ResetCache();
|
|
|
|
#if FEAT_AREC == DYNAREC_JIT
|
|
|
|
FlushCache();
|
|
|
|
#endif
|
2018-09-02 13:49:23 +00:00
|
|
|
|
|
|
|
if ( ! dc_unserialize(&data_ptr, &total_size) )
|
|
|
|
{
|
|
|
|
printf("Failed to load state - could not unserialize data\n") ;
|
|
|
|
cleanup_serialize(data) ;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-10-29 14:11:34 +00:00
|
|
|
sh4_sched_ffts();
|
|
|
|
CalculateSync();
|
|
|
|
|
|
|
|
cleanup_serialize(data) ;
|
2018-09-20 20:41:10 +00:00
|
|
|
printf("Loaded state from %s size %d\n", filename.c_str(), total_size) ;
|
2018-09-29 14:34:58 +00:00
|
|
|
rend_cancel_emu_wait();
|
2018-09-23 14:18:35 +00:00
|
|
|
|
|
|
|
return NULL;
|
2018-09-02 13:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void dc_savestate()
|
|
|
|
{
|
|
|
|
cThread thd(dc_savestate_thread,0);
|
|
|
|
thd.Start() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dc_loadstate()
|
|
|
|
{
|
|
|
|
cThread thd(dc_loadstate_thread,0);
|
|
|
|
thd.Start() ;
|
|
|
|
}
|