nulldc-360/nullDC/gui/base.cpp
2022-02-11 13:27:24 +01:00

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;
};