pcsx2/Memory.c

3330 lines
82 KiB
C

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2003 Pcsx2 Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
RAM
---
0x00100000-0x01ffffff this is the physical address for the ram.its cached there
0x20100000-0x21ffffff uncached
0x30100000-0x31ffffff uncached & acceleretade
0xa0000000-0xa1ffffff MIRROR might...???
0x80000000-0x81ffffff MIRROR might... ????
scratch pad
----------
0x70000000-0x70003fff scratch pad
BIOS
----
0x1FC00000 - 0x1FFFFFFF un-cached
0x9FC00000 - 0x9FFFFFFF cached
0xBFC00000 - 0xBFFFFFFF un-cached
*/
//////////
// Rewritten by zerofrog(@gmail.com) to add os virtual memory
//////////
#if _WIN32_WINNT < 0x0500
#define _WIN32_WINNT 0x0500
#endif
#pragma warning(disable:4799) // No EMMS at end of function
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/stat.h>
#include "Common.h"
#ifdef PCSX2_NORECBUILD
#define REC_CLEARM(mem)
#else
#include "iR5900.h"
#endif
#include "PsxMem.h"
#include "R3000A.h"
#include "PsxHw.h"
#include "VUmicro.h"
#include "GS.h"
#ifdef ENABLECACHE
#include "Cache.h"
#endif
#include <assert.h>
extern u32 maxrecmem;
extern int rdram_devices, rdram_sdevid;
#ifndef __x86_64__
extern void * memcpy_fast(void *dest, const void *src, size_t n);
#endif
//#define FULLTLB
int MemMode = 0; // 0 is Kernel Mode, 1 is Supervisor Mode, 2 is User Mode
u16 ba0R16(u32 mem) {
#ifdef MEM_LOG
//MEM_LOG("ba00000 Memory read16 address %x\n", mem);
#endif
#ifdef PCSX2_VIRTUAL_MEM
if (mem == 0x1a000006) {
#else
if (mem == 0xba000006) {
#endif
static int ba6;
ba6++;
if (ba6 == 3) ba6 = 0;
return ba6;
}
return 0;
}
/////////////////////////////
// VIRTUAL MEM START
/////////////////////////////
#ifdef PCSX2_VIRTUAL_MEM
PSMEMORYBLOCK s_psM = {0}, s_psHw = {0}, s_psS = {0}, s_psxM = {0}, s_psVuMem = {0};
#define PHYSICAL_ALLOC(ptr, size, block) { \
if(SysPhysicalAlloc(size, &block) == -1 ) \
goto eCleanupAndExit; \
if(SysVirtualPhyAlloc((void*)ptr, size, &block) == -1) \
goto eCleanupAndExit; \
} \
#define PHYSICAL_FREE(ptr, size, block) { \
SysVirtualFree(ptr, size); \
SysPhysicalFree(&block); \
} \
#ifdef _WIN32 // windows implementation of vm
PSMEMORYMAP initMemoryMap(ULONG_PTR* aPFNs, ULONG_PTR* aVFNs)
{
PSMEMORYMAP m;
m.aPFNs = aPFNs;
m.aVFNs = aVFNs;
return m;
}
// only do vm hack for release
#ifndef PCSX2_DEVBUILD
#define VM_HACK
#endif
static int XmmExtendedRegOffset = 160;
// virtual memory blocks
PSMEMORYMAP *memLUT = NULL;
#define VIRTUAL_ALLOC(base, size, Protection) { \
LPVOID lpMemReserved = VirtualAlloc( base, size, MEM_RESERVE|MEM_COMMIT, Protection ); \
if( lpMemReserved == NULL || base != lpMemReserved ) \
{ \
SysPrintf("Cannot reserve memory at 0x%8.8x(%x), error: %d.\n", base, lpMemReserved, GetLastError()); \
goto eCleanupAndExit; \
} \
} \
#define VIRTUAL_FREE(ptr, size) { \
VirtualFree(ptr, size, MEM_DECOMMIT); \
VirtualFree(ptr, 0, MEM_RELEASE); \
} \
static int s_testmem[4] = { 0xfafafafa, 0xbabababa, 0xbfa8123f, 0xa123fde0 };
INT FindXmmOffsetException(LPEXCEPTION_POINTERS pexdata)
{
int i;
u32* p = (u32*)pexdata->ContextRecord->ExtendedRegisters;
assert( pexdata->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION);
XmmExtendedRegOffset = 160;
for(i = 0; i < sizeof(pexdata->ContextRecord->ExtendedRegisters)/4; ++i, ++p ) {
if( p[0] == s_testmem[0] && p[1] == s_testmem[1] && p[2] == s_testmem[2] && p[3] == s_testmem[3] ) {
XmmExtendedRegOffset = i*4;
break;
}
}
pexdata->ContextRecord->Eip += 7;
return EXCEPTION_CONTINUE_EXECUTION;
}
#if _MSC_VER < 1400
#define VC_HANDLER _except_handler3
#else
#define VC_HANDLER _except_handler4
#endif
//C's default exception handler
EXCEPTION_DISPOSITION VC_HANDLER(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext
);
char cpp_handler_instructions[5];
BOOL saved_handler_instructions = FALSE;
//Exception handler that replaces C's default handler.
EXCEPTION_DISPOSITION SysPageFaultExceptionFilter(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext
);
#pragma pack(1)
typedef struct _jmp_instr
{
unsigned char jmp;
DWORD offset;
} jmp_instr;
#pragma pack()
BOOL WriteMemory(void * loc, void * buffer, int size)
{
DWORD o2;
HANDLE hProcess = GetCurrentProcess();
//change the protection of pages containing range of memory
//[loc, loc+size] to READ WRITE
DWORD old_protection;
BOOL ret;
ret = VirtualProtectEx(hProcess, loc, size,
PAGE_READWRITE, &old_protection);
if(ret == FALSE)
return FALSE;
ret = WriteProcessMemory(hProcess, loc, buffer, size, NULL);
//restore old protection
VirtualProtectEx(hProcess, loc, size, old_protection, &o2);
return (ret == TRUE);
}
BOOL ReadMemory(void *loc, void *buffer, DWORD size)
{
HANDLE hProcess = GetCurrentProcess();
DWORD bytes_read = 0;
BOOL ret;
ret = ReadProcessMemory(hProcess, loc, buffer, size, &bytes_read);
return (ret == TRUE && bytes_read == size);
}
BOOL install_my_handler()
{
void * my_hdlr = SysPageFaultExceptionFilter;
void * cpp_hdlr = VC_HANDLER;
jmp_instr jmp_my_hdlr;
jmp_my_hdlr.jmp = 0xE9;
//We actually calculate the offset from __CxxFrameHandler+5
//as the jmp instruction is 5 byte length.
jmp_my_hdlr.offset = (char*)(my_hdlr) -
((char*)(cpp_hdlr) + 5);
if(!saved_handler_instructions)
{
if(!ReadMemory(cpp_hdlr, cpp_handler_instructions,
sizeof(cpp_handler_instructions)))
return FALSE;
saved_handler_instructions = TRUE;
}
return WriteMemory(cpp_hdlr, &jmp_my_hdlr, sizeof(jmp_my_hdlr));
}
BOOL restore_cpp_handler()
{
if(!saved_handler_instructions)
return FALSE;
else
{
void *loc = VC_HANDLER;
return WriteMemory(loc, cpp_handler_instructions,
sizeof(cpp_handler_instructions));
}
}
int memInit() {
int i;
LPVOID pExtraMem = NULL;
// release the previous reserved mem
VirtualFree(PS2MEM_BASE, 0, MEM_RELEASE);
// allocate all virtual memory
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PAGE_READONLY);
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PAGE_READONLY);
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PAGE_NOACCESS);
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PAGE_READWRITE);
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PAGE_READWRITE);
// reserve the left over 224Mb, don't map
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x02000000, 0x0e000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_BASE+0x02000000 )
goto eCleanupAndExit;
// reserve left over psx mem
pExtraMem = VirtualAlloc(PS2MEM_PSX+0x00200000, 0x00600000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_PSX+0x00200000 )
goto eCleanupAndExit;
// reserve gs mem
pExtraMem = VirtualAlloc(PS2MEM_BASE+0x20000000, 0x10000000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( pExtraMem != PS2MEM_BASE+0x20000000 )
goto eCleanupAndExit;
// special addrs mmap
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PAGE_READWRITE);
// alloc virtual mappings
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(PSMEMORYMAP), 16);
memset(memLUT, 0, sizeof(PSMEMORYMAP)*0x100000);
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = initMemoryMap(&s_psM.aPFNs[i], &s_psM.aVFNs[i]);
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = initMemoryMap(&s_psHw.aPFNs[i], &s_psHw.aVFNs[i]);
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = initMemoryMap(&s_psxM.aPFNs[(i & 0x1ff)], &s_psxM.aVFNs[(i & 0x1ff)]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = initMemoryMap(&s_psVuMem.aPFNs[0], &s_psVuMem.aVFNs[0]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = initMemoryMap(&s_psVuMem.aPFNs[1], &s_psVuMem.aVFNs[1]);
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = initMemoryMap(&s_psVuMem.aPFNs[4+i], &s_psVuMem.aVFNs[4+i]);
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = initMemoryMap(&s_psVuMem.aPFNs[8+i], &s_psVuMem.aVFNs[8+i]);
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = initMemoryMap(&s_psS.aPFNs[i], &s_psS.aVFNs[i]);
// map to other modes
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(PSMEMORYMAP));
if (psxInit() == -1)
goto eCleanupAndExit;
// figure out xmm reg offset
// __asm movups xmm0, s_testmem
// __try {
// u8* p = 0;
// __asm {
// mov eax, dword ptr [p]
// }
// }
// __except( FindXmmOffsetException( GetExceptionInformation() ) ) {
// }
//#ifdef WIN32_FILE_MAPPING
if( !install_my_handler() ) {
SysPrintf("Failed to install custom exception handler!\n");
return -1;
}
//#endif
return 0;
eCleanupAndExit:
if( pExtraMem != NULL )
VirtualFree(pExtraMem, 0x0e000000, MEM_RELEASE);
memShutdown();
return -1;
}
void memShutdown()
{
VirtualFree(PS2MEM_BASE+0x02000000, 0, MEM_RELEASE);
VirtualFree(PS2MEM_PSX+0x00200000, 0, MEM_RELEASE);
VirtualFree(PS2MEM_BASE+0x20000000, 0, MEM_RELEASE);
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM);
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
_aligned_free(memLUT); memLUT = NULL;
// reserve mem
VirtualAlloc(PS2MEM_BASE, 0x40000000, MEM_RESERVE, PAGE_NOACCESS);
}
#define GET_REGVALUE(code) *((u32*)&pexdata->ContextRecord->Eax + (((code)>>11)&7))
#define GET_XMMVALUE(xmm) ((u64*)((u8*)pexdata->ContextRecord->ExtendedRegisters + XmmExtendedRegOffset + ((xmm)<<4)))
//NOTE: A lot of the code reading depends on the registers being less than 8
// MOV8 88/8A
// MOV16 6689
// MOV32 89/8B
// SSEMtoR64 120f
// SSERtoM64 130f
// SSEMtoR128 280f
// SSERtoM128 290f
#define SKIP_WRITE(pexdata) { \
switch(code&0xff) { \
case 0x88: \
if( !(code&0x8000) ) goto DefaultHandler; \
ContextRecord->Eip += 6; \
break; \
case 0x66: \
assert( code&0x800000 ); \
assert( (code&0xffff) == 0x8966 ); \
ContextRecord->Eip += 7; \
break; \
case 0x89: \
assert( code&0x8000 ); \
ContextRecord->Eip += 6; \
break; \
case 0x0f: /* 130f, 230f*/ \
assert( (code&0xffff) == 0x290f || (code&0xffff) == 0x130f ); \
assert( code&0x800000 ); \
ContextRecord->Eip += 7; \
break; \
default: \
goto DefaultHandler; \
} \
} \
#define SKIP_READ(pexdata) { \
switch(code&0xff) { \
case 0x8A: \
if( !(code&0x8000) ) goto DefaultHandler; \
ContextRecord->Eip += 6; \
rd = (code>>(8+3))&7; \
break; \
case 0x66: \
if( (code&0x07000000) == 0x05000000 ) ContextRecord->Eip += 8; /* 8 for mem reads*/ \
else ContextRecord->Eip += 4 + ((code&0x1f000000) == 0x0c000000) + !!(code&0x40000000); \
rd = (code>>(24+3))&7; \
break; \
case 0x8B: \
if( !(code&0x8000) ) goto DefaultHandler; \
ContextRecord->Eip += 6; \
rd = (code>>(8+3))&7; \
break; \
case 0x0f: { \
assert( (code&0xffff)==0x120f || (code&0xffff)==0x280f || (code&0xffff) == 0xb60f || (code&0xffff) == 0xb70f ); \
if( !(code&0x800000) ) goto DefaultHandler; \
ContextRecord->Eip += 7; \
rd = (code>>(16+3))&7; \
break; } \
default: \
goto DefaultHandler; \
} \
} \
EXCEPTION_DISPOSITION SysPageFaultExceptionFilter(
struct _EXCEPTION_RECORD *ExceptionRecord,
void * EstablisherFrame,
struct _CONTEXT *ContextRecord,
void * DispatcherContext
)
{
u32 addr;
C_ASSERT(sizeof(ContextRecord->Eax) == 4);
// If the exception is not a page fault, exit.
if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
{
// call old handler
EXCEPTION_DISPOSITION d;
restore_cpp_handler();
d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext);
install_my_handler();
return d;
}
// get bad virtual address
addr = (u32)ExceptionRecord->ExceptionInformation[1];
if( addr >= (u32)PS2MEM_BASE && addr < (u32)PS2MEM_BASE+0x60000000) {
PSMEMORYMAP* pmap;
pmap = &memLUT[(addr-(u32)PS2MEM_BASE)>>12];
if( pmap->aPFNs == NULL ) {
// NOTE: this is a hack because the address is truncated and there's no way
// to tell what it's upper bits are (due to OS limitations).
pmap += 0x80000;
if( pmap->aPFNs == NULL ) {
pmap += 0x20000;
}
//else addr += 0x20000000;
}
if( pmap->aPFNs != NULL ) {
LPVOID pnewaddr;
DWORD oldaddr = pmap->aVFNs[0];
if( pmap->aVFNs[0] != 0 ) {
// delete the current mapping
SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0);
}
assert( pmap->aPFNs[0] != 0 );
pmap->aVFNs[0] = addr&~0xfff;
if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) )
return ExceptionContinueExecution;
// try allocing the virtual mem
pnewaddr = VirtualAlloc((void*)(addr&~0xffff), 0x10000, MEM_RESERVE|MEM_PHYSICAL, PAGE_READWRITE);
if( SysMapUserPhysicalPages((void*)(addr&~0xfff), 1, pmap->aPFNs, 0) )
return ExceptionContinueExecution;
SysPrintf("Fatal error, virtual page 0x%x cannot be found %d (p:%x,v:%x)\n",
addr-(u32)PS2MEM_BASE, GetLastError(), pmap->aPFNs[0], pmap->aVFNs[0]);
}
}
else {
// check if vumem
if( (addr&0xffff4000) == 0x11000000 ) {
// vu0mem
SysMapUserPhysicalPages((void*)s_psVuMem.aVFNs[1], 1, NULL, 0);
s_psVuMem.aVFNs[1] = addr&~0xfff;
SysMapUserPhysicalPages((void*)addr, 1, s_psVuMem.aPFNs, 1);
return ExceptionContinueExecution;//EXCEPTION_CONTINUE_EXECUTION;
}
}
{
// call old handler
EXCEPTION_DISPOSITION d;
#ifdef VM_HACK
u32 code = *(u32*)ExceptionRecord->ExceptionAddress;
u32 rd = 0;
if( ExceptionRecord->ExceptionInformation[0] ) {
//SKIP_WRITE(ptrs);
// shouldn't be writing
}
else {
SysPrintf("vmhack ");
SKIP_READ(ptrs);
//((u32*)&ContextRecord->Eax)[rd] = 0;
return ExceptionContinueExecution;
}
DefaultHandler:
#endif
restore_cpp_handler();
d = VC_HANDLER(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext);
install_my_handler();
return d;
}
// continue execution
return EXCEPTION_CONTINUE_EXECUTION;
}
#else // linux implementation
#define VIRTUAL_ALLOC(base, size, Protection) { \
void* lpMemReserved = mmap( base, size, Protection, MAP_PRIVATE|MAP_ANONYMOUS ); \
if( lpMemReserved == NULL || base != lpMemReserved ) \
{ \
SysPrintf("Cannot reserve memory at 0x%8.8x(%x).\n", base, lpMemReserved); \
perror("err"); \
goto eCleanupAndExit; \
} \
} \
#define VIRTUAL_FREE(ptr, size) munmap(ptr, size)
uptr *memLUT = NULL;
int memInit()
{
int i;
LPVOID pExtraMem = NULL;
// release the previous reserved mem
munmap(PS2MEM_BASE, 0x40000000);
// allocate all virtual memory
PHYSICAL_ALLOC(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_ALLOC(PS2MEM_ROM, 0x00400000, PROT_READ);
VIRTUAL_ALLOC(PS2MEM_ROM1, 0x00040000, PROT_READ);
VIRTUAL_ALLOC(PS2MEM_ROM2, 0x00080000, PROT_READ);
VIRTUAL_ALLOC(PS2MEM_EROM, 0x001C0000, PROT_READ);
PHYSICAL_ALLOC(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_ALLOC(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_ALLOC(PS2MEM_PSX, 0x00200000, s_psxM);
PHYSICAL_ALLOC(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_ALLOC(PS2MEM_PSXHW, 0x00010000, PROT_READ|PROT_WRITE);
VIRTUAL_ALLOC(PS2MEM_PSXHW4, 0x00010000, PROT_NONE);
VIRTUAL_ALLOC(PS2MEM_GS, 0x00002000, PROT_READ|PROT_WRITE);
VIRTUAL_ALLOC(PS2MEM_DEV9, 0x00010000, PROT_NONE);
VIRTUAL_ALLOC(PS2MEM_SPU2, 0x00010000, PROT_NONE);
VIRTUAL_ALLOC(PS2MEM_SPU2_, 0x00010000, PROT_NONE);
VIRTUAL_ALLOC(PS2MEM_B80, 0x00010000, PROT_READ|PROT_WRITE);
VIRTUAL_ALLOC(PS2MEM_BA0, 0x00010000, PROT_READ|PROT_WRITE);
// special addrs mmap
VIRTUAL_ALLOC(PS2MEM_BASE+0x5fff0000, 0x10000, PROT_READ|PROT_WRITE);
// alloc virtual mappings
memLUT = (PSMEMORYMAP*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
memset(memLUT, 0, sizeof(uptr)*0x100000);
for (i=0; i<0x02000; i++) memLUT[i + 0x00000] = PS2MEM_BASE+(i<<12);
for (i=2; i<0x00010; i++) memLUT[i + 0x10000] = PS2MEM_BASE+0x10000000+(i<<12);
for (i=0; i<0x00800; i++) memLUT[i + 0x1c000] = PS2MEM_BASE+0x1c000000+(i<<12);
for (i=0; i<0x00004; i++) memLUT[i + 0x11000] = PS2MEM_VU0MICRO;
for (i=0; i<0x00004; i++) memLUT[i + 0x11004] = PS2MEM_VU0MEM;
for (i=0; i<0x00004; i++) memLUT[i + 0x11008] = PS2MEM_VU1MICRO+(i<<12);
for (i=0; i<0x00004; i++) memLUT[i + 0x1100c] = PS2MEM_VU1MEM+(i<<12);
for (i=0; i<0x00004; i++) memLUT[i + 0x50000] = PS2MEM_SCRATCH+(i<<12);
// map to other modes
memcpy(memLUT+0x80000, memLUT, 0x20000*sizeof(uptr));
memcpy(memLUT+0xa0000, memLUT, 0x20000*sizeof(uptr));
if (psxInit() == -1)
goto eCleanupAndExit;
eCleanupAndExit:
memShutdown();
return -1;
}
void memShutdown()
{
VIRTUAL_FREE(PS2MEM_BASE, 0x40000000);
VIRTUAL_FREE(PS2MEM_PSX, 0x00800000);
PHYSICAL_FREE(PS2MEM_BASE, 0x02000000, s_psM);
VIRTUAL_FREE(PS2MEM_ROM, 0x00400000);
VIRTUAL_FREE(PS2MEM_ROM1, 0x00080000);
VIRTUAL_FREE(PS2MEM_ROM2, 0x00080000);
VIRTUAL_FREE(PS2MEM_EROM, 0x001C0000);
PHYSICAL_FREE(PS2MEM_SCRATCH, 0x00010000, s_psS);
PHYSICAL_FREE(PS2MEM_HW, 0x00010000, s_psHw);
PHYSICAL_FREE(PS2MEM_PSX, 0x00800000, s_psxM);
PHYSICAL_FREE(PS2MEM_VU0MICRO, 0x00010000, s_psVuMem);
VIRTUAL_FREE(PS2MEM_VU0MICRO, 0x00010000); // allocate for all VUs
VIRTUAL_FREE(PS2MEM_PSXHW, 0x00010000);
VIRTUAL_FREE(PS2MEM_PSXHW4, 0x00010000);
VIRTUAL_FREE(PS2MEM_GS, 0x00010000);
VIRTUAL_FREE(PS2MEM_DEV9, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2, 0x00010000);
VIRTUAL_FREE(PS2MEM_SPU2_, 0x00010000);
VIRTUAL_FREE(PS2MEM_B80, 0x00010000);
VIRTUAL_FREE(PS2MEM_BA0, 0x00010000);
VirtualFree(PS2MEM_VU0MICRO, 0, MEM_RELEASE);
_aligned_free(memLUT); memLUT = NULL;
// reserve mem
if( mmap(PS2MEM_BASE, 0x40000000, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) != PS2MEM_BASE ) {
SysPrintf("failed to reserve mem\n");
}
}
#endif // _WIN32
// Some games read/write between different addrs but same physical memory
// this causes major slowdowns because it goes into the exception handler, so use this (zerofrog)
u32 VM_RETRANSLATE(u32 mem)
{
u8* p, *pbase;
if( (mem&0xffff0000) == 0x50000000 ) // reserved scratch pad mem
return PS2MEM_BASE_+mem;
p = (u8*)dmaGetAddrBase(mem), *pbase;
#ifdef _WIN32
// do manual LUT since IPU/SPR seems to use addrs 0x3000xxxx quite often
if( memLUT[ (p-PS2MEM_BASE)>>12 ].aPFNs == NULL ) {
return PS2MEM_BASE_+mem;
}
pbase = (u8*)memLUT[ (p-PS2MEM_BASE)>>12 ].aVFNs[0];
if( pbase != NULL )
p = pbase + ((u32)p&0xfff);
#endif
return (u32)p;
}
void memSetPageAddr(u32 vaddr, u32 paddr) {
PSMEMORYMAP* pmap;
if( vaddr == paddr )
return;
if( (vaddr>>28) != 1 && (vaddr>>28) != 9 && (vaddr>>28) != 11 ) {
#ifdef _WIN32
pmap = &memLUT[vaddr >> 12];
if( pmap->aPFNs != NULL && (pmap->aPFNs != memLUT[paddr>>12].aPFNs ||
pmap->aVFNs[0] != TRANSFORM_ADDR(vaddr)+(u32)PS2MEM_BASE) ) {
SysMapUserPhysicalPages((void*)pmap->aVFNs[0], 1, NULL, 0);
pmap->aVFNs[0] = 0;
}
*pmap = memLUT[paddr >> 12];
#else
memLUT[vaddr>>12] = memLUT[paddr>>12];
#endif
}
}
void memClearPageAddr(u32 vaddr) {
// SysPrintf("memClearPageAddr: %8.8x\n", vaddr);
if ((vaddr & 0xffffc000) == 0x70000000) return;
#ifdef _WIN32
// if( vaddr >= 0x20000000 && vaddr < 0x80000000 ) {
// Cpu->Clear(vaddr&~0xfff, 0x1000/4);
// if( memLUT[vaddr>>12].aVFNs != NULL ) {
// SysMapUserPhysicalPages((void*)memLUT[vaddr>>12].aVFNs[0], 1, NULL, 0 );
// memLUT[vaddr>>12].aVFNs = NULL;
// memLUT[vaddr>>12].aPFNs = NULL;
// }
// }
#else
if( memLUT[vaddr>>12] != NULL ) {
SysVirtualFree(memLUT[vaddr>>12], 0x1000);
memLUT[vaddr>>12] = 0;
}
#endif
}
u8 recMemRead8()
{
register u32 mem;
__asm mov mem, ecx // already anded with ~0xa0000000
switch( (mem&~0xffff) ) {
case 0x1f400000: return psxHw4Read8(mem);
case 0x10000000: return hwRead8(mem);
case 0x1f800000: return psxHwRead8(mem);
case 0x12000000: return *(PS2MEM_BASE+(mem&~0xc00));
case 0x14000000:
{
u32 ret = DEV9read8(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret);
return ret;
}
default:
return *(u8*)(PS2MEM_BASE+mem);
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return 0;
}
void _eeReadConstMem8(int mmreg, u32 mem, int sign)
{
assert( !IS_XMMREG(mmreg));
if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVDMtoMMX(mmreg&0xf, mem-3);
assert(0);
}
else {
if( sign ) MOVSX32M8toR(mmreg, mem);
else MOVZX32M8toR(mmreg, mem);
}
}
void _eeReadConstMem16(int mmreg, u32 mem, int sign)
{
assert( !IS_XMMREG(mmreg));
if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVDMtoMMX(mmreg&0xf, mem-2);
assert(0);
}
else {
if( sign ) MOVSX32M16toR(mmreg, mem);
else MOVZX32M16toR(mmreg, mem);
}
}
void _eeReadConstMem32(int mmreg, u32 mem)
{
if( IS_XMMREG(mmreg) ) SSEX_MOVD_M32_to_XMM(mmreg&0xf, mem);
else if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVDMtoMMX(mmreg&0xf, mem);
}
else MOV32MtoR(mmreg, mem);
}
void _eeReadConstMem128(int mmreg, u32 mem)
{
if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVQMtoR((mmreg>>4)&0xf, mem+8);
MOVQMtoR(mmreg&0xf, mem);
}
else SSEX_MOVDQA_M128_to_XMM( mmreg&0xf, mem);
}
void _eeWriteConstMem8(u32 mem, int mmreg)
{
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
if( IS_EECONSTREG(mmreg) ) MOV8ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) MOV8ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else MOV8RtoM(mem, mmreg);
}
void _eeWriteConstMem16(u32 mem, int mmreg)
{
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
if( IS_EECONSTREG(mmreg) ) MOV16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) MOV16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else MOV16RtoM(mem, mmreg);
}
void _eeWriteConstMem16OP(u32 mem, int mmreg, int op)
{
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
switch(op) {
case 0: // and
if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else AND16RtoM(mem, mmreg);
break;
case 1: // and
if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else OR16RtoM(mem, mmreg);
break;
default: assert(0);
}
}
void _eeWriteConstMem32(u32 mem, int mmreg)
{
if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
else if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVDMMXtoM(mem, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else MOV32RtoM(mem, mmreg);
}
void _eeWriteConstMem32OP(u32 mem, int mmreg, int op)
{
switch(op) {
case 0: // and
if( IS_XMMREG(mmreg) ) {
_deleteEEreg((mmreg>>16)&0x1f, 1);
SSE2_PAND_M128_to_XMM(mmreg&0xf, mem);
SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
}
else if( IS_MMXREG(mmreg) ) {
_deleteEEreg((mmreg>>16)&0x1f, 1);
SetMMXstate();
PANDMtoR(mmreg&0xf, mem);
MOVDMMXtoM(mem, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) {
AND32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
}
else if( IS_PSXCONSTREG(mmreg) ) {
AND32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
}
else {
AND32RtoM(mem, mmreg&0xf);
}
break;
case 1: // or
if( IS_XMMREG(mmreg) ) {
_deleteEEreg((mmreg>>16)&0x1f, 1);
SSE2_POR_M128_to_XMM(mmreg&0xf, mem);
SSE2_MOVD_XMM_to_M32(mem, mmreg&0xf);
}
else if( IS_MMXREG(mmreg) ) {
_deleteEEreg((mmreg>>16)&0x1f, 1);
SetMMXstate();
PORMtoR(mmreg&0xf, mem);
MOVDMMXtoM(mem, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) {
OR32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
}
else if( IS_PSXCONSTREG(mmreg) ) {
OR32ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
}
else {
OR32RtoM(mem, mmreg&0xf);
}
break;
case 2: // not and
if( mmreg & MEM_XMMTAG ) {
_deleteEEreg(mmreg>>16, 1);
SSEX_PANDN_M128_to_XMM(mmreg&0xf, mem);
SSEX_MOVD_XMM_to_M32(mem, mmreg&0xf);
}
else if( mmreg & MEM_MMXTAG ) {
_deleteEEreg(mmreg>>16, 1);
PANDNMtoR(mmreg&0xf, mem);
MOVDMMXtoM(mem, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) {
AND32ItoM(mem, ~g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
}
else if( IS_PSXCONSTREG(mmreg) ) {
AND32ItoM(mem, ~g_psxConstRegs[((mmreg>>16)&0x1f)]);
}
else {
NOT32R(mmreg&0xf);
AND32RtoM(mem, mmreg&0xf);
}
break;
default: assert(0);
}
}
void _eeWriteConstMem64(u32 mem, int mmreg)
{
if( IS_XMMREG(mmreg) ) SSE_MOVLPS_XMM_to_M64(mem, mmreg&0xf);
else if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVQRtoM(mem, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) {
MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]);
}
else assert(0);
}
void _eeWriteConstMem128(u32 mem, int mmreg)
{
assert( cpucaps.hasStreamingSIMDExtensions );
if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVQRtoM(mem, mmreg&0xf);
MOVQRtoM(mem+8, (mmreg>>4)&0xf);
}
else if( IS_EECONSTREG(mmreg) ) {
SetMMXstate();
MOV32ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
MOV32ItoM(mem+4, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[1]);
MOVQRtoM(mem+8, mmreg&0xf);
}
else SSEX_MOVDQA_XMM_to_M128(mem, mmreg&0xf);
}
void _eeMoveMMREGtoR(x86IntRegType to, int mmreg)
{
if( IS_XMMREG(mmreg) ) SSE2_MOVD_XMM_to_R(to, mmreg&0xf);
else if( IS_MMXREG(mmreg) ) {
SetMMXstate();
MOVD32MMXtoR(to, mmreg&0xf);
}
else if( IS_EECONSTREG(mmreg) ) MOV32ItoR(to, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) MOV32ItoR(to, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else if( mmreg != to ) MOV32RtoR(to, mmreg);
}
int recMemConstRead8(u32 x86reg, u32 mem, u32 sign)
{
mem = TRANSFORM_ADDR(mem);
switch( mem>>16 ) {
case 0x1f40: return psxHw4ConstRead8(x86reg, mem, sign);
case 0x1000: return hwConstRead8(x86reg, mem, sign);
case 0x1f80: return psxHwConstRead8(x86reg, mem, sign);
case 0x1200: return gsConstRead8(x86reg, mem, sign);
case 0x1400:
{
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9read8);
if( sign ) MOVSX32R8toR(EAX, EAX);
else MOVZX32R8toR(EAX, EAX);
return 1;
}
default:
_eeReadConstMem8(x86reg, VM_RETRANSLATE(mem), sign);
return 0;
}
}
u16 recMemRead16() {
register u32 mem;
__asm mov mem, ecx // already anded with ~0xa0000000
switch( mem>>16 ) {
case 0x1000: return hwRead16(mem);
case 0x1f80: return psxHwRead16(mem);
case 0x1200: return *(u16*)(PS2MEM_BASE+(mem&~0xc00));
case 0x1800: return 0;
case 0x1a00: return ba0R16(mem);
case 0x1f90:
case 0x1f00:
return SPU2read(mem);
case 0x1400:
{
u32 ret = DEV9read16(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, ret);
return ret;
}
default:
return *(u16*)(PS2MEM_BASE+mem);
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return 0;
}
int recMemConstRead16(u32 x86reg, u32 mem, u32 sign)
{
mem = TRANSFORM_ADDR(mem);
switch( mem>>16 ) {
case 0x1000: return hwConstRead16(x86reg, mem, sign);
case 0x1f80: return psxHwConstRead16(x86reg, mem, sign);
case 0x1200: return gsConstRead16(x86reg, mem, sign);
case 0x1800:
if( IS_MMXREG(x86reg) ) PXORRtoR(x86reg&0xf, x86reg&0xf);
else XOR32RtoR(x86reg, x86reg);
return 0;
case 0x1a00:
iFlushCall(0);
PUSH32I(mem);
CALLFunc((u32)ba0R16);
ADD32ItoR(ESP, 4);
if( sign ) MOVSX32R16toR(EAX, EAX);
else MOVZX32R16toR(EAX, EAX);
return 1;
case 0x1f90:
case 0x1f00:
iFlushCall(0);
PUSH32I(mem);
CALLFunc((u32)SPU2read);
if( sign ) MOVSX32R16toR(EAX, EAX);
else MOVZX32R16toR(EAX, EAX);
return 1;
case 0x1400:
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9read16);
if( sign ) MOVSX32R16toR(EAX, EAX);
else MOVZX32R16toR(EAX, EAX);
return 1;
default:
_eeReadConstMem16(x86reg, VM_RETRANSLATE(mem), sign);
return 0;
}
}
__declspec(naked)
u32 recMemRead32() {
// ecx is address - already anded with ~0xa0000000
__asm {
mov edx, ecx
shr edx, 16
cmp dx, 0x1000
je hwread
cmp dx, 0x1f80
je psxhwread
cmp dx, 0x1200
je gsread
cmp dx, 0x1400
je devread
// default read
mov eax, dword ptr [ecx+PS2MEM_BASE_]
ret
}
hwread:
{
__asm {
cmp ecx, 0x10002000
jb counterread
cmp ecx, 0x1000f260
je hwsifpresetread
cmp ecx, 0x1000f240
je hwsifsyncread
cmp ecx, 0x1000f440
je hwmch_drd
cmp ecx, 0x1000f430
je hwmch_ricm
cmp ecx, 0x10003000
jb hwdefread2
mov eax, dword ptr [ecx+PS2MEM_BASE_]
ret
// ipu
hwdefread2:
push ecx
call ipuRead32
add esp, 4
ret
// sif
hwsifpresetread:
xor eax, eax
ret
hwsifsyncread:
mov eax, 0x1000F240
mov eax, dword ptr [eax+PS2MEM_BASE_]
or eax, 0xF0000102
ret
}
counterread:
{
static u32 mem, index;
// counters
__asm mov mem, ecx
index = (mem>>11)&3;
if( (mem&0x7ff) == 0 ) {
__asm {
push index
call rcntRcount
add esp, 4
and eax, 0xffff
ret
}
}
index = (u32)&counters[index] + ((mem>>2)&0xc);
__asm {
mov eax, index
mov eax, dword ptr [eax]
movzx eax, ax
ret
}
}
hwmch_drd: // MCH_DRD
__asm {
mov eax, dword ptr [ecx+PS2MEM_BASE_-0x10]
shr eax, 6
test eax, 0xf
jz mch_drd_2
hwmch_ricm:
xor eax, eax
ret
mch_drd_2:
shr eax, 10
and eax, 0xfff
cmp eax, 0x21 // INIT
je mch_drd_init
cmp eax, 0x23 // CNFGA
je mch_drd_cnfga
cmp eax, 0x24 // CNFGB
je mch_drd_cnfgb
cmp eax, 0x40 // DEVID
je mch_drd_devid
xor eax, eax
ret
mch_drd_init:
mov edx, rdram_devices
xor eax, eax
cmp edx, rdram_sdevid
setg al
add rdram_sdevid, eax
imul eax, 0x1f
ret
mch_drd_cnfga:
mov eax, 0x0D0D
ret
mch_drd_cnfgb:
mov eax, 0x0090
ret
mch_drd_devid:
mov eax, dword ptr [ecx+PS2MEM_BASE_-0x10]
and eax, 0x1f
ret
}
}
psxhwread:
__asm {
push ecx
call psxHwRead32
add esp, 4
ret
}
gsread:
__asm {
and ecx, 0xfffff3ff
mov eax, dword ptr [ecx+PS2MEM_BASE_]
ret
}
devread:
__asm {
and ecx, 0xfbffffff
push ecx
call DEV9read32
add esp, 4
ret
}
}
int recMemConstRead32(u32 x86reg, u32 mem)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: return hwConstRead32(x86reg, mem);
case 0x1f800000: return psxHwConstRead32(x86reg, mem);
case 0x12000000: return gsConstRead32(x86reg, mem);
case 0x14000000:
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9read32);
return 1;
default:
_eeReadConstMem32(x86reg, VM_RETRANSLATE(mem));
return 0;
}
}
void recMemRead64(u64 *out)
{
register u32 mem;
__asm mov mem, ecx // already anded with ~0xa0000000
switch( (mem&0xffff0000) ) {
case 0x10000000: *out = hwRead64(mem); return;
case 0x11000000: *out = *(u64*)(PS2MEM_BASE+mem); return;
case 0x12000000: *out = *(u64*)(PS2MEM_BASE+(mem&~0xc00)); return;
default:
//assert(0);
*out = *(u64*)(PS2MEM_BASE+mem);
return;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
}
void recMemConstRead64(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&0xffff0000) ) {
case 0x10000000: hwConstRead64(mem, mmreg); return;
case 0x12000000: gsConstRead64(mem, mmreg); return;
default:
if( IS_XMMREG(mmreg) ) SSE_MOVLPS_M64_to_XMM(mmreg&0xff, VM_RETRANSLATE(mem));
else {
MOVQMtoR(mmreg, VM_RETRANSLATE(mem));
SetMMXstate();
}
return;
}
}
void recMemRead128(u64 *out) {
register u32 mem;
__asm mov mem, ecx // already anded with ~0xa0000000
switch( (mem&0xffff0000) ) {
case 0x10000000:
hwRead128(mem, out);
return;
case 0x12000000:
out[0] = *(u64*)(PS2MEM_BASE+(mem&~0xc00));
out[1] = *(u64*)(PS2MEM_BASE+(mem&~0xc00)+8);
return;
case 0x11000000:
out[0] = *(u64*)(PS2MEM_BASE+mem);
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
return;
default:
//assert(0);
out[0] = *(u64*)(PS2MEM_BASE+mem);
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
return;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
}
void recMemConstRead128(u32 mem, int xmmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&0xffff0000) ) {
case 0x10000000: hwConstRead128(mem, xmmreg); return;
case 0x12000000: gsConstRead128(mem, xmmreg); return;
default:
_eeReadConstMem128(xmmreg, VM_RETRANSLATE(mem));
return;
}
}
void errwrite()
{
int i, bit, tempeax;
__asm mov i, ecx
__asm mov tempeax, eax
__asm mov bit, edx
SysPrintf("Error write%d at %x\n", bit, i);
assert(0);
__asm mov eax, tempeax
__asm mov ecx, i
}
void recMemWrite8()
{
register u32 mem;
register u8 value;
__asm mov mem, ecx // already anded with ~0xa0000000
__asm mov value, al
switch( mem>>16 ) {
case 0x1f40: psxHw4Write8(mem, value); return;
case 0x1000: hwWrite8(mem, value); return;
case 0x1f80: psxHwWrite8(mem, value); return;
case 0x1200: gsWrite8(mem, value); return;
case 0x1400:
DEV9write8(mem & ~0x04000000, value);
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value);
return;
#ifdef _DEBUG
case 0x1100: assert(0);
#endif
default:
// vus, bad addrs, etc
*(u8*)(PS2MEM_BASE+mem) = value;
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
int recMemConstWrite8(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( mem>>16 ) {
case 0x1f40: psxHw4ConstWrite8(mem, mmreg); return 0;
case 0x1000: hwConstWrite8(mem, mmreg); return 0;
case 0x1f80: psxHwConstWrite8(mem, mmreg); return 0;
case 0x1200: gsConstWrite8(mem, mmreg); return 0;
case 0x1400:
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9write8);
return 0;
case 0x1100:
_eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg);
if( mem < 0x11004000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU0);
ADD32ItoR(ESP, 8);
}
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU1);
ADD32ItoR(ESP, 8);
}
return 0;
default:
_eeWriteConstMem8(PS2MEM_BASE_+mem, mmreg);
return 1;
}
}
void recMemWrite16() {
register u32 mem;
register u16 value;
__asm mov mem, ecx // already anded with ~0xa0000000
__asm mov value, ax
switch( mem>>16 ) {
case 0x1000: hwWrite16(mem, value); return;
case 0x1600:
//HACK: DEV9 VM crash fix
return;
case 0x1f80: psxHwWrite16(mem, value); return;
case 0x1200: gsWrite16(mem, value); return;
case 0x1f90:
case 0x1f00: SPU2write(mem, value); return;
case 0x1400:
DEV9write16(mem & ~0x04000000, value);
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value);
return;
#ifdef _DEBUG
case 0x1100: assert(0);
#endif
default:
// vus, bad addrs, etc
*(u16*)(PS2MEM_BASE+mem) = value;
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
int recMemConstWrite16(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( mem>>16 ) {
case 0x1000: hwConstWrite16(mem, mmreg); return 0;
case 0x1600:
//HACK: DEV9 VM crash fix
return 0;
case 0x1f80: psxHwConstWrite16(mem, mmreg); return 0;
case 0x1200: gsConstWrite16(mem, mmreg); return 0;
case 0x1f90:
case 0x1f00:
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((u32)SPU2write);
return 0;
case 0x1400:
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9write16);
return 0;
case 0x1100:
_eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg);
if( mem < 0x11004000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU0);
ADD32ItoR(ESP, 8);
}
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU1);
ADD32ItoR(ESP, 8);
}
return 0;
default:
_eeWriteConstMem16(PS2MEM_BASE_+mem, mmreg);
return 1;
}
}
C_ASSERT( sizeof(BASEBLOCK) == 8 );
__declspec(naked)
void recMemWrite32()
{
// ecx is address - already anded with ~0xa0000000
__asm {
mov edx, ecx
shr edx, 16
cmp dx, 0x1000
je hwwrite
cmp dx, 0x1f80
je psxwrite
cmp dx, 0x1200
je gswrite
cmp dx, 0x1400
je devwrite
cmp dx, 0x1100
je vuwrite
}
__asm {
// default write
mov dword ptr [ecx+PS2MEM_BASE_], eax
ret
hwwrite:
push eax
push ecx
call hwWrite32
add esp, 8
ret
psxwrite:
push eax
push ecx
call psxHwWrite32
add esp, 8
ret
gswrite:
push eax
push ecx
call gsWrite32
add esp, 8
ret
devwrite:
and ecx, 0xfbffffff
push eax
push ecx
call DEV9write32
add esp, 8
ret
vuwrite:
// default write
mov dword ptr [ecx+PS2MEM_BASE_], eax
cmp ecx, 0x11004000
jge vu1write
and ecx, 0x3ff8
// clear vu0mem
mov eax, Cpu
push 1
push ecx
call [eax]Cpu.ClearVU0
add esp, 8
ret
vu1write:
cmp ecx, 0x11008000
jl vuend
cmp ecx, 0x1100c000
jge vuend
// clear vu1mem
and ecx, 0x3ff8
mov eax, Cpu
push 1
push ecx
call [eax]Cpu.ClearVU1
add esp, 8
vuend:
ret
}
}
int recMemConstWrite32(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( mem&0xffff0000 ) {
case 0x10000000: hwConstWrite32(mem, mmreg); return 0;
case 0x1f800000: psxHwConstWrite32(mem, mmreg); return 0;
case 0x12000000: gsConstWrite32(mem, mmreg); return 0;
case 0x1f900000:
case 0x1f000000:
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem);
CALLFunc((u32)SPU2write);
return 0;
case 0x14000000:
_recPushReg(mmreg);
iFlushCall(0);
PUSH32I(mem & ~0x04000000);
CALLFunc((u32)DEV9write32);
return 0;
case 0x1100:
_eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg);
if( mem < 0x11004000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU0);
ADD32ItoR(ESP, 8);
}
else if( mem >= 0x11008000 && mem < 0x1100c0000 ) {
PUSH32I(1);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU1);
ADD32ItoR(ESP, 8);
}
return 0;
default:
_eeWriteConstMem32(PS2MEM_BASE_+mem, mmreg);
return 1;
}
}
__declspec(naked) void recMemWrite64()
{
__asm {
mov edx, ecx
shr edx, 16
cmp dx, 0x1000
je hwwrite
cmp dx, 0x1200
je gswrite
cmp dx, 0x1100
je vuwrite
}
__asm {
// default write
mov edx, 64
call errwrite
hwwrite:
push dword ptr [eax+4]
push dword ptr [eax]
push ecx
call hwWrite64
add esp, 12
ret
gswrite:
push dword ptr [eax+4]
push dword ptr [eax]
push ecx
call gsWrite64
add esp, 12
ret
vuwrite:
mov ebx, dword ptr [eax]
mov edx, dword ptr [eax+4]
mov dword ptr [ecx+PS2MEM_BASE_], ebx
mov dword ptr [ecx+PS2MEM_BASE_+4], edx
cmp ecx, 0x11004000
jge vu1write
and ecx, 0x3ff8
// clear vu0mem
mov eax, Cpu
push 2
push ecx
call [eax]Cpu.ClearVU0
add esp, 8
ret
vu1write:
cmp ecx, 0x11008000
jl vuend
cmp ecx, 0x1100c000
jge vuend
// clear vu1mem
and ecx, 0x3ff8
mov eax, Cpu
push 2
push ecx
call [eax]Cpu.ClearVU1
add esp, 8
vuend:
ret
}
}
int recMemConstWrite64(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem>>16) ) {
case 0x1000: hwConstWrite64(mem, mmreg); return 0;
case 0x1200: gsConstWrite64(mem, mmreg); return 0;
case 0x1100:
_eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg);
if( mem < 0x11004000 ) {
PUSH32I(2);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU0);
ADD32ItoR(ESP, 8);
}
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
PUSH32I(2);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU1);
ADD32ItoR(ESP, 8);
}
return 0;
default:
_eeWriteConstMem64(PS2MEM_BASE_+mem, mmreg);
return 1;
}
}
__declspec(naked)
void recMemWrite128()
{
__asm {
mov edx, ecx
shr edx, 16
cmp dx, 0x1000
je hwwrite
cmp dx, 0x1200
je gswrite
cmp dx, 0x1100
je vuwrite
}
__asm {
mov edx, 128
call errwrite
hwwrite:
push eax
push ecx
call hwWrite128
add esp, 8
ret
vuwrite:
mov ebx, dword ptr [eax]
mov edx, dword ptr [eax+4]
mov edi, dword ptr [eax+8]
mov eax, dword ptr [eax+12]
mov dword ptr [ecx+PS2MEM_BASE_], ebx
mov dword ptr [ecx+PS2MEM_BASE_+4], edx
mov dword ptr [ecx+PS2MEM_BASE_+8], edi
mov dword ptr [ecx+PS2MEM_BASE_+12], eax
cmp ecx, 0x11004000
jge vu1write
and ecx, 0x3ff8
// clear vu0mem
mov eax, Cpu
push 4
push ecx
call [eax]Cpu.ClearVU0
add esp, 8
ret
vu1write:
cmp ecx, 0x11008000
jl vuend
cmp ecx, 0x1100c000
jge vuend
// clear vu1mem
and ecx, 0x3ff8
mov eax, Cpu
push 4
push ecx
call [eax]Cpu.ClearVU1
add esp, 8
vuend:
// default write
//movaps xmm7, qword ptr [eax]
// removes possible exceptions and saves on remapping memory
// *might* be faster for certain games, no way to tell
// cmp ecx, 0x20000000
// jb Write128
//
// // look for better mapping
// mov edx, ecx
// shr edx, 12
// shl edx, 3
// add edx, memLUT
// mov edx, dword ptr [edx + 4]
// cmp edx, 0
// je Write128
// mov edx, dword ptr [edx]
// cmp edx, 0
// je Write128
// and ecx, 0xfff
// movaps qword ptr [ecx+edx], xmm7
// jmp CheckOverwrite
//Write128:
//movaps qword ptr [ecx+PS2MEM_BASE_], xmm7
ret
gswrite:
sub esp, 8
movlps xmm7, qword ptr [eax]
movlps qword ptr [esp], xmm7
push ecx
call gsWrite64
// call again for upper 8 bytes
movlps xmm7, qword ptr [eax+8]
movlps qword ptr [esp+4], xmm7
add [esp], 8
call gsWrite64
add esp, 12
ret
}
}
int recMemConstWrite128(u32 mem, int mmreg)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&0xffff0000) ) {
case 0x10000000: hwConstWrite128(mem, mmreg); return 0;
case 0x12000000: gsConstWrite128(mem, mmreg); return 0;
case 0x1100:
_eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg);
if( mem < 0x11004000 ) {
PUSH32I(4);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU0);
ADD32ItoR(ESP, 8);
}
else if( mem >= 0x11008000 && mem < 0x1100c000 ) {
PUSH32I(4);
PUSH32I(mem&0x3ff8);
CALLFunc((u32)Cpu->ClearVU1);
ADD32ItoR(ESP, 8);
}
return 0;
default:
_eeWriteConstMem128(PS2MEM_BASE_+mem, mmreg);
return 1;
}
}
int memRead8 (u32 mem, u8 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x1f400000: *out = psxHw4Read8(mem); return 0;
case 0x10000000: *out = hwRead8(mem); return 0;
case 0x1f800000: *out = psxHwRead8(mem); return 0;
case 0x12000000: *out = gsRead8(mem); return 0;
case 0x14000000:
*out = DEV9read8(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u8*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead8RS (u32 mem, u64 *out)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x1f400000: *out = (s8)psxHw4Read8(mem); return 0;
case 0x10000000: *out = (s8)hwRead8(mem); return 0;
case 0x1f800000: *out = (s8)psxHwRead8(mem); return 0;
case 0x12000000: *out = (s8)gsRead8(mem); return 0;
case 0x14000000:
*out = (s8)DEV9read8(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(s8*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead8RU (u32 mem, u64 *out)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x1f400000: *out = (u8)psxHw4Read8(mem); return 0;
case 0x10000000: *out = (u8)hwRead8(mem); return 0;
case 0x1f800000: *out = (u8)psxHwRead8(mem); return 0;
case 0x12000000: *out = (u8)gsRead8(mem); return 0;
case 0x14000000:
*out = (u8)DEV9read8(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u8*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16(u32 mem, u16 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = hwRead16(mem); return 0;
case 0x1f800000: *out = psxHwRead16(mem); return 0;
case 0x12000000: *out = gsRead16(mem); return 0;
case 0x18000000: *out = 0; return 0;
case 0x1a000000: *out = ba0R16(mem); return 0;
case 0x1f900000:
case 0x1f000000:
*out = SPU2read(mem); return 0;
break;
case 0x14000000:
*out = DEV9read16(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u16*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16RS(u32 mem, u64 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = (s16)hwRead16(mem); return 0;
case 0x1f800000: *out = (s16)psxHwRead16(mem); return 0;
case 0x12000000: *out = (s16)gsRead16(mem); return 0;
case 0x18000000: *out = 0; return 0;
case 0x1a000000: *out = (s16)ba0R16(mem); return 0;
case 0x1f900000:
case 0x1f000000:
*out = (s16)SPU2read(mem); return 0;
break;
case 0x14000000:
*out = (s16)DEV9read16(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(s16*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16RU(u32 mem, u64 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = (u16)hwRead16(mem ); return 0;
case 0x1f800000: *out = (u16)psxHwRead16(mem ); return 0;
case 0x12000000: *out = (u16)gsRead16(mem); return 0;
case 0x18000000: *out = 0; return 0;
case 0x1a000000: *out = (u16)ba0R16(mem); return 0;
case 0x1f900000:
case 0x1f000000:
*out = (u16)SPU2read(mem ); return 0;
break;
case 0x14000000:
*out = (u16)DEV9read16(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u16*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32(u32 mem, u32 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = hwRead32(mem); return 0;
case 0x1f800000: *out = psxHwRead32(mem); return 0;
case 0x12000000: *out = gsRead32(mem); return 0;
case 0x14000000:
*out = (u32)DEV9read32(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u32*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32RS(u32 mem, u64 *out)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = (s32)hwRead32(mem); return 0;
case 0x1f800000: *out = (s32)psxHwRead32(mem); return 0;
case 0x12000000: *out = (s32)gsRead32(mem); return 0;
case 0x14000000:
*out = (s32)DEV9read32(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(s32*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32RU(u32 mem, u64 *out)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = (u32)hwRead32(mem); return 0;
case 0x1f800000: *out = (u32)psxHwRead32(mem); return 0;
case 0x12000000: *out = (u32)gsRead32(mem); return 0;
case 0x14000000:
*out = (u32)DEV9read32(mem & ~0x04000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0x04000000, *out);
return 0;
default:
*out = *(u32*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead64(u32 mem, u64 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: *out = hwRead64(mem); return 0;
case 0x12000000: *out = gsRead64(mem); return 0;
default:
*out = *(u64*)(PS2MEM_BASE+mem);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead128(u32 mem, u64 *out) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000:
hwRead128(mem, out);
return 0;
case 0x12000000:
out[0] = gsRead64(mem);
out[1] = gsRead64(mem + 8);
return 0;
default:
out[0] = *(u64*)(PS2MEM_BASE+mem);
out[1] = *(u64*)(PS2MEM_BASE+mem+8);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
void memWrite8 (u32 mem, u8 value) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x1f400000: psxHw4Write8(mem, value); return;
case 0x10000000: hwWrite8(mem, value); return;
case 0x1f800000: psxHwWrite8(mem, value); return;
case 0x12000000: gsWrite8(mem, value); return;
case 0x14000000:
DEV9write8(mem & ~0x04000000, value);
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0x04000000, value);
return;
default:
*(u8*)(PS2MEM_BASE+mem) = value;
if (CHECK_EEREC) {
REC_CLEARM(mem&~3);
}
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite16(u32 mem, u16 value) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: hwWrite16(mem, value); return;
case 0x1f800000: psxHwWrite16(mem, value); return;
case 0x12000000: gsWrite16(mem, value); return;
case 0x1f900000:
case 0x1f000000: SPU2write(mem, value); return;
case 0x14000000:
DEV9write16(mem & ~0x04000000, value);
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0x04000000, value);
return;
default:
*(u16*)(PS2MEM_BASE+mem) = value;
if (CHECK_EEREC) {
REC_CLEARM(mem&~3);
}
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite32(u32 mem, u32 value)
{
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: hwWrite32(mem, value); return;
case 0x1f800000: psxHwWrite32(mem, value); return;
case 0x12000000: gsWrite32(mem, value); return;
case 0x1f900000:
case 0x1f000000: SPU2write(mem, value); return;
case 0x14000000:
DEV9write32(mem & ~0x4000000, value);
SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0x4000000, value);
return;
default:
*(u32*)(PS2MEM_BASE+mem) = value;
if (CHECK_EEREC) {
REC_CLEARM(mem);
}
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite64(u32 mem, u64 value) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: hwWrite64(mem, value); return;
case 0x12000000: gsWrite64(mem, value); return;
default:
*(u64*)(PS2MEM_BASE+mem) = value;
if (CHECK_EEREC) {
REC_CLEARM(mem);
REC_CLEARM(mem+4);
}
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite128(u32 mem, u64 *value) {
mem = TRANSFORM_ADDR(mem);
switch( (mem&~0xffff) ) {
case 0x10000000: hwWrite128(mem, value); return;
case 0x12000000:
gsWrite64(mem, value[0]);
gsWrite64(mem + 8, value[1]);
return;
default:
*(u64*)(PS2MEM_BASE+mem) = value[0];
*(u64*)(PS2MEM_BASE+mem+8) = value[1];
if (CHECK_EEREC) {
REC_CLEARM(mem);
REC_CLEARM(mem+4);
REC_CLEARM(mem+8);
REC_CLEARM(mem+12);
}
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
#else
u8 *psM; //32mb Main Ram
u8 *psR; //4mb rom area
u8 *psR1; //256kb rom1 area (actually 196kb, but can't mask this)
u8 *psR2; // 0x00080000
u8 *psER; // 0x001C0000
u8 *psS; //0.015 mb, scratch pad
uptr *memLUTR;
uptr *memLUTW;
uptr *memLUTRK;
uptr *memLUTWK;
uptr *memLUTRU;
uptr *memLUTWU;
#define CHECK_MEM(mem) //MyMemCheck(mem)
void MyMemCheck(u32 mem)
{
if( mem == 0x1c02f2a0 )
SysPrintf("yo\n");
}
/////////////////////////////
// REGULAR MEM START
/////////////////////////////
void memMapMem(u32 base) {
int i;
for (i=0; i<0x02000; i++) memLUTRK[i + 0x00000 + base] = (uptr)&psM[i << 12];
for (i=0; i<0x00400; i++) memLUTRK[i + 0x1fc00 + base] = (uptr)&psR[i << 12];
for (i=0; i<0x00040; i++) memLUTRK[i + 0x1e000 + base] = (uptr)&psR1[i << 12];
for (i=0; i<0x00080; i++) memLUTRK[i + 0x1e400 + base] = (uptr)&psR2[i << 12];
for (i=0; i<0x001C0; i++) memLUTRK[i + 0x1e040 + base] = (uptr)&psER[i << 12];
for (i=0; i<0x00800; i++) memLUTRK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12];
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11000 + base] = (uptr)VU0.Micro;
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11004 + base] = (uptr)VU0.Mem;
for (i=0; i<0x00004; i++) memLUTRK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12];
for (i=0; i<0x00004; i++) memLUTRK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12];
for (i=0; i<0x02000; i++) memLUTWK[i + 0x00000 + base] = (uptr)&psM[i << 12];
for (i=0; i<0x00400; i++) memLUTWK[i + 0x1fc00 + base] = (uptr)&psR[i << 12];
for (i=0; i<0x00040; i++) memLUTWK[i + 0x1e000 + base] = (uptr)&psR1[i << 12];
for (i=0; i<0x00080; i++) memLUTWK[i + 0x1e400 + base] = (uptr)&psR2[i << 12];
for (i=0; i<0x001C0; i++) memLUTWK[i + 0x1e040 + base] = (uptr)&psER[i << 12];
for (i=0; i<0x00800; i++) memLUTWK[i + 0x1c000 + base] = (uptr)&psxM[(i & 0x1ff) << 12];
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11000 + base] = (uptr)VU0.Micro;
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11004 + base] = (uptr)VU0.Mem;
for (i=0; i<0x00004; i++) memLUTWK[i + 0x11008 + base] = (uptr)&VU1.Micro[i << 12];
for (i=0; i<0x00004; i++) memLUTWK[i + 0x1100c + base] = (uptr)&VU1.Mem[i << 12];
assert( ((uptr)VU0.Mem&15)==0 && ((uptr)VU0.Micro&15)==0);
for (i=0; i<0x00010; i++) memLUTRK[i + 0x10000 + base] = 1; // hwm
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f800 + base] = 2; // psh
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f400 + base] = 3; // psh4
for (i=0; i<0x00010; i++) memLUTRK[i + 0x18000 + base] = 4; // b80
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1a000 + base] = 5; // ba0
for (i=0; i<0x00010; i++) memLUTRK[i + 0x12000 + base] = 6; // gsm
for (i=0; i<0x00010; i++) memLUTRK[i + 0x14000 + base] = 7; // dev9
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f900 + base] = 8; // spu2
for (i=0; i<0x00010; i++) memLUTRK[i + 0x1f000 + base] = 8; // spu2 (not sure)
for (i=0; i<0x00010; i++) memLUTWK[i + 0x10000 + base] = 1; // hwm
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f800 + base] = 2; // psh
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f400 + base] = 3; // psh4
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1a000 + base] = 5; // ba0
for (i=0; i<0x00010; i++) memLUTWK[i + 0x12000 + base] = 6; // gsm
for (i=0; i<0x00010; i++) memLUTWK[i + 0x14000 + base] = 7; // dev9
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f900 + base] = 8; // spu2
for (i=0; i<0x00010; i++) memLUTWK[i + 0x1f000 + base] = 8; // spu2 (not sure)
}
void memMapKernelMem() {
memMapMem(0xa0000);
memMapMem(0x80000);
memMapMem(0x00000);
}
void memMapSupervisorMem() {
}
void memMapUserMem() {
}
int memInit() {
int i;
psR = (u8*)_aligned_malloc(0x00400010, 16);
psR1 = (u8*)_aligned_malloc(0x00080010, 16);
psR2 = (u8*)_aligned_malloc(0x00080010, 16);
if (psxInit() == -1)
return -1;
memLUTRK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
memLUTWK = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
memLUTRU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
memLUTWU = (uptr*)_aligned_malloc(0x100000 * sizeof(uptr), 16);
psM = (u8*)_aligned_malloc(0x02000010, 16);
psER = (u8*)_aligned_malloc(0x001C0010, 16);
psS = (u8*)_aligned_malloc(0x00004010, 16);
if (memLUTRK == NULL || memLUTWK == NULL ||
memLUTRU == NULL || memLUTWU == NULL ||
psM == NULL || psR == NULL || psR1 == NULL ||
psR2 == NULL || psER == NULL || psS == NULL) {
SysMessage(_("Error allocating memory")); return -1;
}
memset(memLUTRK, 0, 0x100000 * 4);
memset(memLUTWK, 0, 0x100000 * 4);
memset(memLUTRU, 0, 0x100000 * 4);
memset(memLUTWU, 0, 0x100000 * 4);
memset(psM, 0, 0x02000010);
memset(psR, 0, 0x00400010);
memset(psR1, 0, 0x00080010);
memset(psR2, 0, 0x00080010);
memset(psER, 0, 0x001C0010);
memset(psS, 0, 0x00004010);
for (i=0x00000; i<0x00004; i++) memLUTRK[i + 0x70000] = (uptr)&psS[i << 12];
for (i=0x00000; i<0x00004; i++) memLUTWK[i + 0x70000] = (uptr)&psS[i << 12];
for (i=0x00000; i<0x00004; i++) memLUTRU[i + 0x70000] = (uptr)&psS[i << 12];
for (i=0x00000; i<0x00004; i++) memLUTWU[i + 0x70000] = (uptr)&psS[i << 12];
memMapKernelMem();
memMapSupervisorMem();
memMapUserMem();
memSetKernelMode();
#ifdef ENABLECACHE
memset(pCache,0,sizeof(_cacheS)*64);
#endif
return 0;
}
void memShutdown() {
FREE(psM);
FREE(psR);
FREE(psR1);
FREE(psR2);
FREE(psER);
FREE(psS);
FREE(memLUTRK);
FREE(memLUTWK);
FREE(memLUTRU);
FREE(memLUTWU);
}
void memSetPageAddr(u32 vaddr, u32 paddr) {
// SysPrintf("memSetPageAddr: %8.8x -> %8.8x\n", vaddr, paddr);
memLUTRU[vaddr >> 12] = memLUTRK[paddr >> 12];
memLUTWU[vaddr >> 12] = memLUTWK[paddr >> 12];
memLUTRK[vaddr >> 12] = memLUTRK[paddr >> 12];
memLUTWK[vaddr >> 12] = memLUTWK[paddr >> 12];
}
void memClearPageAddr(u32 vaddr) {
// SysPrintf("memClearPageAddr: %8.8x\n", vaddr);
if ((vaddr & 0xffffc000) == 0x70000000) return;
memLUTRU[vaddr >> 12] = 0;
memLUTWU[vaddr >> 12] = 0;
#ifdef FULLTLB
memLUTRK[vaddr >> 12] = 0;
memLUTWK[vaddr >> 12] = 0;
#endif
}
int memRead8 (u32 mem, u8 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
u8 *tmp = readCache(mem);
*out = *(u8 *)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u8 *)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = hwRead8(mem & ~0xa0000000); return 0;
case 2: // psh
*out = psxHwRead8(mem & ~0xa0000000); return 0;
case 3: // psh4
*out = psxHw4Read8(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = gsRead8(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = DEV9read8(mem & ~0xa4000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead8RS (u32 mem, u64 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(s8 *)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(s8 *)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (s8)hwRead8(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (s8)psxHwRead8(mem & ~0xa0000000); return 0;
case 3: // psh4
*out = (s8)psxHw4Read8(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = (s8)gsRead8(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (s8)DEV9read8(mem & ~0xa4000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead8RU (u32 mem, u64 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(u8 *)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u8 *)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (u8)hwRead8(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (u8)psxHwRead8(mem & ~0xa0000000); return 0;
case 3: // psh4
*out = (u8)psxHw4Read8(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = (u8)gsRead8(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (u8)DEV9read8(mem & ~0xa4000000);
SysPrintf("DEV9 read8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read32 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16(u32 mem, u16 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
u8 *tmp = readCache(mem);
*out = *(u16 *)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u16*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = hwRead16(mem & ~0xa0000000); return 0;
case 2: // psh
*out = psxHwRead16(mem & ~0xa0000000); return 0;
case 4: // b80
#ifdef MEM_LOG
MEM_LOG("b800000 Memory read16 address %x\n", mem);
#endif
*out = 0; return 0;
case 5: // ba0
*out = ba0R16(mem); return 0;
case 6: // gsm
*out = gsRead16(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = DEV9read16(mem & ~0xa4000000);
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
return 0;
case 8: // spu2
*out = SPU2read(mem & ~0xa0000000); return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16RS(u32 mem, u64 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(s16*)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(s16*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (s16)hwRead16(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (s16)psxHwRead16(mem & ~0xa0000000); return 0;
case 4: // b80
#ifdef MEM_LOG
MEM_LOG("b800000 Memory read16 address %x\n", mem);
#endif
*out = 0; return 0;
case 5: // ba0
*out = (s16)ba0R16(mem); return 0;
case 6: // gsm
*out = (s16)gsRead16(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (s16)DEV9read16(mem & ~0xa4000000);
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
return 0;
case 8: // spu2
*out = (s16)SPU2read(mem & ~0xa0000000); return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead16RU(u32 mem, u64 *out) {
char *p;
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(u16*)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u16*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (u16)hwRead16(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (u16)psxHwRead16(mem & ~0xa0000000); return 0;
case 4: // b80
#ifdef MEM_LOG
MEM_LOG("b800000 Memory read16 address %x\n", mem);
#endif
*out = 0; return 0;
case 5: // ba0
*out = (u16)ba0R16(mem); return 0;
case 6: // gsm
*out = (u16)gsRead16(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (u16)DEV9read16(mem & ~0xa4000000);
SysPrintf("DEV9 read16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, *out);
return 0;
case 8: // spu2
*out = (u16)SPU2read(mem & ~0xa0000000); return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read16 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32(u32 mem, u32 *out) {
char *p;
CHECK_MEM(mem);
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
u8 *tmp = readCache(mem);
*out = *(u32 *)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u32*)(p + (mem & 0xfff));
return 0;
}
assert( (int)(uptr)p < 8 );
switch ((int)(uptr)p) {
case 1: // hwm
*out = hwRead32(mem & ~0xa0000000); return 0;
case 2: // psh
*out = psxHwRead32(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = gsRead32(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = DEV9read32(mem & ~0xa4000000);
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32RS(u32 mem, u64 *out) {
char *p;
CHECK_MEM(mem);
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(s32*)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(s32*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (s32)hwRead32(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (s32)psxHwRead32(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = (s32)gsRead32(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (s32)DEV9read32(mem & ~0xa4000000);
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead32RU(u32 mem, u64 *out) {
char *p;
CHECK_MEM(mem);
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
char *tmp = (char*)readCache(mem);
*out = *(u32*)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u32*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = (u32)hwRead32(mem & ~0xa0000000); return 0;
case 2: // psh
*out = (u32)psxHwRead32(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = (u32)gsRead32(mem & ~0xa0000000); return 0;
case 7: // dev9
*out = (u32)DEV9read32(mem & ~0xa4000000);
SysPrintf("DEV9 read32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, *out);
return 0;
}
#ifdef PCSX2_DEVBUILD
MEM_LOG("Unknown Memory read32 from address %8.8x (Status=%8.8x)\n", mem, cpuRegs.CP0.n.Status);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead64(u32 mem, u64 *out) {
char *p;
CHECK_MEM(mem);
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
u8 *tmp = readCache(mem);
*out = *(u64*)(tmp+(mem&0xf));
return 0;
}
#endif
*out = *(u64*)(p + (mem & 0xfff));
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
*out = hwRead64(mem & ~0xa0000000); return 0;
case 6: // gsm
*out = gsRead64(mem & ~0xa0000000); return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read64 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
int memRead128(u32 mem, u64 *out) {
char *p;
CHECK_MEM(mem);
p = (char *)(memLUTR[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 &&
(cpuRegs.CP0.r[16] & 0x10000) && !(cpuRegs.CP0.n.Status.val & 0x4)) {
u64 *tmp = (u64*)readCache(mem);
out[0] = tmp[0];
out[1] = tmp[1];
return 0;
}
#endif
p+= mem & 0xfff;
out[0] = ((u64*)p)[0];
out[1] = ((u64*)p)[1];
return 0;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwRead128(mem & ~0xa0000000, out); return 0;
case 6: // gsm
out[0] = gsRead64((mem ) & ~0xa0000000);
out[1] = gsRead64((mem+8) & ~0xa0000000); return 0;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory read128 from address %8.8x\n", mem);
#endif
cpuTlbMissR(mem, cpuRegs.branch);
return -1;
}
#define CHECK_VUMEM(size) { \
if( mem >= 0x11000000 && mem < 0x11004000 ) \
Cpu->ClearVU0(mem&0x3ff8, size); \
else if( mem >= 0x11008000 && mem < 0x1100c000 ) \
Cpu->ClearVU1(mem&0x3ff8, size); \
}
void memWrite8 (u32 mem, u8 value) {
char *p;
p = (char *)(memLUTW[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
writeCache8(mem, value);
return;
}
#endif
*(u8 *)(p + (mem & 0xfff)) = value;
if (CHECK_EEREC) {
CHECK_VUMEM(1);
REC_CLEARM(mem&(~3));
// PSXREC_CLEARM(mem & 0x1ffffc);
}
return;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwWrite8(mem & ~0xa0000000, value);
return;
case 2: // psh
psxHwWrite8(mem & ~0xa0000000, value); return;
case 3: // psh4
psxHw4Write8(mem & ~0xa0000000, value); return;
case 6: // gsm
gsWrite8(mem & ~0xa0000000, value); return;
case 7: // dev9
DEV9write8(mem & ~0xa4000000, value);
SysPrintf("DEV9 write8 %8.8lx: %2.2lx\n", mem & ~0xa4000000, value);
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write8 to address %x with data %2.2x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite16(u32 mem, u16 value) {
char *p;
p = (char *)(memLUTW[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
writeCache16(mem, value);
return;
}
#endif
*(u16*)(p + (mem & 0xfff)) = value;
if (CHECK_EEREC) {
CHECK_VUMEM(1);
REC_CLEARM(mem&~1);
//PSXREC_CLEARM(mem & 0x1ffffe);
}
return;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwWrite16(mem & ~0xa0000000, value);
return;
case 2: // psh
psxHwWrite16(mem & ~0xa0000000, value); return;
case 5: // ba0
#ifdef MEM_LOG
MEM_LOG("ba00000 Memory write16 to address %x with data %x\n", mem, value);
#endif
return;
case 6: // gsm
gsWrite16(mem & ~0xa0000000, value); return;
case 7: // dev9
DEV9write16(mem & ~0xa4000000, value);
SysPrintf("DEV9 write16 %8.8lx: %4.4lx\n", mem & ~0xa4000000, value);
return;
case 8: // spu2
SPU2write(mem & ~0xa0000000, value); return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write16 to address %x with data %4.4x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite32(u32 mem, u32 value)
{
char *p;
p = (char *)(memLUTW[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000))
{
writeCache32(mem, value);
return;
}
#endif
*(u32*)(p + (mem & 0xfff)) = value;
if (CHECK_EEREC) {
CHECK_VUMEM(1);
REC_CLEARM(mem);
// PSXREC_CLEARM(mem & 0x1fffff);
}
return;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwWrite32(mem & ~0xa0000000, value);
return;
case 2: // psh
psxHwWrite32(mem & ~0xa0000000, value); return;
case 6: // gsm
gsWrite32(mem & ~0xa0000000, value); return;
case 7: // dev9
DEV9write32(mem & ~0xa4000000, value);
SysPrintf("DEV9 write32 %8.8lx: %8.8lx\n", mem & ~0xa4000000, value);
return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write32 to address %x with data %8.8x\n", mem, value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite64(u32 mem, u64 value) {
char *p;
p = (char *)(memLUTW[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
writeCache64(mem, value);
return;
}
#endif
/* __asm __volatile (
"movq %1, %%mm0\n"
"movq %%mm0, %0\n"
"emms\n"
: "=m"(*(u64*)(p + (mem & 0xfff))) : "m"(value)
);*/
*(u64*)(p + (mem & 0xfff)) = value;
if (CHECK_EEREC) {
CHECK_VUMEM(2);
REC_CLEARM(mem);
REC_CLEARM(mem+4);
}
return;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwWrite64(mem & ~0xa0000000, value);
return;
case 6: // gsm
gsWrite64(mem & ~0xa0000000, value); return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write64 to address %x with data %8.8x_%8.8x\n", mem, (u32)(value>>32), (u32)value);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
void memWrite128(u32 mem, u64 *value) {
char *p;
p = (char *)(memLUTW[mem >> 12]);
if ((uptr)p > 0x10) {
#ifdef ENABLECACHE
if ((mem & 0x20000000) == 0 && (cpuRegs.CP0.r[16] & 0x10000)) {
writeCache128(mem, value);
return;
}
#endif
p+= mem & 0xfff;
((u64*)p)[0] = value[0];
((u64*)p)[1] = value[1];
if (CHECK_EEREC) {
CHECK_VUMEM(4);
REC_CLEARM(mem);
REC_CLEARM(mem+4);
REC_CLEARM(mem+8);
REC_CLEARM(mem+12);
/* PSXREC_CLEARM((mem) & 0x1fffff);
PSXREC_CLEARM((mem+4) & 0x1fffff);
PSXREC_CLEARM((mem+8) & 0x1fffff);
PSXREC_CLEARM((mem+12) & 0x1fffff);*/
}
return;
}
switch ((int)(uptr)p) {
case 1: // hwm
hwWrite128(mem & ~0xa0000000, value);
return;
case 6: // gsm
mem &= ~0xa0000000;
gsWrite64(mem, value[0]);
gsWrite64(mem+8, value[1]); return;
}
#ifdef MEM_LOG
MEM_LOG("Unknown Memory write128 to address %x with data %8.8x_%8.8x_%8.8x_%8.8x\n", mem, ((u32*)value)[3], ((u32*)value)[2], ((u32*)value)[1], ((u32*)value)[0]);
#endif
cpuTlbMissW(mem, cpuRegs.branch);
}
#endif // PCSX2_VIRTUAL_MEM
void loadBiosRom(char *ext, u8 *dest) {
struct stat buf;
char Bios1[256];
char Bios[256];
FILE *fp;
char *ptr;
int i;
strcpy(Bios, Config.BiosDir);
strcat(Bios, Config.Bios);
sprintf(Bios1, "%s.%s", Bios, ext);
if (stat(Bios1, &buf) != -1) {
fp = fopen(Bios1, "rb");
fread(dest, 1, buf.st_size, fp);
fclose(fp);
return;
}
sprintf(Bios1, "%s", Bios);
ptr = Bios1; i = strlen(Bios1);
while (i > 0) { if (ptr[i] == '.') break; i--; }
ptr[i+1] = 0;
strcat(Bios1, ext);
if (stat(Bios1, &buf) != -1) {
fp = fopen(Bios1, "rb");
fread(dest, 1, buf.st_size, fp);
fclose(fp);
return;
}
sprintf(Bios1, "%s%s.bin", Config.BiosDir, ext);
if (stat(Bios1, &buf) != -1) {
fp = fopen(Bios1, "rb");
fread(dest, 1, buf.st_size, fp);
fclose(fp);
return;
}
SysPrintf("\n\n\n");
SysPrintf("**************\n");
SysPrintf("%s NOT FOUND\n", ext);
SysPrintf("**************\n\n\n");
}
void memReset() {
struct stat buf;
char Bios[256];
FILE *fp;
#ifdef PCSX2_VIRTUAL_MEM
DWORD OldProtect;
memset(PS2MEM_BASE, 0, 0x02000000);
memset(PS2MEM_SCRATCH, 0, 0x00004000);
#else
memset(psM, 0, 0x02000000);
memset(psS, 0, 0x00004000);
#endif
strcpy(Bios, Config.BiosDir);
strcat(Bios, Config.Bios);
if (stat(Bios, &buf) == -1) {
SysMessage(_("Unable to load bios: '%s', PCSX2 can't run without that"), Bios);
return;
}
#ifdef PCSX2_VIRTUAL_MEM
#ifdef _WIN32
// make sure can write
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READWRITE, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READWRITE, &OldProtect);
#else
mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ|PROT_WRITE);
mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ|PROT_WRITE);
mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ|PROT_WRITE);
mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ|PROT_WRITE);
#endif
#endif
fp = fopen(Bios, "rb");
fread(PS2MEM_ROM, 1, buf.st_size, fp);
fclose(fp);
BiosVersion = GetBiosVersion();
SysPrintf("Bios Version %d.%d\n", BiosVersion >> 8, BiosVersion & 0xff);
//injectIRX("host.irx"); //not fully tested; still buggy
// reset memLUT
loadBiosRom("rom1", PS2MEM_ROM1);
loadBiosRom("rom2", PS2MEM_ROM2);
loadBiosRom("erom", PS2MEM_EROM);
#ifdef PCSX2_VIRTUAL_MEM
#ifdef _WIN32
VirtualProtect(PS2MEM_ROM, 0x00400000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM1, 0x00040000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_ROM2, 0x00080000, PAGE_READONLY, &OldProtect);
VirtualProtect(PS2MEM_EROM, 0x001C0000, PAGE_READONLY, &OldProtect);
#else
mprotect(PS2EMEM_ROM, 0x00400000, PROT_READ);
mprotect(PS2EMEM_ROM1, 0x00400000, PROT_READ);
mprotect(PS2EMEM_ROM2, 0x00800000, PROT_READ);
mprotect(PS2EMEM_EROM, 0x001C0000, PROT_READ);
#endif
#endif
}
void memSetKernelMode() {
#ifndef PCSX2_VIRTUAL_MEM
memLUTR = memLUTRK;
memLUTW = memLUTWK;
#endif
MemMode = 0;
}
void memSetSupervisorMode() {
}
void memSetUserMode() {
#ifdef FULLTLB
#ifndef PCSX2_VIRTUAL_MEM
memLUTR = memLUTRU;
memLUTW = memLUTWU;
#endif
MemMode = 2;
#endif
}