o add bsnes

This commit is contained in:
optixx
2009-04-08 21:29:36 +02:00
parent bcb4a055e9
commit 27b58a09f2
413 changed files with 71887 additions and 0 deletions

112
bsnes/memory/memory.cpp Executable file
View File

@@ -0,0 +1,112 @@
#include <../base.hpp>
#define MEMORY_CPP
namespace memory {
MMIOAccess mmio;
StaticRAM wram(128 * 1024);
StaticRAM apuram(64 * 1024);
StaticRAM vram(64 * 1024);
StaticRAM oam(544);
StaticRAM cgram(512);
UnmappedMemory memory_unmapped;
UnmappedMMIO mmio_unmapped;
};
uint8 UnmappedMemory::read(unsigned) { return cpu.regs.mdr; }
void UnmappedMemory::write(unsigned, uint8) {}
uint8 UnmappedMMIO::mmio_read(unsigned) { return cpu.regs.mdr; }
void UnmappedMMIO::mmio_write(unsigned, uint8) {}
void MMIOAccess::map(unsigned addr, MMIO &access) {
//MMIO: $[00-3f]:[2000-5fff]
mmio[(addr - 0x2000) & 0x3fff] = &access;
}
MMIO* MMIOAccess::get(unsigned addr) {
return mmio[(addr - 0x2000) & 0x3fff];
}
uint8 MMIOAccess::read(unsigned addr) {
return mmio[(addr - 0x2000) & 0x3fff]->mmio_read(addr);
}
void MMIOAccess::write(unsigned addr, uint8 data) {
mmio[(addr - 0x2000) & 0x3fff]->mmio_write(addr, data);
}
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;
}
void Bus::map(unsigned addr, Memory &access, unsigned offset) {
page[addr >> 8].access = &access;
page[addr >> 8].offset = offset - addr;
}
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;
}
}

135
bsnes/memory/memory.hpp Executable file
View File

@@ -0,0 +1,135 @@
struct Memory {
virtual unsigned size() const { return 0; }
virtual uint8 read(unsigned addr) = 0;
virtual void write(unsigned addr, uint8 data) = 0;
};
struct MMIO {
virtual uint8 mmio_read(unsigned addr) = 0;
virtual void mmio_write(unsigned addr, uint8 data) = 0;
};
struct UnmappedMemory : Memory {
uint8 read(unsigned);
void write(unsigned, uint8);
};
struct UnmappedMMIO : MMIO {
uint8 mmio_read(unsigned);
void mmio_write(unsigned, uint8);
};
struct StaticRAM : Memory {
uint8* handle() { return data; }
unsigned size() const { return datasize; }
inline uint8 read(unsigned addr) { return data[addr]; }
inline void write(unsigned addr, uint8 n) { data[addr] = n; }
inline uint8& operator[](unsigned addr) { return data[addr]; }
inline const uint8& operator[](unsigned addr) const { return data[addr]; }
StaticRAM(unsigned n) : datasize(n) { data = new uint8[datasize]; }
~StaticRAM() { delete[] data; }
private:
uint8 *data;
unsigned datasize;
};
struct MappedRAM : Memory {
void map(uint8 *source, unsigned length) { data = source; datasize = length > 0 ? length : -1U; }
void write_protect(bool status) { write_protection = status; }
uint8* handle() { return data; }
unsigned size() const { return datasize; }
inline uint8 read(unsigned addr) { return data[addr]; }
inline void write(unsigned addr, uint8 n) { if(!write_protection) data[addr] = n; }
inline const uint8& operator[](unsigned addr) const { return data[addr]; }
MappedRAM() : data(0), datasize(0), write_protection(false) {}
private:
uint8 *data;
unsigned datasize;
bool write_protection;
};
struct MMIOAccess : Memory {
void map(unsigned addr, MMIO &access);
MMIO* get(unsigned addr);
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
private:
MMIO *mmio[0x4000];
};
class Bus {
public:
unsigned mirror(unsigned addr, unsigned size);
void map(unsigned addr, Memory &access, unsigned offset);
enum MapMode { MapDirect, MapLinear, MapShadow };
void map(MapMode mode,
uint8 bank_lo, uint8 bank_hi,
uint16 addr_lo, uint16 addr_hi,
Memory &access, unsigned offset = 0, unsigned size = 0);
alwaysinline uint8 read(unsigned addr) {
#if defined(CHEAT_SYSTEM)
if(cheat.active() && cheat.exists(addr)) {
uint8 r;
if(cheat.read(addr, r)) return r;
}
#endif
Page &p = page[addr >> 8];
return p.access->read(p.offset + addr);
}
alwaysinline void write(unsigned addr, uint8 data) {
Page &p = page[addr >> 8];
return p.access->write(p.offset + addr, data);
}
void set_speed(bool fast) {
fastSpeed = fast ? 6 : 8;
}
alwaysinline unsigned speed(unsigned addr) const {
if(addr & 0x408000) {
if(addr & 0x800000) return fastSpeed;
return 8;
}
if((addr + 0x6000) & 0x4000) return 8;
if((addr - 0x4000) & 0x7e00) return 6;
return 12;
}
virtual bool load_cart() = 0;
virtual void unload_cart() = 0;
virtual void power() = 0;
virtual void reset() = 0;
Bus() {}
virtual ~Bus() {}
protected:
struct Page {
Memory *access;
unsigned offset;
} page[65536];
unsigned fastSpeed;
};
namespace memory {
extern MMIOAccess mmio; //S-CPU, S-PPU
extern StaticRAM wram; //S-CPU
extern StaticRAM apuram; //S-SMP, S-DSP
extern StaticRAM vram; //S-PPU
extern StaticRAM oam; //S-PPU
extern StaticRAM cgram; //S-PPU
extern UnmappedMemory memory_unmapped;
extern UnmappedMMIO mmio_unmapped;
};

