Update to bsnes v061 release.

Please keep in mind that bsnes v060 remains the current stable release. v061 has been released as a work-in-progress build. As such, it is only available at Google Code.
I am releasing this WIP to allow the public to test out and comment on the new XML mapping system, as well as the integration of mightymo's cheat code database into the cheat editor. I would greatly appreciate feedback on these two on the forums.
There are some important issues with this release. The biggest is the move to C++0x. This requires GCC 4.4.0 or newer to compile, thus it is not currently possible to build this on OS X using Xcode. Nor would it be possible on certain BSDs or older distros. If you have an older compiler, please stick with v060, or use a binary release where available.
Another issue is that TDM/GCC 4.4.1 for Windows crashes with an internal compiler error when attempting to generate a profile for the DSP-1 module. This is a bug in the compiler, and not in the code itself. The workaround is to simply omit profile-guided optimization for this one object.
Lastly, there's also a known bug in the memory mapping. If you load an SA-1 game, SuperFX games will not load properly afterward unless you restart the emulator. I'm looking into the cause now, but it didn't seem serious enough to hold up a WIP release.
So, yes. If you want a good gaming experience that's been fully tested and stable, please stick with v060. If you want to see some bleeding edge features, I'd appreciate feedback on v061. Thanks for reading this.
Changelog:
    - added mightymo's cheat code database, access via "Find Cheat Codes" button on cheat editor window
    - added an option to temporarily disable all cheat codes quickly
    - debugger now properly uses S-SMP IPLROM when needed for disassembling and tracing
    - indexed indirect read opcodes in the S-CPU were testing for IRQs one cycle too early [someone42]
    - fix an off-by-one array iteration in S-PPU OAM rendering [PiCiJi]
    - added some implicit linked libraries to linker flags for Fedora [belegdol]
    - moved from C++98 to C++0x, resulting in substantial code cleanups and simplifications
    - C++0x: implemented foreach() concept for linear container iteration
    - C++0x: implemented concept system using SFINAE and type traits
    - C++0x: utilized auto keyword to increase source readability
    - C++0x: moved to strongly-typed enumerators
    - C++0x: rewrote va_list-based code to use type-safe variadic templates
    - C++0x: replaced noncopyable class with deleted default copy functions
    - C++0x: replaced custom static_assert template class with built-in version
    - C++0x: utilized rvalue references to implement move semantics into string, array, vector and serialization classes
    - C++0x: utilized std::initializer_list for { ... } initialization support to lstring, array and vector classes
This commit is contained in:
byuu 2010-03-07 02:17:46 +00:00
parent a295c86c05
commit 6c59a2f1b4
560 changed files with 54793 additions and 2937 deletions

BIN
QtCore4.dll Normal file

Binary file not shown.

BIN
QtGui4.dll Normal file

Binary file not shown.

BIN
bsnes-debugger.exe Normal file

Binary file not shown.

BIN
bsnes.exe Normal file

Binary file not shown.

View File

