/* Copyright (C) 2001 StrmnNrmn 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. */ // InternalRead is only used for debug puposes. static InternalMemFastFunction gInternalReadFastTable[0x4000]; bool Memory_GetInternalReadAddress(u32 address, void ** translated) { return (gInternalReadFastTable)[(address)>>18](address, translated); } static bool InternalReadInvalid( u32 address [[maybe_unused]], void ** translated ) { *translated = g_pMemoryBuffers[MEM_UNUSED]; return false; } static bool InternalReadMapped( u32 address, void ** translated ) { bool missing; u32 physical_addr = TLBEntry::Translate(address, missing); if (physical_addr != 0) { *translated = g_pu8RamBase + (physical_addr & 0x007FFFFF); return true; } return InternalReadInvalid(address, translated); } static bool InternalRead_4Mb_8000_803F( u32 address, void ** translated ) { *translated = g_pu8RamBase + (address & 0x003FFFFF); return true; } static bool InternalRead_8Mb_8000_807F( u32 address, void ** translated ) { *translated = g_pu8RamBase + (address & 0x007FFFFF); return true; } static bool InternalReadROM( u32 address, void ** translated ) { // Note: NOT 0x1FFFFFFF u32 offset( address & 0x00FFFFFF ); *translated = RomBuffer::GetAddressRaw( offset ); if (*translated != NULL) return true; return InternalReadInvalid( address, translated ); } static bool InternalRead_8400_8400( u32 address, void ** translated ) { u32 offset = 0; // 0x0400 0000 to 0x0400 FFFF SP registers if ((address&0x1FFFFFFF) < 0x4002000) { DPF( DEBUG_MEMORY_SP_IMEM, "Reading from SP_MEM: 0x%08x", address ); offset = address & 0x1FFF; *translated = (u8 *)g_pMemoryBuffers[MEM_SP_MEM] + offset; return true; } return InternalReadInvalid( address, translated ); } static bool InternalRead_9FC0_9FCF( u32 address, void ** translated ) { u32 offset = 0; if ((address&0x1FFFFFFF) <= PIF_ROM_END) { DPF( DEBUG_MEMORY_PIF, "Reading from MEM_PIF_ROM: 0x%08x", address ); offset = address & 0x0FFF; *translated = (u8 *)g_pMemoryBuffers[MEM_PIF_RAM] + offset; return true; } else if ((address&0x1FFFFFFF) <= PIF_RAM_END) { DPF( DEBUG_MEMORY_PIF, "Reading from MEM_PIF_RAM: 0x%08x", address ); DBGConsole_Msg(0, "[WReading directly from PI ram]: 0x%08x!", address); offset = address & 0x0FFF; *translated = (u8 *)g_pMemoryBuffers[MEM_PIF_RAM] + offset; return true; } return InternalReadInvalid( address, translated ); } struct InternalMemMapEntry { u32 mStartAddr, mEndAddr; InternalMemFastFunction InternalReadFastFunction; }; // Physical ram: 0x80000000 upwards is set up when tables are initialised InternalMemMapEntry InternalMemMapEntries[] = { { 0x0000, 0x7FFF, InternalReadMapped }, // Mapped Memory { 0x8000, 0x807F, InternalReadInvalid }, // RDRAM - Initialised later { 0x8080, 0x83FF, InternalReadInvalid }, // Cartridge Domain 2 Address 1 { 0x8400, 0x8400, InternalRead_8400_8400 }, // Cartridge Domain 2 Address 1 { 0x8404, 0x85FF, InternalReadInvalid }, // Cartridge Domain 2 Address 1 { 0x8600, 0x87FF, InternalReadROM }, // Cartridge Domain 1 Address 1 { 0x8800, 0x8FFF, InternalReadROM }, // Cartridge Domain 2 Address 2 { 0x9000, 0x9FBF, InternalReadROM }, // Cartridge Domain 1 Address 2 { 0x9FC0, 0x9FCF, InternalRead_9FC0_9FCF }, // pif RAM/ROM { 0x9FD0, 0x9FFF, InternalReadROM }, // Cartridge Domain 1 Address 3 { 0xA000, 0xA07F, InternalReadInvalid }, // Physical RAM - Copy of above { 0xA080, 0xA3FF, InternalReadInvalid }, // Unused { 0xA400, 0xA400, InternalRead_8400_8400 }, // Unused { 0xA404, 0xA4FF, InternalReadInvalid }, // Unused { 0xA500, 0xA5FF, InternalReadROM }, // Cartridge Domain 2 Address 1 { 0xA600, 0xA7FF, InternalReadROM }, // Cartridge Domain 1 Address 1 { 0xA800, 0xAFFF, InternalReadROM }, // Cartridge Domain 2 Address 2 { 0xB000, 0xBFBF, InternalReadROM }, // Cartridge Domain 1 Address 2 { 0xBFC0, 0xBFCF, InternalRead_9FC0_9FCF }, // pif RAM/ROM { 0xBFD0, 0xBFFF, InternalReadROM }, // Cartridge Domain 1 Address 3 { 0xC000, 0xDFFF, InternalReadMapped }, // Mapped Memory { 0xE000, 0xFFFF, InternalReadMapped }, // Mapped Memory { 0, 0, NULL} }; void Memory_InitInternalTables(u32 ram_size) { memset(gInternalReadFastTable, 0, sizeof(gInternalReadFastTable)); u32 i = 0; u32 entry = 0; u32 start_addr = 0; u32 end_addr = 0; while (InternalMemMapEntries[entry].InternalReadFastFunction != NULL) { start_addr = InternalMemMapEntries[entry].mStartAddr; end_addr = InternalMemMapEntries[entry].mEndAddr; for (i = (start_addr>>2); i <= (end_addr>>2); i++) { gInternalReadFastTable[i] = InternalMemMapEntries[entry].InternalReadFastFunction; } entry++; } // "Real" start_addr = 0x8000; end_addr = 0x8000 + ((ram_size>>16)-1); for (i = (start_addr>>2); i <= (end_addr>>2); i++) { gInternalReadFastTable[i] = InternalRead_8Mb_8000_807F; } // Shadow start_addr = 0xA000; end_addr = 0xA000 + ((ram_size>>16)-1); for (i = (start_addr>>2); i <= (end_addr>>2); i++) { gInternalReadFastTable[i] = InternalRead_4Mb_8000_803F; } }