Author Topic: SNES memory bus mapping  (Read 13469 times)

0 Members and 1 Guest are viewing this topic.

Offline Conle

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2203
SNES memory bus mapping
« on: February 17, 2010, 01:42:48 AM »
Edit : Dr.Neo , how about a SNES Development section?

So it seems that the SNES Myth supports up to 128Mb roms  :
http://www.neoflash.com/forum/index.php/topic,5633.msg39390.html#msg39390
http://www.neoflash.com/forum/index.php/topic,5633.msg39396.html#msg39396

But unfortunately Dr.Neo couldn't find info on the IO mapping and they limited the rom size(that can be mapped) to 64Mb.

I did some quick research and i found all the mapping info for any rom in bsnes's source code.

Here is my findings :

Code: [Select]
 function map() args :
  MapMode mode,
  uint8  bank_lo, uint8  bank_hi,
  uint16 addr_lo, uint16 addr_hi,
  Memory &access, unsigned offset, unsigned size

Code: [Select]
//from bsnes - file : src/memory/smemory/generic.cpp
void sBus::map_generic() {
  switch(cartridge.mapper()) {
    case Cartridge::LoROM: {
      map(MapLinear, 0x00, 0x7f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x80, 0xff, 0x8000, 0xffff, memory::cartrom);
      map_generic_sram();
    } break;

    case Cartridge::HiROM: {
      map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
      map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
      map_generic_sram();
    } break;

    case Cartridge::ExLoROM: { /* >64Mb roms <-- This is also for the infamous 96Mbit ROM Star ocean SDD1 Uncompressed version*/
      map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom);
      map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
      map_generic_sram();
    } break;

    case Cartridge::ExHiROM: {
      map(MapShadow, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x400000);
      map(MapLinear, 0x40, 0x7f, 0x0000, 0xffff, memory::cartrom, 0x400000);
      map(MapShadow, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x000000);
      map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom, 0x000000);
      map_generic_sram();
    } break;

    case Cartridge::SuperFXROM: {
      //mapped via SuperFXBus::init();
    } break;

    case Cartridge::SA1ROM: {
      //mapped via SA1Bus::init();
    } break;

    case Cartridge::SPC7110ROM: {
      map(MapDirect, 0x00, 0x00, 0x6000, 0x7fff, spc7110);          //save RAM w/custom logic
      map(MapShadow, 0x00, 0x0f, 0x8000, 0xffff, memory::cartrom);  //program ROM
      map(MapDirect, 0x30, 0x30, 0x6000, 0x7fff, spc7110);          //save RAM w/custom logic
      map(MapDirect, 0x50, 0x50, 0x0000, 0xffff, spc7110);          //decompression MMIO port
      map(MapShadow, 0x80, 0x8f, 0x8000, 0xffff, memory::cartrom);  //program ROM
      map(MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, memory::cartrom);  //program ROM
      map(MapDirect, 0xd0, 0xff, 0x0000, 0xffff, spc7110);          //MMC-controlled data ROM
    } break;

    case Cartridge::BSXROM: {
      //full map is dynamically mapped by:
      //src/chip/bsx/bsx_cart.cpp : BSXCart::update_memory_map();
      map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
    } break;

    case Cartridge::BSCLoROM: {
      map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
      map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
      map(MapLinear, 0x70, 0x7f, 0x0000, 0x7fff, memory::cartram, 0x000000);
      map(MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
      map(MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x100000);
      map(MapLinear, 0xc0, 0xef, 0x0000, 0xffff, bsxflash);
      map(MapLinear, 0xf0, 0xff, 0x0000, 0x7fff, memory::cartram, 0x000000);
    } break;

    case Cartridge::BSCHiROM: {
      map(MapShadow, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
      map(MapShadow, 0x20, 0x3f, 0x8000, 0xffff, bsxflash);
      map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::cartrom);
      map(MapLinear, 0x60, 0x7f, 0x0000, 0xffff, bsxflash);
      map(MapShadow, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);
      map(MapShadow, 0xa0, 0xbf, 0x8000, 0xffff, bsxflash);
      map(MapLinear, 0xc0, 0xdf, 0x0000, 0xffff, memory::cartrom);
      map(MapLinear, 0xe0, 0xff, 0x0000, 0xffff, bsxflash);
    } break;

    case Cartridge::STROM: {
      map(MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::stArom);
      map(MapLinear, 0x40, 0x5f, 0x8000, 0xffff, memory::stBrom);
      map(MapLinear, 0x60, 0x63, 0x8000, 0xffff, memory::stAram);
      map(MapLinear, 0x70, 0x73, 0x8000, 0xffff, memory::stBram);
      map(MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
      map(MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::stArom);
      map(MapLinear, 0xc0, 0xdf, 0x8000, 0xffff, memory::stBrom);
      map(MapLinear, 0xe0, 0xe3, 0x8000, 0xffff, memory::stAram);
      map(MapLinear, 0xf0, 0xf3, 0x8000, 0xffff, memory::stBram);
    } break;
  }
}

