mirror of
https://github.com/PCSX2/pcsx2-sourceforge.git
synced 2026-02-04 11:21:17 +01:00
2118 lines
50 KiB
C++
2118 lines
50 KiB
C++
/* Pcsx2 - Pc Ps2 Emulator
|
|
* Copyright (C) 2002-2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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"
|
|
#include "iR5900.h"
|
|
#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
|
|
|
|
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
|
|
|
|
if (mem == 0x1a000006) {
|
|
static int ba6;
|
|
ba6++;
|
|
if (ba6 == 3) ba6 = 0;
|
|
return ba6;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
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); \
|
|
} \
|
|
|
|
PSMEMORYMAP initMemoryMap(uptr* aPFNs, uptr* aVFNs)
|
|
{
|
|
PSMEMORYMAP m;
|
|
m.aPFNs = aPFNs;
|
|
m.aVFNs = aVFNs;
|
|
return m;
|
|
}
|
|
|
|
// only do vm hack for release
|
|
#ifndef PCSX2_DEVBUILD
|
|
#define VM_HACK
|
|
#endif
|
|
|
|
// 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); \
|
|
} \
|
|
|
|
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;
|
|
|
|
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);
|
|
}
|
|
|
|
//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() { \
|
|
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() { \
|
|
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; \
|
|
} \
|
|
} \
|
|
|
|
int SysPageFaultExceptionFilter(struct _EXCEPTION_POINTERS* eps)
|
|
{
|
|
struct _EXCEPTION_RECORD* ExceptionRecord = eps->ExceptionRecord;
|
|
struct _CONTEXT* ContextRecord = eps->ContextRecord;
|
|
|
|
u32 addr;
|
|
|
|
C_ASSERT(sizeof(ContextRecord->Eax) == 4);
|
|
|
|
// If the exception is not a page fault, exit.
|
|
if (ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
|
{
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
// 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 EXCEPTION_CONTINUE_EXECUTION;
|
|
|
|
// 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 EXCEPTION_CONTINUE_EXECUTION;
|
|
|
|
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 EXCEPTION_CONTINUE_EXECUTION;
|
|
}
|
|
}
|
|
|
|
#ifdef VM_HACK
|
|
{
|
|
u32 code = *(u32*)ExceptionRecord->ExceptionAddress;
|
|
u32 rd = 0;
|
|
|
|
if( ExceptionRecord->ExceptionInformation[0] ) {
|
|
//SKIP_WRITE();
|
|
// shouldn't be writing
|
|
}
|
|
else {
|
|
SysPrintf("vmhack ");
|
|
SKIP_READ();
|
|
//((u32*)&ContextRecord->Eax)[rd] = 0;
|
|
return EXCEPTION_CONTINUE_EXECUTION; // TODO: verify this!!!
|
|
}
|
|
}
|
|
DefaultHandler:
|
|
#endif
|
|
|
|
return EXCEPTION_CONTINUE_SEARCH;
|
|
}
|
|
|
|
// 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);
|
|
|
|
// 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);
|
|
|
|
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 ) {
|
|
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];
|
|
}
|
|
}
|
|
|
|
void memClearPageAddr(u32 vaddr) {
|
|
// SysPrintf("memClearPageAddr: %8.8x\n", vaddr);
|
|
|
|
if ((vaddr & 0xffffc000) == 0x70000000) return;
|
|
|
|
// 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;
|
|
// }
|
|
// }
|
|
}
|
|
|
|
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 0x11000000:
|
|
_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 < 0x1100c000 ) {
|
|
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 0x11000000:
|
|
_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;
|
|
|
|
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;
|
|
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;
|
|
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;
|
|
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];
|
|
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);
|
|
}
|
|
|
|
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;
|
|
|
|
DWORD OldProtect;
|
|
memset(PS2MEM_BASE, 0, 0x02000000);
|
|
memset(PS2MEM_SCRATCH, 0, 0x00004000);
|
|
|
|
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;
|
|
}
|
|
|
|
// 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);
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
|
|
void memSetKernelMode() {
|
|
MemMode = 0;
|
|
}
|
|
|
|
void memSetSupervisorMode() {
|
|
}
|
|
|
|
void memSetUserMode() {
|
|
#ifdef FULLTLB
|
|
MemMode = 2;
|
|
#endif
|
|
}
|
|
|
|
|