Try to fix our memory map to match the GameCube.
This basically just restores the RAM mirroring that existed before PR1856 (address translation).
This commit is contained in:
parent
6a14300c9c
commit
314b241220
|
@ -118,7 +118,8 @@ bool IsInitialized()
|
|||
// with address translation turned off. (This is only used by the CPU;
|
||||
// other devices, like the GPU, use other rules, approximated by
|
||||
// Memory::GetPointer.) This memory is laid out as follows:
|
||||
// [0x00000000, 0x01800000) - 24MB RAM
|
||||
// [0x00000000, 0x02000000) - 32MB RAM
|
||||
// [0x02000000, 0x08000000) - Mirrors of 32MB RAM
|
||||
// [0x08000000, 0x0C000000) - EFB "mapping" (not handled here)
|
||||
// [0x0C000000, 0x0E000000) - MMIO etc. (not handled here)
|
||||
// [0x10000000, 0x14000000) - 64MB RAM (Wii-only; slightly slower)
|
||||
|
@ -127,13 +128,16 @@ bool IsInitialized()
|
|||
// with address translation turned on. Instead of changing the mapping
|
||||
// based on the BAT registers, we approximate the common BAT configuration
|
||||
// used by games:
|
||||
// [0x00000000, 0x01800000) - 24MB RAM, cached access, normally only mapped
|
||||
// [0x00000000, 0x02000000) - 32MB RAM, cached access, normally only mapped
|
||||
// during startup by Wii WADs
|
||||
// [0x02000000, 0x08000000) - Mirrors of 32MB RAM (not implemented here)
|
||||
// [0x40000000, 0x50000000) - FakeVMEM
|
||||
// [0x70000000, 0x80000000) - FakeVMEM
|
||||
// [0x80000000, 0x81800000) - 24MB RAM, cached access
|
||||
// [0x80000000, 0x82000000) - 32MB RAM, cached access
|
||||
// [0x82000000, 0x88000000) - Mirrors of 32MB RAM (not implemented here)
|
||||
// [0x90000000, 0x94000000) - 64MB RAM, Wii-only, cached access
|
||||
// [0xC0000000, 0xC1800000) - 24MB RAM, uncached access
|
||||
// [0xC0000000, 0xC2000000) - 32MB RAM, uncached access
|
||||
// [0xC2000000, 0xC8000000) - Mirrors of 32MB RAM (not implemented here)
|
||||
// [0xC8000000, 0xCC000000) - EFB "mapping" (not handled here)
|
||||
// [0xCC000000, 0xCE000000) - MMIO etc. (not handled here)
|
||||
// [0xD0000000, 0xD4000000) - 64MB RAM, Wii-only, uncached access
|
||||
|
@ -145,7 +149,16 @@ bool IsInitialized()
|
|||
// Each of these 4GB regions is followed by 4GB of empty space so overflows
|
||||
// in address computation in the JIT don't access the wrong memory.
|
||||
//
|
||||
// The neighboring mirrors of RAM ([0x02000000, 0x08000000), etc.) exist because
|
||||
// the bus masks off the bits in question for RAM accesses; using them is a
|
||||
// terrible idea because the CPU cache won't handle them correctly, but a
|
||||
// few buggy games (notably Rogue Squadron 2) use them by accident. They
|
||||
// aren't backed by memory mappings because they are used very rarely.
|
||||
//
|
||||
// Dolphin doesn't emulate the difference between cached and uncached access.
|
||||
//
|
||||
// TODO: The actual size of RAM is REALRAM_SIZE (24MB); the other 8MB shouldn't
|
||||
// be backed by actual memory.
|
||||
static MemoryView views[] =
|
||||
{
|
||||
{&m_pRAM, 0x00000000, RAM_SIZE, 0},
|
||||
|
|
|
@ -136,12 +136,17 @@ __forceinline static T ReadFromHardware(const u32 em_address)
|
|||
else
|
||||
return (T)Memory::mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address);
|
||||
}
|
||||
if ((segment == 0x0 || segment == 0x8 || segment == 0xC) && (em_address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
if (segment == 0x0 || segment == 0x8 || segment == 0xC)
|
||||
{
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address & 0x0FFFFFFF]));
|
||||
// Handle RAM; the masking intentionally discards bits (essentially creating
|
||||
// mirrors of memory).
|
||||
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK]));
|
||||
}
|
||||
if (Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
// Handle EXRAM.
|
||||
// TODO: Is this supposed to be mirrored like main RAM?
|
||||
return bswap((*(const T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF]));
|
||||
}
|
||||
if (segment == 0xE && (em_address < (0xE0000000 + Memory::L1_CACHE_SIZE)))
|
||||
|
@ -165,9 +170,12 @@ __forceinline static T ReadFromHardware(const u32 em_address)
|
|||
else
|
||||
return (T)Memory::mmio_mapping->Read<typename std::make_unsigned<T>::type>(em_address | 0xC0000000);
|
||||
}
|
||||
if (em_address < Memory::REALRAM_SIZE)
|
||||
if (segment == 0x0)
|
||||
{
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address]));
|
||||
// Handle RAM; the masking intentionally discards bits (essentially creating
|
||||
// mirrors of memory).
|
||||
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
|
||||
return bswap((*(const T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK]));
|
||||
}
|
||||
if (Memory::m_pEXRAM && segment == 0x1 && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
|
@ -254,13 +262,18 @@ __forceinline static void WriteToHardware(u32 em_address, const T data)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if ((segment == 0x8 || segment == 0xC) && (em_address & 0x0FFFFFFF) < Memory::REALRAM_SIZE)
|
||||
if (segment == 0x0 || segment == 0x8 || segment == 0xC)
|
||||
{
|
||||
*(T*)&Memory::m_pRAM[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
// Handle RAM; the masking intentionally discards bits (essentially creating
|
||||
// mirrors of memory).
|
||||
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
|
||||
*(T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK] = bswap(data);
|
||||
return;
|
||||
}
|
||||
if (Memory::m_pEXRAM && (segment == 0x9 || segment == 0xD) && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
{
|
||||
// Handle EXRAM.
|
||||
// TODO: Is this supposed to be mirrored like main RAM?
|
||||
*(T*)&Memory::m_pEXRAM[em_address & 0x0FFFFFFF] = bswap(data);
|
||||
return;
|
||||
}
|
||||
|
@ -304,9 +317,12 @@ __forceinline static void WriteToHardware(u32 em_address, const T data)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (em_address < Memory::REALRAM_SIZE)
|
||||
if (segment == 0x0)
|
||||
{
|
||||
*(T*)&Memory::m_pRAM[em_address] = bswap(data);
|
||||
// Handle RAM; the masking intentionally discards bits (essentially creating
|
||||
// mirrors of memory).
|
||||
// TODO: Only the first REALRAM_SIZE is supposed to be backed by actual memory.
|
||||
*(T*)&Memory::m_pRAM[em_address & Memory::RAM_MASK] = bswap(data);
|
||||
return;
|
||||
}
|
||||
if (Memory::m_pEXRAM && segment == 0x1 && (em_address & 0x0FFFFFFF) < Memory::EXRAM_SIZE)
|
||||
|
|
Loading…
Reference in New Issue