void sBus::map_generic_sram() {
  if(memory::cartram.size() == 0 || memory::cartram.size() == -1U) { return; }

  map(MapLinear, 0x20, 0x3f, 0x6000, 0x7fff, memory::cartram);
  map(MapLinear, 0xa0, 0xbf, 0x6000, 0x7fff, memory::cartram);

  //research shows only games with very large ROM/RAM sizes require MAD-1 memory mapping of RAM
  //otherwise, default to safer, larger RAM address window
  uint16 addr_hi = (memory::cartrom.size() > 0x200000 || memory::cartram.size() > 32 * 1024) ? 0x7fff : 0xffff;
  map(MapLinear, 0x70, 0x7f, 0x0000, addr_hi, memory::cartram);
  if(cartridge.mapper() != Cartridge::LoROM) return;
  map(MapLinear, 0xf0, 0xff, 0x0000, addr_hi, memory::cartram);
}

SuperFX:
Code: [Select]
 map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);

  map(MapLinear, 0x00, 0x3f, 0x0000, 0x7fff, memory::gsurom);
  map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::gsurom);
  map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::gsurom);
  map(MapLinear, 0x60, 0x7f, 0x0000, 0xffff, memory::gsuram);

  bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::fxram, 0x0000, 0x2000);
  bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::fxrom);
  bus.map(MapLinear, 0x40, 0x5f, 0x0000, 0xffff, memory::fxrom);
  bus.map(MapLinear, 0x60, 0x7d, 0x0000, 0xffff, memory::fxram);
  bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::fxram, 0x0000, 0x2000);
  bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::fxrom);
  bus.map(MapLinear, 0xc0, 0xdf, 0x0000, 0xffff, memory::fxrom);
  bus.map(MapLinear, 0xe0, 0xff, 0x0000, 0xffff, memory::fxram);

BSX:
Code: [Select]
void BSXCart::update_memory_map() {
  Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)memory::bsxpram;

  if((regs.r[0x02] & 0x80) == 0x00) {
    //LoROM mapping
    bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
    bus.map(Bus::MapLinear, 0x80, 0xff, 0x8000, 0xffff, cart);
  } else {
    //HiROM mapping
    bus.map(Bus::MapShadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
    bus.map(Bus::MapLinear, 0x40, 0x7d, 0x0000, 0xffff, cart);
    bus.map(Bus::MapShadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
    bus.map(Bus::MapLinear, 0xc0, 0xff, 0x0000, 0xffff, cart);
  }

  if(regs.r[0x03] & 0x80) {
    bus.map(Bus::MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
  //bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
  }

  if((regs.r[0x05] & 0x80) == 0x00) {
    bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
  }

  if((regs.r[0x06] & 0x80) == 0x00) {
    bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
  }

  if(regs.r[0x07] & 0x80) {
    bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
  }

  if(regs.r[0x08] & 0x80) {
    bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
  }

  bus.map(Bus::MapShadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
  bus.map(Bus::MapLinear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
}

SA1:
Code: [Select]
void SA1Bus::init() {
  map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
  for(unsigned i = 0x2200; i <= 0x23ff; i++) memory::mmio.map(i, sa1);

  map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::sa1iram);
  map(MapDirect, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
  map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::sa1iram);
  map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram);
  map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
  map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::sa1bwram);
  map(MapLinear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
  map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::sa1iram);
  map(MapDirect, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
  map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::sa1iram);
  map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram);
  map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
  map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);

  bus.map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::cpuiram);
  bus.map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram);
  bus.map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
  bus.map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cc1bwram);
  bus.map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::cpuiram);
  bus.map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram);
  bus.map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
  bus.map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);

  memory::vectorsp.sync();
}


