git-svn-id: http://svn.purei.org/purei/trunk@177 b36208d7-6611-0410-8bec-b1987f11c4a2

This commit is contained in:
jpd002 2007-11-22 19:49:07 +00:00
parent 25ca7a6144
commit 3eefc47451
41 changed files with 1481 additions and 84 deletions

View File

@ -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="&quot;$(FrameworkRoot)/include&quot;;&quot;$(SolutionDir)/source&quot;"
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"
> >

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

View 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

View File

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

View File

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

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

View 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

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

View 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

View File

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

View File

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

View File

@ -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());
} }

View File

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

View File

@ -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);

View File

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

View File

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

View File

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

View File

@ -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, &param);
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);
}

View File

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

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

View 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

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

View 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

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

View 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

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

View 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

View File

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

View File

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

View File

@ -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)
{ {

View File

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

View 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());
}

View 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

View 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());
}

View 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

View File

@ -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);

View File

@ -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*);

View File

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

View File

@ -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.