@ -8,8 +8,8 @@ include lib/nall/qt/Makefile
### compiler ###
################
c := $(compiler)
cpp := $(subst cc,++,$(compiler))
c := $(compiler) --std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
flags := -O3 -fomit-frame-pointer -Ilib
link :=
@ -25,7 +25,7 @@ link :=
################
ifeq ($(platform),x)
link += -s
link += -s -ldl -lX11 -lXext
ruby := video.glx video.xv video.qtraster video.sdl
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
@ -70,7 +70,8 @@ link += $(if $(findstring video.xv,$(ruby)),-lXv)
link += $(if $(findstring audio.alsa,$(ruby)),-lasound)
link += $(if $(findstring audio.ao,$(ruby)),-lao)
link += $(if $(findstring audio.directsound,$(ruby)),-ldsound)
link += $(if $(findstring audio.pulseaudio,$(ruby)),-lpulse-simple)
link += $(if $(findstring audio.pulseaudio,$(ruby)),-lpulse)
link += $(if $(findstring audio.pulseaudiosimple,$(ruby)),-lpulse-simple)
link += $(if $(findstring input.directinput,$(ruby)),-ldinput8 -ldxguid)
link += $(if $(findstring input.rawinput,$(ruby)),-ldinput8 -ldxguid)
@ -82,8 +83,8 @@ objects := libco ruby
objects += system cartridge cheat
objects += memory smemory cpu cpucore scpu smp smpcore ssmp dsp sdsp ppu bppu
objects += supergameboy superfx sa1
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 st011 st018
objects += msu
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st0010 st0011 st0018
objects += msu1
######################
### implicit rules ###
@ -183,10 +184,10 @@ obj/dsp2.o : chip/dsp2/dsp2.cpp chip/dsp2/*
obj/dsp3.o : chip/dsp3/dsp3.cpp chip/dsp3/*
obj/dsp4.o : chip/dsp4/dsp4.cpp chip/dsp4/*
obj/obc1.o : chip/obc1/obc1.cpp chip/obc1/*
obj/st010.o : chip/st010/st010.cpp chip/st010/*
obj/st011.o : chip/st011/st011.cpp chip/st011/*
obj/st018.o : chip/st018/st018.cpp chip/st018/*
obj/msu.o : chip/msu/msu.cpp chip/msu/*
obj/st0010.o : chip/st0010/st0010.cpp chip/st0010/*
obj/st0011.o : chip/st0011/st0011.cpp chip/st0011/*
obj/st0018.o : chip/st0018/st0018.cpp chip/st0018/*
obj/msu1.o : chip/msu1/msu1.cpp chip/msu1/*
###############
### targets ###

View File

@ -1,6 +1,6 @@
static const char bsnesVersion[] = "060";
static const char bsnesVersion[] = "061";
static const char bsnesTitle[] = "bsnes";
static const unsigned bsnesSerializerVersion = 4;
static const unsigned bsnesSerializerVersion = 5;
//S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
@ -22,6 +22,7 @@ static const unsigned bsnesSerializerVersion = 4;
#include <nall/dl.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/foreach.hpp>
#include <nall/function.hpp>
#include <nall/moduloarray.hpp>
#include <nall/platform.hpp>

View File

@ -5,8 +5,7 @@
#define CARTRIDGE_CPP
namespace SNES {
#include "header.cpp"
#include "gameboyheader.cpp"
#include "xml.cpp"
#include "serialization.cpp"
namespace memory {
@ -19,9 +18,32 @@ namespace memory {
Cartridge cartridge;
void Cartridge::load(Mode cartridge_mode) {
void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
spc7110_data_rom_offset = 0x100000;
supergameboy_version = SuperGameBoyVersion::Version1;
supergameboy_ram_size = 0;
supergameboy_rtc_size = 0;
has_bsx_slot = false;
has_superfx = false;
has_sa1 = false;
has_srtc = false;
has_sdd1 = false;
has_spc7110 = false;
has_spc7110rtc = false;
has_cx4 = false;
has_dsp1 = false;
has_dsp2 = false;
has_dsp3 = false;
has_dsp4 = false;
has_obc1 = false;
has_st0010 = false;
has_st0011 = false;
has_st0018 = false;
has_msu1 = false;
mode = cartridge_mode;
read_header(memory::cartrom.data(), memory::cartrom.size());
parse_xml(xml_list);
if(ram_size > 0) {
memory::cartram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
@ -31,23 +53,20 @@ void Cartridge::load(Mode cartridge_mode) {
memory::cartrtc.map(allocate<uint8_t>(20, 0xff), 20);
}
if(mode == ModeBsx) {
if(mode == Mode::Bsx) {
memory::bsxram.map (allocate<uint8_t>( 32 * 1024, 0xff), 32 * 1024);
memory::bsxpram.map(allocate<uint8_t>(512 * 1024, 0xff), 512 * 1024);
}
if(mode == ModeSufamiTurbo) {
if(mode == Mode::SufamiTurbo) {
if(memory::stArom.data()) memory::stAram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024);
if(memory::stBrom.data()) memory::stBram.map(allocate<uint8_t>(128 * 1024, 0xff), 128 * 1024);
}
if(mode == ModeSuperGameBoy) {
if(mode == Mode::SuperGameBoy) {
if(memory::gbrom.data()) {
unsigned ram_size = gameboy_ram_size();
unsigned rtc_size = gameboy_rtc_size();
if(ram_size) memory::gbram.map(allocate<uint8_t>(ram_size, 0xff), ram_size);
if(rtc_size) memory::gbrtc.map(allocate<uint8_t>(rtc_size, 0x00), rtc_size);
if(supergameboy_ram_size) memory::gbram.map(allocate<uint8_t>(supergameboy_ram_size, 0xff), supergameboy_ram_size);
if(supergameboy_rtc_size) memory::gbrtc.map(allocate<uint8_t>(supergameboy_rtc_size, 0x00), supergameboy_rtc_size);
}
}
@ -65,21 +84,13 @@ void Cartridge::load(Mode cartridge_mode) {
memory::gbram.write_protect(false);
memory::gbrtc.write_protect(false);
unsigned checksum = ~0;
for(unsigned n = 0; n < memory::cartrom.size(); n++) checksum = crc32_adjust(checksum, memory::cartrom[n]);
if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0)
for(unsigned n = 0; n < memory::bsxflash.size(); n++) checksum = crc32_adjust(checksum, memory::bsxflash[n]);
if(memory::stArom.size() != 0 && memory::stArom.size() != ~0)
for(unsigned n = 0; n < memory::stArom.size(); n++) checksum = crc32_adjust(checksum, memory::stArom[n]);
if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0)
for(unsigned n = 0; n < memory::stBrom.size(); n++) checksum = crc32_adjust(checksum, memory::stBrom[n]);
if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0)
for(unsigned n = 0; n < memory::gbrom.size(); n++) checksum = crc32_adjust(checksum, memory::gbrom[n]);
unsigned checksum = ~0; foreach(n, memory::cartrom ) checksum = crc32_adjust(checksum, n);
if(memory::bsxflash.size() != 0 && memory::bsxflash.size() != ~0) foreach(n, memory::bsxflash) checksum = crc32_adjust(checksum, n);
if(memory::stArom.size() != 0 && memory::stArom.size() != ~0) foreach(n, memory::stArom ) checksum = crc32_adjust(checksum, n);
if(memory::stBrom.size() != 0 && memory::stBrom.size() != ~0) foreach(n, memory::stBrom ) checksum = crc32_adjust(checksum, n);
if(memory::gbrom.size() != 0 && memory::gbrom.size() != ~0) foreach(n, memory::gbrom ) checksum = crc32_adjust(checksum, n);
crc32 = ~checksum;
#if 0
fprintf(stdout, "crc32 = %.8x\n", (unsigned)crc32);
sha256_ctx sha;
uint8_t shahash[32];
sha256_init(&sha);
@ -87,10 +98,9 @@ void Cartridge::load(Mode cartridge_mode) {
sha256_final(&sha);
sha256_hash(&sha, shahash);
fprintf(stdout, "sha256 = ");
for(unsigned i = 0; i < 32; i++) fprintf(stdout, "%.2x", shahash[i]);
fprintf(stdout, "\n");
#endif
string hash;
foreach(n, shahash) hash << strhex<2>(n);
sha256 = hash;
bus.load_cart();
system.serialize_init();
@ -117,10 +127,6 @@ void Cartridge::unload() {
loaded = false;
}
bool Cartridge::has_msu() const {
return msu.exists();
}
Cartridge::Cartridge() {
loaded = false;
unload();

View File

@ -0,0 +1,111 @@
class Cartridge : property<Cartridge> {
public:
enum class Mode : unsigned {
Normal,
BsxSlotted,
Bsx,
SufamiTurbo,
SuperGameBoy,
};
enum class Region : unsigned {
NTSC,
PAL,
};
enum class SuperGameBoyVersion : unsigned {
Version1,
Version2,
};
readonly<bool> loaded;
readonly<unsigned> crc32;
readonly<string> sha256;
readonly<Mode> mode;
readonly<Region> region;
readonly<unsigned> ram_size;
readonly<unsigned> spc7110_data_rom_offset;
readonly<SuperGameBoyVersion> supergameboy_version;
readonly<unsigned> supergameboy_ram_size;
readonly<unsigned> supergameboy_rtc_size;
readonly<bool> has_bsx_slot;
readonly<bool> has_superfx;
readonly<bool> has_sa1;
readonly<bool> has_srtc;
readonly<bool> has_sdd1;
readonly<bool> has_spc7110;
readonly<bool> has_spc7110rtc;
readonly<bool> has_cx4;
readonly<bool> has_dsp1;
readonly<bool> has_dsp2;
readonly<bool> has_dsp3;
readonly<bool> has_dsp4;
readonly<bool> has_obc1;
readonly<bool> has_st0010;
readonly<bool> has_st0011;
readonly<bool> has_st0018;
readonly<bool> has_msu1;
struct Mapping {
Memory *memory;
MMIO *mmio;
Bus::MapMode mode;
unsigned banklo;
unsigned bankhi;
unsigned addrlo;
unsigned addrhi;
unsigned offset;
unsigned size;
Mapping();
Mapping(Memory&);
Mapping(MMIO&);
};
array<Mapping> mapping;
void load(Mode, const lstring&);
void unload();
void serialize(serializer&);
Cartridge();
~Cartridge();
private:
void parse_xml(const lstring&);
void parse_xml_cartridge(const char*);
void parse_xml_bsx(const char*);
void parse_xml_sufami_turbo(const char*, bool);
void parse_xml_gameboy(const char*);
void xml_parse_rom(xml_element*);
void xml_parse_ram(xml_element*);
void xml_parse_superfx(xml_element*);
void xml_parse_sa1(xml_element*);
void xml_parse_bsx(xml_element*);
void xml_parse_sufamiturbo(xml_element*);
void xml_parse_supergameboy(xml_element*);
void xml_parse_srtc(xml_element*);
void xml_parse_sdd1(xml_element*);
void xml_parse_spc7110(xml_element*);
void xml_parse_cx4(xml_element*);
void xml_parse_necdsp(xml_element*);
void xml_parse_obc1(xml_element*);
void xml_parse_setadsp(xml_element*);
void xml_parse_setarisc(xml_element*);
void xml_parse_msu1(xml_element*);
void xml_parse_address(Mapping&, const string&);
void xml_parse_mode(Mapping&, const string&);
};
namespace memory {
extern MappedRAM cartrom, cartram, cartrtc;
extern MappedRAM bsxflash, bsxram, bsxpram;
extern MappedRAM stArom, stAram;
extern MappedRAM stBrom, stBram;
extern MappedRAM gbrom, gbram, gbrtc;
};
extern Cartridge cartridge;

655
bsnes/cartridge/xml.cpp Normal file
View File

@ -0,0 +1,655 @@
#ifdef CARTRIDGE_CPP
void Cartridge::parse_xml(const lstring &list) {
parse_xml_cartridge(list[0]);
if(mode == Mode::BsxSlotted) {
parse_xml_bsx(list[1]);
} else if(mode == Mode::Bsx) {
parse_xml_bsx(list[1]);
} else if(mode == Mode::SufamiTurbo) {
parse_xml_sufami_turbo(list[1], 0);
parse_xml_sufami_turbo(list[2], 1);
} else if(mode == Mode::SuperGameBoy) {
parse_xml_gameboy(list[1]);
}
}
void Cartridge::parse_xml_cartridge(const char *data) {
xml_element *document = xml_parse(data);
if(document == 0) return;
foreach(head, document->element) {
if(head->name == "cartridge") {
foreach(attr, head->attribute) {
if(attr->name == "region") {
if(attr->content == "NTSC") region = Region::NTSC;
if(attr->content == "PAL") region = Region::PAL;
}
}
foreach(node, head->element) {
if(node->name == "rom") xml_parse_rom(node);
if(node->name == "ram") xml_parse_ram(node);
if(node->name == "superfx") xml_parse_superfx(node);
if(node->name == "sa1") xml_parse_sa1(node);
if(node->name == "bsx") xml_parse_bsx(node);
if(node->name == "sufamiturbo") xml_parse_sufamiturbo(node);
if(node->name == "supergameboy") xml_parse_supergameboy(node);
if(node->name == "srtc") xml_parse_srtc(node);
if(node->name == "sdd1") xml_parse_sdd1(node);
if(node->name == "spc7110") xml_parse_spc7110(node);
if(node->name == "cx4") xml_parse_cx4(node);
if(node->name == "necdsp") xml_parse_necdsp(node);
if(node->name == "obc1") xml_parse_obc1(node);
if(node->name == "setadsp") xml_parse_setadsp(node);
if(node->name == "setarisc") xml_parse_setarisc(node);
if(node->name == "msu1") xml_parse_msu1(node);
}
}
}
}
void Cartridge::parse_xml_bsx(const char *data) {
}
void Cartridge::parse_xml_sufami_turbo(const char *data, bool slot) {
}
void Cartridge::parse_xml_gameboy(const char *data) {
xml_element *document = xml_parse(data);
if(document == 0) return;
foreach(head, document->element) {
if(head->name == "cartridge") {
foreach(attr, head->attribute) {
if(attr->name == "rtc") {
supergameboy_rtc_size = (attr->content == "true") ? 4 : 0;
}
}
foreach(leaf, head->element) {
if(leaf->name == "ram") {
foreach(attr, leaf->attribute) {
if(attr->name == "size") {
supergameboy_ram_size = strhex(attr->content);
}
}
}
}
}
}
delete document;
}
void Cartridge::xml_parse_rom(xml_element *root) {
foreach(leaf, root->element) {
if(leaf->name == "map") {
Mapping m(memory::cartrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
}
void Cartridge::xml_parse_ram(xml_element *root) {
foreach(attr, root->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
}
foreach(leaf, root->element) {
if(leaf->name == "map") {
Mapping m(memory::cartram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
}
void Cartridge::xml_parse_superfx(xml_element *root) {
has_superfx = true;
foreach(node, root->element) {
if(node->name == "rom") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::fxrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "ram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::fxram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(superfx);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_sa1(xml_element *root) {
has_sa1 = true;
foreach(node, root->element) {
if(node->name == "rom") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::vsprom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "iram") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::cpuiram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "bwram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::cc1bwram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(sa1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_bsx(xml_element *root) {
foreach(node, root->element) {
if(node->name == "slot") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(memory::bsxflash);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(bsxcart);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_sufamiturbo(xml_element *root) {
foreach(node, root->element) {
if(node->name == "slot") {
bool slotid = 0;
foreach(attr, node->attribute) {
if(attr->name == "id") {
if(attr->content == "A") slotid = 0;
if(attr->content == "B") slotid = 1;
}
}
foreach(slot, node->element) {
if(slot->name == "rom") {
foreach(leaf, slot->element) {
if(leaf->name == "map") {
Mapping m(slotid == 0 ? memory::stArom : memory::stBrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
if(m.memory->size() > 0) mapping.add(m);
}
}
} else if(slot->name == "ram") {
foreach(leaf, slot->element) {
if(leaf->name == "map") {
Mapping m(slotid == 0 ? memory::stAram : memory::stBram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
if(m.memory->size() > 0) mapping.add(m);
}
}
}
}
}
}
}
void Cartridge::xml_parse_supergameboy(xml_element *root) {
foreach(attr, root->attribute) {
if(attr->name == "revision") {
if(attr->content == "1") supergameboy_version = SuperGameBoyVersion::Version1;
if(attr->content == "2") supergameboy_version = SuperGameBoyVersion::Version2;
}
}
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m((Memory&)supergameboy);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_srtc(xml_element *root) {
has_srtc = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(srtc);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_sdd1(xml_element *root) {
has_sdd1 = true;
foreach(node, root->element) {
if(node->name == "mcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m((Memory&)sdd1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m((MMIO&)sdd1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_spc7110(xml_element *root) {
has_spc7110 = true;
foreach(node, root->element) {
if(node->name == "dcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(spc7110dcu);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(spc7110mcu);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "offset") spc7110_data_rom_offset = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(spc7110);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "ram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(spc7110ram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "rtc") {
has_spc7110rtc = true;
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(spc7110);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_cx4(xml_element *root) {
has_cx4 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(cx4);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_necdsp(xml_element *root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "DSP-1" || attr->content == "DSP-1A" || attr->content == "DSP-1B") {
program = 1;
has_dsp1 = true;
} else if(attr->content == "DSP-2") {
program = 2;
has_dsp2 = true;
} else if(attr->content == "DSP-3") {
program = 3;
has_dsp3 = true;
} else if(attr->content == "DSP-4") {
program = 4;
has_dsp4 = true;
}
}
}
Memory *dr[5] = { 0, &dsp1dr, &dsp2, &dsp3, &dsp4 };
Memory *sr[5] = { 0, &dsp1sr, &dsp2, &dsp3, &dsp4 };
foreach(node, root->element) {
if(node->name == "dr" && dr[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(*dr[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
} else if(node->name == "sr" && sr[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(*sr[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_obc1(xml_element *root) {
has_obc1 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(obc1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_setadsp(xml_element *root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "ST-0010") {
program = 1;
has_st0010 = true;
} else if(attr->content == "ST-0011") {
program = 2;
has_st0011 = true;
}
}
}
Memory *map[3] = { 0, &st0010, 0 };
foreach(node, root->element) {
if(node->name == "mmio" && map[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(*map[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_setarisc(xml_element *root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "ST-0018") {
program = 1;
has_st0018 = true;
}
}
}
MMIO *map[2] = { 0, &st0018 };
foreach(node, root->element) {
if(node->name == "mmio" && map[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(*map[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_msu1(xml_element *root) {
has_msu1 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
Mapping m(msu1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
}
mapping.add(m);
}
}
}
}
}
void Cartridge::xml_parse_address(Mapping &m, const string &data) {
lstring part;
part.split(":", data);
if(part.size() != 2) return;
lstring subpart;
subpart.split("-", part[0]);
if(subpart.size() == 1) {
m.banklo = strhex(subpart[0]);
m.bankhi = m.banklo;
} else if(subpart.size() == 2) {
m.banklo = strhex(subpart[0]);
m.bankhi = strhex(subpart[1]);
}
subpart.split("-", part[1]);
if(subpart.size() == 1) {
m.addrlo = strhex(subpart[0]);
m.addrhi = m.addrlo;
} else if(subpart.size() == 2) {
m.addrlo = strhex(subpart[0]);
m.addrhi = strhex(subpart[1]);
}
}
void Cartridge::xml_parse_mode(Mapping &m, const string& data) {
if(data == "direct") m.mode = Bus::MapMode::Direct;
else if(data == "linear") m.mode = Bus::MapMode::Linear;
else if(data == "shadow") m.mode = Bus::MapMode::Shadow;
}
Cartridge::Mapping::Mapping() {
memory = 0;
mmio = 0;
mode = Bus::MapMode::Direct;
banklo = bankhi = addrlo = addrhi = offset = size = 0;
}
Cartridge::Mapping::Mapping(Memory &memory_) {
memory = &memory_;
mmio = 0;
mode = Bus::MapMode::Direct;
banklo = bankhi = addrlo = addrhi = offset = size = 0;
}
Cartridge::Mapping::Mapping(MMIO &mmio_) {
memory = 0;
mmio = &mmio_;
mode = Bus::MapMode::Direct;
banklo = bankhi = addrlo = addrhi = offset = size = 0;
}
#endif

View File

@ -83,7 +83,7 @@ bool Cheat::decode(const char *s, unsigned &addr, uint8 &data, Type &type) {
//validate input
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false;
type = ProActionReplay;
type = Type::ProActionReplay;
unsigned r = strhex((const char*)t);
addr = r >> 8;
data = r & 0xff;
@ -94,7 +94,7 @@ bool Cheat::decode(const char *s, unsigned &addr, uint8 &data, Type &type) {
//validate input
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false;
type = GameGenie;
type = Type::GameGenie;
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
unsigned r = strhex((const char*)t);
//8421 8421 8421 8421 8421 8421
@ -124,11 +124,10 @@ bool Cheat::decode(const char *s, unsigned &addr, uint8 &data, Type &type) {
bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
char t[16];
if(type == ProActionReplay) {
sprintf(t, "%.6x%.2x", addr, data);
s = t;
if(type == Type::ProActionReplay) {
s = sprint("$$", strhex<6>(addr), strhex<2>(data));
return true;
} else if(type == GameGenie) {
} else if(type == Type::GameGenie) {
unsigned r = addr;
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22)
| (!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20)
@ -142,9 +141,8 @@ bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
| (!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4)
| (!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2)
| (!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
sprintf(t, "%.2x%.2x-%.4x", data, addr >> 16, addr & 0xffff);
strtr(t, "0123456789abcdef", "df4709156bc8a23e");
s = t;
s = sprint("$$-$", strhex<2>(data), strhex<2>(addr >> 16), strhex<4>(addr & 0xffff));
strtr(s, "0123456789abcdef", "df4709156bc8a23e");
return true;
} else {
return false;

View File

@ -7,9 +7,9 @@ struct CheatCode {
CheatCode();
};
class Cheat : public vector<CheatCode> {
class Cheat : public linear_vector<CheatCode> {
public:
enum Type { ProActionReplay, GameGenie };
enum class Type : unsigned { ProActionReplay, GameGenie };
bool enabled() const;
void enable(bool);

View File

@ -6,7 +6,6 @@ void BSXCart::init() {
}
void BSXCart::enable() {
for(uint16 i = 0x5000; i <= 0x5fff; i++) memory::mmio.map(i, *this);
}
void BSXCart::power() {
@ -26,39 +25,39 @@ void BSXCart::update_memory_map() {
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);
bus.map(Bus::MapMode::Linear, 0x00, 0x7d, 0x8000, 0xffff, cart);
bus.map(Bus::MapMode::Linear, 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);
bus.map(Bus::MapMode::Shadow, 0x00, 0x3f, 0x8000, 0xffff, cart);
bus.map(Bus::MapMode::Linear, 0x40, 0x7d, 0x0000, 0xffff, cart);
bus.map(Bus::MapMode::Shadow, 0x80, 0xbf, 0x8000, 0xffff, cart);
bus.map(Bus::MapMode::Linear, 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);
bus.map(Bus::MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, memory::bsxpram);
//bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
}
if((regs.r[0x05] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
bus.map(Bus::MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::bsxpram);
}
if((regs.r[0x06] & 0x80) == 0x00) {
bus.map(Bus::MapLinear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
bus.map(Bus::MapMode::Linear, 0x50, 0x5f, 0x0000, 0xffff, memory::bsxpram);
}
if(regs.r[0x07] & 0x80) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom);
}
if(regs.r[0x08] & 0x80) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom);
bus.map(Bus::MapMode::Linear, 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);
bus.map(Bus::MapMode::Shadow, 0x20, 0x3f, 0x6000, 0x7fff, memory::bsxpram);
bus.map(Bus::MapMode::Linear, 0x70, 0x77, 0x0000, 0xffff, memory::bsxpram);
}
uint8 BSXCart::mmio_read(unsigned addr) {

View File

@ -60,7 +60,7 @@ void BSXFlash::write(unsigned addr, uint8 data) {
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
//read-only flashcarts.
//below is an unfortunately necessary workaround to this problem.
if(cartridge.mapper() == Cartridge::BSCHiROM) return;
//if(cartridge.mapper() == Cartridge::BSCHiROM) return;
if((addr & 0xff0000) == 0) {
regs.write_old = regs.write_new;

View File

@ -11,7 +11,7 @@
#include "dsp3/dsp3.hpp"
#include "dsp4/dsp4.hpp"
#include "obc1/obc1.hpp"
#include "st010/st010.hpp"
#include "st011/st011.hpp"
#include "st018/st018.hpp"
#include "msu/msu.hpp"
#include "st0010/st0010.hpp"
#include "st0011/st0011.hpp"
#include "st0018/st0018.hpp"
#include "msu1/msu1.hpp"

View File

@ -21,8 +21,6 @@ void Cx4::init() {
}
void Cx4::enable() {
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
}
uint32 Cx4::ldr(uint8 r) {

33
bsnes/chip/dsp1/dsp1.cpp Normal file
View File

@ -0,0 +1,33 @@
#include <../base.hpp>
#define DSP1_CPP
namespace SNES {
DSP1 dsp1;
DSP1DR dsp1dr;
DSP1SR dsp1sr;
#include "serialization.cpp"
#include "dsp1emu.cpp"
void DSP1::init() {
}
void DSP1::enable() {
}
void DSP1::power() {
reset();
}
void DSP1::reset() {
dsp1.reset();
}
uint8 DSP1DR::read(unsigned addr) { return dsp1.dsp1.getDr(); }
void DSP1DR::write(unsigned addr, uint8 data) { dsp1.dsp1.setDr(data); }
uint8 DSP1SR::read(unsigned addr) { return dsp1.dsp1.getSr(); }
void DSP1SR::write(unsigned addr, uint8 data) {}
};

View File

@ -1,20 +1,30 @@
#include "dsp1emu.hpp"
class DSP1 : public Memory {
class DSP1 {
public:
void init();
void enable();
void power();
void reset();
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
private:
Dsp1 dsp1;
bool addr_decode(uint16 addr);
friend class DSP1DR;
friend class DSP1SR;
};
class DSP1DR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class DSP1SR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
extern DSP1 dsp1;
extern DSP1DR dsp1dr;
extern DSP1SR dsp1sr;

View File

@ -12,10 +12,6 @@ void DSP2::init() {
}
void DSP2::enable() {
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x6000, 0x6fff, *this);
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xbfff, *this);
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x6000, 0x6fff, *this);
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xbfff, *this);
}
void DSP2::power() {

View File

@ -15,8 +15,6 @@ void DSP3::init() {
}
void DSP3::enable() {
bus.map(Bus::MapDirect, 0x20, 0x3f, 0x8000, 0xffff, *this);
bus.map(Bus::MapDirect, 0xa0, 0xbf, 0x8000, 0xffff, *this);
}
void DSP3::power() {

View File

@ -9,8 +9,6 @@ void DSP4::init() {
}
void DSP4::enable() {
bus.map(Bus::MapDirect, 0x30, 0x3f, 0x8000, 0xffff, *this);
bus.map(Bus::MapDirect, 0xb0, 0xbf, 0x8000, 0xffff, *this);
}
namespace DSP4i {

View File

@ -1,18 +1,18 @@
#include <../base.hpp>
#define MSU_CPP
#define MSU1_CPP
namespace SNES {
MSU msu;
MSU1 msu1;
#include "serialization.cpp"
void MSU::enter() {
void MSU1::enter() {
scheduler.clock.cop_freq = 44100;
while(true) {
if(scheduler.sync == Scheduler::SyncAll) {
scheduler.exit(Scheduler::SynchronizeEvent);
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
int16 left = 0, right = 0;
@ -41,26 +41,22 @@ void MSU::enter() {
}
}
void MSU::init() {
void MSU1::init() {
}
void MSU::enable() {
void MSU1::enable() {
audio.coprocessor_enable(true);
audio.coprocessor_frequency(44100.0);
for(unsigned i = 0x2000; i <= 0x2007; i++) {
memory::mmio.map(i, *this);
}
if(datafile.open()) datafile.close();
datafile.open(string() << basename << ".msu", file::mode_read);
}
void MSU::power() {
void MSU1::power() {
reset();
}
void MSU::reset() {
void MSU1::reset() {
mmio.data_offset = 0;
mmio.audio_offset = 0;
mmio.audio_track = 0;
@ -71,7 +67,7 @@ void MSU::reset() {
mmio.audio_play = false;
}
uint8 MSU::mmio_read(unsigned addr) {
uint8 MSU1::mmio_read(unsigned addr) {
addr &= 0xffff;
if(addr == 0x2000) {
@ -99,7 +95,7 @@ uint8 MSU::mmio_read(unsigned addr) {
return 0x00;
}
void MSU::mmio_write(unsigned addr, uint8 data) {
void MSU1::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;
if(addr == 0x2000) {
@ -147,12 +143,8 @@ void MSU::mmio_write(unsigned addr, uint8 data) {
}
}
void MSU::base(const string& name) {
void MSU1::base(const string& name) {
basename = name;
}
bool MSU::exists() {
return file::exists(string() << basename << ".msu");
}
}

View File

@ -1,4 +1,4 @@
class MSU : public MMIO {
class MSU1 : public MMIO {
public:
void enter();
@ -11,8 +11,6 @@ public:
void mmio_write(unsigned addr, uint8 data);
void base(const string &name);
bool exists();
void serialize(serializer&);
private:
@ -40,4 +38,4 @@ private:
} mmio;
};
extern MSU msu;
extern MSU1 msu1;

View File

@ -1,6 +1,6 @@
#ifdef MSU_CPP
#ifdef MSU1_CPP
void MSU::serialize(serializer &s) {
void MSU1::serialize(serializer &s) {
s.integer(mmio.data_offset);
s.integer(mmio.audio_offset);
s.integer(mmio.audio_track);

View File

@ -11,8 +11,6 @@ void OBC1::init() {
}
void OBC1::enable() {
bus.map(Bus::MapDirect, 0x00, 0x3f, 0x6000, 0x7fff, *this);
bus.map(Bus::MapDirect, 0x80, 0xbf, 0x6000, 0x7fff, *this);
}
void OBC1::power() {

View File

@ -5,13 +5,13 @@ SA1Bus sa1bus;
namespace memory {
StaticRAM iram(2048);
//accessed by:
VectorSelectionPage vectorsp; //S-CPU + SA-1
CPUIRAM cpuiram; //S-CPU
SA1IRAM sa1iram; //SA-1
SA1BWRAM sa1bwram; //SA-1
CC1BWRAM cc1bwram; //S-CPU
BitmapRAM bitmapram; //SA-1
//accessed by:
VSPROM vsprom; //S-CPU + SA-1
CPUIRAM cpuiram; //S-CPU
SA1IRAM sa1iram; //SA-1
SA1BWRAM sa1bwram; //SA-1
CC1BWRAM cc1bwram; //S-CPU
BitmapRAM bitmapram; //SA-1
}
//$230c (VDPL), $230d (VDPH) use this bus to read variable-length data.
@ -20,53 +20,41 @@ namespace memory {
//these ports.
//(* eg, memory::cartram is used directly, as memory::sa1bwram syncs to the S-CPU)
void VBRBus::init() {
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
map(MapLinear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
map(MapLinear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapLinear, 0x00, 0x3f, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0x40, 0x4f, 0x0000, 0xffff, memory::cartram);
map(MapLinear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
map(MapLinear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
map(MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cartram);
map(MapLinear, 0x80, 0xbf, 0x8000, 0xffff, memory::cartrom);
map(MapLinear, 0xc0, 0xff, 0x0000, 0xffff, memory::cartrom);
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, memory::iram);
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, memory::iram);
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cartram);
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::vsprom);
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::cartram);
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, memory::iram);
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, memory::iram);
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cartram);
map(MapMode::Linear, 0x80, 0xbf, 0x8000, 0xffff, memory::vsprom);
map(MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, memory::vsprom);
}
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(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
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();
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x07ff, memory::sa1iram);
map(MapMode::Direct, 0x00, 0x3f, 0x2200, 0x23ff, memory::mmio);
map(MapMode::Linear, 0x00, 0x3f, 0x3000, 0x37ff, memory::sa1iram);
map(MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram);
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::vsprom);
map(MapMode::Linear, 0x40, 0x4f, 0x0000, 0xffff, memory::sa1bwram);
map(MapMode::Linear, 0x60, 0x6f, 0x0000, 0xffff, memory::bitmapram);
map(MapMode::Linear, 0x80, 0xbf, 0x0000, 0x07ff, memory::sa1iram);
map(MapMode::Direct, 0x80, 0xbf, 0x2200, 0x23ff, memory::mmio);
map(MapMode::Linear, 0x80, 0xbf, 0x3000, 0x37ff, memory::sa1iram);
map(MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram);
map(MapMode::Linear, 0x80, 0xbf, 0x8000, 0xffff, memory::vsprom);
map(MapMode::Linear, 0xc0, 0xff, 0x0000, 0xffff, memory::vsprom);
}
//===================
//VectorSelectionPage
//===================
//======
//VSPROM
//======
//this class maps $00:[ff00-ffff] for the purpose of supporting:
//$2209.d6 IVSW (S-CPU IRQ vector selection) (0 = cart, 1 = SA-1)
@ -78,35 +66,22 @@ void SA1Bus::init() {
//$00:[ffea-ffeb|ffee-ffef] are special cased on read;
//all other addresses return original mapped data.
uint8 VectorSelectionPage::read(unsigned addr) {
switch(0xff00 | (addr & 0xff)) {
case 0xffea: case 0xffeb: {
if(sa1.mmio.cpu_nvsw == true) return (sa1.mmio.snv >> ((addr & 1) << 3));
} break;
case 0xffee: case 0xffef: {
if(sa1.mmio.cpu_ivsw == true) return (sa1.mmio.siv >> ((addr & 1) << 3));
} break;
}
return access->read(addr);
unsigned VSPROM::size() const {
return memory::cartrom.size();
}
void VectorSelectionPage::write(unsigned addr, uint8 data) {
return access->write(addr, data);
uint8 VSPROM::read(unsigned addr) {
//use $7fex instead of $ffex due to linear mapping of 32k granularity ROM data
if((addr & 0xffffe0) == 0x007fe0) {
if(addr == 0x7fea && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 0;
if(addr == 0x7feb && sa1.mmio.cpu_nvsw) return sa1.mmio.snv >> 8;
if(addr == 0x7fee && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 0;
if(addr == 0x7fef && sa1.mmio.cpu_ivsw) return sa1.mmio.siv >> 8;
}
return memory::cartrom.read(addr);
}
//call this whenever bus is remapped.
//note: S-CPU and SA-1 bus always share $00:[ff00-ffff] as cartridge ROM data;
//the SA-1 MMC does not allow mapping these independently between processors.
//this allows this class to be shared for both, caching only ones' access class.
void VectorSelectionPage::sync() {
if(bus.page[0x00ff00 >> 8].access != this) {
//bus was re-mapped, hook access routine
access = bus.page[0x00ff00 >> 8].access;
bus.page[0x00ff00 >> 8].access = this;
sa1bus.page[0x00ff00 >> 8].access = this;
}
void VSPROM::write(unsigned addr, uint8 data) {
}
//=======

View File

@ -6,11 +6,10 @@ struct SA1Bus : Bus {
void init();
};
struct VectorSelectionPage : Memory {
struct VSPROM : Memory {
unsigned size() const;
alwaysinline uint8 read(unsigned);
alwaysinline void write(unsigned, uint8);
void sync();
Memory *access;
};
struct CPUIRAM : Memory {
@ -47,7 +46,7 @@ struct BitmapRAM : Memory {
namespace memory {
extern StaticRAM iram;
extern VectorSelectionPage vectorsp;
extern VSPROM vsprom;
extern CPUIRAM cpuiram;
extern SA1IRAM sa1iram;
extern SA1BWRAM sa1bwram;

View File

@ -2,8 +2,8 @@
//BS-X flash carts, when present, are mapped to 0x400000+
Memory& SA1::mmio_access(unsigned &addr) {
if(!memory::bsxflash.data()) return memory::cartrom;
if(addr < 0x400000) return memory::cartrom;
if(!memory::bsxflash.data()) return memory::vsprom;
if(addr < 0x400000) return memory::vsprom;
addr &= 0x3fffff;
return bsxflash;
}
@ -156,17 +156,15 @@ void SA1::mmio_w2220(uint8 data) {
Memory &access = mmio_access(addr);
if(mmio.cbmode == 0) {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, memory::cartrom, 0x000000);
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::vsprom, 0x000000);
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, memory::vsprom, 0x000000);
} else {
bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x1f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
memory::vectorsp.sync();
bus.map(Bus::MapMode::Linear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0xc0, 0xcf, 0x0000, 0xffff, access, addr);
}
//(DXB) Super MMC bank D
@ -178,15 +176,15 @@ void SA1::mmio_w2221(uint8 data) {
Memory &access = mmio_access(addr);
if(mmio.dbmode == 0) {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, memory::cartrom, 0x100000);
bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, memory::vsprom, 0x100000);
sa1bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, memory::vsprom, 0x100000);
} else {
bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0x20, 0x3f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0xd0, 0xdf, 0x0000, 0xffff, access, addr);
}
//(EXB) Super MMC bank E
@ -198,15 +196,15 @@ void SA1::mmio_w2222(uint8 data) {
Memory &access = mmio_access(addr);
if(mmio.ebmode == 0) {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, memory::cartrom, 0x200000);
bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::vsprom, 0x200000);
sa1bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, memory::vsprom, 0x200000);
} else {
bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0x80, 0x9f, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0xe0, 0xef, 0x0000, 0xffff, access, addr);
}
//(FXB) Super MMC bank F
@ -218,23 +216,23 @@ void SA1::mmio_w2223(uint8 data) {
Memory &access = mmio_access(addr);
if(mmio.fbmode == 0) {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, memory::cartrom, 0x300000);
bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, memory::vsprom, 0x300000);
sa1bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, memory::vsprom, 0x300000);
} else {
bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0xa0, 0xbf, 0x8000, 0xffff, access, addr);
}
bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapLinear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
bus.map(Bus::MapMode::Linear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
sa1bus.map(Bus::MapMode::Linear, 0xf0, 0xff, 0x0000, 0xffff, access, addr);
}
//(BMAPS) S-CPU BW-RAM address mapping
void SA1::mmio_w2224(uint8 data) {
mmio.sbm = (data & 0x1f);
bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::cc1bwram, mmio.sbm * 0x2000, 0x2000);
}
//(BMAP) SA-1 BW-RAM address mapping
@ -244,12 +242,12 @@ void SA1::mmio_w2225(uint8 data) {
if(mmio.sw46 == 0) {
//$[40-43]:[0000-ffff] x 32 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
sa1bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::sa1bwram, (mmio.cbm & 0x1f) * 0x2000, 0x2000);
} else {
//$[60-6f]:[0000-ffff] x 128 projection
sa1bus.map(Bus::MapLinear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
sa1bus.map(Bus::MapLinear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
sa1bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
sa1bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x6000, 0x7fff, memory::bitmapram, mmio.cbm * 0x2000, 0x2000);
}
}

View File

@ -13,8 +13,8 @@ SA1 sa1;
void SA1::enter() {
while(true) {
if(scheduler.sync == Scheduler::SyncAll) {
scheduler.exit(Scheduler::SynchronizeEvent);
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
if(mmio.sa1_rdyb || mmio.sa1_resb) {
@ -127,7 +127,6 @@ void SA1::power() {
}
void SA1::reset() {
memory::vectorsp.access = 0;
memory::cc1bwram.dma = false;
for(unsigned addr = 0; addr < memory::iram.size(); addr++) {
memory::iram.write(addr, 0x00);
@ -152,7 +151,7 @@ void SA1::reset() {
status.interrupt_pending = false;
status.interrupt_vector = 0x0000;
status.scanlines = (system.region() == System::NTSC ? 262 : 312);
status.scanlines = (system.region() == System::Region::NTSC ? 262 : 312);
status.vcounter = 0;
status.hcounter = 0;

View File

@ -16,8 +16,6 @@ void SA1::serialize(serializer &s) {
//bus/bus.hpp
s.array(memory::iram.data(), memory::iram.size());
memory::vectorsp.sync();
s.integer(memory::cc1bwram.dma);
//dma/dma.hpp

View File

@ -17,11 +17,6 @@ void SDD1::enable() {
cpu_mmio[i & 0x7f] = memory::mmio.mmio[i - 0x2000];
memory::mmio.map(i, *this);
}
//hook S-DD1 MMIO registers
for(unsigned i = 0x4800; i <= 0x4807; i++) {
memory::mmio.map(i, *this);
}
}
void SDD1::power() {
@ -43,8 +38,6 @@ void SDD1::reset() {
}
buffer.ready = false;
bus.map(Bus::MapDirect, 0xc0, 0xff, 0x0000, 0xffff, *this);
}
uint8 SDD1::mmio_read(unsigned addr) {

View File

@ -24,9 +24,9 @@ void SPC7110Decomp::write(uint8 data) {
}
uint8 SPC7110Decomp::dataread() {
unsigned size = memory::cartrom.size() - 0x100000;
unsigned size = memory::cartrom.size() - cartridge.spc7110_data_rom_offset();
while(decomp_offset >= size) decomp_offset -= size;
return memory::cartrom.read(0x100000 + decomp_offset++);
return memory::cartrom.read(cartridge.spc7110_data_rom_offset() + decomp_offset++);
}
void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) {

View File

@ -4,6 +4,9 @@
namespace SNES {
SPC7110 spc7110;
SPC7110MCU spc7110mcu;
SPC7110DCU spc7110dcu;
SPC7110RAM spc7110ram;
#include "serialization.cpp"
#include "decomp.cpp"
@ -11,11 +14,7 @@ SPC7110 spc7110;
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
void SPC7110::init() {}
void SPC7110::enable() {
uint16_t limit = (cartridge.has_spc7110rtc() ? 0x4842 : 0x483f);
for(uint16_t i = 0x4800; i <= limit; i++) memory::mmio.map(i, *this);
}
void SPC7110::enable() {}
void SPC7110::power() {
reset();
@ -85,9 +84,9 @@ void SPC7110::reset() {
}
unsigned SPC7110::datarom_addr(unsigned addr) {
unsigned size = memory::cartrom.size() - 0x100000;
unsigned size = memory::cartrom.size() - cartridge.spc7110_data_rom_offset();
while(addr >= size) addr -= size;
return addr + 0x100000;
return cartridge.spc7110_data_rom_offset() + addr;
}
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
@ -632,46 +631,52 @@ void SPC7110::mmio_write(unsigned addr, uint8 data) {
}
}
uint8 SPC7110::read(unsigned addr) {
//$[00-0f|80-8f]:[8000-ffff], $[c0-cf]:[0000-ffff] mapped directly to memory::cartrom
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
//$[00|30]:[6000-7fff]
return memory::cartram.read(addr & 0x1fff);
}
if((addr & 0xff0000) == 0x500000) {
//$[50]:[0000-ffff]
return mmio_read(0x4800);
}
if((addr & 0xf00000) == 0xd00000) {
//$[d0-df]:[0000-ffff]
return memory::cartrom.read(dx_offset + (addr & 0x0fffff));
}
if((addr & 0xf00000) == 0xe00000) {
//$[e0-ef]:[0000-ffff]
return memory::cartrom.read(ex_offset + (addr & 0x0fffff));
}
if((addr & 0xf00000) == 0xf00000) {
//$[f0-ff]:[0000-ffff]
return memory::cartrom.read(fx_offset + (addr & 0x0fffff));
}
return cpu.regs.mdr;
}
void SPC7110::write(unsigned addr, uint8 data) {
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
//$[00|30]:[6000-7fff]
if(r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
return;
}
}
SPC7110::SPC7110() {
}
//==========
//SPC7110MCU
//==========
unsigned SPC7110MCU::size() const {
return 0x300000;
}
uint8 SPC7110MCU::read(unsigned addr) {
if(addr <= 0xdfffff) return memory::cartrom.read(spc7110.dx_offset + (addr & 0x0fffff));
if(addr <= 0xefffff) return memory::cartrom.read(spc7110.ex_offset + (addr & 0x0fffff));
if(addr <= 0xffffff) return memory::cartrom.read(spc7110.fx_offset + (addr & 0x0fffff));
return cpu.regs.mdr;
}
void SPC7110MCU::write(unsigned addr, uint8 data) {
}
//==========
//SPC7110DCU
//==========
uint8 SPC7110DCU::read(unsigned) {
return spc7110.mmio_read(0x4800);
}
void SPC7110DCU::write(unsigned, uint8) {
}
//==========
//SPC7110RAM
//==========
unsigned SPC7110RAM::size() const {
return 0x2000;
}
uint8 SPC7110RAM::read(unsigned addr) {
return memory::cartram.read(addr & 0x1fff);
}
void SPC7110RAM::write(unsigned addr, uint8 data) {
if(spc7110.r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
}
};

View File

@ -1,6 +1,6 @@
/*****
* SPC7110 emulator - version 0.03 (2008-08-10)
* Copyright (c) 2008, byuu and neviksti
* SPC7110 emulator - version 0.04 (2010-02-14)
* Copyright (c) 2008-2010, byuu and neviksti
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -17,7 +17,7 @@
#include "decomp.hpp"
class SPC7110 : public MMIO, public Memory {
class SPC7110 : public MMIO {
public:
void init();
void enable();
@ -38,9 +38,6 @@ public:
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
//spc7110decomp
void decomp_init();
uint8 decomp_read();
@ -131,6 +128,32 @@ private:
unsigned rtc_index;
static const unsigned months[12];
friend class SPC7110MCU;
friend class SPC7110DCU;
friend class SPC7110RAM;
};
class SPC7110MCU : public Memory {
public:
unsigned size() const;
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class SPC7110DCU : public Memory {
public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class SPC7110RAM : public Memory {
public:
unsigned size() const;
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
extern SPC7110 spc7110;
extern SPC7110MCU spc7110mcu;
extern SPC7110DCU spc7110dcu;
extern SPC7110RAM spc7110ram;

View File

@ -13,8 +13,6 @@ void SRTC::init() {
}
void SRTC::enable() {
memory::mmio.map(0x2800, *this);
memory::mmio.map(0x2801, *this);
}
void SRTC::power() {

View File

@ -1,4 +1,6 @@
const int16 ST010::sin_table[256] = {
#ifdef ST0010_CPP
const int16 ST0010::sin_table[256] = {
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
@ -33,7 +35,7 @@ const int16 ST010::sin_table[256] = {
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
};
const int16 ST010::mode7_scale[176] = {
const int16 ST0010::mode7_scale[176] = {
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
@ -58,7 +60,7 @@ const int16 ST010::mode7_scale[176] = {
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b
};
const uint8 ST010::arctan[32][32] = {
const uint8 ST0010::arctan[32][32] = {
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
{ 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
@ -124,3 +126,5 @@ const uint8 ST010::arctan[32][32] = {
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 }
};
#endif

View File

@ -1,9 +1,9 @@
#ifdef ST010_CPP
#ifdef ST0010_CPP
//ST-010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
//ST-0010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
//bsnes port - Copyright (C) 2007 byuu
void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
void ST0010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
if((x0 < 0) && (y0 < 0)) {
x1 = -x0;
y1 = -y0;
@ -34,7 +34,7 @@ void ST010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int
//
void ST010::op_01() {
void ST0010::op_01() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 x1, y1, quadrant, theta;
@ -48,7 +48,7 @@ void ST010::op_01() {
writew(0x0010, theta);
}
void ST010::op_02() {
void ST0010::op_02() {
int16 positions = readw(0x0024);
uint16 *places = (uint16*)(ram + 0x0040);
uint16 *drivers = (uint16*)(ram + 0x0080);
@ -76,7 +76,7 @@ void ST010::op_02() {
}
}
void ST010::op_03() {
void ST0010::op_03() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 multiplier = readw(0x0004);
@ -89,7 +89,7 @@ void ST010::op_03() {
writed(0x0014, y1);
}
void ST010::op_04() {
void ST0010::op_04() {
int16 x = readw(0x0000);
int16 y = readw(0x0002);
int16 square;
@ -99,7 +99,7 @@ void ST010::op_04() {
writew(0x0010, square);
}
void ST010::op_05() {
void ST0010::op_05() {
int32 dx, dy;
int16 a1, b1, c1;
uint16 o1;
@ -217,7 +217,7 @@ void ST010::op_05() {
writew(0x00dc, flags);
}
void ST010::op_06() {
void ST0010::op_06() {
int16 multiplicand = readw(0x0000);
int16 multiplier = readw(0x0002);
int32 product;
@ -227,7 +227,7 @@ void ST010::op_06() {
writed(0x0010, product);
}
void ST010::op_07() {
void ST0010::op_07() {
int16 theta = readw(0x0000);
int16 data;
@ -245,7 +245,7 @@ void ST010::op_07() {
}
}
void ST010::op_08() {
void ST0010::op_08() {
int16 x0 = readw(0x0000);
int16 y0 = readw(0x0002);
int16 theta = readw(0x0004);

View File

@ -0,0 +1,7 @@
#ifdef ST0010_CPP
void ST0010::serialize(serializer &s) {
s.array(ram);
}
#endif

View File

@ -1,56 +1,54 @@
#include <../base.hpp>
#define ST010_CPP
#define ST0010_CPP
namespace SNES {
ST010 st010;
ST0010 st0010;
#include "st010_data.hpp"
#include "data.hpp"
#include "opcodes.cpp"
#include "serialization.cpp"
#include "st010_op.cpp"
void ST010::init() {
void ST0010::init() {
}
void ST010::enable() {
bus.map(Bus::MapDirect, 0x68, 0x6f, 0x0000, 0x0fff, *this);
bus.map(Bus::MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, *this);
void ST0010::enable() {
}
int16 ST010::sin(int16 theta) {
int16 ST0010::sin(int16 theta) {
return sin_table[(theta >> 8) & 0xff];
}
int16 ST010::cos(int16 theta) {
int16 ST0010::cos(int16 theta) {
return sin_table[((theta + 0x4000) >> 8) & 0xff];
}
uint8 ST010::readb(uint16 addr) {
uint8 ST0010::readb(uint16 addr) {
return ram[addr & 0xfff];
}
uint16 ST010::readw(uint16 addr) {
uint16 ST0010::readw(uint16 addr) {
return (readb(addr + 0) << 0) |
(readb(addr + 1) << 8);
}
uint32 ST010::readd(uint16 addr) {
uint32 ST0010::readd(uint16 addr) {
return (readb(addr + 0) << 0) |
(readb(addr + 1) << 8) |
(readb(addr + 2) << 16) |
(readb(addr + 3) << 24);
}
void ST010::writeb(uint16 addr, uint8 data) {
void ST0010::writeb(uint16 addr, uint8 data) {
ram[addr & 0xfff] = data;
}
void ST010::writew(uint16 addr, uint16 data) {
void ST0010::writew(uint16 addr, uint16 data) {
writeb(addr + 0, data >> 0);
writeb(addr + 1, data >> 8);
}
void ST010::writed(uint16 addr, uint32 data) {
void ST0010::writed(uint16 addr, uint32 data) {
writeb(addr + 0, data >> 0);
writeb(addr + 1, data >> 8);
writeb(addr + 2, data >> 16);
@ -59,21 +57,21 @@ void ST010::writed(uint16 addr, uint32 data) {
//
void ST010::power() {
void ST0010::power() {
reset();
}
void ST010::reset() {
void ST0010::reset() {
memset(ram, 0x00, sizeof ram);
}
//
uint8 ST010::read(unsigned addr) {
uint8 ST0010::read(unsigned addr) {
return readb(addr);
}
void ST010::write(unsigned addr, uint8 data) {
void ST0010::write(unsigned addr, uint8 data) {
writeb(addr, data);
if((addr & 0xfff) == 0x0021 && (data & 0x80)) {

View File

@ -1,4 +1,4 @@
class ST010 : public Memory {
class ST0010 : public Memory {
public:
void init();
void enable();
@ -41,4 +41,4 @@ private:
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
};
extern ST010 st010;
extern ST0010 st0010;

View File

@ -0,0 +1,20 @@
#include <../base.hpp>
#define ST0011_CPP
namespace SNES {
ST0011 st0011;
void ST0011::init() {
}
void ST0011::enable() {
}
void ST0011::power() {
}
void ST0011::reset() {
}
};

View File

@ -1,4 +1,4 @@
class ST011 {
class ST0011 {
public:
void init();
void enable();
@ -6,4 +6,4 @@ public:
void reset();
};
extern ST011 st011;
extern ST0011 st0011;

View File

@ -1,18 +1,18 @@
#include <../base.hpp>
#define ST018_CPP
#define ST0018_CPP
namespace SNES {
ST018 st018;
ST0018 st0018;
uint8 ST018::mmio_read(unsigned addr) {
uint8 ST0018::mmio_read(unsigned addr) {
addr &= 0xffff;
if(addr == 0x3800) return regs.r3800;
if(addr == 0x3804) return regs.r3804;
return cpu.regs.mdr;
}
void ST018::mmio_write(unsigned addr, uint8 data) {
void ST0018::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;
if(addr == 0x3802) {
@ -45,18 +45,17 @@ void ST018::mmio_write(unsigned addr, uint8 data) {
}
}
void ST018::init() {
void ST0018::init() {
}
void ST018::enable() {
for(unsigned i = 0x3800; i <= 0x38ff; i++) memory::mmio.map(i, *this);
void ST0018::enable() {
}
void ST018::power() {
void ST0018::power() {
reset();
}
void ST018::reset() {
void ST0018::reset() {
regs.mode = Waiting;
regs.r3800 = 0x00;
regs.r3804 = 0x85;
@ -64,17 +63,17 @@ void ST018::reset() {
for(unsigned i = 0; i < 97; i++) board[i] = 0;
}
//=============
//ST018 opcodes
//=============
//===============
//ST-0018 opcodes
//===============
void ST018::op_board_upload() {
void ST0018::op_board_upload() {
regs.mode = BoardUpload;
regs.counter = 0;
regs.r3800 = 0xe0;
}
void ST018::op_board_upload(uint8 data) {
void ST0018::op_board_upload(uint8 data) {
board[regs.counter] = data;
regs.r3800 = 96 - regs.counter;
regs.counter++;
@ -93,31 +92,31 @@ void ST018::op_board_upload(uint8 data) {
}
}
void ST018::op_b2() {
void ST0018::op_b2() {
fprintf(stdout, "* ST018 w3802::b2\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 0; //unknown
}
void ST018::op_b3() {
void ST0018::op_b3() {
fprintf(stdout, "* ST018 w3802::b3\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 1; //0 = player lost?
}
void ST018::op_b4() {
void ST0018::op_b4() {
fprintf(stdout, "* ST018 w3802::b4\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 1; //0 = player won?
}
void ST018::op_b5() {
void ST0018::op_b5() {
fprintf(stdout, "* ST018 w3802::b5\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 0; //1 = move will result in checkmate?
}
void ST018::op_query_chip() {
void ST0018::op_query_chip() {
regs.r3800 = 0x00;
}

View File

@ -1,4 +1,4 @@
class ST018 : public MMIO {
class ST0018 : public MMIO {
public:
void init();
void enable();
@ -48,4 +48,4 @@ private:
void op_query_chip();
};
extern ST018 st018;
extern ST0018 st0018;

View File

@ -10,21 +10,12 @@ namespace memory {
}
void SuperFXBus::init() {
map(MapDirect, 0x00, 0xff, 0x0000, 0xffff, memory::memory_unmapped);
map(MapMode::Direct, 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);
map(MapMode::Linear, 0x00, 0x3f, 0x0000, 0x7fff, memory::gsurom);
map(MapMode::Linear, 0x00, 0x3f, 0x8000, 0xffff, memory::gsurom);
map(MapMode::Linear, 0x40, 0x5f, 0x0000, 0xffff, memory::gsurom);
map(MapMode::Linear, 0x60, 0x7f, 0x0000, 0xffff, memory::gsuram);
}
//ROM / RAM access from the SuperFX CPU
@ -34,7 +25,7 @@ unsigned SuperFXGSUROM::size() const {
}
uint8 SuperFXGSUROM::read(unsigned addr) {
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SyncAll) {
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
superfx.add_clocks(6);
scheduler.sync_copcpu();
}
@ -42,7 +33,7 @@ uint8 SuperFXGSUROM::read(unsigned addr) {
}
void SuperFXGSUROM::write(unsigned addr, uint8 data) {
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SyncAll) {
while(!superfx.regs.scmr.ron && scheduler.sync != Scheduler::SynchronizeMode::All) {
superfx.add_clocks(6);
scheduler.sync_copcpu();
}
@ -54,7 +45,7 @@ unsigned SuperFXGSURAM::size() const {
}
uint8 SuperFXGSURAM::read(unsigned addr) {
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SyncAll) {
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
superfx.add_clocks(6);
scheduler.sync_copcpu();
}
@ -62,7 +53,7 @@ uint8 SuperFXGSURAM::read(unsigned addr) {
}
void SuperFXGSURAM::write(unsigned addr, uint8 data) {
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SyncAll) {
while(!superfx.regs.scmr.ran && scheduler.sync != Scheduler::SynchronizeMode::All) {
superfx.add_clocks(6);
scheduler.sync_copcpu();
}

View File

@ -1,5 +1,5 @@
//accepts a callback binding so r14 writes can trigger ROM buffering transparently
struct reg16_t : noncopyable {
struct reg16_t {
uint16 data;
function<void (uint16)> on_modify;
@ -29,6 +29,7 @@ struct reg16_t : noncopyable {
inline unsigned operator = (const reg16_t& i) { return assign(i); }
reg16_t() : data(0) {}
reg16_t(const reg16_t&) = delete;
};
struct sfr_t {

View File

@ -15,8 +15,8 @@ SuperFX superfx;
void SuperFX::enter() {
while(true) {
if(scheduler.sync == Scheduler::SyncAll) {
scheduler.exit(Scheduler::SynchronizeEvent);
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
if(regs.sfr.g == 0) {
@ -42,7 +42,6 @@ void SuperFX::init() {
}
void SuperFX::enable() {
for(unsigned i = 0x3000; i <= 0x32ff; i++) memory::mmio.map(i, *this);
}
void SuperFX::power() {

Some files were not shown because too many files have changed in this diff Show More