Code: [Select]
//bus map - in file /src/memory/memory.cpp

void Bus::map(
  MapMode mode,
  uint8  bank_lo, uint8  bank_hi,
  uint16 addr_lo, uint16 addr_hi,
  Memory &access, unsigned offset, unsigned size
) {
  assert(bank_lo <= bank_hi);
  assert(addr_lo <= addr_hi);
  if(access.size() == -1U) return;

  uint8 page_lo = addr_lo >> 8;
  uint8 page_hi = addr_hi >> 8;
  unsigned index = 0;

  switch(mode) {
    case MapDirect: {
      for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
        for(unsigned page = page_lo; page <= page_hi; page++) {
          map((bank << 16) + (page << 8), access, (bank << 16) + (page << 8));
        }
      }
    } break;

    case MapLinear: {
      for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
        for(unsigned page = page_lo; page <= page_hi; page++) {
          map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
          index += 256;
          if(size) index %= size;
        }
      }
    } break;

    case MapShadow: {
      for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
        index += page_lo * 256;
        if(size) index %= size;

        for(unsigned page = page_lo; page <= page_hi; page++) {
          map((bank << 16) + (page << 8), access, mirror(offset + index, access.size()));
          index += 256;
          if(size) index %= size;
        }

        index += (255 - page_hi) * 256;
        if(size) index %= size;
      }
    } break;
  }
}

unsigned Bus::mirror(unsigned addr, unsigned size) {
  unsigned base = 0;
  if(size) {
    unsigned mask = 1 << 23;
    while(addr >= size) {
      while(!(addr & mask)) mask >>= 1;
      addr -= mask;
      if(size > mask) {
        size -= mask;
        base += mask;
      }
      mask >>= 1;
    }
    base += addr;
  }
  return base;
}


« Last Edit: February 17, 2010, 02:07:27 AM by Conle »

Offline the|Gamer

  • Jr. Member
  • **
  • Posts: 67
Re: SNES memory bus mapping
« Reply #1 on: February 17, 2010, 03:30:19 AM »
Hi,
BS-X Carts would be nice!
Is there allready support?
Dr.Neo hope you implement what Conle just showed you ;)

Offline ~tak

  • Newbie
  • *
  • Posts: 46
Re: SNES memory bus mapping
« Reply #2 on: February 17, 2010, 04:24:40 AM »
Hi,
BS-X Carts would be nice!
Is there allready support?
Dr.Neo hope you implement what Conle just showed you ;)

BS-X games without need ot the extra hardware (satellaview) can be used already by minor BS-X ROM header modification

Offline the|Gamer

  • Jr. Member
  • **
  • Posts: 67
Re: SNES memory bus mapping
« Reply #3 on: February 17, 2010, 04:56:27 AM »
Hi,
ist there a Tool das does that or a Tutorial for doing this with a Hex Editor?

Offline ronaldo_76

  • Full Member
  • ***
  • Posts: 196
Re: SNES memory bus mapping
« Reply #4 on: February 17, 2010, 05:17:47 AM »
Hmmmm,

Star Ocean, playable in the Future?  :-*

 ~sm-42.gif~

I hope so...

Offline stefan_iro

  • Full Member
  • ***
  • Posts: 218
  • It´s a me, Mario
Re: SNES memory bus mapping
« Reply #5 on: February 17, 2010, 05:24:19 AM »
Dr.Neo , how about a SNES Development section?

