Update to v087 release.

byuu says:

This release adds ST018 emulation. As this was the final unsupported
SNES coprocessor, this means that bsnes v087 is the first SNES emulator
to be able to claim 100% known compatibility with all officially
released games. And it does this with absolutely no hacks.

Again, I really have to stress the word known. No emulator is perfect.
No emulator ever really can be perfect for a system of this complexity.
The concept doesn't even really exist, since every SNES behaves subtly
different. What I mean by this, is that every single game ever
officially sold has been tested, and zero bugs (of any severity level)
are currently known.

It is of course extremely likely that bugs will be found in this
release, as well as in future releases. But this will always be
a problem for every emulator ever made: there is no way to test every
possible codepath of every single game to guarantee perfection. I will,
of course, continue to do my best to fix newfound bugs so long as I'm
around.

I'd really like to thank Cydrak and LostTemplar for their assistance in
emulating the ST018. I could not have done it without their help.

The ST018 ROM, like the other coprocessor ROMs, is copyrighted. This
means I am unable to distribute the image.

Changelog (since v086):
- emulated the 21.47MHz ST018 (ARMv3) coprocessor used by Hayazashi
  Nidan Morita Shougi 2
- fixed PPU TM/TS edge case; fixes bottom scanline of text boxes in
  Moryo Senki Madara 2
- fixed saving and loading of Super Game Boy save RAM
- NEC uPD7725,96050 ROMs now stored in little-endian format for
  consistency
- cartridge folder concept has been reworked to use fixed file names
- added emulation of serial USART interface (replaces asynchronous UART
  support previously)
This commit is contained in:
Tim Allen 2012-03-08 00:29:38 +11:00
parent 533aa97011
commit 386ac87d21
114 changed files with 135 additions and 290 deletions

View File

