Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emulate memory-mapping of a game console, access different locations based on the address provided

I am implementing an emulator for an old game console, mostly for learning purposes.

This console maps roms, and a lot of other things, to regions within its address space. Certain locations are also mirrored so that multiple addresses can correspond to the same physical location. I would like to emulate this, but I am not sure what would be a good approach to do so (and also have no idea what this process is called, hence this somewhat generic question).

One thing that does work is a simple, unordered map. Have it contain absolute addresses and the corresponding pointers to my data structures. This way, I can easily map everything I need into the system's address space. The problem with this approach is that, it's obviously a memory hog. Even with small roms, I end up with close to ten million entries, thanks to the aforementioned mirroring. Surely, this can't be the rigth thing to do?

Any help is much appreciated.

Edit:

To provide some details as to how exactly I am doing this:

The system in question is, of course, the SNES. Using this wiki as my primary resource, I implemeted what I mentioned above as follows:

  • Create a std::unordered_map<uint32,uint8_t*> mMemoryMap;
  • Check whether the rom is LoRom or HiRom
  • For each byte in the rom
    • Calculate the address where it should be mapped and emplace both the address and a pointer to said byte in the map
    • If the section needs to be mirrored somewhere else, repeat the above
  • This will be applied to anything else I need to make available, such as video- or system-memory

If I now want to access anything within the address space, I can simply use the address the system would use internally.

like image 701
ZeroSum Avatar asked Oct 31 '22 11:10

ZeroSum


2 Answers

I'm assuming that for contiguous addresses the physical locations are also contiguous, within certain blocks of memory or "chunks". That is, if the address 0x0000 maps to 0xFF00, then 0x0004 maps to 0xFF04.

enter image description here

If they work like that, then you can make a list that contains the information of those chunks. Say:

struct Chunk
{
   int addressStart, memoryStart, size;
}

The chunks may be ordered by the addressStart, so you can find out the correct chunk you would need for any address. This requires you to iterate the list, but if you have only a few chunks this may be acceptable.

like image 84
Andres Urquijo Avatar answered Nov 13 '22 18:11

Andres Urquijo


Rather than use simple maps (which even with ranges can grow to large sizes) you can instead use a more intelligent map.

For instance if the console maps 0x10XXXX through 0x1FXXXX all to the same 0x20XXXX you can design a structure which holds that repetition (start 0x100000 end 0x1FFFFF repeat 0x010000 although you may want to use a bitmask rather than repeat).

like image 45
Guvante Avatar answered Nov 13 '22 18:11

Guvante