2012-11-15 00:39:56 +01:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "System.h"
|
|
|
|
|
#include "Emu/Memory/Memory.h"
|
|
|
|
|
#include "Ini.h"
|
|
|
|
|
|
|
|
|
|
#include "Emu/Cell/PPUThread.h"
|
|
|
|
|
#include "Emu/Cell/SPUThread.h"
|
2013-07-03 18:17:16 +02:00
|
|
|
#include "Emu/Cell/PPUInstrTable.h"
|
2013-12-08 17:54:45 +01:00
|
|
|
|
2014-03-03 05:48:07 +01:00
|
|
|
#include "../Crypto/unself.h"
|
2013-11-27 20:16:19 +01:00
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <fstream>
|
2013-07-03 18:17:16 +02:00
|
|
|
using namespace PPU_instr;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-11-27 20:16:19 +01:00
|
|
|
static const std::string& BreakPointsDBName = "BreakPoints.dat";
|
2013-07-03 18:17:16 +02:00
|
|
|
static const u16 bpdb_version = 0x1000;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-07-06 01:49:38 +02:00
|
|
|
ModuleInitializer::ModuleInitializer()
|
|
|
|
|
{
|
|
|
|
|
Emu.AddModuleInit(this);
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
|
|
|
Emulator::Emulator()
|
|
|
|
|
: m_status(Stopped)
|
|
|
|
|
, m_mode(DisAsm)
|
2013-12-08 17:54:45 +01:00
|
|
|
, m_dbg_console(nullptr)
|
2012-11-15 00:39:56 +01:00
|
|
|
, m_rsx_callback(0)
|
2014-01-31 19:40:18 +01:00
|
|
|
, m_ppu_callback_thr(0)
|
2014-02-24 00:40:03 +01:00
|
|
|
, m_event_manager(new EventManager())
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Emulator::Init()
|
|
|
|
|
{
|
2013-07-06 01:49:38 +02:00
|
|
|
while(m_modules_init.GetCount())
|
|
|
|
|
{
|
|
|
|
|
m_modules_init[0].Init();
|
|
|
|
|
m_modules_init.RemoveAt(0);
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
//if(m_memory_viewer) m_memory_viewer->Close();
|
|
|
|
|
//m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
void Emulator::SetPath(const wxString& path, const wxString& elf_path)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
|
|
|
|
m_path = path;
|
2013-09-24 23:11:29 +02:00
|
|
|
m_elf_path = elf_path;
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2013-12-07 21:56:42 +01:00
|
|
|
void Emulator::SetTitleID(const wxString& id)
|
|
|
|
|
{
|
|
|
|
|
m_title_id = id;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-15 00:39:56 +01:00
|
|
|
void Emulator::CheckStatus()
|
|
|
|
|
{
|
2013-11-03 20:23:16 +01:00
|
|
|
ArrayF<CPUThread>& threads = GetCPU().GetThreads();
|
2012-11-15 00:39:56 +01:00
|
|
|
if(!threads.GetCount())
|
|
|
|
|
{
|
|
|
|
|
Stop();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsAllPaused = true;
|
|
|
|
|
for(u32 i=0; i<threads.GetCount(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if(threads[i].IsPaused()) continue;
|
|
|
|
|
IsAllPaused = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(IsAllPaused)
|
|
|
|
|
{
|
2013-06-30 10:46:29 +02:00
|
|
|
//ConLog.Warning("all paused!");
|
2012-11-15 00:39:56 +01:00
|
|
|
Pause();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool IsAllStoped = true;
|
|
|
|
|
for(u32 i=0; i<threads.GetCount(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if(threads[i].IsStopped()) continue;
|
|
|
|
|
IsAllStoped = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if(IsAllStoped)
|
|
|
|
|
{
|
2013-06-30 10:46:29 +02:00
|
|
|
//ConLog.Warning("all stoped!");
|
2012-11-15 00:39:56 +01:00
|
|
|
Pause(); //Stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-08 17:54:45 +01:00
|
|
|
bool Emulator::BootGame(const std::string& path)
|
|
|
|
|
{
|
|
|
|
|
static const char* elf_path[6] =
|
|
|
|
|
{
|
|
|
|
|
"\\PS3_GAME\\USRDIR\\BOOT.BIN",
|
|
|
|
|
"\\USRDIR\\BOOT.BIN",
|
|
|
|
|
"\\BOOT.BIN",
|
|
|
|
|
"\\PS3_GAME\\USRDIR\\EBOOT.BIN",
|
|
|
|
|
"\\USRDIR\\EBOOT.BIN",
|
|
|
|
|
"\\EBOOT.BIN",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for(int i=0; i<sizeof(elf_path) / sizeof(*elf_path);i++)
|
|
|
|
|
{
|
|
|
|
|
const wxString& curpath = path + elf_path[i];
|
|
|
|
|
|
|
|
|
|
if(wxFile::Access(curpath, wxFile::read))
|
|
|
|
|
{
|
|
|
|
|
SetPath(curpath);
|
|
|
|
|
Load();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
void Emulator::Load()
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2013-06-30 10:46:29 +02:00
|
|
|
if(!wxFileExists(m_path)) return;
|
2013-12-08 17:54:45 +01:00
|
|
|
|
2014-02-10 13:53:09 +01:00
|
|
|
if(IsSelf(m_path.ToStdString()))
|
2013-12-08 17:54:45 +01:00
|
|
|
{
|
2014-02-23 17:52:52 +01:00
|
|
|
std::string self_path = m_path.ToStdString();
|
|
|
|
|
std::string elf_path = wxFileName(m_path).GetPath().ToStdString();
|
2013-12-08 17:54:45 +01:00
|
|
|
|
|
|
|
|
if(wxFileName(m_path).GetFullName().CmpNoCase("EBOOT.BIN") == 0)
|
|
|
|
|
{
|
|
|
|
|
elf_path += "\\BOOT.BIN";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
elf_path += "\\" + wxFileName(m_path).GetName() + ".elf";
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-24 04:58:32 +01:00
|
|
|
if(!DecryptSelf(elf_path, self_path))
|
|
|
|
|
return;
|
2013-12-08 17:54:45 +01:00
|
|
|
|
|
|
|
|
m_path = elf_path;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-10 13:53:09 +01:00
|
|
|
ConLog.Write("Loading '%s'...", m_path.wx_str());
|
2012-11-15 00:39:56 +01:00
|
|
|
GetInfo().Reset();
|
2013-09-24 23:11:29 +02:00
|
|
|
m_vfs.Init(m_path);
|
|
|
|
|
|
|
|
|
|
ConLog.SkipLn();
|
|
|
|
|
ConLog.Write("Mount info:");
|
|
|
|
|
for(uint i=0; i<m_vfs.m_devices.GetCount(); ++i)
|
|
|
|
|
{
|
2014-02-24 17:03:47 +01:00
|
|
|
ConLog.Write("%s -> %s", m_vfs.m_devices[i].GetPs3Path().wx_str(), m_vfs.m_devices[i].GetLocalPath().wx_str());
|
2013-09-24 23:11:29 +02:00
|
|
|
}
|
|
|
|
|
ConLog.SkipLn();
|
|
|
|
|
|
2013-10-06 14:07:42 +02:00
|
|
|
if(m_elf_path.IsEmpty())
|
|
|
|
|
{
|
|
|
|
|
GetVFS().GetDeviceLocal(m_path, m_elf_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vfsFile f(m_elf_path);
|
2013-09-24 23:11:29 +02:00
|
|
|
|
2013-10-06 14:07:42 +02:00
|
|
|
if(!f.IsOpened())
|
2013-09-24 23:11:29 +02:00
|
|
|
{
|
2014-02-10 13:53:09 +01:00
|
|
|
ConLog.Error("Elf not found! (%s - %s)", m_path.wx_str(), m_elf_path.wx_str());
|
2013-09-24 23:11:29 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
bool is_error;
|
2013-10-06 14:07:42 +02:00
|
|
|
Loader l(f);
|
2013-06-30 10:46:29 +02:00
|
|
|
|
|
|
|
|
try
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
2014-02-16 16:19:06 +01:00
|
|
|
if(!(is_error = !l.Analyze()) && l.GetMachine() != MACHINE_Unknown)
|
2013-11-03 20:23:16 +01:00
|
|
|
{
|
|
|
|
|
switch(l.GetMachine())
|
|
|
|
|
{
|
|
|
|
|
case MACHINE_SPU:
|
|
|
|
|
case MACHINE_PPC64:
|
|
|
|
|
Memory.Init(Memory_PS3);
|
|
|
|
|
break;
|
2013-11-05 19:12:18 +01:00
|
|
|
|
|
|
|
|
case MACHINE_MIPS:
|
|
|
|
|
Memory.Init(Memory_PSP);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MACHINE_ARM:
|
|
|
|
|
Memory.Init(Memory_PSV);
|
|
|
|
|
break;
|
2013-11-03 20:23:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
is_error = !l.Load();
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
catch(const wxString& e)
|
|
|
|
|
{
|
|
|
|
|
ConLog.Error(e);
|
|
|
|
|
is_error = true;
|
|
|
|
|
}
|
|
|
|
|
catch(...)
|
|
|
|
|
{
|
|
|
|
|
ConLog.Error("Unhandled loader error.");
|
|
|
|
|
is_error = true;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-03 20:23:16 +01:00
|
|
|
CPUThreadType thread_type;
|
|
|
|
|
|
|
|
|
|
if(!is_error)
|
|
|
|
|
{
|
|
|
|
|
switch(l.GetMachine())
|
|
|
|
|
{
|
|
|
|
|
case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break;
|
|
|
|
|
case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break;
|
2013-11-05 20:22:58 +01:00
|
|
|
case MACHINE_ARM: thread_type = CPU_THREAD_ARMv7; break;
|
2013-11-03 20:23:16 +01:00
|
|
|
|
|
|
|
|
default:
|
2013-11-05 20:22:58 +01:00
|
|
|
ConLog.Error("Unimplemented thread type for machine.");
|
2013-11-03 20:23:16 +01:00
|
|
|
is_error = true;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
if(is_error)
|
2012-11-15 00:39:56 +01:00
|
|
|
{
|
|
|
|
|
Memory.Close();
|
|
|
|
|
Stop();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-03 18:17:16 +02:00
|
|
|
LoadPoints(BreakPointsDBName);
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-11-03 20:23:16 +01:00
|
|
|
CPUThread& thread = GetCPU().AddThread(thread_type);
|
|
|
|
|
|
|
|
|
|
switch(l.GetMachine())
|
2013-07-06 01:49:38 +02:00
|
|
|
{
|
2013-11-03 20:23:16 +01:00
|
|
|
case MACHINE_SPU:
|
2013-07-06 01:49:38 +02:00
|
|
|
ConLog.Write("offset = 0x%llx", Memory.MainMem.GetStartAddr());
|
|
|
|
|
ConLog.Write("max addr = 0x%x", l.GetMaxAddr());
|
|
|
|
|
thread.SetOffset(Memory.MainMem.GetStartAddr());
|
2014-02-02 20:49:10 +01:00
|
|
|
Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr() + l.GetMaxAddr(), 0xFFFFED - l.GetMaxAddr());
|
2013-07-06 01:49:38 +02:00
|
|
|
thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr());
|
2013-11-03 20:23:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case MACHINE_PPC64:
|
2013-07-06 01:49:38 +02:00
|
|
|
{
|
2014-01-31 19:40:18 +01:00
|
|
|
m_ppu_callback_thr = &GetCPU().AddThread(CPU_THREAD_PPU);
|
|
|
|
|
|
2013-07-06 01:49:38 +02:00
|
|
|
thread.SetEntry(l.GetEntry());
|
2014-02-02 20:49:10 +01:00
|
|
|
Memory.StackMem.AllocAlign(0x1000);
|
2013-07-08 15:24:46 +02:00
|
|
|
thread.InitStack();
|
2013-12-24 04:58:32 +01:00
|
|
|
thread.AddArgv(m_elf_path);
|
2013-07-08 15:24:46 +02:00
|
|
|
//thread.AddArgv("-emu");
|
|
|
|
|
|
2014-02-02 20:49:10 +01:00
|
|
|
m_rsx_callback = Memory.MainMem.AllocAlign(4 * 4) + 4;
|
2013-07-08 15:24:46 +02:00
|
|
|
Memory.Write32(m_rsx_callback - 4, m_rsx_callback);
|
|
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
mem32_ptr_t callback_data(m_rsx_callback);
|
2013-07-08 15:24:46 +02:00
|
|
|
callback_data += ADDI(11, 0, 0x3ff);
|
|
|
|
|
callback_data += SC(2);
|
|
|
|
|
callback_data += BCLR(0x10 | 0x04, 0, 0, 0);
|
|
|
|
|
|
2014-02-02 20:49:10 +01:00
|
|
|
m_ppu_thr_exit = Memory.MainMem.AllocAlign(4 * 4);
|
2013-07-08 15:24:46 +02:00
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
mem32_ptr_t ppu_thr_exit_data(m_ppu_thr_exit);
|
2013-08-19 01:06:11 +02:00
|
|
|
ppu_thr_exit_data += ADDI(3, 0, 0);
|
2013-07-08 15:24:46 +02:00
|
|
|
ppu_thr_exit_data += ADDI(11, 0, 41);
|
|
|
|
|
ppu_thr_exit_data += SC(2);
|
|
|
|
|
ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0);
|
2014-03-04 20:18:17 +01:00
|
|
|
|
|
|
|
|
Memory.Write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE);
|
2013-07-06 01:49:38 +02:00
|
|
|
}
|
2013-11-03 20:23:16 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
thread.SetEntry(l.GetEntry());
|
|
|
|
|
break;
|
|
|
|
|
}
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
if(!m_dbg_console)
|
|
|
|
|
{
|
|
|
|
|
m_dbg_console = new DbgConsole();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
GetDbgCon().Close();
|
|
|
|
|
GetDbgCon().Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GetGSManager().Init();
|
|
|
|
|
GetCallbackManager().Init();
|
2013-12-27 11:55:11 +01:00
|
|
|
GetAudioManager().Init();
|
2014-02-13 12:13:05 +01:00
|
|
|
GetEventManager().Init();
|
2013-09-24 23:11:29 +02:00
|
|
|
|
2012-11-15 00:39:56 +01:00
|
|
|
thread.Run();
|
|
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
m_status = Ready;
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_READY_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2013-06-30 10:46:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Emulator::Run()
|
|
|
|
|
{
|
|
|
|
|
if(!IsReady())
|
|
|
|
|
{
|
|
|
|
|
Load();
|
|
|
|
|
if(!IsReady()) return;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-12 11:56:56 +02:00
|
|
|
if(IsRunning()) Stop();
|
2013-06-30 10:46:29 +02:00
|
|
|
if(IsPaused())
|
|
|
|
|
{
|
|
|
|
|
Resume();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_START_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2013-07-03 18:17:16 +02:00
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
//ConLog.Write("run...");
|
2013-08-12 11:56:56 +02:00
|
|
|
m_status = Running;
|
2013-06-30 10:46:29 +02:00
|
|
|
|
2012-11-15 00:39:56 +01:00
|
|
|
//if(m_memory_viewer && m_memory_viewer->exit) safe_delete(m_memory_viewer);
|
|
|
|
|
|
|
|
|
|
//m_memory_viewer->SetPC(loader.GetEntry());
|
|
|
|
|
//m_memory_viewer->Show();
|
|
|
|
|
//m_memory_viewer->ShowPC();
|
|
|
|
|
|
2013-06-30 10:46:29 +02:00
|
|
|
GetCPU().Exec();
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_STARTED_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Emulator::Pause()
|
|
|
|
|
{
|
2013-08-12 11:56:56 +02:00
|
|
|
if(!IsRunning()) return;
|
2012-11-15 00:39:56 +01:00
|
|
|
//ConLog.Write("pause...");
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_PAUSE_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
|
|
|
m_status = Paused;
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_PAUSED_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Emulator::Resume()
|
|
|
|
|
{
|
|
|
|
|
if(!IsPaused()) return;
|
|
|
|
|
//ConLog.Write("resume...");
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_RESUME_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-08-12 11:56:56 +02:00
|
|
|
m_status = Running;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
|
|
|
CheckStatus();
|
2013-08-12 11:56:56 +02:00
|
|
|
if(IsRunning() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec();
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_RESUMED_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Emulator::Stop()
|
|
|
|
|
{
|
|
|
|
|
if(IsStopped()) return;
|
|
|
|
|
//ConLog.Write("shutdown...");
|
2013-07-03 18:17:16 +02:00
|
|
|
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-07-03 18:17:16 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_STOP_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2013-12-27 12:35:08 +01:00
|
|
|
m_status = Stopped;
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
|
|
|
m_rsx_callback = 0;
|
2013-07-03 18:17:16 +02:00
|
|
|
|
|
|
|
|
SavePoints(BreakPointsDBName);
|
|
|
|
|
m_break_points.Clear();
|
|
|
|
|
m_marked_points.Clear();
|
2012-11-15 00:39:56 +01:00
|
|
|
|
2013-08-03 11:40:03 +02:00
|
|
|
m_vfs.UnMountAll();
|
|
|
|
|
|
2012-11-15 00:39:56 +01:00
|
|
|
GetGSManager().Close();
|
2013-12-27 11:55:11 +01:00
|
|
|
GetAudioManager().Close();
|
2014-02-13 12:13:05 +01:00
|
|
|
GetEventManager().Clear();
|
2012-11-15 00:39:56 +01:00
|
|
|
GetCPU().Close();
|
2013-06-30 10:46:29 +02:00
|
|
|
//SysCallsManager.Close();
|
2012-11-15 00:39:56 +01:00
|
|
|
GetIdManager().Clear();
|
|
|
|
|
GetPadManager().Close();
|
2013-09-11 22:49:49 +02:00
|
|
|
GetKeyboardManager().Close();
|
2013-09-14 20:20:57 +02:00
|
|
|
GetMouseManager().Close();
|
2013-06-30 10:46:29 +02:00
|
|
|
GetCallbackManager().Clear();
|
|
|
|
|
UnloadModules();
|
2012-11-15 00:39:56 +01:00
|
|
|
|
|
|
|
|
CurGameInfo.Reset();
|
|
|
|
|
Memory.Close();
|
|
|
|
|
|
|
|
|
|
//if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide();
|
2013-11-27 20:16:19 +01:00
|
|
|
#ifndef QT_UI
|
2013-09-05 10:06:59 +02:00
|
|
|
wxGetApp().SendDbgCommand(DID_STOPPED_EMU);
|
2013-11-27 20:16:19 +01:00
|
|
|
#endif
|
2013-07-03 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
2013-11-27 20:16:19 +01:00
|
|
|
void Emulator::SavePoints(const std::string& path)
|
2013-07-03 18:17:16 +02:00
|
|
|
{
|
2013-11-27 20:16:19 +01:00
|
|
|
std::ofstream f(path, std::ios::binary | std::ios::trunc);
|
2013-07-03 18:17:16 +02:00
|
|
|
|
|
|
|
|
u32 break_count = m_break_points.GetCount();
|
|
|
|
|
u32 marked_count = m_marked_points.GetCount();
|
|
|
|
|
|
2013-11-27 20:16:19 +01:00
|
|
|
f << bpdb_version << break_count << marked_count;
|
|
|
|
|
|
2013-07-03 18:17:16 +02:00
|
|
|
if(break_count)
|
|
|
|
|
{
|
2013-11-27 20:16:19 +01:00
|
|
|
f.write(reinterpret_cast<char*>(&m_break_points[0]), sizeof(u64) * break_count);
|
2013-07-03 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(marked_count)
|
|
|
|
|
{
|
2013-11-27 20:16:19 +01:00
|
|
|
f.write(reinterpret_cast<char*>(&m_marked_points[0]), sizeof(u64) * marked_count);
|
2013-07-03 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-27 20:16:19 +01:00
|
|
|
void Emulator::LoadPoints(const std::string& path)
|
2013-07-03 18:17:16 +02:00
|
|
|
{
|
2013-11-27 20:16:19 +01:00
|
|
|
struct stat buf;
|
|
|
|
|
if (!stat(path.c_str(), &buf))
|
|
|
|
|
return;
|
|
|
|
|
std::ifstream f(path, std::ios::binary);
|
|
|
|
|
if (!f.is_open())
|
|
|
|
|
return;
|
|
|
|
|
f.seekg(0, std::ios::end);
|
2013-12-08 17:54:45 +01:00
|
|
|
int length = f.tellg();
|
2013-11-27 20:16:19 +01:00
|
|
|
f.seekg(0, std::ios::beg);
|
2013-07-03 18:17:16 +02:00
|
|
|
u32 break_count, marked_count;
|
|
|
|
|
u16 version;
|
2013-11-27 20:16:19 +01:00
|
|
|
f >> version >> break_count >> marked_count;
|
2013-07-03 18:17:16 +02:00
|
|
|
|
|
|
|
|
if(version != bpdb_version ||
|
2013-11-27 20:16:19 +01:00
|
|
|
(sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != length)
|
2013-07-03 18:17:16 +02:00
|
|
|
{
|
2014-02-10 19:51:03 +01:00
|
|
|
ConLog.Error("'%s' is broken", wxString(path).wx_str());
|
2013-07-03 18:17:16 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(break_count > 0)
|
|
|
|
|
{
|
|
|
|
|
m_break_points.SetCount(break_count);
|
2013-11-27 20:16:19 +01:00
|
|
|
f.read(reinterpret_cast<char*>(&m_break_points[0]), sizeof(u64) * break_count);
|
2013-07-03 18:17:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(marked_count > 0)
|
|
|
|
|
{
|
|
|
|
|
m_marked_points.SetCount(marked_count);
|
2013-11-27 20:16:19 +01:00
|
|
|
f.read(reinterpret_cast<char*>(&m_marked_points[0]), sizeof(u64) * marked_count);
|
2013-07-03 18:17:16 +02:00
|
|
|
}
|
2012-11-15 00:39:56 +01:00
|
|
|
}
|
|
|
|
|
|
2013-09-24 23:11:29 +02:00
|
|
|
Emulator Emu;
|