Merge pull request #2 from Alcaro/master

Create memory descriptor API
This commit is contained in:
Twinaphex 2014-06-05 18:47:59 +02:00
commit 573b198e6a
4 changed files with 292 additions and 33 deletions

View File

@ -320,8 +320,19 @@ void retro_cheat_set(unsigned index, bool enabled, const char *code)
S9xApplyCheats();
}
#define MAX_MAPS 32
static struct retro_memory_descriptor memorydesc[MAX_MAPS];
static unsigned memorydesc_c;
void S9xAppendMapping(struct retro_memory_descriptor * desc)
{
//do it backwards - snes9x defines the last one to win, while we define the first one to win
memcpy(&memorydesc[MAX_MAPS - (++memorydesc_c)], desc, sizeof(struct retro_memory_descriptor));
}
bool retro_load_game(const struct retro_game_info *game)
{
memorydesc_c = 0;
if(game->data == NULL && game->size == 0 && game->path != NULL)
rom_loaded = Memory.LoadROM(game->path);
else
@ -330,6 +341,9 @@ bool retro_load_game(const struct retro_game_info *game)
if (!rom_loaded && log_cb)
log_cb(RETRO_LOG_ERROR, "[libretro]: Rom loading failed...\n");
struct retro_memory_map map={ memorydesc+MAX_MAPS-memorydesc_c, memorydesc_c };
if (rom_loaded) environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &map);
return rom_loaded;
}
@ -339,6 +353,8 @@ void retro_unload_game(void)
bool retro_load_game_special(unsigned game_type,
const struct retro_game_info *info, size_t num_info) {
memorydesc_c = 0;
switch (game_type) {
case RETRO_GAME_TYPE_BSX:
@ -380,6 +396,9 @@ bool retro_load_game_special(unsigned game_type,
rom_loaded = false;
break;
}
struct retro_memory_map map={ memorydesc+MAX_MAPS-memorydesc_c, memorydesc_c };
if (rom_loaded) environ_cb(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &map);
return rom_loaded;
}
@ -688,6 +707,9 @@ void* retro_get_memory_data(unsigned type)
case RETRO_MEMORY_VIDEO_RAM:
data = Memory.VRAM;
break;
case RETRO_MEMORY_ROM:
data = Memory.ROM;
break;
default:
data = NULL;
break;
@ -719,6 +741,9 @@ size_t retro_get_memory_size(unsigned type)
case RETRO_MEMORY_VIDEO_RAM:
size = 64 * 1024;
break;
case RETRO_MEMORY_ROM:
size = Memory.CalculatedSize;
break;
default:
size = 0;
break;

View File

@ -180,6 +180,9 @@ extern "C" {
// Video ram lets a frontend peek into a game systems video RAM (VRAM).
#define RETRO_MEMORY_VIDEO_RAM 3
// ROM lets a frontend poke a game system's main program.
#define RETRO_MEMORY_ROM 4
// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD.
enum retro_key
{
@ -637,6 +640,111 @@ enum retro_mod
// The core must pass an array of const struct retro_controller_info which is terminated with
// a blanked out struct. Each element of the struct corresponds to an ascending port index to retro_set_controller_port_device().
// Even if special device types are set in the libretro core, libretro should only poll input based on the base input device types.
#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL)
// const struct retro_memory_map * --
// This environment call lets a libretro core tell the frontend about the memory maps this
// core emulates. This can be used to implement, for example, cheats in a core-agnostic way.
//
// Should only be used by emulators; it doesn't make much sense for anything else.
// It is recommended to expose all relevant pointers through retro_get_memory_* as well.
//
// Can be called from retro_init and retro_load_game.
//
#define RETRO_MEMDESC_CONST (1 << 0) // The frontend will never change this memory area once retro_load_game has returned.
#define RETRO_MEMDESC_BIGENDIAN (1 << 1) // The memory area contains big endian data. Default is little endian.
#define RETRO_MEMDESC_ALIGN_2 (1 << 16) // All memory access in this area is aligned to their own size, or 2, whichever is smaller.
#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) // All memory in this region is accessed at least 2 bytes at the time.
#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
struct retro_memory_descriptor {
uint64_t flags;
//Pointer to the start of the relevant ROM or RAM chip.
//It's strongly recommended to use 'offset' if possible, rather than doing math on the pointer.
//If the same byte is mapped my multiple descriptors, their descriptors must have the same pointer.
//If 'start' does not point to the first byte in the pointer, put the difference in 'offset' instead.
//May be NULL if there's nothing usable here (e.g. hardware registers and open bus). No flags should be set if the pointer is NULL.
//It's recommended to minimize the number of descriptors if possible, but not mandatory.
void * ptr;
size_t offset;
//This is the location in the emulated address space where the mapping starts.
size_t start;
//Which bits must be same as in 'start' for this mapping to apply.
//The first memory descriptor to claim a certain byte is the one that applies.
//A bit which is set in 'start' must also be set in this.
//Can be zero, in which case each byte is assumed mapped exactly once. In this case, 'len' must be a power of two.
size_t select;
//If this is nonzero, the set bits are assumed not connected to the memory chip's address pins.
size_t disconnect;
//This one tells the size of the current memory area.
//If, after start+disconnect are applied, the address is higher than this, the highest bit of the address is cleared.
//If the address is still too high, the next highest bit is cleared.
//Can be zero, in which case it's assumed to be infinite (as limited by 'select' and 'disconnect').
size_t len;
//To go from emulated address to physical address, the following order applies:
//Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'.
//The address space name must consist of only a-zA-Z0-9_-, should be as short as feasible (maximum length is 8 plus the NUL),
// and may not be any other address space plus one or more 0-9A-F at the end.
//However, multiple memory descriptors for the same address space is allowed, and the address
// space name can be empty. NULL is treated as empty.
//Address space names are case sensitive, but avoid lowercase if possible.
//The same pointer may exist in multiple address spaces.
//Examples:
// blank+blank - valid (multiple things may be mapped in the same namespace)
// 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace)
// 'A'+'B' - valid (neither is a prefix of each other)
// 'S'+blank - valid ('S' is not in 0-9A-F)
// 'a'+blank - valid ('a' is not in 0-9A-F)
// 'a'+'A' - valid (neither is a prefix of each other)
// 'AR'+blank - valid ('R' is not in 0-9A-F)
// 'ARB'+blank - valid (the B can't be part of the address either, because there is no namespace 'AR')
// blank+'B' - not valid, because it's ambigous which address space B1234 would refer to.
// The length can't be used for that purpose; the frontend may want to append arbitrary data to an address, without a separator.
const char * addrspace;
};
//The frontend may use the largest value of 'start'+'select' in a certain namespace to infer the size of the address space.
//If the address space is larger than that, a mapping with .ptr=NULL should be at the end of the array, with .select set to all ones for as long as the address space is big.
//Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags):
//SNES WRAM:
// .start=0x7E0000, .len=0x20000
//(Note that this must be mapped before the ROM in most cases; some of the ROM mappers try to claim $7E0000, or at least $7E8000.)
//SNES SPC700 RAM:
// .addrspace="S", .len=0x10000
//SNES WRAM mirrors:
// .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000
// .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000
//SNES WRAM mirrors, alternate equivalent descriptor:
// .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF
//(Various similar constructions can be created by combining parts of the above two.)
//SNES LoROM (512KB, mirrored a couple of times):
// .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024
// .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024
//SNES HiROM (4MB):
// .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024
// .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024
//SNES ExHiROM (8MB):
// .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024
// .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024
// .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024
// .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024
//Clarify the size of the address space:
// .ptr=NULL, .select=0xFFFFFF
//.len can be implied by .select in many of them, but was included for clarity.
struct retro_memory_map
{
const struct retro_memory_descriptor * descriptors;
unsigned num_descriptors;
};
struct retro_controller_description
{

View File

@ -201,6 +201,11 @@
#include "movie.h"
#include "display.h"
#ifdef __LIBRETRO__
#include "libretro.h"
void S9xAppendMapping(struct retro_memory_descriptor * desc);
#endif
#ifndef SET_UI_COLOR
#define SET_UI_COLOR(r, g, b) ;
#endif
@ -2527,6 +2532,9 @@ void CMemory::InitROM (void)
Map_Initialize();
CalculatedChecksum = 0;
// SRAM size
SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0;
if (HiROM)
{
if (Settings.BS)
@ -2657,9 +2665,6 @@ void CMemory::InitROM (void)
*p = 0;
}
// SRAM size
SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0;
// checksum
if (!isChecksumOK || ((uint32) CalculatedSize > (uint32) (((1 << (ROMSize - 7)) * 128) * 1024)))
{
@ -2758,7 +2763,7 @@ uint32 CMemory::map_mirror (uint32 size, uint32 pos)
return (mask + map_mirror(size - mask, pos - mask));
}
void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size)
void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, bool auto_export_map)
{
uint32 c, i, p, addr;
@ -2773,9 +2778,23 @@ void CMemory::map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 add
BlockIsRAM[p] = FALSE;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.flags=RETRO_MEMDESC_CONST;
desc.ptr=ROM;
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
desc.disconnect=0x8000;
desc.len=size;
S9xAppendMapping(&desc);
}
#endif
}
void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size)
void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, bool auto_export_map)
{
uint32 c, i, p, addr;
@ -2790,9 +2809,23 @@ void CMemory::map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 add
BlockIsRAM[p] = FALSE;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.flags=RETRO_MEMDESC_CONST;
desc.ptr=ROM;
desc.offset=map_mirror(size, addr_s);
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
desc.len=size - desc.offset;
S9xAppendMapping(&desc);
}
#endif
}
void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset)
void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset, bool auto_export_map)
{
uint32 c, i, p, addr;
@ -2807,9 +2840,24 @@ void CMemory::map_lorom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uin
BlockIsRAM[p] = FALSE;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.flags=RETRO_MEMDESC_CONST;
desc.ptr=ROM;
desc.offset=offset;
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
desc.disconnect=0x8000;
desc.len=size;
S9xAppendMapping(&desc);
}
#endif
}
void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset)
void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size, uint32 offset, bool auto_export_map)
{
uint32 c, i, p, addr;
@ -2824,9 +2872,22 @@ void CMemory::map_hirom_offset (uint32 bank_s, uint32 bank_e, uint32 addr_s, uin
BlockIsRAM[p] = FALSE;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.flags=RETRO_MEMDESC_CONST;
desc.ptr=ROM;
desc.offset=map_mirror(size, offset + addr_s);
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
desc.len=size;
S9xAppendMapping(&desc);
}
#endif
}
void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data)
void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data, bool auto_export_map)
{
uint32 c, i, p;
@ -2840,9 +2901,20 @@ void CMemory::map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 add
BlockIsRAM[p] = TRUE;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.ptr=data;
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
desc.disconnect=0xFF0000;
S9xAppendMapping(&desc);
}
#endif
}
void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type)
void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type, bool auto_export_map)
{
uint32 c, i, p;
bool8 isROM, isRAM;
@ -2860,6 +2932,41 @@ void CMemory::map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 add
BlockIsRAM[p] = isRAM;
}
}
#ifdef __LIBRETRO__
if (auto_export_map)
{
struct retro_memory_descriptor desc = {0};
desc.start=bank_s<<16 | addr_s;
desc.select=(bank_s<<16 | addr_s) ^ (bank_e<<16 | addr_e) ^ 0xFFFFFF;
if (type==MAP_LOROM_SRAM || type==MAP_SA1RAM)
{
desc.ptr=Memory.SRAM;
desc.disconnect=0x8000;
desc.len=Memory.SRAMMask+1;
S9xAppendMapping(&desc);
}
if (type==MAP_LOROM_SRAM_B)
{
desc.ptr=Multi.sramB;
desc.disconnect=0x8000;
desc.len=Multi.sramMaskB+1;
S9xAppendMapping(&desc);
}
if (type==MAP_HIROM_SRAM || type==MAP_RONLY_SRAM)
{
desc.ptr=Memory.SRAM;
desc.disconnect=0x00E000;
desc.len=Memory.SRAMMask+1;
S9xAppendMapping(&desc);
}
if (type==MAP_BWRAM)
{
desc.ptr=Memory.SRAM;//this one varies, but we can't use variable maps in this system.
desc.disconnect=0xFFE000;//It's the same as SRAM, anyways. Let's point it to there and let the front ignore it.
S9xAppendMapping(&desc);
}
}
#endif
}
void CMemory::map_System (void)
@ -2876,20 +2983,20 @@ void CMemory::map_System (void)
void CMemory::map_WRAM (void)
{
// will overwrite others
map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM);
map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000);
map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM);
}
void CMemory::map_LoROMSRAM (void)
{
map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
}
void CMemory::map_HiROMSRAM (void)
{
map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
}
void CMemory::map_DSP (void)
@ -3020,8 +3127,8 @@ void CMemory::Map_NoMAD1LoROMMap (void)
map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_WRAM();
@ -3072,10 +3179,10 @@ void CMemory::Map_SRAM512KLoROMMap (void)
map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000);
map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000);
map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000);
map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000);
map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000);
map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
map_WRAM();
@ -3096,14 +3203,14 @@ void CMemory::Map_SufamiTurboLoROMMap (void)
if (Multi.sramSizeA)
{
map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
}
if (Multi.sramSizeB)
{
map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
}
map_WRAM();
@ -3127,8 +3234,8 @@ void CMemory::Map_SufamiTurboPseudoLoROMMap (void)
// I don't care :P
map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000);
map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000);
map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000, false);
map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000, false);
map_WRAM();
@ -3156,8 +3263,8 @@ void CMemory::Map_SuperFXLoROMMap (void)
map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000);
map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000);
map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000);
map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
map_WRAM();
@ -3210,13 +3317,23 @@ void CMemory::Map_SA1LoROMMap (void)
map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM);
map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
for (int c = 0x40; c < 0x80; c++)
map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000);
map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000, false);
#ifdef __LIBRETRO__
struct retro_memory_descriptor desc = {0};
desc.ptr=SRAM;
desc.start=0x400000;
desc.select=0xC00000;
desc.disconnect=0xFE0000;
desc.len=0x20000;
S9xAppendMapping(&desc);
#endif
map_WRAM();
@ -3252,13 +3369,22 @@ void CMemory::Map_GNEXTSA1LoROMMap (void)
map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM);
map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
for (int c = 0x40; c < 0x80; c++)
map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000);
map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000, false);
#ifdef __LIBRETRO__
struct retro_memory_descriptor desc = {0};
desc.ptr=SRAM;
desc.start=0x400000;
desc.select=0xC00000;
desc.disconnect=0xFE0000;
S9xAppendMapping(&desc);
#endif
// FIXME: untested!
map_hirom_offset(0x70, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);

View File

@ -295,12 +295,12 @@ struct CMemory
void InitROM (void);
uint32 map_mirror (uint32, uint32);
void map_lorom (uint32, uint32, uint32, uint32, uint32);
void map_hirom (uint32, uint32, uint32, uint32, uint32);
void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32);
void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32);
void map_space (uint32, uint32, uint32, uint32, uint8 *);
void map_index (uint32, uint32, uint32, uint32, int, int);
void map_lorom (uint32, uint32, uint32, uint32, uint32, bool = true);
void map_hirom (uint32, uint32, uint32, uint32, uint32, bool = true);
void map_lorom_offset (uint32, uint32, uint32, uint32, uint32, uint32, bool = true);
void map_hirom_offset (uint32, uint32, uint32, uint32, uint32, uint32, bool = true);
void map_space (uint32, uint32, uint32, uint32, uint8 *, bool = true);
void map_index (uint32, uint32, uint32, uint32, int, int, bool = true);
void map_System (void);
void map_WRAM (void);
void map_LoROMSRAM (void);