Update to v106r44 release.

byuu says:

Changelog:

  - hiro/Windows: use `WS_CLIPSIBLINGS` on Label to prevent resize
    drawing issues
  - bsnes: correct viewport resizing
  - bsnes: speed up window resizing a little bit
  - bsnes: fix the cheat editor list enable checkbox
  - bsnes: fix the state manager filename display in game ROM mode
  - bsnes: fix the state manager save/rename/remove functionality in
    game ROM mode
  - bsnes: correct path searching for IPS and BPS patches in game ROM
    mode
  - bsnes: patch BS-X town cartridge to disable play limits
  - bsnes: do not load (program,data,expansion).(rom,flash) from disk in
    game pak mode
      - this is required to support soft-patching and ROM hacks
  - bsnes: added speed mode selection (50%, 75%, 100%, 150%, 200%);
    maintains proper pitch
  - bsnes: added icons to the menubar
      - this is particularly useful to tell game ROMs from game paks in
        the load recent game menu
  - bsnes: added emblem at bottom left of status bar to indicate if a
    game is verified or not
      - verified means it is in the icarus verified game dump database
      - the verified diamond is orange; the unverified diamond is blue
  - bsnes: added an option (which defaults to off) to warn when loading
    unverified games
      - working around a bug in GTK, I have to use the uglier
        MessageWindow instead of MessageDialog
  - bsnes: added (non-functional) link to <https://doc.byuu.org/bsnes/>
    to the help menu
  - bsnes: added GUI setting to toggle memory auto-save feature
  - bsnes: added GUI setting to toggle capturing a backup save state
    when closing the emulator
  - bsnes: made auto-saving states on exit an option
  - bsnes: added an option to auto-load the auto-saved state on load
      - basically, the two combined implements auto-resume
  - bsnes: when firmware is missing, offer to take the user to the
    online help documentation
  - bsnes: added fast PPU option to disable the sprite limit
      - increase from 32 items/line + 34 tiles/line to 128 items/line +
        128 tiles/line
      - technically, 1024 tiles/line are possible with 128 sprites at
        64-width
      - but this is just a waste of cache locality and worst-case
        performance; it'll never happen

Errata:

  - hiro/Windows: fallthrough on Canvas `WM_ERASEBKGND` to prevent
    startup flicker
This commit is contained in:
Tim Allen 2018-06-28 16:28:27 +10:00
parent b14c6bf155
commit ec960c5172
30 changed files with 559 additions and 319 deletions

View File

