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:
magumagu 2015-02-15 17:31:08 -08:00
parent 6a14300c9c
commit 314b241220
2 changed files with 41 additions and 12 deletions

View File

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

View File

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