@ -4,14 +4,14 @@ nes := nes
snes := snes snes := snes
gameboy := gameboy gameboy := gameboy
profile := accuracy profile := accuracy
ui := ui target := ui
# options += console # options += console
# compiler # compiler
c := $(compiler) -std=gnu99 c := $(compiler) -std=gnu99
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
flags := -I. -march=native -O3 -fomit-frame-pointer flags := -I. -O3 -fomit-frame-pointer
link := link :=
objects := libco objects := libco
@ -38,6 +38,8 @@ else
unknown_platform: help; unknown_platform: help;
endif endif
ui := target-$(target)
# implicit rules # implicit rules
compile = \ compile = \
$(strip \ $(strip \
@ -89,6 +91,6 @@ sync:
rm -r phoenix/test rm -r phoenix/test
archive-all: archive-all:
tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat purge.bat tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes target-debugger target-libsnes target-ui Makefile cc.bat purge.bat
help:; help:;

View File

@ -1,7 +1,7 @@
#ifndef BASE_HPP #ifndef BASE_HPP
#define BASE_HPP #define BASE_HPP
const char Version[] = "086.16"; const char Version[] = "087";
#include <nall/platform.hpp> #include <nall/platform.hpp>
#include <nall/algorithm.hpp> #include <nall/algorithm.hpp>

View File

@ -1,64 +1,49 @@
#ifndef NALL_BIT_HPP #ifndef NALL_BIT_HPP
#define NALL_BIT_HPP #define NALL_BIT_HPP
#include <nall/type_traits.hpp>
namespace nall { namespace nall {
template<unsigned bits, typename type_t = unsigned> template<unsigned bits>
constexpr inline constexpr inline uintmax_t uclamp(const uintmax_t x) {
typename type_if<sizeof(type_t) <= sizeof(unsigned), unsigned, uintmax_t>::type enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
uclamp(const type_t x) {
enum : type_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
return y + ((x - y) & -(x < y)); //min(x, y); return y + ((x - y) & -(x < y)); //min(x, y);
} }
template<unsigned bits, typename type_t = unsigned> template<unsigned bits>
constexpr inline constexpr inline uintmax_t uclip(const uintmax_t x) {
typename type_if<sizeof(type_t) <= sizeof(unsigned), unsigned, uintmax_t>::type enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
uclip(const type_t x) {
enum : type_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
return (x & m); return (x & m);
} }
template<unsigned bits, typename type_t = signed> template<unsigned bits>
constexpr inline constexpr inline intmax_t sclamp(const intmax_t x) {
typename type_if<sizeof(type_t) <= sizeof(signed), signed, intmax_t>::type enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 };
sclamp(const type_t x) {
enum : type_t { b = 1ull << (bits - 1), m = b - 1 };
return (x > m) ? m : (x < -b) ? -b : x; return (x > m) ? m : (x < -b) ? -b : x;
} }
template<unsigned bits, typename type_t = signed> template<unsigned bits>
constexpr inline constexpr inline intmax_t sclip(const intmax_t x) {
typename type_if<sizeof(type_t) <= sizeof(signed), signed, intmax_t>::type enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
sclip(const type_t x) {
typedef typename type_if<sizeof(type_t) <= sizeof(signed), unsigned, uintmax_t>::type cast_t;
enum : cast_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
return ((x & m) ^ b) - b; return ((x & m) ^ b) - b;
} }
namespace bit { namespace bit {
//lowest(0b1110) == 0b0010 //lowest(0b1110) == 0b0010
template<typename T> constexpr inline uintmax_t lowest(const uintmax_t x) {
constexpr inline T lowest(const T x) {
return x & -x; return x & -x;
} }
//clear_lowest(0b1110) == 0b1100 //clear_lowest(0b1110) == 0b1100
template<typename T> constexpr inline uintmax_t clear_lowest(const uintmax_t x) {
constexpr inline T clear_lowest(const T x) {
return x & (x - 1); return x & (x - 1);
} }
//set_lowest(0b0101) == 0b0111 //set_lowest(0b0101) == 0b0111
template<typename T> constexpr inline uintmax_t set_lowest(const uintmax_t x) {
constexpr inline T set_lowest(const T x) {
return x | (x + 1); return x | (x + 1);
} }
//count number of bits set in a byte //count number of bits set in a byte
template<typename T> inline unsigned count(uintmax_t x) {
inline unsigned count(T x) {
unsigned count = 0; unsigned count = 0;
do count += x & 1; while(x >>= 1); do count += x & 1; while(x >>= 1);
return count; return count;
@ -66,8 +51,7 @@ namespace nall {
//round up to next highest single bit: //round up to next highest single bit:
//round(15) == 16, round(16) == 16, round(17) == 32 //round(15) == 16, round(16) == 16, round(17) == 32
template<typename T> inline uintmax_t round(uintmax_t x) {
inline T round(T x) {
if((x & (x - 1)) == 0) return x; if((x & (x - 1)) == 0) return x;
while(x & (x - 1)) x &= x - 1; while(x & (x - 1)) x &= x - 1;
return x << 1; return x << 1;

View File

@ -420,7 +420,8 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_dsp1) { if(has_dsp1) {
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.rom' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n"); //91e87d11e1c30d172556bed2211cce2efa94ba595f58c5d264809ef4d363a97b dsp1.rom
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.rom' sha256='d789cb3c36b05c0b23b6c6f23be7aa37c6e78b6ee9ceac8d2d2aa9d8c4d35fa9'>\n");
if(dsp1_mapper == DSP1LoROM1MB) markup.append( if(dsp1_mapper == DSP1LoROM1MB) markup.append(
" <dr>\n" " <dr>\n"
" <map address='20-3f:8000-bfff'/>\n" " <map address='20-3f:8000-bfff'/>\n"
@ -455,7 +456,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
} }
if(has_dsp2) markup.append( if(has_dsp2) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.rom' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n" " <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.rom' sha256='03ef4ef26c9f701346708cb5d07847b5203cf1b0818bf2930acd34510ffdd717'>\n"
" <dr>\n" " <dr>\n"
" <map address='20-3f:8000-bfff'/>\n" " <map address='20-3f:8000-bfff'/>\n"
" <map address='a0-bf:8000-bfff'/>\n" " <map address='a0-bf:8000-bfff'/>\n"
@ -468,7 +469,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_dsp3) markup.append( if(has_dsp3) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.rom' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n" " <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.rom' sha256='0971b08f396c32e61989d1067dddf8e4b14649d548b2188f7c541b03d7c69e4e'>\n"
" <dr>\n" " <dr>\n"
" <map address='20-3f:8000-bfff'/>\n" " <map address='20-3f:8000-bfff'/>\n"
" <map address='a0-bf:8000-bfff'/>\n" " <map address='a0-bf:8000-bfff'/>\n"
@ -481,7 +482,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_dsp4) markup.append( if(has_dsp4) markup.append(
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.rom' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n" " <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.rom' sha256='752d03b2d74441e430b7f713001fa241f8bbcfc1a0d890ed4143f174dbe031da'>\n"
" <dr>\n" " <dr>\n"
" <map address='30-3f:8000-bfff'/>\n" " <map address='30-3f:8000-bfff'/>\n"
" <map address='b0-bf:8000-bfff'/>\n" " <map address='b0-bf:8000-bfff'/>\n"
@ -494,7 +495,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_st010) markup.append( if(has_st010) markup.append(
" <necdsp model='uPD96050' frequency='10000000' firmware='st010.rom' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n" " <necdsp model='uPD96050' frequency='10000000' firmware='st010.rom' sha256='fa9bced838fedea11c6f6ace33d1878024bdd0d02cc9485899d0bdd4015ec24c'>\n"
" <dr>\n" " <dr>\n"
" <map address='60:0000'/>\n" " <map address='60:0000'/>\n"
" <map address='e0:0000'/>\n" " <map address='e0:0000'/>\n"
@ -511,7 +512,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_st011) markup.append( if(has_st011) markup.append(
" <necdsp model='uPD96050' frequency='15000000' firmware='st011.rom' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n" " <necdsp model='uPD96050' frequency='15000000' firmware='st011.rom' sha256='8b2b3f3f3e6e29f4d21d8bc736b400bc988b7d2214ebee15643f01c1fee2f364'>\n"
" <dr>\n" " <dr>\n"
" <map address='60:0000'/>\n" " <map address='60:0000'/>\n"
" <map address='e0:0000'/>\n" " <map address='e0:0000'/>\n"
@ -528,7 +529,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
); );
if(has_st018) markup.append( if(has_st018) markup.append(
" <armdsp firmware='st018.rom' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'>\n" " <armdsp firmware='st018.rom' frequency='21477272' sha256='6df209ab5d2524d1839c038be400ae5eb20dafc14a3771a3239cd9e8acd53806'>\n"
" <map address='00-3f:3800-38ff'/>\n" " <map address='00-3f:3800-38ff'/>\n"
" <map address='80-bf:3800-38ff'/>\n" " <map address='80-bf:3800-38ff'/>\n"
" </armdsp>\n" " </armdsp>\n"

View File

@ -12,27 +12,27 @@ namespace nall {
public: public:
inline operator type_t() const { return data; } inline operator type_t() const { return data; }
inline type_t operator ++(int) { type_t r = data; data = uclip<bits, type_t>(data + 1); return r; } inline type_t operator ++(int) { type_t r = data; data = uclip<bits>(data + 1); return r; }
inline type_t operator --(int) { type_t r = data; data = uclip<bits, type_t>(data - 1); return r; } inline type_t operator --(int) { type_t r = data; data = uclip<bits>(data - 1); return r; }
inline type_t operator ++() { return data = uclip<bits, type_t>(data + 1); } inline type_t operator ++() { return data = uclip<bits>(data + 1); }
inline type_t operator --() { return data = uclip<bits, type_t>(data - 1); } inline type_t operator --() { return data = uclip<bits>(data - 1); }
inline type_t operator =(const type_t i) { return data = uclip<bits, type_t>(i); } inline type_t operator =(const type_t i) { return data = uclip<bits>(i); }
inline type_t operator |=(const type_t i) { return data = uclip<bits, type_t>(data | i); } inline type_t operator |=(const type_t i) { return data = uclip<bits>(data | i); }
inline type_t operator ^=(const type_t i) { return data = uclip<bits, type_t>(data ^ i); } inline type_t operator ^=(const type_t i) { return data = uclip<bits>(data ^ i); }
inline type_t operator &=(const type_t i) { return data = uclip<bits, type_t>(data & i); } inline type_t operator &=(const type_t i) { return data = uclip<bits>(data & i); }
inline type_t operator<<=(const type_t i) { return data = uclip<bits, type_t>(data << i); } inline type_t operator<<=(const type_t i) { return data = uclip<bits>(data << i); }
inline type_t operator>>=(const type_t i) { return data = uclip<bits, type_t>(data >> i); } inline type_t operator>>=(const type_t i) { return data = uclip<bits>(data >> i); }
inline type_t operator +=(const type_t i) { return data = uclip<bits, type_t>(data + i); } inline type_t operator +=(const type_t i) { return data = uclip<bits>(data + i); }
inline type_t operator -=(const type_t i) { return data = uclip<bits, type_t>(data - i); } inline type_t operator -=(const type_t i) { return data = uclip<bits>(data - i); }
inline type_t operator *=(const type_t i) { return data = uclip<bits, type_t>(data * i); } inline type_t operator *=(const type_t i) { return data = uclip<bits>(data * i); }
inline type_t operator /=(const type_t i) { return data = uclip<bits, type_t>(data / i); } inline type_t operator /=(const type_t i) { return data = uclip<bits>(data / i); }
inline type_t operator %=(const type_t i) { return data = uclip<bits, type_t>(data % i); } inline type_t operator %=(const type_t i) { return data = uclip<bits>(data % i); }
inline uint_t() : data(0) {} inline uint_t() : data(0) {}
inline uint_t(const type_t i) : data(uclip<bits, type_t>(i)) {} inline uint_t(const type_t i) : data(uclip<bits>(i)) {}
template<unsigned s> inline type_t operator=(const uint_t<s> &i) { return data = uclip<bits, type_t>((type_t)i); } template<unsigned s> inline type_t operator=(const uint_t<s> &i) { return data = uclip<bits>((type_t)i); }
template<unsigned s> inline uint_t(const uint_t<s> &i) : data(uclip<bits, type_t>(i)) {} template<unsigned s> inline uint_t(const uint_t<s> &i) : data(uclip<bits>(i)) {}
}; };
template<unsigned bits> class int_t { template<unsigned bits> class int_t {
@ -42,27 +42,27 @@ namespace nall {
public: public:
inline operator type_t() const { return data; } inline operator type_t() const { return data; }
inline type_t operator ++(int) { type_t r = data; data = sclip<bits, type_t>(data + 1); return r; } inline type_t operator ++(int) { type_t r = data; data = sclip<bits>(data + 1); return r; }
inline type_t operator --(int) { type_t r = data; data = sclip<bits, type_t>(data - 1); return r; } inline type_t operator --(int) { type_t r = data; data = sclip<bits>(data - 1); return r; }
inline type_t operator ++() { return data = sclip<bits, type_t>(data + 1); } inline type_t operator ++() { return data = sclip<bits>(data + 1); }
inline type_t operator --() { return data = sclip<bits, type_t>(data - 1); } inline type_t operator --() { return data = sclip<bits>(data - 1); }
inline type_t operator =(const type_t i) { return data = sclip<bits, type_t>(i); } inline type_t operator =(const type_t i) { return data = sclip<bits>(i); }
inline type_t operator |=(const type_t i) { return data = sclip<bits, type_t>(data | i); } inline type_t operator |=(const type_t i) { return data = sclip<bits>(data | i); }
inline type_t operator ^=(const type_t i) { return data = sclip<bits, type_t>(data ^ i); } inline type_t operator ^=(const type_t i) { return data = sclip<bits>(data ^ i); }
inline type_t operator &=(const type_t i) { return data = sclip<bits, type_t>(data & i); } inline type_t operator &=(const type_t i) { return data = sclip<bits>(data & i); }
inline type_t operator<<=(const type_t i) { return data = sclip<bits, type_t>(data << i); } inline type_t operator<<=(const type_t i) { return data = sclip<bits>(data << i); }
inline type_t operator>>=(const type_t i) { return data = sclip<bits, type_t>(data >> i); } inline type_t operator>>=(const type_t i) { return data = sclip<bits>(data >> i); }
inline type_t operator +=(const type_t i) { return data = sclip<bits, type_t>(data + i); } inline type_t operator +=(const type_t i) { return data = sclip<bits>(data + i); }
inline type_t operator -=(const type_t i) { return data = sclip<bits, type_t>(data - i); } inline type_t operator -=(const type_t i) { return data = sclip<bits>(data - i); }
inline type_t operator *=(const type_t i) { return data = sclip<bits, type_t>(data * i); } inline type_t operator *=(const type_t i) { return data = sclip<bits>(data * i); }
inline type_t operator /=(const type_t i) { return data = sclip<bits, type_t>(data / i); } inline type_t operator /=(const type_t i) { return data = sclip<bits>(data / i); }
inline type_t operator %=(const type_t i) { return data = sclip<bits, type_t>(data % i); } inline type_t operator %=(const type_t i) { return data = sclip<bits>(data % i); }
inline int_t() : data(0) {} inline int_t() : data(0) {}
inline int_t(const type_t i) : data(sclip<bits, type_t>(i)) {} inline int_t(const type_t i) : data(sclip<bits>(i)) {}
template<unsigned s> inline type_t operator=(const int_t<s> &i) { return data = sclip<bits, type_t>((type_t)i); } template<unsigned s> inline type_t operator=(const int_t<s> &i) { return data = sclip<bits>((type_t)i); }
template<unsigned s> inline int_t(const int_t<s> &i) : data(sclip<bits, type_t>(i)) {} template<unsigned s> inline int_t(const int_t<s> &i) : data(sclip<bits>(i)) {}
}; };
class varuint_t { class varuint_t {

View File

@ -5,7 +5,7 @@ snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
snes_objects += snes-icd2 snes-nss snes-superfx snes-sa1 snes_objects += snes-icd2 snes-nss snes-superfx snes-sa1
snes_objects += snes-necdsp snes-hitachidsp snes-armdsp snes_objects += snes-necdsp snes-hitachidsp snes-armdsp
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110
snes_objects += snes-obc1 snes-st0018 snes-sufamiturbo snes_objects += snes-obc1 snes-sufamiturbo
snes_objects += snes-msu1 snes-link snes_objects += snes-msu1 snes-link
objects += $(snes_objects) objects += $(snes_objects)
@ -54,7 +54,6 @@ obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/*
obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/* obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/*
obj/snes-spc7110.o : $(snes)/chip/spc7110/spc7110.cpp $(snes)/chip/spc7110/* obj/snes-spc7110.o : $(snes)/chip/spc7110/spc7110.cpp $(snes)/chip/spc7110/*
obj/snes-obc1.o : $(snes)/chip/obc1/obc1.cpp $(snes)/chip/obc1/* obj/snes-obc1.o : $(snes)/chip/obc1/obc1.cpp $(snes)/chip/obc1/*
obj/snes-st0018.o : $(snes)/chip/st0018/st0018.cpp $(snes)/chip/st0018/*
obj/snes-sufamiturbo.o: $(snes)/chip/sufamiturbo/sufamiturbo.cpp $(snes)/chip/sufamiturbo/* obj/snes-sufamiturbo.o: $(snes)/chip/sufamiturbo/sufamiturbo.cpp $(snes)/chip/sufamiturbo/*
obj/snes-msu1.o : $(snes)/chip/msu1/msu1.cpp $(snes)/chip/msu1/* obj/snes-msu1.o : $(snes)/chip/msu1/msu1.cpp $(snes)/chip/msu1/*
obj/snes-link.o : $(snes)/chip/link/link.cpp $(snes)/chip/link/* obj/snes-link.o : $(snes)/chip/link/link.cpp $(snes)/chip/link/*

View File

@ -28,7 +28,6 @@ void Cartridge::load(Mode cartridge_mode, const char *markup) {
has_spc7110 = false; has_spc7110 = false;
has_spc7110rtc = false; has_spc7110rtc = false;
has_obc1 = false; has_obc1 = false;
has_st0018 = false;
has_msu1 = false; has_msu1 = false;
has_link = false; has_link = false;

View File

@ -44,7 +44,6 @@ struct Cartridge : property<Cartridge> {
readonly<bool> has_spc7110; readonly<bool> has_spc7110;
readonly<bool> has_spc7110rtc; readonly<bool> has_spc7110rtc;
readonly<bool> has_obc1; readonly<bool> has_obc1;
readonly<bool> has_st0018;
readonly<bool> has_msu1; readonly<bool> has_msu1;
readonly<bool> has_link; readonly<bool> has_link;
@ -109,7 +108,6 @@ private:
void parse_markup_sdd1(XML::Node&); void parse_markup_sdd1(XML::Node&);
void parse_markup_spc7110(XML::Node&); void parse_markup_spc7110(XML::Node&);
void parse_markup_obc1(XML::Node&); void parse_markup_obc1(XML::Node&);
void parse_markup_setarisc(XML::Node&);
void parse_markup_msu1(XML::Node&); void parse_markup_msu1(XML::Node&);
void parse_markup_link(XML::Node&); void parse_markup_link(XML::Node&);
}; };

View File

@ -23,7 +23,6 @@ void Cartridge::parse_markup(const char *markup) {
parse_markup_sdd1(cartridge["sdd1"]); parse_markup_sdd1(cartridge["sdd1"]);
parse_markup_spc7110(cartridge["spc7110"]); parse_markup_spc7110(cartridge["spc7110"]);
parse_markup_obc1(cartridge["obc1"]); parse_markup_obc1(cartridge["obc1"]);
parse_markup_setarisc(cartridge["setarisc"]);
parse_markup_msu1(cartridge["msu1"]); parse_markup_msu1(cartridge["msu1"]);
parse_markup_link(cartridge["link"]); parse_markup_link(cartridge["link"]);
} }
@ -236,8 +235,8 @@ void Cartridge::parse_markup_necdsp(XML::Node &root) {
interface->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." }); interface->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." });
fp.close(); fp.close();
} else { } else {
for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readm(3); for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readl(3);
for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readm(2); for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readl(2);
if(!sha256.empty()) { if(!sha256.empty()) {
//XML file specified SHA256 sum for program. Verify file matches the hash. //XML file specified SHA256 sum for program. Verify file matches the hash.
@ -460,6 +459,7 @@ void Cartridge::parse_markup_sdd1(XML::Node &root) {
void Cartridge::parse_markup_spc7110(XML::Node &root) { void Cartridge::parse_markup_spc7110(XML::Node &root) {
if(root.exists() == false) return; if(root.exists() == false) return;
has_spc7110 = true; has_spc7110 = true;
has_spc7110rtc = root["rtc"].exists();
auto &ram = root["ram"]; auto &ram = root["ram"];
auto &mmio = root["mmio"]; auto &mmio = root["mmio"];
@ -518,18 +518,6 @@ void Cartridge::parse_markup_obc1(XML::Node &root) {
} }
} }
void Cartridge::parse_markup_setarisc(XML::Node &root) {
if(root.exists() == false) return;
has_st0018 = true;
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m({ &ST0018::mmio_read, &st0018 }, { &ST0018::mmio_write, &st0018 });
parse_markup_map(m, node);
mapping.append(m);
}
}
void Cartridge::parse_markup_msu1(XML::Node &root) { void Cartridge::parse_markup_msu1(XML::Node &root) {
if(root.exists() == false) { if(root.exists() == false) {
has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, "msu1.rom")); has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, "msu1.rom"));

View File

@ -107,6 +107,8 @@ struct Register {
} r[16]; } r[16];
bool shiftercarry; bool shiftercarry;
uint32 instruction;
bool exception;
struct Pipeline { struct Pipeline {
bool reload; bool reload;
@ -118,6 +120,3 @@ struct Pipeline {
Instruction prefetch; Instruction prefetch;
Instruction mdr; Instruction mdr;
} pipeline; } pipeline;
uint32 instruction;
bool exception;

View File

@ -2,6 +2,63 @@
void ArmDSP::serialize(serializer &s) { void ArmDSP::serialize(serializer &s) {
Processor::serialize(s); Processor::serialize(s);
s.array(programRAM, 16 * 1024);
s.integer(bridge.cputoarm.ready);
s.integer(bridge.cputoarm.data);
s.integer(bridge.armtocpu.ready);
s.integer(bridge.armtocpu.data);
s.integer(bridge.timer);
s.integer(bridge.timerlatch);
s.integer(bridge.reset);
s.integer(bridge.ready);
s.integer(bridge.busy);
s.integer(cpsr.n);
s.integer(cpsr.z);
s.integer(cpsr.c);
s.integer(cpsr.v);
s.integer(cpsr.i);
s.integer(cpsr.f);
s.integer(cpsr.m);
s.integer(spsr.n);
s.integer(spsr.z);
s.integer(spsr.c);
s.integer(spsr.v);
s.integer(spsr.i);
s.integer(spsr.f);
s.integer(spsr.m);
s.integer(r[ 0].data);
s.integer(r[ 1].data);
s.integer(r[ 2].data);
s.integer(r[ 3].data);
s.integer(r[ 4].data);
s.integer(r[ 5].data);
s.integer(r[ 6].data);
s.integer(r[ 7].data);
s.integer(r[ 8].data);
s.integer(r[ 9].data);
s.integer(r[10].data);
s.integer(r[11].data);
s.integer(r[12].data);
s.integer(r[13].data);
s.integer(r[14].data);
s.integer(r[15].data);
s.integer(shiftercarry);
s.integer(instruction);
s.integer(exception);
s.integer(pipeline.reload);
s.integer(pipeline.instruction.opcode);
s.integer(pipeline.instruction.address);
s.integer(pipeline.prefetch.opcode);
s.integer(pipeline.prefetch.address);
s.integer(pipeline.mdr.opcode);
s.integer(pipeline.mdr.address);
} }
#endif #endif

View File

@ -18,7 +18,6 @@ struct Coprocessor : Processor {
#include <snes/chip/sdd1/sdd1.hpp> #include <snes/chip/sdd1/sdd1.hpp>
#include <snes/chip/spc7110/spc7110.hpp> #include <snes/chip/spc7110/spc7110.hpp>
#include <snes/chip/obc1/obc1.hpp> #include <snes/chip/obc1/obc1.hpp>
#include <snes/chip/st0018/st0018.hpp>
#include <snes/chip/sufamiturbo/sufamiturbo.hpp> #include <snes/chip/sufamiturbo/sufamiturbo.hpp>
#include <snes/chip/msu1/msu1.hpp> #include <snes/chip/msu1/msu1.hpp>
#include <snes/chip/link/link.hpp> #include <snes/chip/link/link.hpp>

View File

@ -15,7 +15,7 @@ void SPC7110::init() {
void SPC7110::load() { void SPC7110::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ ".rtc", rtc, 20 }); if(cartridge.has_spc7110rtc()) cartridge.nvram.append({ "program.rtc", rtc, 20 });
} }
void SPC7110::unload() { void SPC7110::unload() {

View File

@ -14,7 +14,7 @@ void SRTC::init() {
void SRTC::load() { void SRTC::load() {
for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff; for(unsigned n = 0; n < 20; n++) rtc[n] = 0xff;
cartridge.nvram.append({ ".rtc", rtc, 20 }); cartridge.nvram.append({ "program.rtc", rtc, 20 });
} }
void SRTC::unload() { void SRTC::unload() {

View File

@ -1,125 +0,0 @@
#include <snes/snes.hpp>
#define ST0018_CPP
namespace SNES {
ST0018 st0018;
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 ST0018::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;
if(addr == 0x3802) {
switch(regs.mode) {
case Waiting: {
switch(data) {
case 0x01: regs.r3800 = regs.r3800_01; break;
case 0xaa: op_board_upload(); break;
case 0xb2: op_b2(); break;
case 0xb3: op_b3(); break;
case 0xb4: op_b4(); break;
case 0xb5: op_b5(); break;
case 0xf1: op_query_chip(); break;
case 0xf2: op_query_chip(); break;
default: fprintf(stdout, "* ST018 w3802::%.2x\n", data); break;
}
} return;
case BoardUpload: {
op_board_upload(data);
} return;
}
}
if(addr == 0x3804) {
regs.w3804 <<= 8;
regs.w3804 |= data;
regs.w3804 &= 0xffffff;
return;
}
}
void ST0018::init() {
}
void ST0018::load() {
}
void ST0018::unload() {
}
void ST0018::power() {
}
void ST0018::reset() {
regs.mode = Waiting;
regs.r3800 = 0x00;
regs.r3804 = 0x85;
regs.w3804 = 0;
for(unsigned i = 0; i < 97; i++) board[i] = 0;
}
//===============
//ST-0018 opcodes
//===============
void ST0018::op_board_upload() {
regs.mode = BoardUpload;
regs.counter = 0;
regs.r3800 = 0xe0;
}
void ST0018::op_board_upload(uint8 data) {
board[regs.counter] = data;
regs.r3800 = 96 - regs.counter;
regs.counter++;
if(regs.counter >= 97) {
regs.mode = Waiting;
#if 0
for(unsigned y = 0; y < 9; y++) {
for(unsigned x = 0; x < 9; x++) {
fprintf(stdout, "%.2x ", board[y * 9 + x]);
}
fprintf(stdout, "\n");
}
for(unsigned n = 0; n < 16; n++) fprintf(stdout, "%.2x ", board[81 + n]);
fprintf(stdout, "\n\n");
#endif
}
}
void ST0018::op_b2() {
fprintf(stdout, "* ST018 w3802::b2\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 0; //unknown
}
void ST0018::op_b3() {
fprintf(stdout, "* ST018 w3802::b3\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 1; //0 = player lost?
}
void ST0018::op_b4() {
fprintf(stdout, "* ST018 w3802::b4\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 1; //0 = player won?
}
void ST0018::op_b5() {
fprintf(stdout, "* ST018 w3802::b5\n");
regs.r3800 = 0xe0;
regs.r3800_01 = 0; //1 = move will result in checkmate?
}
void ST0018::op_query_chip() {
regs.r3800 = 0x00;
}
}

View File

@ -1,52 +0,0 @@
class ST0018 {
public:
void init();
void load();
void unload();
void power();
void reset();
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
enum mode_t { Waiting, BoardUpload };
struct regs_t {
mode_t mode;
uint8 r3800;
uint8 r3800_01;
uint8 r3804;
unsigned w3804;
unsigned counter;
} regs;
enum PieceID {
Pawn = 0x00, //foot soldier
Lance = 0x04, //incense chariot
Knight = 0x08, //cassia horse
Silver = 0x0c, //silver general
Gold = 0x10, //gold general
Rook = 0x14, //flying chariot
Bishop = 0x18, //angle mover
King = 0x1c, //king
};
enum PieceFlag {
PlayerA = 0x20,
PlayerB = 0x40,
};
uint8 board[9 * 9 + 16];
private:
void op_board_upload();
void op_board_upload(uint8 data);
void op_b2();
void op_b3();
void op_b4();
void op_b5();
void op_query_chip();
};
extern ST0018 st0018;

View File

@ -44,8 +44,8 @@ void USART::write(uint8 data) {
//clock //clock
uint2 USART::data() { uint2 USART::data() {
//SNES -> USART //SNES -> USART
if(txlength == 0 && latched == 0) { if(txlength == 0) {
txlength++; if(latched == 0) txlength++;
} else if(txlength <= 8) { } else if(txlength <= 8) {
txdata = (latched << 7) | (txdata >> 1); txdata = (latched << 7) | (txdata >> 1);
txlength++; txlength++;

View File

@ -80,7 +80,6 @@ void System::init() {
sdd1.init(); sdd1.init();
spc7110.init(); spc7110.init();
obc1.init(); obc1.init();
st0018.init();
msu1.init(); msu1.init();
link.init(); link.init();
@ -121,7 +120,6 @@ void System::load() {
if(cartridge.has_sdd1()) sdd1.load(); if(cartridge.has_sdd1()) sdd1.load();
if(cartridge.has_spc7110()) spc7110.load(); if(cartridge.has_spc7110()) spc7110.load();
if(cartridge.has_obc1()) obc1.load(); if(cartridge.has_obc1()) obc1.load();
if(cartridge.has_st0018()) st0018.load();
if(cartridge.has_msu1()) msu1.load(); if(cartridge.has_msu1()) msu1.load();
if(cartridge.has_link()) link.load(); if(cartridge.has_link()) link.load();
@ -148,7 +146,6 @@ void System::unload() {
if(cartridge.has_sdd1()) sdd1.unload(); if(cartridge.has_sdd1()) sdd1.unload();
if(cartridge.has_spc7110()) spc7110.unload(); if(cartridge.has_spc7110()) spc7110.unload();
if(cartridge.has_obc1()) obc1.unload(); if(cartridge.has_obc1()) obc1.unload();
if(cartridge.has_st0018()) st0018.unload();
if(cartridge.has_msu1()) msu1.unload(); if(cartridge.has_msu1()) msu1.unload();
if(cartridge.has_link()) link.unload(); if(cartridge.has_link()) link.unload();
} }
@ -187,7 +184,6 @@ void System::power() {
if(cartridge.has_sdd1()) sdd1.power(); if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_spc7110()) spc7110.power(); if(cartridge.has_spc7110()) spc7110.power();
if(cartridge.has_obc1()) obc1.power(); if(cartridge.has_obc1()) obc1.power();
if(cartridge.has_st0018()) st0018.power();
if(cartridge.has_msu1()) msu1.power(); if(cartridge.has_msu1()) msu1.power();
if(cartridge.has_link()) link.power(); if(cartridge.has_link()) link.power();
@ -218,7 +214,6 @@ void System::reset() {
if(cartridge.has_sdd1()) sdd1.reset(); if(cartridge.has_sdd1()) sdd1.reset();
if(cartridge.has_spc7110()) spc7110.reset(); if(cartridge.has_spc7110()) spc7110.reset();
if(cartridge.has_obc1()) obc1.reset(); if(cartridge.has_obc1()) obc1.reset();
if(cartridge.has_st0018()) st0018.reset();
if(cartridge.has_msu1()) msu1.reset(); if(cartridge.has_msu1()) msu1.reset();
if(cartridge.has_link()) link.reset(); if(cartridge.has_link()) link.reset();

View File

@ -226,6 +226,7 @@ void InterfaceSNES::run() {
string InterfaceSNES::memoryName(SNES::Cartridge::NonVolatileRAM &memory) { string InterfaceSNES::memoryName(SNES::Cartridge::NonVolatileRAM &memory) {
if(memory.slot == SNES::Cartridge::Slot::Base) { if(memory.slot == SNES::Cartridge::Slot::Base) {
if(memory.id == "program.ram") return interface->base.filename("program.ram", ".srm"); if(memory.id == "program.ram") return interface->base.filename("program.ram", ".srm");
if(memory.id == "program.rtc") return interface->base.filename("program.rtc", ".rtc");
if(memory.id == "upd96050.ram") return interface->base.filename("upd96050.ram", ".nec"); if(memory.id == "upd96050.ram") return interface->base.filename("upd96050.ram", ".nec");
if(memory.id == "bsx.ram") return interface->base.filename("bsx.ram", ".bss"); if(memory.id == "bsx.ram") return interface->base.filename("bsx.ram", ".bss");
if(memory.id == "bsx.psram") return interface->base.filename("bsx.psram", ".bsp"); if(memory.id == "bsx.psram") return interface->base.filename("bsx.psram", ".bsp");

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