mirror of
https://github.com/libretro/Play-.git
synced 2024-11-27 18:50:28 +00:00
Even more conversion done for quake.elf (SIF/IOP overhaul)
git-svn-id: http://svn.purei.org/purei/trunk@224 b36208d7-6611-0410-8bec-b1987f11c4a2
This commit is contained in:
parent
07657fd612
commit
669ac71159
344
Purei.vcproj
344
Purei.vcproj
@ -956,158 +956,6 @@
|
||||
RelativePath=".\Source\INTC.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Cdvdfsv.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_DbcMan.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Dummy.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_FileIO.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_LibSD.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_LoadFile.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_McServ.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_PadMan.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_SysMem.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Unknown.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IPU.cpp"
|
||||
>
|
||||
@ -1526,50 +1374,6 @@
|
||||
RelativePath=".\Source\Integer64.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Cdvdfsv.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_DbcMan.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Dummy.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_FileIO.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_LibSD.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_LoadFile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_McServ.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Module.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_PadMan.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_SysMem.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IOP_Unknown.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\IPU.h"
|
||||
>
|
||||
@ -1698,6 +1502,10 @@
|
||||
RelativePath=".\Source\Profiler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\Ps2Const.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\PS2OS.h"
|
||||
>
|
||||
@ -1730,6 +1538,10 @@
|
||||
RelativePath=".\Source\SIF.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\SifModule.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\ThreadMsg.h"
|
||||
>
|
||||
@ -1887,6 +1699,146 @@
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="IOP"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Source\iop\ArgumentIterator.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\ArgumentIterator.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\DirectoryDevice.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\DirectoryDevice.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Ioman_Device.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Dynamic.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Dynamic.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Intc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Intc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Intrman.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Intrman.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Ioman.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Ioman.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Loadcore.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Loadcore.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Modload.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Modload.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Module.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Stdio.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Stdio.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Sysclib.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Sysclib.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Sysmem.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Sysmem.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thbase.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thbase.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thevent.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thevent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thsema.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Thsema.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Timrman.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\Iop_Timrman.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\IopBios.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Source\iop\IopBios.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\Source\win32ui\shaders\TexClamp.frag"
|
||||
|
@ -170,34 +170,22 @@ void CCOP_FPU::BC1F()
|
||||
//01
|
||||
void CCOP_FPU::BC1T()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
Branch(true);
|
||||
}
|
||||
CCodeGen::End();
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
BranchEx(true);
|
||||
}
|
||||
|
||||
//02
|
||||
void CCOP_FPU::BC1FL()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
BranchLikely(false);
|
||||
}
|
||||
CCodeGen::End();
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
BranchLikelyEx(false);
|
||||
}
|
||||
|
||||
//03
|
||||
void CCOP_FPU::BC1TL()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
BranchLikely(true);
|
||||
}
|
||||
CCodeGen::End();
|
||||
TestCCBit(m_nCCMask[(m_nOpcode >> 18) & 0x07]);
|
||||
BranchLikelyEx(true);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
@ -383,15 +371,12 @@ void CCOP_FPU::C_LT_S()
|
||||
//36
|
||||
void CCOP_FPU::C_LE_S()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
CFPU::PushSingle(&m_pCtx->m_State.nCOP10[m_nFT * 2]);
|
||||
CFPU::PushSingle(&m_pCtx->m_State.nCOP10[m_nFS * 2]);
|
||||
CFPU::Cmp(CCodeGen::CONDITION_BE);
|
||||
m_codeGen->FP_PushSingle(offsetof(CMIPS, m_State.nCOP10[m_nFT * 2]));
|
||||
m_codeGen->FP_PushSingle(offsetof(CMIPS, m_State.nCOP10[m_nFS * 2]));
|
||||
|
||||
SetCCBit(true, m_nCCMask[((m_nOpcode >> 8) & 0x07)]);
|
||||
}
|
||||
CCodeGen::End();
|
||||
m_codeGen->FP_Cmp(CCodeGen::CONDITION_BE);
|
||||
|
||||
SetCCBit(true, m_nCCMask[((m_nOpcode >> 8) & 0x07)]);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -2052,6 +2052,36 @@ void CCodeGen::Shl64(uint8 nAmount)
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::Sra()
|
||||
{
|
||||
if(FitsPattern<RelativeRelative>())
|
||||
{
|
||||
RelativeRelative::PatternValue ops = GetPattern<RelativeRelative>();
|
||||
unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT);
|
||||
unsigned int resultRegister = AllocateRegister();
|
||||
LoadRelativeInRegister(resultRegister, ops.first);
|
||||
LoadRelativeInRegister(shiftAmount, ops.second);
|
||||
m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister]));
|
||||
FreeRegister(shiftAmount);
|
||||
PushReg(resultRegister);
|
||||
}
|
||||
else if(FitsPattern<ConstantRelative>())
|
||||
{
|
||||
ConstantRelative::PatternValue ops = GetPattern<ConstantRelative>();
|
||||
unsigned int shiftAmount = AllocateRegister(REGISTER_SHIFTAMOUNT);
|
||||
unsigned int resultRegister = AllocateRegister();
|
||||
LoadConstantInRegister(resultRegister, ops.first);
|
||||
LoadRelativeInRegister(shiftAmount, ops.second);
|
||||
m_Assembler.SarEd(CX86Assembler::MakeRegisterAddress(m_nRegisterLookupEx[resultRegister]));
|
||||
FreeRegister(shiftAmount);
|
||||
PushReg(resultRegister);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::Sra(uint8 nAmount)
|
||||
{
|
||||
if(FitsPattern<SingleRegister>())
|
||||
@ -2062,7 +2092,7 @@ void CCodeGen::Sra(uint8 nAmount)
|
||||
}
|
||||
else if(FitsPattern<SingleRelative>())
|
||||
{
|
||||
UnaryRelativeSelfCallAsRegister(bind(&CCodeGen::Sra, nAmount));
|
||||
UnaryRelativeSelfCallAsRegister(bind(&CCodeGen::Sra, this, nAmount));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -119,8 +119,9 @@ public:
|
||||
void Shl(uint8);
|
||||
static void Shl64();
|
||||
void Shl64(uint8);
|
||||
static void Sra(uint8);
|
||||
static void Sra64(uint8);
|
||||
void Sra();
|
||||
void Sra(uint8);
|
||||
void Sra64(uint8);
|
||||
void Srl();
|
||||
void Srl(uint8);
|
||||
static void Srl64();
|
||||
@ -145,14 +146,16 @@ public:
|
||||
void FP_Neg();
|
||||
|
||||
//SIMD (128-bits only)
|
||||
void MD_PushRel(size_t);
|
||||
void MD_PullRel(size_t);
|
||||
virtual void MD_PushRel(size_t);
|
||||
virtual void MD_PullRel(size_t);
|
||||
void MD_PushReg(XMMREGISTER);
|
||||
|
||||
void MD_And();
|
||||
void MD_Not();
|
||||
void MD_Or();
|
||||
void MD_SubB();
|
||||
void MD_SubW();
|
||||
void MD_Xor();
|
||||
|
||||
void SetStream(Framework::CStream*);
|
||||
static CX86Assembler m_Assembler;
|
||||
|
@ -368,15 +368,18 @@ void CCodeGen::FP_Cmp(CCodeGen::CONDITION condition)
|
||||
case CONDITION_BL:
|
||||
conditionCode = CX86Assembler::SSE_CMP_LT;
|
||||
break;
|
||||
case CONDITION_BE:
|
||||
conditionCode = CX86Assembler::SSE_CMP_LE;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
XMMREGISTER tempResultRegister = AllocateXmmRegister();
|
||||
unsigned int resultRegister = AllocateRegister();
|
||||
FP_LoadSingleRelativeInRegister(tempResultRegister, ops.first);
|
||||
FP_LoadSingleRelativeInRegister(tempResultRegister, ops.second);
|
||||
m_Assembler.CmpssEd(tempResultRegister,
|
||||
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second),
|
||||
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.first),
|
||||
conditionCode);
|
||||
//Can't move directly to register using MOVSS, so we use CVTTSS2SI
|
||||
//0x00000000 -- CVT -> zero
|
||||
|
@ -2,20 +2,20 @@
|
||||
#include "CodeGen.h"
|
||||
#include "CodeGen_StackPatterns.h"
|
||||
|
||||
bool CCodeGen::Register128HasNextUse(XMMREGISTER registerId)
|
||||
{
|
||||
unsigned int nCount = m_Shadow.GetCount();
|
||||
|
||||
for(unsigned int i = 0; i < nCount; i += 2)
|
||||
{
|
||||
if(m_Shadow.GetAt(i) == REGISTER128)
|
||||
{
|
||||
if(m_Shadow.GetAt(i + 1) == registerId) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
bool CCodeGen::Register128HasNextUse(XMMREGISTER registerId)
|
||||
{
|
||||
unsigned int nCount = m_Shadow.GetCount();
|
||||
|
||||
for(unsigned int i = 0; i < nCount; i += 2)
|
||||
{
|
||||
if(m_Shadow.GetAt(i) == REGISTER128)
|
||||
{
|
||||
if(m_Shadow.GetAt(i + 1) == registerId) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CCodeGen::LoadRelative128InRegister(XMMREGISTER registerId, uint32 offset)
|
||||
{
|
||||
@ -119,3 +119,37 @@ void CCodeGen::MD_SubB()
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::MD_SubW()
|
||||
{
|
||||
if(FitsPattern<RelativeRelative128>())
|
||||
{
|
||||
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
||||
XMMREGISTER resultRegister = AllocateXmmRegister();
|
||||
LoadRelative128InRegister(resultRegister, ops.first);
|
||||
m_Assembler.PsubdVo(resultRegister,
|
||||
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second));
|
||||
MD_PushReg(resultRegister);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeGen::MD_Xor()
|
||||
{
|
||||
if(FitsPattern<RelativeRelative128>())
|
||||
{
|
||||
RelativeRelative128::PatternValue ops(GetPattern<RelativeRelative128>());
|
||||
XMMREGISTER resultRegister = AllocateXmmRegister();
|
||||
LoadRelative128InRegister(resultRegister, ops.first);
|
||||
m_Assembler.PxorVo(resultRegister,
|
||||
CX86Assembler::MakeIndRegOffAddress(g_nBaseRegister, ops.second));
|
||||
MD_PushReg(resultRegister);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include "PS2VM.h"
|
||||
#include "DMAC.h"
|
||||
#include "INTC.h"
|
||||
#include "GIF.h"
|
||||
#include "SIF.h"
|
||||
#include "Ps2Const.h"
|
||||
#include "Profiler.h"
|
||||
#include "Log.h"
|
||||
#include "RegisterStateFile.h"
|
||||
@ -143,11 +143,11 @@ uint32 CDMAC::ResumeDMA3(void* pBuffer, uint32 nSize)
|
||||
|
||||
if(m_D3_MADR & 0x80000000)
|
||||
{
|
||||
pDst = m_spr + (m_D3_MADR & (CPS2VM::SPRSIZE - 1));
|
||||
pDst = m_spr + (m_D3_MADR & (PS2::SPRSIZE - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
pDst = m_ram + (m_D3_MADR & (CPS2VM::RAMSIZE - 1));
|
||||
pDst = m_ram + (m_D3_MADR & (PS2::EERAMSIZE - 1));
|
||||
}
|
||||
|
||||
memcpy(pDst, pBuffer, nSize * 0x10);
|
||||
@ -212,8 +212,8 @@ uint32 CDMAC::ReceiveSPRDMA(uint32 nSrcAddress, uint32 nCount, bool nTagIncluded
|
||||
assert(nTagIncluded == false);
|
||||
|
||||
nDstAddress = m_D9_SADR;
|
||||
nDstAddress &= (CPS2VM::SPRSIZE - 1);
|
||||
nSrcAddress &= (CPS2VM::RAMSIZE - 1);
|
||||
nDstAddress &= (PS2::SPRSIZE - 1);
|
||||
nSrcAddress &= (PS2::EERAMSIZE - 1);
|
||||
|
||||
memcpy(m_spr + nDstAddress, m_ram + nSrcAddress, nCount * 0x10);
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <algorithm>
|
||||
#include "GIF.h"
|
||||
#include "uint128.h"
|
||||
#include "PS2VM.h"
|
||||
#include "Ps2Const.h"
|
||||
#include "Profiler.h"
|
||||
#include "Log.h"
|
||||
|
||||
@ -283,7 +283,7 @@ uint32 CGIF::ReceiveDMA(uint32 nAddress, uint32 nQWC, uint32 unused, bool nTagIn
|
||||
if(nAddress & 0x80000000)
|
||||
{
|
||||
pMemory = m_spr;
|
||||
nAddress &= CPS2VM::SPRSIZE - 1;
|
||||
nAddress &= PS2::SPRSIZE - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1155,6 +1155,8 @@ void CGSH_OpenGL::DisplayTransferedImage(uint32 nAddress)
|
||||
glBindTexture(GL_TEXTURE_2D, NULL);
|
||||
|
||||
glDeleteTextures(1, &nTexture);
|
||||
|
||||
FlipImpl();
|
||||
}
|
||||
|
||||
void CGSH_OpenGL::SetVBlank()
|
||||
|
@ -1,374 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "IOP_Cdvdfsv.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
uint32 CCdvdfsv::m_nStreamPos = 0;
|
||||
|
||||
CCdvdfsv::CCdvdfsv(uint32 nID)
|
||||
{
|
||||
m_nID = nID;
|
||||
}
|
||||
|
||||
CCdvdfsv::~CCdvdfsv()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(m_nID)
|
||||
{
|
||||
case MODULE_ID_1:
|
||||
Invoke592(nMethod, pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case MODULE_ID_2:
|
||||
Invoke593(nMethod, pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case MODULE_ID_4:
|
||||
Invoke595(nMethod, pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case MODULE_ID_6:
|
||||
Invoke597(nMethod, pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case MODULE_ID_7:
|
||||
Invoke59C(nMethod, pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::SaveState(CStream* pStream)
|
||||
{
|
||||
if(m_nID != MODULE_ID_1) return;
|
||||
|
||||
pStream->Write(&m_nStreamPos, 4);
|
||||
}
|
||||
|
||||
void CCdvdfsv::LoadState(CStream* pStream)
|
||||
{
|
||||
if(m_nID != MODULE_ID_1) return;
|
||||
|
||||
pStream->Read(&m_nStreamPos, 4);
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke592(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0:
|
||||
//Init
|
||||
uint32 nMode;
|
||||
|
||||
assert(nArgsSize >= 4);
|
||||
assert(nRetSize >= 0x10);
|
||||
|
||||
nMode = ((uint32*)pArgs)[0x00];
|
||||
|
||||
Log("Init(mode = %i);\r\n", nMode);
|
||||
|
||||
((uint32*)pRet)[0x03] = 0xFF;
|
||||
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke593(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x03:
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("GetDiskType();\r\n");
|
||||
|
||||
//Returns PS2DVD for now.
|
||||
((uint32*)pRet)[0x00] = 0x14;
|
||||
|
||||
break;
|
||||
|
||||
case 0x04:
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("GetError();\r\n");
|
||||
|
||||
((uint32*)pRet)[0x00] = 0x00;
|
||||
break;
|
||||
|
||||
case 0x0C:
|
||||
//Status
|
||||
//Returns
|
||||
//0 - Stopped
|
||||
//1 - Open
|
||||
//2 - Spin
|
||||
//3 - Read
|
||||
//and more...
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("Status();\r\n");
|
||||
|
||||
((uint32*)pRet)[0x00] = 0;
|
||||
|
||||
break;
|
||||
case 0x22:
|
||||
//Set Media Mode (1 - CDROM, 2 - DVDROM)
|
||||
uint32 nMode;
|
||||
|
||||
assert(nArgsSize >= 4);
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
nMode = ((uint32*)pArgs)[0x00];
|
||||
|
||||
Log("SetMediaMode(mode = %i);\r\n", nMode);
|
||||
|
||||
((uint32*)pRet)[0x00] = 1;
|
||||
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke595(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 1:
|
||||
Read(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 4:
|
||||
//GetToc
|
||||
uint32 nBuffer;
|
||||
|
||||
assert(nArgsSize >= 4);
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
nBuffer = ((uint32*)pArgs)[0x00];
|
||||
|
||||
Log("GetToc(buffer = 0x%0.8X);\r\n", nBuffer);
|
||||
|
||||
((uint32*)pRet)[0x00] = 1;
|
||||
break;
|
||||
case 9:
|
||||
StreamCmd(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x0E:
|
||||
//DiskReady (returns 2 if ready, 6 if not ready)
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
Log("NDiskReady();\r\n");
|
||||
|
||||
((uint32*)pRet)[0x00] = 2;
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke597(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0:
|
||||
SearchFile(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::Invoke59C(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0:
|
||||
//DiskReady (returns 2 if ready, 6 if not ready)
|
||||
|
||||
uint32 nMode;
|
||||
|
||||
assert(nRetSize >= 4);
|
||||
assert(nArgsSize >= 4);
|
||||
|
||||
nMode = ((uint32*)pArgs)[0x00];
|
||||
|
||||
Log("DiskReady(mode = %i);\r\n", nMode);
|
||||
|
||||
((uint32*)pRet)[0x00] = 2;
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X, 0x%0.8X).\r\n", m_nID, nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::Read(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nSector, nCount, nDstAddr, nMode;
|
||||
unsigned int i;
|
||||
|
||||
nSector = ((uint32*)pArgs)[0x00];
|
||||
nCount = ((uint32*)pArgs)[0x01];
|
||||
nDstAddr = ((uint32*)pArgs)[0x02];
|
||||
nMode = ((uint32*)pArgs)[0x04];
|
||||
|
||||
Log("Read(sector = 0x%0.8X, count = 0x%0.8X, addr = 0x%0.8X, mode = 0x%0.8X);\r\n", \
|
||||
nSector,
|
||||
nCount,
|
||||
nDstAddr,
|
||||
nMode);
|
||||
|
||||
for(i = 0; i < nCount; i++)
|
||||
{
|
||||
CPS2VM::m_pCDROM0->ReadBlock(nSector + i, CPS2VM::m_pRAM + (nDstAddr + (i * 0x800)));
|
||||
}
|
||||
|
||||
if(nRetSize >= 4)
|
||||
{
|
||||
((uint32*)pRet)[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::StreamCmd(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nSector, nCount, nDstAddr, nCmd, nMode, i;
|
||||
|
||||
nSector = ((uint32*)pArgs)[0x00];
|
||||
nCount = ((uint32*)pArgs)[0x01];
|
||||
nDstAddr = ((uint32*)pArgs)[0x02];
|
||||
nCmd = ((uint32*)pArgs)[0x03];
|
||||
nMode = ((uint32*)pArgs)[0x04];
|
||||
|
||||
Log("StreamCmd(sector = 0x%0.8X, count = 0x%0.8X, addr = 0x%0.8X, cmd = 0x%0.8X);\r\n", \
|
||||
nSector,
|
||||
nCount,
|
||||
nDstAddr,
|
||||
nMode);
|
||||
|
||||
switch(nCmd)
|
||||
{
|
||||
case 1:
|
||||
//Start
|
||||
m_nStreamPos = nSector;
|
||||
((uint32*)pRet)[0] = 1;
|
||||
|
||||
Log("StreamStart(pos = 0x%0.8X);\r\n", \
|
||||
nSector);
|
||||
break;
|
||||
case 2:
|
||||
//Read
|
||||
nDstAddr &= (CPS2VM::RAMSIZE - 1);
|
||||
|
||||
for(i = 0; i < nCount; i++)
|
||||
{
|
||||
CPS2VM::m_pCDROM0->ReadBlock(m_nStreamPos, CPS2VM::m_pRAM + (nDstAddr + (i * 0x800)));
|
||||
m_nStreamPos++;
|
||||
}
|
||||
|
||||
((uint32*)pRet)[0] = nCount;
|
||||
|
||||
Log("StreamRead(count = 0x%0.8X, dest = 0x%0.8X);\r\n", \
|
||||
nCount, \
|
||||
nDstAddr);
|
||||
break;
|
||||
case 5:
|
||||
//Init
|
||||
((uint32*)pRet)[0] = 1;
|
||||
|
||||
Log("StreamInit(bufsize = 0x%0.8X, numbuf = 0x%0.8X, buf = 0x%0.8X);\r\n", \
|
||||
nSector, \
|
||||
nCount, \
|
||||
nDstAddr);
|
||||
break;
|
||||
case 4:
|
||||
case 9:
|
||||
//Seek
|
||||
m_nStreamPos = nSector;
|
||||
((uint32*)pRet)[0] = 1;
|
||||
|
||||
Log("StreamSeek(pos = 0x%0.8X);\r\n", \
|
||||
nSector);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCdvdfsv::SearchFile(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
char* sPath;
|
||||
char* sTemp;
|
||||
char sFixedPath[256];
|
||||
CISO9660* pISO;
|
||||
ISO9660::CDirectoryRecord Record;
|
||||
|
||||
assert(nArgsSize >= 0x128);
|
||||
assert(nRetSize == 4);
|
||||
|
||||
pISO = CPS2VM::m_pCDROM0;
|
||||
if(pISO == NULL)
|
||||
{
|
||||
*(uint32*)pRet = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//0x12C structure
|
||||
//00 - Block Num
|
||||
//04 - Size
|
||||
//08
|
||||
//0C
|
||||
//10
|
||||
//14
|
||||
//18
|
||||
//1C
|
||||
//20 - Unknown
|
||||
//24 - Path
|
||||
|
||||
sPath = (char*)pArgs + 0x24;
|
||||
|
||||
strcpy(sFixedPath, sPath);
|
||||
|
||||
//Fix all slashes
|
||||
sTemp = strchr(sFixedPath, '\\');
|
||||
while(sTemp != NULL)
|
||||
{
|
||||
*sTemp = '/';
|
||||
sTemp = strchr(sTemp + 1, '\\');
|
||||
}
|
||||
|
||||
Log("SearchFile(path = %s);\r\n", sFixedPath);
|
||||
|
||||
if(!pISO->GetFileRecord(&Record, sFixedPath))
|
||||
{
|
||||
*(uint32*)pRet = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
((uint32*)pArgs)[0x00] = Record.GetPosition();
|
||||
((uint32*)pArgs)[0x01] = Record.GetDataLength();
|
||||
|
||||
*(uint32*)pRet = 1;
|
||||
}
|
||||
|
||||
void CCdvdfsv::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_Cdvdfsv: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
#ifndef _IOP_CDVDFSV_H_
|
||||
#define _IOP_CDVDFSV_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
|
||||
class CCdvdfsv : public CModule
|
||||
{
|
||||
public:
|
||||
CCdvdfsv(uint32);
|
||||
virtual ~CCdvdfsv();
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID_1 = 0x80000592,
|
||||
MODULE_ID_2 = 0x80000593,
|
||||
MODULE_ID_3 = 0x80000594,
|
||||
MODULE_ID_4 = 0x80000595,
|
||||
MODULE_ID_5 = 0x80000596,
|
||||
MODULE_ID_6 = 0x80000597,
|
||||
MODULE_ID_7 = 0x8000059C,
|
||||
};
|
||||
|
||||
private:
|
||||
void Invoke592(uint32, void*, uint32, void*, uint32);
|
||||
void Invoke593(uint32, void*, uint32, void*, uint32);
|
||||
void Invoke595(uint32, void*, uint32, void*, uint32);
|
||||
void Invoke597(uint32, void*, uint32, void*, uint32);
|
||||
void Invoke59C(uint32, void*, uint32, void*, uint32);
|
||||
|
||||
//Methods
|
||||
void Read(void*, uint32, void*, uint32);
|
||||
void StreamCmd(void*, uint32, void*, uint32);
|
||||
void SearchFile(void*, uint32, void*, uint32);
|
||||
|
||||
static void Log(const char*, ...);
|
||||
|
||||
uint32 m_nID;
|
||||
static uint32 m_nStreamPos;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,223 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "IOP_DbcMan.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
CDbcMan::CDbcMan()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CDbcMan::~CDbcMan()
|
||||
{
|
||||
DeleteAllSockets();
|
||||
}
|
||||
|
||||
void CDbcMan::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x80000901:
|
||||
CreateSocket(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x80000904:
|
||||
SetWorkAddr(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x8000091A:
|
||||
ReceiveData(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x80000963:
|
||||
GetVersionInformation(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CDbcMan::SaveState(CStream* pStream)
|
||||
{
|
||||
uint32 nCount, nID;
|
||||
SOCKET* pSocket;
|
||||
CList<SOCKET>::ITERATOR itSocket;
|
||||
|
||||
nCount = m_Socket.Count();
|
||||
pStream->Write(&nCount, 4);
|
||||
|
||||
for(itSocket = m_Socket.Begin(); itSocket.HasNext(); itSocket++)
|
||||
{
|
||||
nID = itSocket.GetKey();
|
||||
pSocket = (*itSocket);
|
||||
|
||||
pStream->Write(&nID, 4);
|
||||
pStream->Write(pSocket, sizeof(SOCKET));
|
||||
}
|
||||
}
|
||||
|
||||
void CDbcMan::LoadState(CStream* pStream)
|
||||
{
|
||||
uint32 nCount, nID, i;
|
||||
SOCKET* pSocket;
|
||||
|
||||
DeleteAllSockets();
|
||||
|
||||
pStream->Read(&nCount, 4);
|
||||
|
||||
for(i = 0; i < nCount; i++)
|
||||
{
|
||||
pSocket = new SOCKET;
|
||||
|
||||
pStream->Read(&nID, 4);
|
||||
pStream->Read(pSocket, sizeof(SOCKET));
|
||||
|
||||
m_Socket.Insert(pSocket, nID);
|
||||
}
|
||||
}
|
||||
|
||||
void CDbcMan::SetButtonState(unsigned int nPadNumber, CPadListener::BUTTON nButton, bool nPressed)
|
||||
{
|
||||
SOCKET* pSocket;
|
||||
CList<SOCKET>::ITERATOR itSocket;
|
||||
uint16 nStatus;
|
||||
|
||||
for(itSocket = m_Socket.Begin(); itSocket.HasNext(); itSocket++)
|
||||
{
|
||||
pSocket = (*itSocket);
|
||||
if(pSocket->nPort != nPadNumber) continue;
|
||||
|
||||
nStatus = (CPS2VM::m_pRAM[pSocket->nBuf1 + 0x1C] << 8) | (CPS2VM::m_pRAM[pSocket->nBuf1 + 0x1D]);
|
||||
|
||||
nStatus &= (~nButton);
|
||||
if(!nPressed)
|
||||
{
|
||||
nStatus |= nButton;
|
||||
}
|
||||
|
||||
CPS2VM::m_pRAM[pSocket->nBuf1 + 0x1C] = (uint8)(nStatus >> 8);
|
||||
CPS2VM::m_pRAM[pSocket->nBuf1 + 0x1D] = (uint8)(nStatus >> 0);
|
||||
|
||||
// *(uint16*)&CPS2VM::m_pRAM[pSocket->nBuf1 + 0x1C] ^= 0x2010;
|
||||
}
|
||||
}
|
||||
|
||||
void CDbcMan::CreateSocket(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nType1, nType2, nPort, nSlot, nBuf1, nBuf2, nID;
|
||||
SOCKET* pSocket;
|
||||
|
||||
assert(nArgsSize >= 0x30);
|
||||
assert(nRetSize >= 0x04);
|
||||
|
||||
nType1 = ((uint32*)pArgs)[0x00];
|
||||
nType2 = ((uint32*)pArgs)[0x01];
|
||||
nPort = ((uint32*)pArgs)[0x02];
|
||||
nSlot = ((uint32*)pArgs)[0x03];
|
||||
nBuf1 = ((uint32*)pArgs)[0x0A];
|
||||
nBuf2 = ((uint32*)pArgs)[0x0B];
|
||||
|
||||
pSocket = new SOCKET;
|
||||
pSocket->nPort = nPort;
|
||||
pSocket->nSlot = nSlot;
|
||||
pSocket->nBuf1 = nBuf1;
|
||||
pSocket->nBuf2 = nBuf2;
|
||||
|
||||
nID = m_Socket.MakeKey();
|
||||
m_Socket.Insert(pSocket, nID);
|
||||
|
||||
((uint32*)pRet)[0x09] = nID;
|
||||
|
||||
Log("CreateSocket(type1 = 0x%0.8X, type2 = 0x%0.8X, port = %i, slot = %i, buf1 = 0x%0.8X, buf2 = 0x%0.8X);\r\n", \
|
||||
nType1, \
|
||||
nType2, \
|
||||
nPort, \
|
||||
nSlot, \
|
||||
nBuf1, \
|
||||
nBuf2);
|
||||
}
|
||||
|
||||
void CDbcMan::SetWorkAddr(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nAddress;
|
||||
|
||||
assert(nArgsSize == 0x400);
|
||||
assert(nRetSize == 0x400);
|
||||
|
||||
//0 - Some number (0x0200) (size?)
|
||||
//1 - Address to bind with
|
||||
|
||||
nAddress = ((uint32*)pArgs)[1];
|
||||
|
||||
//Set Ready (?) status
|
||||
CPS2VM::m_pRAM[nAddress] = 1;
|
||||
|
||||
((uint32*)pRet)[0] = 0x00000000;
|
||||
|
||||
Log("SetWorkAddr(addr = 0x%0.8X);\r\n", nAddress);
|
||||
}
|
||||
|
||||
void CDbcMan::ReceiveData(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nParam, nFlags, nSocket;
|
||||
SOCKET* pSocket;
|
||||
|
||||
//Param Frame
|
||||
//0 - Socket ID
|
||||
//1 - Value passed in parameter to the library
|
||||
//2 - Some parameter (0x01, or some address)
|
||||
|
||||
nSocket = ((uint32*)pArgs)[0];
|
||||
nFlags = ((uint32*)pArgs)[1];
|
||||
nParam = ((uint32*)pArgs)[2];
|
||||
|
||||
pSocket = m_Socket.Find(nSocket);
|
||||
if(pSocket != NULL)
|
||||
{
|
||||
CPS2VM::m_pRAM[pSocket->nBuf1 + 0x02] = 0x20;
|
||||
*(uint32*)&CPS2VM::m_pRAM[pSocket->nBuf1 + 0x04] = 0x01;
|
||||
}
|
||||
|
||||
//Return frame
|
||||
//0 - Success Status
|
||||
//1 - ???
|
||||
//2 - Size of returned data
|
||||
//3+ - Data
|
||||
|
||||
((uint32*)pRet)[0] = 0;
|
||||
((uint32*)pRet)[2] = 0x1;
|
||||
((uint32*)pRet)[3] = 0x1;
|
||||
|
||||
Log("ReceiveData(socket = 0x%0.8X, flags = 0x%0.8X, param = 0x%0.8X);\r\n", nSocket, nFlags, nParam);
|
||||
}
|
||||
|
||||
void CDbcMan::GetVersionInformation(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nArgsSize == 0x400);
|
||||
assert(nRetSize == 0x400);
|
||||
|
||||
((uint32*)pRet)[0] = 0x00000200;
|
||||
|
||||
Log("GetVersionInformation();\r\n");
|
||||
}
|
||||
|
||||
void CDbcMan::DeleteAllSockets()
|
||||
{
|
||||
while(m_Socket.Count() != 0)
|
||||
{
|
||||
delete m_Socket.Pull();
|
||||
}
|
||||
}
|
||||
|
||||
void CDbcMan::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_DbcMan: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#ifndef _IOP_DBCMAN_H_
|
||||
#define _IOP_DBCMAN_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
#include "PadListener.h"
|
||||
#include "List.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
|
||||
class CDbcMan : public CModule, public CPadListener
|
||||
{
|
||||
public:
|
||||
CDbcMan();
|
||||
virtual ~CDbcMan();
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
virtual void SetButtonState(unsigned int, CPadListener::BUTTON, bool);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000900
|
||||
};
|
||||
|
||||
private:
|
||||
struct SOCKET
|
||||
{
|
||||
uint32 nPort;
|
||||
uint32 nSlot;
|
||||
uint32 nBuf1;
|
||||
uint32 nBuf2;
|
||||
};
|
||||
|
||||
void CreateSocket(void*, uint32, void*, uint32);
|
||||
void SetWorkAddr(void*, uint32, void*, uint32);
|
||||
void ReceiveData(void*, uint32, void*, uint32);
|
||||
void GetVersionInformation(void*, uint32, void*, uint32);
|
||||
|
||||
void DeleteAllSockets();
|
||||
|
||||
void Log(const char*, ...);
|
||||
|
||||
Framework::CList<SOCKET> m_Socket;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,29 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include "IOP_Dummy.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
void CDummy::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
((uint32*)pRet)[0] = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CDummy::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDummy::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#ifndef _IOP_DUMMY_H_
|
||||
#define _IOP_DUMMY_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CDummy : public CModule
|
||||
{
|
||||
public:
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x00000030,
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,378 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "IOP_FileIO.h"
|
||||
#include "PS2VM.h"
|
||||
#include "Config.h"
|
||||
#include "StdStream.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
CFileIO::CFileIO()
|
||||
{
|
||||
CConfig::GetInstance()->RegisterPreferenceBoolean("iop.fileio.stdlogging", false);
|
||||
CConfig::GetInstance()->RegisterPreferenceString("ps2.host.directory", "./vfs/host");
|
||||
CConfig::GetInstance()->RegisterPreferenceString("ps2.mc0.directory", "./vfs/mc0");
|
||||
CConfig::GetInstance()->RegisterPreferenceString("ps2.mc1.directory", "./vfs/mc1");
|
||||
|
||||
m_Device.Insert(new CDirectoryDevice("mc0", "ps2.mc0.directory"));
|
||||
m_Device.Insert(new CDirectoryDevice("host", "ps2.host.directory"));
|
||||
m_Device.Insert(new CCDROM0Device());
|
||||
|
||||
//Insert standard files if requested.
|
||||
if(CConfig::GetInstance()->GetPreferenceBoolean("iop.fileio.stdlogging"))
|
||||
{
|
||||
try
|
||||
{
|
||||
m_File.Insert(new CStdStream(fopen("ps2_stdout.txt", "ab")), 1);
|
||||
m_File.Insert(new CStdStream(fopen("ps2_stderr.txt", "ab")), 2);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
//Humm, some error occured when opening these files...
|
||||
}
|
||||
}
|
||||
|
||||
m_nFileID = 3;
|
||||
}
|
||||
|
||||
CFileIO::~CFileIO()
|
||||
{
|
||||
while(m_File.Count() != 0)
|
||||
{
|
||||
delete m_File.Pull();
|
||||
}
|
||||
while(m_Device.Count() != 0)
|
||||
{
|
||||
delete m_Device.Pull();
|
||||
}
|
||||
}
|
||||
|
||||
void CFileIO::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x00000000:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Open(*(uint32*)pArgs, ((char*)pArgs) + 4);
|
||||
break;
|
||||
case 0x00000001:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Close(*(uint32*)pArgs);
|
||||
break;
|
||||
case 0x00000002:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Read(((uint32*)pArgs)[0], ((uint32*)pArgs)[2], (void*)(CPS2VM::m_pRAM + ((uint32*)pArgs)[1]));
|
||||
break;
|
||||
case 0x00000003:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Write(((uint32*)pArgs)[0], ((uint32*)pArgs)[2], (void*)(CPS2VM::m_pRAM + ((uint32*)pArgs)[1]));
|
||||
break;
|
||||
case 0x00000004:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Seek(((uint32*)pArgs)[0], ((uint32*)pArgs)[1], ((uint32*)pArgs)[2]);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CFileIO::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CFileIO::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CStream* CFileIO::GetFile(uint32 nMode, const char* sPath)
|
||||
{
|
||||
char sDevice[256];
|
||||
char sDevicePath[256];
|
||||
CDevice* pDevice;
|
||||
|
||||
if(!SplitPath(sPath, sDevice, sDevicePath))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pDevice = FindDevice(sDevice);
|
||||
if(pDevice == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pDevice->OpenFile(nMode, sDevicePath);
|
||||
}
|
||||
|
||||
bool CFileIO::SplitPath(const char* sPath, char* sDevice, char* sDevicePath)
|
||||
{
|
||||
const char* sSplit;
|
||||
unsigned int nLenght;
|
||||
unsigned int nDevLenght;
|
||||
unsigned int nDevPathLenght;
|
||||
|
||||
nLenght = (unsigned int)strlen(sPath);
|
||||
sSplit = strchr(sPath, ':');
|
||||
if(sSplit == NULL)
|
||||
{
|
||||
//Invalid path
|
||||
return false;
|
||||
}
|
||||
|
||||
nDevLenght = (unsigned int)(sSplit - sPath);
|
||||
nDevPathLenght = (unsigned int)(nLenght - (sSplit - sPath) - 1);
|
||||
|
||||
strncpy(sDevice, sPath, nDevLenght);
|
||||
strncpy(sDevicePath, sSplit + 1, nDevPathLenght);
|
||||
|
||||
sDevice[nDevLenght] = '\0';
|
||||
sDevicePath[nDevPathLenght] = '\0';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CFileIO::CDevice* CFileIO::FindDevice(const char* sDeviceName)
|
||||
{
|
||||
CList<CDevice>::ITERATOR itDevice;
|
||||
CDevice* pDevice;
|
||||
|
||||
for(itDevice = m_Device.Begin(); itDevice.HasNext(); itDevice++)
|
||||
{
|
||||
pDevice = (*itDevice);
|
||||
if(!strcmp(pDevice->GetName(), sDeviceName))
|
||||
{
|
||||
return pDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32 CFileIO::RegisterFile(CStream* pFile)
|
||||
{
|
||||
uint32 nFD;
|
||||
nFD = m_nFileID;
|
||||
m_File.Insert(pFile, nFD);
|
||||
m_nFileID++;
|
||||
return nFD;
|
||||
}
|
||||
|
||||
uint32 CFileIO::Open(uint32 nMode, const char* sPath)
|
||||
{
|
||||
/*
|
||||
char sDevice[256];
|
||||
char sDevicePath[256];
|
||||
CDevice* pDevice;
|
||||
*/
|
||||
CStream* pFile;
|
||||
|
||||
Log("Attempting to open file '%s'.\r\n", sPath);
|
||||
|
||||
pFile = GetFile(nMode, sPath);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
return RegisterFile(pFile);
|
||||
/*
|
||||
if(!SplitPath(sPath, sDevice, sDevicePath))
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
pDevice = FindDevice(sDevice);
|
||||
if(pDevice == NULL)
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
pFile = pDevice->OpenFile(nMode, sDevicePath);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
uint32 CFileIO::Close(uint32 nFile)
|
||||
{
|
||||
CStream* pFile;
|
||||
|
||||
pFile = m_File.Remove(nFile);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
delete pFile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 CFileIO::Read(uint32 nFile, uint32 nSize, void* pBuffer)
|
||||
{
|
||||
CStream* pFile;
|
||||
|
||||
pFile = m_File.Find(nFile);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
Log("Reading from an unopened file (fd = %i).\r\n", nFile);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
if(pFile->IsEOF())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (uint32)pFile->Read(pBuffer, nSize);
|
||||
}
|
||||
|
||||
uint32 CFileIO::Write(uint32 nFile, uint32 nSize, void* pBuffer)
|
||||
{
|
||||
CStream* pFile;
|
||||
uint32 nAmount;
|
||||
|
||||
pFile = m_File.Find(nFile);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
if(nFile > 2)
|
||||
{
|
||||
Log("Writing to an unopened file (fd = %i).\r\n", nFile);
|
||||
}
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
nAmount = (uint32)pFile->Write(pBuffer, nSize);
|
||||
pFile->Flush();
|
||||
return nAmount;
|
||||
}
|
||||
|
||||
uint32 CFileIO::Seek(uint32 nFile, uint32 nOffset, uint32 nWhence)
|
||||
{
|
||||
CStream* pFile;
|
||||
STREAM_SEEK_DIRECTION nPosition;
|
||||
|
||||
pFile = m_File.Find(nFile);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
Log("Seeking in an unopened file (fd = %i).\r\n", nFile);
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
switch(nWhence)
|
||||
{
|
||||
case 0:
|
||||
nPosition = Framework::STREAM_SEEK_SET;
|
||||
break;
|
||||
case 1:
|
||||
nPosition = Framework::STREAM_SEEK_CUR;
|
||||
break;
|
||||
case 2:
|
||||
nPosition = Framework::STREAM_SEEK_END;
|
||||
break;
|
||||
}
|
||||
|
||||
pFile->Seek(nOffset, nPosition);
|
||||
return (uint32)pFile->Tell();
|
||||
}
|
||||
|
||||
void CFileIO::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_FileIO: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//Devices Implementation
|
||||
/////////////////////////////////////////////
|
||||
|
||||
CFileIO::CDevice::CDevice(const char* sName)
|
||||
{
|
||||
m_sName = sName;
|
||||
}
|
||||
|
||||
const char* CFileIO::CDevice::GetName()
|
||||
{
|
||||
return m_sName;
|
||||
}
|
||||
|
||||
CFileIO::CDirectoryDevice::CDirectoryDevice(const char* sName, const char* sBasePathPreference) :
|
||||
CDevice(sName)
|
||||
{
|
||||
m_sBasePathPreference = sBasePathPreference;
|
||||
}
|
||||
|
||||
CStream* CFileIO::CDirectoryDevice::OpenFile(uint32 nMode, const char* sDevicePath)
|
||||
{
|
||||
FILE* pStream;
|
||||
char sPath[256];
|
||||
const char* sMode;
|
||||
const char* sBasePath;
|
||||
|
||||
sBasePath = CConfig::GetInstance()->GetPreferenceString(m_sBasePathPreference);
|
||||
|
||||
strcpy(sPath, sBasePath);
|
||||
if(sDevicePath[0] != '/')
|
||||
{
|
||||
strcat(sPath, "/");
|
||||
}
|
||||
strcat(sPath, sDevicePath);
|
||||
|
||||
switch(nMode)
|
||||
{
|
||||
case 0:
|
||||
case O_RDONLY:
|
||||
sMode = "rb";
|
||||
break;
|
||||
case (O_RDWR | O_CREAT):
|
||||
sMode = "w+";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
pStream = fopen(sPath, sMode);
|
||||
if(pStream == NULL) return NULL;
|
||||
|
||||
return new CStdStream(pStream);
|
||||
}
|
||||
|
||||
CFileIO::CCDROM0Device::CCDROM0Device() :
|
||||
CFileIO::CDevice("cdrom0")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CFileIO::CCDROM0Device::~CCDROM0Device()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CStream* CFileIO::CCDROM0Device::OpenFile(uint32 nMode, const char* sDevicePath)
|
||||
{
|
||||
CISO9660* pISO;
|
||||
|
||||
if(nMode != O_RDONLY) return NULL;
|
||||
|
||||
pISO = CPS2VM::m_pCDROM0;
|
||||
if(pISO == NULL) return NULL;
|
||||
|
||||
return pISO->Open(sDevicePath);
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
#ifndef _IOP_FILEIO_H_
|
||||
#define _IOP_FILEIO_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include "IOP_Module.h"
|
||||
#include "List.h"
|
||||
#include "Stream.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CFileIO : public CModule
|
||||
{
|
||||
public:
|
||||
CFileIO();
|
||||
~CFileIO();
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
Framework::CStream* GetFile(uint32, const char*);
|
||||
uint32 Read(uint32, uint32, void*);
|
||||
uint32 Write(uint32, uint32, void*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000001
|
||||
};
|
||||
|
||||
enum OPEN_FLAGS
|
||||
{
|
||||
O_RDONLY = 0x00000001,
|
||||
O_WRONLY = 0x00000002,
|
||||
O_RDWR = 0x00000003,
|
||||
O_CREAT = 0x00000200,
|
||||
};
|
||||
|
||||
private:
|
||||
class CDevice
|
||||
{
|
||||
public:
|
||||
CDevice(const char*);
|
||||
virtual ~CDevice() {}
|
||||
virtual Framework::CStream* OpenFile(uint32, const char*) = 0;
|
||||
virtual const char* GetName();
|
||||
|
||||
private:
|
||||
const char* m_sName;
|
||||
};
|
||||
|
||||
class CDirectoryDevice : public CDevice
|
||||
{
|
||||
public:
|
||||
CDirectoryDevice(const char*, const char*);
|
||||
virtual Framework::CStream* OpenFile(uint32, const char*);
|
||||
private:
|
||||
const char* m_sBasePathPreference;
|
||||
};
|
||||
|
||||
class CCDROM0Device : public CDevice
|
||||
{
|
||||
public:
|
||||
CCDROM0Device();
|
||||
virtual ~CCDROM0Device();
|
||||
virtual Framework::CStream* OpenFile(uint32, const char*);
|
||||
};
|
||||
|
||||
bool SplitPath(const char*, char*, char*);
|
||||
CDevice* FindDevice(const char*);
|
||||
uint32 RegisterFile(Framework::CStream*);
|
||||
|
||||
uint32 Open(uint32, const char*);
|
||||
uint32 Close(uint32);
|
||||
uint32 Seek(uint32, uint32, uint32);
|
||||
|
||||
void Log(const char*, ...);
|
||||
|
||||
uint32 m_nFileID;
|
||||
|
||||
Framework::CList<Framework::CStream> m_File;
|
||||
Framework::CList<CDevice> m_Device;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
#include "IOP_LibSD.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
void CLibSD::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x8100:
|
||||
//Not sure about this one
|
||||
GetBufferSize(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CLibSD::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLibSD::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLibSD::GetBufferSize(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
static uint32 nTemp = 0;
|
||||
nTemp += 0x400;
|
||||
((uint32*)pRet)[0] = nTemp;
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
#ifndef _IOP_LIBSD_H_
|
||||
#define _IOP_LIBSD_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CLibSD : public CModule
|
||||
{
|
||||
public:
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000701
|
||||
};
|
||||
|
||||
private:
|
||||
void GetBufferSize(void*, uint32, void*, uint32);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,77 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "IOP_LoadFile.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
void CLoadFile::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x00:
|
||||
LoadModule(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0xFF:
|
||||
//This is sometimes called after binding this server with a client
|
||||
Initialize(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CLoadFile::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLoadFile::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CLoadFile::LoadModule(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
char sModuleName[253];
|
||||
|
||||
assert(nArgsSize == 512);
|
||||
|
||||
//Sometimes called with 4, sometimes 8
|
||||
assert(nRetSize >= 4);
|
||||
|
||||
memset(sModuleName, 0, 253);
|
||||
strncpy(sModuleName, &((const char*)pArgs)[8], 252);
|
||||
|
||||
//Load the module???
|
||||
Log("Request to load module '%s' received.\r\n", sModuleName);
|
||||
|
||||
//This function returns something negative upon failure
|
||||
*(uint32*)pRet = 0x00000000;
|
||||
}
|
||||
|
||||
void CLoadFile::Initialize(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nArgsSize == 0);
|
||||
assert(nRetSize == 4);
|
||||
|
||||
*(uint32*)pRet = 0x2E2E2E2E;
|
||||
}
|
||||
|
||||
void CLoadFile::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_LoadFile: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef _IOP_LOADFILE_H_
|
||||
#define _IOP_LOADFILE_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CLoadFile : public CModule
|
||||
{
|
||||
public:
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000006
|
||||
};
|
||||
|
||||
private:
|
||||
void LoadModule(void*, uint32, void*, uint32);
|
||||
void Initialize(void*, uint32, void*, uint32);
|
||||
void Log(const char*, ...);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,414 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#include "Config.h"
|
||||
#include "IOP_McServ.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
using namespace boost;
|
||||
using namespace std;
|
||||
|
||||
const char* CMcServ::m_sMcPathPreference[2] =
|
||||
{
|
||||
"ps2.mc0.directory",
|
||||
"ps2.mc1.directory",
|
||||
};
|
||||
|
||||
CMcServ::CMcServ()
|
||||
{
|
||||
assert(sizeof(CMD) == 0x414);
|
||||
m_nNextHandle = 1;
|
||||
}
|
||||
|
||||
CMcServ::~CMcServ()
|
||||
{
|
||||
//Close any handles that might still be in there...
|
||||
|
||||
for(HandleMap::iterator itHandle = m_Handles.begin();
|
||||
itHandle != m_Handles.end();
|
||||
itHandle++)
|
||||
{
|
||||
fclose(itHandle->second);
|
||||
}
|
||||
}
|
||||
|
||||
void CMcServ::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x01:
|
||||
GetInfo(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x02:
|
||||
Open(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x03:
|
||||
Close(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x05:
|
||||
Read(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x0D:
|
||||
GetDir(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0xFE:
|
||||
//Get version?
|
||||
GetVersionInformation(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X).\r\n", nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CMcServ::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMcServ::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CMcServ::GetInfo(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nArgsSize >= 0x1C);
|
||||
|
||||
uint32 nPort, nSlot;
|
||||
uint32* pRetBuffer;
|
||||
|
||||
bool nWantType;
|
||||
bool nWantFreeSpace;
|
||||
bool nWantFormatted;
|
||||
|
||||
nPort = ((uint32*)pArgs)[1];
|
||||
nSlot = ((uint32*)pArgs)[2];
|
||||
nWantType = ((uint32*)pArgs)[3] != 0;
|
||||
nWantFreeSpace = ((uint32*)pArgs)[4] != 0;
|
||||
nWantFormatted = ((uint32*)pArgs)[5] != 0;
|
||||
pRetBuffer = (uint32*)&CPS2VM::m_pRAM[((uint32*)pArgs)[7]];
|
||||
|
||||
Log("GetInfo(nPort = %i, nSlot = %i, nWantType = %i, nWantFreeSpace = %i, nWantFormatted = %i, nRetBuffer = 0x%0.8X);\r\n",
|
||||
nPort, nSlot, nWantType, nWantFreeSpace, nWantFormatted, ((uint32*)pArgs)[7]);
|
||||
|
||||
if(nWantType)
|
||||
{
|
||||
pRetBuffer[0x00] = 2;
|
||||
}
|
||||
if(nWantFreeSpace)
|
||||
{
|
||||
pRetBuffer[0x01] = 0x800000;
|
||||
}
|
||||
if(nWantFormatted)
|
||||
{
|
||||
pRetBuffer[0x24] = 1;
|
||||
}
|
||||
|
||||
((uint32*)pRet)[0] = 0;
|
||||
}
|
||||
|
||||
void CMcServ::Open(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nHandle;
|
||||
CMD* pCmd;
|
||||
FILE* pFile;
|
||||
const char* sAccess;
|
||||
|
||||
assert(nArgsSize >= 0x414);
|
||||
|
||||
pCmd = reinterpret_cast<CMD*>(pArgs);
|
||||
|
||||
Log("Open(nPort = %i, nSlot = %i, nFlags = %i, sName = %s);\r\n",
|
||||
pCmd->nPort, pCmd->nSlot, pCmd->nFlags, pCmd->sName);
|
||||
|
||||
if(pCmd->nPort > 1)
|
||||
{
|
||||
assert(0);
|
||||
((uint32*)pRet)[0] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
filesystem::path Path;
|
||||
|
||||
try
|
||||
{
|
||||
Path = filesystem::path(CConfig::GetInstance()->GetPreferenceString(m_sMcPathPreference[pCmd->nPort]), filesystem::native);
|
||||
Path /= pCmd->sName;
|
||||
}
|
||||
catch(const exception& Exception)
|
||||
{
|
||||
Log("Error while executing Open: %s\r\n.", Exception.what());
|
||||
reinterpret_cast<uint32*>(pRet)[0] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
sAccess = NULL;
|
||||
switch(pCmd->nFlags)
|
||||
{
|
||||
case 1:
|
||||
sAccess = "rb";
|
||||
break;
|
||||
}
|
||||
|
||||
if(sAccess == NULL)
|
||||
{
|
||||
((uint32*)pRet)[0] = -1;
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
pFile = fopen(Path.string().c_str(), sAccess);
|
||||
if(pFile == NULL)
|
||||
{
|
||||
((uint32*)pRet)[0] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
nHandle = GenerateHandle();
|
||||
m_Handles[nHandle] = pFile;
|
||||
|
||||
((uint32*)pRet)[0] = nHandle;
|
||||
}
|
||||
|
||||
void CMcServ::Close(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
FILECMD* pCmd;
|
||||
|
||||
pCmd = reinterpret_cast<FILECMD*>(pArgs);
|
||||
|
||||
Log("Close(nHandle = %i);\r\n",
|
||||
pCmd->nHandle);
|
||||
|
||||
HandleMap::iterator itHandle;
|
||||
|
||||
itHandle = m_Handles.find(pCmd->nHandle);
|
||||
if(itHandle == m_Handles.end())
|
||||
{
|
||||
((uint32*)pRet)[0] = -1;
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(itHandle->second);
|
||||
m_Handles.erase(itHandle);
|
||||
|
||||
((uint32*)pRet)[0] = 0;
|
||||
}
|
||||
|
||||
void CMcServ::Read(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
FILECMD* pCmd;
|
||||
FILE* pFile;
|
||||
void* pDst;
|
||||
|
||||
pCmd = reinterpret_cast<FILECMD*>(pArgs);
|
||||
|
||||
Log("Read(nHandle = %i, nSize = 0x%0.8X, nBufferAddress = 0x%0.8X, nParamAddress = 0x%0.8X);\r\n",
|
||||
pCmd->nHandle, pCmd->nSize, pCmd->nBufferAddress, pCmd->nParamAddress);
|
||||
|
||||
HandleMap::iterator itHandle;
|
||||
|
||||
itHandle = m_Handles.find(pCmd->nHandle);
|
||||
if(itHandle == m_Handles.end())
|
||||
{
|
||||
((uint32*)pRet)[0] = -1;
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
pFile = itHandle->second;
|
||||
pDst = &CPS2VM::m_pRAM[pCmd->nBufferAddress];
|
||||
|
||||
//This param buffer is used in the callback after calling this method... No clue what it's for
|
||||
((uint32*)&CPS2VM::m_pRAM[pCmd->nParamAddress])[0] = 0;
|
||||
((uint32*)&CPS2VM::m_pRAM[pCmd->nParamAddress])[1] = 0;
|
||||
|
||||
((uint32*)pRet)[0] = static_cast<uint32>(fread(pDst, 1, pCmd->nSize, pFile));
|
||||
}
|
||||
|
||||
void CMcServ::GetDir(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nRet;
|
||||
|
||||
nRet = 0;
|
||||
|
||||
assert(nArgsSize >= 0x414);
|
||||
|
||||
CMD* pCmd;
|
||||
pCmd = reinterpret_cast<CMD*>(pArgs);
|
||||
|
||||
Log("GetDir(nPort = %i, nSlot = %i, nFlags = %i, nMaxEntries = %i, nTableAddress = 0x%0.8X, sName = %s);\r\n",
|
||||
pCmd->nPort, pCmd->nSlot, pCmd->nFlags, pCmd->nMaxEntries, pCmd->nTableAddress, pCmd->sName);
|
||||
|
||||
if(pCmd->nPort > 1)
|
||||
{
|
||||
assert(0);
|
||||
((uint32*)pRet)[0] = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
filesystem::path McPath(CConfig::GetInstance()->GetPreferenceString(m_sMcPathPreference[pCmd->nPort]), filesystem::native);
|
||||
McPath = filesystem::complete(McPath);
|
||||
|
||||
if(filesystem::exists(McPath))
|
||||
{
|
||||
CPathFinder PathFinder(McPath, reinterpret_cast<CPathFinder::ENTRY*>(&CPS2VM::m_pRAM[pCmd->nTableAddress]), pCmd->nMaxEntries, pCmd->sName);
|
||||
nRet = PathFinder.Search();
|
||||
}
|
||||
}
|
||||
catch(const exception& Exception)
|
||||
{
|
||||
Log("Error while executing GetDir: %s\r\n.", Exception.what());
|
||||
}
|
||||
|
||||
((uint32*)pRet)[0] = nRet;
|
||||
}
|
||||
|
||||
void CMcServ::GetVersionInformation(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nArgsSize == 0x30);
|
||||
assert(nRetSize == 0x0C);
|
||||
|
||||
((uint32*)pRet)[0] = 0x00000000;
|
||||
((uint32*)pRet)[1] = 0x0000020A; //mcserv version
|
||||
((uint32*)pRet)[2] = 0x0000020E; //mcman version
|
||||
|
||||
Log("Init();\r\n");
|
||||
}
|
||||
|
||||
uint32 CMcServ::GenerateHandle()
|
||||
{
|
||||
return m_nNextHandle++;
|
||||
}
|
||||
|
||||
void CMcServ::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_McServ: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//CPathFinder Implementation
|
||||
/////////////////////////////////////////////
|
||||
|
||||
CMcServ::CPathFinder::CPathFinder(const filesystem::path& BasePath, ENTRY* pEntry, unsigned int nMax, const char* sFilter)
|
||||
{
|
||||
m_BasePath = BasePath;
|
||||
m_pEntry = pEntry;
|
||||
m_nIndex = 0;
|
||||
m_nMax = nMax;
|
||||
m_sFilter = sFilter;
|
||||
}
|
||||
|
||||
CMcServ::CPathFinder::~CPathFinder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
unsigned int CMcServ::CPathFinder::Search()
|
||||
{
|
||||
SearchRecurse(m_BasePath);
|
||||
return m_nIndex;
|
||||
}
|
||||
|
||||
void CMcServ::CPathFinder::SearchRecurse(const filesystem::path& Path)
|
||||
{
|
||||
filesystem::directory_iterator itEnd;
|
||||
|
||||
for(filesystem::directory_iterator itElement(Path);
|
||||
itElement != itEnd;
|
||||
itElement++)
|
||||
{
|
||||
string sRelativePath((*itElement).string());
|
||||
|
||||
//"Extract" a more appropriate relative path from the memory card point of view
|
||||
sRelativePath.erase(0, m_BasePath.string().size());
|
||||
|
||||
//Attempt to match this against the filter
|
||||
if(MatchesFilter(sRelativePath.c_str()))
|
||||
{
|
||||
//This fits... fill in the information
|
||||
|
||||
ENTRY* pEntry;
|
||||
pEntry = &m_pEntry[m_nIndex];
|
||||
|
||||
//strncpy(reinterpret_cast<char*>(pEntry->sName), sRelativePath.c_str(), 0x1F);
|
||||
strncpy(reinterpret_cast<char*>(pEntry->sName), (*itElement).leaf().c_str(), 0x1F);
|
||||
pEntry->sName[0x1F] = 0;
|
||||
|
||||
if(filesystem::is_directory(*itElement))
|
||||
{
|
||||
pEntry->nSize = 0;
|
||||
pEntry->nAttributes = 0x8427;
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry->nSize = static_cast<uint32>(filesystem::file_size(*itElement));
|
||||
pEntry->nAttributes = 0x8497;
|
||||
}
|
||||
|
||||
m_nIndex++;
|
||||
}
|
||||
|
||||
if(filesystem::is_directory(*itElement))
|
||||
{
|
||||
SearchRecurse(*itElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Based on an algorithm found on http://xoomer.alice.it/acantato/dev/wildcard/wildmatch.html
|
||||
bool CMcServ::CPathFinder::MatchesFilter(const char* sPath)
|
||||
{
|
||||
const char* sPattern;
|
||||
const char* s;
|
||||
const char* p;
|
||||
bool nStar;
|
||||
|
||||
sPattern = m_sFilter.c_str();
|
||||
nStar = false;
|
||||
|
||||
_loopStart:
|
||||
|
||||
for(s = sPath, p = sPattern; *s; s++, p++)
|
||||
{
|
||||
switch(*p)
|
||||
{
|
||||
case '*':
|
||||
nStar = true;
|
||||
sPath = s;
|
||||
sPattern = p;
|
||||
if((*++p) == 0) return true;
|
||||
goto _loopStart;
|
||||
break;
|
||||
default:
|
||||
if(toupper(*s) != toupper(*p))
|
||||
{
|
||||
goto _starCheck;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(*p == '*') p++;
|
||||
return (*p) == 0;
|
||||
|
||||
_starCheck:
|
||||
if(!nStar) return false;
|
||||
sPath++;
|
||||
goto _loopStart;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
#ifndef _IOP_MCSERV_H_
|
||||
#define _IOP_MCSERV_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
|
||||
class CMcServ : public CModule
|
||||
{
|
||||
public:
|
||||
CMcServ();
|
||||
virtual ~CMcServ();
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000400,
|
||||
};
|
||||
|
||||
private:
|
||||
struct CMD
|
||||
{
|
||||
uint32 nPort;
|
||||
uint32 nSlot;
|
||||
uint32 nFlags;
|
||||
uint32 nMaxEntries;
|
||||
uint32 nTableAddress;
|
||||
char sName[0x400];
|
||||
};
|
||||
|
||||
struct FILECMD
|
||||
{
|
||||
uint32 nHandle;
|
||||
uint32 nPad[2];
|
||||
uint32 nSize;
|
||||
uint32 nOffset;
|
||||
uint32 nOrigin;
|
||||
uint32 nBufferAddress;
|
||||
uint32 nParamAddress;
|
||||
char nData[16];
|
||||
};
|
||||
|
||||
class CPathFinder
|
||||
{
|
||||
public:
|
||||
struct ENTRY
|
||||
{
|
||||
struct TIME
|
||||
{
|
||||
uint8 nUnknown;
|
||||
uint8 nSecond;
|
||||
uint8 nMinute;
|
||||
uint8 nHour;
|
||||
uint8 nDay;
|
||||
uint8 nMonth;
|
||||
uint16 nYear;
|
||||
};
|
||||
|
||||
TIME CreationTime;
|
||||
TIME ModificationTime;
|
||||
uint32 nSize;
|
||||
uint16 nAttributes;
|
||||
uint16 nReserved0;
|
||||
uint32 nReserved1[2];
|
||||
uint8 sName[0x20];
|
||||
};
|
||||
CPathFinder(const boost::filesystem::path&, ENTRY*, unsigned int, const char*);
|
||||
~CPathFinder();
|
||||
|
||||
unsigned int Search();
|
||||
|
||||
private:
|
||||
void SearchRecurse(const boost::filesystem::path&);
|
||||
bool MatchesFilter(const char*);
|
||||
|
||||
ENTRY* m_pEntry;
|
||||
boost::filesystem::path m_BasePath;
|
||||
std::string m_sFilter;
|
||||
unsigned int m_nIndex;
|
||||
unsigned int m_nMax;
|
||||
|
||||
};
|
||||
|
||||
void GetInfo(void*, uint32, void*, uint32);
|
||||
void Open(void*, uint32, void*, uint32);
|
||||
void Close(void*, uint32, void*, uint32);
|
||||
void Read(void*, uint32, void*, uint32);
|
||||
void GetDir(void*, uint32, void*, uint32);
|
||||
void GetVersionInformation(void*, uint32, void*, uint32);
|
||||
|
||||
uint32 GenerateHandle();
|
||||
void Log(const char*, ...);
|
||||
|
||||
typedef std::map<uint32, FILE*> HandleMap;
|
||||
|
||||
HandleMap m_Handles;
|
||||
static const char* m_sMcPathPreference[2];
|
||||
uint32 m_nNextHandle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -1,19 +0,0 @@
|
||||
#ifndef _IOP_MODULE_H_
|
||||
#define _IOP_MODULE_H_
|
||||
|
||||
#include "Types.h"
|
||||
#include "Stream.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CModule
|
||||
{
|
||||
public:
|
||||
virtual ~CModule() {}
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32) = 0;
|
||||
virtual void SaveState(Framework::CStream*) = 0;
|
||||
virtual void LoadState(Framework::CStream*) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,224 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <boost/bind.hpp>
|
||||
#include "IOP_PadMan.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
using namespace boost;
|
||||
|
||||
#define PADNUM (1)
|
||||
#define MODE (0x4)
|
||||
|
||||
CPadMan::CPadMan()
|
||||
{
|
||||
m_nPadDataAddress = 0;
|
||||
m_nPadDataType = 0;
|
||||
m_pPad = NULL;
|
||||
}
|
||||
|
||||
void CPadMan::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nMethod == 1);
|
||||
nMethod = ((uint32*)pArgs)[0];
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x00000001:
|
||||
case 0x80000100:
|
||||
Open(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x00000008:
|
||||
SetActuatorAlign(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x00000010:
|
||||
Init(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
case 0x00000012:
|
||||
GetModuleVersion(pArgs, nArgsSize, pRet, nRetSize);
|
||||
break;
|
||||
default:
|
||||
Log("Unknown method invoked (0x%0.8X).\r\n", nMethod);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CPadMan::SaveState(CStream* pStream)
|
||||
{
|
||||
pStream->Write(&m_nPadDataAddress, 4);
|
||||
pStream->Write(&m_nPadDataType, 4);
|
||||
}
|
||||
|
||||
void CPadMan::LoadState(CStream* pStream)
|
||||
{
|
||||
pStream->Read(&m_nPadDataAddress, 4);
|
||||
pStream->Read(&m_nPadDataType, 4);
|
||||
}
|
||||
|
||||
void CPadMan::SetButtonState(unsigned int nPadNumber, CPadListener::BUTTON nButton, bool nPressed)
|
||||
{
|
||||
if(m_nPadDataAddress == 0) return;
|
||||
|
||||
ExecutePadDataFunction(bind(&CPadMan::PDF_SetButtonState, _1, nButton, nPressed),
|
||||
CPS2VM::m_pRAM + m_nPadDataAddress, PADNUM);
|
||||
}
|
||||
|
||||
void CPadMan::Open(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
uint32 nPort, nSlot, nAddress;
|
||||
|
||||
nPort = ((uint32*)pArgs)[1];
|
||||
nSlot = ((uint32*)pArgs)[2];
|
||||
nAddress = ((uint32*)pArgs)[4];
|
||||
|
||||
if(nPort == 0)
|
||||
{
|
||||
m_nPadDataAddress = nAddress;
|
||||
m_pPad = (PADDATA*)(CPS2VM::m_pRAM + nAddress);
|
||||
}
|
||||
|
||||
Log("Opening device on port %i and slot %i.\r\n", nPort, nSlot);
|
||||
|
||||
ExecutePadDataFunction(&CPadMan::PDF_InitializeStruct0, CPS2VM::m_pRAM + m_nPadDataAddress, 0);
|
||||
ExecutePadDataFunction(&CPadMan::PDF_InitializeStruct1, CPS2VM::m_pRAM + m_nPadDataAddress, 1);
|
||||
|
||||
//Returns 0 on error
|
||||
((uint32*)pRet)[3] = 0x00000001;
|
||||
}
|
||||
|
||||
void CPadMan::SetActuatorAlign(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nRetSize >= 24);
|
||||
|
||||
((uint32*)pRet)[5] = 1;
|
||||
}
|
||||
|
||||
void CPadMan::Init(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nRetSize >= 0x10);
|
||||
|
||||
m_nPadDataType = 1;
|
||||
|
||||
Log("Init();\r\n");
|
||||
|
||||
((uint32*)pRet)[3] = 1;
|
||||
}
|
||||
|
||||
void CPadMan::GetModuleVersion(void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
assert(nRetSize >= 0x10);
|
||||
|
||||
Log("GetModuleVersion();\r\n");
|
||||
|
||||
((uint32*)pRet)[3] = 0x00000400;
|
||||
}
|
||||
|
||||
void CPadMan::ExecutePadDataFunction(PadDataFunction Function, void* pBase, size_t nOffset)
|
||||
{
|
||||
switch(m_nPadDataType)
|
||||
{
|
||||
case 0:
|
||||
Function(&CPadDataHandler<PADDATA>(reinterpret_cast<PADDATA*>(pBase) + nOffset));
|
||||
break;
|
||||
case 1:
|
||||
Function(&CPadDataHandler<PADDATAEX>(reinterpret_cast<PADDATAEX*>(pBase) + nOffset));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CPadMan::PDF_InitializeStruct0(CPadDataInterface* pPadData)
|
||||
{
|
||||
pPadData->SetFrame(0);
|
||||
pPadData->SetState(6);
|
||||
pPadData->SetReqState(0);
|
||||
pPadData->SetLength(32);
|
||||
pPadData->SetOk(1);
|
||||
|
||||
// m_pPad[0].nFrame = 0;
|
||||
// m_pPad[0].nState = 6;
|
||||
// m_pPad[0].nReqState = 0;
|
||||
// m_pPad[0].nLength = 32;
|
||||
// m_pPad[0].nOk = 1;
|
||||
}
|
||||
|
||||
void CPadMan::PDF_InitializeStruct1(CPadDataInterface* pPadData)
|
||||
{
|
||||
pPadData->SetFrame(1);
|
||||
pPadData->SetState(6);
|
||||
pPadData->SetReqState(0);
|
||||
pPadData->SetLength(32);
|
||||
pPadData->SetOk(1);
|
||||
|
||||
//EX struct initialization
|
||||
pPadData->SetModeCurId(MODE << 4);
|
||||
pPadData->SetModeCurOffset(0);
|
||||
pPadData->SetModeTable(0, MODE);
|
||||
/*
|
||||
m_pPad[1].nFrame = 1;
|
||||
m_pPad[1].nState = 6;
|
||||
m_pPad[1].nReqState = 0;
|
||||
m_pPad[1].nLength = 32;
|
||||
m_pPad[1].nOk = 1;
|
||||
#ifdef USE_EX
|
||||
m_pPad[1].nModeCurId = MODE << 4;
|
||||
m_pPad[1].nModeCurOffset = 0;
|
||||
m_pPad[1].nModeTable[0] = MODE;
|
||||
#endif
|
||||
*/
|
||||
}
|
||||
|
||||
void CPadMan::PDF_SetButtonState(CPadDataInterface* pPadData, BUTTON nButton, bool nPressed)
|
||||
{
|
||||
uint16 nStatus;
|
||||
|
||||
nStatus = (pPadData->GetData(2) << 8) | (pPadData->GetData(3));
|
||||
|
||||
nStatus &= ~nButton;
|
||||
if(!nPressed)
|
||||
{
|
||||
nStatus |= nButton;
|
||||
}
|
||||
|
||||
pPadData->SetReqState(0);
|
||||
|
||||
pPadData->SetData(2, static_cast<uint8>(nStatus >> 8));
|
||||
pPadData->SetData(3, static_cast<uint8>(nStatus >> 0));
|
||||
|
||||
pPadData->SetData(0, 0);
|
||||
pPadData->SetData(1, MODE << 4);
|
||||
|
||||
/*
|
||||
uint16 nStatus;
|
||||
if(m_pPad == NULL) return;
|
||||
nStatus = (m_pPad[PADNUM].nData[2] << 8) | (m_pPad[PADNUM].nData[3]);
|
||||
|
||||
nStatus &= ~nButton;
|
||||
if(!nPressed)
|
||||
{
|
||||
nStatus |= nButton;
|
||||
}
|
||||
|
||||
m_pPad[PADNUM].nReqState = 0;
|
||||
|
||||
m_pPad[PADNUM].nData[2] = (uint8)(nStatus >> 8);
|
||||
m_pPad[PADNUM].nData[3] = (uint8)(nStatus >> 0);
|
||||
|
||||
m_pPad[PADNUM].nData[0] = 0;
|
||||
m_pPad[PADNUM].nData[1] = MODE << 4;
|
||||
*/
|
||||
}
|
||||
|
||||
void CPadMan::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_PadMan: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
#ifndef _IOP_PADMAN_H_
|
||||
#define _IOP_PADMAN_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
#include "PadListener.h"
|
||||
#include <boost/function.hpp>
|
||||
|
||||
//#define USE_EX
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CPadMan : public CModule, public CPadListener
|
||||
{
|
||||
public:
|
||||
CPadMan();
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
virtual void SetButtonState(unsigned int, CPadListener::BUTTON, bool);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID_1 = 0x80000100,
|
||||
MODULE_ID_2 = 0x80000101,
|
||||
MODULE_ID_3 = 0x8000010F,
|
||||
MODULE_ID_4 = 0x0000011F,
|
||||
};
|
||||
|
||||
private:
|
||||
struct PADDATAEX
|
||||
{
|
||||
uint8 nData[32];
|
||||
uint32 nReserved1[4];
|
||||
uint8 nActuator[32];
|
||||
uint16 nModeTable[4];
|
||||
uint32 nFrame;
|
||||
uint32 nReserved2;
|
||||
uint32 nLength;
|
||||
uint8 nModeOk;
|
||||
uint8 nModeCurId;
|
||||
uint8 nReserved3[2];
|
||||
uint8 nNrOfModes;
|
||||
uint8 nModeCurOffset;
|
||||
uint8 nActuatorCount;
|
||||
uint8 nReserved4[5];
|
||||
uint8 nState;
|
||||
uint8 nReqState;
|
||||
uint8 nOk;
|
||||
uint8 nReserved5[13];
|
||||
};
|
||||
|
||||
struct PADDATA
|
||||
{
|
||||
uint32 nFrame;
|
||||
uint8 nState;
|
||||
uint8 nReqState;
|
||||
uint8 nOk;
|
||||
uint8 nReserved0;
|
||||
uint8 nData[32];
|
||||
uint32 nLength;
|
||||
uint32 nReserved1[5];
|
||||
};
|
||||
|
||||
class CPadDataInterface
|
||||
{
|
||||
public:
|
||||
virtual ~CPadDataInterface() {}
|
||||
virtual void SetData(unsigned int, uint8) = 0;
|
||||
virtual uint8 GetData(unsigned int) = 0;
|
||||
virtual void SetFrame(unsigned int) = 0;
|
||||
virtual void SetState(unsigned int) = 0;
|
||||
virtual void SetReqState(unsigned int) = 0;
|
||||
virtual void SetLength(unsigned int) = 0;
|
||||
virtual void SetOk(unsigned int) = 0;
|
||||
virtual void SetModeCurId(unsigned int) = 0;
|
||||
virtual void SetModeCurOffset(unsigned int) = 0;
|
||||
virtual void SetModeTable(unsigned int, unsigned int) = 0;
|
||||
};
|
||||
|
||||
template <typename T> class CPadDataHandler : public CPadDataInterface
|
||||
{
|
||||
public:
|
||||
CPadDataHandler(void* pPtr)
|
||||
{
|
||||
m_pPadData = reinterpret_cast<T*>(pPtr);
|
||||
}
|
||||
|
||||
virtual ~CPadDataHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual uint8 GetData(unsigned int nIndex)
|
||||
{
|
||||
return m_pPadData->nData[nIndex];
|
||||
}
|
||||
|
||||
virtual void SetData(unsigned int nIndex, uint8 nValue)
|
||||
{
|
||||
m_pPadData->nData[nIndex] = nValue;
|
||||
}
|
||||
|
||||
virtual void SetFrame(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nFrame = nValue;
|
||||
}
|
||||
|
||||
virtual void SetState(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nState = nValue;
|
||||
}
|
||||
|
||||
virtual void SetReqState(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nReqState = nValue;
|
||||
}
|
||||
|
||||
virtual void SetLength(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nLength = nValue;
|
||||
}
|
||||
|
||||
virtual void SetOk(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nOk = nValue;
|
||||
}
|
||||
|
||||
virtual void SetModeCurId(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nModeCurId = nValue;
|
||||
}
|
||||
|
||||
virtual void SetModeCurOffset(unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nModeCurOffset = nValue;
|
||||
}
|
||||
|
||||
virtual void SetModeTable(unsigned int nIndex, unsigned int nValue)
|
||||
{
|
||||
m_pPadData->nModeTable[nIndex] = nValue;
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_pPadData;
|
||||
};
|
||||
|
||||
typedef boost::function< void (CPadDataInterface*) > PadDataFunction;
|
||||
|
||||
PADDATA* m_pPad;
|
||||
|
||||
unsigned int m_nPadDataType;
|
||||
uint32 m_nPadDataAddress;
|
||||
|
||||
void Open(void*, uint32, void*, uint32);
|
||||
void SetActuatorAlign(void*, uint32, void*, uint32);
|
||||
void Init(void*, uint32, void*, uint32);
|
||||
void GetModuleVersion(void*, uint32, void*, uint32);
|
||||
void ExecutePadDataFunction(PadDataFunction, void*, size_t);
|
||||
|
||||
static void PDF_InitializeStruct0(CPadDataInterface*);
|
||||
static void PDF_InitializeStruct1(CPadDataInterface*);
|
||||
static void PDF_SetButtonState(CPadDataInterface*, BUTTON, bool);
|
||||
|
||||
static void Log(const char*, ...);
|
||||
};
|
||||
|
||||
template <> void CPadMan::CPadDataHandler<CPadMan::PADDATA>::SetModeCurId(unsigned int);
|
||||
template <> void CPadMan::CPadDataHandler<CPadMan::PADDATA>::SetModeCurOffset(unsigned int);
|
||||
template <> void CPadMan::CPadDataHandler<CPadMan::PADDATA>::SetModeTable(unsigned int, unsigned int);
|
||||
}
|
||||
|
||||
#endif
|
@ -1,65 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "IOP_SysMem.h"
|
||||
#include "PS2VM.h"
|
||||
|
||||
using namespace IOP;
|
||||
using namespace Framework;
|
||||
|
||||
void CSysMem::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x01:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Allocate(*(uint32*)pArgs);
|
||||
break;
|
||||
case 0x04:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = AllocateSystemMemory(((uint32*)pArgs)[0], ((uint32*)pArgs)[1], ((uint32*)pArgs)[2]);
|
||||
break;
|
||||
default:
|
||||
//assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CSysMem::SaveState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CSysMem::LoadState(CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32 CSysMem::Allocate(uint32 nSize)
|
||||
{
|
||||
Log("Allocate(size = 0x%0.8X);\r\n", nSize);
|
||||
//return 0x01;
|
||||
return nSize;
|
||||
}
|
||||
|
||||
uint32 CSysMem::AllocateSystemMemory(uint32 nFlags, uint32 nSize, uint32 nPtr)
|
||||
{
|
||||
//Ys 1&2 Eternal Story calls this
|
||||
|
||||
Log("AllocateSystemMemory(flags = 0x%0.8X, size = 0x%0.8X, ptr = 0x%0.8X);\r\n", nFlags, nSize, nPtr);
|
||||
return 0x01;
|
||||
}
|
||||
|
||||
void CSysMem::Log(const char* sFormat, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
if(!CPS2VM::m_Logging.GetIOPLoggingStatus()) return;
|
||||
|
||||
va_list Args;
|
||||
printf("IOP_SysMem: ");
|
||||
va_start(Args, sFormat);
|
||||
vprintf(sFormat, Args);
|
||||
va_end(Args);
|
||||
|
||||
#endif
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#ifndef _IOP_SYSMEM_H_
|
||||
#define _IOP_SYSMEM_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CSysMem : public CModule
|
||||
{
|
||||
public:
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x80000003
|
||||
};
|
||||
|
||||
private:
|
||||
uint32 Allocate(uint32);
|
||||
uint32 AllocateSystemMemory(uint32, uint32, uint32);
|
||||
|
||||
void Log(const char*, ...);
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,33 +0,0 @@
|
||||
#include "PS2VM.h"
|
||||
#include "IOP_Unknown.h"
|
||||
|
||||
using namespace IOP;
|
||||
|
||||
void CUnknown::Invoke(uint32 nMethod, void* pArgs, uint32 nArgsSize, void* pRet, uint32 nRetSize)
|
||||
{
|
||||
switch(nMethod)
|
||||
{
|
||||
case 0x01000000:
|
||||
{
|
||||
if(nRetSize == 0x7C)
|
||||
{
|
||||
(reinterpret_cast<uint16*>(pRet))[0x30] |= 0x7;
|
||||
(reinterpret_cast<uint16*>(pRet))[0x31] |= 0x7;
|
||||
|
||||
(reinterpret_cast<uint16*>(pRet))[0x30] ^= 0x8;
|
||||
(reinterpret_cast<uint16*>(pRet))[0x31] ^= 0x8;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CUnknown::LoadState(Framework::CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CUnknown::SaveState(Framework::CStream* pStream)
|
||||
{
|
||||
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
#ifndef _IOP_UNKNOWN_H_
|
||||
#define _IOP_UNKNOWN_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CUnknown : public CModule
|
||||
{
|
||||
public:
|
||||
virtual void Invoke(uint32, void*, uint32, void*, uint32);
|
||||
virtual void LoadState(Framework::CStream*);
|
||||
virtual void SaveState(Framework::CStream*);
|
||||
|
||||
enum MODULE_ID
|
||||
{
|
||||
MODULE_ID = 0x00012345,
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -272,33 +272,13 @@ void CMA_EE::MULTU1()
|
||||
//1A
|
||||
void CMA_EE::DIV1()
|
||||
{
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
||||
m_pB->DivS();
|
||||
|
||||
m_pB->SeX32();
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO1[1]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO1[0]);
|
||||
|
||||
m_pB->SeX32();
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nHI1[1]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nHI1[0]);
|
||||
Template_Div32()(bind(&CCodeGen::DivS, m_codeGen), 1);
|
||||
}
|
||||
|
||||
//1B
|
||||
void CMA_EE::DIVU1()
|
||||
{
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
||||
m_pB->Div();
|
||||
|
||||
m_pB->SeX32();
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO1[1]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO1[0]);
|
||||
|
||||
m_pB->SeX32();
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nHI1[1]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nHI1[0]);
|
||||
Template_Div32()(bind(&CCodeGen::Div, m_codeGen), 1);
|
||||
}
|
||||
|
||||
//28
|
||||
@ -356,14 +336,10 @@ void CMA_EE::PSRAH()
|
||||
//01
|
||||
void CMA_EE::PSUBW()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
PushVector(m_nRS);
|
||||
PushVector(m_nRT);
|
||||
CVUI128::SubW();
|
||||
PullVector(m_nRD);
|
||||
}
|
||||
CCodeGen::End();
|
||||
PushVector(m_nRS);
|
||||
PushVector(m_nRT);
|
||||
m_codeGen->MD_SubW();
|
||||
PullVector(m_nRD);
|
||||
}
|
||||
|
||||
//04
|
||||
@ -646,14 +622,10 @@ void CMA_EE::PAND()
|
||||
//13
|
||||
void CMA_EE::PXOR()
|
||||
{
|
||||
CCodeGen::Begin(m_pB);
|
||||
{
|
||||
CVUI128::Push(&m_pCtx->m_State.nGPR[m_nRS]);
|
||||
CVUI128::Push(&m_pCtx->m_State.nGPR[m_nRT]);
|
||||
CVUI128::Xor();
|
||||
CVUI128::Pull(&m_pCtx->m_State.nGPR[m_nRD]);
|
||||
}
|
||||
CCodeGen::End();
|
||||
PushVector(m_nRS);
|
||||
PushVector(m_nRT);
|
||||
m_codeGen->MD_Xor();
|
||||
PullVector(m_nRD);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
@ -791,7 +791,7 @@ void CMA_MIPSIV::SRL()
|
||||
//03
|
||||
void CMA_MIPSIV::SRA()
|
||||
{
|
||||
Template_ShiftCst32()(&CCodeGen::Sra);
|
||||
Template_ShiftCst32()(bind(&CCodeGen::Sra, m_codeGen, _1));
|
||||
}
|
||||
|
||||
//04
|
||||
@ -809,11 +809,7 @@ void CMA_MIPSIV::SRLV()
|
||||
//07
|
||||
void CMA_MIPSIV::SRAV()
|
||||
{
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRT].nV[0]);
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
||||
m_pB->Sra();
|
||||
SignExtendTop32(m_nRD);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nGPR[m_nRD].nV[0]);
|
||||
Template_ShiftVar32()(bind(&CCodeGen::Sra, m_codeGen));
|
||||
}
|
||||
|
||||
//08
|
||||
@ -907,11 +903,11 @@ void CMA_MIPSIV::MFLO()
|
||||
//13
|
||||
void CMA_MIPSIV::MTLO()
|
||||
{
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[0]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO[0]);
|
||||
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[0]));
|
||||
|
||||
m_pB->PushAddr(&m_pCtx->m_State.nGPR[m_nRS].nV[1]);
|
||||
m_pB->PullAddr(&m_pCtx->m_State.nLO[1]);
|
||||
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[1]));
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[1]));
|
||||
}
|
||||
|
||||
//14
|
||||
@ -961,13 +957,13 @@ void CMA_MIPSIV::MULTU()
|
||||
//1A
|
||||
void CMA_MIPSIV::DIV()
|
||||
{
|
||||
Template_Div32()(bind(&CCodeGen::DivS, m_codeGen));
|
||||
Template_Div32()(bind(&CCodeGen::DivS, m_codeGen), 0);
|
||||
}
|
||||
|
||||
//1B
|
||||
void CMA_MIPSIV::DIVU()
|
||||
{
|
||||
Template_Div32()(bind(&CCodeGen::Div, m_codeGen));
|
||||
Template_Div32()(bind(&CCodeGen::Div, m_codeGen), 0);
|
||||
}
|
||||
|
||||
//20
|
||||
|
@ -89,7 +89,7 @@ protected:
|
||||
struct Template_Div32
|
||||
{
|
||||
typedef std::tr1::function<void ()> OperationFunctionType;
|
||||
void operator()(const OperationFunctionType&) const;
|
||||
void operator()(const OperationFunctionType&, unsigned int) const;
|
||||
};
|
||||
|
||||
struct Template_MovEqual
|
||||
|
@ -91,19 +91,41 @@ void CMA_MIPSIV::Template_Mult32::operator()(const OperationFunctionType& Functi
|
||||
}
|
||||
}
|
||||
|
||||
void CMA_MIPSIV::Template_Div32::operator()(const OperationFunctionType& function) const
|
||||
void CMA_MIPSIV::Template_Div32::operator()(const OperationFunctionType& function, unsigned int unit) const
|
||||
{
|
||||
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
||||
size_t lo[2];
|
||||
size_t hi[2];
|
||||
|
||||
switch(unit)
|
||||
{
|
||||
case 0:
|
||||
lo[0] = offsetof(CMIPS, m_State.nLO[0]);
|
||||
lo[1] = offsetof(CMIPS, m_State.nLO[1]);
|
||||
hi[0] = offsetof(CMIPS, m_State.nHI[0]);
|
||||
hi[1] = offsetof(CMIPS, m_State.nHI[1]);
|
||||
break;
|
||||
case 1:
|
||||
lo[0] = offsetof(CMIPS, m_State.nLO1[0]);
|
||||
lo[1] = offsetof(CMIPS, m_State.nLO1[1]);
|
||||
hi[0] = offsetof(CMIPS, m_State.nHI1[0]);
|
||||
hi[1] = offsetof(CMIPS, m_State.nHI1[1]);
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Invalid unit number.");
|
||||
break;
|
||||
}
|
||||
|
||||
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRS].nV[0]));
|
||||
m_codeGen->PushRel(offsetof(CMIPS, m_State.nGPR[m_nRT].nV[0]));
|
||||
function();
|
||||
|
||||
m_codeGen->SeX();
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[1]));
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nLO[0]));
|
||||
m_codeGen->PullRel(lo[1]);
|
||||
m_codeGen->PullRel(lo[0]);
|
||||
|
||||
m_codeGen->SeX();
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI[1]));
|
||||
m_codeGen->PullRel(offsetof(CMIPS, m_State.nHI[0]));
|
||||
m_codeGen->PullRel(hi[1]);
|
||||
m_codeGen->PullRel(hi[0]);
|
||||
}
|
||||
|
||||
void CMA_MIPSIV::Template_MovEqual::operator()(bool isEqual) const
|
||||
|
@ -109,6 +109,25 @@ void CMipsCodeGen::FP_PullWordTruncate(size_t offset)
|
||||
CCodeGen::FP_PullWordTruncate(offset);
|
||||
}
|
||||
|
||||
void CMipsCodeGen::MD_PushRel(size_t offset)
|
||||
{
|
||||
//Dump all four 32-bits of the variable
|
||||
for(unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
DumpVariable(offset + (i * 4));
|
||||
}
|
||||
CCodeGen::MD_PushRel(offset);
|
||||
}
|
||||
|
||||
void CMipsCodeGen::MD_PullRel(size_t offset)
|
||||
{
|
||||
for(unsigned int i = 0; i < 4; i++)
|
||||
{
|
||||
assert(GetVariableStatus(offset + (i * 4)) == NULL);
|
||||
}
|
||||
CCodeGen::MD_PullRel(offset);
|
||||
}
|
||||
|
||||
void CMipsCodeGen::EndIf()
|
||||
{
|
||||
assert(m_Shadow.GetCount() == 0);
|
||||
|
@ -19,6 +19,9 @@ public:
|
||||
virtual void FP_PullSingle(size_t);
|
||||
virtual void FP_PullWordTruncate(size_t);
|
||||
|
||||
virtual void MD_PushRel(size_t);
|
||||
virtual void MD_PullRel(size_t);
|
||||
|
||||
virtual void EndIf();
|
||||
virtual void BeginIfElseAlt();
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "PS2OS.h"
|
||||
#include "PS2VM.h"
|
||||
#include "Ps2Const.h"
|
||||
#include "StdStream.h"
|
||||
#include "PtrMacro.h"
|
||||
#include "Utils.h"
|
||||
@ -2140,7 +2140,7 @@ void CPS2OS::sc_Deci2Call()
|
||||
if(pHandler->nValid != 0)
|
||||
{
|
||||
nParam = *(uint32*)&m_ram[pHandler->nBufferAddr + 0x10];
|
||||
nParam &= (CPS2VM::RAMSIZE - 1);
|
||||
nParam &= (PS2::EERAMSIZE - 1);
|
||||
|
||||
nLength = m_ram[nParam + 0x00] - 0x0C;
|
||||
sString = &m_ram[nParam + 0x0C];
|
||||
@ -2182,7 +2182,7 @@ void CPS2OS::sc_Deci2Call()
|
||||
//7F
|
||||
void CPS2OS::sc_GetMemorySize()
|
||||
{
|
||||
m_ee.m_State.nGPR[SC_RETURN].nV[0] = CPS2VM::RAMSIZE;
|
||||
m_ee.m_State.nGPR[SC_RETURN].nV[0] = PS2::EERAMSIZE;
|
||||
m_ee.m_State.nGPR[SC_RETURN].nV[1] = 0;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <exception>
|
||||
#include "PS2VM.h"
|
||||
#include "Ps2Const.h"
|
||||
#include "IPU.h"
|
||||
#include "VIF.h"
|
||||
#include "Timer.h"
|
||||
@ -19,7 +20,8 @@
|
||||
#include "zip/ZipArchiveWriter.h"
|
||||
#include "Config.h"
|
||||
#include "Profiler.h"
|
||||
#include "IOP_FileIO.h"
|
||||
#include "iop/IopBios.h"
|
||||
#include "iop/DirectoryDevice.h"
|
||||
|
||||
#define STATE_EE ("ee")
|
||||
#define STATE_VU1 ("vu1")
|
||||
@ -28,6 +30,13 @@
|
||||
#define STATE_VUMEM1 ("vumem1")
|
||||
#define STATE_MICROMEM1 ("micromem1")
|
||||
|
||||
#define PREF_PS2_HOST_DIRECTORY ("ps2.host.directory")
|
||||
#define PREF_PS2_MC0_DIRECTORY ("ps2.mc0.directory")
|
||||
#define PREF_PS2_MC1_DIRECTORY ("ps2.mc1.directory")
|
||||
#define PREF_PS2_HOST_DIRECTORY_DEFAULT ("./vfs/host")
|
||||
#define PREF_PS2_MC0_DIRECTORY_DEFAULT ("./vfs/mc0")
|
||||
#define PREF_PS2_MC1_DIRECTORY_DEFAULT ("./vfs/mc1")
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
//#define SCREENTICKS 10000
|
||||
@ -52,9 +61,10 @@ using namespace std;
|
||||
using namespace std::tr1;
|
||||
|
||||
CPS2VM::CPS2VM() :
|
||||
m_pRAM(new uint8[RAMSIZE]),
|
||||
m_pBIOS(new uint8[BIOSSIZE]),
|
||||
m_pSPR(new uint8[SPRSIZE]),
|
||||
m_pRAM(new uint8[PS2::EERAMSIZE]),
|
||||
m_pBIOS(new uint8[PS2::EEBIOSSIZE]),
|
||||
m_pSPR(new uint8[PS2::SPRSIZE]),
|
||||
m_iopRam(new uint8[PS2::IOPRAMSIZE]),
|
||||
m_pVUMem0(NULL),
|
||||
m_pMicroMem0(NULL),
|
||||
m_pVUMem1(NULL),
|
||||
@ -62,6 +72,7 @@ m_pMicroMem1(NULL),
|
||||
m_pThread(NULL),
|
||||
m_EE(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x20000000),
|
||||
m_VU1(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x00008000),
|
||||
m_iop(MEMORYMAP_ENDIAN_LSBF, 0x00000000, 0x00400000),
|
||||
m_executor(m_EE),
|
||||
m_nStatus(PAUSED),
|
||||
m_nEnd(false),
|
||||
@ -76,12 +87,18 @@ m_gif(m_pGS, m_pRAM, m_pSPR),
|
||||
m_sif(m_dmac, m_pRAM),
|
||||
m_intc(m_dmac)
|
||||
{
|
||||
CConfig::GetInstance()->RegisterPreferenceString(PREF_PS2_HOST_DIRECTORY, PREF_PS2_HOST_DIRECTORY_DEFAULT);
|
||||
CConfig::GetInstance()->RegisterPreferenceString(PREF_PS2_MC0_DIRECTORY, PREF_PS2_MC0_DIRECTORY_DEFAULT);
|
||||
CConfig::GetInstance()->RegisterPreferenceString(PREF_PS2_MC1_DIRECTORY, PREF_PS2_MC1_DIRECTORY_DEFAULT);
|
||||
|
||||
m_os = new CPS2OS(m_EE, m_VU1, m_pRAM, m_pBIOS, m_pGS, m_sif);
|
||||
m_iopOs = new CIopBios(0x100, m_iop, m_iopRam, PS2::IOPRAMSIZE, m_sif);
|
||||
}
|
||||
|
||||
CPS2VM::~CPS2VM()
|
||||
{
|
||||
delete m_os;
|
||||
delete m_iopOs;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
@ -231,13 +248,11 @@ unsigned int CPS2VM::LoadState(const char* sPath)
|
||||
|
||||
void CPS2VM::CreateVM()
|
||||
{
|
||||
printf("PS2VM: Virtual Machine Memory Usage: RAM: %i MBs, BIOS: %i MBs, SPR: %i KBs.\r\n", RAMSIZE / 0x100000, BIOSSIZE / 0x100000, SPRSIZE / 0x1000);
|
||||
printf("PS2VM: Virtual Machine Memory Usage: RAM: %i MBs, BIOS: %i MBs, SPR: %i KBs.\r\n",
|
||||
PS2::EERAMSIZE / 0x100000, PS2::EEBIOSSIZE / 0x100000, PS2::SPRSIZE / 0x1000);
|
||||
|
||||
// m_pRAM = (uint8*)malloc(RAMSIZE);
|
||||
// m_pBIOS = (uint8*)malloc(BIOSSIZE);
|
||||
// m_pSPR = (uint8*)malloc(SPRSIZE);
|
||||
m_pVUMem1 = (uint8*)malloc(VUMEM1SIZE);
|
||||
m_pMicroMem1 = (uint8*)malloc(MICROMEM1SIZE);
|
||||
m_pVUMem1 = (uint8*)malloc(PS2::VUMEM1SIZE);
|
||||
m_pMicroMem1 = (uint8*)malloc(PS2::MICROMEM1SIZE);
|
||||
|
||||
//EmotionEngine context setup
|
||||
m_EE.m_pMemoryMap->InsertReadMap(0x00000000, 0x01FFFFFF, m_pRAM, 0x00);
|
||||
@ -296,10 +311,10 @@ void CPS2VM::ResetVM()
|
||||
{
|
||||
m_executor.Clear();
|
||||
|
||||
memset(m_pRAM, 0, RAMSIZE);
|
||||
memset(m_pSPR, 0, SPRSIZE);
|
||||
memset(m_pVUMem1, 0, VUMEM1SIZE);
|
||||
memset(m_pMicroMem1, 0, MICROMEM1SIZE);
|
||||
memset(m_pRAM, 0, PS2::EERAMSIZE);
|
||||
memset(m_pSPR, 0, PS2::SPRSIZE);
|
||||
memset(m_pVUMem1, 0, PS2::VUMEM1SIZE);
|
||||
memset(m_pMicroMem1, 0, PS2::MICROMEM1SIZE);
|
||||
|
||||
//LoadBIOS();
|
||||
|
||||
@ -336,8 +351,13 @@ void CPS2VM::ResetVM()
|
||||
// m_pOS = new CPS2OS(m_EE, m_VU1, m_pRAM, m_pBIOS, m_pGS);
|
||||
m_os->Release();
|
||||
m_os->Initialize();
|
||||
m_iopOs->Reset();
|
||||
|
||||
RegisterModulesInPadHandler();
|
||||
m_iopOs->GetIoman()->RegisterDevice("host", new CDirectoryDevice(PREF_PS2_HOST_DIRECTORY));
|
||||
m_iopOs->GetIoman()->RegisterDevice("mc0", new CDirectoryDevice(PREF_PS2_MC0_DIRECTORY));
|
||||
m_iopOs->GetIoman()->RegisterDevice("mc1", new CDirectoryDevice(PREF_PS2_MC1_DIRECTORY));
|
||||
|
||||
RegisterModulesInPadHandler();
|
||||
}
|
||||
|
||||
void CPS2VM::DestroyVM()
|
||||
@ -364,10 +384,10 @@ void CPS2VM::SaveVMState(const char* sPath, unsigned int& result)
|
||||
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_EE, &m_EE.m_State, sizeof(MIPSSTATE)));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_VU1, &m_VU1.m_State, sizeof(MIPSSTATE)));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_RAM, m_pRAM, RAMSIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_SPR, m_pSPR, SPRSIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_VUMEM1, m_pVUMem1, VUMEM1SIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_MICROMEM1, m_pMicroMem1, MICROMEM1SIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_RAM, m_pRAM, PS2::EERAMSIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_SPR, m_pSPR, PS2::SPRSIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_VUMEM1, m_pVUMem1, PS2::VUMEM1SIZE));
|
||||
archive.InsertFile(new CMemoryStateFile(STATE_MICROMEM1, m_pMicroMem1, PS2::MICROMEM1SIZE));
|
||||
|
||||
m_pGS->SaveState(archive);
|
||||
m_dmac.SaveState(archive);
|
||||
@ -405,10 +425,10 @@ void CPS2VM::LoadVMState(const char* sPath, unsigned int& result)
|
||||
|
||||
archive.BeginReadFile(STATE_EE )->Read(&m_EE.m_State, sizeof(MIPSSTATE));
|
||||
archive.BeginReadFile(STATE_VU1 )->Read(&m_VU1.m_State, sizeof(MIPSSTATE));
|
||||
archive.BeginReadFile(STATE_RAM )->Read(m_pRAM, RAMSIZE);
|
||||
archive.BeginReadFile(STATE_SPR )->Read(m_pSPR, SPRSIZE);
|
||||
archive.BeginReadFile(STATE_VUMEM1 )->Read(m_pVUMem1, VUMEM1SIZE);
|
||||
archive.BeginReadFile(STATE_MICROMEM1 )->Read(m_pMicroMem1, MICROMEM1SIZE);
|
||||
archive.BeginReadFile(STATE_RAM )->Read(m_pRAM, PS2::EERAMSIZE);
|
||||
archive.BeginReadFile(STATE_SPR )->Read(m_pSPR, PS2::SPRSIZE);
|
||||
archive.BeginReadFile(STATE_VUMEM1 )->Read(m_pVUMem1, PS2::VUMEM1SIZE);
|
||||
archive.BeginReadFile(STATE_MICROMEM1 )->Read(m_pMicroMem1, PS2::MICROMEM1SIZE);
|
||||
|
||||
m_pGS->LoadState(archive);
|
||||
m_dmac.LoadState(archive);
|
||||
@ -516,7 +536,7 @@ void CPS2VM::CDROM0_Destroy()
|
||||
void CPS2VM::LoadBIOS()
|
||||
{
|
||||
CStdStream BiosStream(fopen("./vfs/rom0/scph10000.bin", "rb"));
|
||||
BiosStream.Read(m_pBIOS, BIOSSIZE);
|
||||
BiosStream.Read(m_pBIOS, PS2::EEBIOSSIZE);
|
||||
}
|
||||
|
||||
void CPS2VM::RegisterModulesInPadHandler()
|
||||
@ -633,7 +653,7 @@ uint32 CPS2VM::IOPortWriteHandler(uint32 nAddress, uint32 nData)
|
||||
|
||||
void CPS2VM::EEMemWriteHandler(uint32 nAddress)
|
||||
{
|
||||
if(nAddress < RAMSIZE)
|
||||
if(nAddress < PS2::EERAMSIZE)
|
||||
{
|
||||
//Check if the block we're about to invalidate is the same
|
||||
//as the one we're executing in
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "VirtualMachine.h"
|
||||
#include "MipsExecutor.h"
|
||||
|
||||
class CSIF;
|
||||
class CIopBios;
|
||||
|
||||
enum PS2VM_MSG
|
||||
{
|
||||
@ -46,31 +46,6 @@ typedef CPadHandler* (*PADHANDLERFACTORY)(void*);
|
||||
class CPS2VM : public CVirtualMachine
|
||||
{
|
||||
public:
|
||||
enum PS2VM_RAMSIZE
|
||||
{
|
||||
RAMSIZE = 0x02000000,
|
||||
};
|
||||
|
||||
enum PS2VM_BIOSSIZE
|
||||
{
|
||||
BIOSSIZE = 0x00400000,
|
||||
};
|
||||
|
||||
enum PS2VM_SPRSIZE
|
||||
{
|
||||
SPRSIZE = 0x00004000,
|
||||
};
|
||||
|
||||
enum PS2VM_VUMEM1SIZE
|
||||
{
|
||||
VUMEM1SIZE = 0x00004000,
|
||||
};
|
||||
|
||||
enum PS2VM_MICROMEM1SIZE
|
||||
{
|
||||
MICROMEM1SIZE = 0x00004000,
|
||||
};
|
||||
|
||||
CPS2VM();
|
||||
virtual ~CPS2VM();
|
||||
|
||||
@ -109,12 +84,14 @@ public:
|
||||
uint8* m_pRAM;
|
||||
uint8* m_pBIOS;
|
||||
uint8* m_pSPR;
|
||||
uint8* m_iopRam;
|
||||
|
||||
CDMAC m_dmac;
|
||||
CGIF m_gif;
|
||||
CSIF m_sif;
|
||||
CINTC m_intc;
|
||||
CPS2OS* m_os;
|
||||
CIopBios* m_iopOs;
|
||||
|
||||
uint8* m_pVUMem0;
|
||||
uint8* m_pMicroMem0;
|
||||
@ -124,6 +101,7 @@ public:
|
||||
|
||||
CMIPS m_EE;
|
||||
CMIPS m_VU1;
|
||||
CMIPS m_iop;
|
||||
CMipsExecutor m_executor;
|
||||
unsigned int m_nVBlankTicks;
|
||||
bool m_nInVBlank;
|
||||
|
37
Source/Ps2Const.h
Normal file
37
Source/Ps2Const.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef _PS2CONST_H_
|
||||
#define _PS2CONST_H_
|
||||
|
||||
namespace PS2
|
||||
{
|
||||
enum EERAMSIZE
|
||||
{
|
||||
EERAMSIZE = 0x02000000,
|
||||
};
|
||||
|
||||
enum IOPRAMSIZE
|
||||
{
|
||||
IOPRAMSIZE = 0x00400000,
|
||||
};
|
||||
|
||||
enum EEBIOSSIZE
|
||||
{
|
||||
EEBIOSSIZE = 0x00400000,
|
||||
};
|
||||
|
||||
enum SPRSIZE
|
||||
{
|
||||
SPRSIZE = 0x00004000,
|
||||
};
|
||||
|
||||
enum VUMEM1SIZE
|
||||
{
|
||||
VUMEM1SIZE = 0x00004000,
|
||||
};
|
||||
|
||||
enum MICROMEM1SIZE
|
||||
{
|
||||
MICROMEM1SIZE = 0x00004000,
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,17 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include "PS2VM.h"
|
||||
#include "Ps2Const.h"
|
||||
#include "SIF.h"
|
||||
#include "PtrMacro.h"
|
||||
#include "IOP_PadMan.h"
|
||||
#include "IOP_LoadFile.h"
|
||||
#include "IOP_FileIO.h"
|
||||
#include "IOP_SysMem.h"
|
||||
#include "IOP_McServ.h"
|
||||
#include "IOP_DbcMan.h"
|
||||
#include "IOP_LibSD.h"
|
||||
#include "IOP_Cdvdfsv.h"
|
||||
#include "IOP_Dummy.h"
|
||||
#include "IOP_Unknown.h"
|
||||
#include "Profiler.h"
|
||||
#include "Log.h"
|
||||
|
||||
@ -25,6 +15,7 @@
|
||||
#endif
|
||||
|
||||
using namespace Framework;
|
||||
using namespace std;
|
||||
|
||||
CSIF::CSIF(CDMAC& dmac, uint8* eeRam) :
|
||||
m_nMAINADDR(0),
|
||||
@ -33,9 +24,10 @@ m_nMSFLAG(0),
|
||||
m_nSMFLAG(0),
|
||||
m_nEERecvAddr(0),
|
||||
m_nDataAddr(0),
|
||||
m_pPadMan(NULL),
|
||||
m_dmac(dmac),
|
||||
m_eeRam(eeRam)
|
||||
m_eeRam(eeRam),
|
||||
m_dmaBuffer(NULL),
|
||||
m_dmaBufferSize(0)
|
||||
{
|
||||
|
||||
}
|
||||
@ -78,23 +70,29 @@ void CSIF::Reset()
|
||||
// m_Module.Insert(new IOP::CDbcMan, IOP::CDbcMan::MODULE_ID);
|
||||
}
|
||||
|
||||
void CSIF::SetDmaBuffer(uint8* buffer, uint32 size)
|
||||
{
|
||||
m_dmaBuffer = buffer;
|
||||
m_dmaBufferSize = size;
|
||||
}
|
||||
|
||||
void CSIF::RegisterModule(uint32 moduleId, CSifModule* module)
|
||||
{
|
||||
m_modules[moduleId] = module;
|
||||
}
|
||||
|
||||
void CSIF::DeleteModules()
|
||||
{
|
||||
m_modules.erase(IOP::CPadMan::MODULE_ID_1);
|
||||
m_modules.erase(IOP::CPadMan::MODULE_ID_3);
|
||||
|
||||
DELETEPTR(m_pPadMan);
|
||||
|
||||
for(ModuleMap::iterator moduleIterator(m_modules.begin());
|
||||
m_modules.end() != moduleIterator; moduleIterator++)
|
||||
{
|
||||
delete moduleIterator->second;
|
||||
}
|
||||
m_modules.clear();
|
||||
}
|
||||
|
||||
uint32 CSIF::ReceiveDMA5(uint32 srcAddress, uint32 size, uint32 unused, bool isTagIncluded)
|
||||
{
|
||||
memcpy(m_eeRam + srcAddress, CSIF::m_pRAM, size);
|
||||
if(size > m_dmaBufferSize)
|
||||
{
|
||||
throw runtime_error("Packet too big.");
|
||||
}
|
||||
memcpy(m_eeRam + srcAddress, m_dmaBuffer, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -108,7 +106,7 @@ uint32 CSIF::ReceiveDMA6(uint32 nSrcAddr, uint32 nSize, uint32 nDstAddr, bool is
|
||||
PACKETHDR* pHDR;
|
||||
|
||||
//Humm, this is kinda odd, but it ors the address with 0x20000000
|
||||
nSrcAddr &= (CPS2VM::RAMSIZE - 1);
|
||||
nSrcAddr &= (PS2::EERAMSIZE - 1);
|
||||
|
||||
if(nDstAddr == RPC_RECVADDR)
|
||||
{
|
||||
@ -163,10 +161,13 @@ void CSIF::SendDMA(void* pData, uint32 nSize)
|
||||
//Humm, the DMAC doesn't know about our addresses on this side...
|
||||
uint32 nQuads;
|
||||
|
||||
memcpy(m_pRAM, pData, nSize);
|
||||
if(nSize > m_dmaBufferSize)
|
||||
{
|
||||
throw runtime_error("Packet too big.");
|
||||
}
|
||||
|
||||
nQuads = nSize / 0x10;
|
||||
if((nSize & 0x0F) != 0) nQuads++;
|
||||
memcpy(m_dmaBuffer, pData, nSize);
|
||||
nQuads = (nSize + 0x0F) / 0x10;
|
||||
|
||||
m_dmac.SetRegister(CDMAC::D5_MADR, m_nEERecvAddr);
|
||||
m_dmac.SetRegister(CDMAC::D5_QWC, nQuads);
|
||||
@ -209,23 +210,6 @@ void CSIF::SaveState(CStream* pStream)
|
||||
*/
|
||||
}
|
||||
|
||||
IOP::CPadMan* CSIF::GetPadMan()
|
||||
{
|
||||
return m_pPadMan;
|
||||
}
|
||||
|
||||
IOP::CDbcMan* CSIF::GetDbcMan()
|
||||
{
|
||||
ModuleMap::iterator moduleIterator(m_modules.find(IOP::CDbcMan::MODULE_ID));
|
||||
return moduleIterator == m_modules.end() ? NULL : static_cast<IOP::CDbcMan*>(moduleIterator->second);
|
||||
}
|
||||
|
||||
IOP::CFileIO* CSIF::GetFileIO()
|
||||
{
|
||||
ModuleMap::iterator moduleIterator(m_modules.find(IOP::CFileIO::MODULE_ID));
|
||||
return moduleIterator == m_modules.end() ? NULL : static_cast<IOP::CFileIO*>(moduleIterator->second);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
//SIF Commands
|
||||
/////////////////////////////////////////////////////////
|
||||
@ -250,7 +234,7 @@ void CSIF::Cmd_Initialize(PACKETHDR* pHDR)
|
||||
if(pInit->Header.nOptional == 0)
|
||||
{
|
||||
m_nEERecvAddr = pInit->nEEAddress;
|
||||
m_nEERecvAddr &= (CPS2VM::RAMSIZE - 1);
|
||||
m_nEERecvAddr &= (PS2::EERAMSIZE - 1);
|
||||
}
|
||||
else if(pInit->Header.nOptional == 1)
|
||||
{
|
||||
@ -312,13 +296,16 @@ void CSIF::Cmd_Call(PACKETHDR* pHDR)
|
||||
|
||||
CLog::GetInstance().Print(LOG_NAME, "Calling function 0x%0.8X of module 0x%0.8X.\r\n", pCall->nRPCNumber, pCall->nServerDataAddr);
|
||||
|
||||
nRecvAddr = (pCall->nRecv & (CPS2VM::RAMSIZE - 1));
|
||||
nRecvAddr = (pCall->nRecv & (PS2::EERAMSIZE - 1));
|
||||
|
||||
ModuleMap::iterator moduleIterator(m_modules.find(pCall->nServerDataAddr));
|
||||
if(moduleIterator != m_modules.end())
|
||||
{
|
||||
IOP::CModule* pModule(moduleIterator->second);
|
||||
pModule->Invoke(pCall->nRPCNumber, m_eeRam + m_nDataAddr, pCall->nSendSize, m_eeRam + nRecvAddr, pCall->nRecvSize);
|
||||
CSifModule* pModule(moduleIterator->second);
|
||||
pModule->Invoke(pCall->nRPCNumber,
|
||||
reinterpret_cast<uint32*>(m_eeRam + m_nDataAddr), pCall->nSendSize,
|
||||
reinterpret_cast<uint32*>(m_eeRam + nRecvAddr), pCall->nRecvSize,
|
||||
m_eeRam);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
24
Source/SIF.h
24
Source/SIF.h
@ -3,16 +3,9 @@
|
||||
|
||||
#include <map>
|
||||
#include "Stream.h"
|
||||
#include "IOP_Module.h"
|
||||
#include "SifModule.h"
|
||||
#include "DMAC.h"
|
||||
|
||||
namespace IOP
|
||||
{
|
||||
class CPadMan;
|
||||
class CDbcMan;
|
||||
class CFileIO;
|
||||
};
|
||||
|
||||
class CSIF
|
||||
{
|
||||
public:
|
||||
@ -21,6 +14,9 @@ public:
|
||||
|
||||
void Reset();
|
||||
|
||||
void RegisterModule(uint32, CSifModule*);
|
||||
void SetDmaBuffer(uint8*, uint32);
|
||||
|
||||
uint32 ReceiveDMA5(uint32, uint32, uint32, bool);
|
||||
uint32 ReceiveDMA6(uint32, uint32, uint32, bool);
|
||||
void SendDMA(void*, uint32);
|
||||
@ -31,15 +27,8 @@ public:
|
||||
void LoadState(Framework::CStream*);
|
||||
void SaveState(Framework::CStream*);
|
||||
|
||||
IOP::CPadMan* GetPadMan();
|
||||
IOP::CDbcMan* GetDbcMan();
|
||||
IOP::CFileIO* GetFileIO();
|
||||
|
||||
//This will eventually be moved in the IOP
|
||||
uint8 m_pRAM[0x1000];
|
||||
|
||||
private:
|
||||
typedef std::map<uint32, IOP::CModule*> ModuleMap;
|
||||
typedef std::map<uint32, CSifModule*> ModuleMap;
|
||||
|
||||
enum CONST_MAX_USERREG
|
||||
{
|
||||
@ -115,6 +104,8 @@ private:
|
||||
void Cmd_Call(PACKETHDR*);
|
||||
|
||||
uint8* m_eeRam;
|
||||
uint8* m_dmaBuffer;
|
||||
uint32 m_dmaBufferSize;
|
||||
CDMAC& m_dmac;
|
||||
|
||||
uint32 m_nMAINADDR;
|
||||
@ -127,7 +118,6 @@ private:
|
||||
|
||||
uint32 m_nUserReg[MAX_USERREG];
|
||||
|
||||
IOP::CPadMan* m_pPadMan;
|
||||
ModuleMap m_modules;
|
||||
};
|
||||
|
||||
|
11
Source/SifModule.h
Normal file
11
Source/SifModule.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _SIFMODULE_H_
|
||||
#define _SIFMODULE_H_
|
||||
|
||||
class CSifModule
|
||||
{
|
||||
public:
|
||||
virtual ~CSifModule() {}
|
||||
virtual void Invoke(uint32, uint32*, uint32, uint32*, uint32, uint8*) = 0;
|
||||
};
|
||||
|
||||
#endif
|
@ -397,6 +397,11 @@ void CX86Assembler::Ret()
|
||||
WriteByte(0xC3);
|
||||
}
|
||||
|
||||
void CX86Assembler::SarEd(const CAddress& address)
|
||||
{
|
||||
WriteEvOp(0xD3, 0x07, false, address);
|
||||
}
|
||||
|
||||
void CX86Assembler::SarEd(const CAddress& address, uint8 amount)
|
||||
{
|
||||
WriteEvOp(0xC1, 0x07, false, address);
|
||||
|
@ -146,6 +146,7 @@ public:
|
||||
void PushEd(const CAddress&);
|
||||
void PushId(uint32);
|
||||
void Ret();
|
||||
void SarEd(const CAddress&);
|
||||
void SarEd(const CAddress&, uint8);
|
||||
void SbbEd(REGISTER, const CAddress&);
|
||||
void SbbId(const CAddress&, uint32);
|
||||
@ -204,6 +205,7 @@ public:
|
||||
void PcmpeqdVo(XMMREGISTER, const CAddress&);
|
||||
void PorVo(XMMREGISTER, const CAddress&);
|
||||
void PsubbVo(XMMREGISTER, const CAddress&);
|
||||
void PsubdVo(XMMREGISTER, const CAddress&);
|
||||
void PxorVo(XMMREGISTER, const CAddress&);
|
||||
|
||||
void MovssEd(const CAddress&, XMMREGISTER);
|
||||
|
@ -42,6 +42,13 @@ void CX86Assembler::PsubbVo(XMMREGISTER registerId, const CAddress& address)
|
||||
WriteEdVdOp(0xF8, address, registerId);
|
||||
}
|
||||
|
||||
void CX86Assembler::PsubdVo(XMMREGISTER registerId, const CAddress& address)
|
||||
{
|
||||
WriteByte(0x66);
|
||||
WriteByte(0x0F);
|
||||
WriteEdVdOp(0xFA, address, registerId);
|
||||
}
|
||||
|
||||
void CX86Assembler::PxorVo(XMMREGISTER registerId, const CAddress& address)
|
||||
{
|
||||
WriteByte(0x66);
|
||||
|
26
Source/iop/ArgumentIterator.cpp
Normal file
26
Source/iop/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
Source/iop/ArgumentIterator.h
Normal file
18
Source/iop/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
|
52
Source/iop/DirectoryDevice.cpp
Normal file
52
Source/iop/DirectoryDevice.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include "DirectoryDevice.h"
|
||||
#include "StdStream.h"
|
||||
#include "../Config.h"
|
||||
|
||||
using namespace Framework;
|
||||
using namespace std;
|
||||
|
||||
CDirectoryDevice::CDirectoryDevice(const char* basePathPreferenceName) :
|
||||
m_basePathPreferenceName(basePathPreferenceName)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CDirectoryDevice::~CDirectoryDevice()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CStream* CDirectoryDevice::GetFile(uint32 accessType, const char* devicePath)
|
||||
{
|
||||
const char* mode(NULL);
|
||||
string path;
|
||||
|
||||
const char* basePath = CConfig::GetInstance()->GetPreferenceString(m_basePathPreferenceName.c_str());
|
||||
|
||||
path = basePath;
|
||||
if(devicePath[0] != '/')
|
||||
{
|
||||
path += "/";
|
||||
}
|
||||
path += devicePath;
|
||||
|
||||
switch(accessType)
|
||||
{
|
||||
case 0:
|
||||
case O_RDONLY:
|
||||
mode = "rb";
|
||||
break;
|
||||
case (O_RDWR | O_CREAT):
|
||||
mode = "w+";
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
FILE* stream = fopen(path.c_str(), mode);
|
||||
if(stream == NULL) return NULL;
|
||||
|
||||
return new CStdStream(stream);
|
||||
}
|
18
Source/iop/DirectoryDevice.h
Normal file
18
Source/iop/DirectoryDevice.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _DIRECTORYDEVICE_H_
|
||||
#define _DIRECTORYDEVICE_H_
|
||||
|
||||
#include <string>
|
||||
#include "Ioman_Device.h"
|
||||
|
||||
class CDirectoryDevice : public Iop::Ioman::CDevice
|
||||
{
|
||||
public:
|
||||
CDirectoryDevice(const char*);
|
||||
virtual ~CDirectoryDevice();
|
||||
virtual Framework::CStream* GetFile(uint32, const char*);
|
||||
|
||||
private:
|
||||
std::string m_basePathPreferenceName;
|
||||
};
|
||||
|
||||
#endif
|
27
Source/iop/Ioman_Device.h
Normal file
27
Source/iop/Ioman_Device.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _IOMAN_DEVICE_H_
|
||||
#define _IOMAN_DEVICE_H_
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
namespace Ioman
|
||||
{
|
||||
class CDevice
|
||||
{
|
||||
public:
|
||||
enum OPEN_FLAGS
|
||||
{
|
||||
O_RDONLY = 0x00000001,
|
||||
O_WRONLY = 0x00000002,
|
||||
O_RDWR = 0x00000003,
|
||||
O_CREAT = 0x00000200,
|
||||
};
|
||||
|
||||
virtual ~CDevice() {}
|
||||
virtual Framework::CStream* GetFile(uint32, const char*) = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
733
Source/iop/IopBios.cpp
Normal file
733
Source/iop/IopBios.cpp
Normal file
@ -0,0 +1,733 @@
|
||||
#include "IopBios.h"
|
||||
#include "../COP_SCU.h"
|
||||
#include "../Log.h"
|
||||
#include "Iop_Sysclib.h"
|
||||
#include "Iop_Loadcore.h"
|
||||
#include "Iop_Thbase.h"
|
||||
#include "Iop_Thsema.h"
|
||||
#include "Iop_Thevent.h"
|
||||
#include "Iop_Timrman.h"
|
||||
#include "Iop_Intrman.h"
|
||||
#include <vector>
|
||||
#include <time.h>
|
||||
|
||||
#define LOGNAME "iop_bios"
|
||||
|
||||
using namespace std;
|
||||
using namespace Framework;
|
||||
|
||||
CIopBios::CIopBios(uint32 baseAddress, CMIPS& cpu, uint8* ram, uint32 ramSize, CSIF& sif) :
|
||||
m_baseAddress(baseAddress),
|
||||
m_cpu(cpu),
|
||||
m_ram(ram),
|
||||
m_ramSize(ramSize),
|
||||
m_sif(sif),
|
||||
m_nextThreadId(1),
|
||||
m_nextSemaphoreId(1),
|
||||
m_stdio(NULL),
|
||||
m_sysmem(NULL),
|
||||
m_ioman(NULL),
|
||||
m_modload(NULL),
|
||||
m_rescheduleNeeded(false),
|
||||
m_currentThreadId(-1)
|
||||
{
|
||||
CMIPSAssembler assembler(reinterpret_cast<uint32*>(&m_ram[m_baseAddress]));
|
||||
m_threadFinishAddress = AssembleThreadFinish(assembler);
|
||||
}
|
||||
|
||||
CIopBios::~CIopBios()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
SaveAllModulesTags(m_cpu.m_Comments, "comments");
|
||||
SaveAllModulesTags(m_cpu.m_Functions, "functions");
|
||||
#endif
|
||||
DeleteModules();
|
||||
}
|
||||
|
||||
void CIopBios::Reset()
|
||||
{
|
||||
DeleteModules();
|
||||
|
||||
//Register built-in modules
|
||||
{
|
||||
m_stdio = new Iop::CStdio(m_ram);
|
||||
RegisterModule(m_stdio);
|
||||
}
|
||||
{
|
||||
m_ioman = new Iop::CIoman(m_ram, m_sif);
|
||||
RegisterModule(m_ioman);
|
||||
}
|
||||
{
|
||||
m_sysmem = new Iop::CSysmem(0x1000, m_ramSize, *m_stdio);
|
||||
RegisterModule(m_sysmem);
|
||||
}
|
||||
{
|
||||
m_modload = new Iop::CModload(*this, m_ram);
|
||||
RegisterModule(m_modload);
|
||||
}
|
||||
{
|
||||
RegisterModule(new Iop::CSysclib(m_ram, *m_stdio));
|
||||
}
|
||||
{
|
||||
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());
|
||||
}
|
||||
{
|
||||
RegisterModule(new Iop::CIntrman(m_ram));
|
||||
}
|
||||
|
||||
const int sifDmaBufferSize = 0x1000;
|
||||
uint32 sifDmaBufferPtr = m_sysmem->AllocateMemory(sifDmaBufferSize, 0);
|
||||
m_sif.SetDmaBuffer(m_ram + sifDmaBufferPtr, sifDmaBufferSize);
|
||||
}
|
||||
|
||||
void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned int argsLength)
|
||||
{
|
||||
ExecutableRange moduleRange;
|
||||
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);
|
||||
|
||||
typedef vector<uint32> ParamListType;
|
||||
ParamListType paramList;
|
||||
|
||||
paramList.push_back(Push(
|
||||
thread.context.gpr[CMIPS::SP],
|
||||
reinterpret_cast<const uint8*>(path),
|
||||
static_cast<uint32>(strlen(path)) + 1));
|
||||
if(argsLength != 0 && args != NULL)
|
||||
{
|
||||
paramList.push_back(Push(
|
||||
thread.context.gpr[CMIPS::SP],
|
||||
reinterpret_cast<const uint8*>(args),
|
||||
static_cast<uint32>(strlen(args)) + 1));
|
||||
}
|
||||
thread.context.gpr[CMIPS::A0] = static_cast<uint32>(paramList.size());
|
||||
for(ParamListType::reverse_iterator param(paramList.rbegin());
|
||||
paramList.rend() != param; param++)
|
||||
{
|
||||
thread.context.gpr[CMIPS::A1] = Push(
|
||||
thread.context.gpr[CMIPS::SP],
|
||||
reinterpret_cast<const uint8*>(&(*param)),
|
||||
4);
|
||||
}
|
||||
|
||||
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) == 0xB730)
|
||||
{
|
||||
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 == 0x41410)
|
||||
{
|
||||
printf("Allo: 0x%0.8X\r\n", i * 4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*reinterpret_cast<uint32*>(&m_ram[0x41674]) = 0;
|
||||
}
|
||||
|
||||
CIopBios::THREAD& CIopBios::GetThread(uint32 threadId)
|
||||
{
|
||||
return GetThreadPosition(threadId)->second;
|
||||
}
|
||||
|
||||
CIopBios::ThreadMapType::iterator CIopBios::GetThreadPosition(uint32 threadId)
|
||||
{
|
||||
for(ThreadMapType::iterator thread(m_threads.begin());
|
||||
thread != m_threads.end(); thread++)
|
||||
{
|
||||
if(thread->second.id == threadId)
|
||||
{
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
throw runtime_error("Unexisting thread id.");
|
||||
}
|
||||
|
||||
uint32 CIopBios::CreateThread(uint32 threadProc, uint32 priority)
|
||||
{
|
||||
THREAD thread;
|
||||
memset(&thread, 0, sizeof(thread));
|
||||
thread.context.delayJump = 1;
|
||||
uint32 stackBaseAddress = m_sysmem->AllocateMemory(DEFAULT_STACKSIZE, 0);
|
||||
thread.id = m_nextThreadId++;
|
||||
thread.priority = priority;
|
||||
thread.status = THREAD_STATUS_CREATED;
|
||||
thread.context.epc = threadProc;
|
||||
thread.nextActivateTime = 0;
|
||||
thread.context.gpr[CMIPS::RA] = m_threadFinishAddress;
|
||||
thread.context.gpr[CMIPS::SP] = stackBaseAddress;
|
||||
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
||||
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()
|
||||
{
|
||||
ThreadMapType::iterator thread = GetThreadPosition(m_currentThreadId);
|
||||
m_threads.erase(thread);
|
||||
m_currentThreadId = -1;
|
||||
m_rescheduleNeeded = true;
|
||||
}
|
||||
|
||||
void CIopBios::LoadThreadContext(uint32 threadId)
|
||||
{
|
||||
THREAD& thread = GetThread(threadId);
|
||||
for(unsigned int i = 0; i < 32; i++)
|
||||
{
|
||||
if(i == CMIPS::R0) continue;
|
||||
if(i == CMIPS::K0) continue;
|
||||
if(i == CMIPS::K1) continue;
|
||||
m_cpu.m_State.nGPR[i].nD0 = static_cast<int32>(thread.context.gpr[i]);
|
||||
}
|
||||
m_cpu.m_State.nPC = thread.context.epc;
|
||||
m_cpu.m_State.nDelayedJumpAddr = thread.context.delayJump;
|
||||
}
|
||||
|
||||
void CIopBios::SaveThreadContext(uint32 threadId)
|
||||
{
|
||||
THREAD& thread = GetThread(threadId);
|
||||
for(unsigned int i = 0; i < 32; i++)
|
||||
{
|
||||
if(i == CMIPS::R0) continue;
|
||||
if(i == CMIPS::K0) continue;
|
||||
if(i == CMIPS::K1) continue;
|
||||
thread.context.gpr[i] = m_cpu.m_State.nGPR[i].nV0;
|
||||
}
|
||||
thread.context.epc = m_cpu.m_State.nPC;
|
||||
thread.context.delayJump = m_cpu.m_State.nDelayedJumpAddr;
|
||||
}
|
||||
|
||||
void CIopBios::Reschedule()
|
||||
{
|
||||
if(m_currentThreadId != -1)
|
||||
{
|
||||
SaveThreadContext(m_currentThreadId);
|
||||
//Reinsert the thread into the map
|
||||
ThreadMapType::iterator threadPosition = GetThreadPosition(m_currentThreadId);
|
||||
THREAD thread(threadPosition->second);
|
||||
m_threads.erase(threadPosition);
|
||||
m_threads.insert(ThreadMapType::value_type(thread.priority, thread));
|
||||
}
|
||||
|
||||
uint32 nextThreadId = GetNextReadyThread(true);
|
||||
if(nextThreadId == -1)
|
||||
{
|
||||
//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;
|
||||
}
|
||||
|
||||
uint32 CIopBios::GetNextReadyThread(bool checkActivateTime)
|
||||
{
|
||||
if(checkActivateTime)
|
||||
{
|
||||
for(ThreadMapType::const_iterator thread(m_threads.begin());
|
||||
thread != m_threads.end(); thread++)
|
||||
{
|
||||
const THREAD& nextThread = thread->second;
|
||||
if(GetCurrentTime() <= nextThread.nextActivateTime) continue;
|
||||
if(nextThread.status == THREAD_STATUS_RUNNING)
|
||||
{
|
||||
return nextThread.id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Find the thread with the earliest wakeup time
|
||||
uint64 activateTime = -1;
|
||||
uint32 nextThreadId = -1;
|
||||
for(ThreadMapType::const_iterator thread(m_threads.begin());
|
||||
thread != m_threads.end(); thread++)
|
||||
{
|
||||
const THREAD& nextThread = thread->second;
|
||||
if(nextThread.status != THREAD_STATUS_RUNNING) continue;
|
||||
if(nextThread.nextActivateTime < activateTime)
|
||||
{
|
||||
nextThreadId = nextThread.id;
|
||||
}
|
||||
}
|
||||
return nextThreadId;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return m_ioman;
|
||||
}
|
||||
|
||||
uint32 CIopBios::AssembleThreadFinish(CMIPSAssembler& assembler)
|
||||
{
|
||||
uint32 address = m_baseAddress + assembler.GetProgramSize();
|
||||
assembler.ADDIU(CMIPS::V0, CMIPS::R0, 0x0666);
|
||||
assembler.SYSCALL();
|
||||
return address;
|
||||
}
|
||||
|
||||
void CIopBios::SysCallHandler()
|
||||
{
|
||||
uint32 searchAddress = m_cpu.m_State.nCOP0[CCOP_SCU::EPC];
|
||||
uint32 callInstruction = m_cpu.m_pMemoryMap->GetWord(searchAddress);
|
||||
if(callInstruction == 0x0000000C)
|
||||
{
|
||||
if(m_cpu.m_State.nGPR[CMIPS::V0].nV0 == 0x666)
|
||||
{
|
||||
ExitCurrentThread();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Search for the import record
|
||||
uint32 instruction = callInstruction;
|
||||
while(instruction != 0x41E00000)
|
||||
{
|
||||
searchAddress -= 4;
|
||||
instruction = m_cpu.m_pMemoryMap->GetWord(searchAddress);
|
||||
}
|
||||
uint32 functionId = callInstruction & 0xFFFF;
|
||||
uint32 version = m_cpu.m_pMemoryMap->GetWord(searchAddress + 8);
|
||||
string moduleName = ReadModuleName(searchAddress + 0x0C);
|
||||
|
||||
IopModuleMapType::iterator module(m_modules.find(moduleName));
|
||||
if(module != m_modules.end())
|
||||
{
|
||||
module->second->Invoke(m_cpu, functionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void CIopBios::DeleteModules()
|
||||
{
|
||||
while(m_modules.size() != 0)
|
||||
{
|
||||
delete m_modules.begin()->second;
|
||||
m_modules.erase(m_modules.begin());
|
||||
}
|
||||
}
|
||||
|
||||
string CIopBios::ReadModuleName(uint32 address)
|
||||
{
|
||||
string moduleName;
|
||||
while(1)
|
||||
{
|
||||
uint8 character = m_cpu.m_pMemoryMap->GetByte(address++);
|
||||
if(character == 0) break;
|
||||
if(character < 0x10) continue;
|
||||
moduleName += character;
|
||||
}
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
void CIopBios::RegisterModule(Iop::CModule* module)
|
||||
{
|
||||
m_modules[module->GetId()] = module;
|
||||
}
|
||||
|
||||
uint32 CIopBios::Push(uint32& address, const uint8* data, uint32 size)
|
||||
{
|
||||
uint32 fixedSize = ((size + 0x3) / 0x4) * 0x4;
|
||||
address -= fixedSize;
|
||||
memcpy(&m_ram[address], data, size);
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32 CIopBios::LoadExecutable(const char* path, ExecutableRange& executableRange)
|
||||
{
|
||||
uint32 handle = m_ioman->Open(Iop::Ioman::CDevice::O_RDONLY, path);
|
||||
if(handle & 0x80000000)
|
||||
{
|
||||
throw runtime_error("Couldn't open executable for reading.");
|
||||
}
|
||||
Iop::CIoman::CFile file(handle, *m_ioman);
|
||||
CStream* stream = m_ioman->GetFileStream(file);
|
||||
CELF elf(stream);
|
||||
|
||||
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);
|
||||
|
||||
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++)
|
||||
{
|
||||
ELFPROGRAMHEADER* programHeader = elf.GetProgram(i);
|
||||
if(programHeader != NULL && programHeader->nType == 1)
|
||||
{
|
||||
if(program != -1)
|
||||
{
|
||||
throw runtime_error("Multiple loadable program headers found.");
|
||||
}
|
||||
program = i;
|
||||
}
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
void CIopBios::RelocateElf(CELF& elf, uint32 baseAddress)
|
||||
{
|
||||
//Process relocation
|
||||
for(unsigned int i = 0; i < elf.m_Header.nSectHeaderCount; i++)
|
||||
{
|
||||
ELFSECTIONHEADER* sectionHeader = elf.GetSection(i);
|
||||
if(sectionHeader != NULL && sectionHeader->nType == CELF::SHT_REL)
|
||||
{
|
||||
uint32 lastHi16 = -1;
|
||||
uint32 instructionHi16 = -1;
|
||||
unsigned int linkedSection = sectionHeader->nInfo;
|
||||
unsigned int recordCount = sectionHeader->nSize / 8;
|
||||
ELFSECTIONHEADER* relocatedSection = elf.GetSection(linkedSection);
|
||||
const uint32* relocationRecord = reinterpret_cast<const uint32*>(elf.GetSectionData(i));
|
||||
uint8* relocatedSectionData = reinterpret_cast<uint8*>(const_cast<void*>(elf.GetSectionData(linkedSection)));
|
||||
if(relocatedSection == NULL || relocationRecord == NULL || relocatedSection == NULL) continue;
|
||||
uint32 sectionBase = relocatedSection->nStart;
|
||||
for(unsigned int record = 0; record < recordCount; record++)
|
||||
{
|
||||
uint32 relocationAddress = relocationRecord[0] - sectionBase;
|
||||
uint32 relocationType = relocationRecord[1];
|
||||
if(relocationAddress < relocatedSection->nSize)
|
||||
{
|
||||
uint32& instruction = *reinterpret_cast<uint32*>(&relocatedSectionData[relocationAddress]);
|
||||
switch(relocationType)
|
||||
{
|
||||
case CELF::R_MIPS_32:
|
||||
{
|
||||
instruction += baseAddress;
|
||||
}
|
||||
break;
|
||||
case CELF::R_MIPS_26:
|
||||
{
|
||||
uint32 offset = (instruction & 0x03FFFFFF) + (baseAddress >> 2);
|
||||
instruction &= ~0x03FFFFFF;
|
||||
instruction |= offset;
|
||||
}
|
||||
break;
|
||||
case CELF::R_MIPS_HI16:
|
||||
{
|
||||
lastHi16 = relocationAddress;
|
||||
instructionHi16 = instruction;
|
||||
}
|
||||
break;
|
||||
case CELF::R_MIPS_LO16:
|
||||
{
|
||||
if(lastHi16 != -1)
|
||||
{
|
||||
uint32 offset = static_cast<int16>(instruction) + (instructionHi16 << 16);
|
||||
offset += baseAddress;
|
||||
instruction &= ~0xFFFF;
|
||||
instruction |= offset & 0xFFFF;
|
||||
|
||||
uint32& prevInstruction = *reinterpret_cast<uint32*>(&relocatedSectionData[lastHi16]);
|
||||
prevInstruction &= ~0xFFFF;
|
||||
if(offset & 0x8000) offset += 0x10000;
|
||||
prevInstruction |= offset >> 16;
|
||||
lastHi16 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
CLog::GetInstance().Print(LOGNAME, "%s: No HI16 relocation record found for corresponding LO16.\r\n",
|
||||
__FUNCTION__);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("Unknown relocation type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
relocationRecord += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
142
Source/iop/IopBios.h
Normal file
142
Source/iop/IopBios.h
Normal file
@ -0,0 +1,142 @@
|
||||
#ifndef _IOPBIOS_H_
|
||||
#define _IOPBIOS_H_
|
||||
|
||||
#include <list>
|
||||
#include "../MIPSAssembler.h"
|
||||
#include "../MIPS.h"
|
||||
#include "../ELF.h"
|
||||
#include "../SIF.h"
|
||||
#include "Iop_Ioman.h"
|
||||
#include "Iop_Stdio.h"
|
||||
#include "Iop_Sysmem.h"
|
||||
#include "Iop_Modload.h"
|
||||
|
||||
class CIopBios
|
||||
{
|
||||
public:
|
||||
CIopBios(uint32, CMIPS&, uint8*, uint32, CSIF&);
|
||||
virtual ~CIopBios();
|
||||
|
||||
void LoadAndStartModule(const char*, const char*, unsigned int);
|
||||
void SysCallHandler();
|
||||
|
||||
void Reset();
|
||||
|
||||
Iop::CIoman* GetIoman();
|
||||
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:
|
||||
enum DEFAULT_STACKSIZE
|
||||
{
|
||||
DEFAULT_STACKSIZE = 0x8000,
|
||||
};
|
||||
|
||||
enum DEFAULT_PRIORITY
|
||||
{
|
||||
DEFAULT_PRIORITY = 7,
|
||||
};
|
||||
|
||||
struct THREADCONTEXT
|
||||
{
|
||||
uint32 gpr[0x20];
|
||||
uint32 epc;
|
||||
uint32 delayJump;
|
||||
};
|
||||
|
||||
struct THREAD
|
||||
{
|
||||
uint32 id;
|
||||
uint32 priority;
|
||||
THREADCONTEXT context;
|
||||
uint32 status;
|
||||
uint32 waitSemaphore;
|
||||
uint32 wakeupCount;
|
||||
uint64 nextActivateTime;
|
||||
};
|
||||
|
||||
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<uint32, SEMAPHORE> SemaphoreMapType;
|
||||
typedef std::list<LOADEDMODULE> LoadedModuleListType;
|
||||
typedef std::pair<uint32, uint32> ExecutableRange;
|
||||
|
||||
THREAD& GetThread(uint32);
|
||||
ThreadMapType::iterator GetThreadPosition(uint32);
|
||||
void ExitCurrentThread();
|
||||
void LoadThreadContext(uint32);
|
||||
void SaveThreadContext(uint32);
|
||||
void Reschedule();
|
||||
uint32 GetNextReadyThread(bool);
|
||||
uint64 GetCurrentTime();
|
||||
|
||||
SEMAPHORE& GetSemaphore(uint32);
|
||||
|
||||
uint32 LoadExecutable(const char*, ExecutableRange&);
|
||||
unsigned int GetElfProgramToLoad(CELF&);
|
||||
void RelocateElf(CELF&, 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*);
|
||||
void DeleteModules();
|
||||
uint32 Push(uint32&, const uint8*, uint32);
|
||||
|
||||
uint32 AssembleThreadFinish(CMIPSAssembler&);
|
||||
|
||||
CMIPS& m_cpu;
|
||||
CSIF& m_sif;
|
||||
uint8* m_ram;
|
||||
uint32 m_ramSize;
|
||||
uint32 m_baseAddress;
|
||||
uint32 m_threadFinishAddress;
|
||||
uint32 m_nextThreadId;
|
||||
uint32 m_nextSemaphoreId;
|
||||
uint32 m_currentThreadId;
|
||||
bool m_rescheduleNeeded;
|
||||
ThreadMapType m_threads;
|
||||
SemaphoreMapType m_semaphores;
|
||||
IopModuleMapType m_modules;
|
||||
LoadedModuleListType m_loadedModules;
|
||||
Iop::CStdio* m_stdio;
|
||||
Iop::CIoman* m_ioman;
|
||||
Iop::CSysmem* m_sysmem;
|
||||
Iop::CModload* m_modload;
|
||||
};
|
||||
|
||||
#endif
|
28
Source/iop/Iop_Dynamic.cpp
Normal file
28
Source/iop/Iop_Dynamic.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "Iop_Dynamic.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Iop;
|
||||
|
||||
CDynamic::CDynamic(uint32* exportTable) :
|
||||
m_exportTable(exportTable),
|
||||
m_name(reinterpret_cast<char*>(m_exportTable) + 12)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CDynamic::~CDynamic()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CDynamic::GetId() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void CDynamic::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
uint32 functionAddress = m_exportTable[5 + functionId];
|
||||
context.m_State.nGPR[CMIPS::RA].nD0 = context.m_State.nPC;
|
||||
context.m_State.nPC = functionAddress;
|
||||
}
|
23
Source/iop/Iop_Dynamic.h
Normal file
23
Source/iop/Iop_Dynamic.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef _IOP_DYNAMIC_H_
|
||||
#define _IOP_DYNAMIC_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CDynamic : public CModule
|
||||
{
|
||||
public:
|
||||
CDynamic(uint32*);
|
||||
virtual ~CDynamic();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
private:
|
||||
uint32* m_exportTable;
|
||||
std::string m_name;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
40
Source/iop/Iop_Intc.cpp
Normal file
40
Source/iop/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
Source/iop/Iop_Intc.h
Normal file
26
Source/iop/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
|
91
Source/iop/Iop_Intrman.cpp
Normal file
91
Source/iop/Iop_Intrman.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "Iop_Intrman.h"
|
||||
#include "../Log.h"
|
||||
#include "../COP_SCU.h"
|
||||
|
||||
#define LOGNAME "iop_intrman"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
|
||||
CIntrman::CIntrman(uint8* ram) :
|
||||
m_ram(ram)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CIntrman::~CIntrman()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CIntrman::GetId() const
|
||||
{
|
||||
return "intrman";
|
||||
}
|
||||
|
||||
void CIntrman::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 9:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(EnableInterrupts(
|
||||
context
|
||||
));
|
||||
break;
|
||||
case 17:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SuspendInterrupts(
|
||||
context,
|
||||
reinterpret_cast<uint32*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
||||
));
|
||||
break;
|
||||
case 18:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(ResumeInterrupts(
|
||||
context,
|
||||
context.m_State.nGPR[CMIPS::A0].nV0
|
||||
));
|
||||
break;
|
||||
case 23:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(QueryIntrContext(
|
||||
context
|
||||
));
|
||||
break;
|
||||
default:
|
||||
CLog::GetInstance().Print(LOGNAME, "%0.8X: Unknown function (%d) called.\r\n", context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CIntrman::EnableInterrupts(CMIPS& context)
|
||||
{
|
||||
uint32& statusRegister = context.m_State.nCOP0[CCOP_SCU::STATUS];
|
||||
statusRegister |= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 CIntrman::SuspendInterrupts(CMIPS& context, uint32* state)
|
||||
{
|
||||
uint32& statusRegister = context.m_State.nCOP0[CCOP_SCU::STATUS];
|
||||
(*state) = statusRegister & 1;
|
||||
statusRegister &= ~1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 CIntrman::ResumeInterrupts(CMIPS& context, uint32 state)
|
||||
{
|
||||
uint32& statusRegister = context.m_State.nCOP0[CCOP_SCU::STATUS];
|
||||
if(state)
|
||||
{
|
||||
statusRegister |= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
statusRegister &= ~1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 CIntrman::QueryIntrContext(CMIPS& context)
|
||||
{
|
||||
uint32& statusRegister = context.m_State.nCOP0[CCOP_SCU::STATUS];
|
||||
return (statusRegister & 0x02 ? 1 : 0);
|
||||
}
|
27
Source/iop/Iop_Intrman.h
Normal file
27
Source/iop/Iop_Intrman.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _IOP_INTRMAN_H_
|
||||
#define _IOP_INTRMAN_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CIntrman : public CModule
|
||||
{
|
||||
public:
|
||||
CIntrman(uint8*);
|
||||
virtual ~CIntrman();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
private:
|
||||
uint32 EnableInterrupts(CMIPS&);
|
||||
uint32 SuspendInterrupts(CMIPS&, uint32*);
|
||||
uint32 ResumeInterrupts(CMIPS&, uint32);
|
||||
uint32 QueryIntrContext(CMIPS&);
|
||||
uint8* m_ram;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
277
Source/iop/Iop_Ioman.cpp
Normal file
277
Source/iop/Iop_Ioman.cpp
Normal file
@ -0,0 +1,277 @@
|
||||
#include "../Config.h"
|
||||
#include "Iop_Ioman.h"
|
||||
#include "StdStream.h"
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
using namespace Framework;
|
||||
|
||||
#define PREF_IOP_FILEIO_STDLOGGING ("iop.fileio.stdlogging")
|
||||
|
||||
CIoman::CIoman(uint8* ram, CSIF& sif) :
|
||||
m_ram(ram),
|
||||
m_nextFileHandle(3)
|
||||
{
|
||||
CConfig::GetInstance()->RegisterPreferenceBoolean(PREF_IOP_FILEIO_STDLOGGING, false);
|
||||
sif.RegisterModule(SIF_MODULE_ID, this);
|
||||
|
||||
//Insert standard files if requested.
|
||||
if(CConfig::GetInstance()->GetPreferenceBoolean(PREF_IOP_FILEIO_STDLOGGING))
|
||||
{
|
||||
try
|
||||
{
|
||||
m_files[1] = new CStdStream(fopen("ps2_stdout.txt", "ab"));
|
||||
m_files[2] = new CStdStream(fopen("ps2_stderr.txt", "ab"));
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
//Humm, some error occured when opening these files...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CIoman::~CIoman()
|
||||
{
|
||||
for(FileMapType::iterator fileIterator(m_files.begin());
|
||||
m_files.end() != fileIterator; fileIterator++)
|
||||
{
|
||||
delete fileIterator->second;
|
||||
}
|
||||
for(DeviceMapType::iterator deviceIterator(m_devices.begin());
|
||||
m_devices.end() != deviceIterator; deviceIterator++)
|
||||
{
|
||||
delete deviceIterator->second;
|
||||
}
|
||||
}
|
||||
|
||||
std::string CIoman::GetId() const
|
||||
{
|
||||
return "ioman";
|
||||
}
|
||||
|
||||
void CIoman::RegisterDevice(const char* name, Ioman::CDevice* device)
|
||||
{
|
||||
m_devices[name] = device;
|
||||
}
|
||||
|
||||
uint32 CIoman::Open(uint32 flags, const char* path)
|
||||
{
|
||||
uint32 handle = 0xFFFFFFFF;
|
||||
try
|
||||
{
|
||||
string fullPath(path);
|
||||
string::size_type position = fullPath.find(":");
|
||||
if(position == string::npos)
|
||||
{
|
||||
throw runtime_error("Invalid path.");
|
||||
}
|
||||
string deviceName(fullPath.begin(), fullPath.begin() + position);
|
||||
string devicePath(fullPath.begin() + position + 1, fullPath.end());
|
||||
DeviceMapType::iterator device(m_devices.find(deviceName));
|
||||
if(device == m_devices.end())
|
||||
{
|
||||
throw runtime_error("Device not found.");
|
||||
}
|
||||
CStream* stream = device->second->GetFile(flags, devicePath.c_str());
|
||||
if(stream == NULL)
|
||||
{
|
||||
throw runtime_error("File not found.");
|
||||
}
|
||||
handle = m_nextFileHandle++;
|
||||
m_files[handle] = stream;
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to open file : %s\r\n", __FUNCTION__, except.what());
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
uint32 CIoman::Close(uint32 handle)
|
||||
{
|
||||
uint32 result = 0xFFFFFFFF;
|
||||
try
|
||||
{
|
||||
FileMapType::iterator file(m_files.find(handle));
|
||||
if(file == m_files.end())
|
||||
{
|
||||
throw runtime_error("Invalid file handle.");
|
||||
}
|
||||
delete file->second;
|
||||
m_files.erase(file);
|
||||
result = 0;
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to close file : %s\r\n", __FUNCTION__, except.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 CIoman::Read(uint32 handle, uint32 size, void* buffer)
|
||||
{
|
||||
uint32 result = 0xFFFFFFFF;
|
||||
try
|
||||
{
|
||||
CStream* stream = GetFileStream(handle);
|
||||
result = static_cast<uint32>(stream->Read(buffer, size));
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to read file : %s\r\n", __FUNCTION__, except.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 CIoman::Write(uint32 handle, uint32 size, void* buffer)
|
||||
{
|
||||
uint32 result = 0xFFFFFFFF;
|
||||
try
|
||||
{
|
||||
CStream* stream = GetFileStream(handle);
|
||||
result = static_cast<uint32>(stream->Write(buffer, size));
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to write file : %s\r\n", __FUNCTION__, except.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 CIoman::Seek(uint32 handle, uint32 position, uint32 whence)
|
||||
{
|
||||
uint32 result = 0xFFFFFFFF;
|
||||
try
|
||||
{
|
||||
CStream* stream = GetFileStream(handle);
|
||||
switch(whence)
|
||||
{
|
||||
case 0:
|
||||
whence = STREAM_SEEK_SET;
|
||||
break;
|
||||
case 1:
|
||||
whence = STREAM_SEEK_CUR;
|
||||
break;
|
||||
case 2:
|
||||
whence = STREAM_SEEK_END;
|
||||
break;
|
||||
}
|
||||
|
||||
stream->Seek(position, static_cast<STREAM_SEEK_DIRECTION>(whence));
|
||||
result = static_cast<uint32>(stream->Tell());
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to seek file : %s\r\n", __FUNCTION__, except.what());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32 CIoman::DelDrv(const char* deviceName)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
CStream* CIoman::GetFileStream(uint32 handle)
|
||||
{
|
||||
FileMapType::iterator file(m_files.find(handle));
|
||||
if(file == m_files.end())
|
||||
{
|
||||
throw runtime_error("Invalid file handle.");
|
||||
}
|
||||
return file->second;
|
||||
}
|
||||
|
||||
//IOP Invoke
|
||||
void CIoman::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 4:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Open(
|
||||
context.m_State.nGPR[CMIPS::A1].nV[0],
|
||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV[0]])
|
||||
));
|
||||
break;
|
||||
case 5:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Close(
|
||||
context.m_State.nGPR[CMIPS::A0].nV[0]
|
||||
));
|
||||
break;
|
||||
case 6:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Read(
|
||||
context.m_State.nGPR[CMIPS::A0].nV[0],
|
||||
context.m_State.nGPR[CMIPS::A2].nV[0],
|
||||
&m_ram[context.m_State.nGPR[CMIPS::A1].nV[0]]
|
||||
));
|
||||
break;
|
||||
case 8:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(Seek(
|
||||
context.m_State.nGPR[CMIPS::A0].nV[0],
|
||||
context.m_State.nGPR[CMIPS::A1].nV[0],
|
||||
context.m_State.nGPR[CMIPS::A2].nV[0]));
|
||||
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:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//SIF Invoke
|
||||
void CIoman::Invoke(uint32 method, uint32* args, uint32 argsSize, uint32* ret, uint32 retSize, uint8* ram)
|
||||
{
|
||||
switch(method)
|
||||
{
|
||||
case 0:
|
||||
assert(retSize == 4);
|
||||
*ret = Open(*args, reinterpret_cast<char*>(args) + 4);
|
||||
break;
|
||||
/*
|
||||
case 0x00000001:
|
||||
assert(nRetSize == 4);
|
||||
*(uint32*)pRet = Close(*(uint32*)pArgs);
|
||||
break;
|
||||
*/
|
||||
case 2:
|
||||
assert(retSize == 4);
|
||||
*ret = Read(args[0], args[2], reinterpret_cast<void*>(ram + args[1]));
|
||||
break;
|
||||
case 3:
|
||||
assert(retSize == 4);
|
||||
*ret = Write(args[0], args[2], reinterpret_cast<void*>(ram + args[1]));
|
||||
break;
|
||||
case 4:
|
||||
assert(retSize == 4);
|
||||
*ret = Seek(args[0], args[1], args[2]);
|
||||
break;
|
||||
default:
|
||||
printf("%s: Unknown function (%d) called.\r\n", __FUNCTION__, method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
//--------------------------------------------------
|
||||
|
||||
CIoman::CFile::CFile(uint32 handle, CIoman& ioman) :
|
||||
m_handle(handle),
|
||||
m_ioman(ioman)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CIoman::CFile::~CFile()
|
||||
{
|
||||
m_ioman.Close(m_handle);
|
||||
}
|
||||
|
||||
CIoman::CFile::operator uint32()
|
||||
{
|
||||
return m_handle;
|
||||
}
|
63
Source/iop/Iop_Ioman.h
Normal file
63
Source/iop/Iop_Ioman.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef _IOP_IOMAN_H_
|
||||
#define _IOP_IOMAN_H_
|
||||
|
||||
#include <map>
|
||||
#include "../Sif.h"
|
||||
#include "Iop_Module.h"
|
||||
#include "Ioman_Device.h"
|
||||
#include "Stream.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CIoman : public CModule, public CSifModule
|
||||
{
|
||||
public:
|
||||
class CFile
|
||||
{
|
||||
public:
|
||||
CFile(uint32, CIoman&);
|
||||
virtual ~CFile();
|
||||
|
||||
operator uint32();
|
||||
private:
|
||||
uint32 m_handle;
|
||||
CIoman& m_ioman;
|
||||
};
|
||||
|
||||
enum SIF_MODULE_ID
|
||||
{
|
||||
SIF_MODULE_ID = 0x80000001
|
||||
};
|
||||
|
||||
CIoman(uint8*, CSIF&);
|
||||
virtual ~CIoman();
|
||||
|
||||
virtual std::string GetId() const;
|
||||
virtual void Invoke(CMIPS&, unsigned int);
|
||||
virtual void Invoke(uint32, uint32*, uint32, uint32*, uint32, uint8*);
|
||||
|
||||
void RegisterDevice(const char*, Ioman::CDevice*);
|
||||
|
||||
uint32 Open(uint32, const char*);
|
||||
uint32 Close(uint32);
|
||||
uint32 Read(uint32, uint32, void*);
|
||||
uint32 Write(uint32, uint32, void*);
|
||||
uint32 Seek(uint32, uint32, uint32);
|
||||
uint32 DelDrv(const char*);
|
||||
|
||||
Framework::CStream* GetFileStream(uint32);
|
||||
|
||||
private:
|
||||
typedef std::map<uint32, Framework::CStream*> FileMapType;
|
||||
typedef std::map<std::string, Ioman::CDevice*> DeviceMapType;
|
||||
|
||||
void Open(CMIPS&);
|
||||
|
||||
FileMapType m_files;
|
||||
DeviceMapType m_devices;
|
||||
uint8* m_ram;
|
||||
uint32 m_nextFileHandle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
44
Source/iop/Iop_Loadcore.cpp
Normal file
44
Source/iop/Iop_Loadcore.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "Iop_Loadcore.h"
|
||||
#include "Iop_Dynamic.h"
|
||||
#include "IopBios.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
|
||||
CLoadcore::CLoadcore(CIopBios& bios, uint8* ram) :
|
||||
m_bios(bios),
|
||||
m_ram(ram)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CLoadcore::~CLoadcore()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CLoadcore::GetId() const
|
||||
{
|
||||
return "loadcore";
|
||||
}
|
||||
|
||||
void CLoadcore::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 6:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(RegisterLibraryEntries(
|
||||
reinterpret_cast<uint32*>(&m_ram[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 CLoadcore::RegisterLibraryEntries(uint32* exportTable)
|
||||
{
|
||||
m_bios.RegisterModule(new CDynamic(exportTable));
|
||||
return 1;
|
||||
}
|
27
Source/iop/Iop_Loadcore.h
Normal file
27
Source/iop/Iop_Loadcore.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _IOP_LOADCORE_H_
|
||||
#define _IOP_LOADCORE_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
|
||||
class CIopBios;
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CLoadcore : public CModule
|
||||
{
|
||||
public:
|
||||
CLoadcore(CIopBios&, uint8*);
|
||||
virtual ~CLoadcore();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
private:
|
||||
uint32 RegisterLibraryEntries(uint32*);
|
||||
|
||||
CIopBios& m_bios;
|
||||
uint8* m_ram;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
54
Source/iop/Iop_Modload.cpp
Normal file
54
Source/iop/Iop_Modload.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "Iop_Modload.h"
|
||||
#include "IopBios.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
using namespace Framework;
|
||||
|
||||
CModload::CModload(CIopBios& bios, uint8* ram) :
|
||||
m_bios(bios),
|
||||
m_ram(ram)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CModload::~CModload()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CModload::GetId() const
|
||||
{
|
||||
return "modload";
|
||||
}
|
||||
|
||||
void CModload::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 7:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(LoadStartModule(
|
||||
reinterpret_cast<const char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
||||
context.m_State.nGPR[CMIPS::A1].nV0,
|
||||
reinterpret_cast<const char*>(&m_ram[context.m_State.nGPR[CMIPS::A2].nV0]),
|
||||
reinterpret_cast<uint32*>(&m_ram[context.m_State.nGPR[CMIPS::A3].nV0])
|
||||
));
|
||||
break;
|
||||
default:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CModload::LoadStartModule(const char* path, uint32 argsLength, const char* args, uint32* result)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_bios.LoadAndStartModule(path, args, argsLength);
|
||||
}
|
||||
catch(const exception& except)
|
||||
{
|
||||
printf("%s: Error occured while trying to load module '%s' : %s\r\n", __FUNCTION__, path, except.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
26
Source/iop/Iop_Modload.h
Normal file
26
Source/iop/Iop_Modload.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _IOP_MODLOAD_H_
|
||||
#define _IOP_MODLOAD_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
|
||||
class CIopBios;
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CModload : public CModule
|
||||
{
|
||||
public:
|
||||
CModload(CIopBios&, uint8*);
|
||||
virtual ~CModload();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
private:
|
||||
uint32 LoadStartModule(const char*, uint32, const char*, uint32*);
|
||||
CIopBios& m_bios;
|
||||
uint8* m_ram;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
21
Source/iop/Iop_Module.h
Normal file
21
Source/iop/Iop_Module.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _IOP_MODULE_H_
|
||||
#define _IOP_MODULE_H_
|
||||
|
||||
#include <string>
|
||||
#include "../MIPS.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CModule
|
||||
{
|
||||
public:
|
||||
virtual ~CModule() {}
|
||||
virtual std::string GetId() const = 0;
|
||||
virtual void Invoke(CMIPS&, unsigned int) = 0;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
99
Source/iop/Iop_Stdio.cpp
Normal file
99
Source/iop/Iop_Stdio.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
#include "Iop_Stdio.h"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "lexical_cast_ex.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
|
||||
CStdio::CStdio(uint8* ram) :
|
||||
m_ram(ram)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CStdio::~CStdio()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CStdio::GetId() const
|
||||
{
|
||||
return "stdio";
|
||||
}
|
||||
|
||||
void CStdio::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 4:
|
||||
__printf(context);
|
||||
break;
|
||||
default:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string CStdio::PrintFormatted(CArgumentIterator& args)
|
||||
{
|
||||
string output;
|
||||
const char* format = reinterpret_cast<const char*>(&m_ram[args.GetNext()]);
|
||||
while(*format != 0)
|
||||
{
|
||||
char character = *(format++);
|
||||
if(character == '%')
|
||||
{
|
||||
bool paramDone = false;
|
||||
bool inPrecision = false;
|
||||
string precision;
|
||||
while(!paramDone && *format != 0)
|
||||
{
|
||||
char type = *(format++);
|
||||
if(type == 's')
|
||||
{
|
||||
const char* text = reinterpret_cast<const char*>(&m_ram[args.GetNext()]);
|
||||
output += text;
|
||||
paramDone = true;
|
||||
}
|
||||
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
|
||||
{
|
||||
output += character;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
void CStdio::__printf(CMIPS& context)
|
||||
{
|
||||
CArgumentIterator args(context);
|
||||
string output = PrintFormatted(args);
|
||||
printf("%s", output.c_str());
|
||||
}
|
25
Source/iop/Iop_Stdio.h
Normal file
25
Source/iop/Iop_Stdio.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef _IOP_STDIO_H_
|
||||
#define _IOP_STDIO_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
#include "ArgumentIterator.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CStdio : public CModule
|
||||
{
|
||||
public:
|
||||
CStdio(uint8*);
|
||||
virtual ~CStdio();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
void __printf(CMIPS&);
|
||||
std::string PrintFormatted(CArgumentIterator&);
|
||||
|
||||
private:
|
||||
uint8* m_ram;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
119
Source/iop/Iop_Sysclib.cpp
Normal file
119
Source/iop/Iop_Sysclib.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
#include "Iop_Sysclib.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
|
||||
CSysclib::CSysclib(uint8* ram, CStdio& stdio) :
|
||||
m_ram(ram),
|
||||
m_stdio(stdio)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CSysclib::~CSysclib()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CSysclib::GetId() const
|
||||
{
|
||||
return "sysclib";
|
||||
}
|
||||
|
||||
void CSysclib::Invoke(CMIPS& context, unsigned int 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:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
||||
__memset(
|
||||
&m_ram[context.m_State.nGPR[CMIPS::A0].nV0],
|
||||
context.m_State.nGPR[CMIPS::A1].nV0,
|
||||
context.m_State.nGPR[CMIPS::A2].nV0);
|
||||
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:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strlen(
|
||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
|
||||
));
|
||||
break;
|
||||
case 30:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = context.m_State.nGPR[CMIPS::A0].nD0;
|
||||
__strncpy(
|
||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A1].nV0]),
|
||||
context.m_State.nGPR[CMIPS::A2].nV0);
|
||||
break;
|
||||
case 36:
|
||||
assert(context.m_State.nGPR[CMIPS::A1].nV0 == 0);
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(__strtol(
|
||||
reinterpret_cast<char*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0]),
|
||||
context.m_State.nGPR[CMIPS::A2].nV0
|
||||
));
|
||||
break;
|
||||
default:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
strncpy(dst, src, count);
|
||||
}
|
||||
|
||||
uint32 CSysclib::__strtol(const char* string, unsigned int radix)
|
||||
{
|
||||
return strtol(string, NULL, radix);
|
||||
}
|
31
Source/iop/Iop_Sysclib.h
Normal file
31
Source/iop/Iop_Sysclib.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _IOP_SYSCLIB_H_
|
||||
#define _IOP_SYSCLIB_H_
|
||||
|
||||
#include "IOP_Module.h"
|
||||
#include "IOP_Stdio.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CSysclib : public CModule
|
||||
{
|
||||
public:
|
||||
CSysclib(uint8*, CStdio&);
|
||||
virtual ~CSysclib();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
private:
|
||||
void __memcpy(void*, const void*, unsigned int);
|
||||
void __memset(void*, int, unsigned int);
|
||||
uint32 __sprintf(CMIPS& context);
|
||||
uint32 __strlen(const char*);
|
||||
void __strcpy(char*, const char*);
|
||||
void __strncpy(char*, const char*, unsigned int);
|
||||
uint32 __strtol(const char*, unsigned int);
|
||||
uint8* m_ram;
|
||||
CStdio& m_stdio;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
86
Source/iop/Iop_Sysmem.cpp
Normal file
86
Source/iop/Iop_Sysmem.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "Iop_Sysmem.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
|
||||
CSysmem::CSysmem(uint32 memoryBegin, uint32 memoryEnd, CStdio& stdio) :
|
||||
m_memoryBegin(memoryBegin),
|
||||
m_memoryEnd(memoryEnd),
|
||||
m_stdio(stdio),
|
||||
m_memorySize(memoryEnd - memoryBegin)
|
||||
{
|
||||
//Initialize block map
|
||||
m_blockMap[m_memorySize] = 0;
|
||||
}
|
||||
|
||||
CSysmem::~CSysmem()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CSysmem::GetId() const
|
||||
{
|
||||
return "sysmem";
|
||||
}
|
||||
|
||||
void CSysmem::Invoke(CMIPS& context, unsigned int functionId)
|
||||
{
|
||||
switch(functionId)
|
||||
{
|
||||
case 4:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(AllocateMemory(
|
||||
context.m_State.nGPR[CMIPS::A1].nV[0],
|
||||
context.m_State.nGPR[CMIPS::A0].nV[0]
|
||||
));
|
||||
break;
|
||||
case 5:
|
||||
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(FreeMemory(
|
||||
context.m_State.nGPR[CMIPS::A0].nV[0]
|
||||
));
|
||||
break;
|
||||
case 14:
|
||||
m_stdio.__printf(context);
|
||||
break;
|
||||
default:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 CSysmem::AllocateMemory(uint32 size, uint32 flags)
|
||||
{
|
||||
uint32 begin = 0;
|
||||
const uint32 blockSize = 0x400;
|
||||
size = ((size + (blockSize - 1)) / blockSize) * blockSize;
|
||||
for(BlockMapType::iterator blockIterator(m_blockMap.begin());
|
||||
blockIterator != m_blockMap.end(); blockIterator++)
|
||||
{
|
||||
uint32 end = blockIterator->first;
|
||||
if((end - begin) >= size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
begin = blockIterator->first + blockIterator->second;
|
||||
}
|
||||
if(begin != m_memorySize)
|
||||
{
|
||||
m_blockMap[begin] = size;
|
||||
return begin + m_memoryBegin;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32 CSysmem::FreeMemory(uint32 address)
|
||||
{
|
||||
address -= m_memoryBegin;
|
||||
BlockMapType::iterator block(m_blockMap.find(address));
|
||||
if(block != m_blockMap.end())
|
||||
{
|
||||
m_blockMap.erase(block);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s: Trying to unallocate an unexisting memory block (0x%0.8X).\r\n", __FUNCTION__, address);
|
||||
}
|
||||
return 0;
|
||||
}
|
33
Source/iop/Iop_Sysmem.h
Normal file
33
Source/iop/Iop_Sysmem.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef _IOP_SYSMEM_H_
|
||||
#define _IOP_SYSMEM_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
#include "Iop_Stdio.h"
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CSysmem : public CModule
|
||||
{
|
||||
public:
|
||||
CSysmem(uint32, uint32, Iop::CStdio&);
|
||||
virtual ~CSysmem();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
uint32 AllocateMemory(uint32, uint32);
|
||||
uint32 FreeMemory(uint32);
|
||||
|
||||
private:
|
||||
typedef std::map<uint32, uint32> BlockMapType;
|
||||
|
||||
BlockMapType m_blockMap;
|
||||
uint32 m_memoryBegin;
|
||||
uint32 m_memoryEnd;
|
||||
uint32 m_memorySize;
|
||||
Iop::CStdio& m_stdio;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif
|
92
Source/iop/Iop_Thbase.cpp
Normal file
92
Source/iop/Iop_Thbase.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "Iop_Thbase.h"
|
||||
#include "IopBios.h"
|
||||
|
||||
using namespace Iop;
|
||||
using namespace std;
|
||||
|
||||
CThbase::CThbase(CIopBios& bios, uint8* ram) :
|
||||
m_ram(ram),
|
||||
m_bios(bios)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CThbase::~CThbase()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string CThbase::GetId() const
|
||||
{
|
||||
return "thbase";
|
||||
}
|
||||
|
||||
void CThbase::Invoke(CMIPS& context, unsigned int 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:
|
||||
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
|
||||
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);
|
||||
}
|
41
Source/iop/Iop_Thbase.h
Normal file
41
Source/iop/Iop_Thbase.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef _IOP_THBASE_H_
|
||||
#define _IOP_THBASE_H_
|
||||
|
||||
#include "Iop_Module.h"
|
||||
|
||||
class CIopBios;
|
||||
|
||||
namespace Iop
|
||||
{
|
||||
class CThbase : public CModule
|
||||
{
|
||||
public:
|
||||
CThbase(CIopBios&, uint8*);
|
||||
virtual ~CThbase();
|
||||
|
||||
std::string GetId() const;
|
||||
void Invoke(CMIPS&, unsigned int);
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
39
Source/iop/Iop_Thevent.cpp
Normal file
39
Source/iop/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
Source/iop/Iop_Thevent.h
Normal file
27
Source/iop/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
Source/iop/Iop_Thsema.cpp
Normal file
62
Source/iop/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
Source/iop/Iop_Thsema.h
Normal file
36
Source/iop/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
Source/iop/Iop_Timrman.cpp
Normal file
34
Source/iop/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
Source/iop/Iop_Timrman.h
Normal file
22
Source/iop/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
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user