mirror of
https://github.com/libretro/Play-.git
synced 2025-02-04 07:56:10 +00:00
git-svn-id: http://svn.purei.org/purei/trunk@177 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
25ca7a6144
commit
3eefc47451
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
<?xml version="1.0" encoding="Windows-1252"?>
|
||||||
<VisualStudioProject
|
<VisualStudioProject
|
||||||
ProjectType="Visual C++"
|
ProjectType="Visual C++"
|
||||||
Version="8.00"
|
Version="8,00"
|
||||||
Name="PsfPlayer"
|
Name="PsfPlayer"
|
||||||
ProjectGUID="{EDA20432-A4C3-481C-B0EA-24AA8ABD7621}"
|
ProjectGUID="{EDA20432-A4C3-481C-B0EA-24AA8ABD7621}"
|
||||||
RootNamespace="PsfPlayer"
|
RootNamespace="PsfPlayer"
|
||||||
@ -117,7 +117,8 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
AdditionalIncludeDirectories=""$(FrameworkRoot)/include";"$(SolutionDir)/source""
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MSVC;_CRT_SECURE_NO_WARNINGS"
|
||||||
RuntimeLibrary="2"
|
RuntimeLibrary="2"
|
||||||
UsePrecompiledHeader="0"
|
UsePrecompiledHeader="0"
|
||||||
WarningLevel="3"
|
WarningLevel="3"
|
||||||
@ -135,6 +136,7 @@
|
|||||||
/>
|
/>
|
||||||
<Tool
|
<Tool
|
||||||
Name="VCLinkerTool"
|
Name="VCLinkerTool"
|
||||||
|
AdditionalDependencies="comctl32.lib"
|
||||||
LinkIncremental="1"
|
LinkIncremental="1"
|
||||||
GenerateDebugInformation="true"
|
GenerateDebugInformation="true"
|
||||||
SubSystem="2"
|
SubSystem="2"
|
||||||
@ -176,6 +178,10 @@
|
|||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\ArgumentIterator.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\Source\win32ui\DisAsm.cpp"
|
RelativePath="..\..\Source\win32ui\DisAsm.cpp"
|
||||||
>
|
>
|
||||||
@ -192,6 +198,14 @@
|
|||||||
RelativePath=".\Source\Iop_Dynamic.cpp"
|
RelativePath=".\Source\Iop_Dynamic.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Intc.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Intrman.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\Iop_Ioman.cpp"
|
RelativePath=".\Source\Iop_Ioman.cpp"
|
||||||
>
|
>
|
||||||
@ -220,10 +234,34 @@
|
|||||||
RelativePath=".\Source\Iop_Thbase.cpp"
|
RelativePath=".\Source\Iop_Thbase.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Thevent.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Thsema.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Timrman.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\IopBios.cpp"
|
RelativePath=".\Source\IopBios.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Log.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\Source\win32ui\MemoryView.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\Source\win32ui\MemoryViewMIPS.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\win32\MiniDebugger.cpp"
|
RelativePath=".\Source\win32\MiniDebugger.cpp"
|
||||||
>
|
>
|
||||||
@ -248,6 +286,14 @@
|
|||||||
RelativePath="..\..\Source\win32ui\RegViewPage.cpp"
|
RelativePath="..\..\Source\win32ui\RegViewPage.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Spu2.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Spu2_Core.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\win32\WinMain.cpp"
|
RelativePath=".\Source\win32\WinMain.cpp"
|
||||||
>
|
>
|
||||||
@ -262,6 +308,10 @@
|
|||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\ArgumentIterator.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\Source\win32ui\DisAsm.h"
|
RelativePath="..\..\Source\win32ui\DisAsm.h"
|
||||||
>
|
>
|
||||||
@ -282,6 +332,14 @@
|
|||||||
RelativePath=".\Source\Iop_Dynamic.h"
|
RelativePath=".\Source\Iop_Dynamic.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Intc.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Intrman.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\Iop_Ioman.h"
|
RelativePath=".\Source\Iop_Ioman.h"
|
||||||
>
|
>
|
||||||
@ -314,10 +372,34 @@
|
|||||||
RelativePath=".\Source\Iop_Thbase.h"
|
RelativePath=".\Source\Iop_Thbase.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Thevent.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Thsema.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Iop_Timrman.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\IopBios.h"
|
RelativePath=".\Source\IopBios.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Log.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\Source\win32ui\MemoryView.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\Source\win32ui\MemoryViewMIPS.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\Source\win32\MiniDebugger.h"
|
RelativePath=".\Source\win32\MiniDebugger.h"
|
||||||
>
|
>
|
||||||
@ -342,6 +424,14 @@
|
|||||||
RelativePath="..\..\Source\win32ui\RegViewPage.h"
|
RelativePath="..\..\Source\win32ui\RegViewPage.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Spu2.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\Source\Spu2_Core.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\Source\win32ui\WinUtils.h"
|
RelativePath="..\..\Source\win32ui\WinUtils.h"
|
||||||
>
|
>
|
||||||
|
26
tools/PsfPlayer/Source/ArgumentIterator.cpp
Normal file
26
tools/PsfPlayer/Source/ArgumentIterator.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include "ArgumentIterator.h"
|
||||||
|
|
||||||
|
CArgumentIterator::CArgumentIterator(CMIPS& context) :
|
||||||
|
m_context(context),
|
||||||
|
m_current(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CArgumentIterator::~CArgumentIterator()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CArgumentIterator::GetNext()
|
||||||
|
{
|
||||||
|
if(m_current > 3)
|
||||||
|
{
|
||||||
|
uint32 address = m_context.m_State.nGPR[CMIPS::SP].nV0 + (m_current++ - 4) * 4 + 0x10;
|
||||||
|
return m_context.m_pMemoryMap->GetWord(address);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return m_context.m_State.nGPR[CMIPS::A0 + m_current++].nV[0];
|
||||||
|
}
|
||||||
|
}
|
18
tools/PsfPlayer/Source/ArgumentIterator.h
Normal file
18
tools/PsfPlayer/Source/ArgumentIterator.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _ARGUMENT_ITERATOR_H_
|
||||||
|
#define _ARGUMENT_ITERATOR_H_
|
||||||
|
|
||||||
|
#include "MIPS.h"
|
||||||
|
|
||||||
|
class CArgumentIterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CArgumentIterator(CMIPS&);
|
||||||
|
virtual ~CArgumentIterator();
|
||||||
|
uint32 GetNext();
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_current;
|
||||||
|
CMIPS& m_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -2,7 +2,15 @@
|
|||||||
#include "COP_SCU.h"
|
#include "COP_SCU.h"
|
||||||
#include "Iop_Sysclib.h"
|
#include "Iop_Sysclib.h"
|
||||||
#include "Iop_Loadcore.h"
|
#include "Iop_Loadcore.h"
|
||||||
|
#include "Iop_Thbase.h"
|
||||||
|
#include "Iop_Thsema.h"
|
||||||
|
#include "Iop_Thevent.h"
|
||||||
|
#include "Iop_Timrman.h"
|
||||||
|
#include "Log.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define LOGNAME "iop_bios"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Framework;
|
using namespace Framework;
|
||||||
@ -12,10 +20,12 @@ m_baseAddress(baseAddress),
|
|||||||
m_cpu(cpu),
|
m_cpu(cpu),
|
||||||
m_ram(ram),
|
m_ram(ram),
|
||||||
m_nextThreadId(1),
|
m_nextThreadId(1),
|
||||||
|
m_nextSemaphoreId(1),
|
||||||
m_stdio(NULL),
|
m_stdio(NULL),
|
||||||
m_sysmem(NULL),
|
m_sysmem(NULL),
|
||||||
m_ioman(NULL),
|
m_ioman(NULL),
|
||||||
m_modload(NULL),
|
m_modload(NULL),
|
||||||
|
m_rescheduleNeeded(false),
|
||||||
m_currentThreadId(-1)
|
m_currentThreadId(-1)
|
||||||
{
|
{
|
||||||
CMIPSAssembler assembler(reinterpret_cast<uint32*>(&m_ram[m_baseAddress]));
|
CMIPSAssembler assembler(reinterpret_cast<uint32*>(&m_ram[m_baseAddress]));
|
||||||
@ -31,7 +41,7 @@ m_currentThreadId(-1)
|
|||||||
RegisterModule(m_ioman);
|
RegisterModule(m_ioman);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
m_sysmem = new Iop::CSysmem(0x1000, ramSize);
|
m_sysmem = new Iop::CSysmem(0x1000, ramSize, *m_stdio);
|
||||||
RegisterModule(m_sysmem);
|
RegisterModule(m_sysmem);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -39,15 +49,31 @@ m_currentThreadId(-1)
|
|||||||
RegisterModule(m_modload);
|
RegisterModule(m_modload);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
RegisterModule(new Iop::CSysclib(m_ram));
|
RegisterModule(new Iop::CSysclib(m_ram, *m_stdio));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
RegisterModule(new Iop::CLoadcore(*this, m_ram));
|
RegisterModule(new Iop::CLoadcore(*this, m_ram));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
RegisterModule(new Iop::CThbase(*this, m_ram));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RegisterModule(new Iop::CThsema(*this, m_ram));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RegisterModule(new Iop::CThevent(*this, m_ram));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RegisterModule(new Iop::CTimrman());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CIopBios::~CIopBios()
|
CIopBios::~CIopBios()
|
||||||
{
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
SaveAllModulesTags(m_cpu.m_Comments, "comments");
|
||||||
|
SaveAllModulesTags(m_cpu.m_Functions, "functions");
|
||||||
|
#endif
|
||||||
while(m_modules.size() != 0)
|
while(m_modules.size() != 0)
|
||||||
{
|
{
|
||||||
delete m_modules.begin()->second;
|
delete m_modules.begin()->second;
|
||||||
@ -57,8 +83,16 @@ CIopBios::~CIopBios()
|
|||||||
|
|
||||||
void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned int argsLength)
|
void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned int argsLength)
|
||||||
{
|
{
|
||||||
uint32 entryPoint = LoadExecutable(path);
|
ExecutableRange moduleRange;
|
||||||
uint32 threadId = CreateThread(entryPoint);
|
uint32 entryPoint = LoadExecutable(path, moduleRange);
|
||||||
|
|
||||||
|
LOADEDMODULE loadedModule;
|
||||||
|
loadedModule.name = GetModuleNameFromPath(path);
|
||||||
|
loadedModule.begin = moduleRange.first;
|
||||||
|
loadedModule.end = moduleRange.second;
|
||||||
|
m_loadedModules.push_back(loadedModule);
|
||||||
|
|
||||||
|
uint32 threadId = CreateThread(entryPoint, DEFAULT_PRIORITY);
|
||||||
THREAD& thread = GetThread(threadId);
|
THREAD& thread = GetThread(threadId);
|
||||||
|
|
||||||
typedef vector<uint32> ParamListType;
|
typedef vector<uint32> ParamListType;
|
||||||
@ -75,7 +109,7 @@ void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned i
|
|||||||
reinterpret_cast<const uint8*>(args),
|
reinterpret_cast<const uint8*>(args),
|
||||||
static_cast<uint32>(strlen(args)) + 1));
|
static_cast<uint32>(strlen(args)) + 1));
|
||||||
}
|
}
|
||||||
thread.context.gpr[CMIPS::A0] = paramList.size();
|
thread.context.gpr[CMIPS::A0] = static_cast<uint32>(paramList.size());
|
||||||
for(ParamListType::reverse_iterator param(paramList.rbegin());
|
for(ParamListType::reverse_iterator param(paramList.rbegin());
|
||||||
paramList.rend() != param; param++)
|
paramList.rend() != param; param++)
|
||||||
{
|
{
|
||||||
@ -85,7 +119,53 @@ void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned i
|
|||||||
4);
|
4);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reschedule();
|
StartThread(threadId);
|
||||||
|
if(m_currentThreadId == -1)
|
||||||
|
{
|
||||||
|
Reschedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
LoadModuleTags(loadedModule, m_cpu.m_Comments, "comments");
|
||||||
|
LoadModuleTags(loadedModule, m_cpu.m_Functions, "functions");
|
||||||
|
m_cpu.m_pAnalysis->Analyse(moduleRange.first, moduleRange.second);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for(int i = 0; i < 0x00400000 / 4; i++)
|
||||||
|
{
|
||||||
|
uint32 nVal = ((uint32*)m_ram)[i];
|
||||||
|
// if(nVal == 0x34C00)
|
||||||
|
// {
|
||||||
|
// printf("Allo: 0x%0.8X\r\n", i * 4);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if((nVal & 0xFFFF) == 0xC958)
|
||||||
|
{
|
||||||
|
char mnemonic[256];
|
||||||
|
m_cpu.m_pArch->GetInstructionMnemonic(&m_cpu, i * 4, nVal, mnemonic, 256);
|
||||||
|
printf("Allo: %s, 0x%0.8X\r\n", mnemonic, i * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(nVal == 0x2F9B50)
|
||||||
|
{
|
||||||
|
printf("Allo: 0x%0.8X\r\n", i * 4);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
if((nVal & 0xFC000000) == 0x0C000000)
|
||||||
|
{
|
||||||
|
nVal &= 0x3FFFFFF;
|
||||||
|
nVal *= 4;
|
||||||
|
if(nVal == 0x034C00)
|
||||||
|
{
|
||||||
|
printf("Allo: 0x%0.8X\r\n", i * 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
*reinterpret_cast<uint32*>(&m_ram[0x41674]) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CIopBios::THREAD& CIopBios::GetThread(uint32 threadId)
|
CIopBios::THREAD& CIopBios::GetThread(uint32 threadId)
|
||||||
@ -106,27 +186,90 @@ CIopBios::ThreadMapType::iterator CIopBios::GetThreadPosition(uint32 threadId)
|
|||||||
throw runtime_error("Unexisting thread id.");
|
throw runtime_error("Unexisting thread id.");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CIopBios::CreateThread(uint32 threadProc)
|
uint32 CIopBios::CreateThread(uint32 threadProc, uint32 priority)
|
||||||
{
|
{
|
||||||
THREAD thread;
|
THREAD thread;
|
||||||
memset(&thread, 0, sizeof(thread));
|
memset(&thread, 0, sizeof(thread));
|
||||||
thread.context.delayJump = 1;
|
thread.context.delayJump = 1;
|
||||||
uint32 stackBaseAddress = m_sysmem->AllocateMemory(DEFAULT_STACKSIZE, 0);
|
uint32 stackBaseAddress = m_sysmem->AllocateMemory(DEFAULT_STACKSIZE, 0);
|
||||||
thread.id = m_nextThreadId++;
|
thread.id = m_nextThreadId++;
|
||||||
thread.priority = 7;
|
thread.priority = priority;
|
||||||
|
thread.status = THREAD_STATUS_CREATED;
|
||||||
thread.context.epc = threadProc;
|
thread.context.epc = threadProc;
|
||||||
|
thread.nextActivateTime = 0;
|
||||||
thread.context.gpr[CMIPS::RA] = m_threadFinishAddress;
|
thread.context.gpr[CMIPS::RA] = m_threadFinishAddress;
|
||||||
thread.context.gpr[CMIPS::SP] = stackBaseAddress;
|
thread.context.gpr[CMIPS::SP] = stackBaseAddress;
|
||||||
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
||||||
return thread.id;
|
return thread.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CIopBios::StartThread(uint32 threadId, uint32* param)
|
||||||
|
{
|
||||||
|
THREAD& thread = GetThread(threadId);
|
||||||
|
if(thread.status != THREAD_STATUS_CREATED)
|
||||||
|
{
|
||||||
|
throw runtime_error("Invalid thread state.");
|
||||||
|
}
|
||||||
|
thread.status = THREAD_STATUS_RUNNING;
|
||||||
|
if(param != NULL)
|
||||||
|
{
|
||||||
|
thread.context.gpr[CMIPS::A0] = *param;
|
||||||
|
}
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIopBios::DelayThread(uint32 delay)
|
||||||
|
{
|
||||||
|
//TODO : Need to delay or something...
|
||||||
|
THREAD& thread = GetThread(m_currentThreadId);
|
||||||
|
thread.nextActivateTime = GetCurrentTime() + delay;
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIopBios::SleepThread()
|
||||||
|
{
|
||||||
|
THREAD& thread = GetThread(m_currentThreadId);
|
||||||
|
if(thread.status != THREAD_STATUS_RUNNING)
|
||||||
|
{
|
||||||
|
throw runtime_error("Thread isn't running.");
|
||||||
|
}
|
||||||
|
if(thread.wakeupCount == 0)
|
||||||
|
{
|
||||||
|
thread.status = THREAD_STATUS_SLEEPING;
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread.wakeupCount--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::WakeupThread(uint32 threadId)
|
||||||
|
{
|
||||||
|
THREAD& thread = GetThread(threadId);
|
||||||
|
if(thread.status == THREAD_STATUS_SLEEPING)
|
||||||
|
{
|
||||||
|
thread.status = THREAD_STATUS_RUNNING;
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread.wakeupCount++;
|
||||||
|
}
|
||||||
|
return thread.wakeupCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::GetThreadId()
|
||||||
|
{
|
||||||
|
return m_currentThreadId;
|
||||||
|
}
|
||||||
|
|
||||||
void CIopBios::ExitCurrentThread()
|
void CIopBios::ExitCurrentThread()
|
||||||
{
|
{
|
||||||
ThreadMapType::iterator thread = GetThreadPosition(m_currentThreadId);
|
ThreadMapType::iterator thread = GetThreadPosition(m_currentThreadId);
|
||||||
m_threads.erase(thread);
|
m_threads.erase(thread);
|
||||||
m_currentThreadId = -1;
|
m_currentThreadId = -1;
|
||||||
Reschedule();
|
m_rescheduleNeeded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIopBios::LoadThreadContext(uint32 threadId)
|
void CIopBios::LoadThreadContext(uint32 threadId)
|
||||||
@ -169,12 +312,116 @@ void CIopBios::Reschedule()
|
|||||||
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
THREAD& nextThread = m_threads.begin()->second;
|
uint32 nextThreadId = GetNextReadyThread(true);
|
||||||
LoadThreadContext(nextThread.id);
|
if(nextThreadId == -1)
|
||||||
m_currentThreadId = nextThread.id;
|
{
|
||||||
|
//Try without checking activation time
|
||||||
|
nextThreadId = GetNextReadyThread(false);
|
||||||
|
if(nextThreadId == -1)
|
||||||
|
{
|
||||||
|
throw runtime_error("No thread available for running.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadThreadContext(nextThreadId);
|
||||||
|
m_currentThreadId = nextThreadId;
|
||||||
m_cpu.m_nQuota = 1;
|
m_cpu.m_nQuota = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::GetNextReadyThread(bool checkActivateTime)
|
||||||
|
{
|
||||||
|
for(ThreadMapType::const_iterator thread(m_threads.begin());
|
||||||
|
thread != m_threads.end(); thread++)
|
||||||
|
{
|
||||||
|
const THREAD& nextThread = thread->second;
|
||||||
|
if(checkActivateTime && (GetCurrentTime() <= nextThread.nextActivateTime)) continue;
|
||||||
|
if(nextThread.status == THREAD_STATUS_RUNNING)
|
||||||
|
{
|
||||||
|
return nextThread.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 CIopBios::GetCurrentTime()
|
||||||
|
{
|
||||||
|
return (clock() * 1000) / CLOCKS_PER_SEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
CIopBios::SEMAPHORE& CIopBios::GetSemaphore(uint32 semaphoreId)
|
||||||
|
{
|
||||||
|
SemaphoreMapType::iterator semaphore(m_semaphores.find(semaphoreId));
|
||||||
|
if(semaphore == m_semaphores.end())
|
||||||
|
{
|
||||||
|
throw runtime_error("Invalid semaphore id.");
|
||||||
|
}
|
||||||
|
return semaphore->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::CreateSemaphore(uint32 initialCount, uint32 maxCount)
|
||||||
|
{
|
||||||
|
SEMAPHORE semaphore;
|
||||||
|
memset(&semaphore, 0, sizeof(SEMAPHORE));
|
||||||
|
semaphore.count = initialCount;
|
||||||
|
semaphore.maxCount = maxCount;
|
||||||
|
semaphore.id = m_nextSemaphoreId++;
|
||||||
|
semaphore.waitCount = 0;
|
||||||
|
m_semaphores[semaphore.id] = semaphore;
|
||||||
|
return semaphore.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::SignalSemaphore(uint32 semaphoreId)
|
||||||
|
{
|
||||||
|
SEMAPHORE& semaphore = GetSemaphore(semaphoreId);
|
||||||
|
if(semaphore.waitCount != 0)
|
||||||
|
{
|
||||||
|
for(ThreadMapType::iterator threadIterator(m_threads.begin());
|
||||||
|
m_threads.end() != threadIterator; ++threadIterator)
|
||||||
|
{
|
||||||
|
THREAD& thread(threadIterator->second);
|
||||||
|
if(thread.waitSemaphore == semaphoreId)
|
||||||
|
{
|
||||||
|
if(thread.status != THREAD_STATUS_WAITING)
|
||||||
|
{
|
||||||
|
throw runtime_error("Thread not waiting (inconsistent state).");
|
||||||
|
}
|
||||||
|
thread.status = THREAD_STATUS_RUNNING;
|
||||||
|
thread.waitSemaphore = 0;
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
semaphore.waitCount--;
|
||||||
|
if(semaphore.waitCount == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semaphore.count++;
|
||||||
|
}
|
||||||
|
return semaphore.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CIopBios::WaitSemaphore(uint32 semaphoreId)
|
||||||
|
{
|
||||||
|
SEMAPHORE& semaphore = GetSemaphore(semaphoreId);
|
||||||
|
if(semaphore.count == 0)
|
||||||
|
{
|
||||||
|
THREAD& thread = GetThread(m_currentThreadId);
|
||||||
|
thread.status = THREAD_STATUS_WAITING;
|
||||||
|
thread.waitSemaphore = semaphoreId;
|
||||||
|
semaphore.waitCount++;
|
||||||
|
m_rescheduleNeeded = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
semaphore.count--;
|
||||||
|
}
|
||||||
|
return semaphore.count;
|
||||||
|
}
|
||||||
|
|
||||||
Iop::CIoman* CIopBios::GetIoman()
|
Iop::CIoman* CIopBios::GetIoman()
|
||||||
{
|
{
|
||||||
return m_ioman;
|
return m_ioman;
|
||||||
@ -219,12 +466,77 @@ void CIopBios::SysCallHandler()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("IOP(%0.8X): Trying to call a function from non-existing module (%s, %d).\r\n",
|
#ifdef _DEBUG
|
||||||
|
CLog::GetInstance().Print(LOGNAME, "%0.8X: Trying to call a function from non-existing module (%s, %d).\r\n",
|
||||||
m_cpu.m_State.nPC, moduleName.c_str(), functionId);
|
m_cpu.m_State.nPC, moduleName.c_str(), functionId);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cpu.m_State.nCOP0[CCOP_SCU::EPC] = 0;
|
if(m_rescheduleNeeded)
|
||||||
|
{
|
||||||
|
m_rescheduleNeeded = false;
|
||||||
|
Reschedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cpu.m_State.nHasException = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string CIopBios::GetModuleNameFromPath(const std::string& path)
|
||||||
|
{
|
||||||
|
string::size_type slashPosition;
|
||||||
|
slashPosition = path.rfind('/');
|
||||||
|
if(slashPosition != string::npos)
|
||||||
|
{
|
||||||
|
return string(path.begin() + slashPosition + 1, path.end());
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CIopBios::LOADEDMODULE& CIopBios::GetModuleAtAddress(uint32 address)
|
||||||
|
{
|
||||||
|
for(LoadedModuleListType::const_iterator moduleIterator(m_loadedModules.begin());
|
||||||
|
m_loadedModules.end() != moduleIterator; moduleIterator++)
|
||||||
|
{
|
||||||
|
const LOADEDMODULE& module(*moduleIterator);
|
||||||
|
if(address >= module.begin && address <= module.end)
|
||||||
|
{
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw runtime_error("No module at specified address.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIopBios::LoadModuleTags(const LOADEDMODULE& module, CMIPSTags& tags, const char* tagCollectionName)
|
||||||
|
{
|
||||||
|
CMIPSTags moduleTags;
|
||||||
|
moduleTags.Unserialize((module.name + "." + string(tagCollectionName)).c_str());
|
||||||
|
for(CMIPSTags::TagIterator tag(moduleTags.GetTagsBegin());
|
||||||
|
tag != moduleTags.GetTagsEnd(); tag++)
|
||||||
|
{
|
||||||
|
tags.InsertTag(tag->first + module.begin, tag->second.c_str());
|
||||||
|
}
|
||||||
|
tags.m_OnTagListChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIopBios::SaveAllModulesTags(CMIPSTags& tags, const char* tagCollectionName)
|
||||||
|
{
|
||||||
|
for(LoadedModuleListType::const_iterator moduleIterator(m_loadedModules.begin());
|
||||||
|
m_loadedModules.end() != moduleIterator; moduleIterator++)
|
||||||
|
{
|
||||||
|
const LOADEDMODULE& module(*moduleIterator);
|
||||||
|
CMIPSTags moduleTags;
|
||||||
|
for(CMIPSTags::TagIterator tag(tags.GetTagsBegin());
|
||||||
|
tag != tags.GetTagsEnd(); tag++)
|
||||||
|
{
|
||||||
|
uint32 tagAddress = tag->first;
|
||||||
|
if(tagAddress >= module.begin && tagAddress <= module.end)
|
||||||
|
{
|
||||||
|
moduleTags.InsertTag(tagAddress - module.begin, tag->second.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moduleTags.Serialize((module.name + "." + string(tagCollectionName)).c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string CIopBios::ReadModuleName(uint32 address)
|
string CIopBios::ReadModuleName(uint32 address)
|
||||||
@ -253,7 +565,7 @@ uint32 CIopBios::Push(uint32& address, const uint8* data, uint32 size)
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 CIopBios::LoadExecutable(const char* path)
|
uint32 CIopBios::LoadExecutable(const char* path, ExecutableRange& executableRange)
|
||||||
{
|
{
|
||||||
uint32 handle = m_ioman->Open(Iop::Ioman::CDevice::O_RDONLY, path);
|
uint32 handle = m_ioman->Open(Iop::Ioman::CDevice::O_RDONLY, path);
|
||||||
if(handle & 0x80000000)
|
if(handle & 0x80000000)
|
||||||
@ -264,22 +576,42 @@ uint32 CIopBios::LoadExecutable(const char* path)
|
|||||||
CStream* stream = m_ioman->GetFileStream(file);
|
CStream* stream = m_ioman->GetFileStream(file);
|
||||||
CELF elf(stream);
|
CELF elf(stream);
|
||||||
|
|
||||||
uint32 baseAddress = m_sysmem->AllocateMemory(elf.m_nLenght, 0);
|
unsigned int programHeaderIndex = GetElfProgramToLoad(elf);
|
||||||
|
if(programHeaderIndex == -1)
|
||||||
|
{
|
||||||
|
throw runtime_error("No program to load.");
|
||||||
|
}
|
||||||
|
ELFPROGRAMHEADER* programHeader = elf.GetProgram(programHeaderIndex);
|
||||||
|
// uint32 baseAddress = m_sysmem->AllocateMemory(elf.m_nLenght, 0);
|
||||||
|
uint32 baseAddress = m_sysmem->AllocateMemory(programHeader->nMemorySize, 0);
|
||||||
RelocateElf(elf, baseAddress);
|
RelocateElf(elf, baseAddress);
|
||||||
|
|
||||||
|
memcpy(
|
||||||
|
m_ram + baseAddress,
|
||||||
|
elf.m_pData + programHeader->nOffset,
|
||||||
|
programHeader->nFileSize);
|
||||||
|
|
||||||
|
executableRange.first = baseAddress;
|
||||||
|
executableRange.second = baseAddress + programHeader->nMemorySize;
|
||||||
|
return baseAddress + elf.m_Header.nEntryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CIopBios::GetElfProgramToLoad(CELF& elf)
|
||||||
|
{
|
||||||
|
unsigned int program = -1;
|
||||||
for(unsigned int i = 0; i < elf.m_Header.nProgHeaderCount; i++)
|
for(unsigned int i = 0; i < elf.m_Header.nProgHeaderCount; i++)
|
||||||
{
|
{
|
||||||
ELFPROGRAMHEADER* programHeader = elf.GetProgram(i);
|
ELFPROGRAMHEADER* programHeader = elf.GetProgram(i);
|
||||||
if(programHeader != NULL && programHeader->nType == 1)
|
if(programHeader != NULL && programHeader->nType == 1)
|
||||||
{
|
{
|
||||||
memcpy(
|
if(program != -1)
|
||||||
m_ram + baseAddress,
|
{
|
||||||
elf.m_pData + programHeader->nOffset,
|
throw runtime_error("Multiple loadable program headers found.");
|
||||||
programHeader->nFileSize);
|
}
|
||||||
|
program = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return program;
|
||||||
return baseAddress + elf.m_Header.nEntryPoint;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CIopBios::RelocateElf(CELF& elf, uint32 baseAddress)
|
void CIopBios::RelocateElf(CELF& elf, uint32 baseAddress)
|
||||||
@ -343,7 +675,10 @@ void CIopBios::RelocateElf(CELF& elf, uint32 baseAddress)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("%s: No HI16 relocation record found for corresponding LO16.\r\n", __FUNCTION__);
|
#ifdef _DEBUG
|
||||||
|
CLog::GetInstance().Print(LOGNAME, "%s: No HI16 relocation record found for corresponding LO16.\r\n",
|
||||||
|
__FUNCTION__);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef _IOPBIOS_H_
|
#ifndef _IOPBIOS_H_
|
||||||
#define _IOPBIOS_H_
|
#define _IOPBIOS_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include "MIPSAssembler.h"
|
#include "MIPSAssembler.h"
|
||||||
#include "MIPS.h"
|
#include "MIPS.h"
|
||||||
#include "ELF.h"
|
#include "ELF.h"
|
||||||
@ -21,12 +22,28 @@ public:
|
|||||||
Iop::CIoman* GetIoman();
|
Iop::CIoman* GetIoman();
|
||||||
void RegisterModule(Iop::CModule*);
|
void RegisterModule(Iop::CModule*);
|
||||||
|
|
||||||
|
uint32 CreateThread(uint32, uint32);
|
||||||
|
void StartThread(uint32, uint32* = NULL);
|
||||||
|
void DelayThread(uint32);
|
||||||
|
uint32 GetThreadId();
|
||||||
|
void SleepThread();
|
||||||
|
uint32 WakeupThread(uint32);
|
||||||
|
|
||||||
|
uint32 CreateSemaphore(uint32, uint32);
|
||||||
|
uint32 SignalSemaphore(uint32);
|
||||||
|
uint32 WaitSemaphore(uint32);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum DEFAULT_STACKSIZE
|
enum DEFAULT_STACKSIZE
|
||||||
{
|
{
|
||||||
DEFAULT_STACKSIZE = 0x8000,
|
DEFAULT_STACKSIZE = 0x8000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum DEFAULT_PRIORITY
|
||||||
|
{
|
||||||
|
DEFAULT_PRIORITY = 7,
|
||||||
|
};
|
||||||
|
|
||||||
struct THREADCONTEXT
|
struct THREADCONTEXT
|
||||||
{
|
{
|
||||||
uint32 gpr[0x20];
|
uint32 gpr[0x20];
|
||||||
@ -39,22 +56,61 @@ private:
|
|||||||
uint32 id;
|
uint32 id;
|
||||||
uint32 priority;
|
uint32 priority;
|
||||||
THREADCONTEXT context;
|
THREADCONTEXT context;
|
||||||
|
uint32 status;
|
||||||
|
uint32 waitSemaphore;
|
||||||
|
uint32 wakeupCount;
|
||||||
|
uint64 nextActivateTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::multimap<uint32, THREAD> ThreadMapType;
|
struct SEMAPHORE
|
||||||
|
{
|
||||||
|
uint32 id;
|
||||||
|
uint32 count;
|
||||||
|
uint32 maxCount;
|
||||||
|
uint32 waitCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LOADEDMODULE
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
uint32 begin;
|
||||||
|
uint32 end;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum THREAD_STATUS
|
||||||
|
{
|
||||||
|
THREAD_STATUS_CREATED = 1,
|
||||||
|
THREAD_STATUS_RUNNING = 2,
|
||||||
|
THREAD_STATUS_SLEEPING = 3,
|
||||||
|
THREAD_STATUS_ZOMBIE = 4,
|
||||||
|
THREAD_STATUS_WAITING = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::multimap<uint32, THREAD, std::greater<uint32> > ThreadMapType;
|
||||||
typedef std::map<std::string, Iop::CModule*> IopModuleMapType;
|
typedef std::map<std::string, Iop::CModule*> IopModuleMapType;
|
||||||
|
typedef std::map<uint32, SEMAPHORE> SemaphoreMapType;
|
||||||
|
typedef std::list<LOADEDMODULE> LoadedModuleListType;
|
||||||
|
typedef std::pair<uint32, uint32> ExecutableRange;
|
||||||
|
|
||||||
THREAD& GetThread(uint32);
|
THREAD& GetThread(uint32);
|
||||||
ThreadMapType::iterator GetThreadPosition(uint32);
|
ThreadMapType::iterator GetThreadPosition(uint32);
|
||||||
uint32 CreateThread(uint32);
|
|
||||||
void ExitCurrentThread();
|
void ExitCurrentThread();
|
||||||
void LoadThreadContext(uint32);
|
void LoadThreadContext(uint32);
|
||||||
void SaveThreadContext(uint32);
|
void SaveThreadContext(uint32);
|
||||||
void Reschedule();
|
void Reschedule();
|
||||||
|
uint32 GetNextReadyThread(bool);
|
||||||
|
uint64 GetCurrentTime();
|
||||||
|
|
||||||
uint32 LoadExecutable(const char*);
|
SEMAPHORE& GetSemaphore(uint32);
|
||||||
|
|
||||||
|
uint32 LoadExecutable(const char*, ExecutableRange&);
|
||||||
|
unsigned int GetElfProgramToLoad(CELF&);
|
||||||
void RelocateElf(CELF&, uint32);
|
void RelocateElf(CELF&, uint32);
|
||||||
std::string ReadModuleName(uint32);
|
std::string ReadModuleName(uint32);
|
||||||
|
std::string GetModuleNameFromPath(const std::string&);
|
||||||
|
const LOADEDMODULE& GetModuleAtAddress(uint32);
|
||||||
|
void LoadModuleTags(const LOADEDMODULE&, CMIPSTags&, const char*);
|
||||||
|
void SaveAllModulesTags(CMIPSTags&, const char*);
|
||||||
uint32 Push(uint32&, const uint8*, uint32);
|
uint32 Push(uint32&, const uint8*, uint32);
|
||||||
|
|
||||||
uint32 AssembleThreadFinish(CMIPSAssembler&);
|
uint32 AssembleThreadFinish(CMIPSAssembler&);
|
||||||
@ -64,9 +120,13 @@ private:
|
|||||||
uint32 m_baseAddress;
|
uint32 m_baseAddress;
|
||||||
uint32 m_threadFinishAddress;
|
uint32 m_threadFinishAddress;
|
||||||
uint32 m_nextThreadId;
|
uint32 m_nextThreadId;
|
||||||
|
uint32 m_nextSemaphoreId;
|
||||||
uint32 m_currentThreadId;
|
uint32 m_currentThreadId;
|
||||||
|
bool m_rescheduleNeeded;
|
||||||
ThreadMapType m_threads;
|
ThreadMapType m_threads;
|
||||||
|
SemaphoreMapType m_semaphores;
|
||||||
IopModuleMapType m_modules;
|
IopModuleMapType m_modules;
|
||||||
|
LoadedModuleListType m_loadedModules;
|
||||||
Iop::CStdio* m_stdio;
|
Iop::CStdio* m_stdio;
|
||||||
Iop::CIoman* m_ioman;
|
Iop::CIoman* m_ioman;
|
||||||
Iop::CSysmem* m_sysmem;
|
Iop::CSysmem* m_sysmem;
|
||||||
|
40
tools/PsfPlayer/Source/Iop_Intc.cpp
Normal file
40
tools/PsfPlayer/Source/Iop_Intc.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "Iop_Intc.h"
|
||||||
|
|
||||||
|
using namespace Iop;
|
||||||
|
|
||||||
|
CIntc::CIntc() :
|
||||||
|
m_mask(0),
|
||||||
|
m_status(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CIntc::~CIntc()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIntc::AssertLine(unsigned int line)
|
||||||
|
{
|
||||||
|
m_status |= 1 << line;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIntc::ClearLine(unsigned int line)
|
||||||
|
{
|
||||||
|
m_status &= ~(1 << line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIntc::SetMask(uint32 mask)
|
||||||
|
{
|
||||||
|
m_mask = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIntc::SetStatus(uint32 status)
|
||||||
|
{
|
||||||
|
m_status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CIntc::HasPendingInterrupt()
|
||||||
|
{
|
||||||
|
return (m_mask & m_status) != 0;
|
||||||
|
}
|
26
tools/PsfPlayer/Source/Iop_Intc.h
Normal file
26
tools/PsfPlayer/Source/Iop_Intc.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _IOP_INTC_H_
|
||||||
|
#define _IOP_INTC_H_
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
namespace Iop
|
||||||
|
{
|
||||||
|
class CIntc
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CIntc();
|
||||||
|
virtual ~CIntc();
|
||||||
|
|
||||||
|
void AssertLine(unsigned int);
|
||||||
|
void ClearLine(unsigned int);
|
||||||
|
void SetStatus(uint32);
|
||||||
|
void SetMask(uint32);
|
||||||
|
bool HasPendingInterrupt();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 m_status;
|
||||||
|
uint32 m_mask;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
32
tools/PsfPlayer/Source/Iop_Intrman.cpp
Normal file
32
tools/PsfPlayer/Source/Iop_Intrman.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "Iop_Intrman.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
#define LOGNAME "iop_intrman"
|
||||||
|
|
||||||
|
using namespace Iop;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CIntrman::CIntrman()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CIntrman::~CIntrman()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string CIntrman::GetId() const
|
||||||
|
{
|
||||||
|
return "intrman";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CIntrman::Invoke(CMIPS& context, unsigned int functionId)
|
||||||
|
{
|
||||||
|
switch(functionId)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
CLog::GetInstance().Print(LOGNAME, "%0.8X: Unknown function (%d) called.\r\n", context.m_State.nPC, functionId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
23
tools/PsfPlayer/Source/Iop_Intrman.h
Normal file
23
tools/PsfPlayer/Source/Iop_Intrman.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _IOP_INTRMAN_H_
|
||||||
|
#define _IOP_INTRMAN_H_
|
||||||
|
|
||||||
|
#include "Iop_Module.h"
|
||||||
|
|
||||||
|
namespace Iop
|
||||||
|
{
|
||||||
|
class CIntrman : public CModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CIntrman();
|
||||||
|
virtual ~CIntrman();
|
||||||
|
|
||||||
|
std::string GetId() const;
|
||||||
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -125,6 +125,11 @@ uint32 CIoman::Seek(uint32 handle, uint32 position, uint32 whence)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 CIoman::DelDrv(const char* deviceName)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
CStream* CIoman::GetFileStream(uint32 handle)
|
CStream* CIoman::GetFileStream(uint32 handle)
|
||||||
{
|
{
|
||||||
FileMapType::iterator file(m_files.find(handle));
|
FileMapType::iterator file(m_files.find(handle));
|
||||||
@ -163,6 +168,11 @@ void CIoman::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
context.m_State.nGPR[CMIPS::A1].nV[0],
|
context.m_State.nGPR[CMIPS::A1].nV[0],
|
||||||
context.m_State.nGPR[CMIPS::A2].nV[0]));
|
context.m_State.nGPR[CMIPS::A2].nV[0]));
|
||||||
break;
|
break;
|
||||||
|
case 21:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(DelDrv(
|
||||||
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nD0])
|
||||||
|
));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
break;
|
break;
|
||||||
|
@ -35,11 +35,11 @@ namespace Iop
|
|||||||
uint32 Close(uint32);
|
uint32 Close(uint32);
|
||||||
uint32 Read(uint32, uint32, void*);
|
uint32 Read(uint32, uint32, void*);
|
||||||
uint32 Seek(uint32, uint32, uint32);
|
uint32 Seek(uint32, uint32, uint32);
|
||||||
|
uint32 DelDrv(const char*);
|
||||||
|
|
||||||
Framework::CStream* GetFileStream(uint32);
|
Framework::CStream* GetFileStream(uint32);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
typedef std::map<uint32, Framework::CStream*> FileMapType;
|
typedef std::map<uint32, Framework::CStream*> FileMapType;
|
||||||
typedef std::map<std::string, Ioman::CDevice*> DeviceMapType;
|
typedef std::map<std::string, Ioman::CDevice*> DeviceMapType;
|
||||||
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include "Iop_Stdio.h"
|
#include "Iop_Stdio.h"
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
#include "lexical_cast_ex.h"
|
||||||
|
|
||||||
using namespace Iop;
|
using namespace Iop;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace boost;
|
||||||
|
|
||||||
CStdio::CStdio(uint8* ram) :
|
CStdio::CStdio(uint8* ram) :
|
||||||
m_ram(ram)
|
m_ram(ram)
|
||||||
@ -24,7 +27,7 @@ void CStdio::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
switch(functionId)
|
switch(functionId)
|
||||||
{
|
{
|
||||||
case 4:
|
case 4:
|
||||||
Printf(context);
|
__printf(context);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s(%0.8X): Unknown function (%d) called.", __FUNCTION__, context.m_State.nPC, functionId);
|
printf("%s(%0.8X): Unknown function (%d) called.", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
@ -32,30 +35,65 @@ void CStdio::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStdio::Printf(CMIPS& context)
|
string CStdio::PrintFormatted(CArgumentIterator& args)
|
||||||
{
|
{
|
||||||
const char* format = reinterpret_cast<const char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV[0]]);
|
string output;
|
||||||
unsigned int param = CMIPS::A1;
|
const char* format = reinterpret_cast<const char*>(&m_ram[args.GetNext()]);
|
||||||
while(*format != 0)
|
while(*format != 0)
|
||||||
{
|
{
|
||||||
char character = *(format++);
|
char character = *(format++);
|
||||||
if(character == '%')
|
if(character == '%')
|
||||||
{
|
{
|
||||||
char type = *(format++);
|
bool paramDone = false;
|
||||||
if(type == 's')
|
bool inPrecision = false;
|
||||||
|
string precision;
|
||||||
|
while(!paramDone && *format != 0)
|
||||||
{
|
{
|
||||||
const char* text = reinterpret_cast<const char*>(&m_ram[context.m_State.nGPR[param++].nV[0]]);
|
char type = *(format++);
|
||||||
printf("%s", text);
|
if(type == 's')
|
||||||
}
|
{
|
||||||
else if(type == 'd')
|
const char* text = reinterpret_cast<const char*>(&m_ram[args.GetNext()]);
|
||||||
{
|
output += text;
|
||||||
int number = context.m_State.nGPR[param++].nV[0];
|
paramDone = true;
|
||||||
printf("%d", number);
|
}
|
||||||
|
else if(type == 'd')
|
||||||
|
{
|
||||||
|
int number = args.GetNext();
|
||||||
|
unsigned int precisionValue = precision.length() ? lexical_cast<unsigned int>(precision) : 0;
|
||||||
|
output += lexical_cast<string>(number);
|
||||||
|
paramDone = true;
|
||||||
|
}
|
||||||
|
else if(type == 'u')
|
||||||
|
{
|
||||||
|
unsigned int number = args.GetNext();
|
||||||
|
unsigned int precisionValue = precision.length() ? lexical_cast<unsigned int>(precision) : 0;
|
||||||
|
output += lexical_cast_uint<string>(number, precisionValue);
|
||||||
|
paramDone = true;
|
||||||
|
}
|
||||||
|
else if(type == '.')
|
||||||
|
{
|
||||||
|
inPrecision = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(inPrecision)
|
||||||
|
{
|
||||||
|
precision += type;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
putc(character, stdout);
|
output += character;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStdio::__printf(CMIPS& context)
|
||||||
|
{
|
||||||
|
CArgumentIterator args(context);
|
||||||
|
string output = PrintFormatted(args);
|
||||||
|
printf("%s", output.c_str());
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define _IOP_STDIO_H_
|
#define _IOP_STDIO_H_
|
||||||
|
|
||||||
#include "Iop_Module.h"
|
#include "Iop_Module.h"
|
||||||
|
#include "ArgumentIterator.h"
|
||||||
|
|
||||||
namespace Iop
|
namespace Iop
|
||||||
{
|
{
|
||||||
@ -13,10 +14,11 @@ namespace Iop
|
|||||||
|
|
||||||
std::string GetId() const;
|
std::string GetId() const;
|
||||||
void Invoke(CMIPS&, unsigned int);
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
void __printf(CMIPS&);
|
||||||
|
std::string PrintFormatted(CArgumentIterator&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Printf(CMIPS&);
|
uint8* m_ram;
|
||||||
uint8* m_ram;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@
|
|||||||
using namespace Iop;
|
using namespace Iop;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CSysclib::CSysclib(uint8* ram) :
|
CSysclib::CSysclib(uint8* ram, CStdio& stdio) :
|
||||||
m_ram(ram)
|
m_ram(ram),
|
||||||
|
m_stdio(stdio)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -23,6 +24,13 @@ void CSysclib::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
{
|
{
|
||||||
switch(functionId)
|
switch(functionId)
|
||||||
{
|
{
|
||||||
|
case 12:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
||||||
|
__memcpy(
|
||||||
|
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
||||||
|
&m_ram[context.m_State.nGPR[CMIPS::A1].nV0],
|
||||||
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
||||||
|
break;
|
||||||
case 14:
|
case 14:
|
||||||
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
||||||
__memset(
|
__memset(
|
||||||
@ -30,6 +38,22 @@ void CSysclib::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
context.m_State.nGPR[CMIPS::A1].nV0,
|
context.m_State.nGPR[CMIPS::A1].nV0,
|
||||||
context.m_State.nGPR[CMIPS::A2].nV0);
|
context.m_State.nGPR[CMIPS::A2].nV0);
|
||||||
break;
|
break;
|
||||||
|
case 17:
|
||||||
|
__memset(
|
||||||
|
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
||||||
|
0,
|
||||||
|
context.m_State.nGPR[CMIPS::A1].nV0);
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__sprintf(context));
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
||||||
|
__strcpy(
|
||||||
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
||||||
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0])
|
||||||
|
);
|
||||||
|
break;
|
||||||
case 27:
|
case 27:
|
||||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strlen(
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strlen(
|
||||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
||||||
@ -55,16 +79,35 @@ void CSysclib::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSysclib::__memcpy(void* dest, const void* src, unsigned int length)
|
||||||
|
{
|
||||||
|
memcpy(dest, src, length);
|
||||||
|
}
|
||||||
|
|
||||||
void CSysclib::__memset(void* dest, int character, unsigned int length)
|
void CSysclib::__memset(void* dest, int character, unsigned int length)
|
||||||
{
|
{
|
||||||
memset(dest, character, length);
|
memset(dest, character, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 CSysclib::__sprintf(CMIPS& context)
|
||||||
|
{
|
||||||
|
CArgumentIterator args(context);
|
||||||
|
char* destination = reinterpret_cast<char*>(&m_ram[args.GetNext()]);
|
||||||
|
string output = m_stdio.PrintFormatted(args);
|
||||||
|
strcpy(destination, output.c_str());
|
||||||
|
return static_cast<uint32>(output.length());
|
||||||
|
}
|
||||||
|
|
||||||
uint32 CSysclib::__strlen(const char* string)
|
uint32 CSysclib::__strlen(const char* string)
|
||||||
{
|
{
|
||||||
return static_cast<uint32>(strlen(string));
|
return static_cast<uint32>(strlen(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSysclib::__strcpy(char* dst, const char* src)
|
||||||
|
{
|
||||||
|
strcpy(dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
void CSysclib::__strncpy(char* dst, const char* src, unsigned int count)
|
void CSysclib::__strncpy(char* dst, const char* src, unsigned int count)
|
||||||
{
|
{
|
||||||
strncpy(dst, src, count);
|
strncpy(dst, src, count);
|
||||||
|
@ -2,24 +2,29 @@
|
|||||||
#define _IOP_SYSCLIB_H_
|
#define _IOP_SYSCLIB_H_
|
||||||
|
|
||||||
#include "IOP_Module.h"
|
#include "IOP_Module.h"
|
||||||
|
#include "IOP_Stdio.h"
|
||||||
|
|
||||||
namespace Iop
|
namespace Iop
|
||||||
{
|
{
|
||||||
class CSysclib : public CModule
|
class CSysclib : public CModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSysclib(uint8*);
|
CSysclib(uint8*, CStdio&);
|
||||||
virtual ~CSysclib();
|
virtual ~CSysclib();
|
||||||
|
|
||||||
std::string GetId() const;
|
std::string GetId() const;
|
||||||
void Invoke(CMIPS&, unsigned int);
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void __memcpy(void*, const void*, unsigned int);
|
||||||
void __memset(void*, int, unsigned int);
|
void __memset(void*, int, unsigned int);
|
||||||
|
uint32 __sprintf(CMIPS& context);
|
||||||
uint32 __strlen(const char*);
|
uint32 __strlen(const char*);
|
||||||
|
void __strcpy(char*, const char*);
|
||||||
void __strncpy(char*, const char*, unsigned int);
|
void __strncpy(char*, const char*, unsigned int);
|
||||||
uint32 __strtol(const char*, unsigned int);
|
uint32 __strtol(const char*, unsigned int);
|
||||||
uint8* m_ram;
|
uint8* m_ram;
|
||||||
|
CStdio& m_stdio;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,10 @@
|
|||||||
using namespace Iop;
|
using namespace Iop;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CSysmem::CSysmem(uint32 memoryBegin, uint32 memoryEnd) :
|
CSysmem::CSysmem(uint32 memoryBegin, uint32 memoryEnd, CStdio& stdio) :
|
||||||
m_memoryBegin(memoryBegin),
|
m_memoryBegin(memoryBegin),
|
||||||
m_memoryEnd(memoryEnd),
|
m_memoryEnd(memoryEnd),
|
||||||
|
m_stdio(stdio),
|
||||||
m_memorySize(memoryEnd - memoryBegin)
|
m_memorySize(memoryEnd - memoryBegin)
|
||||||
{
|
{
|
||||||
//Initialize block map
|
//Initialize block map
|
||||||
@ -37,6 +38,9 @@ void CSysmem::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
context.m_State.nGPR[CMIPS::A0].nV[0]
|
context.m_State.nGPR[CMIPS::A0].nV[0]
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
|
case 14:
|
||||||
|
m_stdio.__printf(context);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
break;
|
break;
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
#define _IOP_SYSMEM_H_
|
#define _IOP_SYSMEM_H_
|
||||||
|
|
||||||
#include "Iop_Module.h"
|
#include "Iop_Module.h"
|
||||||
|
#include "Iop_Stdio.h"
|
||||||
|
|
||||||
namespace Iop
|
namespace Iop
|
||||||
{
|
{
|
||||||
class CSysmem : public CModule
|
class CSysmem : public CModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CSysmem(uint32, uint32);
|
CSysmem(uint32, uint32, Iop::CStdio&);
|
||||||
virtual ~CSysmem();
|
virtual ~CSysmem();
|
||||||
|
|
||||||
std::string GetId() const;
|
std::string GetId() const;
|
||||||
@ -24,6 +25,7 @@ namespace Iop
|
|||||||
uint32 m_memoryBegin;
|
uint32 m_memoryBegin;
|
||||||
uint32 m_memoryEnd;
|
uint32 m_memoryEnd;
|
||||||
uint32 m_memorySize;
|
uint32 m_memorySize;
|
||||||
|
Iop::CStdio& m_stdio;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include "Iop_Thbase.h"
|
#include "Iop_Thbase.h"
|
||||||
|
#include "IopBios.h"
|
||||||
|
|
||||||
using namespace Iop;
|
using namespace Iop;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CThbase::CThbase()
|
CThbase::CThbase(CIopBios& bios, uint8* ram) :
|
||||||
|
m_ram(ram),
|
||||||
|
m_bios(bios)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -22,8 +25,68 @@ void CThbase::Invoke(CMIPS& context, unsigned int functionId)
|
|||||||
{
|
{
|
||||||
switch(functionId)
|
switch(functionId)
|
||||||
{
|
{
|
||||||
|
case 4:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(CreateThread(
|
||||||
|
reinterpret_cast<THREAD*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(StartThread(
|
||||||
|
context.m_State.nGPR[CMIPS::A0].nV0,
|
||||||
|
context.m_State.nGPR[CMIPS::A1].nV0
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(GetThreadId());
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SleepThread());
|
||||||
|
break;
|
||||||
|
case 25:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(WakeupThread(
|
||||||
|
context.m_State.nGPR[CMIPS::A0].nV0
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case 33:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(DelayThread(
|
||||||
|
context.m_State.nGPR[CMIPS::A0].nV0
|
||||||
|
));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::CreateThread(const THREAD* thread)
|
||||||
|
{
|
||||||
|
return m_bios.CreateThread(thread->threadProc, thread->priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::StartThread(uint32 threadId, uint32 param)
|
||||||
|
{
|
||||||
|
m_bios.StartThread(threadId, ¶m);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::DelayThread(uint32 delay)
|
||||||
|
{
|
||||||
|
m_bios.DelayThread(delay);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::GetThreadId()
|
||||||
|
{
|
||||||
|
return m_bios.GetThreadId();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::SleepThread()
|
||||||
|
{
|
||||||
|
m_bios.SleepThread();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThbase::WakeupThread(uint32 threadId)
|
||||||
|
{
|
||||||
|
return m_bios.WakeupThread(threadId);
|
||||||
|
}
|
||||||
|
@ -3,19 +3,38 @@
|
|||||||
|
|
||||||
#include "Iop_Module.h"
|
#include "Iop_Module.h"
|
||||||
|
|
||||||
|
class CIopBios;
|
||||||
|
|
||||||
namespace Iop
|
namespace Iop
|
||||||
{
|
{
|
||||||
class CThbase : public CModule
|
class CThbase : public CModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CThbase();
|
CThbase(CIopBios&, uint8*);
|
||||||
virtual ~CThbase();
|
virtual ~CThbase();
|
||||||
|
|
||||||
std::string GetId() const;
|
std::string GetId() const;
|
||||||
void Invoke(CMIPS&, unsigned int);
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct THREAD
|
||||||
|
{
|
||||||
|
uint32 attributes;
|
||||||
|
uint32 options;
|
||||||
|
uint32 threadProc;
|
||||||
|
uint32 stackSize;
|
||||||
|
uint32 priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32 CreateThread(const THREAD*);
|
||||||
|
uint32 StartThread(uint32, uint32);
|
||||||
|
uint32 DelayThread(uint32);
|
||||||
|
uint32 GetThreadId();
|
||||||
|
uint32 SleepThread();
|
||||||
|
uint32 WakeupThread(uint32);
|
||||||
|
|
||||||
|
uint8* m_ram;
|
||||||
|
CIopBios& m_bios;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
tools/PsfPlayer/Source/Iop_Thevent.cpp
Normal file
39
tools/PsfPlayer/Source/Iop_Thevent.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "Iop_Thevent.h"
|
||||||
|
|
||||||
|
using namespace Iop;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CThevent::CThevent(CIopBios& bios, uint8* ram) :
|
||||||
|
m_bios(bios),
|
||||||
|
m_ram(ram)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CThevent::~CThevent()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string CThevent::GetId() const
|
||||||
|
{
|
||||||
|
return "thevent";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CThevent::Invoke(CMIPS& context, unsigned int functionId)
|
||||||
|
{
|
||||||
|
switch(functionId)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(CreateEventFlag());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThevent::CreateEventFlag()
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
27
tools/PsfPlayer/Source/Iop_Thevent.h
Normal file
27
tools/PsfPlayer/Source/Iop_Thevent.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _IOP_THEVENT_H_
|
||||||
|
#define _IOP_THEVENT_H_
|
||||||
|
|
||||||
|
#include "Iop_Module.h"
|
||||||
|
|
||||||
|
class CIopBios;
|
||||||
|
|
||||||
|
namespace Iop
|
||||||
|
{
|
||||||
|
class CThevent : public CModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CThevent(CIopBios&, uint8*);
|
||||||
|
virtual ~CThevent();
|
||||||
|
|
||||||
|
std::string GetId() const;
|
||||||
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32 CreateEventFlag();
|
||||||
|
|
||||||
|
uint8* m_ram;
|
||||||
|
CIopBios& m_bios;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
62
tools/PsfPlayer/Source/Iop_Thsema.cpp
Normal file
62
tools/PsfPlayer/Source/Iop_Thsema.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "Iop_Thsema.h"
|
||||||
|
#include "IopBios.h"
|
||||||
|
|
||||||
|
using namespace Iop;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CThsema::CThsema(CIopBios& bios, uint8* ram) :
|
||||||
|
m_bios(bios),
|
||||||
|
m_ram(ram)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CThsema::~CThsema()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string CThsema::GetId() const
|
||||||
|
{
|
||||||
|
return "thsemap";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CThsema::Invoke(CMIPS& context, unsigned int functionId)
|
||||||
|
{
|
||||||
|
switch(functionId)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(CreateSemaphore(
|
||||||
|
reinterpret_cast<SEMAPHORE*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SignalSemaphore(
|
||||||
|
context.m_State.nGPR[CMIPS::A0].nV0
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(WaitSemaphore(
|
||||||
|
context.m_State.nGPR[CMIPS::A0].nV0
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThsema::CreateSemaphore(const SEMAPHORE* semaphore)
|
||||||
|
{
|
||||||
|
return m_bios.CreateSemaphore(semaphore->initialCount, semaphore->maxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThsema::SignalSemaphore(uint32 semaphoreId)
|
||||||
|
{
|
||||||
|
return m_bios.SignalSemaphore(semaphoreId);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CThsema::WaitSemaphore(uint32 semaphoreId)
|
||||||
|
{
|
||||||
|
return m_bios.WaitSemaphore(semaphoreId);
|
||||||
|
}
|
36
tools/PsfPlayer/Source/Iop_Thsema.h
Normal file
36
tools/PsfPlayer/Source/Iop_Thsema.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _IOP_THSEMA_H_
|
||||||
|
#define _IOP_THSEMA_H_
|
||||||
|
|
||||||
|
#include "Iop_Module.h"
|
||||||
|
#include "IopBios.h"
|
||||||
|
|
||||||
|
namespace Iop
|
||||||
|
{
|
||||||
|
class CThsema : public CModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CThsema(CIopBios&, uint8*);
|
||||||
|
virtual ~CThsema();
|
||||||
|
|
||||||
|
std::string GetId() const;
|
||||||
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct SEMAPHORE
|
||||||
|
{
|
||||||
|
uint32 attributes;
|
||||||
|
uint32 options;
|
||||||
|
uint32 initialCount;
|
||||||
|
uint32 maxCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32 CreateSemaphore(const SEMAPHORE*);
|
||||||
|
uint32 WaitSemaphore(uint32);
|
||||||
|
uint32 SignalSemaphore(uint32);
|
||||||
|
|
||||||
|
uint8* m_ram;
|
||||||
|
CIopBios& m_bios;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
34
tools/PsfPlayer/Source/Iop_Timrman.cpp
Normal file
34
tools/PsfPlayer/Source/Iop_Timrman.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "Iop_Timrman.h"
|
||||||
|
|
||||||
|
using namespace Iop;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CTimrman::CTimrman()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CTimrman::~CTimrman()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string CTimrman::GetId() const
|
||||||
|
{
|
||||||
|
return "timrman";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTimrman::Invoke(CMIPS& context, unsigned int functionId)
|
||||||
|
{
|
||||||
|
switch(functionId)
|
||||||
|
{
|
||||||
|
case 20:
|
||||||
|
context.m_State.nGPR[CMIPS::V0].nD0 = 0;
|
||||||
|
printf("Timrman: Install handler.\r\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
22
tools/PsfPlayer/Source/Iop_Timrman.h
Normal file
22
tools/PsfPlayer/Source/Iop_Timrman.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _TIMRMAN_H_
|
||||||
|
#define _TIMRMAN_H_
|
||||||
|
|
||||||
|
#include "Iop_Module.h"
|
||||||
|
|
||||||
|
namespace Iop
|
||||||
|
{
|
||||||
|
class CTimrman : public CModule
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CTimrman();
|
||||||
|
virtual ~CTimrman();
|
||||||
|
|
||||||
|
std::string GetId() const;
|
||||||
|
void Invoke(CMIPS&, unsigned int);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
44
tools/PsfPlayer/Source/Log.cpp
Normal file
44
tools/PsfPlayer/Source/Log.cpp
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
#define LOG_PATH "./logs/"
|
||||||
|
|
||||||
|
using namespace Framework;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
CLog::CLog()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CLog::~CLog()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLog::Print(const char* logName, const char* format, ...)
|
||||||
|
{
|
||||||
|
CStdStream* log(GetLog(logName));
|
||||||
|
if(log == NULL) return;
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
vfprintf(*log, format, args);
|
||||||
|
va_end(args);
|
||||||
|
log->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
CStdStream* CLog::GetLog(const char* logName)
|
||||||
|
{
|
||||||
|
LogMapType::iterator logIterator(m_logs.find(logName));
|
||||||
|
if(logIterator != m_logs.end())
|
||||||
|
{
|
||||||
|
return logIterator->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CStdStream* log = new CStdStream((LOG_PATH + string(logName) + ".log").c_str(), "wb");
|
||||||
|
m_logs[logName] = log;
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
}
|
26
tools/PsfPlayer/Source/Log.h
Normal file
26
tools/PsfPlayer/Source/Log.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _LOG_H_
|
||||||
|
#define _LOG_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include "StdStream.h"
|
||||||
|
#include "Singleton.h"
|
||||||
|
|
||||||
|
class CLog : public CSingleton<CLog>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Print(const char*, const char*, ...);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class CSingleton<CLog>;
|
||||||
|
typedef std::map<std::string, Framework::CStdStream*> LogMapType;
|
||||||
|
|
||||||
|
CLog();
|
||||||
|
virtual ~CLog();
|
||||||
|
|
||||||
|
Framework::CStdStream* GetLog(const char*);
|
||||||
|
|
||||||
|
LogMapType m_logs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -137,25 +137,45 @@ void CPsfFs::ReadDirectory(CStream& stream, DIRECTORY& baseDirectory)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CPsfFs::NODE* CPsfFs::GetFileFindNode(const DIRECTORY& directory, const char* path) const
|
||||||
|
{
|
||||||
|
for(DIRECTORY::FileListType::const_iterator nodeIterator(directory.fileList.begin());
|
||||||
|
nodeIterator != directory.fileList.end(); nodeIterator++)
|
||||||
|
{
|
||||||
|
const NODE* node(*nodeIterator);
|
||||||
|
if(!_stricmp(node->name, path))
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const CPsfFs::FILE* CPsfFs::GetFileDetail(const DIRECTORY& directory, const char* path) const
|
const CPsfFs::FILE* CPsfFs::GetFileDetail(const DIRECTORY& directory, const char* path) const
|
||||||
{
|
{
|
||||||
if(*path == '/') path++;
|
if(*path == '/') path++;
|
||||||
const char* separator = strchr(path, '/');
|
const char* separator = strchr(path, '/');
|
||||||
|
|
||||||
|
string filename(path, separator != NULL ? separator : path + strlen(path));
|
||||||
|
|
||||||
|
const NODE* node = GetFileFindNode(directory, filename.c_str());
|
||||||
|
if(node == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(separator == NULL)
|
if(separator == NULL)
|
||||||
{
|
{
|
||||||
for(DIRECTORY::FileListType::const_iterator nodeIterator(directory.fileList.begin());
|
return dynamic_cast<const FILE*>(node);
|
||||||
nodeIterator != directory.fileList.end(); nodeIterator++)
|
|
||||||
{
|
|
||||||
const NODE* node(*nodeIterator);
|
|
||||||
if(!_stricmp(node->name, path))
|
|
||||||
{
|
|
||||||
return dynamic_cast<const FILE*>(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Gotta look in subdir
|
const DIRECTORY* subDir = dynamic_cast<const DIRECTORY*>(node);
|
||||||
|
if(subDir == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return GetFileDetail(*subDir, separator + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ private:
|
|||||||
void ReadFile(Framework::CStream&, FILE&);
|
void ReadFile(Framework::CStream&, FILE&);
|
||||||
void ReadDirectory(Framework::CStream&, DIRECTORY&);
|
void ReadDirectory(Framework::CStream&, DIRECTORY&);
|
||||||
const FILE* GetFileDetail(const DIRECTORY&, const char*) const;
|
const FILE* GetFileDetail(const DIRECTORY&, const char*) const;
|
||||||
|
const NODE* GetFileFindNode(const DIRECTORY&, const char*) const;
|
||||||
std::string GetPsfLibAttributeName(unsigned int);
|
std::string GetPsfLibAttributeName(unsigned int);
|
||||||
|
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
|
@ -21,12 +21,21 @@ m_status(PAUSED),
|
|||||||
m_pauseAck(false),
|
m_pauseAck(false),
|
||||||
m_emuThread(NULL),
|
m_emuThread(NULL),
|
||||||
m_bios(NULL),
|
m_bios(NULL),
|
||||||
|
m_spu(SPUBEGIN),
|
||||||
m_singleStep(false)
|
m_singleStep(false)
|
||||||
{
|
{
|
||||||
memset(&m_cpu.m_State, 0, sizeof(m_cpu.m_State));
|
memset(&m_cpu.m_State, 0, sizeof(m_cpu.m_State));
|
||||||
|
|
||||||
m_ram = new uint8[RAMSIZE];
|
m_ram = new uint8[RAMSIZE];
|
||||||
m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, RAMSIZE - 1, m_ram, MEMORYMAP_TYPE_MEMORY, 0x00);
|
memset(m_ram, 0, RAMSIZE);
|
||||||
m_cpu.m_pMemoryMap->InsertWriteMap(0x00000000, RAMSIZE - 1, m_ram, MEMORYMAP_TYPE_MEMORY, 0x00);
|
|
||||||
|
m_intc.SetMask(0xFFFFFFFF);
|
||||||
|
m_intc.SetStatus(0);
|
||||||
|
|
||||||
|
m_cpu.m_pMemoryMap->InsertReadMap(0x00000000, RAMSIZE - 1, m_ram, 0x00);
|
||||||
|
m_cpu.m_pMemoryMap->InsertReadMap(SPUBEGIN, SPUEND - 1, bind(&CSpu2::ReadRegister, &m_spu, _1), 0x01);
|
||||||
|
|
||||||
|
m_cpu.m_pMemoryMap->InsertWriteMap(0x00000000, RAMSIZE - 1, m_ram, 0x00);
|
||||||
|
|
||||||
m_cpu.m_pArch = &g_MAMIPSIV;
|
m_cpu.m_pArch = &g_MAMIPSIV;
|
||||||
m_cpu.m_pAddrTranslator = m_cpu.TranslateAddress64;
|
m_cpu.m_pAddrTranslator = m_cpu.TranslateAddress64;
|
||||||
@ -35,8 +44,8 @@ m_singleStep(false)
|
|||||||
m_cpu.m_handlerParam = this;
|
m_cpu.m_handlerParam = this;
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
m_cpu.m_Functions.Unserialize("functions.bin");
|
// m_cpu.m_Functions.Unserialize("functions.bin");
|
||||||
m_cpu.m_Comments.Unserialize("comments.bin");
|
// m_cpu.m_Comments.Unserialize("comments.bin");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_bios = new CIopBios(0x100, m_cpu, m_ram, RAMSIZE);
|
m_bios = new CIopBios(0x100, m_cpu, m_ram, RAMSIZE);
|
||||||
@ -44,6 +53,7 @@ m_singleStep(false)
|
|||||||
string execPath = string(PSF_DEVICENAME) + ":/psf2.irx";
|
string execPath = string(PSF_DEVICENAME) + ":/psf2.irx";
|
||||||
|
|
||||||
m_bios->GetIoman()->RegisterDevice(PSF_DEVICENAME, new Iop::Ioman::CPsf(m_fileSystem));
|
m_bios->GetIoman()->RegisterDevice(PSF_DEVICENAME, new Iop::Ioman::CPsf(m_fileSystem));
|
||||||
|
m_bios->GetIoman()->RegisterDevice("host0", new Iop::Ioman::CPsf(m_fileSystem));
|
||||||
m_bios->LoadAndStartModule(execPath.c_str(), NULL, 0);
|
m_bios->LoadAndStartModule(execPath.c_str(), NULL, 0);
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@ -65,9 +75,10 @@ m_singleStep(false)
|
|||||||
|
|
||||||
CPsfVm::~CPsfVm()
|
CPsfVm::~CPsfVm()
|
||||||
{
|
{
|
||||||
|
Pause();
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
m_cpu.m_Functions.Serialize("functions.bin");
|
// m_cpu.m_Functions.Serialize("functions.bin");
|
||||||
m_cpu.m_Comments.Serialize("comments.bin");
|
// m_cpu.m_Comments.Serialize("comments.bin");
|
||||||
#endif
|
#endif
|
||||||
delete m_bios;
|
delete m_bios;
|
||||||
delete [] m_ram;
|
delete [] m_ram;
|
||||||
@ -118,6 +129,14 @@ unsigned int CPsfVm::TickFunctionStub(unsigned int ticks, CMIPS* context)
|
|||||||
|
|
||||||
unsigned int CPsfVm::TickFunction(unsigned int ticks)
|
unsigned int CPsfVm::TickFunction(unsigned int ticks)
|
||||||
{
|
{
|
||||||
|
if(m_cpu.m_State.nGPR[CMIPS::RA].nV0 > 0x1FC00000)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(m_cpu.m_State.nPC > 0x1FC00000)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
if(m_cpu.MustBreak())
|
if(m_cpu.MustBreak())
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@ -130,17 +149,53 @@ void CPsfVm::SysCallHandlerStub(CMIPS* state)
|
|||||||
reinterpret_cast<CPsfVm*>(state->m_handlerParam)->m_bios->SysCallHandler();
|
reinterpret_cast<CPsfVm*>(state->m_handlerParam)->m_bios->SysCallHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPsfVm::ProcessTimer()
|
||||||
|
{
|
||||||
|
static clock_t timerValue = 0;
|
||||||
|
if(timerValue == 0)
|
||||||
|
{
|
||||||
|
timerValue = clock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(clock() - timerValue > 2 * CLOCKS_PER_SEC)
|
||||||
|
{
|
||||||
|
m_intc.AssertLine(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPsfVm::CheckInterrupts()
|
||||||
|
{
|
||||||
|
if(m_intc.HasPendingInterrupt())
|
||||||
|
{
|
||||||
|
if(m_cpu.GenerateInterrupt(0x1FC00000))
|
||||||
|
{
|
||||||
|
m_cpu.m_State.nHasException = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPsfVm::EmulationProc()
|
void CPsfVm::EmulationProc()
|
||||||
{
|
{
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
if(m_status == RUNNING)
|
if(m_status == RUNNING)
|
||||||
{
|
{
|
||||||
RET_CODE returnCode = m_cpu.Execute(m_singleStep ? 1 : 1000);
|
RET_CODE returnCode = RET_CODE_QUOTADONE;
|
||||||
if(m_cpu.m_State.nCOP0[CCOP_SCU::EPC] != 0)
|
ProcessTimer();
|
||||||
|
if(!m_cpu.m_State.nHasException)
|
||||||
|
{
|
||||||
|
CheckInterrupts();
|
||||||
|
}
|
||||||
|
if(!m_cpu.m_State.nHasException)
|
||||||
|
{
|
||||||
|
returnCode = m_cpu.Execute(m_singleStep ? 1 : 5000);
|
||||||
|
}
|
||||||
|
if(m_cpu.m_State.nHasException)
|
||||||
{
|
{
|
||||||
m_bios->SysCallHandler();
|
m_bios->SysCallHandler();
|
||||||
assert(m_cpu.m_State.nCOP0[CCOP_SCU::EPC] == 0);
|
assert(!m_cpu.m_State.nHasException);
|
||||||
}
|
}
|
||||||
if(returnCode == RET_CODE_BREAKPOINT || m_singleStep)
|
if(returnCode == RET_CODE_BREAKPOINT || m_singleStep)
|
||||||
{
|
{
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#include "MIPS.h"
|
#include "MIPS.h"
|
||||||
#include "PsfFs.h"
|
#include "PsfFs.h"
|
||||||
|
#include "Spu2.h"
|
||||||
#include "VirtualMachine.h"
|
#include "VirtualMachine.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include "IopBios.h"
|
#include "IopBios.h"
|
||||||
|
#include "Iop_Intc.h"
|
||||||
|
|
||||||
class CPsfVm : public CVirtualMachine
|
class CPsfVm : public CVirtualMachine
|
||||||
{
|
{
|
||||||
@ -26,16 +28,26 @@ private:
|
|||||||
RAMSIZE = 0x00400000,
|
RAMSIZE = 0x00400000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SPUADDRESS
|
||||||
|
{
|
||||||
|
SPUBEGIN = 0x1F800000,
|
||||||
|
SPUEND = 0x1F900800,
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned int TickFunctionStub(unsigned int, CMIPS*);
|
static unsigned int TickFunctionStub(unsigned int, CMIPS*);
|
||||||
unsigned int TickFunction(unsigned int);
|
unsigned int TickFunction(unsigned int);
|
||||||
static void SysCallHandlerStub(CMIPS*);
|
static void SysCallHandlerStub(CMIPS*);
|
||||||
|
|
||||||
|
void ProcessTimer();
|
||||||
|
void CheckInterrupts();
|
||||||
void EmulationProc();
|
void EmulationProc();
|
||||||
|
|
||||||
CMIPS m_cpu;
|
CMIPS m_cpu;
|
||||||
CPsfFs m_fileSystem;
|
CPsfFs m_fileSystem;
|
||||||
CIopBios* m_bios;
|
CIopBios* m_bios;
|
||||||
|
CSpu2 m_spu;
|
||||||
uint8* m_ram;
|
uint8* m_ram;
|
||||||
|
Iop::CIntc m_intc;
|
||||||
STATUS m_status;
|
STATUS m_status;
|
||||||
bool m_pauseAck;
|
bool m_pauseAck;
|
||||||
boost::thread* m_emuThread;
|
boost::thread* m_emuThread;
|
||||||
|
51
tools/PsfPlayer/Source/Spu2.cpp
Normal file
51
tools/PsfPlayer/Source/Spu2.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "Spu2.h"
|
||||||
|
#include "Log.h"
|
||||||
|
#include "lexical_cast_ex.h"
|
||||||
|
|
||||||
|
using namespace Spu2;
|
||||||
|
using namespace std;
|
||||||
|
using namespace Framework;
|
||||||
|
|
||||||
|
CSpu2::CSpu2(uint32 baseAddress) :
|
||||||
|
m_baseAddress(baseAddress)
|
||||||
|
{
|
||||||
|
m_cores.push_back(CCore(0, 0x100000));
|
||||||
|
m_cores.push_back(CCore(1, 0x100400));
|
||||||
|
}
|
||||||
|
|
||||||
|
CSpu2::~CSpu2()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 CSpu2::ReadRegister(uint32 address)
|
||||||
|
{
|
||||||
|
address -= m_baseAddress;
|
||||||
|
if(address > 0x100000)
|
||||||
|
{
|
||||||
|
unsigned int coreId = (address - 0x100000) >> 10;
|
||||||
|
if(coreId >= m_cores.size())
|
||||||
|
{
|
||||||
|
throw runtime_error("Invalid core identification.");
|
||||||
|
}
|
||||||
|
CCore& core(m_cores[coreId]);
|
||||||
|
return core.ReadRegister(address) | (core.ReadRegister(address + 2) << 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogRead(address);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSpu2::LogRead(uint32 address)
|
||||||
|
{
|
||||||
|
string readValue;
|
||||||
|
switch(address)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
readValue = "(Unknown @ 0x" + lexical_cast_hex<string>(address, 4) + ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CLog::GetInstance().Print("spu2", "Read : %s.\r\n", readValue.c_str());
|
||||||
|
}
|
25
tools/PsfPlayer/Source/Spu2.h
Normal file
25
tools/PsfPlayer/Source/Spu2.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef _SPU2_H_
|
||||||
|
#define _SPU2_H_
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Spu2_Core.h"
|
||||||
|
|
||||||
|
class CSpu2
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSpu2(uint32);
|
||||||
|
virtual ~CSpu2();
|
||||||
|
|
||||||
|
uint32 ReadRegister(uint32);
|
||||||
|
void WriteRegister(uint32, uint32);
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::vector<Spu2::CCore> CoreArrayType;
|
||||||
|
|
||||||
|
void LogRead(uint32);
|
||||||
|
|
||||||
|
uint32 m_baseAddress;
|
||||||
|
CoreArrayType m_cores;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
52
tools/PsfPlayer/Source/Spu2_Core.cpp
Normal file
52
tools/PsfPlayer/Source/Spu2_Core.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "lexical_cast_ex.h"
|
||||||
|
#include "Spu2_Core.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
using namespace Spu2;
|
||||||
|
using namespace std;
|
||||||
|
using namespace Framework;
|
||||||
|
|
||||||
|
CCore::CCore(unsigned int coreId, uint32 baseAddress) :
|
||||||
|
m_coreId(coreId),
|
||||||
|
m_baseAddress(baseAddress)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CCore::~CCore()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 CCore::ReadRegister(uint32 address)
|
||||||
|
{
|
||||||
|
address -= m_baseAddress;
|
||||||
|
uint16 result = 0;
|
||||||
|
switch(address)
|
||||||
|
{
|
||||||
|
case STATX:
|
||||||
|
result = 0x0000;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef _DEBUG
|
||||||
|
LogRead(address);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCore::LogRead(uint32 address)
|
||||||
|
{
|
||||||
|
string readValue;
|
||||||
|
switch(address)
|
||||||
|
{
|
||||||
|
case STATX:
|
||||||
|
readValue = "STATX";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
readValue = "(Unknown @ 0x" + lexical_cast_hex<string>(address, 4) + ")";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CLog::GetInstance().Print("spu2_core", "Core %i read : %s.\r\n", m_coreId, readValue.c_str());
|
||||||
|
}
|
29
tools/PsfPlayer/Source/Spu2_Core.h
Normal file
29
tools/PsfPlayer/Source/Spu2_Core.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _SPU2_CORE_H_
|
||||||
|
#define _SPU2_CORE_H_
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
namespace Spu2
|
||||||
|
{
|
||||||
|
class CCore
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCore(unsigned int, uint32);
|
||||||
|
virtual ~CCore();
|
||||||
|
|
||||||
|
uint16 ReadRegister(uint32);
|
||||||
|
void WriteRegister(uint32, uint16);
|
||||||
|
|
||||||
|
enum REGISTERS
|
||||||
|
{
|
||||||
|
STATX = 0x344,
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LogRead(uint32);
|
||||||
|
uint32 m_baseAddress;
|
||||||
|
unsigned int m_coreId;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,4 +1,5 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
#include "FunctionsView.h"
|
#include "FunctionsView.h"
|
||||||
#include "HorizontalLayout.h"
|
#include "HorizontalLayout.h"
|
||||||
#include "win32/LayoutWindow.h"
|
#include "win32/LayoutWindow.h"
|
||||||
@ -12,6 +13,7 @@
|
|||||||
|
|
||||||
using namespace Framework;
|
using namespace Framework;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace boost;
|
||||||
|
|
||||||
CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx)
|
CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx)
|
||||||
{
|
{
|
||||||
@ -62,7 +64,9 @@ CFunctionsView::CFunctionsView(HWND hParent, CMIPS* pCtx)
|
|||||||
m_pLayout->InsertObject(new Win32::CLayoutWindow(1, 1, 1, 1, m_pList));
|
m_pLayout->InsertObject(new Win32::CLayoutWindow(1, 1, 1, 1, m_pList));
|
||||||
m_pLayout->InsertObject(pSubLayout0);
|
m_pLayout->InsertObject(pSubLayout0);
|
||||||
|
|
||||||
SetSize(469, 612);
|
m_pCtx->m_Functions.m_OnTagListChanged.connect(bind(&CFunctionsView::Refresh, this));
|
||||||
|
|
||||||
|
SetSize(469, 612);
|
||||||
|
|
||||||
SetELF(NULL);
|
SetELF(NULL);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "MIPS.h"
|
#include "MIPS.h"
|
||||||
#include "ELF.h"
|
#include "ELF.h"
|
||||||
|
|
||||||
class CFunctionsView : public Framework::Win32::CWindow
|
class CFunctionsView : public Framework::Win32::CWindow, public boost::signals::trackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CFunctionsView(HWND, CMIPS*);
|
CFunctionsView(HWND, CMIPS*);
|
||||||
|
@ -7,15 +7,19 @@
|
|||||||
#define WNDSTYLE (WS_CAPTION | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU)
|
#define WNDSTYLE (WS_CAPTION | WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU)
|
||||||
#define WNDSTYLEEX (0)
|
#define WNDSTYLEEX (0)
|
||||||
|
|
||||||
|
#define ID_VM_PAUSE (0xBEEF)
|
||||||
|
|
||||||
using namespace Framework;
|
using namespace Framework;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
CMiniDebugger::CMiniDebugger(CPsfVm& virtualMachine) :
|
CMiniDebugger::CMiniDebugger(CPsfVm& virtualMachine) :
|
||||||
m_virtualMachine(virtualMachine),
|
m_virtualMachine(virtualMachine),
|
||||||
m_functionsView(NULL),
|
m_functionsView(NULL),
|
||||||
m_splitter(NULL),
|
m_mainSplitter(NULL),
|
||||||
|
m_subSplitter(NULL),
|
||||||
m_disAsmView(NULL),
|
m_disAsmView(NULL),
|
||||||
m_registerView(NULL)
|
m_registerView(NULL),
|
||||||
|
m_memoryView(NULL)
|
||||||
{
|
{
|
||||||
if(!DoesWindowClassExist(CLSNAME))
|
if(!DoesWindowClassExist(CLSNAME))
|
||||||
{
|
{
|
||||||
@ -36,18 +40,24 @@ m_registerView(NULL)
|
|||||||
Center();
|
Center();
|
||||||
CreateAccelerators();
|
CreateAccelerators();
|
||||||
|
|
||||||
m_splitter = new Win32::CHorizontalSplitter(m_hWnd, GetClientRect());
|
m_mainSplitter = new Win32::CVerticalSplitter(m_hWnd, GetClientRect());
|
||||||
m_disAsmView = new CDisAsm(m_splitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_virtualMachine.GetCpu());
|
|
||||||
m_registerView = new CRegViewGeneral(m_splitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_virtualMachine.GetCpu());
|
m_subSplitter = new Win32::CHorizontalSplitter(m_mainSplitter->m_hWnd, GetClientRect());
|
||||||
|
m_memoryView = new CMemoryViewMIPS(m_mainSplitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_virtualMachine.GetCpu());
|
||||||
|
|
||||||
|
m_disAsmView = new CDisAsm(m_subSplitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_virtualMachine.GetCpu());
|
||||||
|
m_registerView = new CRegViewGeneral(m_subSplitter->m_hWnd, Win32::CRect(0, 0, 1, 1), m_virtualMachine, &m_virtualMachine.GetCpu());
|
||||||
m_registerView->Show(SW_SHOW);
|
m_registerView->Show(SW_SHOW);
|
||||||
|
|
||||||
m_functionsView = new CFunctionsView(NULL, &m_virtualMachine.GetCpu());
|
m_functionsView = new CFunctionsView(NULL, &m_virtualMachine.GetCpu());
|
||||||
m_functionsView->m_OnFunctionDblClick.connect(bind(&CMiniDebugger::OnFunctionDblClick, this, _1));
|
m_functionsView->m_OnFunctionDblClick.connect(bind(&CMiniDebugger::OnFunctionDblClick, this, _1));
|
||||||
m_functionsView->Refresh();
|
m_functionsView->Refresh();
|
||||||
|
|
||||||
m_splitter->SetChild(0, *m_disAsmView);
|
m_subSplitter->SetChild(0, *m_disAsmView);
|
||||||
m_splitter->SetChild(1, *m_registerView);
|
m_subSplitter->SetChild(1, *m_registerView);
|
||||||
m_splitter->SetEdgePosition(0.675);
|
m_subSplitter->SetEdgePosition(0.675);
|
||||||
|
m_mainSplitter->SetChild(0, *m_subSplitter);
|
||||||
|
m_mainSplitter->SetChild(1, *m_memoryView);
|
||||||
m_disAsmView->SetAddress(m_virtualMachine.GetCpu().m_State.nPC);
|
m_disAsmView->SetAddress(m_virtualMachine.GetCpu().m_State.nPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +66,8 @@ CMiniDebugger::~CMiniDebugger()
|
|||||||
delete m_functionsView;
|
delete m_functionsView;
|
||||||
delete m_disAsmView;
|
delete m_disAsmView;
|
||||||
delete m_registerView;
|
delete m_registerView;
|
||||||
delete m_splitter;
|
delete m_mainSplitter;
|
||||||
|
delete m_subSplitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMiniDebugger::Run()
|
void CMiniDebugger::Run()
|
||||||
@ -83,6 +94,9 @@ long CMiniDebugger::OnCommand(unsigned short command, unsigned short id, HWND hw
|
|||||||
case ID_VM_RESUME:
|
case ID_VM_RESUME:
|
||||||
m_virtualMachine.Resume();
|
m_virtualMachine.Resume();
|
||||||
break;
|
break;
|
||||||
|
case ID_VM_PAUSE:
|
||||||
|
m_virtualMachine.Pause();
|
||||||
|
break;
|
||||||
case ID_VIEW_FUNCTIONS:
|
case ID_VIEW_FUNCTIONS:
|
||||||
if(m_functionsView != NULL)
|
if(m_functionsView != NULL)
|
||||||
{
|
{
|
||||||
@ -114,7 +128,7 @@ void CMiniDebugger::OnFunctionDblClick(uint32 address)
|
|||||||
|
|
||||||
void CMiniDebugger::CreateAccelerators()
|
void CMiniDebugger::CreateAccelerators()
|
||||||
{
|
{
|
||||||
ACCEL Accel[10];
|
ACCEL Accel[11];
|
||||||
|
|
||||||
Accel[0].cmd = ID_VM_SAVESTATE;
|
Accel[0].cmd = ID_VM_SAVESTATE;
|
||||||
Accel[0].key = VK_F7;
|
Accel[0].key = VK_F7;
|
||||||
@ -156,5 +170,9 @@ void CMiniDebugger::CreateAccelerators()
|
|||||||
Accel[9].key = 'T';
|
Accel[9].key = 'T';
|
||||||
Accel[9].fVirt = FCONTROL | FVIRTKEY;
|
Accel[9].fVirt = FCONTROL | FVIRTKEY;
|
||||||
|
|
||||||
|
Accel[10].cmd = ID_VM_PAUSE;
|
||||||
|
Accel[10].key = VK_F6;
|
||||||
|
Accel[10].fVirt = FVIRTKEY;
|
||||||
|
|
||||||
m_acceleratorTable = CreateAcceleratorTable(Accel, sizeof(Accel) / sizeof(ACCEL));
|
m_acceleratorTable = CreateAcceleratorTable(Accel, sizeof(Accel) / sizeof(ACCEL));
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
|
|
||||||
#include "win32/Window.h"
|
#include "win32/Window.h"
|
||||||
#include "win32/HorizontalSplitter.h"
|
#include "win32/HorizontalSplitter.h"
|
||||||
|
#include "win32/VerticalSplitter.h"
|
||||||
#include "win32ui/DisAsm.h"
|
#include "win32ui/DisAsm.h"
|
||||||
#include "win32ui/RegViewGeneral.h"
|
#include "win32ui/RegViewGeneral.h"
|
||||||
|
#include "win32ui/MemoryViewMIPS.h"
|
||||||
#include "FunctionsView.h"
|
#include "FunctionsView.h"
|
||||||
#include "../PsfVm.h"
|
#include "../PsfVm.h"
|
||||||
|
|
||||||
@ -24,9 +26,11 @@ private:
|
|||||||
void OnFunctionDblClick(uint32);
|
void OnFunctionDblClick(uint32);
|
||||||
|
|
||||||
CPsfVm& m_virtualMachine;
|
CPsfVm& m_virtualMachine;
|
||||||
Framework::Win32::CHorizontalSplitter* m_splitter;
|
Framework::Win32::CHorizontalSplitter* m_subSplitter;
|
||||||
|
Framework::Win32::CVerticalSplitter* m_mainSplitter;
|
||||||
CDisAsm* m_disAsmView;
|
CDisAsm* m_disAsmView;
|
||||||
CRegViewGeneral* m_registerView;
|
CRegViewGeneral* m_registerView;
|
||||||
|
CMemoryViewMIPS* m_memoryView;
|
||||||
CFunctionsView* m_functionsView;
|
CFunctionsView* m_functionsView;
|
||||||
HACCEL m_acceleratorTable;
|
HACCEL m_acceleratorTable;
|
||||||
};
|
};
|
||||||
|
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user