@ -13,13 +13,13 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.43";
static const string Version = "106.44";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";
//incremented only when serialization format changes
static const string SerializerVersion = "104";
static const string SerializerVersion = "106.44";
namespace Constants {
namespace Colorburst {

View File

@ -48,6 +48,7 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void {
}
if(auto node = board["memory(type=ROM,content=Program)"]) loadROM(node);
if(auto node = board["memory(type=ROM,content=Expansion)"]) loadROM(node); //todo: handle this better
if(auto node = board["memory(type=RAM,content=Save)"]) loadRAM(node);
if(auto node = board["processor(identifier=ICD)"]) loadICD(node);
if(auto node = board["processor(identifier=MCC)"]) loadMCC(node);

View File

@ -234,6 +234,7 @@ auto Interface::cheatSet(const string_vector& list) -> void {
auto Interface::cap(const string& name) -> bool {
if(name == "Fast PPU") return true;
if(name == "Fast PPU/No Sprite Limit") return true;
if(name == "Fast DSP") return true;
if(name == "Mode") return true;
if(name == "Blur Emulation") return true;
@ -250,6 +251,7 @@ auto Interface::get(const string& name) -> any {
: ""
};
if(name == "Fast PPU") return settings.fastPPU;
if(name == "Fast PPU/No Sprite Limit") return settings.fastPPUNoSpriteLimit;
if(name == "Fast DSP") return settings.fastDSP;
if(name == "Blur Emulation") return settings.blurEmulation;
if(name == "Color Emulation") return settings.colorEmulation;
@ -262,6 +264,10 @@ auto Interface::set(const string& name, const any& value) -> bool {
settings.fastPPU = value.get<bool>();
return true;
}
if(name == "Fast PPU/No Sprite Limit" && value.is<bool>()) {
settings.fastPPUNoSpriteLimit = value.get<bool>();
return true;
}
if(name == "Fast DSP" && value.is<bool>()) {
settings.fastDSP = value.get<bool>();
return true;
@ -275,7 +281,10 @@ auto Interface::set(const string& name, const any& value) -> bool {
Emulator::video.setPalette();
return true;
}
if(name == "Scanline Emulation" && value.is<bool>()) return settings.scanlineEmulation = value.get<bool>(), true;
if(name == "Scanline Emulation" && value.is<bool>()) {
settings.scanlineEmulation = value.get<bool>();
return true;
}
return false;
}

View File

@ -68,6 +68,7 @@ struct Interface : Emulator::Interface {
struct Settings {
bool fastPPU = false;
bool fastPPUNoSpriteLimit = false;
bool fastDSP = false;
bool blurEmulation = true;

View File

@ -8,8 +8,8 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
uint itemCount = 0;
uint tileCount = 0;
for(auto& item : items) item.valid = false;
for(auto& tile : tiles) tile.valid = false;
for(auto n : range(ppu.ItemLimit)) items[n].valid = false;
for(auto n : range(ppu.TileLimit)) tiles[n].valid = false;
for(auto n : range(128)) {
ObjectItem item{true, self.first + n};
@ -33,12 +33,12 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
if((y >= object.y && y < object.y + height)
|| (object.y + height >= 256 && y < (object.y + height & 255))
) {
if(itemCount++ >= 32) break;
if(itemCount++ >= ppu.ItemLimit) break;
items[itemCount - 1] = item;
}
}
for(int n = 31; n >= 0; n--) {
for(int n : rrange(ppu.ItemLimit)) {
const auto& item = items[n];
if(!item.valid) continue;
@ -85,18 +85,18 @@ auto PPU::Line::renderObject(PPU::IO::Object& self) -> void {
uint address = tiledataAddress + ((characterY + (characterX + mirrorX & 15)) << 4);
tile.number = address >> 4;
if(tileCount++ >= 34) break;
if(tileCount++ >= ppu.TileLimit) break;
tiles[tileCount - 1] = tile;
}
}
ppu.io.obj.rangeOver |= itemCount > 32;
ppu.io.obj.timeOver |= tileCount > 34;
ppu.io.obj.rangeOver |= itemCount > ppu.ItemLimit;
ppu.io.obj.timeOver |= tileCount > ppu.TileLimit;
uint8 palette[256];
uint8 priority[256];
for(uint n : range(34)) {
for(uint n : range(ppu.TileLimit)) {
const auto& tile = tiles[n];
if(!tile.valid) continue;

View File

@ -124,6 +124,9 @@ auto PPU::power(bool reset) -> void {
io = {};
updateVideoMode();
ItemLimit = !settings.fastPPUNoSpriteLimit ? 32 : 128;
TileLimit = !settings.fastPPUNoSpriteLimit ? 34 : 128;
Line::start = 0;
Line::count = 0;
}

View File

@ -259,6 +259,8 @@ public:
//[unserialized]
uint32* output;
array<uint8*[3]> tilecache; //bitplane -> bitmap tiledata
uint ItemLimit;
uint TileLimit;
struct Line {
//line.cpp
@ -276,7 +278,6 @@ public:
//mode7.cpp
auto renderMode7(PPU::IO::Background&, uint source) -> void;
auto renderMode7Hires(PPU::IO::Background&, uint source) -> void;
//object.cpp
auto renderObject(PPU::IO::Object&) -> void;
@ -291,8 +292,8 @@ public:
IO io;
array<uint15[256]> cgram;
array<ObjectItem[32]> items;
array<ObjectTile[34]> tiles;
array<ObjectItem[128]> items; //32 on real hardware
array<ObjectTile[128]> tiles; //34 on real hardware; 1024 max (128 * 64-width tiles)
array<Pixel[256]> above;
array<Pixel[256]> below;

View File

@ -7,20 +7,20 @@ Presentation::Presentation() {
presentation = this;
systemMenu.setText("System");
loadGame.setText("Load Game ...").onActivate([&] {
loadGame.setIcon(Icon::Action::Open).setText("Load Game ...").onActivate([&] {
program->load();
});
loadRecentGame.setText("Load Recent Game");
loadRecentGame.setIcon(Icon::Action::Open).setText("Load Recent Game");
updateRecentGames();
resetSystem.setText("Reset System").setEnabled(false).onActivate([&] {
resetSystem.setIcon(Icon::Action::Refresh).setText("Reset System").setEnabled(false).onActivate([&] {
program->reset();
});
unloadGame.setText("Unload Game").setEnabled(false).onActivate([&] {
unloadGame.setIcon(Icon::Action::Remove).setText("Unload Game").setEnabled(false).onActivate([&] {
program->unload();
});
controllerPort1.setText("Controller Port 1");
controllerPort2.setText("Controller Port 2");
expansionPort.setText("Expansion Port");
controllerPort1.setIcon(Icon::Device::Joypad).setText("Controller Port 1");
controllerPort2.setIcon(Icon::Device::Joypad).setText("Controller Port 2");
expansionPort.setIcon(Icon::Device::Storage).setText("Expansion Port");
for(auto& port : emulator->ports) {
Menu* menu = nullptr;
if(port.name == "Controller Port 1") menu = &controllerPort1;
@ -53,22 +53,31 @@ Presentation::Presentation() {
devices.objects<MenuRadioItem>()(0).doActivate();
}
}
quit.setText("Quit").onActivate([&] { program->quit(); });
quit.setIcon(Icon::Action::Quit).setText("Quit").onActivate([&] { program->quit(); });
settingsMenu.setText("Settings");
viewMenu.setText("View");
smallView.setText("Small").onActivate([&] {
scaleMenu.setIcon(Icon::Emblem::Image).setText("View");
smallestScale.setText("Smallest (240p)").onActivate([&] {
settings["View/Size"].setValue("Smallest");
resizeWindow();
});
smallScale.setText("Small (480p)").onActivate([&] {
settings["View/Size"].setValue("Small");
resizeWindow();
});
mediumView.setText("Medium").onActivate([&] {
mediumScale.setText("Medium (720p)").onActivate([&] {
settings["View/Size"].setValue("Medium");
resizeWindow();
});
largeView.setText("Large").onActivate([&] {
largeScale.setText("Large (960p)").onActivate([&] {
settings["View/Size"].setValue("Large");
resizeWindow();
});
largestScale.setText("Largest (1200p)").onActivate([&] {
settings["View/Size"].setValue("Largest");
resizeWindow();
});
outputMenu.setIcon(Icon::Emblem::Image).setText("Output");
aspectCorrection.setText("Aspect Correction").setChecked(settings["View/AspectCorrection"].boolean()).onToggle([&] {
settings["View/AspectCorrection"].setValue(aspectCorrection.checked());
resizeWindow();
@ -85,7 +94,7 @@ Presentation::Presentation() {
settings["View/BlurEmulation"].setValue(blurEmulation.checked());
emulator->set("Blur Emulation", blurEmulation.checked());
}).doToggle();
shaderMenu.setText("Shader");
shaderMenu.setIcon(Icon::Emblem::Image).setText("Shader");
updateShaders();
synchronizeVideo.setText("Synchronize Video").setChecked(settings["Video/Blocking"].boolean()).onToggle([&] {
settings["Video/Blocking"].setValue(synchronizeVideo.checked());
@ -108,38 +117,47 @@ Presentation::Presentation() {
}
if(visible()) resizeWindow();
});
videoSettings.setText("Video ...").onActivate([&] { settingsWindow->show(0); });
audioSettings.setText("Audio ...").onActivate([&] { settingsWindow->show(1); });
inputSettings.setText("Input ...").onActivate([&] { settingsWindow->show(2); });
hotkeySettings.setText("Hotkeys ...").onActivate([&] { settingsWindow->show(3); });
pathSettings.setText("Paths ...").onActivate([&] { settingsWindow->show(4); });
advancedSettings.setText("Advanced ...").onActivate([&] { settingsWindow->show(5); });
videoSettings.setIcon(Icon::Device::Display).setText("Video ...").onActivate([&] { settingsWindow->show(0); });
audioSettings.setIcon(Icon::Device::Speaker).setText("Audio ...").onActivate([&] { settingsWindow->show(1); });
inputSettings.setIcon(Icon::Device::Joypad).setText("Input ...").onActivate([&] { settingsWindow->show(2); });
hotkeySettings.setIcon(Icon::Device::Keyboard).setText("Hotkeys ...").onActivate([&] { settingsWindow->show(3); });
pathSettings.setIcon(Icon::Emblem::Folder).setText("Paths ...").onActivate([&] { settingsWindow->show(4); });
advancedSettings.setIcon(Icon::Action::Settings).setText("Advanced ...").onActivate([&] { settingsWindow->show(5); });
toolsMenu.setText("Tools").setVisible(false);
saveState.setText("Save State");
saveState.setIcon(Icon::Action::Save).setText("Save State");
for(uint index : range(QuickStates)) {
saveState.append(MenuItem().setText({"Slot ", 1 + index}).onActivate([=] {
program->saveState({"quick/slot ", 1 + index});
}));
}
loadState.setText("Load State");
loadState.setIcon(Icon::Media::Play).setText("Load State");
for(uint index : range(QuickStates)) {
loadState.append(MenuItem().setText({"Slot ", 1 + index}).onActivate([=] {
program->loadState({"quick/slot ", 1 + index});
}));
}
loadState.append(MenuSeparator());
loadState.append(MenuItem().setText("Recovery").onActivate([&] {
loadState.append(MenuItem().setIcon(Icon::Edit::Undo).setText("Undo Last Save").onActivate([&] {
program->loadState("quick/recovery");
}));
speedMenu.setIcon(Icon::Device::Clock).setText("Speed");
speedSlowest.setText("Slowest (50%)").setProperty("multiplier", "2.0").onActivate([&] { program->updateAudioFrequency(); });
speedSlow.setText("Slow (75%)").setProperty("multiplier", "1.333").onActivate([&] { program->updateAudioFrequency(); });
speedNormal.setText("Normal (100%)").setProperty("multiplier", "1.0").onActivate([&] { program->updateAudioFrequency(); });
speedFast.setText("Fast (150%)").setProperty("multiplier", "0.667").onActivate([&] { program->updateAudioFrequency(); });
speedFastest.setText("Fastest (200%)").setProperty("multiplier", "0.5").onActivate([&] { program->updateAudioFrequency(); });
pauseEmulation.setText("Pause Emulation").onToggle([&] {
if(pauseEmulation.checked()) audio->clear();
});
cheatEditor.setText("Cheat Editor ...").onActivate([&] { toolsWindow->show(0); });
stateManager.setText("State Manager ...").onActivate([&] { toolsWindow->show(1); });
cheatEditor.setIcon(Icon::Edit::Replace).setText("Cheat Editor ...").onActivate([&] { toolsWindow->show(0); });
stateManager.setIcon(Icon::Application::FileManager).setText("State Manager ...").onActivate([&] { toolsWindow->show(1); });
helpMenu.setText("Help");
about.setText("About ...").onActivate([&] {
documentation.setIcon(Icon::Application::Browser).setText("Documentation ...").onActivate([&] {
invoke("https://doc.byuu.org/bsnes/");
});
about.setIcon(Icon::Prompt::Question).setText("About ...").onActivate([&] {
aboutWindow->setCentered(*this).setVisible().setFocused();
});
@ -153,15 +171,27 @@ Presentation::Presentation() {
layout.remove(statusLayout);
}
statusLeft.setFont(Font().setBold());
statusLeft.setAlignment(0.0);
statusLeft.setBackgroundColor({ 32, 32, 32});
statusLeft.setForegroundColor({255, 255, 255});
auto font = Font().setBold();
auto back = Color{ 32, 32, 32};
auto fore = Color{255, 255, 255};
statusRight.setFont(Font().setBold());
updateStatusIcon();
spacerIcon.setBackgroundColor(back).setForegroundColor(fore);
spacerLeft.setBackgroundColor(back).setForegroundColor(fore);
statusLeft.setFont(font);
statusLeft.setAlignment(0.0);
statusLeft.setBackgroundColor(back);
statusLeft.setForegroundColor(fore);
statusRight.setFont(font);
statusRight.setAlignment(1.0);
statusRight.setBackgroundColor({ 32, 32, 32});
statusRight.setForegroundColor({255, 255, 255});
statusRight.setBackgroundColor(back);
statusRight.setForegroundColor(fore);
spacerRight.setBackgroundColor(back).setForegroundColor(fore);
program->updateStatus();
@ -200,6 +230,19 @@ Presentation::Presentation() {
#endif
}
auto Presentation::updateStatusIcon() -> void {
image icon;
icon.allocate(16, StatusHeight);
icon.fill(0xff202020);
if(emulator->loaded()) {
image emblem{program->verified() ? Icon::Emblem::Program : Icon::Emblem::Binary};
icon.impose(image::blend::sourceAlpha, 0, (StatusHeight - 16) / 2, emblem, 0, 0, 16, 16);
}
statusIcon.setIcon(icon);
}
auto Presentation::drawIcon(uint32_t* output, uint length, uint width, uint height) -> void {
return;
@ -225,8 +268,8 @@ auto Presentation::clearViewport() -> void {
uint32_t* output;
uint length;
uint width = viewport.geometry().width();
uint height = viewport.geometry().height();
uint width = 16;
uint height = 16;
if(video->lock(output, length, width, height)) {
for(uint y : range(height)) {
auto line = output + y * (length >> 2);
@ -262,8 +305,9 @@ auto Presentation::resizeViewport() -> void {
viewportHeight = height * multiplier;
}
uint paddingWidth = (windowWidth - viewportWidth) / 2;
uint paddingHeight = (windowHeight - viewportHeight) / 2;
//center viewport within viewportLayout by use of viewportLayout padding
uint paddingWidth = windowWidth - viewportWidth;
uint paddingHeight = windowHeight - viewportHeight;
viewportLayout.setPadding({
paddingWidth / 2, paddingHeight / 2,
paddingWidth - paddingWidth / 2, paddingHeight - paddingHeight / 2
@ -278,9 +322,11 @@ auto Presentation::resizeWindow() -> void {
uint statusHeight = settings["UserInterface/ShowStatusBar"].boolean() ? StatusHeight : 0;
uint multiplier = 2;
if(settings["View/Size"].text() == "Small" ) multiplier = 2;
if(settings["View/Size"].text() == "Medium") multiplier = 3;
if(settings["View/Size"].text() == "Large" ) multiplier = 4;
if(settings["View/Size"].text() == "Smallest") multiplier = 1;
if(settings["View/Size"].text() == "Small" ) multiplier = 2;
if(settings["View/Size"].text() == "Medium" ) multiplier = 3;
if(settings["View/Size"].text() == "Large" ) multiplier = 4;
if(settings["View/Size"].text() == "Largest" ) multiplier = 5;
setSize({width * multiplier, height * multiplier + statusHeight});
resizeViewport();
@ -322,17 +368,20 @@ auto Presentation::updateRecentGames() -> void {
displayName.append(Location::prefix(part), " + ");
}
displayName.trimRight(" + ", 1L);
item.setText(displayName).onActivate([=] {
item.setIcon(games(0).endsWith("/") ? Icon::Action::Open : Icon::Emblem::File);
item.setText(displayName);
item.onActivate([=] {
program->gameQueue = games;
program->load();
});
} else {
item.setText("<empty>").setEnabled(false);
item.setText("<empty>");
item.setEnabled(false);
}
loadRecentGame.append(item);
}
loadRecentGame.append(MenuSeparator());
loadRecentGame.append(MenuItem().setText("Clear List").onActivate([&] {
loadRecentGame.append(MenuItem().setIcon(Icon::Edit::Clear).setText("Clear List").onActivate([&] {
for(auto index : range(RecentGames)) {
settings({"Game/Recent/", 1 + index}).setValue("");
}

View File

@ -10,9 +10,10 @@ struct AboutWindow : Window {
struct Presentation : Window {
enum : uint { RecentGames = 9, QuickStates = 9 };
enum : uint { StatusHeight = 25 };
enum : uint { StatusHeight = 24 };
Presentation();
auto updateStatusIcon() -> void;
auto drawIcon(uint32_t* output, uint length, uint width, uint height) -> void;
auto clearViewport() -> void;
auto resizeViewport() -> void;
@ -37,15 +38,17 @@ struct Presentation : Window {
MenuSeparator quitSeparator{&systemMenu};
MenuItem quit{&systemMenu};
Menu settingsMenu{&menuBar};
Menu viewMenu{&settingsMenu};
MenuItem smallView{&viewMenu};
MenuItem mediumView{&viewMenu};
MenuItem largeView{&viewMenu};
MenuSeparator viewSeparator{&viewMenu};
MenuCheckItem aspectCorrection{&viewMenu};
MenuCheckItem overscanCropping{&viewMenu};
MenuCheckItem integralScaling{&viewMenu};
MenuCheckItem blurEmulation{&viewMenu};
Menu scaleMenu{&settingsMenu};
MenuItem smallestScale{&scaleMenu};
MenuItem smallScale{&scaleMenu};
MenuItem mediumScale{&scaleMenu};
MenuItem largeScale{&scaleMenu};
MenuItem largestScale{&scaleMenu};
Menu outputMenu{&settingsMenu};
MenuCheckItem aspectCorrection{&outputMenu};
MenuCheckItem overscanCropping{&outputMenu};
MenuCheckItem integralScaling{&outputMenu};
MenuCheckItem blurEmulation{&outputMenu};
Menu shaderMenu{&settingsMenu};
MenuSeparator settingsSeparatorA{&settingsMenu};
MenuCheckItem synchronizeVideo{&settingsMenu};
@ -62,19 +65,33 @@ struct Presentation : Window {
Menu toolsMenu{&menuBar};
Menu saveState{&toolsMenu};
Menu loadState{&toolsMenu};
MenuSeparator toolsSeparatorA{&toolsMenu};
Menu speedMenu{&toolsMenu};
MenuRadioItem speedSlowest{&speedMenu};
MenuRadioItem speedSlow{&speedMenu};
MenuRadioItem speedNormal{&speedMenu};
MenuRadioItem speedFast{&speedMenu};
MenuRadioItem speedFastest{&speedMenu};
Group speedGroup{&speedSlowest, &speedSlow, &speedNormal, &speedFast, &speedFastest};
MenuCheckItem pauseEmulation{&toolsMenu};
MenuSeparator toolsSeparator{&toolsMenu};
MenuSeparator toolsSeparatorB{&toolsMenu};
MenuItem cheatEditor{&toolsMenu};
MenuItem stateManager{&toolsMenu};
Menu helpMenu{&menuBar};
MenuItem documentation{&helpMenu};
MenuSeparator helpSeparator{&helpMenu};
MenuItem about{&helpMenu};
VerticalLayout layout{this};
HorizontalLayout viewportLayout{&layout, Size{~0, ~0}, 0};
Viewport viewport{&viewportLayout, Size{~0, ~0}, 0};
HorizontalLayout statusLayout{&layout, Size{~0, StatusHeight}, 0};
Label spacerIcon{&statusLayout, Size{8, ~0}, 0};
Canvas statusIcon{&statusLayout, Size{16, ~0}, 0};
Label spacerLeft{&statusLayout, Size{4, ~0}, 0};
Label statusLeft{&statusLayout, Size{~0, ~0}, 0};
Label statusRight{&statusLayout, Size{80, ~0}, 0};
Label spacerRight{&statusLayout, Size{8, ~0}, 0};
};
extern unique_pointer<AboutWindow> aboutWindow;

View File

@ -48,7 +48,11 @@ auto Program::updateAudioFrequency() -> void {
settings["Audio/Frequency"].setValue(audio->availableFrequencies()(0));
}
audio->setFrequency(settings["Audio/Frequency"].real());
Emulator::audio.setFrequency(settings["Audio/Frequency"].real() + settings["Audio/Skew"].integer());
double frequency = settings["Audio/Frequency"].real() + settings["Audio/Skew"].integer();
for(auto item : presentation->speedGroup.objects<MenuRadioItem>()) {
if(item.checked()) frequency *= item.property("multiplier").real();
}
Emulator::audio.setFrequency(frequency);
settingsWindow->audio.updateFrequency();
}

View File

@ -152,8 +152,8 @@ auto Program::openRomBSMemory(string name, vfs::file::mode mode) -> vfs::shared:
return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
}
if(name == "program.flash" && mode == vfs::file::mode::read) {
//write mode is not supported for ROM mode
if(name == "program.flash") {
//writes are not flushed to disk in bsnes
return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
}

View File

@ -7,17 +7,31 @@ auto Program::load() -> void {
Emulator::audio.reset(2, audio->frequency());
if(emulator->load(media.id)) {
gameQueue = {};
if(!verified() && settingsWindow->advanced.warnOnUnverifiedGames.checked()) {
//todo: MessageDialog crashes with GTK+; unsure the reason why this happens
//once MessageDialog functions, add an "Always" option
if(MessageWindow(
"Warning: this game image is unverified. Running it *may* be a security risk.\n\n"
"Do you wish to run the game anyway?"
).setParent(*presentation).question() == MessageWindow::Response::No) {
emulator->unload();
return showMessage("Game loading cancelled");
}
}
updateInputDevices();
applyHacks();
hackCompatibility();
emulator->power();
updateVideoPalette();
updateAudioEffects();
if(settingsWindow->advanced.autoLoadStateOnLoad.checked()) {
program->loadState("quick/recovery");
}
showMessage(!appliedPatch() ? "Game loaded" : "Game loaded and patch applied");
presentation->setTitle(emulator->title());
presentation->resetSystem.setEnabled(true);
presentation->unloadGame.setEnabled(true);
presentation->toolsMenu.setVisible(true);
presentation->speedNormal.setChecked();
presentation->pauseEmulation.setChecked(false);
presentation->updateStatusIcon();
presentation->resizeViewport();
toolsWindow->cheatEditor.loadCheats();
toolsWindow->stateManager.loadStates();
@ -28,6 +42,10 @@ auto Program::load() -> void {
if(auto location = sufamiTurboA.location) locations.append("|", location);
if(auto location = sufamiTurboB.location) locations.append("|", location);
presentation->addRecentGame(locations);
updateVideoPalette();
updateAudioEffects();
updateAudioFrequency();
}
break;
@ -81,11 +99,13 @@ auto Program::loadSuperFamicom(string location) -> void {
if(auto document = BML::unserialize(string::read(locate("database/Super Famicom.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
superFamicom.verified = true;
}
}
superFamicom.label = heuristics.label();
superFamicom.manifest = manifest ? manifest : heuristics.manifest();
applyHackOverclockSuperFX();
hackPatchMemory(rom);
hackOverclockSuperFX();
superFamicom.document = BML::unserialize(superFamicom.manifest);
superFamicom.location = location;
@ -130,11 +150,13 @@ auto Program::loadGameBoy(string location) -> void {
if(auto document = BML::unserialize(string::read(locate("database/Game Boy.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
gameBoy.verified = true;
}
}
if(auto document = BML::unserialize(string::read(locate("database/Game Boy Color.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
gameBoy.verified = true;
}
}
gameBoy.manifest = manifest ? manifest : heuristics.manifest();
@ -163,6 +185,7 @@ auto Program::loadBSMemory(string location) -> void {
if(auto document = BML::unserialize(string::read(locate("database/BS Memory.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
bsMemory.verified = true;
}
}
bsMemory.manifest = manifest ? manifest : heuristics.manifest();
@ -190,6 +213,7 @@ auto Program::loadSufamiTurboA(string location) -> void {
if(auto document = BML::unserialize(string::read(locate("database/Sufami Turbo.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
sufamiTurboA.verified = true;
}
}
sufamiTurboA.manifest = manifest ? manifest : heuristics.manifest();
@ -217,6 +241,7 @@ auto Program::loadSufamiTurboB(string location) -> void {
if(auto document = BML::unserialize(string::read(locate("database/Sufami Turbo.bml")))) {
if(auto game = document[{"game(sha256=", sha256, ")"}]) {
manifest = BML::serialize(game);
sufamiTurboB.verified = true;
}
}
sufamiTurboB.manifest = manifest ? manifest : heuristics.manifest();
@ -233,7 +258,7 @@ auto Program::save() -> void {
auto Program::reset() -> void {
if(!emulator->loaded()) return;
applyHacks();
hackCompatibility();
emulator->reset();
showMessage("Game reset");
}
@ -242,7 +267,9 @@ auto Program::unload() -> void {
if(!emulator->loaded()) return;
toolsWindow->cheatEditor.saveCheats();
toolsWindow->setVisible(false);
saveRecoveryState();
if(settingsWindow->advanced.autoSaveStateOnUnload.checked()) {
saveRecoveryState();
}
emulator->unload();
showMessage("Game unloaded");
superFamicom = {};
@ -254,5 +281,17 @@ auto Program::unload() -> void {
presentation->resetSystem.setEnabled(false);
presentation->unloadGame.setEnabled(false);
presentation->toolsMenu.setVisible(false);
presentation->updateStatusIcon();
presentation->clearViewport();
}
//a game is considered verified if the game plus its slot(s) are found in the games database
auto Program::verified() const -> bool {
if(!emulator->loaded()) return false;
if(superFamicom && !superFamicom.verified) return false;
if(gameBoy && !gameBoy.verified) return false;
if(bsMemory && !bsMemory.verified) return false;
if(sufamiTurboA && !sufamiTurboA.verified) return false;
if(sufamiTurboB && !sufamiTurboB.verified) return false;
return true;
}

View File

@ -1,5 +1,6 @@
auto Program::applyHacks() -> void {
auto Program::hackCompatibility() -> void {
bool fastPPU = settingsWindow->advanced.fastPPUOption.checked();
bool fastPPUNoSpriteLimit = settingsWindow->advanced.noSpriteLimit.checked();
bool fastDSP = settingsWindow->advanced.fastDSPOption.checked();
auto label = superFamicom.label;
@ -8,13 +9,30 @@ auto Program::applyHacks() -> void {
if(label == "RENDERING RANGER R2") fastDSP = false;
emulator->set("Fast PPU", fastPPU);
emulator->set("Fast PPU/No Sprite Limit", fastPPUNoSpriteLimit);
emulator->set("Fast DSP", fastDSP);
}
auto Program::applyHackOverclockSuperFX() -> void {
auto Program::hackPatchMemory(vector<uint8_t>& data) -> void {
auto label = superFamicom.label;
if(label == "Satellaview BS-X" && data.size() >= 0x100000) {
//BS-X: Sore wa Namae o Nusumareta Machi no Monogatari (JPN) (1.1)
//disable limited play check for BS Memory flash cartridges
//benefit: allow locked out BS Memory flash games to play without manual header patching
//detriment: BS Memory ROM cartridges will cause the game to hang in the load menu
if(data[0x4a9b] == 0x10) data[0x4a9b] = 0x80;
if(data[0x4d6d] == 0x10) data[0x4d6d] = 0x80;
if(data[0x4ded] == 0x10) data[0x4ded] = 0x80;
if(data[0x4e9a] == 0x10) data[0x4e9a] = 0x80;
}
}
auto Program::hackOverclockSuperFX() -> void {
//todo: implement a better way of detecting SuperFX games
//todo: apply multiplier changes on reset, not just on game load?
double multiplier = settingsWindow->advanced.superFXValue.text().natural() / 100.0;
if(multiplier == 1.0) return;
auto label = superFamicom.label;
if(label == "NIDAN MORITASHOGI2") return; //ST018 uses same clock speed as SuperFX

View File

@ -5,6 +5,7 @@
#include <icarus/heuristics/bs-memory.cpp>
#include <icarus/heuristics/sufami-turbo.cpp>
//ROM data is held in memory to support compressed archives, soft-patching, and game hacks
auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file {
vfs::shared::file result;
@ -25,6 +26,12 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
if(id == 1) { //Super Famicom
if(name == "manifest.bml" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(superFamicom.manifest.data<uint8_t>(), superFamicom.manifest.size());
} else if(name == "program.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(superFamicom.program.data(), superFamicom.program.size());
} else if(name == "data.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(superFamicom.data.data(), superFamicom.data.size());
} else if(name == "expansion.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(superFamicom.expansion.data(), superFamicom.expansion.size());
} else if(superFamicom.location.endsWith("/")) {
result = openPakSuperFamicom(name, mode);
} else {
@ -35,6 +42,8 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
if(id == 2) { //Game Boy
if(name == "manifest.bml" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(gameBoy.manifest.data<uint8_t>(), gameBoy.manifest.size());
} else if(name == "program.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(gameBoy.program.data(), gameBoy.program.size());
} else if(gameBoy.location.endsWith("/")) {
result = openPakGameBoy(name, mode);
} else {
@ -45,6 +54,11 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
if(id == 3) { //BS Memory
if(name == "manifest.bml" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(bsMemory.manifest.data<uint8_t>(), bsMemory.manifest.size());
} else if(name == "program.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
} else if(name == "program.flash") {
//writes are not flushed to disk in bsnes
result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size());
} else if(bsMemory.location.endsWith("/")) {
result = openPakBSMemory(name, mode);
} else {
@ -55,6 +69,8 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
if(id == 4) { //Sufami Turbo - Slot A
if(name == "manifest.bml" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(sufamiTurboA.manifest.data<uint8_t>(), sufamiTurboA.manifest.size());
} else if(name == "program.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(sufamiTurboA.program.data(), sufamiTurboA.program.size());
} else if(sufamiTurboA.location.endsWith("/")) {
result = openPakSufamiTurboA(name, mode);
} else {
@ -65,6 +81,8 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
if(id == 5) { //Sufami Turbo - Slot B
if(name == "manifest.bml" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(sufamiTurboB.manifest.data<uint8_t>(), sufamiTurboB.manifest.size());
} else if(name == "program.rom" && mode == vfs::file::mode::read) {
result = vfs::memory::file::open(sufamiTurboB.program.data(), sufamiTurboB.program.size());
} else if(sufamiTurboB.location.endsWith("/")) {
result = openPakSufamiTurboB(name, mode);
} else {
@ -73,7 +91,12 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
}
if(!result && required) {
MessageDialog({"Error: missing required data: ", name}).setParent(*presentation).error();
if(MessageDialog({
"Error: missing required data: ", name, "\n\n",
"Would you like to view the online documentation for more information?"
}).setParent(*presentation).error({"Yes", "No"}) == "Yes") {
presentation->documentation.doActivate();
}
}
return result;

View File

@ -23,9 +23,9 @@ auto Program::applyPatchIPS(vector<uint8_t>& data, string location) -> bool {
}
}
}
if(!patch) patch = file::read(locate(path("Patches", location, ".ips")));
if(!patch) patch = file::read(path("Patches", location, ".ips"));
} else {
patch = file::read(locate(path("Patches", location, ".ips")));
patch = file::read(path("Patches", location, ".ips"));
}
if(!patch) return false;
@ -101,9 +101,9 @@ auto Program::applyPatchBPS(vector<uint8_t>& input, string location) -> bool {
}
}
}
if(!patch) patch = file::read(locate(path("Patches", location, ".bps")));
if(!patch) patch = file::read(path("Patches", location, ".bps"));
} else {
patch = file::read(locate(path("Patches", location, ".bps")));
patch = file::read(path("Patches", location, ".bps"));
}
if(!patch) return false;

View File

@ -60,6 +60,8 @@ Program::Program(string_vector arguments) {
}
auto Program::main() -> void {
if(Application::modal()) return;
updateStatus();
video->poll();
inputManager->poll();
@ -75,7 +77,7 @@ auto Program::main() -> void {
}
emulator->run();
if(settings["Emulator/AutoSaveMemory/Enable"].boolean()) {
if(settingsWindow->advanced.autoSaveMemory.checked()) {
auto currentTime = chrono::timestamp();
if(currentTime - autoSaveTime >= settings["Emulator/AutoSaveMemory/Interval"].natural()) {
autoSaveTime = currentTime;

View File

@ -23,6 +23,7 @@ struct Program : Emulator::Platform {
auto save() -> void;
auto reset() -> void;
auto unload() -> void;
auto verified() const -> bool;
//game-pak.cpp
auto openPakSuperFamicom(string name, vfs::file::mode mode) -> vfs::shared::file;
@ -83,44 +84,39 @@ struct Program : Emulator::Platform {
auto applyPatchBPS(vector<uint8_t>& data, string location) -> bool;
//hacks.cpp
auto applyHacks() -> void;
auto applyHackOverclockSuperFX() -> void;
auto hackCompatibility() -> void;
auto hackPatchMemory(vector<uint8_t>& data) -> void;
auto hackOverclockSuperFX() -> void;
public:
struct SuperFamicom {
string label;
struct Game {
explicit operator bool() const { return (bool)location; }
string location;
string manifest;
Markup::Node document;
boolean patched;
boolean verified;
};
struct SuperFamicom : Game {
string label;
vector<uint8_t> program;
vector<uint8_t> data;
vector<uint8_t> expansion;
vector<uint8_t> firmware;
boolean patched;
} superFamicom;
struct GameBoy {
string location;
string manifest;
Markup::Node document;
struct GameBoy : Game {
vector<uint8_t> program;
boolean patched;
} gameBoy;
struct BSMemory {
string location;
string manifest;
Markup::Node document;
struct BSMemory : Game {
vector<uint8_t> program;
boolean patched;
} bsMemory;
struct SufamiTurbo {
string location;
string manifest;
Markup::Node document;
struct SufamiTurbo : Game {
vector<uint8_t> program;
boolean patched;
} sufamiTurboA, sufamiTurboB;
string_vector gameQueue;

View File

@ -8,7 +8,7 @@ auto Program::managedStates() -> string_vector {
if(input.open(statePath())) {
string_vector filenames;
for(auto& file : input.file) {
if(file.name.match("managed/*.bst")) filenames.append(file.name);
if(file.name.match("managed/*.bst")) filenames.append(file.name.trimLeft("managed/", 1L));
}
filenames.isort();
return filenames;
@ -75,6 +75,7 @@ auto Program::saveState(string filename) -> bool {
states.append({file.name, input.extract(file)});
}
}
input.close();
Encode::ZIP output{statePath()};
for(auto& state : states) {
@ -114,6 +115,7 @@ auto Program::removeState(string filename) -> bool {
states.append({file.name, input.extract(file)});
}
}
input.close();
if(states) {
Encode::ZIP output{statePath()};
@ -151,6 +153,7 @@ auto Program::renameState(string from, string to) -> bool {
states.append({file.name, input.extract(file)});
}
}
input.close();
Encode::ZIP output{statePath()};
for(auto& state : states) {

View File

@ -12,7 +12,6 @@ auto Program::updateStatus() -> void {
if(chrono::timestamp() - statusTime <= 2) {
message = statusMessage;
}
message.prepend(" ");
if(message != presentation->statusLeft.text()) {
presentation->statusLeft.setText(message);
}
@ -27,7 +26,6 @@ auto Program::updateStatus() -> void {
} else {
frameRate = statusFrameRate;
}
frameRate.append(" ");
if(frameRate != presentation->statusRight.text()) {
presentation->statusRight.setText(frameRate);
}

View File

@ -863,8 +863,8 @@ const nall::vector<uint8_t> Manifest = { //size: 334
115,112,10,32,32,32,32,114,97,109,32,110,97,109,101,61,97,112,117,46,114,97,109,32,115,105,122,101,61,48,120,49,
48,48,48,48,32,118,111,108,97,116,105,108,101,10,
};
const nall::vector<uint8_t> Boards = { //size: 29603
100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,48,49,10,
const nall::vector<uint8_t> Boards = { //size: 30186
100,97,116,97,98,97,115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10,
10,47,47,66,111,97,114,100,115,32,40,80,114,111,100,117,99,116,105,111,110,41,10,10,100,97,116,97,98,97,115,101,
10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,53,45,49,54,10,10,98,111,97,114,100,58,32,
66,65,78,68,65,73,45,80,84,45,57,50,51,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
@ -1437,7 +1437,7 @@ const nall::vector<uint8_t> Boards = { //size: 29603
32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,
32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,
102,102,102,102,10,10,47,47,66,111,97,114,100,115,32,40,71,101,110,101,114,105,99,41,10,10,100,97,116,97,98,97,
115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,48,49,10,10,98,111,97,114,100,
115,101,10,32,32,114,101,118,105,115,105,111,110,58,32,50,48,49,56,45,48,54,45,50,53,10,10,98,111,97,114,100,
58,32,65,82,77,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,
77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,
@ -1585,211 +1585,229 @@ const nall::vector<uint8_t> Boards = { //size: 29603
97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,57,54,48,53,48,10,32,32,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,54,56,45,54,102,44,101,56,45,101,102,58,48,48,48,48,45,55,102,102,102,32,109,97,
115,107,61,48,120,56,48,48,48,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,
32,71,66,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,
101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,55,
100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,55,
102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,
116,105,102,105,101,114,61,73,67,68,32,114,101,118,105,115,105,111,110,61,50,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,54,55,102,102,44,55,48,48,48,
45,55,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,
116,61,66,111,111,116,32,97,114,99,104,105,116,101,99,116,117,114,101,61,76,82,51,53,57,48,50,10,32,32,32,32,
111,115,99,105,108,108,97,116,111,114,10,32,32,32,32,115,108,111,116,32,116,121,112,101,61,71,97,109,101,66,111,121,
10,10,98,111,97,114,100,58,32,71,83,85,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,
104,105,116,101,99,116,117,114,101,61,71,83,85,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,
45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,52,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,97,
112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,
109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,
45,53,102,44,99,48,45,100,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,115,105,122,
101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,49,
44,102,48,45,102,49,58,48,48,48,48,45,102,102,102,102,10,10,98,111,97,114,100,58,32,72,73,82,79,77,10,32,
32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,
10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,
48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,
102,102,58,48,48,48,48,45,102,102,102,102,10,10,98,111,97,114,100,58,32,72,73,82,79,77,45,82,65,77,10,32,
32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,
10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,
48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,
102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,
111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,
102,44,97,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,
111,97,114,100,58,32,72,73,84,65,67,72,73,45,76,79,82,79,77,10,32,32,112,114,111,99,101,115,115,111,114,32,
97,114,99,104,105,116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,99,48,48,45,54,102,102,102,44,55,99,48,
48,45,55,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,
110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,
51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,
32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,55,58,48,48,48,48,45,55,102,102,
102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,
116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,10,32,32,32,32,109,101,
109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,
116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,54,98,102,102,44,55,48,48,48,45,55,
98,102,102,32,109,97,115,107,61,48,120,102,48,48,48,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,
98,111,97,114,100,58,32,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101,109,111,114,121,32,116,121,
32,69,88,83,80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,109,101,109,111,114,121,
32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,69,120,112,97,110,115,105,111,110,10,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,52,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,
111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,
10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,
10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,
44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,
32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,
32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,
61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,
121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,
32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,
69,112,115,111,110,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,
102,58,52,56,52,48,45,52,56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,
99,111,110,116,101,110,116,61,84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,
10,98,111,97,114,100,58,32,71,66,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,
56,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,
58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,
111,114,32,105,100,101,110,116,105,102,105,101,114,61,73,67,68,32,114,101,118,105,115,105,111,110,61,50,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,54,55,
102,102,44,55,48,48,48,45,55,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,66,111,111,116,32,97,114,99,104,105,116,101,99,116,117,114,101,61,76,82,51,53,57,
48,50,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,32,32,32,32,115,108,111,116,32,116,121,112,101,61,
71,97,109,101,66,111,121,10,10,98,111,97,114,100,58,32,71,83,85,45,82,65,77,10,32,32,112,114,111,99,101,115,
115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,71,83,85,10,32,32,32,32,109,97,112,32,97,100,100,
114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,52,102,102,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,
32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,
48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,
114,101,115,115,61,52,48,45,53,102,44,99,48,45,100,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,
102,102,102,32,115,105,122,101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,55,48,45,55,49,44,102,48,45,102,49,58,48,48,48,48,45,102,102,102,102,10,10,98,111,97,114,100,58,32,
72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,
80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,
45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,
45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,10,98,111,97,114,100,58,32,72,73,82,79,
77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,
80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,
45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,
45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,
101,48,48,48,10,10,98,111,97,114,100,58,32,72,73,84,65,67,72,73,45,76,79,82,79,77,10,32,32,112,114,111,
99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,99,48,48,45,54,
102,102,102,44,55,99,48,48,45,55,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,
77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,
120,56,48,48,48,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,
116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,55,58,48,
48,48,48,45,55,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,
10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,
97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,72,71,53,49,66,83,49,54,57,10,32,32,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,54,98,102,102,
44,55,48,48,48,45,55,98,102,102,32,109,97,115,107,61,48,120,102,48,48,48,10,32,32,32,32,111,115,99,105,108,
108,97,116,111,114,10,10,98,111,97,114,100,58,32,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,
61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101,
109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,
102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,
77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,
48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,10,98,111,97,114,100,58,32,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,32,116,121,
112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,
100,100,114,101,115,115,61,48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,
107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,
110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,
45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,
58,32,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
48,48,45,55,100,44,56,48,45,102,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,
48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,
10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,48,48,
48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,58,32,78,69,67,45,72,
73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,
114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,
98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,
55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,101,115,115,111,114,32,97,
114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,
120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,
32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,
114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,
101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,
32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,
61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,48,48,48,45,55,102,102,
102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,
101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,102,102,102,10,
32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,
114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,
101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,
55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,32,78,69,67,45,
76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,
80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,
45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,
45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,10,98,111,97,114,100,
58,32,78,69,67,45,72,73,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,
110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,
45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,
101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48,48,48,45,102,102,102,102,
32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,
68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,
116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,
109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,
104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,
10,10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,65,10,32,32,109,101,109,111,114,
121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,
32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,
111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,
100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,
99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,
51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,
32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,
114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,
101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,
32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,
56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,
97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,
48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,
114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,
107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,
53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,
116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,
99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,
97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,
61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,79,
66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,
54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102,102,102,44,101,48,48,48,
45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100,58,32,83,65,49,45,82,
65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,87,54,53,67,
56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,
58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,
114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,
48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,
58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,
61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,
101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,115,105,122,101,61,48,
120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,52,102,58,48,48,
48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,
101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101,61,48,120,56,48,48,10,
10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,
105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,
48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,
32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,
10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,
114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32,32,109,101,109,111,114,121,
32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,
107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,51,58,48,
48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,
32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,
61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,
32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,
48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,
48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80,67,55,49,49,48,45,82,
65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,
48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,
48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,
48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,
48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,
48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,
32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,
32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,
48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114,100,58,32,83,80,67,55,
49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,
110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,
32,109,97,115,107,61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,
55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,
105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,
10,98,111,97,114,100,58,32,78,69,67,45,72,73,82,79,77,45,82,65,77,10,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,55,100,44,99,48,45,102,102,58,48,48,48,48,45,102,
102,102,102,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,
118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,54,
48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,
32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,
61,48,120,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,
110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,
32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,
32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,
32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,
117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,10,98,111,97,114,
100,58,32,78,69,67,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,
53,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,51,48,45,51,102,44,98,48,45,98,102,58,56,48,
48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,
116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,
50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,
97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,
105,108,108,97,116,111,114,10,10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,65,10,
32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,
109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,45,57,102,58,56,48,
48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,
115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,112,114,111,99,101,
115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,97,
112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,
109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,
55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,109,
101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,97,114,99,104,
105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,116,111,114,10,
10,98,111,97,114,100,58,32,78,69,67,45,76,79,82,79,77,45,82,65,77,35,66,10,32,32,109,101,109,111,114,121,
32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,
112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,
109,97,115,107,61,48,120,56,48,48,48,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,
110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,
44,102,48,45,102,102,58,48,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,
114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,55,
102,102,102,32,109,97,115,107,61,48,120,51,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,
82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,32,97,114,99,104,105,116,101,99,116,117,114,101,
61,117,80,68,55,55,50,53,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,
116,101,110,116,61,68,97,116,97,32,97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,68,97,116,97,32,
97,114,99,104,105,116,101,99,116,117,114,101,61,117,80,68,55,55,50,53,10,32,32,32,32,111,115,99,105,108,108,97,
116,111,114,10,10,98,111,97,114,100,58,32,79,66,67,49,45,76,79,82,79,77,45,82,65,77,10,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,
102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,
105,102,105,101,114,61,79,66,67,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,
44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,49,44,102,48,45,102,49,58,54,48,48,48,45,55,102,
102,102,44,101,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,101,109,
111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,10,98,111,97,114,100,
58,32,83,65,49,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,97,114,99,104,105,116,101,99,116,117,
114,101,61,87,54,53,67,56,49,54,83,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,
102,44,56,48,45,98,102,58,50,50,48,48,45,50,51,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,
102,32,109,97,115,107,61,48,120,52,48,56,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,
115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,101,109,111,
114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,
32,115,105,122,101,61,48,120,50,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,
48,45,52,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,
65,77,32,99,111,110,116,101,110,116,61,73,110,116,101,114,110,97,108,10,32,32,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,51,48,48,48,45,51,55,102,102,32,115,105,122,101,
61,48,120,56,48,48,10,10,98,111,97,114,100,58,32,83,68,68,49,10,32,32,112,114,111,99,101,115,115,111,114,32,
105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,32,32,109,99,117,10,32,32,
32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,
45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,
100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,
48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,
116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,
99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,
32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,
48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,32,32,32,32,109,
97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,52,48,45,52,56,52,50,
10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116,101,110,116,61,84,105,109,
101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97,114,100,58,32,83,84,45,
76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,
80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,49,102,44,56,48,
45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,115,108,111,116,
32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,10,32,32,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,48,48,48,45,102,102,102,
102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,102,102,102,102,10,32,32,
115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,10,32,32,
32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45,100,102,58,48,48,48,48,
45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,32,32,32,
109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,48,48,48,45,102,102,102,
102,10,10,
45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,
48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,
110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,68,68,49,45,82,65,77,10,32,
32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,
32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,
102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
55,48,45,55,51,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,112,114,
111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,68,68,49,10,32,32,32,32,109,97,112,32,
97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,48,102,10,32,32,
32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,
45,98,102,58,56,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,
99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,
101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,10,98,111,97,114,100,58,32,83,80,
67,55,49,49,48,45,82,65,77,10,32,32,112,114,111,99,101,115,115,111,114,32,105,100,101,110,116,105,102,105,101,114,
61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,
48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,53,
48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,32,109,99,117,10,32,32,32,32,32,32,109,97,112,
32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,56,48,48,48,45,102,102,102,102,32,109,
97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,99,
48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,99,48,48,48,48,48,10,32,32,32,
32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,80,114,111,103,114,
97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,111,110,116,101,110,116,
61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,65,77,32,99,111,110,116,101,110,
116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,
48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,107,61,48,120,101,48,48,48,10,10,98,111,97,114,
100,58,32,83,80,67,55,49,49,48,45,82,65,77,45,69,80,83,79,78,82,84,67,10,32,32,112,114,111,99,101,115,
115,111,114,32,105,100,101,110,116,105,102,105,101,114,61,83,80,67,55,49,49,48,10,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,48,48,45,52,56,51,102,10,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,53,48,44,53,56,58,48,48,48,48,45,102,102,102,102,10,32,32,32,
32,109,99,117,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,
98,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,48,48,10,32,32,32,32,32,
32,109,97,112,32,97,100,100,114,101,115,115,61,99,48,45,102,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,
107,61,48,120,99,48,48,48,48,48,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,
32,99,111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,32,32,109,101,109,111,114,121,32,116,121,
112,101,61,82,79,77,32,99,111,110,116,101,110,116,61,68,97,116,97,10,32,32,32,32,109,101,109,111,114,121,32,116,
121,112,101,61,82,65,77,32,99,111,110,116,101,110,116,61,83,97,118,101,10,32,32,32,32,32,32,109,97,112,32,97,
100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,54,48,48,48,45,55,102,102,102,32,109,97,115,
107,61,48,120,101,48,48,48,10,32,32,114,116,99,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,
110,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,48,45,51,102,44,56,48,45,98,102,58,52,56,
52,48,45,52,56,52,50,10,32,32,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,84,67,32,99,111,110,116,
101,110,116,61,84,105,109,101,32,109,97,110,117,102,97,99,116,117,114,101,114,61,69,112,115,111,110,10,10,98,111,97,
114,100,58,32,83,84,45,76,79,82,79,77,10,32,32,109,101,109,111,114,121,32,116,121,112,101,61,82,79,77,32,99,
111,110,116,101,110,116,61,80,114,111,103,114,97,109,10,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,48,
48,45,49,102,44,56,48,45,57,102,58,56,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,
10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,32,114,111,109,
10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,50,48,45,51,102,44,97,48,45,98,102,58,56,
48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,10,32,32,32,
32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,54,48,45,54,102,44,101,48,45,101,102,58,48,48,48,48,45,
102,102,102,102,10,32,32,115,108,111,116,32,116,121,112,101,61,83,117,102,97,109,105,84,117,114,98,111,10,32,32,32,
32,114,111,109,10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,52,48,45,53,102,44,99,48,45,
100,102,58,48,48,48,48,45,102,102,102,102,32,109,97,115,107,61,48,120,56,48,48,48,10,32,32,32,32,114,97,109,
10,32,32,32,32,32,32,109,97,112,32,97,100,100,114,101,115,115,61,55,48,45,55,100,44,102,48,45,102,102,58,48,
48,48,48,45,102,102,102,102,10,10,
};
const nall::vector<uint8_t> IPLROM = { //size: 64
205,239,189,232,0,198,29,208,252,143,170,244,143,187,245,120,204,244,208,251,47,25,235,244,208,252,126,244,208,11,228,245,

View File

@ -62,9 +62,36 @@ AdvancedSettings::AdvancedSettings(TabFrame* parent) : TabFrameItem(parent) {
}
});
optionsLabel.setText("Options").setFont(Font().setBold());
warnOnUnverifiedGames.setText("Warn when loading games that have not been verified").setChecked(settings["Emulator/WarnOnUnverifiedGames"].boolean()).onToggle([&] {
settings["Emulator/WarnOnUnverifiedGames"].setValue(warnOnUnverifiedGames.checked());
});
autoSaveMemory.setText("Auto-save memory periodically").setChecked(settings["Emulator/AutoSaveMemory/Enable"].boolean()).onToggle([&] {
settings["Emulator/AutoSaveMemory/Enable"].setValue(autoSaveMemory.checked());
});
autoSaveStateOnUnload.setText("Auto-save undo state when unloading games").setChecked(settings["Emulator/AutoSaveStateOnUnload"].boolean()).onToggle([&] {
settings["Emulator/AutoSaveStateOnUnload"].setValue(autoSaveStateOnUnload.checked());
if(!autoSaveStateOnUnload.checked()) {
autoLoadStateOnLoad.setEnabled(false).setChecked(false).doToggle();
} else {
autoLoadStateOnLoad.setEnabled(true);
}
}).doToggle();
autoLoadStateOnLoad.setText("Auto-resume on load").setChecked(settings["Emulator/AutoLoadStateOnLoad"].boolean()).onToggle([&] {
settings["Emulator/AutoLoadStateOnLoad"].setValue(autoLoadStateOnLoad.checked());
});
hacksLabel.setText("Emulator Hacks").setFont(Font().setBold());
fastPPUOption.setText("Fast PPU").setChecked(settings["Emulator/Hack/FastPPU"].boolean()).onToggle([&] {
settings["Emulator/Hack/FastPPU"].setValue(fastPPUOption.checked());
if(!fastPPUOption.checked()) {
noSpriteLimit.setEnabled(false).setChecked(false).doToggle();
} else {
noSpriteLimit.setEnabled(true);
}
}).doToggle();
noSpriteLimit.setText("No sprite limit").setChecked(settings["Emulator/Hack/FastPPU/NoSpriteLimit"].boolean()).onToggle([&] {
settings["Emulator/Hack/FastPPU/NoSpriteLimit"].setValue(noSpriteLimit.checked());
});
fastDSPOption.setText("Fast DSP").setChecked(settings["Emulator/Hack/FastDSP"].boolean()).onToggle([&] {
settings["Emulator/Hack/FastDSP"].setValue(fastDSPOption.checked());

View File

@ -54,6 +54,8 @@ AudioSettings::AudioSettings(TabFrame* parent) : TabFrameItem(parent) {
settings["Audio/Reverb"].setValue(reverb.checked());
program->updateAudioEffects();
});
//todo: does not work properly with Super Game Boy
reverb.setVisible(false);
}
auto AudioSettings::updateDevice() -> void {

View File

@ -59,11 +59,15 @@ Settings::Settings() {
set("UserInterface/ShowStatusBar", true);
set("Emulator/Hack/FastPPU", true);
set("Emulator/Hack/FastDSP", true);
set("Emulator/Hack/FastSuperFX", "100%");
set("Emulator/WarnOnUnverifiedGames", false);
set("Emulator/AutoSaveMemory/Enable", true);
set("Emulator/AutoSaveMemory/Interval", 30);
set("Emulator/AutoSaveStateOnUnload", false);
set("Emulator/AutoLoadStateOnLoad", false);
set("Emulator/Hack/FastPPU", true);
set("Emulator/Hack/FastPPU/NoSpriteLimit", false);
set("Emulator/Hack/FastDSP", true);
set("Emulator/Hack/FastSuperFX", "100%");
set("Crashed", false);
}

View File

@ -165,8 +165,16 @@ public:
ComboButton audioDriverOption{&driverLayout, Size{~0, 0}};
Label inputDriverLabel{&driverLayout, Size{0, 0}};
ComboButton inputDriverOption{&driverLayout, Size{~0, 0}};
Label optionsLabel{&layout, Size{~0, 0}, 2};
CheckLabel warnOnUnverifiedGames{&layout, Size{~0, 0}};
CheckLabel autoSaveMemory{&layout, Size{~0, 0}};
HorizontalLayout autoStateLayout{&layout, Size{~0, 0}};
CheckLabel autoSaveStateOnUnload{&autoStateLayout, Size{0, 0}};
CheckLabel autoLoadStateOnLoad{&autoStateLayout, Size{0, 0}};
Label hacksLabel{&layout, Size{~0, 0}, 2};
CheckLabel fastPPUOption{&layout, Size{~0, 0}};
HorizontalLayout fastPPULayout{&layout, Size{~0, 0}};
CheckLabel fastPPUOption{&fastPPULayout, Size{0, 0}};
CheckLabel noSpriteLimit{&fastPPULayout, Size{0, 0}};
CheckLabel fastDSPOption{&layout, Size{~0, 0}};
HorizontalLayout superFXLayout{&layout, Size{~0, 0}};
Label superFXLabel{&superFXLayout, Size{0, 0}};

View File

@ -116,8 +116,11 @@ CheatEditor::CheatEditor(TabFrame* parent) : TabFrameItem(parent) {
editButton.setEnabled(batched.size() == 1);
removeButton.setEnabled(batched.size() >= 1);
});
cheatList.onToggle([&](TableViewCell) {
synchronizeCodes();
cheatList.onToggle([&](TableViewCell cell) {
if(auto item = cell->parentTableViewItem()) {
cheats[item->offset()].enable = cell.checked();
synchronizeCodes();
}
});
findCheatsButton.setText("Find Cheats ...").onActivate([&] {
cheatDatabase->findCheats();

View File

@ -206,6 +206,8 @@ auto Presentation::updateEmulator() -> void {
}
auto Presentation::drawIcon(uint32_t* output, uint length, uint width, uint height) -> void {
return;
int ox = width - 128;
int oy = height - 128;
if(ox >= 0 && oy >= 0) {
@ -228,8 +230,8 @@ auto Presentation::clearViewport() -> void {
uint32_t* output;
uint length = 0;
uint width = viewport.geometry().width();
uint height = viewport.geometry().height();
uint width = 16;
uint height = 16;
if(video->lock(output, length, width, height)) {
for(uint y : range(height)) {
auto line = output + y * (length >> 2);

View File

@ -10,6 +10,10 @@ auto Application::font() -> Font {
return state.font;
}
auto Application::modal() -> bool {
return state.modal > 0;
}
auto Application::name() -> string {
return state.name;
}

View File

@ -374,6 +374,7 @@ struct Application {
static auto doMain() -> void;
static auto font() -> Font;
static auto modal() -> bool;
static auto name() -> string;
static auto onMain(const function<void ()>& callback = {}) -> void;
static auto run() -> void;
@ -408,6 +409,7 @@ struct Application {
//private:
struct State {
Font font;
int modal = 0;
string name;
function<void ()> onMain;
bool quit = false;

View File

@ -248,6 +248,12 @@ auto mWindow::setGeometry(Geometry geometry) -> type& {
auto mWindow::setModal(bool modal) -> type& {
state.modal = modal;
signal(setModal, modal);
if(modal) {
Application::state.modal++;
} else {
Application::state.modal--;
assert(Application::state.modal >= 0);
}
return *this;
}

View File

@ -4,7 +4,7 @@ namespace hiro {
auto pLabel::construct() -> void {
hwnd = CreateWindow(L"hiroLabel", L"",
WS_CHILD,
WS_CHILD | WS_CLIPSIBLINGS,
0, 0, 0, 0, _parentHandle(), nullptr, GetModuleHandle(0), 0);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&reference);
pWidget::_setState();