mirror of https://github.com/bsnes-emu/bsnes.git
Update to v092 release.
In the release thread, byuu says: The first official release of higan has been posted. higan is the new name for bsnes, and it continues with the latter's version numbering. Note that as of now, bsnes still exists. It's a module distributed inside of higan. bsnes is now specific to my SNES emulator. Due to last minute changes to the emulator interface, and missing support in ananke, I wasn't able to include Cydrak's Nintendo DS emulator dasShiny in this build, but I hope to do so in the next release. http://code.google.com/p/higan/downloads/list For both new and experienced users, please read the higan user guide first: http://byuu.org/higan/user-guide In the v091 WIP thread, byuu says: r15->r16: - BS-X MaskROM handling (partial ... need to split bsx/flash away from sfc/chip, restructure code - it requires tagging the base cart markup for now, but it needs to parse the slotted cart markup) - phoenixflags / phoenixlink += -m32 - nall/sort stability - if(input.poll(scancode[activeScancode]) == false) return; - MSU1 / USART need to use interface->path(1) - MSU1 needs to use Markup::Document, not XML::Document - case-insensitive folder listings - remove nall/emulation/system.hpp files (move to ananke) - remove rom/ram id= checks with indexing X have cores ask for manifest.bml (skipped for v092's release, too big a change) - rename compatibility profile to balanced (so people don't assume it has better compatibility than accuracy)
This commit is contained in:
parent
b389d17c9a
commit
032e924495
|
@ -2,11 +2,20 @@ include nall/Makefile
|
||||||
include phoenix/Makefile
|
include phoenix/Makefile
|
||||||
|
|
||||||
path := /usr/local/lib
|
path := /usr/local/lib
|
||||||
flags := -std=gnu++11 -I. -O3 -fomit-frame-pointer
|
flags := -I. -O3 -fomit-frame-pointer
|
||||||
|
ifeq ($(arch),win32)
|
||||||
|
flags := -m32 $(flags)
|
||||||
|
endif
|
||||||
|
|
||||||
all:
|
all:
|
||||||
$(cpp) $(flags) -fPIC -o ananke.o -c ananke.cpp
|
$(cpp) $(flags) -fPIC -o ananke.o -c ananke.cpp
|
||||||
|
ifeq ($(platform),x)
|
||||||
$(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so ananke.o
|
$(cpp) $(flags) -shared -Wl,-soname,libananke.so.1 -o libananke.so ananke.o
|
||||||
|
else ifeq ($(platform),win)
|
||||||
|
$(cpp) $(flags) -fPIC -o phoenix.o -c phoenix/phoenix.cpp $(phoenixflags)
|
||||||
|
$(cpp) $(flags) -shared -o phoenix.dll phoenix.o $(phoenixlink)
|
||||||
|
$(cpp) $(flags) -shared -o ananke.dll ananke.o -L. -lphoenix
|
||||||
|
endif
|
||||||
|
|
||||||
resource: force
|
resource: force
|
||||||
sourcery resource/resource.bml resource/resource.cpp resource/resource.hpp
|
sourcery resource/resource.bml resource/resource.cpp resource/resource.hpp
|
||||||
|
@ -16,13 +25,17 @@ clean:
|
||||||
-@$(call delete,*.so)
|
-@$(call delete,*.so)
|
||||||
|
|
||||||
install: uninstall
|
install: uninstall
|
||||||
|
ifeq ($(platform),x)
|
||||||
if [ ! -d ~/.config/ananke ]; then mkdir ~/.config/ananke; fi
|
if [ ! -d ~/.config/ananke ]; then mkdir ~/.config/ananke; fi
|
||||||
sudo cp libananke.so $(path)/libananke.so.1
|
sudo cp libananke.so $(path)/libananke.so.1
|
||||||
sudo ln -s $(path)/libananke.so.1 $(path)/libananke.so
|
sudo ln -s $(path)/libananke.so.1 $(path)/libananke.so
|
||||||
|
endif
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
|
ifeq ($(platform),x)
|
||||||
if [ -f $(path)/libananke.so ]; then sudo rm $(path)/libananke.so; fi
|
if [ -f $(path)/libananke.so ]; then sudo rm $(path)/libananke.so; fi
|
||||||
if [ -f $(path)/libananke.so.1 ]; then sudo rm $(path)/libananke.so.1; fi
|
if [ -f $(path)/libananke.so.1 ]; then sudo rm $(path)/libananke.so.1; fi
|
||||||
|
endif
|
||||||
|
|
||||||
sync:
|
sync:
|
||||||
ifeq ($(shell id -un),byuu)
|
ifeq ($(shell id -un),byuu)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#include <nall/nall.hpp>
|
#include <nall/nall.hpp>
|
||||||
#include <nall/beat/patch.hpp>
|
#include <nall/beat/patch.hpp>
|
||||||
#include <nall/emulation/famicom.hpp>
|
#include "heuristics/famicom.hpp"
|
||||||
#include <nall/emulation/super-famicom.hpp>
|
#include "heuristics/super-famicom.hpp"
|
||||||
#include <nall/emulation/game-boy.hpp>
|
#include "heuristics/game-boy.hpp"
|
||||||
#include <nall/emulation/game-boy-advance.hpp>
|
#include "heuristics/game-boy-advance.hpp"
|
||||||
using namespace nall;
|
using namespace nall;
|
||||||
|
|
||||||
#include <phoenix/phoenix.hpp>
|
#include <phoenix/phoenix.hpp>
|
||||||
|
@ -12,6 +12,7 @@ using namespace phoenix;
|
||||||
namespace Database {
|
namespace Database {
|
||||||
#include "database/super-famicom.hpp"
|
#include "database/super-famicom.hpp"
|
||||||
#include "database/sufami-turbo.hpp"
|
#include "database/sufami-turbo.hpp"
|
||||||
|
#include "database/bsx-satellaview.hpp"
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ananke {
|
struct Ananke {
|
||||||
|
@ -49,6 +50,11 @@ struct Ananke {
|
||||||
string createSufamiTurboHeuristic(vector<uint8_t> &buffer);
|
string createSufamiTurboHeuristic(vector<uint8_t> &buffer);
|
||||||
string openSufamiTurbo(vector<uint8_t> &buffer);
|
string openSufamiTurbo(vector<uint8_t> &buffer);
|
||||||
|
|
||||||
|
//bsx-satellaview.cpp
|
||||||
|
string createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest);
|
||||||
|
string createBsxSatellaviewHeuristic(vector<uint8_t> &buffer);
|
||||||
|
string openBsxSatellaview(vector<uint8_t> &buffer);
|
||||||
|
|
||||||
//game-boy.cpp
|
//game-boy.cpp
|
||||||
void copyGameBoySaves(const string &pathname);
|
void copyGameBoySaves(const string &pathname);
|
||||||
string createGameBoyHeuristic(vector<uint8_t> &buffer);
|
string createGameBoyHeuristic(vector<uint8_t> &buffer);
|
||||||
|
@ -70,6 +76,7 @@ struct Ananke {
|
||||||
#include "famicom.cpp"
|
#include "famicom.cpp"
|
||||||
#include "super-famicom.cpp"
|
#include "super-famicom.cpp"
|
||||||
#include "sufami-turbo.cpp"
|
#include "sufami-turbo.cpp"
|
||||||
|
#include "bsx-satellaview.cpp"
|
||||||
#include "game-boy.cpp"
|
#include "game-boy.cpp"
|
||||||
#include "game-boy-advance.cpp"
|
#include "game-boy-advance.cpp"
|
||||||
|
|
||||||
|
@ -82,8 +89,8 @@ bool Ananke::supported(const string &filename) {
|
||||||
if(extension == "nes") return true;
|
if(extension == "nes") return true;
|
||||||
if(extension == "sfc") return true;
|
if(extension == "sfc") return true;
|
||||||
if(extension == "smc") return true;
|
if(extension == "smc") return true;
|
||||||
if(extension == "bs" ) return true;
|
|
||||||
if(extension == "st" ) return true;
|
if(extension == "st" ) return true;
|
||||||
|
if(extension == "bs" ) return true;
|
||||||
if(extension == "gb" ) return true;
|
if(extension == "gb" ) return true;
|
||||||
if(extension == "gbc") return true;
|
if(extension == "gbc") return true;
|
||||||
if(extension == "gba") return true;
|
if(extension == "gba") return true;
|
||||||
|
@ -119,6 +126,7 @@ string Ananke::open(string filename) {
|
||||||
if(information.name.endswith(".fc") || information.name.endswith(".nes")) return openFamicom(buffer);
|
if(information.name.endswith(".fc") || information.name.endswith(".nes")) return openFamicom(buffer);
|
||||||
if(information.name.endswith(".sfc") || information.name.endswith(".smc")) return openSuperFamicom(buffer);
|
if(information.name.endswith(".sfc") || information.name.endswith(".smc")) return openSuperFamicom(buffer);
|
||||||
if(information.name.endswith(".st")) return openSufamiTurbo(buffer);
|
if(information.name.endswith(".st")) return openSufamiTurbo(buffer);
|
||||||
|
if(information.name.endswith(".bs")) return openBsxSatellaview(buffer);
|
||||||
if(information.name.endswith(".gb") || information.name.endswith(".gbc")) return openGameBoy(buffer);
|
if(information.name.endswith(".gb") || information.name.endswith(".gbc")) return openGameBoy(buffer);
|
||||||
if(information.name.endswith(".gba")) return openGameBoyAdvance(buffer);
|
if(information.name.endswith(".gba")) return openGameBoyAdvance(buffer);
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
string Ananke::createBsxSatellaviewDatabase(vector<uint8_t> &buffer, Markup::Node &document, const string &manifest) {
|
||||||
|
string pathname = {
|
||||||
|
userpath(), "Emulation/BS-X Satellaview/",
|
||||||
|
document["release/information/name"].text(),
|
||||||
|
" (", document["release/information/region"].text(), ")",
|
||||||
|
" (", document["release/information/revision"].text(), ")",
|
||||||
|
".bs/"
|
||||||
|
};
|
||||||
|
directory::create(pathname);
|
||||||
|
|
||||||
|
//strip "release" root node from database entry (since a single game manifest isn't part of a database)
|
||||||
|
string markup = manifest;
|
||||||
|
markup.replace("\n ", "\n");
|
||||||
|
markup.replace("information", "\ninformation");
|
||||||
|
markup.ltrim<1>("release\n");
|
||||||
|
|
||||||
|
file::write({pathname, "manifest.bml"}, markup);
|
||||||
|
file::write({pathname, "program.rom"}, buffer);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string Ananke::createBsxSatellaviewHeuristic(vector<uint8_t> &buffer) {
|
||||||
|
string pathname = {
|
||||||
|
userpath(), "Emulation/BS-X Satellaview/",
|
||||||
|
nall::basename(information.name),
|
||||||
|
" (!).bs/"
|
||||||
|
};
|
||||||
|
directory::create(pathname);
|
||||||
|
|
||||||
|
file::write({pathname, "manifest.bml"}, {
|
||||||
|
"cartridge\n"
|
||||||
|
" rom name=program.rom size=0x", hex(buffer.size()), " type=FlashROM\n",
|
||||||
|
"\n",
|
||||||
|
"information\n",
|
||||||
|
" title: ", nall::basename(information.name), "\n"
|
||||||
|
});
|
||||||
|
file::write({pathname, "program.rom"}, buffer);
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
string Ananke::openBsxSatellaview(vector<uint8_t> &buffer) {
|
||||||
|
string sha256 = nall::sha256(buffer.data(), buffer.size());
|
||||||
|
|
||||||
|
string databaseText = string::read({configpath(), "ananke/database/BS-X Satellaview.bml"}).strip();
|
||||||
|
if(databaseText.empty()) databaseText = string{Database::BsxSatellaview}.strip();
|
||||||
|
lstring databaseItem = databaseText.split("\n\n");
|
||||||
|
|
||||||
|
for(auto &item : databaseItem) {
|
||||||
|
item.append("\n");
|
||||||
|
auto document = Markup::Document(item);
|
||||||
|
|
||||||
|
if(document["release/information/sha256"].text() == sha256) {
|
||||||
|
return createBsxSatellaviewDatabase(buffer, document, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createBsxSatellaviewHeuristic(buffer);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
string BsxSatellaview = R"(
|
||||||
|
|
||||||
|
database revision=2013-01-12
|
||||||
|
|
||||||
|
release
|
||||||
|
cartridge
|
||||||
|
rom name=program.rom size=0x80000 type=MaskROM
|
||||||
|
information
|
||||||
|
title: 鮫亀 キャラカセット
|
||||||
|
name: Same Game - Character Cassette
|
||||||
|
region: JP
|
||||||
|
revision: 1.0
|
||||||
|
board: BSMC-CR-01
|
||||||
|
serial: BSMC-ZS5J-JPN
|
||||||
|
sha256: 80c34b50817d58820bc8c88d2d9fa462550b4a76372e19c6467cbfbc8cf5d9ef
|
||||||
|
configuration
|
||||||
|
rom name=program.rom size=0x80000 type=MaskROM
|
||||||
|
|
||||||
|
)";
|
|
@ -1,9 +1,9 @@
|
||||||
string SufamiTurbo = R"(
|
string SufamiTurbo = R"(
|
||||||
|
|
||||||
database revision=2012-12-24
|
database revision=2013-01-12
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
information
|
information
|
||||||
|
@ -16,9 +16,10 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
information
|
information
|
||||||
|
@ -31,9 +32,10 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
information
|
information
|
||||||
|
@ -46,13 +48,14 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x800
|
ram name=save.ram size=0x800
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
information
|
information
|
||||||
title: SDガンダムジェネレーション 一年戦争機
|
title: SDガンダムジェネレーション 一年戦争記
|
||||||
name: SD Gundam Generation - Ichinen Sensouki
|
name: SD Gundam Generation - Ichinen Sensouki
|
||||||
region: JP
|
region: JP
|
||||||
revision: 1.0
|
revision: 1.0
|
||||||
|
@ -61,9 +64,10 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
information
|
information
|
||||||
|
@ -76,13 +80,14 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
information
|
information
|
||||||
title: ゲゲゲの鬼太郎 妖怪ドンジャン
|
title: ゲゲゲの鬼太郎 妖怪ドンジャラ
|
||||||
name: Gegege no Kitarou - Youkai Dungeon
|
name: Gegege no Kitarou - Youkai Donjara
|
||||||
region: JP
|
region: JP
|
||||||
revision: 1.0
|
revision: 1.0
|
||||||
serial: SFT-0106-JPN
|
serial: SFT-0106-JPN
|
||||||
|
@ -91,7 +96,7 @@ release
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
information
|
information
|
||||||
|
@ -104,9 +109,10 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
information
|
information
|
||||||
|
@ -119,9 +125,10 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
information
|
information
|
||||||
|
@ -134,20 +141,22 @@ release
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x2000
|
||||||
|
linkable
|
||||||
|
|
||||||
release
|
release
|
||||||
cartridge region=NTSC
|
cartridge linkable
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x800
|
||||||
information
|
information
|
||||||
title: SDガンダムジェネレーション コロニア格闘記
|
title: SDガンダムジェネレーション コロニー格闘記
|
||||||
name: SD Gundam Generation - Colonia Kakotouki
|
name: SD Gundam Generation - Colony Kakutouki
|
||||||
region: JP
|
region: JP
|
||||||
revision: 1.0
|
revision: 1.0
|
||||||
serial: SFT-0111-JPN
|
serial: SFT-0111-JPN
|
||||||
sha256: e639b5d5d722432b6809ccc6801dc584e1a3016379f34b335ed2dfa73b1ebf69
|
sha256: e639b5d5d722432b6809ccc6801dc584e1a3016379f34b335ed2dfa73b1ebf69
|
||||||
configuration
|
configuration
|
||||||
rom name=program.rom size=0x80000
|
rom name=program.rom size=0x80000
|
||||||
ram name=save.ram size=0x2000
|
ram name=save.ram size=0x800
|
||||||
|
linkable
|
||||||
|
|
||||||
)";
|
)";
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -74,7 +74,7 @@ struct FileDialog : Window {
|
||||||
layout.setMargin(5);
|
layout.setMargin(5);
|
||||||
homeButton.setImage({resource::home, sizeof resource::home});
|
homeButton.setImage({resource::home, sizeof resource::home});
|
||||||
upButton.setImage({resource::up, sizeof resource::up});
|
upButton.setImage({resource::up, sizeof resource::up});
|
||||||
filterLabel.setText("Filter: *.fc, *.sfc, *.bs, *.st, *.gb, *.gbc, *.gba, *.nes, *.smc, *.zip");
|
filterLabel.setText("Filter: *.fc, *.sfc, *.st, *.bs, *.gb, *.gbc, *.gba, *.nes, *.smc, *.zip");
|
||||||
openButton.setText("Open");
|
openButton.setText("Open");
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace nall {
|
||||||
for(signed i = 1, j; i < size; i++) {
|
for(signed i = 1, j; i < size; i++) {
|
||||||
T copy = std::move(list[i]);
|
T copy = std::move(list[i]);
|
||||||
for(j = i - 1; j >= 0; j--) {
|
for(j = i - 1; j >= 0; j--) {
|
||||||
if(lessthan(list[j], copy)) break;
|
if(!lessthan(copy, list[j])) break;
|
||||||
list[j + 1] = std::move(list[j]);
|
list[j + 1] = std::move(list[j]);
|
||||||
}
|
}
|
||||||
list[j + 1] = std::move(copy);
|
list[j + 1] = std::move(copy);
|
||||||
|
@ -55,7 +55,7 @@ namespace nall {
|
||||||
T *buffer = new T[size];
|
T *buffer = new T[size];
|
||||||
unsigned offset = 0, left = 0, right = middle;
|
unsigned offset = 0, left = 0, right = middle;
|
||||||
while(left < middle && right < size) {
|
while(left < middle && right < size) {
|
||||||
if(lessthan(list[left], list[right])) {
|
if(!lessthan(list[right], list[left])) {
|
||||||
buffer[offset++] = std::move(list[left++]);
|
buffer[offset++] = std::move(list[left++]);
|
||||||
} else {
|
} else {
|
||||||
buffer[offset++] = std::move(list[right++]);
|
buffer[offset++] = std::move(list[right++]);
|
||||||
|
|
|
@ -74,7 +74,8 @@ char* integer(char *result, intmax_t value) {
|
||||||
buffer[size++] = '0' + n;
|
buffer[size++] = '0' + n;
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size++] = negative ? '-' : '+';
|
if(negative) buffer[size++] = '-';
|
||||||
|
//buffer[size++] = negative ? '-' : '+';
|
||||||
|
|
||||||
for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
|
for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y];
|
||||||
result[size] = 0;
|
result[size] = 0;
|
||||||
|
@ -110,7 +111,8 @@ template<unsigned length_, char padding> string integer(intmax_t value) {
|
||||||
buffer[size++] = '0' + n;
|
buffer[size++] = '0' + n;
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size++] = negative ? '-' : '+';
|
if(negative) buffer[size++] = '-';
|
||||||
|
//buffer[size++] = negative ? '-' : '+';
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
|
|
||||||
unsigned length = (length_ == 0 ? size : length_);
|
unsigned length = (length_ == 0 ? size : length_);
|
||||||
|
@ -137,7 +139,8 @@ template<unsigned length_, char padding> string linteger(intmax_t value) {
|
||||||
buffer[size++] = '0' + n;
|
buffer[size++] = '0' + n;
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size++] = negative ? '-' : '+';
|
if(negative) buffer[size++] = '-';
|
||||||
|
//buffer[size++] = negative ? '-' : '+';
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
|
|
||||||
unsigned length = (length_ == 0 ? size : length_);
|
unsigned length = (length_ == 0 ? size : length_);
|
||||||
|
|
|
@ -15,6 +15,11 @@ ifeq ($(platform),x)
|
||||||
else ifeq ($(platform),win)
|
else ifeq ($(platform),win)
|
||||||
phoenixflags := -DPHOENIX_WINDOWS
|
phoenixflags := -DPHOENIX_WINDOWS
|
||||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||||
|
|
||||||
|
ifeq ($(arch),win32)
|
||||||
|
phoenixflags := -m32 $(phoenixflags)
|
||||||
|
phoenixlink := -m32 $(phoenixlink)
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
phoenixflags := -DPHOENIX_REFERENCE
|
phoenixflags := -DPHOENIX_REFERENCE
|
||||||
phoenixlink :=
|
phoenixlink :=
|
||||||
|
|
|
@ -173,6 +173,10 @@ void OS::quit() {
|
||||||
return pOS::quit();
|
return pOS::quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS::setName(const string &name) {
|
||||||
|
osState.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
void OS::initialize() {
|
void OS::initialize() {
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
if(initialized == false) {
|
if(initialized == false) {
|
||||||
|
|
|
@ -143,13 +143,14 @@ struct Object {
|
||||||
pObject &p;
|
pObject &p;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OS : Object {
|
struct OS {
|
||||||
static void main();
|
static void main();
|
||||||
static bool pendingEvents();
|
static bool pendingEvents();
|
||||||
static void processEvents();
|
static void processEvents();
|
||||||
static void quit();
|
static void quit();
|
||||||
|
static void setName(const nall::string &name);
|
||||||
|
|
||||||
OS();
|
struct State;
|
||||||
static void initialize();
|
static void initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
struct OS::State {
|
||||||
|
string name;
|
||||||
|
|
||||||
|
State() {
|
||||||
|
}
|
||||||
|
} osState;
|
||||||
|
|
||||||
struct Timer::State {
|
struct Timer::State {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
unsigned milliseconds;
|
unsigned milliseconds;
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
Geometry pWidget::minimumGeometry() {
|
|
||||||
return {0, 0, 0, 0};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool pWidget::enabled() {
|
bool pWidget::enabled() {
|
||||||
return gtk_widget_get_sensitive(gtkWidget);
|
return gtk_widget_get_sensitive(gtkWidget);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +6,10 @@ bool pWidget::focused() {
|
||||||
return GTK_WIDGET_HAS_FOCUS(gtkWidget);
|
return GTK_WIDGET_HAS_FOCUS(gtkWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Geometry pWidget::minimumGeometry() {
|
||||||
|
return {0, 0, 0, 0};
|
||||||
|
}
|
||||||
|
|
||||||
void pWidget::setEnabled(bool enabled) {
|
void pWidget::setEnabled(bool enabled) {
|
||||||
if(widget.state.abstract) enabled = false;
|
if(widget.state.abstract) enabled = false;
|
||||||
if(sizable.state.layout && sizable.state.layout->enabled() == false) enabled = false;
|
if(sizable.state.layout && sizable.state.layout->enabled() == false) enabled = false;
|
||||||
|
|
|
@ -296,6 +296,15 @@ void pWindow::constructor() {
|
||||||
|
|
||||||
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
|
//if program was given a name, try and set the window taskbar icon from one of the pixmaps folders
|
||||||
|
if(osState.name.empty() == false) {
|
||||||
|
if(file::exists({"/usr/share/pixmaps/", osState.name, ".png"})) {
|
||||||
|
gtk_window_set_icon_from_file(GTK_WINDOW(widget), string{"/usr/share/pixmaps/", osState.name, ".png"}, nullptr);
|
||||||
|
} else if(file::exists({"/usr/local/share/pixmaps/", osState.name, ".png"})) {
|
||||||
|
gtk_window_set_icon_from_file(GTK_WINDOW(widget), string{"/usr/local/share/pixmaps/", osState.name, ".png"}, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(gdk_screen_is_composited(gdk_screen_get_default())) {
|
if(gdk_screen_is_composited(gdk_screen_get_default())) {
|
||||||
gtk_widget_set_colormap(widget, gdk_screen_get_rgba_colormap(gdk_screen_get_default()));
|
gtk_widget_set_colormap(widget, gdk_screen_get_rgba_colormap(gdk_screen_get_default()));
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** Meta object code from reading C++ file 'platform.moc.hpp'
|
||||||
**
|
**
|
||||||
** Created: Fri Dec 21 16:30:24 2012
|
** Created: Wed Dec 26 00:12:14 2012
|
||||||
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
|
|
@ -266,6 +266,7 @@ struct pWidget : public pSizable {
|
||||||
Widget &widget;
|
Widget &widget;
|
||||||
QWidget *qtWidget;
|
QWidget *qtWidget;
|
||||||
|
|
||||||
|
bool focused();
|
||||||
virtual Geometry minimumGeometry();
|
virtual Geometry minimumGeometry();
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
bool pWidget::focused() {
|
||||||
|
return qtWidget->hasFocus();
|
||||||
|
}
|
||||||
|
|
||||||
Geometry pWidget::minimumGeometry() {
|
Geometry pWidget::minimumGeometry() {
|
||||||
return { 0, 0, 0, 0 };
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setEnabled(bool enabled) {
|
void pWidget::setEnabled(bool enabled) {
|
||||||
|
|
|
@ -179,6 +179,15 @@ void pWindow::constructor() {
|
||||||
qtWindow = new QtWindow(*this);
|
qtWindow = new QtWindow(*this);
|
||||||
qtWindow->setWindowTitle(" ");
|
qtWindow->setWindowTitle(" ");
|
||||||
|
|
||||||
|
//if program was given a name, try and set the window taskbar icon to a matching pixmap image
|
||||||
|
if(osState.name.empty() == false) {
|
||||||
|
if(file::exists({"/usr/share/pixmaps/", osState.name, ".png"})) {
|
||||||
|
qtWindow->setWindowIcon(QIcon(string{"/usr/share/pixmaps/", osState.name, ".png"}));
|
||||||
|
} else if(file::exists({"/usr/local/share/pixmaps/", osState.name, ".png"})) {
|
||||||
|
qtWindow->setWindowIcon(QIcon(string{"/usr/local/share/pixmaps/", osState.name, ".png"}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
qtLayout = new QVBoxLayout(qtWindow);
|
qtLayout = new QVBoxLayout(qtWindow);
|
||||||
qtLayout->setMargin(0);
|
qtLayout->setMargin(0);
|
||||||
qtLayout->setSpacing(0);
|
qtLayout->setSpacing(0);
|
||||||
|
|
|
@ -183,6 +183,7 @@ struct pWidget : public pSizable {
|
||||||
Widget &widget;
|
Widget &widget;
|
||||||
|
|
||||||
bool enabled();
|
bool enabled();
|
||||||
|
bool focused();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
|
|
|
@ -2,8 +2,12 @@ bool pWidget::enabled() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pWidget::focused() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Geometry pWidget::minimumGeometry() {
|
Geometry pWidget::minimumGeometry() {
|
||||||
return { 0, 0, 0, 0 };
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setEnabled(bool enabled) {
|
void pWidget::setEnabled(bool enabled) {
|
||||||
|
|
|
@ -223,6 +223,7 @@ struct pWidget : public pSizable {
|
||||||
HFONT hfont;
|
HFONT hfont;
|
||||||
|
|
||||||
bool enabled();
|
bool enabled();
|
||||||
|
bool focused();
|
||||||
virtual Geometry minimumGeometry();
|
virtual Geometry minimumGeometry();
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
|
|
|
@ -63,10 +63,25 @@ void pButton::setImage(const image &image, Orientation orientation) {
|
||||||
}
|
}
|
||||||
Button_SetImageList(hwnd, &list);
|
Button_SetImageList(hwnd, &list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setText(button.state.text); //update text to display nicely with image (or lack thereof)
|
||||||
}
|
}
|
||||||
|
|
||||||
void pButton::setText(const string &text) {
|
void pButton::setText(const string &text) {
|
||||||
SetWindowText(hwnd, utf16_t(text));
|
if(text.empty()) {
|
||||||
|
//bitmaps will not show up if text is empty
|
||||||
|
SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) | BS_BITMAP);
|
||||||
|
} else {
|
||||||
|
//text will not show up if BS_BITMAP is set
|
||||||
|
SetWindowLongPtr(hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~BS_BITMAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(OsVersion() >= WindowsVista && button.state.image.empty() == false && text.empty() == false) {
|
||||||
|
//Vista+ does not add spacing between the icon and text; causing them to run into each other
|
||||||
|
SetWindowText(hwnd, utf16_t(string{" ", text}));
|
||||||
|
} else {
|
||||||
|
SetWindowText(hwnd, utf16_t(text));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pButton::constructor() {
|
void pButton::constructor() {
|
||||||
|
@ -74,7 +89,7 @@ void pButton::constructor() {
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&button);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&button);
|
||||||
setDefaultFont();
|
setDefaultFont();
|
||||||
setImage(button.state.image, button.state.orientation);
|
setImage(button.state.image, button.state.orientation);
|
||||||
setText(button.state.text);
|
//setText(button.state.text); //called by setImage();
|
||||||
synchronize();
|
synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,12 @@ bool pWidget::enabled() {
|
||||||
return IsWindowEnabled(hwnd);
|
return IsWindowEnabled(hwnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pWidget::focused() {
|
||||||
|
return GetFocus() == hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
Geometry pWidget::minimumGeometry() {
|
Geometry pWidget::minimumGeometry() {
|
||||||
return { 0, 0, 0, 0 };
|
return {0, 0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setEnabled(bool enabled) {
|
void pWidget::setEnabled(bool enabled) {
|
||||||
|
|
|
@ -40,9 +40,9 @@ string Ananke::createSufamiTurboHeuristic(vector<uint8_t> &buffer) {
|
||||||
file::write({pathname, "manifest.bml"}, {
|
file::write({pathname, "manifest.bml"}, {
|
||||||
"cartridge\n",
|
"cartridge\n",
|
||||||
" rom name=program.rom size=0x", hex(buffer.size()), "\n",
|
" rom name=program.rom size=0x", hex(buffer.size()), "\n",
|
||||||
" ram name=save.ram size=0x2000\n"
|
" ram name=save.ram size=0x2000\n",
|
||||||
"\n"
|
"\n",
|
||||||
"information\n"
|
"information\n",
|
||||||
" title: ", nall::basename(information.name), "\n"
|
" title: ", nall::basename(information.name), "\n"
|
||||||
});
|
});
|
||||||
file::write({pathname, "program.rom"}, buffer);
|
file::write({pathname, "program.rom"}, buffer);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "higan";
|
static const char Name[] = "higan";
|
||||||
static const char Version[] = "091.15";
|
static const char Version[] = "092";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ struct Interface {
|
||||||
unsigned id;
|
unsigned id;
|
||||||
string name;
|
string name;
|
||||||
string type;
|
string type;
|
||||||
bool bootable; //false for slotted sub-cartridges (Super Game Boy et al)
|
bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges)
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<Media> media;
|
vector<Media> media;
|
||||||
|
@ -75,7 +75,7 @@ struct Interface {
|
||||||
template<typename... Args> void notify(Args&... args) { return bind->notify({std::forward<Args>(args)...}); }
|
template<typename... Args> void notify(Args&... args) { return bind->notify({std::forward<Args>(args)...}); }
|
||||||
|
|
||||||
//information
|
//information
|
||||||
virtual string title() { return ""; }
|
virtual string title() = 0;
|
||||||
virtual double videoFrequency() = 0;
|
virtual double videoFrequency() = 0;
|
||||||
virtual double audioFrequency() = 0;
|
virtual double audioFrequency() = 0;
|
||||||
|
|
||||||
|
|
|
@ -87,12 +87,12 @@ Board::Board(Markup::Node &document) {
|
||||||
auto cartridge = document["cartridge"];
|
auto cartridge = document["cartridge"];
|
||||||
|
|
||||||
information.type = cartridge["board/type"].data;
|
information.type = cartridge["board/type"].data;
|
||||||
information.battery = cartridge["prg/ram/nonvolatile"].exists();
|
information.battery = cartridge["prg/ram/name"].exists();
|
||||||
|
|
||||||
auto prom = cartridge["prg"]["rom"];
|
auto prom = cartridge["prg/rom"];
|
||||||
auto pram = cartridge["prg"]["ram"];
|
auto pram = cartridge["prg/ram"];
|
||||||
auto crom = cartridge["chr"]["rom"];
|
auto crom = cartridge["chr/rom"];
|
||||||
auto cram = cartridge["chr"]["ram"];
|
auto cram = cartridge["chr/ram"];
|
||||||
|
|
||||||
prgrom.size = numeral(prom["size"].data);
|
prgrom.size = numeral(prom["size"].data);
|
||||||
prgram.size = numeral(pram["size"].data);
|
prgram.size = numeral(pram["size"].data);
|
||||||
|
@ -122,6 +122,7 @@ Board::~Board() {
|
||||||
Board* Board::load(const string &manifest) {
|
Board* Board::load(const string &manifest) {
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
cartridge.information.title = document["information/title"].text();
|
cartridge.information.title = document["information/title"].text();
|
||||||
|
|
||||||
string type = document["cartridge/board/type"].text();
|
string type = document["cartridge/board/type"].text();
|
||||||
|
|
||||||
if(type == "BANDAI-FCG" ) return new BandaiFCG(document);
|
if(type == "BANDAI-FCG" ) return new BandaiFCG(document);
|
||||||
|
|
|
@ -42,6 +42,9 @@ void System::runthreadtosave() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::load() {
|
void System::load() {
|
||||||
|
string manifest = string::read({interface->path(ID::System), "manifest.bml"});
|
||||||
|
auto document = Markup::Document(manifest);
|
||||||
|
|
||||||
serialize_init();
|
serialize_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
|
||||||
information.rtc = false;
|
information.rtc = false;
|
||||||
information.rumble = false;
|
information.rumble = false;
|
||||||
|
|
||||||
auto rom = document["cartridge"]["rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
auto ram = document["cartridge"]["ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
romsize = numeral(rom["size"].data);
|
romsize = numeral(rom["size"].data);
|
||||||
romdata = allocate<uint8>(romsize, 0xff);
|
romdata = allocate<uint8>(romsize, 0xff);
|
||||||
|
@ -63,8 +63,8 @@ void Cartridge::load(System::Revision revision, const string &manifest) {
|
||||||
if(ram["name"].exists()) memory.append({ID::RAM, ram["name"].data});
|
if(ram["name"].exists()) memory.append({ID::RAM, ram["name"].data});
|
||||||
}
|
}
|
||||||
|
|
||||||
information.romsize = numeral(document["cartridge"]["rom"]["size"].data);
|
information.romsize = numeral(rom["size"].data);
|
||||||
information.ramsize = numeral(document["cartridge"]["ram"]["size"].data);
|
information.ramsize = numeral(ram["size"].data);
|
||||||
information.battery = ram["name"].exists();
|
information.battery = ram["name"].exists();
|
||||||
|
|
||||||
switch(information.mapper) { default:
|
switch(information.mapper) { default:
|
||||||
|
|
|
@ -49,15 +49,15 @@ void System::load(Revision revision) {
|
||||||
serialize_init();
|
serialize_init();
|
||||||
if(revision == Revision::SuperGameBoy) return; //Super Famicom core loads boot ROM for SGB
|
if(revision == Revision::SuperGameBoy) return; //Super Famicom core loads boot ROM for SGB
|
||||||
|
|
||||||
string manifest, firmware;
|
string manifest = string::read({interface->path(ID::System), "manifest.bml"});
|
||||||
manifest.readfile({interface->path(ID::System), "manifest.xml"});
|
auto document = Markup::Document(manifest);
|
||||||
XML::Document document(manifest);
|
|
||||||
interface->loadRequest(
|
interface->loadRequest(
|
||||||
revision == Revision::GameBoy ? ID::GameBoyBootROM : ID::GameBoyColorBootROM,
|
revision == Revision::GameBoy ? ID::GameBoyBootROM : ID::GameBoyColorBootROM,
|
||||||
document["system"]["cpu"]["firmware"]["name"].data
|
document["system/cpu/rom/name"].data
|
||||||
);
|
);
|
||||||
if(!file::exists({interface->path(ID::System), document["system"]["cpu"]["firmware"]["name"].data})) {
|
if(!file::exists({interface->path(ID::System), document["system/cpu/rom/name"].data})) {
|
||||||
interface->notify("Error: required firmware ", firmware, " not found.\n");
|
interface->notify("Error: required Game Boy firmware boot.rom not found.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,13 +23,12 @@ void System::power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::load() {
|
void System::load() {
|
||||||
string manifest;
|
string manifest = string::read({interface->path(ID::System), "manifest.bml"});
|
||||||
manifest.readfile({interface->path(ID::System), "manifest.xml"});
|
auto document = Markup::Document(manifest);
|
||||||
XML::Document document(manifest);
|
|
||||||
string firmware = document["system"]["cpu"]["firmware"]["name"].data;
|
interface->loadRequest(ID::BIOS, document["system/cpu/rom/name"].data);
|
||||||
interface->loadRequest(ID::BIOS, firmware);
|
if(!file::exists({interface->path(ID::System), document["system/cpu/rom/name"].data})) {
|
||||||
if(!file::exists({interface->path(ID::System), firmware})) {
|
interface->notify("Error: required Game Boy Advance firmware bios.rom not found.\n");
|
||||||
interface->notify("Error: required firmware ", firmware, " not found.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize_init();
|
serialize_init();
|
||||||
|
|
|
@ -1,173 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_FAMICOM_HPP
|
|
||||||
#define NALL_EMULATION_FAMICOM_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct FamicomCartridge {
|
|
||||||
string markup;
|
|
||||||
inline FamicomCartridge(const uint8_t *data, unsigned size);
|
|
||||||
|
|
||||||
//private:
|
|
||||||
unsigned mapper;
|
|
||||||
unsigned mirror;
|
|
||||||
unsigned prgrom;
|
|
||||||
unsigned prgram;
|
|
||||||
unsigned chrrom;
|
|
||||||
unsigned chrram;
|
|
||||||
};
|
|
||||||
|
|
||||||
FamicomCartridge::FamicomCartridge(const uint8_t *data, unsigned size) {
|
|
||||||
markup = "";
|
|
||||||
if(size < 16) return;
|
|
||||||
if(data[0] != 'N') return;
|
|
||||||
if(data[1] != 'E') return;
|
|
||||||
if(data[2] != 'S') return;
|
|
||||||
if(data[3] != 26) return;
|
|
||||||
|
|
||||||
mapper = ((data[7] >> 4) << 4) | (data[6] >> 4);
|
|
||||||
mirror = ((data[6] & 0x08) >> 2) | (data[6] & 0x01);
|
|
||||||
prgrom = data[4] * 0x4000;
|
|
||||||
chrrom = data[5] * 0x2000;
|
|
||||||
prgram = 0u;
|
|
||||||
chrram = chrrom == 0u ? 8192u : 0u;
|
|
||||||
|
|
||||||
markup.append("cartridge\n");
|
|
||||||
|
|
||||||
switch(mapper) {
|
|
||||||
default:
|
|
||||||
markup.append(" board type=NES-NROM-256\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
markup.append(" board type=NES-SXROM\n");
|
|
||||||
markup.append(" chip type=MMC1B2\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
markup.append(" board type=NES-UOROM\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
markup.append(" board type=NES-CNROM\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
//MMC3
|
|
||||||
markup.append(" board type=NES-TLROM\n");
|
|
||||||
markup.append(" chip type=MMC3B\n");
|
|
||||||
prgram = 8192;
|
|
||||||
//MMC6
|
|
||||||
//markup.append(" board type=NES-HKROM\n");
|
|
||||||
//markup.append(" chip type=MMC6n");
|
|
||||||
//prgram = 1024;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
markup.append(" board type=NES-ELROM\n");
|
|
||||||
markup.append(" chip type=MMC5\n");
|
|
||||||
prgram = 65536;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
markup.append(" board type=NES-AOROM\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 9:
|
|
||||||
markup.append(" board type=NES-PNROM\n");
|
|
||||||
markup.append(" chip type=MMC2\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 10:
|
|
||||||
markup.append(" board type=NES-FKROM\n");
|
|
||||||
markup.append(" chip type=MMC4\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 16:
|
|
||||||
markup.append(" board type=BANDAI-FCG\n");
|
|
||||||
markup.append(" chip type=LZ93D50\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 21:
|
|
||||||
case 23:
|
|
||||||
case 25:
|
|
||||||
//VRC4
|
|
||||||
markup.append(" board type=KONAMI-VRC-4\n");
|
|
||||||
markup.append(" chip type=VRC4\n");
|
|
||||||
markup.append(" pinout a0=1 a1=0\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 22:
|
|
||||||
//VRC2
|
|
||||||
markup.append(" board type=KONAMI-VRC-2\n");
|
|
||||||
markup.append(" chip type=VRC2\n");
|
|
||||||
markup.append(" pinout a0=0 a1=1\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 24:
|
|
||||||
markup.append(" board type=KONAMI-VRC-6\n");
|
|
||||||
markup.append(" chip type=VRC6\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 26:
|
|
||||||
markup.append(" board type=KONAMI-VRC-6\n");
|
|
||||||
markup.append(" chip type=VRC6\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 34:
|
|
||||||
markup.append(" board type=NES-BNROM\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 66:
|
|
||||||
markup.append(" board type=NES-GNROM\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 69:
|
|
||||||
markup.append(" board type=SUNSOFT-5B\n");
|
|
||||||
markup.append(" chip type=5B\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 73:
|
|
||||||
markup.append(" board type=KONAMI-VRC-3\n");
|
|
||||||
markup.append(" chip type=VRC3\n");
|
|
||||||
markup.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 75:
|
|
||||||
markup.append(" board type=KONAMI-VRC-1\n");
|
|
||||||
markup.append(" chip type=VRC1\n");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 85:
|
|
||||||
markup.append(" board type=KONAMI-VRC-7\n");
|
|
||||||
markup.append(" chip type=VRC7\n");
|
|
||||||
prgram = 8192;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
markup.append(" prg\n");
|
|
||||||
if(prgrom) markup.append(" rom name=program.rom size=0x", hex(prgrom), "\n");
|
|
||||||
if(prgram) markup.append(" ram name=save.ram size=0x", hex(prgram), "\n");
|
|
||||||
|
|
||||||
markup.append(" chr\n");
|
|
||||||
if(chrrom) markup.append(" rom name=character.rom size=0x", hex(chrrom), "\n");
|
|
||||||
if(chrram) markup.append(" ram size=0x", hex(chrram), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,63 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
|
||||||
#define NALL_EMULATION_GAME_BOY_ADVANCE_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
#include <nall/vector.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct GameBoyAdvanceCartridge {
|
|
||||||
string markup;
|
|
||||||
string identifiers;
|
|
||||||
inline GameBoyAdvanceCartridge(const uint8_t *data, unsigned size);
|
|
||||||
};
|
|
||||||
|
|
||||||
GameBoyAdvanceCartridge::GameBoyAdvanceCartridge(const uint8_t *data, unsigned size) {
|
|
||||||
struct Identifier {
|
|
||||||
string name;
|
|
||||||
unsigned size;
|
|
||||||
};
|
|
||||||
vector<Identifier> idlist;
|
|
||||||
idlist.append({"SRAM_V", 6});
|
|
||||||
idlist.append({"SRAM_F_V", 8});
|
|
||||||
idlist.append({"EEPROM_V", 8});
|
|
||||||
idlist.append({"FLASH_V", 7});
|
|
||||||
idlist.append({"FLASH512_V", 10});
|
|
||||||
idlist.append({"FLASH1M_V", 9});
|
|
||||||
|
|
||||||
lstring list;
|
|
||||||
for(auto &id : idlist) {
|
|
||||||
for(signed n = 0; n < size - 16; n++) {
|
|
||||||
if(!memcmp(data + n, (const char*)id.name, id.size)) {
|
|
||||||
const char *p = (const char*)data + n + id.size;
|
|
||||||
if(p[0] >= '0' && p[0] <= '9'
|
|
||||||
&& p[1] >= '0' && p[1] <= '9'
|
|
||||||
&& p[2] >= '0' && p[2] <= '9'
|
|
||||||
) {
|
|
||||||
char text[16];
|
|
||||||
memcpy(text, data + n, id.size + 3);
|
|
||||||
text[id.size + 3] = 0;
|
|
||||||
list.appendonce(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
identifiers = list.concatenate(",");
|
|
||||||
|
|
||||||
markup = "";
|
|
||||||
markup.append("cartridge\n");
|
|
||||||
markup.append(" rom name=program.rom size=0x", hex(size), "\n");
|
|
||||||
if(0);
|
|
||||||
else if(identifiers.beginswith("SRAM_V" )) markup.append(" ram name=save.ram type=SRAM size=0x8000\n");
|
|
||||||
else if(identifiers.beginswith("SRAM_F_V" )) markup.append(" ram name=save.ram type=FRAM size=0x8000\n");
|
|
||||||
else if(identifiers.beginswith("EEPROM_V" )) markup.append(" ram name=save.ram type=EEPROM size=0x0\n");
|
|
||||||
else if(identifiers.beginswith("FLASH_V" )) markup.append(" ram name=save.ram type=FlashROM size=0x10000\n");
|
|
||||||
else if(identifiers.beginswith("FLASH512_V")) markup.append(" ram name=save.ram type=FlashROM size=0x10000\n");
|
|
||||||
else if(identifiers.beginswith("FLASH1M_V" )) markup.append(" ram name=save.ram type=FlashROM size=0x20000\n");
|
|
||||||
//if(identifiers.empty() == false) markup.append(" #detected: ", identifiers, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,120 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_GAME_BOY_HPP
|
|
||||||
#define NALL_EMULATION_GAME_BOY_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct GameBoyCartridge {
|
|
||||||
string markup;
|
|
||||||
inline GameBoyCartridge(uint8_t *data, unsigned size);
|
|
||||||
|
|
||||||
//private:
|
|
||||||
struct Information {
|
|
||||||
string mapper;
|
|
||||||
bool ram;
|
|
||||||
bool battery;
|
|
||||||
bool rtc;
|
|
||||||
bool rumble;
|
|
||||||
|
|
||||||
unsigned romsize;
|
|
||||||
unsigned ramsize;
|
|
||||||
|
|
||||||
bool cgb;
|
|
||||||
bool cgbonly;
|
|
||||||
} info;
|
|
||||||
};
|
|
||||||
|
|
||||||
GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
|
||||||
markup = "";
|
|
||||||
if(romsize < 0x4000) return;
|
|
||||||
|
|
||||||
info.mapper = "unknown";
|
|
||||||
info.ram = false;
|
|
||||||
info.battery = false;
|
|
||||||
info.rtc = false;
|
|
||||||
info.rumble = false;
|
|
||||||
|
|
||||||
info.romsize = 0;
|
|
||||||
info.ramsize = 0;
|
|
||||||
|
|
||||||
unsigned base = romsize - 0x8000;
|
|
||||||
if(romdata[base + 0x0104] == 0xce && romdata[base + 0x0105] == 0xed
|
|
||||||
&& romdata[base + 0x0106] == 0x66 && romdata[base + 0x0107] == 0x66
|
|
||||||
&& romdata[base + 0x0108] == 0xcc && romdata[base + 0x0109] == 0x0d
|
|
||||||
&& romdata[base + 0x0147] >= 0x0b && romdata[base + 0x0147] <= 0x0d
|
|
||||||
) {
|
|
||||||
//MMM01 stores header at bottom of image
|
|
||||||
//flip this around for consistency with all other mappers
|
|
||||||
uint8_t header[0x8000];
|
|
||||||
memcpy(header, romdata + base, 0x8000);
|
|
||||||
memmove(romdata + 0x8000, romdata, romsize - 0x8000);
|
|
||||||
memcpy(romdata, header, 0x8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
info.cgb = (romdata[0x0143] & 0x80) == 0x80;
|
|
||||||
info.cgbonly = (romdata[0x0143] & 0xc0) == 0xc0;
|
|
||||||
|
|
||||||
switch(romdata[0x0147]) {
|
|
||||||
case 0x00: info.mapper = "none"; break;
|
|
||||||
case 0x01: info.mapper = "MBC1"; break;
|
|
||||||
case 0x02: info.mapper = "MBC1"; info.ram = true; break;
|
|
||||||
case 0x03: info.mapper = "MBC1"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x05: info.mapper = "MBC2"; info.ram = true; break;
|
|
||||||
case 0x06: info.mapper = "MBC2"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x08: info.mapper = "none"; info.ram = true; break;
|
|
||||||
case 0x09: info.mapper = "MBC0"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x0b: info.mapper = "MMM01"; break;
|
|
||||||
case 0x0c: info.mapper = "MMM01"; info.ram = true; break;
|
|
||||||
case 0x0d: info.mapper = "MMM01"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x0f: info.mapper = "MBC3"; info.rtc = true; info.battery = true; break;
|
|
||||||
case 0x10: info.mapper = "MBC3"; info.rtc = true; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x11: info.mapper = "MBC3"; break;
|
|
||||||
case 0x12: info.mapper = "MBC3"; info.ram = true; break;
|
|
||||||
case 0x13: info.mapper = "MBC3"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x19: info.mapper = "MBC5"; break;
|
|
||||||
case 0x1a: info.mapper = "MBC5"; info.ram = true; break;
|
|
||||||
case 0x1b: info.mapper = "MBC5"; info.ram = true; info.battery = true; break;
|
|
||||||
case 0x1c: info.mapper = "MBC5"; info.rumble = true; break;
|
|
||||||
case 0x1d: info.mapper = "MBC5"; info.rumble = true; info.ram = true; break;
|
|
||||||
case 0x1e: info.mapper = "MBC5"; info.rumble = true; info.ram = true; info.battery = true; break;
|
|
||||||
case 0xfc: break; //Pocket Camera
|
|
||||||
case 0xfd: break; //Bandai TAMA5
|
|
||||||
case 0xfe: info.mapper = "HuC3"; break;
|
|
||||||
case 0xff: info.mapper = "HuC1"; info.ram = true; info.battery = true; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(romdata[0x0148]) { default:
|
|
||||||
case 0x00: info.romsize = 2 * 16 * 1024; break;
|
|
||||||
case 0x01: info.romsize = 4 * 16 * 1024; break;
|
|
||||||
case 0x02: info.romsize = 8 * 16 * 1024; break;
|
|
||||||
case 0x03: info.romsize = 16 * 16 * 1024; break;
|
|
||||||
case 0x04: info.romsize = 32 * 16 * 1024; break;
|
|
||||||
case 0x05: info.romsize = 64 * 16 * 1024; break;
|
|
||||||
case 0x06: info.romsize = 128 * 16 * 1024; break;
|
|
||||||
case 0x07: info.romsize = 256 * 16 * 1024; break;
|
|
||||||
case 0x52: info.romsize = 72 * 16 * 1024; break;
|
|
||||||
case 0x53: info.romsize = 80 * 16 * 1024; break;
|
|
||||||
case 0x54: info.romsize = 96 * 16 * 1024; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(romdata[0x0149]) { default:
|
|
||||||
case 0x00: info.ramsize = 0 * 1024; break;
|
|
||||||
case 0x01: info.ramsize = 2 * 1024; break;
|
|
||||||
case 0x02: info.ramsize = 8 * 1024; break;
|
|
||||||
case 0x03: info.ramsize = 32 * 1024; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
|
|
||||||
|
|
||||||
markup = "";
|
|
||||||
markup.append("cartridge\n");
|
|
||||||
markup.append(" board type=", info.mapper, "\n");
|
|
||||||
markup.append(" rom name=program.rom size=0x", hex(romsize), "\n");
|
|
||||||
if(info.ramsize > 0) markup.append(" ram name=save.ram size=0x", hex(info.ramsize), "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_SATELLAVIEW_HPP
|
|
||||||
#define NALL_EMULATION_SATELLAVIEW_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct SatellaviewCartridge {
|
|
||||||
string markup;
|
|
||||||
inline SatellaviewCartridge(const uint8_t *data, unsigned size);
|
|
||||||
};
|
|
||||||
|
|
||||||
SatellaviewCartridge::SatellaviewCartridge(const uint8_t *data, unsigned size) {
|
|
||||||
markup = "";
|
|
||||||
|
|
||||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
|
||||||
markup.append("<cartridge sha256='", sha256(data, size) ,"'>\n");
|
|
||||||
markup.append(" <rom name='program.rom' size='0x", hex(size), "'/>\n");
|
|
||||||
markup.append("</cartridge>\n");
|
|
||||||
markup.transform("'", "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,33 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_SUFAMI_TURBO_HPP
|
|
||||||
#define NALL_EMULATION_SUFAMI_TURBO_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct SufamiTurboCartridge {
|
|
||||||
string markup;
|
|
||||||
inline SufamiTurboCartridge(const uint8_t *data, unsigned size);
|
|
||||||
};
|
|
||||||
|
|
||||||
SufamiTurboCartridge::SufamiTurboCartridge(const uint8_t *data, unsigned size) {
|
|
||||||
markup = "";
|
|
||||||
|
|
||||||
if(size < 0x20000) return; //too small to be a valid game?
|
|
||||||
if(memcmp(data, "BANDAI SFC-ADX", 14)) return; //missing required header?
|
|
||||||
unsigned romsize = data[0x36] * 0x20000; //128KB
|
|
||||||
unsigned ramsize = data[0x37] * 0x800; //2KB
|
|
||||||
bool linkable = data[0x35] != 0x00; //TODO: unconfirmed
|
|
||||||
|
|
||||||
markup.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
|
||||||
markup.append("<cartridge linkable='", linkable, "' sha256='", sha256(data, size) ,"'>\n");
|
|
||||||
markup.append(" <rom name='program.rom' size='0x", hex(romsize), "'/>\n");
|
|
||||||
markup.append(" <ram name='save.ram' size='0x", hex(ramsize), "'/>\n");
|
|
||||||
markup.append("</cartridge>\n");
|
|
||||||
markup.transform("'", "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,814 +0,0 @@
|
||||||
#ifndef NALL_EMULATION_SUPER_FAMICOM_HPP
|
|
||||||
#define NALL_EMULATION_SUPER_FAMICOM_HPP
|
|
||||||
|
|
||||||
#include <nall/sha256.hpp>
|
|
||||||
#include <nall/string.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
|
|
||||||
struct SuperFamicomCartridge {
|
|
||||||
string markup;
|
|
||||||
inline SuperFamicomCartridge(const uint8_t *data, unsigned size);
|
|
||||||
|
|
||||||
//private:
|
|
||||||
inline void read_header(const uint8_t *data, unsigned size);
|
|
||||||
inline unsigned find_header(const uint8_t *data, unsigned size);
|
|
||||||
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
|
||||||
|
|
||||||
enum HeaderField {
|
|
||||||
CartName = 0x00,
|
|
||||||
Mapper = 0x15,
|
|
||||||
RomType = 0x16,
|
|
||||||
RomSize = 0x17,
|
|
||||||
RamSize = 0x18,
|
|
||||||
CartRegion = 0x19,
|
|
||||||
Company = 0x1a,
|
|
||||||
Version = 0x1b,
|
|
||||||
Complement = 0x1c, //inverse checksum
|
|
||||||
Checksum = 0x1e,
|
|
||||||
ResetVector = 0x3c,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Mode {
|
|
||||||
ModeNormal,
|
|
||||||
ModeBsxSlotted,
|
|
||||||
ModeBsx,
|
|
||||||
ModeSufamiTurbo,
|
|
||||||
ModeSuperGameBoy,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
TypeNormal,
|
|
||||||
TypeBsxSlotted,
|
|
||||||
TypeBsxBios,
|
|
||||||
TypeBsx,
|
|
||||||
TypeSufamiTurboBios,
|
|
||||||
TypeSufamiTurbo,
|
|
||||||
TypeSuperGameBoy1Bios,
|
|
||||||
TypeSuperGameBoy2Bios,
|
|
||||||
TypeGameBoy,
|
|
||||||
TypeUnknown,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Region {
|
|
||||||
NTSC,
|
|
||||||
PAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum MemoryMapper {
|
|
||||||
LoROM,
|
|
||||||
HiROM,
|
|
||||||
ExLoROM,
|
|
||||||
ExHiROM,
|
|
||||||
SuperFXROM,
|
|
||||||
SA1ROM,
|
|
||||||
SPC7110ROM,
|
|
||||||
BSCLoROM,
|
|
||||||
BSCHiROM,
|
|
||||||
BSXROM,
|
|
||||||
STROM,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum DSP1MemoryMapper {
|
|
||||||
DSP1Unmapped,
|
|
||||||
DSP1LoROM1MB,
|
|
||||||
DSP1LoROM2MB,
|
|
||||||
DSP1HiROM,
|
|
||||||
};
|
|
||||||
|
|
||||||
bool loaded; //is a base cartridge inserted?
|
|
||||||
unsigned crc32; //crc32 of all cartridges (base+slot(s))
|
|
||||||
unsigned rom_size;
|
|
||||||
unsigned ram_size;
|
|
||||||
bool firmware_appended; //true if firmware is appended to end of ROM data
|
|
||||||
|
|
||||||
Mode mode;
|
|
||||||
Type type;
|
|
||||||
Region region;
|
|
||||||
MemoryMapper mapper;
|
|
||||||
DSP1MemoryMapper dsp1_mapper;
|
|
||||||
|
|
||||||
bool has_bsx_slot;
|
|
||||||
bool has_superfx;
|
|
||||||
bool has_sa1;
|
|
||||||
bool has_srtc;
|
|
||||||
bool has_sdd1;
|
|
||||||
bool has_spc7110;
|
|
||||||
bool has_spc7110rtc;
|
|
||||||
bool has_cx4;
|
|
||||||
bool has_dsp1;
|
|
||||||
bool has_dsp2;
|
|
||||||
bool has_dsp3;
|
|
||||||
bool has_dsp4;
|
|
||||||
bool has_obc1;
|
|
||||||
bool has_st010;
|
|
||||||
bool has_st011;
|
|
||||||
bool has_st018;
|
|
||||||
};
|
|
||||||
|
|
||||||
SuperFamicomCartridge::SuperFamicomCartridge(const uint8_t *data, unsigned size) {
|
|
||||||
firmware_appended = false;
|
|
||||||
|
|
||||||
//skip copier header
|
|
||||||
if((size & 0x7fff) == 512) data += 512, size -= 512;
|
|
||||||
|
|
||||||
markup = "";
|
|
||||||
if(size < 0x8000) return;
|
|
||||||
|
|
||||||
read_header(data, size);
|
|
||||||
|
|
||||||
markup = "";
|
|
||||||
if(type == TypeGameBoy) return;
|
|
||||||
if(type == TypeBsx) return;
|
|
||||||
if(type == TypeSufamiTurbo) return;
|
|
||||||
|
|
||||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
|
||||||
markup.append("cartridge region=", region == NTSC ? "NTSC" : "PAL", "\n");
|
|
||||||
|
|
||||||
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" map id=rom address=00-7f,80-ff:8000-ffff\n"
|
|
||||||
" icd2 revision=1\n"
|
|
||||||
" rom name=boot.rom size=0x100\n"
|
|
||||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
|
||||||
);
|
|
||||||
if((rom_size & 0x7fff) == 0x100) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(has_cx4) {
|
|
||||||
markup.append(
|
|
||||||
" hitachidsp model=HG51B169 frequency=20000000\n"
|
|
||||||
" rom id=program name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" rom id=data name=cx4.data.rom size=0xc00\n"
|
|
||||||
" ram id=data size=0xc00\n"
|
|
||||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
|
||||||
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=ram address=70-77:0000-7fff\n"
|
|
||||||
);
|
|
||||||
if((rom_size & 0x7fff) == 0xc00) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0xc00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(has_spc7110) {
|
|
||||||
markup.append(
|
|
||||||
" spc7110\n"
|
|
||||||
" rom id=program name=program.rom size=0x100000\n"
|
|
||||||
" rom id=data name=data.rom size=0x", hex(rom_size - 0x100000), "\n"
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
" map id=io address=00-3f,80-bf:4800-483f\n"
|
|
||||||
" map id=io address=50:0000-ffff\n"
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
|
||||||
" map id=rom address=c0-ff:0000-ffff\n"
|
|
||||||
" map id=ram address=00-3f,80-bf:6000-7fff mask=0xe000\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(has_sdd1) {
|
|
||||||
markup.append(
|
|
||||||
" sdd1\n"
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=io address=00-3f,80-bf:4800-4807\n"
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=rom address=c0-ff:0000-ffff\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
|
||||||
" map id=ram address=70-7f:0000-7fff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == LoROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=rom address=00-7f,80-ff:8000-ffff mask=0x8000\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=70-7f,f0-ff:", range, "\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == HiROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
|
||||||
" map id=rom address=40-7f,c0-ff:0000-ffff\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=10-3f,90-bf:6000-7fff mask=0xe000\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == ExLoROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=rom address=40-7f:0000-ffff\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=20-3f,a0-bf:6000-7fff\n"
|
|
||||||
" map id=ram address=70-7f:0000-7fff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == ExHiROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=rom address=00-3f:8000-ffff offset=0x400000\n"
|
|
||||||
" map id=rom address=40-7f:0000-ffff offset=0x400000\n"
|
|
||||||
" map id=rom address=80-bf:8000-ffff offset=0x000000\n"
|
|
||||||
" map id=rom address=c0-ff:0000-ffff offset=0x000000\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=20-3f,a0-bf:6000-7fff mask=0xe000\n"
|
|
||||||
" map id=ram address=70-7f:", range, "\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == SuperFXROM) {
|
|
||||||
markup.append(
|
|
||||||
" superfx revision=3\n"
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=io address=00-3f,80-bf:3000-32ff\n"
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=rom address=40-5f,c0-df:0000-ffff\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=ram address=00-3f,80-bf:6000-7fff size=0x2000\n"
|
|
||||||
" map id=ram address=70-71,f0-f1:0000-ffff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == SA1ROM) {
|
|
||||||
markup.append(
|
|
||||||
" sa1\n"
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" ram id=bitmap name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" ram id=internal size=0x800\n"
|
|
||||||
" map id=io address=00-3f,80-bf:2200-23ff\n"
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
|
||||||
" map id=rom address=c0-ff:0000-ffff\n"
|
|
||||||
);
|
|
||||||
if(ram_size > 0) markup.append(
|
|
||||||
" map id=bwram address=00-3f,80-bf:6000-7fff\n"
|
|
||||||
" map id=bwram address=40-4f:0000-ffff\n"
|
|
||||||
);
|
|
||||||
markup.append(
|
|
||||||
" map id=iram address=00-3f,80-bf:3000-37ff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == BSCLoROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
" map id=rom address=00-1f:8000-ffff offset=0x000000 mask=0x8000\n"
|
|
||||||
" map id=rom address=20-3f:8000-ffff offset=0x100000 mask=0x8000\n"
|
|
||||||
" map id=rom address=80-9f:8000-ffff offset=0x200000 mask=0x8000\n"
|
|
||||||
" map id=rom address=a0-bf:8000-ffff offset=0x100000 mask=0x8000\n"
|
|
||||||
" map id=ram address=70-7f,f0-ff:0000-7fff\n"
|
|
||||||
" bsxslot\n"
|
|
||||||
" map id=rom address=c0-ef:0000-ffff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == BSCHiROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" ram name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
" map id=rom address=00-1f,80-9f:8000-ffff\n"
|
|
||||||
" map id=rom address=40-5f,c0-df:0000-ffff\n"
|
|
||||||
" map id=ram address=20-3f,a0-bf:6000-7fff\n"
|
|
||||||
" bsxslot\n"
|
|
||||||
" map id=rom address=20-3f,a0-bf:8000-ffff\n"
|
|
||||||
" map id=rom address=60-7f,e0-ff:0000-ffff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == BSXROM) {
|
|
||||||
markup.append(
|
|
||||||
" bsx\n"
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" ram id=save name=save.ram size=0x", hex(ram_size), "\n"
|
|
||||||
" ram id=download name=bsx.ram size=0x40000\n"
|
|
||||||
" map id=io address=00-3f,80-bf:5000-5fff\n"
|
|
||||||
" map id=rom address=00-3f,80-bf:8000-ffff\n"
|
|
||||||
" map id=rom address=40-7f,c0-ff:0000-ffff\n"
|
|
||||||
" map id=ram address=20-3f:6000-7fff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(mapper == STROM) {
|
|
||||||
markup.append(
|
|
||||||
" rom name=program.rom size=0x", hex(rom_size), "\n"
|
|
||||||
" map id=rom address='00-1f,80-9f:8000-ffff mask=0x8000\n"
|
|
||||||
" sufamiturbo\n"
|
|
||||||
" slot id=A\n"
|
|
||||||
" map id=rom address=20-3f,a0-bf:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=ram address=60-63,e0-e3:8000-ffff\n"
|
|
||||||
" slot id=B\n"
|
|
||||||
" map id=rom address=40-5f,c0-df:8000-ffff mask=0x8000\n"
|
|
||||||
" map id=ram address=70-73,f0-f3:8000-ffff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_spc7110rtc) {
|
|
||||||
markup.append(
|
|
||||||
" epsonrtc\n"
|
|
||||||
" ram name=rtc.ram size=0x10\n"
|
|
||||||
" map id=io address=00-3f,80-bf:4840-4842\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_srtc) {
|
|
||||||
markup.append(
|
|
||||||
" sharprtc\n"
|
|
||||||
" ram name=rtc.ram size=0x10\n"
|
|
||||||
" map id=io address=00-3f,80-bf:2800-2801\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_obc1) {
|
|
||||||
markup.append(
|
|
||||||
" obc1\n"
|
|
||||||
" ram name=save.ram size=0x2000\n"
|
|
||||||
" map id=io address=00-3f,80-bf:6000-7fff\n"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_dsp1) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD7725 frequency=8000000\n"
|
|
||||||
" rom id=program name=dsp1b.program.rom size=0x1800\n"
|
|
||||||
" rom id=data name=dsp1b.data.rom size=0x800\n"
|
|
||||||
" ram id=data size=0x200\n"
|
|
||||||
);
|
|
||||||
if(dsp1_mapper == DSP1LoROM1MB) markup.append(
|
|
||||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
|
||||||
);
|
|
||||||
if(dsp1_mapper == DSP1LoROM2MB) markup.append(
|
|
||||||
" map id=io address=60-6f,e0-ef:0000-7fff select=0x4000\n"
|
|
||||||
);
|
|
||||||
if(dsp1_mapper == DSP1HiROM) markup.append(
|
|
||||||
" map id=io address=00-1f,80-9f:6000-7fff select=0x1000\n"
|
|
||||||
);
|
|
||||||
if((size & 0x7fff) == 0x2000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x2000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_dsp2) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD7725 frequency=8000000\n"
|
|
||||||
" rom id=program name=dsp2.program.rom size=0x1800\n"
|
|
||||||
" rom id=data name=dsp2.data.rom size=0x800\n"
|
|
||||||
" ram id=data size=0x200\n"
|
|
||||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
|
||||||
);
|
|
||||||
if((size & 0x7fff) == 0x2000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x2000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_dsp3) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD7725 frequency=8000000\n"
|
|
||||||
" rom id=program name=dsp3.program.rom size=0x1800\n"
|
|
||||||
" rom id=data name=dsp3.data.rom size=0x800\n"
|
|
||||||
" ram id=data size=0x200\n"
|
|
||||||
" map id=io address=20-3f,a0-bf:8000-ffff select=0x4000\n"
|
|
||||||
);
|
|
||||||
if((size & 0x7fff) == 0x2000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x2000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_dsp4) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD7725 frequency=8000000\n"
|
|
||||||
" rom id=program name=dsp4.program.rom size=0x1800\n"
|
|
||||||
" rom id=data name=dsp4.data.rom size=0x800\n"
|
|
||||||
" ram id=data size=0x200\n"
|
|
||||||
" map address=30-3f,b0-bf:8000-ffff select=0x4000\n"
|
|
||||||
);
|
|
||||||
if((size & 0x7fff) == 0x2000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x2000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_st010) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD96050 frequency=11000000\n"
|
|
||||||
" rom id=program name=st010.program.rom size=0xc000\n"
|
|
||||||
" rom id=data name=st010.data.rom size=0x1000\n"
|
|
||||||
" ram id=data name=save.ram size=0x1000\n"
|
|
||||||
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
|
|
||||||
" map id=ram address=68-6f,e8-ef:0000-7fff\n"
|
|
||||||
);
|
|
||||||
if((size & 0xffff) == 0xd000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0xd000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_st011) {
|
|
||||||
markup.append(
|
|
||||||
" necdsp model=uPD96050 frequency=15000000\n"
|
|
||||||
" rom id=program name=st011.program.rom size=0xc000\n"
|
|
||||||
" rom id=data name=st011.data.rom size=0x1000\n"
|
|
||||||
" ram id=data name=save.ram size=0x1000\n"
|
|
||||||
" map id=io address=60-67,e0-e7:0000-3fff select=0x0001\n"
|
|
||||||
" map id=ram address=68-6f,e8-ef:0000-7fff\n"
|
|
||||||
);
|
|
||||||
if((size & 0xffff) == 0xd000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0xd000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_st018) {
|
|
||||||
markup.append(
|
|
||||||
" armdsp frequency=21477272\n"
|
|
||||||
" rom id=program name=st018.program.rom size=0x20000\n"
|
|
||||||
" rom id=data name=st018.data.rom size=0x8000\n"
|
|
||||||
" ram name=save.ram size=0x4000\n"
|
|
||||||
" map id=io address=00-3f,80-bf:3800-38ff\n"
|
|
||||||
);
|
|
||||||
if((size & 0x3ffff) == 0x28000) {
|
|
||||||
firmware_appended = true;
|
|
||||||
rom_size -= 0x28000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SuperFamicomCartridge::read_header(const uint8_t *data, unsigned size) {
|
|
||||||
type = TypeUnknown;
|
|
||||||
mapper = LoROM;
|
|
||||||
dsp1_mapper = DSP1Unmapped;
|
|
||||||
region = NTSC;
|
|
||||||
rom_size = size;
|
|
||||||
ram_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_st010 = false;
|
|
||||||
has_st011 = false;
|
|
||||||
has_st018 = false;
|
|
||||||
|
|
||||||
//=====================
|
|
||||||
//detect Game Boy carts
|
|
||||||
//=====================
|
|
||||||
|
|
||||||
if(size >= 0x0140) {
|
|
||||||
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
|
|
||||||
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
|
|
||||||
type = TypeGameBoy;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(size < 32768) {
|
|
||||||
type = TypeUnknown;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned index = find_header(data, size);
|
|
||||||
const uint8_t mapperid = data[index + Mapper];
|
|
||||||
const uint8_t rom_type = data[index + RomType];
|
|
||||||
const uint8_t rom_size = data[index + RomSize];
|
|
||||||
const uint8_t company = data[index + Company];
|
|
||||||
const uint8_t regionid = data[index + CartRegion] & 0x7f;
|
|
||||||
|
|
||||||
ram_size = 1024 << (data[index + RamSize] & 7);
|
|
||||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
|
||||||
if(rom_size == 0 && ram_size) ram_size = 0; //fix for Bazooka Blitzkrieg's malformed header (swapped ROM and RAM sizes)
|
|
||||||
|
|
||||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
|
||||||
region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
|
|
||||||
|
|
||||||
//=======================
|
|
||||||
//detect BS-X flash carts
|
|
||||||
//=======================
|
|
||||||
|
|
||||||
if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
|
|
||||||
if(data[index + 0x14] == 0x00) {
|
|
||||||
const uint8_t n15 = data[index + 0x15];
|
|
||||||
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
|
||||||
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
|
|
||||||
type = TypeBsx;
|
|
||||||
mapper = BSXROM;
|
|
||||||
region = NTSC; //BS-X only released in Japan
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//=========================
|
|
||||||
//detect Sufami Turbo carts
|
|
||||||
//=========================
|
|
||||||
|
|
||||||
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
|
|
||||||
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
|
|
||||||
type = TypeSufamiTurboBios;
|
|
||||||
} else {
|
|
||||||
type = TypeSufamiTurbo;
|
|
||||||
}
|
|
||||||
mapper = STROM;
|
|
||||||
region = NTSC; //Sufami Turbo only released in Japan
|
|
||||||
return; //RAM size handled outside this routine
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================
|
|
||||||
//detect Super Game Boy BIOS
|
|
||||||
//==========================
|
|
||||||
|
|
||||||
if(!memcmp(data + index, "Super GAMEBOY2", 14)) {
|
|
||||||
type = TypeSuperGameBoy2Bios;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
|
|
||||||
type = TypeSuperGameBoy1Bios;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=====================
|
|
||||||
//detect standard carts
|
|
||||||
//=====================
|
|
||||||
|
|
||||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
|
||||||
if(data[index - 14] == 'Z') {
|
|
||||||
if(data[index - 11] == 'J') {
|
|
||||||
uint8_t n13 = data[index - 13];
|
|
||||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
|
||||||
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
|
||||||
has_bsx_slot = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_bsx_slot) {
|
|
||||||
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
|
|
||||||
//BS-X base cart
|
|
||||||
type = TypeBsxBios;
|
|
||||||
mapper = BSXROM;
|
|
||||||
region = NTSC; //BS-X only released in Japan
|
|
||||||
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
|
|
||||||
} else {
|
|
||||||
type = TypeBsxSlotted;
|
|
||||||
mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
|
||||||
region = NTSC; //BS-X slotted cartridges only released in Japan
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//standard cart
|
|
||||||
type = TypeNormal;
|
|
||||||
|
|
||||||
if(index == 0x7fc0 && size >= 0x401000) {
|
|
||||||
mapper = ExLoROM;
|
|
||||||
} else if(index == 0x7fc0 && mapperid == 0x32) {
|
|
||||||
mapper = ExLoROM;
|
|
||||||
} else if(index == 0x7fc0) {
|
|
||||||
mapper = LoROM;
|
|
||||||
} else if(index == 0xffc0) {
|
|
||||||
mapper = HiROM;
|
|
||||||
} else { //index == 0x40ffc0
|
|
||||||
mapper = ExHiROM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
|
||||||
has_superfx = true;
|
|
||||||
mapper = SuperFXROM;
|
|
||||||
ram_size = 1024 << (data[index - 3] & 7);
|
|
||||||
if(ram_size == 1024) ram_size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
|
||||||
has_sa1 = true;
|
|
||||||
mapper = SA1ROM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x35 && rom_type == 0x55) {
|
|
||||||
has_srtc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
|
||||||
has_sdd1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
|
||||||
has_spc7110 = true;
|
|
||||||
has_spc7110rtc = (rom_type == 0xf9);
|
|
||||||
mapper = SPC7110ROM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x20 && rom_type == 0xf3) {
|
|
||||||
has_cx4 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
|
|
||||||
has_dsp1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
|
||||||
has_dsp1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
|
||||||
has_dsp1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(has_dsp1 == true) {
|
|
||||||
if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
|
|
||||||
dsp1_mapper = DSP1LoROM1MB;
|
|
||||||
} else if((mapperid & 0x2f) == 0x20) {
|
|
||||||
dsp1_mapper = DSP1LoROM2MB;
|
|
||||||
} else if((mapperid & 0x2f) == 0x21) {
|
|
||||||
dsp1_mapper = DSP1HiROM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x20 && rom_type == 0x05) {
|
|
||||||
has_dsp2 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
|
||||||
has_dsp3 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0x03) {
|
|
||||||
has_dsp4 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0x25) {
|
|
||||||
has_obc1 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
|
||||||
has_st010 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
|
||||||
has_st011 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mapperid == 0x30 && rom_type == 0xf5) {
|
|
||||||
has_st018 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SuperFamicomCartridge::find_header(const uint8_t *data, unsigned size) {
|
|
||||||
unsigned score_lo = score_header(data, size, 0x007fc0);
|
|
||||||
unsigned score_hi = score_header(data, size, 0x00ffc0);
|
|
||||||
unsigned score_ex = score_header(data, size, 0x40ffc0);
|
|
||||||
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
|
||||||
|
|
||||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
|
||||||
return 0x007fc0;
|
|
||||||
} else if(score_hi >= score_ex) {
|
|
||||||
return 0x00ffc0;
|
|
||||||
} else {
|
|
||||||
return 0x40ffc0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned SuperFamicomCartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) {
|
|
||||||
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
|
||||||
int score = 0;
|
|
||||||
|
|
||||||
uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
|
||||||
uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
|
||||||
uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
|
||||||
|
|
||||||
uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
|
||||||
uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
|
||||||
|
|
||||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
|
||||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
|
||||||
if(resetvector < 0x8000) return 0;
|
|
||||||
|
|
||||||
//some images duplicate the header in multiple locations, and others have completely
|
|
||||||
//invalid header information that cannot be relied upon.
|
|
||||||
//below code will analyze the first opcode executed at the specified reset vector to
|
|
||||||
//determine the probability that this is the correct header.
|
|
||||||
|
|
||||||
//most likely opcodes
|
|
||||||
if(resetop == 0x78 //sei
|
|
||||||
|| resetop == 0x18 //clc (clc; xce)
|
|
||||||
|| resetop == 0x38 //sec (sec; xce)
|
|
||||||
|| resetop == 0x9c //stz $nnnn (stz $4200)
|
|
||||||
|| resetop == 0x4c //jmp $nnnn
|
|
||||||
|| resetop == 0x5c //jml $nnnnnn
|
|
||||||
) score += 8;
|
|
||||||
|
|
||||||
//plausible opcodes
|
|
||||||
if(resetop == 0xc2 //rep #$nn
|
|
||||||
|| resetop == 0xe2 //sep #$nn
|
|
||||||
|| resetop == 0xad //lda $nnnn
|
|
||||||
|| resetop == 0xae //ldx $nnnn
|
|
||||||
|| resetop == 0xac //ldy $nnnn
|
|
||||||
|| resetop == 0xaf //lda $nnnnnn
|
|
||||||
|| resetop == 0xa9 //lda #$nn
|
|
||||||
|| resetop == 0xa2 //ldx #$nn
|
|
||||||
|| resetop == 0xa0 //ldy #$nn
|
|
||||||
|| resetop == 0x20 //jsr $nnnn
|
|
||||||
|| resetop == 0x22 //jsl $nnnnnn
|
|
||||||
) score += 4;
|
|
||||||
|
|
||||||
//implausible opcodes
|
|
||||||
if(resetop == 0x40 //rti
|
|
||||||
|| resetop == 0x60 //rts
|
|
||||||
|| resetop == 0x6b //rtl
|
|
||||||
|| resetop == 0xcd //cmp $nnnn
|
|
||||||
|| resetop == 0xec //cpx $nnnn
|
|
||||||
|| resetop == 0xcc //cpy $nnnn
|
|
||||||
) score -= 4;
|
|
||||||
|
|
||||||
//least likely opcodes
|
|
||||||
if(resetop == 0x00 //brk #$nn
|
|
||||||
|| resetop == 0x02 //cop #$nn
|
|
||||||
|| resetop == 0xdb //stp
|
|
||||||
|| resetop == 0x42 //wdm
|
|
||||||
|| resetop == 0xff //sbc $nnnnnn,x
|
|
||||||
) score -= 8;
|
|
||||||
|
|
||||||
//at times, both the header and reset vector's first opcode will match ...
|
|
||||||
//fallback and rely on info validity in these cases to determine more likely header.
|
|
||||||
|
|
||||||
//a valid checksum is the biggest indicator of a valid header.
|
|
||||||
if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
|
|
||||||
|
|
||||||
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
|
|
||||||
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
|
|
||||||
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
|
|
||||||
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
|
|
||||||
|
|
||||||
if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header
|
|
||||||
if(data[addr + RomType] < 0x08) score++;
|
|
||||||
if(data[addr + RomSize] < 0x10) score++;
|
|
||||||
if(data[addr + RamSize] < 0x08) score++;
|
|
||||||
if(data[addr + CartRegion] < 14) score++;
|
|
||||||
|
|
||||||
if(score < 0) score = 0;
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -29,7 +29,7 @@ namespace nall {
|
||||||
for(signed i = 1, j; i < size; i++) {
|
for(signed i = 1, j; i < size; i++) {
|
||||||
T copy = std::move(list[i]);
|
T copy = std::move(list[i]);
|
||||||
for(j = i - 1; j >= 0; j--) {
|
for(j = i - 1; j >= 0; j--) {
|
||||||
if(lessthan(list[j], copy)) break;
|
if(!lessthan(copy, list[j])) break;
|
||||||
list[j + 1] = std::move(list[j]);
|
list[j + 1] = std::move(list[j]);
|
||||||
}
|
}
|
||||||
list[j + 1] = std::move(copy);
|
list[j + 1] = std::move(copy);
|
||||||
|
@ -55,7 +55,7 @@ namespace nall {
|
||||||
T *buffer = new T[size];
|
T *buffer = new T[size];
|
||||||
unsigned offset = 0, left = 0, right = middle;
|
unsigned offset = 0, left = 0, right = middle;
|
||||||
while(left < middle && right < size) {
|
while(left < middle && right < size) {
|
||||||
if(lessthan(list[left], list[right])) {
|
if(!lessthan(list[right], list[left])) {
|
||||||
buffer[offset++] = std::move(list[left++]);
|
buffer[offset++] = std::move(list[left++]);
|
||||||
} else {
|
} else {
|
||||||
buffer[offset++] = std::move(list[right++]);
|
buffer[offset++] = std::move(list[right++]);
|
||||||
|
|
|
@ -15,6 +15,11 @@ ifeq ($(platform),x)
|
||||||
else ifeq ($(platform),win)
|
else ifeq ($(platform),win)
|
||||||
phoenixflags := -DPHOENIX_WINDOWS
|
phoenixflags := -DPHOENIX_WINDOWS
|
||||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||||
|
|
||||||
|
ifeq ($(arch),win32)
|
||||||
|
phoenixflags := -m32 $(phoenixflags)
|
||||||
|
phoenixlink := -m32 $(phoenixlink)
|
||||||
|
endif
|
||||||
else
|
else
|
||||||
phoenixflags := -DPHOENIX_REFERENCE
|
phoenixflags := -DPHOENIX_REFERENCE
|
||||||
phoenixlink :=
|
phoenixlink :=
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
system name:Famicom
|
|
@ -1,3 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<system name="Famicom">
|
|
||||||
</system>
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
system name:Game Boy Advance
|
||||||
|
cpu
|
||||||
|
rom name=bios.rom size=16384
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<system name="Game Boy Advance">
|
|
||||||
<cpu>
|
|
||||||
<firmware name="bios.rom" size="16384" sha256="fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570"/>
|
|
||||||
</cpu>
|
|
||||||
</system>
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
system name:Game Boy Color
|
||||||
|
cpu
|
||||||
|
rom name=boot.rom size=2048
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<system name="Game Boy Color">
|
|
||||||
<cpu>
|
|
||||||
<firmware name="boot.rom" size="2048" sha256="4bf5021be357ce523a59ac5f4efff5d6371ae50112a6db0adf4a75916ad760a9"/>
|
|
||||||
</cpu>
|
|
||||||
</system>
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
system name:Game Boy
|
||||||
|
cpu
|
||||||
|
rom name=boot.rom size=256
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<system name="Game Boy">
|
|
||||||
<cpu>
|
|
||||||
<firmware name="boot.rom" size="256" sha256="cf053eccb4ccafff9e67339d4e78e98dce7d1ed59be819d2a1ba2232c6fce1c7"/>
|
|
||||||
</cpu>
|
|
||||||
</system>
|
|
0
higan/profile/Super Famicom.sys/spc700.rom → higan/profile/Super Famicom.sys/ipl.rom
Executable file → Normal file
0
higan/profile/Super Famicom.sys/spc700.rom → higan/profile/Super Famicom.sys/ipl.rom
Executable file → Normal file
|
@ -1,3 +1,3 @@
|
||||||
system name:Super Famicom
|
system name:Super Famicom
|
||||||
smp
|
smp
|
||||||
rom name=spc700.rom size=64
|
rom name=ipl.rom size=64
|
||||||
|
|
|
@ -23,4 +23,9 @@ else ifeq ($(platform),osx)
|
||||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
||||||
else ifeq ($(platform),win)
|
else ifeq ($(platform),win)
|
||||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
||||||
|
|
||||||
|
ifeq ($(arch),win32)
|
||||||
|
rubyflags := -m32 $(rubyflags)
|
||||||
|
rubylink := -m32 $(rubylink)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -15,12 +15,12 @@ ifeq ($(profile),accuracy)
|
||||||
sfcsmp := $(sfc)/smp
|
sfcsmp := $(sfc)/smp
|
||||||
sfcdsp := $(sfc)/dsp
|
sfcdsp := $(sfc)/dsp
|
||||||
sfcppu := $(sfc)/ppu
|
sfcppu := $(sfc)/ppu
|
||||||
else ifeq ($(profile),compatibility)
|
else ifeq ($(profile),balanced)
|
||||||
flags += -DPROFILE_COMPATIBILITY
|
flags += -DPROFILE_BALANCED
|
||||||
sfccpu := $(sfc)/cpu
|
sfccpu := $(sfc)/cpu
|
||||||
sfcsmp := $(sfc)/smp
|
sfcsmp := $(sfc)/smp
|
||||||
sfcdsp := $(sfc)/alt/dsp
|
sfcdsp := $(sfc)/alt/dsp
|
||||||
sfcppu := $(sfc)/alt/ppu-compatibility
|
sfcppu := $(sfc)/alt/ppu-balanced
|
||||||
else ifeq ($(profile),performance)
|
else ifeq ($(profile),performance)
|
||||||
flags += -DPROFILE_PERFORMANCE
|
flags += -DPROFILE_PERFORMANCE
|
||||||
sfccpu := $(sfc)/alt/cpu
|
sfccpu := $(sfc)/alt/cpu
|
||||||
|
@ -29,36 +29,36 @@ else ifeq ($(profile),performance)
|
||||||
sfcppu := $(sfc)/alt/ppu-performance
|
sfcppu := $(sfc)/alt/ppu-performance
|
||||||
endif
|
endif
|
||||||
|
|
||||||
obj/sfc-interface.o : $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface)
|
obj/sfc-interface.o: $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface)
|
||||||
obj/sfc-system.o : $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/)
|
obj/sfc-system.o: $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/)
|
||||||
obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/)
|
obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/)
|
||||||
obj/sfc-cartridge.o : $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
|
obj/sfc-cartridge.o: $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
|
||||||
obj/sfc-cheat.o : $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
|
obj/sfc-cheat.o: $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
|
||||||
obj/sfc-memory.o : $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/)
|
obj/sfc-memory.o: $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/)
|
||||||
obj/sfc-cpu.o : $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/)
|
obj/sfc-cpu.o: $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/)
|
||||||
obj/sfc-smp.o : $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/)
|
obj/sfc-smp.o: $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/)
|
||||||
obj/sfc-dsp.o : $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/)
|
obj/sfc-dsp.o: $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/)
|
||||||
obj/sfc-ppu.o : $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/)
|
obj/sfc-ppu.o: $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/)
|
||||||
|
|
||||||
obj/sfc-icd2.o : $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
|
obj/sfc-icd2.o: $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
|
||||||
obj/sfc-bsx.o : $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/)
|
obj/sfc-bsx.o: $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/)
|
||||||
obj/sfc-sufamiturbo.o: $(sfc)/chip/sufamiturbo/sufamiturbo.cpp $(sfc)/chip/sufamiturbo/*
|
obj/sfc-sufamiturbo.o: $(sfc)/chip/sufamiturbo/sufamiturbo.cpp $(sfc)/chip/sufamiturbo/*
|
||||||
obj/sfc-nss.o : $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/)
|
obj/sfc-nss.o: $(sfc)/chip/nss/nss.cpp $(call rwildcard,$(sfc)/chip/nss/)
|
||||||
obj/sfc-event.o : $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/)
|
obj/sfc-event.o: $(sfc)/chip/event/event.cpp $(call rwildcard,$(sfc)/chip/event/)
|
||||||
|
|
||||||
obj/sfc-sa1.o : $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/)
|
obj/sfc-sa1.o: $(sfc)/chip/sa1/sa1.cpp $(call rwildcard,$(sfc)/chip/sa1/)
|
||||||
obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/)
|
obj/sfc-superfx.o: $(sfc)/chip/superfx/superfx.cpp $(call rwildcard,$(sfc)/chip/superfx/)
|
||||||
|
|
||||||
obj/sfc-armdsp.o : $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/)
|
obj/sfc-armdsp.o: $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chip/armdsp/)
|
||||||
obj/sfc-hitachidsp.o: $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/)
|
obj/sfc-hitachidsp.o: $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/)
|
||||||
obj/sfc-necdsp.o : $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
|
obj/sfc-necdsp.o: $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
|
||||||
|
|
||||||
obj/sfc-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/)
|
obj/sfc-epsonrtc.o: $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/)
|
||||||
obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/)
|
obj/sfc-sharprtc.o: $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/)
|
||||||
|
|
||||||
obj/sfc-spc7110.o: $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
|
obj/sfc-spc7110.o: $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
|
||||||
obj/sfc-sdd1.o : $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/*
|
obj/sfc-sdd1.o: $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/*
|
||||||
obj/sfc-obc1.o : $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
|
obj/sfc-obc1.o: $(sfc)/chip/obc1/obc1.cpp $(sfc)/chip/obc1/*
|
||||||
|
|
||||||
obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/*
|
obj/sfc-hsu1.o: $(sfc)/chip/hsu1/hsu1.cpp $(sfc)/chip/hsu1/*
|
||||||
obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/*
|
obj/sfc-msu1.o: $(sfc)/chip/msu1/msu1.cpp $(sfc)/chip/msu1/*
|
||||||
|
|
0
higan/sfc/alt/ppu-compatibility/memory/memory.cpp → higan/sfc/alt/ppu-balanced/memory/memory.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/memory/memory.cpp → higan/sfc/alt/ppu-balanced/memory/memory.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/memory/memory.hpp → higan/sfc/alt/ppu-balanced/memory/memory.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/memory/memory.hpp → higan/sfc/alt/ppu-balanced/memory/memory.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/mmio/mmio.cpp → higan/sfc/alt/ppu-balanced/mmio/mmio.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/mmio/mmio.cpp → higan/sfc/alt/ppu-balanced/mmio/mmio.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/mmio/mmio.hpp → higan/sfc/alt/ppu-balanced/mmio/mmio.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/mmio/mmio.hpp → higan/sfc/alt/ppu-balanced/mmio/mmio.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/ppu.cpp → higan/sfc/alt/ppu-balanced/ppu.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/ppu.cpp → higan/sfc/alt/ppu-balanced/ppu.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/ppu.hpp → higan/sfc/alt/ppu-balanced/ppu.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/ppu.hpp → higan/sfc/alt/ppu-balanced/ppu.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/addsub.cpp → higan/sfc/alt/ppu-balanced/render/addsub.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/addsub.cpp → higan/sfc/alt/ppu-balanced/render/addsub.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/bg.cpp → higan/sfc/alt/ppu-balanced/render/bg.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/bg.cpp → higan/sfc/alt/ppu-balanced/render/bg.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/cache.cpp → higan/sfc/alt/ppu-balanced/render/cache.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/cache.cpp → higan/sfc/alt/ppu-balanced/render/cache.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/line.cpp → higan/sfc/alt/ppu-balanced/render/line.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/line.cpp → higan/sfc/alt/ppu-balanced/render/line.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/mode7.cpp → higan/sfc/alt/ppu-balanced/render/mode7.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/mode7.cpp → higan/sfc/alt/ppu-balanced/render/mode7.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/oam.cpp → higan/sfc/alt/ppu-balanced/render/oam.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/oam.cpp → higan/sfc/alt/ppu-balanced/render/oam.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/render.cpp → higan/sfc/alt/ppu-balanced/render/render.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/render.cpp → higan/sfc/alt/ppu-balanced/render/render.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/render.hpp → higan/sfc/alt/ppu-balanced/render/render.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/render.hpp → higan/sfc/alt/ppu-balanced/render/render.hpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/windows.cpp → higan/sfc/alt/ppu-balanced/render/windows.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/render/windows.cpp → higan/sfc/alt/ppu-balanced/render/windows.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/serialization.cpp → higan/sfc/alt/ppu-balanced/serialization.cpp
Executable file → Normal file
0
higan/sfc/alt/ppu-compatibility/serialization.cpp → higan/sfc/alt/ppu-balanced/serialization.cpp
Executable file → Normal file
|
@ -49,15 +49,13 @@ void Cartridge::load(const string &manifest) {
|
||||||
has_hsu1 = false;
|
has_hsu1 = false;
|
||||||
has_msu1 = false;
|
has_msu1 = false;
|
||||||
|
|
||||||
information.title.cartridge = "";
|
information.title.cartridge = "";
|
||||||
information.title.gameBoy = "";
|
information.title.gameBoy = "";
|
||||||
information.title.satellaview = "";
|
information.title.satellaview = "";
|
||||||
information.title.sufamiTurboA = "";
|
information.title.sufamiTurboA = "";
|
||||||
information.title.sufamiTurboB = "";
|
information.title.sufamiTurboB = "";
|
||||||
|
|
||||||
this->manifest = manifest;
|
parse_markup(information.markup = manifest);
|
||||||
parse_markup(manifest);
|
|
||||||
//print(manifest, "\n\n");
|
|
||||||
|
|
||||||
//Super Game Boy
|
//Super Game Boy
|
||||||
if(cartridge.has_gb_slot()) {
|
if(cartridge.has_gb_slot()) {
|
||||||
|
@ -77,6 +75,7 @@ void Cartridge::load(const string &manifest) {
|
||||||
sha256_chunk(&sha, sufamiturbo.slotA.rom.data(), sufamiturbo.slotA.rom.size());
|
sha256_chunk(&sha, sufamiturbo.slotA.rom.data(), sufamiturbo.slotA.rom.size());
|
||||||
sha256_chunk(&sha, sufamiturbo.slotB.rom.data(), sufamiturbo.slotB.rom.size());
|
sha256_chunk(&sha, sufamiturbo.slotB.rom.data(), sufamiturbo.slotB.rom.size());
|
||||||
sha256_final(&sha);
|
sha256_final(&sha);
|
||||||
|
sha256_hash(&sha, hash);
|
||||||
string result;
|
string result;
|
||||||
for(auto &byte : hash) result.append(hex<2>(byte));
|
for(auto &byte : hash) result.append(hex<2>(byte));
|
||||||
sha256 = result;
|
sha256 = result;
|
||||||
|
@ -122,6 +121,7 @@ void Cartridge::load(const string &manifest) {
|
||||||
void Cartridge::load_super_game_boy(const string &manifest) {
|
void Cartridge::load_super_game_boy(const string &manifest) {
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
information.title.gameBoy = document["information/title"].text();
|
information.title.gameBoy = document["information/title"].text();
|
||||||
|
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
|
@ -135,6 +135,7 @@ void Cartridge::load_super_game_boy(const string &manifest) {
|
||||||
void Cartridge::load_satellaview(const string &manifest) {
|
void Cartridge::load_satellaview(const string &manifest) {
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
information.title.satellaview = document["information/title"].text();
|
information.title.satellaview = document["information/title"].text();
|
||||||
|
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
|
|
||||||
if(rom["name"].exists()) {
|
if(rom["name"].exists()) {
|
||||||
|
@ -147,6 +148,7 @@ void Cartridge::load_satellaview(const string &manifest) {
|
||||||
void Cartridge::load_sufami_turbo_a(const string &manifest) {
|
void Cartridge::load_sufami_turbo_a(const string &manifest) {
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
information.title.sufamiTurboA = document["information/title"].text();
|
information.title.sufamiTurboA = document["information/title"].text();
|
||||||
|
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
|
@ -171,6 +173,7 @@ void Cartridge::load_sufami_turbo_a(const string &manifest) {
|
||||||
void Cartridge::load_sufami_turbo_b(const string &manifest) {
|
void Cartridge::load_sufami_turbo_b(const string &manifest) {
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
information.title.sufamiTurboB = document["information/title"].text();
|
information.title.sufamiTurboB = document["information/title"].text();
|
||||||
|
|
||||||
auto rom = document["cartridge/rom"];
|
auto rom = document["cartridge/rom"];
|
||||||
auto ram = document["cartridge/ram"];
|
auto ram = document["cartridge/ram"];
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ struct Cartridge : property<Cartridge> {
|
||||||
|
|
||||||
readonly<bool> loaded;
|
readonly<bool> loaded;
|
||||||
readonly<string> sha256;
|
readonly<string> sha256;
|
||||||
readonly<string> manifest;
|
|
||||||
|
|
||||||
readonly<Region> region;
|
readonly<Region> region;
|
||||||
|
|
||||||
|
@ -62,6 +61,7 @@ struct Cartridge : property<Cartridge> {
|
||||||
vector<Memory> memory;
|
vector<Memory> memory;
|
||||||
|
|
||||||
struct Information {
|
struct Information {
|
||||||
|
string markup;
|
||||||
struct Title {
|
struct Title {
|
||||||
string cartridge;
|
string cartridge;
|
||||||
string gameBoy;
|
string gameBoy;
|
||||||
|
@ -70,6 +70,7 @@ struct Cartridge : property<Cartridge> {
|
||||||
string sufamiTurboB;
|
string sufamiTurboB;
|
||||||
} title;
|
} title;
|
||||||
} information;
|
} information;
|
||||||
|
|
||||||
string title();
|
string title();
|
||||||
|
|
||||||
void load(const string &manifest);
|
void load(const string &manifest);
|
||||||
|
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
void Cartridge::parse_markup(const char *markup) {
|
void Cartridge::parse_markup(const char *markup) {
|
||||||
auto document = Markup::Document(markup);
|
auto document = Markup::Document(markup);
|
||||||
auto cartridge = document["cartridge"];
|
information.title.cartridge = document["information/title"].text();
|
||||||
auto information = document["information"];
|
|
||||||
region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL;
|
|
||||||
|
|
||||||
this->information.title.cartridge = information["title"].text();
|
auto cartridge = document["cartridge"];
|
||||||
|
region = cartridge["region"].data != "PAL" ? Region::NTSC : Region::PAL;
|
||||||
|
|
||||||
mapping.reset();
|
mapping.reset();
|
||||||
parse_markup_cartridge(cartridge);
|
parse_markup_cartridge(cartridge);
|
||||||
|
@ -138,11 +137,13 @@ void Cartridge::parse_markup_bsxslot(Markup::Node root) {
|
||||||
if(node["id"].data == "rom") {
|
if(node["id"].data == "rom") {
|
||||||
if(bsxflash.memory.size() == 0) continue;
|
if(bsxflash.memory.size() == 0) continue;
|
||||||
|
|
||||||
Mapping m(bsxflash.memory);
|
Mapping m(bsxflash);
|
||||||
parse_markup_map(m, node);
|
parse_markup_map(m, node);
|
||||||
mapping.append(m);
|
mapping.append(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bsxflash.readonly = (root["rom/type"].text() == "MaskROM");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
|
void Cartridge::parse_markup_sufamiturbo(Markup::Node root) {
|
||||||
|
@ -253,8 +254,8 @@ void Cartridge::parse_markup_sa1(Markup::Node root) {
|
||||||
has_sa1 = true;
|
has_sa1 = true;
|
||||||
|
|
||||||
parse_markup_memory(sa1.rom, root["rom"], ID::SA1ROM, false);
|
parse_markup_memory(sa1.rom, root["rom"], ID::SA1ROM, false);
|
||||||
parse_markup_memory(sa1.bwram, root["ram(id=bitmap)"], ID::SA1BWRAM, true);
|
parse_markup_memory(sa1.bwram, root["ram[0]"], ID::SA1BWRAM, true);
|
||||||
parse_markup_memory(sa1.iram, root["ram(id=internal)"], ID::SA1IRAM, true);
|
parse_markup_memory(sa1.iram, root["ram[1]"], ID::SA1IRAM, true);
|
||||||
|
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
|
@ -322,9 +323,9 @@ void Cartridge::parse_markup_armdsp(Markup::Node root) {
|
||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
has_armdsp = true;
|
has_armdsp = true;
|
||||||
|
|
||||||
string programROMName = root["rom(id=program)/name"].data;
|
string programROMName = root["rom[0]/name"].data;
|
||||||
string dataROMName = root["rom(id=data)/name"].data;
|
string dataROMName = root["rom[1]/name"].data;
|
||||||
string dataRAMName = root["ram(id=data)/name"].data;
|
string dataRAMName = root["ram/name"].data;
|
||||||
|
|
||||||
interface->loadRequest(ID::ArmDSPPROM, programROMName);
|
interface->loadRequest(ID::ArmDSPPROM, programROMName);
|
||||||
interface->loadRequest(ID::ArmDSPDROM, dataROMName);
|
interface->loadRequest(ID::ArmDSPDROM, dataROMName);
|
||||||
|
@ -348,6 +349,9 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) {
|
||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
has_hitachidsp = true;
|
has_hitachidsp = true;
|
||||||
|
|
||||||
|
parse_markup_memory(hitachidsp.rom, root["rom[0]"], ID::HitachiDSPROM, false);
|
||||||
|
parse_markup_memory(hitachidsp.ram, root["ram[0]"], ID::HitachiDSPRAM, true);
|
||||||
|
|
||||||
for(auto &n : hitachidsp.dataROM) hitachidsp.dataROM[n] = 0x000000;
|
for(auto &n : hitachidsp.dataROM) hitachidsp.dataROM[n] = 0x000000;
|
||||||
for(auto &n : hitachidsp.dataRAM) hitachidsp.dataRAM[n] = 0x00;
|
for(auto &n : hitachidsp.dataRAM) hitachidsp.dataRAM[n] = 0x00;
|
||||||
|
|
||||||
|
@ -355,17 +359,14 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) {
|
||||||
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
||||||
hitachidsp.Roms = roms;
|
hitachidsp.Roms = roms;
|
||||||
|
|
||||||
string dataROMName = root["rom(id=data)/name"].data;
|
string dataROMName = root["rom[1]/name"].data;
|
||||||
string dataRAMName = root["ram(id=data)/name"].data;
|
string dataRAMName = root["ram[1]/name"].data;
|
||||||
|
|
||||||
interface->loadRequest(ID::HitachiDSPDROM, dataROMName);
|
interface->loadRequest(ID::HitachiDSPDROM, dataROMName);
|
||||||
if(dataRAMName.empty() == false) {
|
if(dataRAMName.empty() == false) {
|
||||||
interface->loadRequest(ID::HitachiDSPDRAM, dataRAMName);
|
interface->loadRequest(ID::HitachiDSPDRAM, dataRAMName);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_markup_memory(hitachidsp.rom, root["rom(id=program)"], ID::HitachiDSPROM, false);
|
|
||||||
parse_markup_memory(hitachidsp.ram, root["ram(id=program)"], ID::HitachiDSPRAM, true);
|
|
||||||
|
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
if(node.name != "map") continue;
|
if(node.name != "map") continue;
|
||||||
|
|
||||||
|
@ -406,9 +407,9 @@ void Cartridge::parse_markup_necdsp(Markup::Node root) {
|
||||||
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
|
: root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050
|
||||||
: NECDSP::Revision::uPD7725;
|
: NECDSP::Revision::uPD7725;
|
||||||
|
|
||||||
string programROMName = root["rom(id=program)/name"].data;
|
string programROMName = root["rom[0]/name"].data;
|
||||||
string dataROMName = root["rom(id=data)/name"].data;
|
string dataROMName = root["rom[1]/name"].data;
|
||||||
string dataRAMName = root["ram(id=data)/name"].data;
|
string dataRAMName = root["ram/name"].data;
|
||||||
|
|
||||||
if(necdsp.revision == NECDSP::Revision::uPD7725) {
|
if(necdsp.revision == NECDSP::Revision::uPD7725) {
|
||||||
interface->loadRequest(ID::Nec7725DSPPROM, programROMName);
|
interface->loadRequest(ID::Nec7725DSPPROM, programROMName);
|
||||||
|
@ -488,8 +489,8 @@ void Cartridge::parse_markup_spc7110(Markup::Node root) {
|
||||||
if(root.exists() == false) return;
|
if(root.exists() == false) return;
|
||||||
has_spc7110 = true;
|
has_spc7110 = true;
|
||||||
|
|
||||||
parse_markup_memory(spc7110.prom, root["rom(id=program)"], ID::SPC7110PROM, false);
|
parse_markup_memory(spc7110.prom, root["rom[0]"], ID::SPC7110PROM, false);
|
||||||
parse_markup_memory(spc7110.drom, root["rom(id=data)"], ID::SPC7110DROM, false);
|
parse_markup_memory(spc7110.drom, root["rom[1]"], ID::SPC7110DROM, false);
|
||||||
parse_markup_memory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
|
parse_markup_memory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
|
||||||
|
|
||||||
for(auto &node : root) {
|
for(auto &node : root) {
|
||||||
|
|
|
@ -34,6 +34,8 @@ unsigned BSXFlash::size() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 BSXFlash::read(unsigned addr) {
|
uint8 BSXFlash::read(unsigned addr) {
|
||||||
|
if(readonly) return memory.read(bus.mirror(addr, memory.size()));
|
||||||
|
|
||||||
if(addr == 0x0002) {
|
if(addr == 0x0002) {
|
||||||
if(regs.flash_enable) return 0x80;
|
if(regs.flash_enable) return 0x80;
|
||||||
}
|
}
|
||||||
|
@ -45,15 +47,15 @@ uint8 BSXFlash::read(unsigned addr) {
|
||||||
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
|
if(regs.read_enable && addr >= 0xff00 && addr <= 0xff13) {
|
||||||
//read flash cartridge vendor information
|
//read flash cartridge vendor information
|
||||||
switch(addr - 0xff00) {
|
switch(addr - 0xff00) {
|
||||||
case 0x00: return 0x4d;
|
case 0x00: return 0x4d;
|
||||||
case 0x01: return 0x00;
|
case 0x01: return 0x00;
|
||||||
case 0x02: return 0x50;
|
case 0x02: return 0x50;
|
||||||
case 0x03: return 0x00;
|
case 0x03: return 0x00;
|
||||||
case 0x04: return 0x00;
|
case 0x04: return 0x00;
|
||||||
case 0x05: return 0x00;
|
case 0x05: return 0x00;
|
||||||
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
case 0x06: return 0x2a; //0x2a = 8mbit, 0x2b = 16mbit (not known to exist, though BIOS recognizes ID)
|
||||||
case 0x07: return 0x00;
|
case 0x07: return 0x00;
|
||||||
default: return 0x00;
|
default: return 0x00;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,15 +63,7 @@ uint8 BSXFlash::read(unsigned addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSXFlash::write(unsigned addr, uint8 data) {
|
void BSXFlash::write(unsigned addr, uint8 data) {
|
||||||
//there exist both read-only and read-write BS-X flash cartridges ...
|
if(readonly) return;
|
||||||
//unfortunately, the vendor info is not stored inside memory dumps
|
|
||||||
//of BS-X flashcarts, so it is impossible to determine whether a
|
|
||||||
//given flashcart is writeable.
|
|
||||||
//however, it has been observed that LoROM-mapped BS-X carts always
|
|
||||||
//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((addr & 0xff0000) == 0) {
|
if((addr & 0xff0000) == 0) {
|
||||||
regs.write_old = regs.write_new;
|
regs.write_old = regs.write_new;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
struct BSXFlash : Memory {
|
struct BSXFlash : Memory {
|
||||||
MappedRAM memory;
|
MappedRAM memory;
|
||||||
|
bool readonly;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void load();
|
void load();
|
||||||
|
|
|
@ -87,25 +87,24 @@ void MSU1::reset() {
|
||||||
|
|
||||||
void MSU1::data_open() {
|
void MSU1::data_open() {
|
||||||
if(datafile.open()) datafile.close();
|
if(datafile.open()) datafile.close();
|
||||||
XML::Document document(cartridge.manifest());
|
auto document = Markup::Document(cartridge.information.markup);
|
||||||
string name = document["cartridge"]["msu1"]["rom"]["name"].data;
|
string name = document["cartridge/msu1/rom/name"].data;
|
||||||
if(name.empty()) name = "msu1.rom";
|
if(name.empty()) name = "msu1.rom";
|
||||||
if(datafile.open({interface->path(0), name}, file::mode::read)) {
|
if(datafile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
|
||||||
datafile.seek(mmio.data_offset);
|
datafile.seek(mmio.data_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSU1::audio_open() {
|
void MSU1::audio_open() {
|
||||||
if(audiofile.open()) audiofile.close();
|
if(audiofile.open()) audiofile.close();
|
||||||
XML::Document document(cartridge.manifest());
|
auto document = Markup::Document(cartridge.information.markup);
|
||||||
string name = {"track-", mmio.audio_track, ".pcm"};
|
string name = {"track-", mmio.audio_track, ".pcm"};
|
||||||
for(auto &track : document["cartridge"]["msu1"]) {
|
for(auto &track : document.find("cartridge/msu1/track")) {
|
||||||
if(track.name != "track") continue;
|
|
||||||
if(numeral(track["number"].data) != mmio.audio_track) continue;
|
if(numeral(track["number"].data) != mmio.audio_track) continue;
|
||||||
name = track["name"].data;
|
name = track["name"].data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(audiofile.open({interface->path(0), name}, file::mode::read)) {
|
if(audiofile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
|
||||||
audiofile.seek(mmio.audio_offset);
|
audiofile.seek(mmio.audio_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ USART::USART(bool port) : Controller(port) {
|
||||||
txlength = 0;
|
txlength = 0;
|
||||||
txdata = 0;
|
txdata = 0;
|
||||||
|
|
||||||
string filename = {interface->path(0), "usart.so"};
|
string filename = {interface->path(ID::SuperFamicom), "usart.so"};
|
||||||
if(open_absolute(filename)) {
|
if(open_absolute(filename)) {
|
||||||
init = sym("usart_init");
|
init = sym("usart_init");
|
||||||
main = sym("usart_main");
|
main = sym("usart_main");
|
||||||
|
|
|
@ -86,7 +86,6 @@ unsigned Interface::group(unsigned id) {
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
print(id, "\n");
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,10 +375,10 @@ Interface::Interface() {
|
||||||
information.capability.states = true;
|
information.capability.states = true;
|
||||||
information.capability.cheats = true;
|
information.capability.cheats = true;
|
||||||
|
|
||||||
media.append({ID::SuperFamicom, "Super Famicom", "sfc", true});
|
media.append({ID::SuperFamicom, "Super Famicom", "sfc", true });
|
||||||
media.append({ID::SuperFamicom, "Super Game Boy", "gb", false});
|
media.append({ID::SuperFamicom, "Super Famicom", "gb", false});
|
||||||
media.append({ID::SuperFamicom, "BS-X Satellaview", "bs", false});
|
media.append({ID::SuperFamicom, "Super Famicom", "bs", false});
|
||||||
media.append({ID::SuperFamicom, "Sufami Turbo", "st", false});
|
media.append({ID::SuperFamicom, "Super Famicom", "st", false});
|
||||||
|
|
||||||
{
|
{
|
||||||
Device device{0, ID::Port1 | ID::Port2, "Controller"};
|
Device device{0, ID::Port1 | ID::Port2, "Controller"};
|
||||||
|
|
4
higan/sfc/profile-compatibility.hpp → higan/sfc/profile-balanced.hpp
Executable file → Normal file
4
higan/sfc/profile-compatibility.hpp → higan/sfc/profile-balanced.hpp
Executable file → Normal file
|
@ -1,8 +1,8 @@
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Profile[] = "Compatibility";
|
static const char Profile[] = "Balanced";
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sfc/cpu/cpu.hpp>
|
#include <sfc/cpu/cpu.hpp>
|
||||||
#include <sfc/smp/smp.hpp>
|
#include <sfc/smp/smp.hpp>
|
||||||
#include <sfc/alt/dsp/dsp.hpp>
|
#include <sfc/alt/dsp/dsp.hpp>
|
||||||
#include <sfc/alt/ppu-compatibility/ppu.hpp>
|
#include <sfc/alt/ppu-balanced/ppu.hpp>
|
|
@ -57,8 +57,8 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
#if defined(PROFILE_ACCURACY)
|
#if defined(PROFILE_ACCURACY)
|
||||||
#include "profile-accuracy.hpp"
|
#include "profile-accuracy.hpp"
|
||||||
#elif defined(PROFILE_COMPATIBILITY)
|
#elif defined(PROFILE_BALANCED)
|
||||||
#include "profile-compatibility.hpp"
|
#include "profile-balanced.hpp"
|
||||||
#elif defined(PROFILE_PERFORMANCE)
|
#elif defined(PROFILE_PERFORMANCE)
|
||||||
#include "profile-performance.hpp"
|
#include "profile-performance.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -94,13 +94,12 @@ void System::term() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::load() {
|
void System::load() {
|
||||||
string path = interface->path(ID::System), manifest;
|
string manifest = string::read({interface->path(ID::System), "manifest.bml"});
|
||||||
manifest.readfile({path, "manifest.bml"});
|
|
||||||
auto document = Markup::Document(manifest);
|
auto document = Markup::Document(manifest);
|
||||||
string iplrom = document["system"]["smp"]["rom"]["name"].data;
|
|
||||||
interface->loadRequest(ID::IPLROM, iplrom);
|
interface->loadRequest(ID::IPLROM, document["system/smp/rom/name"].data);
|
||||||
if(!file::exists({interface->path(ID::System), iplrom})) {
|
if(!file::exists({interface->path(ID::System), document["system/smp/rom/name"].data})) {
|
||||||
interface->notify("Error: required firmware ", iplrom, " not found.\n");
|
interface->notify("Error: required Super Famicom firmware ipl.rom not found.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
region = config.region;
|
region = config.region;
|
||||||
|
|
|
@ -28,9 +28,7 @@ Browser::Browser() {
|
||||||
};
|
};
|
||||||
|
|
||||||
homeButton.onActivate = [&] {
|
homeButton.onActivate = [&] {
|
||||||
string pathname = {userpath(), "Emulation/"};
|
setPath({userpath(), "Emulation/"});
|
||||||
directory::create(pathname);
|
|
||||||
setPath(pathname);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
upButton.onActivate = [&] {
|
upButton.onActivate = [&] {
|
||||||
|
@ -147,7 +145,7 @@ void Browser::setPath(const string &path, unsigned selection) {
|
||||||
fileList.reset();
|
fileList.reset();
|
||||||
filenameList.reset();
|
filenameList.reset();
|
||||||
|
|
||||||
lstring contents = directory::contents(path);
|
lstring contents = directory::ifolders(path);
|
||||||
|
|
||||||
for(auto &filename : contents) {
|
for(auto &filename : contents) {
|
||||||
string suffix = {".", this->extension, "/"};
|
string suffix = {".", this->extension, "/"};
|
||||||
|
|
|
@ -59,7 +59,7 @@ Presentation::Presentation() : active(nullptr) {
|
||||||
setStatusVisible();
|
setStatusVisible();
|
||||||
|
|
||||||
loadMenu.setText("Library");
|
loadMenu.setText("Library");
|
||||||
loadImport.setText("Import Game ...");
|
loadImport.setText("Import Game ...");
|
||||||
settingsMenu.setText("Settings");
|
settingsMenu.setText("Settings");
|
||||||
videoMenu.setText("Video");
|
videoMenu.setText("Video");
|
||||||
centerVideo.setText("Center");
|
centerVideo.setText("Center");
|
||||||
|
@ -86,11 +86,8 @@ Presentation::Presentation() : active(nullptr) {
|
||||||
synchronizeTime.setText("Synchronize Time");
|
synchronizeTime.setText("Synchronize Time");
|
||||||
|
|
||||||
append(loadMenu);
|
append(loadMenu);
|
||||||
for(auto &item : loadListSystem) loadMenu.append(*item);
|
for(auto &item : loadListSystem) loadMenu.append(*item);
|
||||||
if(application->ananke.opened()) {
|
if(application->ananke.opened()) loadMenu.append(loadSeparator, loadImport);
|
||||||
loadMenu.append(loadSeparator);
|
|
||||||
loadMenu.append(loadImport);
|
|
||||||
}
|
|
||||||
for(auto &systemItem : emulatorList) append(systemItem->menu);
|
for(auto &systemItem : emulatorList) append(systemItem->menu);
|
||||||
append(settingsMenu);
|
append(settingsMenu);
|
||||||
settingsMenu.append(videoMenu);
|
settingsMenu.append(videoMenu);
|
||||||
|
@ -153,7 +150,7 @@ void Presentation::bootstrap() {
|
||||||
iEmulator->interface = emulator;
|
iEmulator->interface = emulator;
|
||||||
|
|
||||||
for(auto &media : emulator->media) {
|
for(auto &media : emulator->media) {
|
||||||
if(media.bootable == false) continue; //do not add sub-cartridge slot entries to menu
|
if(media.bootable == false) continue;
|
||||||
Item *item = new Item;
|
Item *item = new Item;
|
||||||
item->onActivate = [=, &media] {
|
item->onActivate = [=, &media] {
|
||||||
utility->loadMedia(iEmulator->interface, media);
|
utility->loadMedia(iEmulator->interface, media);
|
||||||
|
|
|
@ -226,7 +226,7 @@ void InputManager::poll() {
|
||||||
using nall::Keyboard;
|
using nall::Keyboard;
|
||||||
|
|
||||||
activeScancode = !activeScancode;
|
activeScancode = !activeScancode;
|
||||||
input.poll(scancode[activeScancode]);
|
if(input.poll(scancode[activeScancode]) == false) return;
|
||||||
|
|
||||||
for(unsigned n = 0; n < Scancode::Limit; n++) {
|
for(unsigned n = 0; n < Scancode::Limit; n++) {
|
||||||
if(scancode[0][n] != scancode[1][n]) {
|
if(scancode[0][n] != scancode[1][n]) {
|
||||||
|
|
|
@ -28,8 +28,8 @@ void Utility::loadMedia(string pathname) {
|
||||||
//determine type by comparing extension against all emulation cores
|
//determine type by comparing extension against all emulation cores
|
||||||
for(auto &emulator : application->emulator) {
|
for(auto &emulator : application->emulator) {
|
||||||
for(auto &media : emulator->media) {
|
for(auto &media : emulator->media) {
|
||||||
if(type != media.type) continue;
|
|
||||||
if(media.bootable == false) continue;
|
if(media.bootable == false) continue;
|
||||||
|
if(type != media.type) continue;
|
||||||
return utility->loadMedia(emulator, media, {pathname, "/"});
|
return utility->loadMedia(emulator, media, {pathname, "/"});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,6 @@ void Utility::loadMedia(Emulator::Interface *emulator, Emulator::Interface::Medi
|
||||||
system().load(media.id, string::read({pathname, "manifest.bml"}));
|
system().load(media.id, string::read({pathname, "manifest.bml"}));
|
||||||
system().power();
|
system().power();
|
||||||
|
|
||||||
if(this->pathname.size() == 0) this->pathname.append(pathname);
|
|
||||||
presentation->setSystemName(media.name);
|
presentation->setSystemName(media.name);
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
shader language=GLSL
|
|
||||||
vertex~
|
|
||||||
void main(void) {
|
|
||||||
gl_Position = ftransform();
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment~ filter=linear
|
|
||||||
uniform sampler2D rubyTexture;
|
|
||||||
|
|
||||||
void main(void) {
|
|
||||||
vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);
|
|
||||||
vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));
|
|
||||||
|
|
||||||
if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8;
|
|
||||||
gl_FragColor = intens;
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
shader language=GLSL
|
|
||||||
vertex~
|
|
||||||
uniform vec2 rubyTextureSize;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
float x = 0.5 * (1.0 / rubyTextureSize.x);
|
|
||||||
float y = 0.5 * (1.0 / rubyTextureSize.y);
|
|
||||||
vec2 dg1 = vec2( x, y);
|
|
||||||
vec2 dg2 = vec2(-x, y);
|
|
||||||
vec2 dx = vec2(x, 0.0);
|
|
||||||
vec2 dy = vec2(0.0, y);
|
|
||||||
|
|
||||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
|
||||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
|
||||||
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
|
|
||||||
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
|
|
||||||
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
|
|
||||||
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
|
|
||||||
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
|
|
||||||
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
|
|
||||||
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
|
|
||||||
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
|
|
||||||
}
|
|
||||||
|
|
||||||
fragment~ filter=linear
|
|
||||||
vec4 compress(vec4 in_color, float threshold, float ratio)
|
|
||||||
{
|
|
||||||
vec4 diff = in_color - vec4(threshold);
|
|
||||||
diff = clamp(diff, 0.0, 100.0);
|
|
||||||
return in_color - (diff * (1.0 - 1.0/ratio));
|
|
||||||
}
|
|
||||||
|
|
||||||
uniform sampler2D rubyTexture;
|
|
||||||
uniform vec2 rubyTextureSize;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
|
|
||||||
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
|
|
||||||
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
|
|
||||||
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
|
|
||||||
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
|
|
||||||
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
|
|
||||||
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
|
|
||||||
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
|
|
||||||
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
|
|
||||||
|
|
||||||
vec2 tex = gl_TexCoord[0].xy;
|
|
||||||
vec2 texsize = rubyTextureSize;
|
|
||||||
|
|
||||||
vec3 first = mix(c00, c20, fract(tex.x * texsize.x + 0.5));
|
|
||||||
vec3 second = mix(c02, c22, fract(tex.x * texsize.x + 0.5));
|
|
||||||
|
|
||||||
vec3 mid_horiz = mix(c01, c21, fract(tex.x * texsize.x + 0.5));
|
|
||||||
vec3 mid_vert = mix(c10, c12, fract(tex.y * texsize.y + 0.5));
|
|
||||||
|
|
||||||
vec3 res = mix(first, second, fract(tex.y * texsize.y + 0.5));
|
|
||||||
vec4 final = vec4(0.26 * (res + mid_horiz + mid_vert) + 3.5 * abs(res - mix(mid_horiz, mid_vert, 0.5)), 1.0);
|
|
||||||
gl_FragColor = compress(final, 0.8, 5.0);
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
install:
|
|
||||||
mkdir -p ~/.config/bsnes/shaders
|
|
||||||
chmod 777 ~/.config/bsnes/shaders
|
|
||||||
cp *.shader ~/.config/bsnes/shaders
|
|
Loading…
Reference in New Issue