mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r17 release.
byuu says: Changelog: - tomoko: the library menu is now called the systems menu (even in code) - tomoko: added icons to menus (disambiguates systems menu entries) - icarus: added missing .ws, .wsc extensions to scan dialog search list - higan: added Benesse - Pocket Challenge V2 emulation¹ ¹: the Benesse - Pocket Challenge V2 is a WonderSwan (ASWAN) SoC inside a custom designed shell. Games made for the WonderSwan (mostly) run on the Pocket Challenge V2 and vice versa. The big difference is that the Benesse has a different number of input buttons, that are also named differently. Of course, right now, I don't know what the buttons are named or where they're mapped on the 16-input keypad matrix I/O port. It's also possible that the internal EEPROM doesn't exist, it definitely has a unique (and also undumped) IPLROM, and other things. The ROMs have their own .pc2 file extension. So it's getting its own system entry. What I'm going to do for v107 and above is utilize the new systems configuration to mark the Benesse as hidden by default from the main menu. I don't think anyone in the world will actually care or want to play this, but there was really no reason not to add it.
This commit is contained in:
parent
540d960e30
commit
8617711ea2
|
@ -12,7 +12,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "106.16";
|
||||
static const string Version = "106.17";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "https://byuu.org/";
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
system name:Pocket Challenge V2
|
||||
eeprom name=internal.ram size=128
|
|
@ -6,7 +6,7 @@ unique_pointer<Presentation> presentation;
|
|||
Presentation::Presentation() {
|
||||
presentation = this;
|
||||
|
||||
libraryMenu.setText("Systems");
|
||||
systemsMenu.setText("Systems");
|
||||
|
||||
systemMenu.setVisible(false);
|
||||
resetSystem.setText("Soft Reset").onActivate([&] { program->softReset(); });
|
||||
|
@ -67,10 +67,10 @@ Presentation::Presentation() {
|
|||
statusBar.setVisible(showStatusBar.checked());
|
||||
if(visible()) resizeViewport();
|
||||
});
|
||||
showSystemSettings.setText("Systems ...").onActivate([&] { settingsManager->show(0); });
|
||||
showVideoSettings.setText("Video ...").onActivate([&] { settingsManager->show(1); });
|
||||
showAudioSettings.setText("Audio ...").onActivate([&] { settingsManager->show(2); });
|
||||
showInputSettings.setText("Input ...").onActivate([&] {
|
||||
showSystemSettings.setIcon(Icon::Device::Storage).setText("Systems ...").onActivate([&] { settingsManager->show(0); });
|
||||
showVideoSettings.setIcon(Icon::Device::Display).setText("Video ...").onActivate([&] { settingsManager->show(1); });
|
||||
showAudioSettings.setIcon(Icon::Device::Speaker).setText("Audio ...").onActivate([&] { settingsManager->show(2); });
|
||||
showInputSettings.setIcon(Icon::Device::Joypad).setText("Input ...").onActivate([&] {
|
||||
if(emulator) {
|
||||
//default input panel to current core's input settings
|
||||
for(auto item : settingsManager->input.emulatorList.items()) {
|
||||
|
@ -83,8 +83,8 @@ Presentation::Presentation() {
|
|||
}
|
||||
settingsManager->show(3);
|
||||
});
|
||||
showHotkeySettings.setText("Hotkeys ...").onActivate([&] { settingsManager->show(4); });
|
||||
showAdvancedSettings.setText("Advanced ...").onActivate([&] { settingsManager->show(5); });
|
||||
showHotkeySettings.setIcon(Icon::Device::Keyboard).setText("Hotkeys ...").onActivate([&] { settingsManager->show(4); });
|
||||
showAdvancedSettings.setIcon(Icon::Action::Settings).setText("Advanced ...").onActivate([&] { settingsManager->show(5); });
|
||||
|
||||
toolsMenu.setText("Tools").setVisible(false);
|
||||
saveQuickStateMenu.setText("Save Quick State");
|
||||
|
@ -100,19 +100,19 @@ Presentation::Presentation() {
|
|||
loadSlot4.setText("Slot 4").onActivate([&] { program->loadState(4); });
|
||||
loadSlot5.setText("Slot 5").onActivate([&] { program->loadState(5); });
|
||||
pauseEmulation.setText("Pause Emulation").onToggle([&] { program->togglePause(); });
|
||||
cheatEditor.setText("Cheat Editor ...").onActivate([&] { toolsManager->show(0); });
|
||||
stateManager.setText("State Manager ...").onActivate([&] { toolsManager->show(1); });
|
||||
manifestViewer.setText("Manifest Viewer ...").onActivate([&] { toolsManager->show(2); });
|
||||
gameNotes.setText("Game Notes ...").onActivate([&] { toolsManager->show(3); });
|
||||
cheatEditor.setIcon(Icon::Edit::Replace).setText("Cheat Editor ...").onActivate([&] { toolsManager->show(0); });
|
||||
stateManager.setIcon(Icon::Application::FileManager).setText("State Manager ...").onActivate([&] { toolsManager->show(1); });
|
||||
manifestViewer.setIcon(Icon::Emblem::Text).setText("Manifest Viewer ...").onActivate([&] { toolsManager->show(2); });
|
||||
gameNotes.setIcon(Icon::Emblem::Text).setText("Game Notes ...").onActivate([&] { toolsManager->show(3); });
|
||||
|
||||
helpMenu.setText("Help");
|
||||
documentation.setText("Documentation ...").onActivate([&] {
|
||||
documentation.setIcon(Icon::Application::Browser).setText("Documentation ...").onActivate([&] {
|
||||
invoke("https://doc.byuu.org/higan/");
|
||||
});
|
||||
credits.setText("Credits ...").onActivate([&] {
|
||||
credits.setIcon(Icon::Application::Browser).setText("Credits ...").onActivate([&] {
|
||||
invoke("https://doc.byuu.org/higan/credits/");
|
||||
});
|
||||
about.setText("About ...").onActivate([&] {
|
||||
about.setIcon(Icon::Prompt::Question).setText("About ...").onActivate([&] {
|
||||
aboutWindow->setVisible().setFocused();
|
||||
});
|
||||
|
||||
|
@ -304,32 +304,34 @@ auto Presentation::toggleFullScreen() -> void {
|
|||
}
|
||||
|
||||
auto Presentation::loadSystems() -> void {
|
||||
libraryMenu.reset();
|
||||
systemsMenu.reset();
|
||||
for(auto system : settings.find("Systems/System")) {
|
||||
if(!system["Show"].boolean()) continue;
|
||||
if(!system["Visible"].boolean()) continue;
|
||||
MenuItem item;
|
||||
string boot = system["Boot"].text();
|
||||
item.setText({system["Name"].text(), " ..."}).onActivate([=] {
|
||||
bool booted = false;
|
||||
string name = system.text();
|
||||
string filename = system["Load"].text();
|
||||
string load = Location::base(filename).trimRight("/", 1L);
|
||||
string alias = system["Alias"].text();
|
||||
item
|
||||
.setIcon(load ? Icon::Emblem::Folder : Icon::Device::Storage)
|
||||
.setText({alias ? alias : load ? load : name, " ..."}).onActivate([=] {
|
||||
for(auto& emulator : program->emulators) {
|
||||
if(boot == emulator->information.name) {
|
||||
if(name == emulator->information.name) {
|
||||
if(filename) program->mediumQueue.append(filename);
|
||||
program->loadMedium(*emulator, emulator->media(0));
|
||||
booted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!booted && directory::exists(boot)) {
|
||||
program->mediumQueue.append(boot);
|
||||
program->loadMedium();
|
||||
}
|
||||
});
|
||||
libraryMenu.append(item);
|
||||
systemsMenu.append(item);
|
||||
}
|
||||
|
||||
//add icarus menu option -- but only if icarus binary is present
|
||||
if(execute("icarus", "--name").output.strip() == "icarus") {
|
||||
if(libraryMenu.actionCount()) libraryMenu.append(MenuSeparator());
|
||||
libraryMenu.append(MenuItem().setText("Load ROM File ...").onActivate([&] {
|
||||
if(systemsMenu.actionCount()) systemsMenu.append(MenuSeparator());
|
||||
systemsMenu.append(MenuItem()
|
||||
.setIcon(Icon::Emblem::File)
|
||||
.setText("Load ROM File ...").onActivate([&] {
|
||||
audio->clear();
|
||||
if(auto location = execute("icarus", "--import")) {
|
||||
program->mediumQueue.append(location.output.strip());
|
||||
|
|
|
@ -18,7 +18,7 @@ struct Presentation : Window {
|
|||
auto loadShaders() -> void;
|
||||
|
||||
MenuBar menuBar{this};
|
||||
Menu libraryMenu{&menuBar};
|
||||
Menu systemsMenu{&menuBar};
|
||||
Menu systemMenu{&menuBar};
|
||||
Menu inputPort1{&systemMenu};
|
||||
Menu inputPort2{&systemMenu};
|
||||
|
@ -74,6 +74,7 @@ struct Presentation : Window {
|
|||
Menu helpMenu{&menuBar};
|
||||
MenuItem documentation{&helpMenu};
|
||||
MenuItem credits{&helpMenu};
|
||||
MenuSeparator helpMenuSeparator{&helpMenu};
|
||||
MenuItem about{&helpMenu};
|
||||
|
||||
FixedLayout layout{this};
|
||||
|
|
|
@ -29,6 +29,7 @@ Program::Program(string_vector args) {
|
|||
emulators.append(new MasterSystem::GameGearInterface);
|
||||
emulators.append(new WonderSwan::WonderSwanInterface);
|
||||
emulators.append(new WonderSwan::WonderSwanColorInterface);
|
||||
emulators.append(new WonderSwan::PocketChallengeV2Interface);
|
||||
|
||||
new Presentation;
|
||||
presentation->setVisible();
|
||||
|
|
|
@ -4,13 +4,16 @@ struct SystemProperties : Window {
|
|||
auto modify(Markup::Node) -> void;
|
||||
|
||||
VerticalLayout layout{this};
|
||||
HorizontalLayout nameLayout{&layout, Size{~0, 0}};
|
||||
Label nameLabel{&nameLayout, Size{40, 0}};
|
||||
LineEdit nameEdit{&nameLayout, Size{~0, 0}};
|
||||
HorizontalLayout bootLayout{&layout, Size{~0, 0}};
|
||||
Label bootLabel{&bootLayout, Size{40, 0}};
|
||||
ComboEdit bootEdit{&bootLayout, Size{~0, 0}};
|
||||
Button bootBrowse{&bootLayout, Size{80, 0}};
|
||||
HorizontalLayout systemLayout{&layout, Size{~0, 0}};
|
||||
Label systemLabel{&systemLayout, Size{50, 0}};
|
||||
ComboButton systemOption{&systemLayout, Size{~0, 0}};
|
||||
HorizontalLayout loadLayout{&layout, Size{~0, 0}};
|
||||
Label loadLabel{&loadLayout, Size{50, 0}};
|
||||
LineEdit loadEdit{&loadLayout, Size{~0, 0}};
|
||||
Button loadBrowse{&loadLayout, Size{80, 0}};
|
||||
HorizontalLayout aliasLayout{&layout, Size{~0, 0}};
|
||||
Label aliasLabel{&aliasLayout, Size{50, 0}};
|
||||
LineEdit aliasEdit{&aliasLayout, Size{~0, 0}};
|
||||
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
||||
Widget spacer{&controlLayout, Size{~0, 0}};
|
||||
Button acceptButton{&controlLayout, Size{80, 0}};
|
||||
|
|
|
@ -2,13 +2,13 @@ SystemProperties::SystemProperties() {
|
|||
systemProperties = this;
|
||||
|
||||
layout.setMargin(5);
|
||||
nameLabel.setText("Name:");
|
||||
bootLabel.setText("Boot:");
|
||||
bootEdit.setEditable(false);
|
||||
systemLabel.setAlignment(1.0).setText("System:");
|
||||
for(auto& emulator : program->emulators) {
|
||||
bootEdit.append(ComboEditItem().setText(emulator->information.name));
|
||||
systemOption.append(ComboButtonItem().setText(emulator->information.name));
|
||||
}
|
||||
bootBrowse.setText("Browse ...").onActivate([&] {
|
||||
loadLabel.setAlignment(1.0).setText("Load:");
|
||||
loadEdit.setEditable(false);
|
||||
loadBrowse.setText("Browse ...").onActivate([&] {
|
||||
string filters = "Games|";
|
||||
for(auto& emulator : program->emulators) {
|
||||
for(auto& media : emulator->media) {
|
||||
|
@ -21,9 +21,10 @@ SystemProperties::SystemProperties() {
|
|||
.setPath(settings["Library/Location"].text())
|
||||
.setFilters(filters)
|
||||
.openFolder()) {
|
||||
bootEdit.setText(location);
|
||||
loadEdit.setText(location);
|
||||
}
|
||||
});
|
||||
aliasLabel.setAlignment(1.0).setText("Alias:");
|
||||
acceptButton.onActivate([&] {
|
||||
setVisible(false);
|
||||
settingsManager->systems.accept();
|
||||
|
@ -39,20 +40,25 @@ SystemProperties::SystemProperties() {
|
|||
|
||||
auto SystemProperties::append() -> void {
|
||||
setCentered(*settingsManager);
|
||||
nameEdit.setText("");
|
||||
bootEdit.setText("");
|
||||
systemOption.item(0).setSelected();
|
||||
loadEdit.setText("");
|
||||
aliasEdit.setText("");
|
||||
acceptButton.setText("Append");
|
||||
setFocused();
|
||||
setVisible();
|
||||
nameEdit.setFocused();
|
||||
systemOption.setFocused();
|
||||
}
|
||||
|
||||
auto SystemProperties::modify(Markup::Node system) -> void {
|
||||
setCentered(*settingsManager);
|
||||
nameEdit.setText(system["Name"].text());
|
||||
bootEdit.setText(system["Boot"].text());
|
||||
systemOption.item(0).setSelected();
|
||||
for(auto item : systemOption.items()) {
|
||||
if(item.text() == system.text()) item.setSelected();
|
||||
}
|
||||
loadEdit.setText(system["Load"].text());
|
||||
aliasEdit.setText(system["Alias"].text());
|
||||
acceptButton.setText("Modify");
|
||||
setFocused();
|
||||
setVisible();
|
||||
nameEdit.setFocused();
|
||||
systemOption.setFocused();
|
||||
}
|
||||
|
|
|
@ -34,17 +34,20 @@ auto SystemSettings::reload() -> void {
|
|||
systemList.reset();
|
||||
systemList.append(TableViewHeader().setVisible()
|
||||
.append(TableViewColumn())
|
||||
.append(TableViewColumn().setText("Name"))
|
||||
.append(TableViewColumn().setText("Boot").setExpandable())
|
||||
.append(TableViewColumn().setText("System").setExpandable())
|
||||
);
|
||||
for(auto system : settings.find("Systems/System")) {
|
||||
string boot = Location::base(system["Boot"].text());
|
||||
string name = system.text();
|
||||
string load = Location::base(system["Load"].text()).trimRight("/", 1L);
|
||||
string alias = system["Alias"].text();
|
||||
systemList.append(TableViewItem()
|
||||
.append(TableViewCell().setCheckable().setChecked(system["Show"].boolean()))
|
||||
.append(TableViewCell().setText(system["Name"].text()))
|
||||
.append(TableViewCell()
|
||||
.setIcon(boot.endsWith("/") ? Icon::Emblem::Folder : Icon::Device::Storage)
|
||||
.setText(string{boot}.trimRight("/", 1L))
|
||||
.setCheckable()
|
||||
.setChecked(system["Visible"].boolean())
|
||||
)
|
||||
.append(TableViewCell()
|
||||
.setIcon(load ? Icon::Emblem::Folder : Icon::Device::Storage)
|
||||
.setText(alias ? alias : load ? load : name)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -55,7 +58,7 @@ auto SystemSettings::reload() -> void {
|
|||
auto SystemSettings::toggle(TableViewCell cell) -> void {
|
||||
if(auto item = cell->parentTableViewItem()) {
|
||||
if(auto system = settings.find("Systems/System")[item->offset()]) {
|
||||
system("Show").setValue(item->cell(0).checked());
|
||||
system("Visible").setValue(item->cell(0).checked());
|
||||
presentation->loadSystems();
|
||||
}
|
||||
}
|
||||
|
@ -93,8 +96,8 @@ auto SystemSettings::remove() -> void {
|
|||
if(auto item = systemList.selected()) {
|
||||
if(auto system = settings.find("Systems/System")[item.offset()]) {
|
||||
if(MessageDialog().setParent(*settingsManager).setText({
|
||||
"Are you sure you want to delete this system?\n\n"
|
||||
"Name: ", system["Name"].text()
|
||||
"Are you sure you want to delete this system?\n\n",
|
||||
item.cell(1).text()
|
||||
}).question() == "Yes") {
|
||||
settings["Systems"].remove(system);
|
||||
reload();
|
||||
|
@ -105,16 +108,17 @@ auto SystemSettings::remove() -> void {
|
|||
|
||||
auto SystemSettings::accept() -> void {
|
||||
if(systemProperties->acceptButton.text() == "Append") {
|
||||
Markup::Node system{"System"};
|
||||
system.append({"Name", systemProperties->nameEdit.text()});
|
||||
system.append({"Boot", systemProperties->bootEdit.text()});
|
||||
system.append({"Show", "true"});
|
||||
Markup::Node system{"System", systemProperties->systemOption.selected().text()};
|
||||
system.append({"Load", systemProperties->loadEdit.text()});
|
||||
system.append({"Alias", systemProperties->aliasEdit.text()});
|
||||
system.append({"Visible", "true"});
|
||||
settings["Systems"].append(system);
|
||||
} else if(systemProperties->acceptButton.text() == "Modify") {
|
||||
if(auto item = systemList.selected()) {
|
||||
if(auto system = settings.find("Systems/System")[item.offset()]) {
|
||||
system("Name").setValue(systemProperties->nameEdit.text());
|
||||
system("Boot").setValue(systemProperties->bootEdit.text());
|
||||
system.setValue(systemProperties->systemOption.selected().text());
|
||||
system("Load").setValue(systemProperties->loadEdit.text());
|
||||
system("Alias").setValue(systemProperties->aliasEdit.text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@ auto Cartridge::load() -> bool {
|
|||
} else return false;
|
||||
}
|
||||
|
||||
if(Model::PocketChallengeV2()) {
|
||||
if(auto loaded = platform->load(ID::PocketChallengeV2, "Pocket Challenge V2", "pc2")) {
|
||||
information.pathID = loaded.pathID();
|
||||
} else return false;
|
||||
}
|
||||
|
||||
if(auto fp = platform->open(pathID(), "manifest.bml", File::Read, File::Required)) {
|
||||
information.manifest = fp->reads();
|
||||
} else return false;
|
||||
|
|
|
@ -51,7 +51,7 @@ auto CPU::power() -> void {
|
|||
bus.map(this, 0x00a0);
|
||||
bus.map(this, 0x00b0, 0x00b6);
|
||||
|
||||
if(!Model::WonderSwan()) {
|
||||
if(Model::WonderSwanColor() || Model::SwanCrystal()) {
|
||||
bus.map(this, 0x0040, 0x0049);
|
||||
bus.map(this, 0x0062);
|
||||
}
|
||||
|
|
|
@ -48,10 +48,10 @@ auto CPU::portRead(uint16 addr) -> uint8 {
|
|||
|
||||
//HW_FLAGS
|
||||
if(addr == 0x00a0) {
|
||||
bool color = !Model::WonderSwan();
|
||||
bool color = Model::WonderSwanColor() || Model::SwanCrystal();
|
||||
return (
|
||||
1 << 0 //0 = BIOS mapped; 1 = cartridge mapped
|
||||
| color << 1 //0 = WonderSwan; 1 = WonderSwan Color or SwanCrystal
|
||||
| color << 1 //0 = WonderSwan or Pocket Challenge V2; 1 = WonderSwan Color or SwanCrystal
|
||||
| 1 << 2 //0 = 8-bit bus width; 1 = 16-bit bus width
|
||||
| 1 << 7 //1 = built-in self-test passed
|
||||
);
|
||||
|
@ -59,7 +59,7 @@ auto CPU::portRead(uint16 addr) -> uint8 {
|
|||
|
||||
//INT_BASE
|
||||
if(addr == 0x00b0) return (
|
||||
r.interruptBase | (Model::WonderSwan() ? 3 : 0)
|
||||
r.interruptBase | (Model::WonderSwan() || Model::PocketChallengeV2() ? 3 : 0)
|
||||
);
|
||||
|
||||
//SER_DATA
|
||||
|
@ -122,7 +122,7 @@ auto CPU::portWrite(uint16 addr, uint8 data) -> void {
|
|||
|
||||
//INT_BASE
|
||||
if(addr == 0x00b0) {
|
||||
r.interruptBase = Model::WonderSwan() ? data & ~7 : data & ~1;
|
||||
r.interruptBase = Model::WonderSwan() || Model::PocketChallengeV2() ? data & ~7 : data & ~1;
|
||||
}
|
||||
|
||||
//SER_DATA
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace WonderSwan {
|
|||
Settings settings;
|
||||
#include "wonderswan.cpp"
|
||||
#include "wonderswan-color.cpp"
|
||||
#include "pocket-challenge-v2.cpp"
|
||||
|
||||
Interface::Interface() {
|
||||
Port hardwarePort{ID::Port::Hardware, "Hardware"};
|
||||
|
|
|
@ -5,6 +5,7 @@ struct ID {
|
|||
System,
|
||||
WonderSwan,
|
||||
WonderSwanColor,
|
||||
PocketChallengeV2,
|
||||
};
|
||||
|
||||
struct Port { enum : uint {
|
||||
|
@ -64,6 +65,17 @@ struct WonderSwanColorInterface : Interface {
|
|||
auto load(uint id) -> bool override;
|
||||
};
|
||||
|
||||
struct PocketChallengeV2Interface : Interface {
|
||||
using Emulator::Interface::load;
|
||||
|
||||
PocketChallengeV2Interface();
|
||||
|
||||
auto videoColors() -> uint32 override;
|
||||
auto videoColor(uint32 color) -> uint64 override;
|
||||
|
||||
auto load(uint id) -> bool override;
|
||||
};
|
||||
|
||||
struct Settings {
|
||||
bool blurEmulation = true;
|
||||
bool colorEmulation = true;
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
PocketChallengeV2Interface::PocketChallengeV2Interface() {
|
||||
information.manufacturer = "Benesse";
|
||||
information.name = "Pocket Challenge V2";
|
||||
information.overscan = false;
|
||||
|
||||
media.append({ID::PocketChallengeV2, "Pocket Challenge V2", "pc2"});
|
||||
}
|
||||
|
||||
//todo: this should be generating grayscale colors
|
||||
//instead, the PPU is selecting grayscale colors from the color palette
|
||||
|
||||
auto PocketChallengeV2Interface::videoColors() -> uint32 {
|
||||
return 1 << 12;
|
||||
}
|
||||
|
||||
auto PocketChallengeV2Interface::videoColor(uint32 color) -> uint64 {
|
||||
uint b = color.bits(0, 3);
|
||||
uint g = color.bits(4, 7);
|
||||
uint r = color.bits(8,11);
|
||||
|
||||
uint64_t R = image::normalize(r, 4, 16);
|
||||
uint64_t G = image::normalize(g, 4, 16);
|
||||
uint64_t B = image::normalize(b, 4, 16);
|
||||
|
||||
if(settings.colorEmulation) {
|
||||
R = (r * 26 + g * 4 + b * 2);
|
||||
G = ( g * 24 + b * 8);
|
||||
B = (r * 6 + g * 4 + b * 22);
|
||||
R = image::normalize(min(480, R), 9, 16);
|
||||
G = image::normalize(min(480, G), 9, 16);
|
||||
B = image::normalize(min(480, B), 9, 16);
|
||||
}
|
||||
|
||||
return R << 32 | G << 16 | B << 0;
|
||||
}
|
||||
|
||||
auto PocketChallengeV2Interface::load(uint id) -> bool {
|
||||
if(id == ID::PocketChallengeV2) return system.load(this, System::Model::PocketChallengeV2);
|
||||
return false;
|
||||
}
|
|
@ -10,7 +10,7 @@ auto InternalRAM::power() -> void {
|
|||
}
|
||||
|
||||
auto InternalRAM::serialize(serializer& s) -> void {
|
||||
s.array(memory, Model::WonderSwan() ? 0x4000 : 0x10000);
|
||||
s.array(memory, Model::WonderSwan() || Model::PocketChallengeV2() ? 0x4000 : 0x10000);
|
||||
}
|
||||
|
||||
auto InternalRAM::read(uint16 addr, uint size) -> uint32 {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
struct System : IO {
|
||||
enum class Model : uint { WonderSwan, WonderSwanColor, SwanCrystal };
|
||||
enum class Model : uint { WonderSwan, WonderSwanColor, SwanCrystal, PocketChallengeV2 };
|
||||
|
||||
auto loaded() const -> bool { return _loaded; }
|
||||
auto model() const -> Model { return _model; }
|
||||
|
@ -67,3 +67,4 @@ extern System system;
|
|||
auto Model::WonderSwan() -> bool { return system.model() == System::Model::WonderSwan; }
|
||||
auto Model::WonderSwanColor() -> bool { return system.model() == System::Model::WonderSwanColor; }
|
||||
auto Model::SwanCrystal() -> bool { return system.model() == System::Model::SwanCrystal; }
|
||||
auto Model::PocketChallengeV2() -> bool { return system.model() == System::Model::PocketChallengeV2; }
|
||||
|
|
|
@ -32,9 +32,10 @@ namespace WonderSwan {
|
|||
};
|
||||
|
||||
struct Model {
|
||||
inline static auto WonderSwan() -> bool; //SW-001 (ASWAN)
|
||||
inline static auto WonderSwanColor() -> bool; //WSC-001 (SPHINX)
|
||||
inline static auto SwanCrystal() -> bool; //SCT-001 (SPHINX2)
|
||||
inline static auto WonderSwan() -> bool; //SW-001 (ASWAN)
|
||||
inline static auto WonderSwanColor() -> bool; //WSC-001 (SPHINX)
|
||||
inline static auto SwanCrystal() -> bool; //SCT-001 (SPHINX2)
|
||||
inline static auto PocketChallengeV2() -> bool; //(ASWAN)
|
||||
};
|
||||
|
||||
#include <ws/memory/memory.hpp>
|
||||
|
|
|
@ -11,6 +11,7 @@ Icarus::Icarus() {
|
|||
Database::GameGear = BML::unserialize(string::read(locate("Database/Game Gear.bml")));
|
||||
Database::WonderSwan = BML::unserialize(string::read(locate("Database/WonderSwan.bml")));
|
||||
Database::WonderSwanColor = BML::unserialize(string::read(locate("Database/WonderSwan Color.bml")));
|
||||
Database::PocketChallengeV2 = BML::unserialize(string::read(locate("Database/Pocket Challenge V2.bml")));
|
||||
Database::BSMemory = BML::unserialize(string::read(locate("Database/BS Memory.bml")));
|
||||
Database::SufamiTurbo = BML::unserialize(string::read(locate("Database/Sufami Turbo.bml")));
|
||||
}
|
||||
|
@ -50,6 +51,7 @@ auto Icarus::manifest(string location) -> string {
|
|||
if(type == ".gg") return gameGearManifest(location);
|
||||
if(type == ".ws") return wonderSwanManifest(location);
|
||||
if(type == ".wsc") return wonderSwanColorManifest(location);
|
||||
if(type == ".pc2") return pocketChallengeV2Manifest(location);
|
||||
if(type == ".bs") return bsMemoryManifest(location);
|
||||
if(type == ".st") return sufamiTurboManifest(location);
|
||||
|
||||
|
@ -93,6 +95,7 @@ auto Icarus::import(string location) -> string {
|
|||
if(type == ".gg") return gameGearImport(buffer, location);
|
||||
if(type == ".ws") return wonderSwanImport(buffer, location);
|
||||
if(type == ".wsc") return wonderSwanColorImport(buffer, location);
|
||||
if(type == ".pc2") return pocketChallengeV2Import(buffer, location);
|
||||
if(type == ".bs") return bsMemoryImport(buffer, location);
|
||||
if(type == ".st") return sufamiTurboImport(buffer, location);
|
||||
|
||||
|
|
|
@ -96,6 +96,11 @@ struct Icarus {
|
|||
auto wonderSwanColorManifest(vector<uint8_t>& buffer, string location) -> string;
|
||||
auto wonderSwanColorImport(vector<uint8_t>& buffer, string location) -> string;
|
||||
|
||||
//pocket-challenge-v2.cpp
|
||||
auto pocketChallengeV2Manifest(string location) -> string;
|
||||
auto pocketChallengeV2Manifest(vector<uint8_t>& buffer, string location) -> string;
|
||||
auto pocketChallengeV2Import(vector<uint8_t>& buffer, string location) -> string;
|
||||
|
||||
//bs-memory.cpp
|
||||
auto bsMemoryManifest(string location) -> string;
|
||||
auto bsMemoryManifest(vector<uint8_t>& buffer, string location) -> string;
|
||||
|
@ -124,6 +129,7 @@ namespace Database {
|
|||
Markup::Node GameGear;
|
||||
Markup::Node WonderSwan;
|
||||
Markup::Node WonderSwanColor;
|
||||
Markup::Node PocketChallengeV2;
|
||||
Markup::Node BSMemory;
|
||||
Markup::Node SufamiTurbo;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
auto Icarus::pocketChallengeV2Manifest(string location) -> string {
|
||||
vector<uint8_t> buffer;
|
||||
concatenate(buffer, {location, "program.rom"});
|
||||
return pocketChallengeV2Manifest(buffer, location);
|
||||
}
|
||||
|
||||
auto Icarus::pocketChallengeV2Manifest(vector<uint8_t>& buffer, string location) -> string {
|
||||
if(settings["icarus/UseDatabase"].boolean()) {
|
||||
auto digest = Hash::SHA256(buffer).digest();
|
||||
for(auto game : Database::PocketChallengeV2.find("game")) {
|
||||
if(game["sha256"].text() == digest) return BML::serialize(game);
|
||||
}
|
||||
}
|
||||
|
||||
if(settings["icarus/UseHeuristics"].boolean()) {
|
||||
Heuristics::WonderSwan game{buffer, location};
|
||||
if(auto manifest = game.manifest()) return manifest;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
auto Icarus::pocketChallengeV2Import(vector<uint8_t>& buffer, string location) -> string {
|
||||
auto name = Location::prefix(location);
|
||||
auto source = Location::path(location);
|
||||
string target{settings["Library/Location"].text(), "Pocket Challenge V2/", name, ".pc2/"};
|
||||
|
||||
auto manifest = pocketChallengeV2Manifest(buffer, location);
|
||||
if(!manifest) return failure("failed to parse ROM image");
|
||||
|
||||
if(!create(target)) return failure("library path unwritable");
|
||||
if(exists({source, name, ".sav"}) && !exists({target, "save.ram"})) {
|
||||
copy({source, name, ".sav"}, {target, "save.ram"});
|
||||
}
|
||||
|
||||
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
|
||||
write({target, "program.rom"}, buffer);
|
||||
return success(target);
|
||||
}
|
|
@ -44,6 +44,7 @@ Settings settings;
|
|||
#include "core/game-gear.cpp"
|
||||
#include "core/wonderswan.cpp"
|
||||
#include "core/wonderswan-color.cpp"
|
||||
#include "core/pocket-challenge-v2.cpp"
|
||||
#include "core/bs-memory.cpp"
|
||||
#include "core/sufami-turbo.cpp"
|
||||
|
||||
|
@ -92,6 +93,7 @@ auto nall::main(string_vector args) -> void {
|
|||
"*.gg:"
|
||||
"*.ws:"
|
||||
"*.wsc:"
|
||||
"*.pc2:"
|
||||
"*.bs:"
|
||||
"*.st:"
|
||||
"*.zip"
|
||||
|
|
|
@ -110,6 +110,9 @@ auto ScanDialog::gamePakType(const string& type) -> bool {
|
|||
|| type == ".gbc"
|
||||
|| type == ".gba"
|
||||
|| type == ".gg"
|
||||
|| type == ".ws"
|
||||
|| type == ".wsc"
|
||||
|| type == ".pc2"
|
||||
|| type == ".bs"
|
||||
|| type == ".st";
|
||||
}
|
||||
|
@ -126,6 +129,9 @@ auto ScanDialog::gameRomType(const string& type) -> bool {
|
|||
|| type == ".gbc"
|
||||
|| type == ".gba"
|
||||
|| type == ".gg"
|
||||
|| type == ".ws"
|
||||
|| type == ".wsc"
|
||||
|| type == ".pc2"
|
||||
|| type == ".bs"
|
||||
|| type == ".st";
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue