What's new

Templates And Emulating Mirrored Memory

zenogais

New member
Ok, this is a little code snippet of something I came up with a little while ago while I was developing NeoPSX. The Playstation has mirrored memory that all ends up at the same location, and I wanted a simple way to do mirroring that didn't require macros or cutting/pasting lots of code(as changes can't be made very easily). Here's what I came up with, it uses C++ templates:

Code:
//////////////////////////////////////////////////////////////////////////////////////
// Define an address range pair
/////////////////////////////////////////////////////////////////////////////////////
template<uint32_t LowAddr, uint32_t HighAddr>
struct AddressRange
{
public:
	static bool InRange(uint32_t Address)
	{
		return (Address >= LowAddr && Address <= HighAddr);
	}
};

//////////////////////////////////////////////////////////////////////////////////////
// Define an address range group
/////////////////////////////////////////////////////////////////////////////////////
template<class Range1, class Range2>
struct AddressRangeGroup
{
public:
	static bool InRange(uint32_t Address)
	{
		return (Range1::InRange(Address) || Range2::InRange(Address));
	}
};

//////////////////////////////////////////////////////////////////////////////////////
// Address range helper macros
/////////////////////////////////////////////////////////////////////////////////////
#define Group1(A1,A2)             AddressRange<A1,A2>
#define Group2(A1,A2,A3,A4)       AddressRangeGroup<Group1(A1,A2), Group1(A3,A4) >
#define Group3(A1,A2,A3,A4,A5,A6) AddressRangeGroup<Group1(A2,A2), Group2(A3,A4,A5,A6) >

//////////////////////////////////////////////////////////////////////////////////////
// Define Playstation address ranges.
/////////////////////////////////////////////////////////////////////////////////////
typedef Group1(0x1F800000UL, 0x1F8003FFUL)                             SPAD;
typedef Group2(0xBFC00000UL, 0xBFC7FFFFUL, 0x1FC00000UL, 0x1FC7FFFFUL) ROM;
typedef Group3(0x00000000UL, 0x001FFFFFUL, 0x80000000UL, 0x801FFFFFUL, 
                                           0xA0000000UL, 0xA01FFFFFUL) RAM;

Now Group1 merely creates a group defined as an address range, meaning that the address range is composed of the space between two addresses. ROM is mirrored in two places, and RAM is mirrored in three. This is a simplistic example, but then all you have to do is something like this to check if the address is in the specified range:

Code:
if( SPAD::InRange( Address ) )
{
// Write to memory here.
}

Hope this helps someone, just thought I'd share a different way of handling memory ranges and mirroring.
 
Last edited:

Top