mirror of https://github.com/PCSX2/pcsx2.git
IOP: Convert most IOP memory access in the IRX HLE and debugging module to
safe access through iopMem* functions.
This commit is contained in:
parent
d3a748ce3a
commit
b3b1f3ac68
|
@ -91,10 +91,42 @@ namespace R3000A {
|
||||||
#define ra (psxRegs.GPR.n.ra)
|
#define ra (psxRegs.GPR.n.ra)
|
||||||
#define pc (psxRegs.pc)
|
#define pc (psxRegs.pc)
|
||||||
|
|
||||||
#define Ra0 (iopVirtMemR<char>(a0))
|
#define Ra0 (iopMemReadString(a0))
|
||||||
#define Ra1 (iopVirtMemR<char>(a1))
|
#define Ra1 (iopMemReadString(a1))
|
||||||
#define Ra2 (iopVirtMemR<char>(a2))
|
#define Ra2 (iopMemReadString(a2))
|
||||||
#define Ra3 (iopVirtMemR<char>(a3))
|
#define Ra3 (iopMemReadString(a3))
|
||||||
|
|
||||||
|
static std::string host_path(const std::string path)
|
||||||
|
{
|
||||||
|
// WIP code. Works well on win32, not so sure on unixes
|
||||||
|
// TODO: get rid of dependency on CWD/PWD
|
||||||
|
#if USE_HOST_REWRITE
|
||||||
|
// we want filenames to be relative to pcs2dir / host
|
||||||
|
|
||||||
|
std::string pathMod;
|
||||||
|
|
||||||
|
// partial "rooting",
|
||||||
|
// it will NOT avoid a path like "../../x" from escaping the pcsx2 folder!
|
||||||
|
|
||||||
|
|
||||||
|
const std::string _local_root = "/usr/local/";
|
||||||
|
if (HOST_REWRITE_USR_LOCAL && 0 == path.compare(0, _local_root.size(), _local_root.data())) {
|
||||||
|
return HostRoot + path.substr(_local_root.size());
|
||||||
|
} else if ((path[0] == '/') || (path[0] == '\\') || (isalpha(path[0]) && (path[1] == ':'))) // absolute NATIVE path (X:\blah)
|
||||||
|
{
|
||||||
|
// TODO: allow some way to use native paths in non-windows platforms
|
||||||
|
// maybe hack it so linux prefixes the path with "X:"? ;P
|
||||||
|
// or have all platforms use a common prefix for native paths
|
||||||
|
// FIXME: Why the hell would we allow this?
|
||||||
|
return path;
|
||||||
|
} else // relative paths
|
||||||
|
return HostRoot + path;
|
||||||
|
|
||||||
|
return pathMod;
|
||||||
|
#else
|
||||||
|
return path;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: sandbox option, other permissions
|
// TODO: sandbox option, other permissions
|
||||||
class HostFile : public IOManFile
|
class HostFile : public IOManFile
|
||||||
|
@ -128,49 +160,14 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open(IOManFile **file, const char *name, s32 flags, u16 mode)
|
static int open(IOManFile **file, const std::string &full_path, s32 flags, u16 mode)
|
||||||
{
|
{
|
||||||
const char *path = strchr(name, ':') + 1;
|
const std::string path = full_path.substr(full_path.rfind(':') + 1);
|
||||||
|
|
||||||
// host: actually DOES let you write!
|
// host: actually DOES let you write!
|
||||||
//if (flags != IOP_O_RDONLY)
|
//if (flags != IOP_O_RDONLY)
|
||||||
// return -IOP_EROFS;
|
// return -IOP_EROFS;
|
||||||
|
|
||||||
// WIP code. Works well on win32, not so sure on unixes
|
|
||||||
// TODO: get rid of dependency on CWD/PWD
|
|
||||||
#if USE_HOST_REWRITE
|
|
||||||
// we want filenames to be relative to pcs2dir / host
|
|
||||||
|
|
||||||
static char pathMod[1024];
|
|
||||||
|
|
||||||
// partial "rooting",
|
|
||||||
// it will NOT avoid a path like "../../x" from escaping the pcsx2 folder!
|
|
||||||
|
|
||||||
#if HOST_REWRITE_USR_LOCAL
|
|
||||||
const char *_local_root = "/usr/local/";
|
|
||||||
if(strncmp(path,_local_root,strlen(_local_root))==0)
|
|
||||||
{
|
|
||||||
strcpy(pathMod,HostRoot);
|
|
||||||
strcat(pathMod,path+strlen(_local_root));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if((path[0] == '/') || (path[0] == '\\') || (isalpha(path[0]) && (path[1] == ':'))) // absolute NATIVE path (X:\blah)
|
|
||||||
{
|
|
||||||
// TODO: allow some way to use native paths in non-windows platforms
|
|
||||||
// maybe hack it so linux prefixes the path with "X:"? ;P
|
|
||||||
// or have all platforms use a common prefix for native paths
|
|
||||||
strcpy(pathMod,path);
|
|
||||||
}
|
|
||||||
else // relative paths
|
|
||||||
{
|
|
||||||
strcpy(pathMod,HostRoot);
|
|
||||||
strcat(pathMod,path);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const char* pathMod = path;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int native_flags = O_BINARY; // necessary in Windows.
|
int native_flags = O_BINARY; // necessary in Windows.
|
||||||
|
|
||||||
switch(flags&IOP_O_RDWR)
|
switch(flags&IOP_O_RDWR)
|
||||||
|
@ -184,7 +181,7 @@ public:
|
||||||
if(flags&IOP_O_CREAT) native_flags |= O_CREAT;
|
if(flags&IOP_O_CREAT) native_flags |= O_CREAT;
|
||||||
if(flags&IOP_O_TRUNC) native_flags |= O_TRUNC;
|
if(flags&IOP_O_TRUNC) native_flags |= O_TRUNC;
|
||||||
|
|
||||||
int hostfd = ::open(pathMod, native_flags);
|
int hostfd = ::open(host_path(path).data(), native_flags);
|
||||||
if (hostfd < 0)
|
if (hostfd < 0)
|
||||||
return translate_error(hostfd);
|
return translate_error(hostfd);
|
||||||
|
|
||||||
|
@ -328,15 +325,21 @@ namespace ioman {
|
||||||
fds[i].close();
|
fds[i].close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_host(const std::string path)
|
||||||
|
{
|
||||||
|
if ((!g_GameStarted || EmuConfig.HostFs) && 0 == path.compare(0, 4, "host") && path[path.find_first_not_of("0123456789", 4)] == ':')
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int open_HLE()
|
int open_HLE()
|
||||||
{
|
{
|
||||||
IOManFile *file = NULL;
|
IOManFile *file = NULL;
|
||||||
const char *name = Ra0;
|
const std::string path = Ra0;
|
||||||
s32 flags = a1;
|
s32 flags = a1;
|
||||||
u16 mode = a2;
|
u16 mode = a2;
|
||||||
|
|
||||||
if ((!g_GameStarted || EmuConfig.HostFs)
|
if (is_host(path))
|
||||||
&& !strncmp(name, "host", 4) && name[4 + strspn(name + 4, "0123456789")] == ':')
|
|
||||||
{
|
{
|
||||||
if (!freefdcount())
|
if (!freefdcount())
|
||||||
{
|
{
|
||||||
|
@ -345,7 +348,7 @@ namespace ioman {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = HostFile::open(&file, name, flags, mode);
|
int err = HostFile::open(&file, path, flags, mode);
|
||||||
|
|
||||||
if (err != 0 || !file)
|
if (err != 0 || !file)
|
||||||
{
|
{
|
||||||
|
@ -403,15 +406,26 @@ namespace ioman {
|
||||||
int read_HLE()
|
int read_HLE()
|
||||||
{
|
{
|
||||||
s32 fd = a0;
|
s32 fd = a0;
|
||||||
u32 buf = a1;
|
u32 data = a1;
|
||||||
u32 count = a2;
|
u32 count = a2;
|
||||||
|
|
||||||
if (IOManFile *file = getfd<IOManFile>(fd))
|
if (IOManFile *file = getfd<IOManFile>(fd))
|
||||||
{
|
{
|
||||||
if (!iopVirtMemR<void>(buf))
|
char *buf;
|
||||||
return 0;
|
try {
|
||||||
|
buf = new char[count];
|
||||||
v0 = file->read(iopVirtMemW<void>(buf), count);
|
v0 = file->read(buf, count);
|
||||||
|
}
|
||||||
|
catch (const std::bad_alloc &) {
|
||||||
|
v0 = -IOP_ENOMEM;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
delete[] buf;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
for (s32 i = 0; i < (s32)v0; i++)
|
||||||
|
iopMemWrite8(data + i, buf[i]);
|
||||||
|
delete[] buf;
|
||||||
pc = ra;
|
pc = ra;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -422,22 +436,32 @@ namespace ioman {
|
||||||
int write_HLE()
|
int write_HLE()
|
||||||
{
|
{
|
||||||
s32 fd = a0;
|
s32 fd = a0;
|
||||||
u32 buf = a1;
|
u32 data = a1;
|
||||||
u32 count = a2;
|
u32 count = a2;
|
||||||
|
|
||||||
if (fd == 1) // stdout
|
if (fd == 1) // stdout
|
||||||
{
|
{
|
||||||
iopConLog(ShiftJIS_ConvertString(Ra1, a2));
|
const std::string s = Ra1;
|
||||||
|
iopConLog(ShiftJIS_ConvertString(s.data(), a2));
|
||||||
pc = ra;
|
pc = ra;
|
||||||
v0 = a2;
|
v0 = a2;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (IOManFile *file = getfd<IOManFile>(fd))
|
else if (IOManFile *file = getfd<IOManFile>(fd))
|
||||||
{
|
{
|
||||||
if (!iopVirtMemR<void>(buf))
|
char *buf = NULL;
|
||||||
return 0;
|
try {
|
||||||
|
buf = new char[count];
|
||||||
v0 = file->write(iopVirtMemW<void>(buf), count);
|
for (u32 i = 0; i < count; i++)
|
||||||
|
buf[i] = iopMemRead8(data + i);
|
||||||
|
v0 = file->write(buf, count);
|
||||||
|
} catch (const std::bad_alloc &) {
|
||||||
|
v0 = -IOP_ENOMEM;
|
||||||
|
} catch (...) {
|
||||||
|
delete[] buf;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
delete[] buf;
|
||||||
pc = ra;
|
pc = ra;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -456,6 +480,7 @@ namespace sysmem {
|
||||||
iopMemWrite32(sp + 12, a3);
|
iopMemWrite32(sp + 12, a3);
|
||||||
pc = ra;
|
pc = ra;
|
||||||
|
|
||||||
|
const std::string fmt = Ra0;
|
||||||
|
|
||||||
// From here we're intercepting the Kprintf and piping it to our console, complete with
|
// From here we're intercepting the Kprintf and piping it to our console, complete with
|
||||||
// printf-style formatting processing. This part can be skipped if the user has the
|
// printf-style formatting processing. This part can be skipped if the user has the
|
||||||
|
@ -467,33 +492,33 @@ namespace sysmem {
|
||||||
char *ptmp = tmp;
|
char *ptmp = tmp;
|
||||||
int n=1, i=0, j = 0;
|
int n=1, i=0, j = 0;
|
||||||
|
|
||||||
while (Ra0[i])
|
while (fmt[i])
|
||||||
{
|
{
|
||||||
switch (Ra0[i])
|
switch (fmt[i])
|
||||||
{
|
{
|
||||||
case '%':
|
case '%':
|
||||||
j = 0;
|
j = 0;
|
||||||
tmp2[j++] = '%';
|
tmp2[j++] = '%';
|
||||||
_start:
|
_start:
|
||||||
switch (Ra0[++i])
|
switch (fmt[++i])
|
||||||
{
|
{
|
||||||
case '.':
|
case '.':
|
||||||
case 'l':
|
case 'l':
|
||||||
tmp2[j++] = Ra0[i];
|
tmp2[j++] = fmt[i];
|
||||||
goto _start;
|
goto _start;
|
||||||
default:
|
default:
|
||||||
if (Ra0[i] >= '0' && Ra0[i] <= '9')
|
if (fmt[i] >= '0' && fmt[i] <= '9')
|
||||||
{
|
{
|
||||||
tmp2[j++] = Ra0[i];
|
tmp2[j++] = fmt[i];
|
||||||
goto _start;
|
goto _start;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp2[j++] = Ra0[i];
|
tmp2[j++] = fmt[i];
|
||||||
tmp2[j] = 0;
|
tmp2[j] = 0;
|
||||||
|
|
||||||
switch (Ra0[i])
|
switch (fmt[i])
|
||||||
{
|
{
|
||||||
case 'f': case 'F':
|
case 'f': case 'F':
|
||||||
ptmp+= sprintf(ptmp, tmp2, (float)iopMemRead32(sp + n * 4));
|
ptmp+= sprintf(ptmp, tmp2, (float)iopMemRead32(sp + n * 4));
|
||||||
|
@ -522,12 +547,15 @@ _start:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
ptmp+= sprintf(ptmp, tmp2, iopVirtMemR<char>(iopMemRead32(sp + n * 4)));
|
{
|
||||||
|
std::string s = iopMemReadString(iopMemRead32(sp + n * 4));
|
||||||
|
ptmp += sprintf(ptmp, tmp2, s.data());
|
||||||
n++;
|
n++;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
*ptmp++ = Ra0[i];
|
*ptmp++ = fmt[i];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -537,7 +565,7 @@ _start:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*ptmp++ = Ra0[i++];
|
*ptmp++ = fmt[i++];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -551,7 +579,8 @@ _start:
|
||||||
namespace loadcore {
|
namespace loadcore {
|
||||||
void RegisterLibraryEntries_DEBUG()
|
void RegisterLibraryEntries_DEBUG()
|
||||||
{
|
{
|
||||||
DevCon.WriteLn(Color_Gray, "RegisterLibraryEntries: %8.8s", iopVirtMemR<char>(a0 + 12));
|
const std::string modname = iopMemReadString(a0 + 12);
|
||||||
|
DevCon.WriteLn(Color_Gray, "RegisterLibraryEntries: %8.8s version %x.%02x", modname.data(), (unsigned)iopMemRead8(a0 + 9), (unsigned)iopMemRead8(a0 + 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,18 +618,21 @@ namespace sifcmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* irxImportLibname(u32 entrypc)
|
const u32 irxImportTableAddr(u32 entrypc)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
|
|
||||||
i = entrypc;
|
i = entrypc - 0x18;
|
||||||
while (iopMemRead32(i -= 4) != 0x41e00000) // documented magic number
|
while (entrypc - i < 0x2000) {
|
||||||
;
|
if (iopMemRead32(i) == 0x41e00000)
|
||||||
|
return i;
|
||||||
|
i -= 4;
|
||||||
|
}
|
||||||
|
|
||||||
return iopVirtMemR<char>(i + 12);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* irxImportFuncname(const char libname[8], u16 index)
|
const char* irxImportFuncname(const std::string &libname, u16 index)
|
||||||
{
|
{
|
||||||
#include "IopModuleNames.cpp"
|
#include "IopModuleNames.cpp"
|
||||||
|
|
||||||
|
@ -614,12 +646,12 @@ const char* irxImportFuncname(const char libname[8], u16 index)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MODULE(n) if (!strncmp(libname, #n, 8)) { using namespace n; switch (index) {
|
#define MODULE(n) if (#n == libname) { using namespace n; switch (index) {
|
||||||
#define END_MODULE }}
|
#define END_MODULE }}
|
||||||
#define EXPORT_D(i, n) case (i): return n ## _DEBUG;
|
#define EXPORT_D(i, n) case (i): return n ## _DEBUG;
|
||||||
#define EXPORT_H(i, n) case (i): return n ## _HLE;
|
#define EXPORT_H(i, n) case (i): return n ## _HLE;
|
||||||
|
|
||||||
irxHLE irxImportHLE(const char libname[8], u16 index)
|
irxHLE irxImportHLE(const std::string &libname, u16 index)
|
||||||
{
|
{
|
||||||
// debugging output
|
// debugging output
|
||||||
MODULE(sysmem)
|
MODULE(sysmem)
|
||||||
|
@ -637,7 +669,7 @@ irxHLE irxImportHLE(const char libname[8], u16 index)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
irxDEBUG irxImportDebug(const char libname[8], u16 index)
|
irxDEBUG irxImportDebug(const std::string &libname, u16 index)
|
||||||
{
|
{
|
||||||
MODULE(loadcore)
|
MODULE(loadcore)
|
||||||
EXPORT_D( 6, RegisterLibraryEntries)
|
EXPORT_D( 6, RegisterLibraryEntries)
|
||||||
|
@ -657,15 +689,24 @@ irxDEBUG irxImportDebug(const char libname[8], u16 index)
|
||||||
#undef EXPORT_D
|
#undef EXPORT_D
|
||||||
#undef EXPORT_H
|
#undef EXPORT_H
|
||||||
|
|
||||||
void __fastcall irxImportLog(const char libname[8], u16 index, const char *funcname)
|
void irxImportLog(const std::string &libname, u16 index, const char *funcname)
|
||||||
{
|
{
|
||||||
PSXBIOS_LOG("%8.8s.%03d: %s (%x, %x, %x, %x)",
|
PSXBIOS_LOG("%8.8s.%03d: %s (%x, %x, %x, %x)",
|
||||||
libname, index, funcname ? funcname : "unknown",
|
libname.data(), index, funcname ? funcname : "unknown",
|
||||||
a0, a1, a2, a3);
|
a0, a1, a2, a3);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __fastcall irxImportExec(const char libname[8], u16 index)
|
void __fastcall irxImportLog_rec(u32 import_table, u16 index, const char *funcname)
|
||||||
{
|
{
|
||||||
|
irxImportLog(iopMemReadString(import_table + 12, 8), index, funcname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int irxImportExec(u32 import_table, u16 index)
|
||||||
|
{
|
||||||
|
if (!import_table)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
std::string libname = iopMemReadString(import_table + 12, 8);
|
||||||
const char *funcname = irxImportFuncname(libname, index);
|
const char *funcname = irxImportFuncname(libname, index);
|
||||||
irxHLE hle = irxImportHLE(libname, index);
|
irxHLE hle = irxImportHLE(libname, index);
|
||||||
irxDEBUG debug = irxImportDebug(libname, index);
|
irxDEBUG debug = irxImportDebug(libname, index);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define IOP_EIO 5
|
#define IOP_EIO 5
|
||||||
#define IOP_ENOMEM 12
|
#define IOP_ENOMEM 12
|
||||||
#define IOP_EACCES 13
|
#define IOP_EACCES 13
|
||||||
|
#define IOP_ENODEV 19
|
||||||
#define IOP_EISDIR 21
|
#define IOP_EISDIR 21
|
||||||
#define IOP_EMFILE 24
|
#define IOP_EMFILE 24
|
||||||
#define IOP_EROFS 30
|
#define IOP_EROFS 30
|
||||||
|
@ -38,7 +39,10 @@
|
||||||
|
|
||||||
class IOManFile {
|
class IOManFile {
|
||||||
public:
|
public:
|
||||||
// int open(IOManFile **file, char *name, s32 flags, u16 mode);
|
static int open(IOManFile **file, const std::string &path, s32 flags, u16 mode)
|
||||||
|
{
|
||||||
|
return -IOP_ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
|
|
||||||
|
@ -59,12 +63,13 @@ typedef void (*irxDEBUG)();
|
||||||
|
|
||||||
namespace R3000A
|
namespace R3000A
|
||||||
{
|
{
|
||||||
const char* irxImportLibname(u32 entrypc);
|
const u32 irxImportTableAddr(u32 entrypc);
|
||||||
const char* irxImportFuncname(const char libname[8], u16 index);
|
const char* irxImportFuncname(const std::string &libname, u16 index);
|
||||||
irxHLE irxImportHLE(const char libname[8], u16 index);
|
irxHLE irxImportHLE(const std::string &libnam, u16 index);
|
||||||
irxDEBUG irxImportDebug(const char libname[8], u16 index);
|
irxDEBUG irxImportDebug(const std::string & libname, u16 index);
|
||||||
void __fastcall irxImportLog(const char libname[8], u16 index, const char *funcname);
|
void irxImportLog(const std::string &libnameptr, u16 index, const char *funcname);
|
||||||
int __fastcall irxImportExec(const char libname[8], u16 index);
|
void __fastcall irxImportLog_rec(u32 import_table, u16 index, const char *funcname);
|
||||||
|
int irxImportExec(u32 import_table, u16 index);
|
||||||
|
|
||||||
namespace ioman
|
namespace ioman
|
||||||
{
|
{
|
||||||
|
|
|
@ -490,3 +490,14 @@ void __fastcall iopMemWrite32(u32 mem, u32 value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string iopMemReadString(u32 mem, int maxlen)
|
||||||
|
{
|
||||||
|
std::string ret;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while ((c = iopMemRead8(mem++)) && maxlen--)
|
||||||
|
ret.push_back(c);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -83,6 +83,8 @@ extern void __fastcall iopMemWrite8 (u32 mem, u8 value);
|
||||||
extern void __fastcall iopMemWrite16(u32 mem, u16 value);
|
extern void __fastcall iopMemWrite16(u32 mem, u16 value);
|
||||||
extern void __fastcall iopMemWrite32(u32 mem, u32 value);
|
extern void __fastcall iopMemWrite32(u32 mem, u32 value);
|
||||||
|
|
||||||
|
std::string iopMemReadString(u32 mem, int maxlen = 65536);
|
||||||
|
|
||||||
namespace IopMemory
|
namespace IopMemory
|
||||||
{
|
{
|
||||||
// Sif functions not made yet (will for future Iop improvements):
|
// Sif functions not made yet (will for future Iop improvements):
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* If not, see <http://www.gnu.org/licenses/>.
|
* If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MODULE(n) if (!strncmp(libname, #n, 8)) switch (index) {
|
#define MODULE(n) if (#n == libname) switch (index) {
|
||||||
#define END_MODULE }
|
#define END_MODULE }
|
||||||
#define EXPORT(i, n) case (i): return #n;
|
#define EXPORT(i, n) case (i): return #n;
|
||||||
|
|
||||||
|
|
|
@ -93,7 +93,7 @@ void psxJ()
|
||||||
{
|
{
|
||||||
// check for iop module import table magic
|
// check for iop module import table magic
|
||||||
u32 delayslot = iopMemRead32(psxRegs.pc);
|
u32 delayslot = iopMemRead32(psxRegs.pc);
|
||||||
if (delayslot >> 16 == 0x2400 && irxImportExec(irxImportLibname(psxRegs.pc), delayslot & 0xffff))
|
if (delayslot >> 16 == 0x2400 && irxImportExec(irxImportTableAddr(psxRegs.pc), delayslot & 0xffff))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
doBranch(_JumpTarget_);
|
doBranch(_JumpTarget_);
|
||||||
|
|
|
@ -498,39 +498,53 @@ void psxRecompileCodeConst0(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode,
|
||||||
PSX_DEL_CONST(_Rd_);
|
PSX_DEL_CONST(_Rd_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void psxRecompileIrxImport()
|
||||||
|
{
|
||||||
|
u32 import_table = irxImportTableAddr(psxpc - 4);
|
||||||
|
u16 index = psxRegs.code & 0xffff;
|
||||||
|
if (!import_table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::string libname = iopMemReadString(import_table + 12, 8);
|
||||||
|
|
||||||
|
irxHLE hle = irxImportHLE(libname, index);
|
||||||
|
irxDEBUG debug = 0;
|
||||||
|
const char *funcname = 0;
|
||||||
|
|
||||||
|
#ifdef PCSX2_DEVBUILD
|
||||||
|
funcname = irxImportFuncname(libname, index);
|
||||||
|
debug = irxImportDebug(libname, index);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!hle && !debug && (!SysTraceActive(IOP.Bios) || !funcname))
|
||||||
|
return;
|
||||||
|
|
||||||
|
xMOV(ptr32[&psxRegs.code], psxRegs.code);
|
||||||
|
xMOV(ptr32[&psxRegs.pc], psxpc);
|
||||||
|
_psxFlushCall(FLUSH_NODESTROY);
|
||||||
|
|
||||||
|
if (SysTraceActive(IOP.Bios)) {
|
||||||
|
xPUSH((uptr)funcname);
|
||||||
|
xFastCall((void *)irxImportLog_rec, import_table, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
xFastCall((void *)debug);
|
||||||
|
|
||||||
|
if (hle) {
|
||||||
|
xFastCall((void *)hle);
|
||||||
|
xTEST(eax, eax);
|
||||||
|
xJNZ(iopDispatcherReg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// rt = rs op imm16
|
// rt = rs op imm16
|
||||||
void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
|
void psxRecompileCodeConst1(R3000AFNPTR constcode, R3000AFNPTR_INFO noconstcode)
|
||||||
{
|
{
|
||||||
if ( ! _Rt_ ) {
|
if ( ! _Rt_ ) {
|
||||||
// check for iop module import table magic
|
// check for iop module import table magic
|
||||||
if (psxRegs.code >> 16 == 0x2400) {
|
if (psxRegs.code >> 16 == 0x2400)
|
||||||
xMOV(ptr32[&psxRegs.code], psxRegs.code );
|
psxRecompileIrxImport();
|
||||||
xMOV(ptr32[&psxRegs.pc], psxpc );
|
|
||||||
_psxFlushCall(FLUSH_NODESTROY);
|
|
||||||
|
|
||||||
const char *libname = irxImportLibname(psxpc);
|
|
||||||
u16 index = psxRegs.code & 0xffff;
|
|
||||||
#ifdef PCSX2_DEVBUILD
|
|
||||||
const char *funcname = irxImportFuncname(libname, index);
|
|
||||||
irxDEBUG debug = irxImportDebug(libname, index);
|
|
||||||
|
|
||||||
if (SysTraceActive(IOP.Bios)) {
|
|
||||||
xMOV(ecx, (uptr)libname);
|
|
||||||
xMOV(edx, index);
|
|
||||||
xPUSH((uptr)funcname);
|
|
||||||
xCALL((void*)irxImportLog);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug)
|
|
||||||
xFastCall((void*)debug);
|
|
||||||
#endif
|
|
||||||
irxHLE hle = irxImportHLE(libname, index);
|
|
||||||
if (hle) {
|
|
||||||
xFastCall((void*)hle);
|
|
||||||
xCMP(eax, 0);
|
|
||||||
xJNE(iopDispatcherReg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue