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:
jpd002 2008-01-15 20:27:44 +00:00
parent 07657fd612
commit 669ac71159
81 changed files with 2994 additions and 2885 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1155,6 +1155,8 @@ void CGSH_OpenGL::DisplayTransferedImage(uint32 nAddress)
glBindTexture(GL_TEXTURE_2D, NULL);
glDeleteTextures(1, &nTexture);
FlipImpl();
}
void CGSH_OpenGL::SetVBlank()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,26 @@
#include "ArgumentIterator.h"
CArgumentIterator::CArgumentIterator(CMIPS& context) :
m_context(context),
m_current(0)
{
}
CArgumentIterator::~CArgumentIterator()
{
}
uint32 CArgumentIterator::GetNext()
{
if(m_current > 3)
{
uint32 address = m_context.m_State.nGPR[CMIPS::SP].nV0 + (m_current++ - 4) * 4 + 0x10;
return m_context.m_pMemoryMap->GetWord(address);
}
else
{
return m_context.m_State.nGPR[CMIPS::A0 + m_current++].nV[0];
}
}

View File

@ -0,0 +1,18 @@
#ifndef _ARGUMENT_ITERATOR_H_
#define _ARGUMENT_ITERATOR_H_
#include "../MIPS.h"
class CArgumentIterator
{
public:
CArgumentIterator(CMIPS&);
virtual ~CArgumentIterator();
uint32 GetNext();
private:
unsigned int m_current;
CMIPS& m_context;
};
#endif

View File

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

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

View 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
View 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
View File

@ -0,0 +1,40 @@
#include "Iop_Intc.h"
using namespace Iop;
CIntc::CIntc() :
m_mask(0),
m_status(0)
{
}
CIntc::~CIntc()
{
}
void CIntc::AssertLine(unsigned int line)
{
m_status |= 1 << line;
}
void CIntc::ClearLine(unsigned int line)
{
m_status &= ~(1 << line);
}
void CIntc::SetMask(uint32 mask)
{
m_mask = mask;
}
void CIntc::SetStatus(uint32 status)
{
m_status = status;
}
bool CIntc::HasPendingInterrupt()
{
return (m_mask & m_status) != 0;
}

26
Source/iop/Iop_Intc.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef _IOP_INTC_H_
#define _IOP_INTC_H_
#include "Types.h"
namespace Iop
{
class CIntc
{
public:
CIntc();
virtual ~CIntc();
void AssertLine(unsigned int);
void ClearLine(unsigned int);
void SetStatus(uint32);
void SetMask(uint32);
bool HasPendingInterrupt();
private:
uint32 m_status;
uint32 m_mask;
};
}
#endif

View File

@ -0,0 +1,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
View 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
View 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
View 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

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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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, &param);
return 1;
}
uint32 CThbase::DelayThread(uint32 delay)
{
m_bios.DelayThread(delay);
return 1;
}
uint32 CThbase::GetThreadId()
{
return m_bios.GetThreadId();
}
uint32 CThbase::SleepThread()
{
m_bios.SleepThread();
return 1;
}
uint32 CThbase::WakeupThread(uint32 threadId)
{
return m_bios.WakeupThread(threadId);
}

41
Source/iop/Iop_Thbase.h Normal file
View 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

View File

@ -0,0 +1,39 @@
#include "Iop_Thevent.h"
using namespace Iop;
using namespace std;
CThevent::CThevent(CIopBios& bios, uint8* ram) :
m_bios(bios),
m_ram(ram)
{
}
CThevent::~CThevent()
{
}
string CThevent::GetId() const
{
return "thevent";
}
void CThevent::Invoke(CMIPS& context, unsigned int functionId)
{
switch(functionId)
{
case 4:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(CreateEventFlag());
break;
default:
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
break;
}
}
uint32 CThevent::CreateEventFlag()
{
return 3;
}

27
Source/iop/Iop_Thevent.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _IOP_THEVENT_H_
#define _IOP_THEVENT_H_
#include "Iop_Module.h"
class CIopBios;
namespace Iop
{
class CThevent : public CModule
{
public:
CThevent(CIopBios&, uint8*);
virtual ~CThevent();
std::string GetId() const;
void Invoke(CMIPS&, unsigned int);
private:
uint32 CreateEventFlag();
uint8* m_ram;
CIopBios& m_bios;
};
}
#endif

62
Source/iop/Iop_Thsema.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "Iop_Thsema.h"
#include "IopBios.h"
using namespace Iop;
using namespace std;
CThsema::CThsema(CIopBios& bios, uint8* ram) :
m_bios(bios),
m_ram(ram)
{
}
CThsema::~CThsema()
{
}
string CThsema::GetId() const
{
return "thsemap";
}
void CThsema::Invoke(CMIPS& context, unsigned int functionId)
{
switch(functionId)
{
case 4:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(CreateSemaphore(
reinterpret_cast<SEMAPHORE*>(&m_ram[context.m_State.nGPR[CMIPS::A0].nV0])
));
break;
case 6:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(SignalSemaphore(
context.m_State.nGPR[CMIPS::A0].nV0
));
break;
case 8:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(WaitSemaphore(
context.m_State.nGPR[CMIPS::A0].nV0
));
break;
default:
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
break;
}
}
uint32 CThsema::CreateSemaphore(const SEMAPHORE* semaphore)
{
return m_bios.CreateSemaphore(semaphore->initialCount, semaphore->maxCount);
}
uint32 CThsema::SignalSemaphore(uint32 semaphoreId)
{
return m_bios.SignalSemaphore(semaphoreId);
}
uint32 CThsema::WaitSemaphore(uint32 semaphoreId)
{
return m_bios.WaitSemaphore(semaphoreId);
}

36
Source/iop/Iop_Thsema.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef _IOP_THSEMA_H_
#define _IOP_THSEMA_H_
#include "Iop_Module.h"
#include "IopBios.h"
namespace Iop
{
class CThsema : public CModule
{
public:
CThsema(CIopBios&, uint8*);
virtual ~CThsema();
std::string GetId() const;
void Invoke(CMIPS&, unsigned int);
private:
struct SEMAPHORE
{
uint32 attributes;
uint32 options;
uint32 initialCount;
uint32 maxCount;
};
uint32 CreateSemaphore(const SEMAPHORE*);
uint32 WaitSemaphore(uint32);
uint32 SignalSemaphore(uint32);
uint8* m_ram;
CIopBios& m_bios;
};
}
#endif

View File

@ -0,0 +1,34 @@
#include "Iop_Timrman.h"
using namespace Iop;
using namespace std;
CTimrman::CTimrman()
{
}
CTimrman::~CTimrman()
{
}
string CTimrman::GetId() const
{
return "timrman";
}
void CTimrman::Invoke(CMIPS& context, unsigned int functionId)
{
switch(functionId)
{
case 20:
context.m_State.nGPR[CMIPS::V0].nD0 = 0;
printf("Timrman: Install handler.\r\n");
break;
default:
printf("%s(%0.8X): Unknown function (%d) called.\r\n", __FUNCTION__, context.m_State.nPC, functionId);
break;
}
}

22
Source/iop/Iop_Timrman.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef _TIMRMAN_H_
#define _TIMRMAN_H_
#include "Iop_Module.h"
namespace Iop
{
class CTimrman : public CModule
{
public:
CTimrman();
virtual ~CTimrman();
std::string GetId() const;
void Invoke(CMIPS&, unsigned int);
private:
};
}
#endif

Binary file not shown.