View File

@@ -0,0 +1,54 @@
#ifdef SMEMORY_CPP
void sBus::map_cx4() {
map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, cx4);
map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, cx4);
}
void sBus::map_dsp1() {
switch(cartridge.dsp1_mapper()) {
case Cartridge::DSP1LoROM1MB: {
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp1);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp1);
} break;
case Cartridge::DSP1LoROM2MB: {
map(MapDirect, 0x60, 0x6f, 0x0000, 0x7fff, dsp1);
map(MapDirect, 0xe0, 0xef, 0x0000, 0x7fff, dsp1);
} break;
case Cartridge::DSP1HiROM: {
map(MapDirect, 0x00, 0x1f, 0x6000, 0x7fff, dsp1);
map(MapDirect, 0x80, 0x9f, 0x6000, 0x7fff, dsp1);
} break;
}
}
void sBus::map_dsp2() {
map(MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, dsp2);
map(MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, dsp2);
map(MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, dsp2);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xbfff, dsp2);
}
void sBus::map_dsp3() {
map(MapDirect, 0x20, 0x3f, 0x8000, 0xffff, dsp3);
map(MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, dsp3);
}
void sBus::map_dsp4() {
map(MapDirect, 0x30, 0x3f, 0x8000, 0xffff, dsp4);
map(MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, dsp4);
}
void sBus::map_obc1() {
map(MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, obc1);
map(MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, obc1);
}
void sBus::map_st010() {
map(MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, st010);
map(MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, st010);
}
#endif

View File

@@ -0,0 +1,104 @@
#ifdef SMEMORY_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: {
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::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 SRAM
//otherwise, default to safer, larger SRAM 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);
}
#endif

View File

@@ -0,0 +1,21 @@
#ifdef SMEMORY_CPP
void sBus::map_reset() {
for(uint32_t i = 0x0000; i <= 0xffff; i++)
map(i << 8, memory::memory_unmapped, 0);
for(uint16_t i = 0x2000; i <= 0x5fff; i++)
memory::mmio.map(i, memory::mmio_unmapped);
}
void sBus::map_system() {
map(MapDirect, 0x00, 0x3f, 0x2000, 0x5fff, memory::mmio);
map(MapDirect, 0x80, 0xbf, 0x2000, 0x5fff, memory::mmio);
map(MapLinear, 0x00, 0x3f, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
map(MapLinear, 0x80, 0xbf, 0x0000, 0x1fff, memory::wram, 0x000000, 0x002000);
map(MapLinear, 0x7e, 0x7f, 0x0000, 0xffff, memory::wram);
}
#endif

View File

@@ -0,0 +1,45 @@
#include <../base.hpp>
#include <../chip/chip.hpp>
#include <../cart/cart.hpp>
#define SMEMORY_CPP
#include "mapper/system.cpp"
#include "mapper/generic.cpp"
#include "mapper/chip.cpp"
void sBus::power() {
for(unsigned i = 0x2000; i <= 0x5fff; i++) memory::mmio.map(i, memory::mmio_unmapped);
for(unsigned i = 0; i < memory::wram.size(); i++) memory::wram[i] = snes.config.cpu.wram_init_value;
reset();
}
void sBus::reset() {
set_speed(false);
}
bool sBus::load_cart() {
if(cartridge.loaded() == true) return false;
map_reset();
map_generic();
map_system();
if(cartridge.has_cx4()) map_cx4();
if(cartridge.has_dsp1()) map_dsp1();
if(cartridge.has_dsp2()) map_dsp2();
if(cartridge.has_dsp3()) map_dsp3();
if(cartridge.has_dsp4()) map_dsp4();
if(cartridge.has_obc1()) map_obc1();
if(cartridge.has_st010()) map_st010();
return true;
}
void sBus::unload_cart() {
}
sBus::sBus() {
}
sBus::~sBus() {
}

View File

@@ -0,0 +1,25 @@
class sBus : public Bus {
public:
bool load_cart();
void unload_cart();
void power();
void reset();
sBus();
~sBus();
private:
void map_reset();
void map_system();
void map_generic();
void map_generic_sram();
void map_cx4();
void map_dsp1();
void map_dsp2();
void map_dsp3();
void map_dsp4();
void map_obc1();
void map_st010();
};