mirror of
https://github.com/gligli/nulldc-360.git
synced 2025-04-02 11:11:56 -04:00
582 lines
No EOL
12 KiB
C++
582 lines
No EOL
12 KiB
C++
#include "types.h"
|
|
#include "base.h"
|
|
#include "dc/maple/maple_if.h"
|
|
#include "dc/dc.h"
|
|
#include "plugins/plugin_manager.h"
|
|
|
|
#include "base.h"
|
|
#include "config/config.h"
|
|
#include "dc/mem/Elf.h"
|
|
#include "dc/gdrom/gdrom_if.h"
|
|
//#include "profiler/profiler.h"
|
|
#include "dc/sh4/rec_v1/blockmanager.h"
|
|
|
|
#define max(a,b) (((a)>(b))?(a):(b))
|
|
#define min(a,b) (((a)<(b))?(a):(b))
|
|
|
|
MenuIDList MenuIDs;
|
|
cDllHandler gui;
|
|
|
|
|
|
s32 EXPORT_CALL b_dbgReadMem(u32 addr,u32 sz,void* dst)
|
|
{
|
|
u8* ptr=(u8*)dst;
|
|
while(sz--)
|
|
*ptr++=ReadMem8(addr++);
|
|
return rv_ok;
|
|
}
|
|
s32 EXPORT_CALL b_dbgWriteMem(u32 addr,u32 sz,void* dst)
|
|
{
|
|
u8* ptr=(u8*)dst;
|
|
while(sz--)
|
|
WriteMem8(addr++,*ptr++);
|
|
return rv_ok;
|
|
}
|
|
|
|
bool EXPORT_CALL b_EmuStarted() //returns if emulation is started.
|
|
{
|
|
return sh4_cpu?sh4_cpu->IsCpuRunning():false;
|
|
}
|
|
|
|
bool EXPORT_CALL b_EmuInit()
|
|
{
|
|
return Init_DC();
|
|
}
|
|
|
|
bool EXPORT_CALL b_EmuStart() //returns false if it failed.It can fail if non inited and implicit init failed.
|
|
{
|
|
bool init=Init_DC();
|
|
if (init==false)
|
|
return false;
|
|
|
|
Start_DC();
|
|
return true;
|
|
}
|
|
void EXPORT_CALL b_EmuStop()
|
|
{
|
|
Stop_DC();
|
|
}
|
|
bool EXPORT_CALL b_EmuReset(bool Manual) //well duh it resets =P.
|
|
{
|
|
return Reset_DC(Manual);
|
|
}
|
|
|
|
bool EXPORT_CALL b_EmuStep() //returns false if it failed.It can fail if non inited or allready running.
|
|
{
|
|
if(!IsDCInited() || sh4_cpu->IsCpuRunning())
|
|
return false;
|
|
|
|
sh4_cpu->Step();
|
|
return true;
|
|
}
|
|
bool EXPORT_CALL b_EmuSkip() //returns false if it failed.It can fail if non inited or allready running.
|
|
{
|
|
if(!IsDCInited() || sh4_cpu->IsCpuRunning())
|
|
return false;
|
|
|
|
sh4_cpu->Skip();
|
|
return true;
|
|
}
|
|
|
|
void EXPORT_CALL b_EmuSetPatch(u32 Value,u32 Mask) //Enable/Disable a patch (system area hooks)
|
|
{
|
|
SetPatches(Value,Mask);
|
|
}
|
|
|
|
|
|
bool EXPORT_CALL b_EmuBootHLE() //Copies the bin file from the disc , descrambles it if needed and sets up needed regs for boot.False if it failed.
|
|
{
|
|
return false;
|
|
}
|
|
bool EXPORT_CALL b_EmuLoadBinary(char* file,u32 address) //Loads a binary on the address.If the file is elf the address is ingored and the elf's
|
|
{
|
|
return LoadBinfileToSh4Mem(address,file)!=0;
|
|
} //offsets are used
|
|
bool EXPORT_CALL b_EmuSelectPlugins() //Request the emu to show the select plugins interface
|
|
{
|
|
return plugins_Select();
|
|
}
|
|
void EXPORT_CALL b_EmuStartProfiler() //Start the TBP
|
|
{
|
|
//gli start_Profiler();
|
|
}
|
|
void EXPORT_CALL b_EmuStopProfiler() //Stop the TBP
|
|
{
|
|
//gli stop_Profiler();
|
|
}
|
|
|
|
void EXPORT_CALL b_DissasembleOpcode(u16 opcode,u32 pc,char* Dissasm)
|
|
{
|
|
char temp[2048];
|
|
DissasembleOpcode(opcode,pc,temp);
|
|
strncpy(Dissasm,temp,2048);
|
|
}
|
|
u32 EXPORT_CALL b_Sh4GetRegister(u32 reg)
|
|
{
|
|
return sh4_cpu->GetRegister((Sh4RegType)reg);
|
|
}
|
|
void EXPORT_CALL b_Sh4SetRegister(u32 reg,u32 value)
|
|
{
|
|
sh4_cpu->SetRegister((Sh4RegType)reg,value);
|
|
}
|
|
int EXPORT_CALL b_GetSymbName(u32 address,char *szDesc,bool bUseUnkAddress)
|
|
{
|
|
char temp[2048];
|
|
int rv=GetSymbName(address,temp,bUseUnkAddress);
|
|
strncpy(szDesc,temp,2048);
|
|
return rv;
|
|
}
|
|
|
|
#define maple_sett(x,y) "Current_maple" #x "_" #y
|
|
#define maple_group(x) maple_sett(x,0), maple_sett(x,1), maple_sett(x,2), maple_sett(x,3), maple_sett(x,4), maple_sett(x,5)
|
|
|
|
char* ndc_snames[]=
|
|
{
|
|
("Current_PVR"),
|
|
("Current_GDR"),
|
|
("Current_AICA"),
|
|
("Current_ARM"),
|
|
("Current_ExtDevice"),
|
|
|
|
maple_group(0),
|
|
maple_group(1),
|
|
maple_group(2),
|
|
maple_group(3),
|
|
};
|
|
|
|
#undef maple_sett
|
|
#undef maple_group
|
|
|
|
#define _esai_(n,v,ma) case NDCS_##n :*tptr=settings.v; break;
|
|
void SwitchCpu()
|
|
{
|
|
if((settings.dynarec.Enable==0 && sh4_cpu->ResetCache==0) ||
|
|
(settings.dynarec.Enable!=0 && sh4_cpu->ResetCache!=0) )
|
|
{
|
|
return;//nothing to do ...
|
|
}
|
|
|
|
bool bStart=false;
|
|
|
|
if (sh4_cpu)
|
|
{
|
|
if (sh4_cpu->IsCpuRunning())
|
|
{
|
|
bStart=true;
|
|
Stop_DC();
|
|
}
|
|
sh4_cpu->Term();
|
|
}
|
|
if(settings.dynarec.Enable)
|
|
{
|
|
sh4_cpu=Get_Sh4Recompiler();
|
|
dlog("Switched to Recompiler\n");
|
|
}
|
|
else
|
|
{
|
|
sh4_cpu=Get_Sh4Interpreter();
|
|
dlog("Switched to Interpreter\n");
|
|
}
|
|
|
|
sh4_cpu->Init();
|
|
|
|
|
|
if (bStart)
|
|
Start_DC();
|
|
}
|
|
extern const char* pluginDefaults[];
|
|
|
|
s32 EXPORT_CALL GetEmuSetting(u32 sid,void* value)
|
|
{
|
|
char* sptr=(char*)value;
|
|
u32* tptr=(u32*)value;
|
|
switch(sid)
|
|
{
|
|
|
|
_esai_(DYNAREC_ENABLED,dynarec.Enable,1);
|
|
_esai_(DYNAREC_CPPASS,dynarec.CPpass,1);
|
|
_esai_(DYNAREC_SAFEMODE,dynarec.Safe,1);
|
|
_esai_(DYNAREC_UCFPU,dynarec.UnderclockFpu,1);
|
|
|
|
_esai_(DREAMCAST_CABLE,dreamcast.cable,3);
|
|
_esai_(DREAMCAST_RTC,dreamcast.RTC,0xFFFFFFFF);
|
|
|
|
_esai_(DREAMCAST_REGION,dreamcast.region,3);
|
|
_esai_(DREAMCAST_BROADCAST,dreamcast.broadcast,4);
|
|
|
|
_esai_(EMULATOR_ASTART,emulator.AutoStart,1);
|
|
|
|
default:
|
|
if (sid<NDCS_COUNT)
|
|
{
|
|
cfgLoadStr(("nullDC_plugins"),ndc_snames[sid-NDCS_PLUGIN_PVR],sptr,pluginDefaults[sid-NDCS_PLUGIN_PVR]);
|
|
return rv_ok;
|
|
}
|
|
else
|
|
return rv_error;
|
|
}
|
|
|
|
return rv_ok;
|
|
}
|
|
#undef _esai_
|
|
|
|
#define _esai_(n,v,ma) case NDCS_##n:settings.v=min(*tptr,ma);SaveSettings();
|
|
s32 EXPORT_CALL SetEmuSetting(u32 sid,void* value)
|
|
{
|
|
char* sptr=(char*)value;
|
|
u32* tptr=(u32*)value;
|
|
|
|
switch(sid)
|
|
{
|
|
_esai_(DYNAREC_ENABLED,dynarec.Enable,1);
|
|
SwitchCpu();//switch cpu if needed
|
|
break;
|
|
|
|
_esai_(DYNAREC_CPPASS,dynarec.CPpass,1);
|
|
if (sh4_cpu->ResetCache)
|
|
sh4_cpu->ResetCache();
|
|
break;
|
|
|
|
_esai_(DYNAREC_SAFEMODE,dynarec.Safe,1);
|
|
if (sh4_cpu->ResetCache)
|
|
sh4_cpu->ResetCache();
|
|
break;
|
|
|
|
_esai_(DYNAREC_UCFPU,dynarec.UnderclockFpu,1);
|
|
if (sh4_cpu->ResetCache)
|
|
sh4_cpu->ResetCache();
|
|
break;
|
|
|
|
_esai_(DREAMCAST_CABLE,dreamcast.cable,3);
|
|
break;
|
|
|
|
_esai_(DREAMCAST_RTC,dreamcast.RTC,0xFFFFFFFF);
|
|
break;
|
|
|
|
_esai_(DREAMCAST_REGION,dreamcast.region,3);
|
|
break;
|
|
|
|
_esai_(DREAMCAST_BROADCAST,dreamcast.broadcast,4);
|
|
break;
|
|
|
|
_esai_(EMULATOR_ASTART,emulator.AutoStart,1);
|
|
break;
|
|
|
|
default:
|
|
if (sid<NDCS_COUNT)
|
|
{
|
|
cfgSaveStr(("nullDC_plugins"),ndc_snames[sid-NDCS_PLUGIN_PVR],sptr);
|
|
return rv_ok;
|
|
}
|
|
else
|
|
return rv_error;
|
|
}
|
|
|
|
return rv_ok;
|
|
}
|
|
#define nlw "\r\n"
|
|
char about_text[] =
|
|
"Credits :" nlw
|
|
" drk||Raziel \t: Main coder" nlw
|
|
" ZeZu \t\t: Main coder" nlw
|
|
" GiGaHeRz \t: Plugin work/misc stuff" nlw
|
|
" PsyMan \t\t: Mental support, managment," nlw
|
|
" \t\t beta testing & everything else" nlw
|
|
" General Plot \t\t: www & forum WIP" nlw
|
|
nlw
|
|
"Beta testing :" nlw
|
|
" emwearz, Miretank, gb_away, Raziel, General Plot," nlw
|
|
" Refraction, Ckemu,Falcon4ever, ChaosCode" nlw
|
|
nlw
|
|
"Many thanks to :" nlw
|
|
"Ector, Jim Denson, Flea, Jupi, Chankast team, lev|" nlw
|
|
"and everyone else we forgot" nlw
|
|
nlw
|
|
"Hate list:" nlw
|
|
"Xylene, for trying to mess channels by impersonating people..." nlw
|
|
" dont worry, you'l never get as good as they are." nlw
|
|
nlw
|
|
;
|
|
char* EXPORT_CALL GetAboutText()
|
|
{
|
|
return about_text;
|
|
}
|
|
PluginInfoList* EXPORT_CALL b_GetPluginList(u32 Type)
|
|
{
|
|
vector<PluginLoadInfo>* lst= GetPluginList((PluginType)Type);
|
|
|
|
PluginInfoList* rt=0,*rc=0,*rv=0;
|
|
for (u32 i=0;i<lst->size();i++)
|
|
{
|
|
rc = new PluginInfoList();
|
|
|
|
strcpy(rc->Name,(*lst)[i].Name);
|
|
strcpy(rc->dll,(*lst)[i].dll);
|
|
|
|
if(rt)
|
|
rt->next=rc;
|
|
else
|
|
rv=rc;
|
|
|
|
rt=rc;
|
|
}
|
|
|
|
delete lst;
|
|
|
|
return rv;
|
|
}
|
|
PluginInfoList* EXPORT_CALL b_GetMapleDeviceList(u32 DeviceType)
|
|
{
|
|
vector<MapleDeviceDefinition>* lst= GetMapleDeviceList((MapleDeviceType)DeviceType);
|
|
|
|
PluginInfoList* rt=0,*rc=0,*rv=0;
|
|
for (u32 i=0;i<lst->size();i++)
|
|
{
|
|
rc = new PluginInfoList();
|
|
|
|
strcpy(rc->Name,(*lst)[i].Name);
|
|
strcpy(rc->dll,(*lst)[i].dll);
|
|
rc->Flags=(*lst)[i].Flags;
|
|
|
|
if(rt)
|
|
rt->next=rc;
|
|
else
|
|
rv=rc;
|
|
|
|
rt=rc;
|
|
}
|
|
|
|
delete lst;
|
|
|
|
return rv;
|
|
}
|
|
s32 EXPORT_CALL b_FreePluginList(PluginInfoList* list)
|
|
{
|
|
if (!list)
|
|
return rv_error;
|
|
while(list)
|
|
{
|
|
PluginInfoList* next=list->next;
|
|
delete list;
|
|
list=next;
|
|
}
|
|
return rv_ok;
|
|
}
|
|
void EXPORT_CALL b_EmuResetCaches()
|
|
{
|
|
if (sh4_cpu && sh4_cpu->ResetCache)
|
|
sh4_cpu->ResetCache();
|
|
}
|
|
void EXPORT_CALL b_GetPerformanceInfo(nullDCPerfomanceInfo* dst)
|
|
{
|
|
/*gli bm_stats bms;
|
|
bm_GetStats(&bms);
|
|
prof_info tbpi(profile_info);
|
|
|
|
if (TBP_Enabled)
|
|
{
|
|
dst->TBP.Valid=1;
|
|
dst->TBP.Ticks=tbpi.total_tc;
|
|
|
|
dst->TBP.PowerVR=tbpi.current_count[GFX_TC];
|
|
dst->TBP.AICA=tbpi.current_count[AICA_TC];
|
|
dst->TBP.GDRom=tbpi.current_count[GDROM_TC];
|
|
dst->TBP.Maple=tbpi.current_count[MAPLE_TC];
|
|
dst->TBP.Main=tbpi.current_count[MAIN_TC];
|
|
dst->TBP.Dyna=tbpi.current_count[DYNA_TC];
|
|
dst->TBP.Rest=tbpi.current_count[REST_TC];
|
|
}
|
|
else
|
|
{
|
|
dst->TBP.Valid=0;
|
|
}
|
|
|
|
dst->Dynarec.CodeGen.CodeSize=bms.cache_size;
|
|
dst->Dynarec.CodeGen.SrcCodeSize=bms.block_size;
|
|
dst->Dynarec.CodeGen.LockedBlocks=bms.locked_blocks;
|
|
dst->Dynarec.CodeGen.ManualBlocks=bms.manual_blocks;
|
|
dst->Dynarec.CodeGen.TotalBlocks=bms.block_count;
|
|
dst->Dynarec.CodeGen.TotalCompileTime=bms.CompileTimeMilisecs;
|
|
|
|
#ifdef _BM_CACHE_STATS
|
|
dst->Dynarec.Runtime.Lookups.Valid=1;
|
|
dst->Dynarec.Runtime.Lookups.FastLookupDelta=bms.fast_lookups;
|
|
dst->Dynarec.Runtime.Lookups.FullLookupDelta=bms.full_lookups;
|
|
dst->Dynarec.Runtime.Lookups.LookupDelta=bms.full_lookups+bms.fast_lookups;
|
|
#else
|
|
dst->Dynarec.Runtime.Lookups.Valid=0;
|
|
#endif
|
|
|
|
#ifdef COUNT_BLOCK_LOCKTYPE_USAGE
|
|
dst->Dynarec.Runtime.Execution.Valid=1;
|
|
dst->Dynarec.Runtime.Execution.LockedBlocks=bms.locked_block_calls_delta;
|
|
dst->Dynarec.Runtime.Execution.ManualBlocks=bms.manual_block_calls_delta;
|
|
dst->Dynarec.Runtime.Execution.TotalBlocks=bms.locked_block_calls_delta+bms.manual_block_calls_delta;
|
|
#else
|
|
dst->Dynarec.Runtime.Execution.Valid=0;
|
|
#endif
|
|
|
|
#ifdef RET_CACHE_PROF
|
|
dst->Dynarec.Runtime.RetCache.Valid=1;
|
|
dst->Dynarec.Runtime.RetCache.Hits=ret_cache_hits;
|
|
dst->Dynarec.Runtime.RetCache.Count=ret_cache_total;
|
|
dst->Dynarec.Runtime.RetCache.Misses=ret_cache_total-ret_cache_hits;
|
|
ret_cache_hits=ret_cache_total=0;
|
|
#else
|
|
dst->Dynarec.Runtime.RetCache.Valid=0;
|
|
#endif
|
|
*/
|
|
}
|
|
|
|
int nCmdShow;
|
|
bool OpenAndLoadGUI(char* file)
|
|
{
|
|
if (!gui.Load(file))
|
|
{
|
|
msgboxf(("Unable to open gui dll (%s)"),MBX_ICONERROR,file);
|
|
return false;
|
|
}
|
|
|
|
ndcGetInterfaceFP* gi=(ndcGetInterfaceFP*)gui.GetProcAddress("ndcGetInterface");
|
|
|
|
if (!gi)
|
|
{
|
|
msgboxf(("Unable to resolve %s:ndcGetInterface"),MBX_ICONERROR,file);
|
|
return false;
|
|
}
|
|
gi(&libgui);
|
|
|
|
gui_emu_info gpi;
|
|
|
|
gpi.ConfigExists=cfgExists;
|
|
gpi.ConfigLoadInt=cfgLoadInt;
|
|
gpi.ConfigLoadStr=cfgLoadStr;
|
|
gpi.ConfigSaveInt=cfgSaveInt;
|
|
gpi.ConfigSaveStr=cfgSaveStr;
|
|
|
|
gpi.dbgReadMem=b_dbgReadMem;
|
|
gpi.dbgWriteMem=b_dbgWriteMem;
|
|
|
|
gpi.EmuStarted=b_EmuStarted;
|
|
|
|
gpi.EmuInit = b_EmuInit ;
|
|
|
|
gpi.EmuStart = b_EmuStart ;
|
|
gpi.EmuStop = b_EmuStop ;
|
|
gpi.EmuStep = b_EmuStep ;
|
|
gpi.EmuSkip = b_EmuSkip ;
|
|
|
|
gpi.EmuSetPatch = b_EmuSetPatch ;
|
|
gpi.EmuReset = b_EmuReset ;
|
|
gpi.EmuResetCaches=b_EmuResetCaches;
|
|
|
|
gpi.EmuBootHLE = b_EmuBootHLE ;
|
|
gpi.EmuLoadBinary = b_EmuLoadBinary ;
|
|
|
|
gpi.EmuSelectPlugins = b_EmuSelectPlugins ;
|
|
gpi.EmuStartProfiler = b_EmuStartProfiler ;
|
|
gpi.EmuStopProfiler = b_EmuStopProfiler ;
|
|
|
|
gpi.DissasembleOpcode = b_DissasembleOpcode ;
|
|
gpi.Sh4GetRegister = b_Sh4GetRegister ;
|
|
gpi.Sh4SetRegister = b_Sh4SetRegister ;
|
|
gpi.GetSymbName = b_GetSymbName ;
|
|
|
|
gpi.GetSetting=GetEmuSetting;
|
|
gpi.SetSetting=SetEmuSetting;
|
|
gpi.GetAboutText=GetAboutText;
|
|
|
|
|
|
gpi.GetPluginList=b_GetPluginList;
|
|
gpi.GetMapleDeviceList=b_GetMapleDeviceList;
|
|
gpi.FreePluginList=b_FreePluginList;
|
|
|
|
gpi.GetPerformanceInfo=b_GetPerformanceInfo;
|
|
|
|
gpi.BroardcastEvent=BroadcastEvent;
|
|
gpi.EmuThread=NULL;
|
|
gpi.nCmdShow = nCmdShow;
|
|
|
|
if (rv_ok != libgui.Load(&gpi))
|
|
return false;
|
|
|
|
libgui.GetMenuIDs(&MenuIDs);
|
|
|
|
return true;
|
|
}
|
|
bool CreateGUI()
|
|
{
|
|
char gui[128];
|
|
cfgLoadStr(("nullDC_plugins"),("GUI"),gui,("nullDC_GUI_Win32.dll"));
|
|
if (!OpenAndLoadGUI(gui))
|
|
{
|
|
if (msgboxf(("Do you want to load default gui ?"),MBX_YESNO) == MBX_RV_YES)
|
|
{
|
|
if (!OpenAndLoadGUI(("nullDC_GUI_Win32.dll")))
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
return true;
|
|
}
|
|
void DestroyGUI()
|
|
{
|
|
plugins_Unload();
|
|
|
|
libgui.Unload();
|
|
gui.Unload();
|
|
}
|
|
void GuiLoop()
|
|
{
|
|
TR
|
|
libgui.Mainloop();
|
|
|
|
//Make sure emulation is stoped
|
|
Stop_DC();
|
|
}
|
|
|
|
void* EXPORT_CALL GetRenderTargetHandle()
|
|
{
|
|
return libgui.GetRenderTarget();
|
|
}
|
|
bool SelectPluginsGui()
|
|
{
|
|
return libgui.SelectPluginsGui();
|
|
}
|
|
|
|
|
|
u32 PowerVR_menu;
|
|
u32 GDRom_menu;
|
|
u32 Aica_menu;
|
|
u32 Maple_menu;
|
|
u32 Maple_menu_ports[4][6];
|
|
u32 ExtDev_menu;
|
|
u32 Debug_menu;
|
|
|
|
|
|
void SetMenuItemHandler(u32 id,MenuItemSelectedFP* h)
|
|
{
|
|
MenuItem mi;
|
|
mi.Handler=h;
|
|
|
|
libgui.SetMenuItem(id,&mi,MIM_Handler);
|
|
}
|
|
|
|
enum ProfilerInfoFlags
|
|
{
|
|
PIF_TBP_ON=1, //Time based profiler is enabled (so the info returned here is valid)
|
|
PIF_TBP_ONEX=2, //Extra profile info is valid (block usage)
|
|
|
|
PIF_BMS_DTCS=4 , //Dynarec Translation Cache stats (size;block counts)
|
|
PIF_BMS_LCS=8 , //lookup cache stats (miss/hit)
|
|
PIF_BMS_CSGS=16 , //call stack guess stats (miss/hit)
|
|
|
|
};
|
|
struct profiler_info
|
|
{
|
|
u32 flags;
|
|
}; |