YES, I think there should be a development section like the one for Mega Drive and Nintendo 64!  ::sm-22.gif::
-----------------------------------
8bit & 16bit
the golden age of videogames

Offline King Of Chaos

  • Full Member
  • ***
  • Posts: 117
Re: SNES memory bus mapping
« Reply #6 on: February 17, 2010, 05:54:57 AM »
Star Ocean? Either the 96Mbit decompressed version is supported or the S-DD1 is supported, whichever. There should be S-DD1 and SPC7110 support within bsnes as well, so that could help.
« Last Edit: February 17, 2010, 06:01:00 AM by King Of Chaos »

Offline Conle

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2203
Re: SNES memory bus mapping
« Reply #7 on: February 17, 2010, 02:02:08 PM »
There should be S-DD1 and SPC7110 support within bsnes as well, so that could help.

I have posted the mappings for SPC7110 already.Will find sdd1 later today  8)

Offline King Of Chaos

  • Full Member
  • ***
  • Posts: 117
Re: SNES memory bus mapping
« Reply #8 on: February 17, 2010, 02:04:55 PM »
Whoops, I see that. =P What about DSP-2, DSP-3 and DSP-4?

EDIT: Byuu posted new SPC7110 mappings here for the upcoming Far East Of Eden Zero translation. Also, this may be useful as well.
« Last Edit: February 17, 2010, 02:11:57 PM by King Of Chaos »

Offline Conle

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2203
Re: SNES memory bus mapping
« Reply #9 on: February 17, 2010, 02:12:22 PM »
Whoops, I see that. =P What about DSP-2, DSP-3 and DSP-4?

Yes i will post them too  ~sm-37.gif~

Offline King Of Chaos

  • Full Member
  • ***
  • Posts: 117
Re: SNES memory bus mapping
« Reply #10 on: February 17, 2010, 02:14:12 PM »
Excellent. The two links I posted in my edit above may be helpful too.

Offline Conle

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2203
Re: SNES memory bus mapping
« Reply #11 on: February 18, 2010, 04:58:41 PM »
I have bad news & good news...

The bad news:
Dr.Neo told me that SNES/SFC Myth has 64Mb PSRAM(like MD Myth).
So in order to support up to 96Mb roms we need a special build with +32Mb PSRAM.

 :-\

The good news:
Its the hardware itself.We have good chances to get chip emulator running on the fpga core.That is , if someone can make it possible.

 ~sm-37.gif~

Offline ~tak

  • Newbie
  • *
  • Posts: 46
Re: SNES memory bus mapping
« Reply #12 on: February 18, 2010, 11:33:59 PM »

The bad news:
Dr.Neo told me that SNES/SFC Myth has 64Mb PSRAM(like MD Myth).
So in order to support up to 96Mb roms we need a special build with +32Mb PSRAM.

 :-\

exactly what I've written down on another post somewhere; it's not a software limitation, it's the HW : - (


anyway, at least the other good news makes me quite happy to hear.

thanks for followup, mate

Offline King Of Chaos

  • Full Member
  • ***
  • Posts: 117
Re: SNES memory bus mapping
« Reply #13 on: February 19, 2010, 03:58:22 AM »
Probably better to just support the S-DD1 then.

Quote
Its the hardware itself.We have good chances to get chip emulator running on the fpga core.That is , if someone can make it possible.

I'm not sure if anyone would want to undertake that one - it sounds like a LOT of work.  =\

Offline mic_

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 632
Re: SNES memory bus mapping
« Reply #14 on: February 19, 2010, 06:12:58 AM »
Quote
Quote
Its the hardware itself.We have good chances to get chip emulator running on the fpga core.That is , if someone can make it possible.

I'm not sure if anyone would want to undertake that one - it sounds like a LOT of work.  =\

Something like the DSP2 would probably be possible for someone who's good with VHDL, if there's enough room on the FPGA. But to expect SuperFX or SA-1 emulation - even if there was room for it on the FPGA - is unrealistic. What we need for extra chip support is for the "boot cart" solution to work, so hopefully there'll be some improvements in future software versions.