diff --git a/bsnes/gameboy/cartridge/cartridge.cpp b/bsnes/gameboy/cartridge/cartridge.cpp index ebb94f26..cc5eb041 100755 --- a/bsnes/gameboy/cartridge/cartridge.cpp +++ b/bsnes/gameboy/cartridge/cartridge.cpp @@ -83,7 +83,9 @@ void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) { ramdata = new uint8_t[ramsize = info.ramsize](); system.load(); + loaded = true; + sha256 = nall::sha256(romdata, romsize); } void Cartridge::unload() { diff --git a/bsnes/gameboy/cartridge/cartridge.hpp b/bsnes/gameboy/cartridge/cartridge.hpp index 92842ebd..8508814b 100755 --- a/bsnes/gameboy/cartridge/cartridge.hpp +++ b/bsnes/gameboy/cartridge/cartridge.hpp @@ -34,6 +34,7 @@ struct Cartridge : MMIO, property { } info; readonly loaded; + readonly sha256; uint8_t *romdata; unsigned romsize; diff --git a/bsnes/gameboy/gameboy.hpp b/bsnes/gameboy/gameboy.hpp index f32c2547..cd3b17bb 100755 --- a/bsnes/gameboy/gameboy.hpp +++ b/bsnes/gameboy/gameboy.hpp @@ -4,7 +4,6 @@ namespace GameBoy { namespace Info { static const char Name[] = "bgameboy"; - static const char Version[] = "000.23"; static unsigned SerializerVersion = 2; } } diff --git a/bsnes/nes/cartridge/cartridge.cpp b/bsnes/nes/cartridge/cartridge.cpp index 82599183..ac3fe4f6 100755 --- a/bsnes/nes/cartridge/cartridge.cpp +++ b/bsnes/nes/cartridge/cartridge.cpp @@ -37,6 +37,7 @@ void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) { } loaded = true; + sha256 = nall::sha256(rom_data, rom_size); } void Cartridge::unload() { diff --git a/bsnes/nes/cartridge/cartridge.hpp b/bsnes/nes/cartridge/cartridge.hpp index 5aff5514..2ee5fe50 100755 --- a/bsnes/nes/cartridge/cartridge.hpp +++ b/bsnes/nes/cartridge/cartridge.hpp @@ -9,6 +9,7 @@ struct Cartridge : property { void reset(); readonly loaded; + readonly sha256; Cartridge(); diff --git a/bsnes/nes/nes.hpp b/bsnes/nes/nes.hpp index 0b7aa956..65934ffd 100755 --- a/bsnes/nes/nes.hpp +++ b/bsnes/nes/nes.hpp @@ -4,7 +4,6 @@ namespace NES { namespace Info { static const char Name[] = "bnes"; - static const char Version[] = "000.14"; } } diff --git a/bsnes/ruby/video/glx.cpp b/bsnes/ruby/video/glx.cpp index 1f6f9a3b..949b811e 100755 --- a/bsnes/ruby/video/glx.cpp +++ b/bsnes/ruby/video/glx.cpp @@ -96,6 +96,7 @@ public: if(name == Video::Shader) { OpenGL::set_shader(any_cast(value)); + settings.filter = any_cast(OpenGL::shaderfilter); return true; } diff --git a/bsnes/ruby/video/opengl.hpp b/bsnes/ruby/video/opengl.hpp index add60abb..e57d0206 100755 --- a/bsnes/ruby/video/opengl.hpp +++ b/bsnes/ruby/video/opengl.hpp @@ -28,6 +28,7 @@ class OpenGL { public: GLuint gltexture; GLuint glprogram; + unsigned shaderfilter; GLuint fragmentshader; GLuint vertexshader; bool shader_support; @@ -139,6 +140,7 @@ public: if(source) { bool is_glsl = false; + shaderfilter = 0; string fragment_source; string vertex_source; @@ -147,6 +149,7 @@ public: if(head.name == "shader") { foreach(attribute, head.attribute) { if(attribute.name == "language" && attribute.content == "GLSL") is_glsl = true; + if(attribute.name == "filter") shaderfilter = attribute.content == "linear" ? 1 : 0; } foreach(element, head.element) { if(element.name == "fragment") { @@ -236,6 +239,7 @@ public: OpenGL() { gltexture = 0; glprogram = 0; + shaderfilter = 0; fragmentshader = 0; vertexshader = 0; diff --git a/bsnes/ruby/video/wgl.cpp b/bsnes/ruby/video/wgl.cpp index 9a2e82ac..5277c695 100755 --- a/bsnes/ruby/video/wgl.cpp +++ b/bsnes/ruby/video/wgl.cpp @@ -65,6 +65,7 @@ public: if(name == Video::Shader) { settings.shader = any_cast(value); OpenGL::set_shader(settings.shader); + settings.filter = any_cast(OpenGL::shaderfilter); return true; } diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index 3e4e6144..d450de5f 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -4,7 +4,6 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "082.18"; static const unsigned SerializerVersion = 22; } } diff --git a/bsnes/ui/config/config.cpp b/bsnes/ui/config/config.cpp index 6d3cd7be..e33ebe50 100755 --- a/bsnes/ui/config/config.cpp +++ b/bsnes/ui/config/config.cpp @@ -3,11 +3,11 @@ Config *config = 0; Config::Config() { attach(video.driver = "", "Video::Driver"); - attach(video.shader = "", "Video::Shader"); + attach(video.filter = "None", "Video::Filter"); + attach(video.shader = "None", "Video::Shader"); attach(video.synchronize = true, "Video::Synchronize"); attach(video.enableOverscan = false, "Video::EnableOverscan"); attach(video.correctAspectRatio = true, "Video::CorrectAspectRatio"); - attach(video.smooth = true, "Video::Smooth"); attach(video.brightness = 100, "Video::Brightness"); attach(video.contrast = 100, "Video::Contrast"); diff --git a/bsnes/ui/config/config.hpp b/bsnes/ui/config/config.hpp index 2d757174..482424b5 100755 --- a/bsnes/ui/config/config.hpp +++ b/bsnes/ui/config/config.hpp @@ -1,11 +1,11 @@ struct Config : public configuration { struct Video { string driver; + string filter; string shader; bool synchronize; bool enableOverscan; bool correctAspectRatio; - bool smooth; unsigned brightness; unsigned contrast; diff --git a/bsnes/ui/general/main-window.cpp b/bsnes/ui/general/main-window.cpp index f4b82fcd..daa885ab 100755 --- a/bsnes/ui/general/main-window.cpp +++ b/bsnes/ui/general/main-window.cpp @@ -59,8 +59,13 @@ MainWindow::MainWindow() { gameBoyCartridgeUnload.setText("Unload Cartridge"); settingsMenu.setText("Settings"); - settingsVideoShaders.setText("Video Shader"); - setupVideoShaders(); + settingsVideoFilter.setText("Video Filter"); + settingsVideoFilterNone.setText("None"); + setupVideoFilters(); + settingsVideoShader.setText("Video Shader"); + settingsVideoShaderNone.setText("None"); + settingsVideoShaderBlur.setText("Blur"); + setupVideoShaders(); settingsSynchronizeVideo.setText("Synchronize Video"); settingsSynchronizeVideo.setChecked(config->video.synchronize); settingsSynchronizeAudio.setText("Synchronize Audio"); @@ -69,8 +74,6 @@ MainWindow::MainWindow() { settingsEnableOverscan.setChecked(config->video.enableOverscan); settingsCorrectAspectRatio.setText("Correct Aspect Ratio"); settingsCorrectAspectRatio.setChecked(config->video.correctAspectRatio); - settingsSmoothVideo.setText("Smooth Video Output"); - settingsSmoothVideo.setChecked(config->video.smooth); settingsMuteAudio.setText("Mute Audio"); settingsMuteAudio.setChecked(config->audio.mute); settingsConfiguration.setText("Configuration ..."); @@ -88,11 +91,9 @@ MainWindow::MainWindow() { toolsStateLoad3.setText("Slot 3"); toolsStateLoad4.setText("Slot 4"); toolsStateLoad5.setText("Slot 5"); - toolsCaptureMouse.setText("Capture Mouse"); toolsShrinkWindow.setText("Shrink Window"); toolsCheatEditor.setText("Cheat Editor ..."); toolsStateManager.setText("State Manager ..."); - toolsTest.setText("Test"); append(cartridgeMenu); cartridgeMenu.append(cartridgeLoadNES); @@ -144,16 +145,25 @@ MainWindow::MainWindow() { gameBoyMenu.append(gameBoyCartridgeUnload); append(settingsMenu); - settingsMenu.append(settingsVideoShaders); - for(unsigned n = 0; n < videoShaderCount; n++) - settingsVideoShaders.append(settingsVideoShader[n]); + settingsMenu.append(settingsVideoFilter); + settingsVideoFilter.append(settingsVideoFilterNone); + if(videoFilterName.size()) + settingsVideoFilter.append(settingsVideoFilterSeparator); + for(unsigned n = 0; n < videoFilterName.size(); n++) + settingsVideoFilter.append(settingsVideoFilterList[n]); + settingsMenu.append(settingsVideoShader); + settingsVideoShader.append(settingsVideoShaderNone); + settingsVideoShader.append(settingsVideoShaderBlur); + if(videoShaderName.size()) + settingsVideoShader.append(settingsVideoShaderSeparator); + for(unsigned n = 0; n < videoShaderName.size(); n++) + settingsVideoShader.append(settingsVideoShaderList[n]); settingsMenu.append(settingsSeparator1); settingsMenu.append(settingsSynchronizeVideo); settingsMenu.append(settingsSynchronizeAudio); settingsMenu.append(settingsSeparator2); settingsMenu.append(settingsEnableOverscan); settingsMenu.append(settingsCorrectAspectRatio); - settingsMenu.append(settingsSmoothVideo); settingsMenu.append(settingsMuteAudio); settingsMenu.append(settingsSeparator3); settingsMenu.append(settingsConfiguration); @@ -171,14 +181,10 @@ MainWindow::MainWindow() { toolsStateLoad.append(toolsStateLoad3); toolsStateLoad.append(toolsStateLoad4); toolsStateLoad.append(toolsStateLoad5); - toolsMenu.append(toolsSeparator1); - toolsMenu.append(toolsCaptureMouse); + toolsMenu.append(toolsSeparator); toolsMenu.append(toolsShrinkWindow); - toolsMenu.append(toolsSeparator2); toolsMenu.append(toolsCheatEditor); toolsMenu.append(toolsStateManager); - toolsMenu.append(toolsSeparator3); - toolsMenu.append(toolsTest); setMenuVisible(); @@ -247,6 +253,21 @@ MainWindow::MainWindow() { gameBoyPower.onTick = { &Interface::power, interface }; gameBoyCartridgeUnload.onTick = { &Interface::unloadCartridge, interface }; + settingsVideoFilterNone.onTick = [&] { + config->video.filter = "None"; + utility->bindVideoFilter(); + }; + + settingsVideoShaderNone.onTick = [&] { + config->video.shader = "None"; + utility->bindVideoShader(); + }; + + settingsVideoShaderBlur.onTick = [&] { + config->video.shader = "Blur"; + utility->bindVideoShader(); + }; + settingsSynchronizeVideo.onTick = [&] { config->video.synchronize = settingsSynchronizeVideo.checked(); video.set(Video::Synchronize, config->video.synchronize); @@ -267,11 +288,6 @@ MainWindow::MainWindow() { utility->resizeMainWindow(); }; - settingsSmoothVideo.onTick = [&] { - config->video.smooth = settingsSmoothVideo.checked(); - video.set(Video::Filter, config->video.smooth == false ? 0u : 1u); - }; - settingsMuteAudio.onTick = [&] { config->audio.mute = settingsMuteAudio.checked(); dspaudio.setVolume(config->audio.mute == false ? 1.0 : 0.0); @@ -291,16 +307,10 @@ MainWindow::MainWindow() { toolsStateLoad4.onTick = [&] { interface->loadState(4); }; toolsStateLoad5.onTick = [&] { interface->loadState(5); }; - toolsCaptureMouse.onTick = [&] { input.acquire(); }; toolsShrinkWindow.onTick = [&] { utility->resizeMainWindow(true); }; - toolsCheatEditor.onTick = [&] { cheatEditor->setVisible(); }; toolsStateManager.onTick = [&] { stateManager->setVisible(); }; - toolsTest.onTick = [&] { - NES::cpu.trace = toolsTest.checked(); - }; - synchronize(); } @@ -314,33 +324,56 @@ void MainWindow::synchronize() { } } +void MainWindow::setupVideoFilters() { + lstring files = directory::files({ application->userpath, "filters/" }, "*.filter"); + reference_array group; + + settingsVideoFilterList = new RadioItem[files.size()]; + for(unsigned n = 0; n < files.size(); n++) { + string name = files[n]; + videoFilterName.append({ application->userpath, "filters/", name }); + if(auto position = name.position(".filter")) name[position()] = 0; + + settingsVideoFilterList[n].setText(name); + settingsVideoFilterList[n].onTick = [&, n] { + config->video.filter = videoFilterName[n]; + utility->bindVideoFilter(); + }; + } + + group.append(settingsVideoFilterNone); + for(unsigned n = 0; n < files.size(); n++) group.append(settingsVideoFilterList[n]); + RadioItem::group(group); + + if(config->video.filter == "None") settingsVideoFilterNone.setChecked(); + for(unsigned n = 0; n < files.size(); n++) + if(config->video.filter == videoFilterName[n]) settingsVideoFilterList[n].setChecked(); +} + void MainWindow::setupVideoShaders() { lstring files = directory::files({ application->userpath, "shaders/" }, { "*.", config->video.driver, ".shader" }); - videoShaderCount = 1 + files.size(); - reference_array group; - unsigned active = 0; - settingsVideoShader = new RadioItem[videoShaderCount]; - for(unsigned n = 0; n < videoShaderCount; n++) { - string name; - if(n == 0) { - name = "None"; - videoShaderName.append(""); - } else { - name = files[n - 1]; - videoShaderName.append({ application->userpath, "shaders/", name }); - if(auto position = name.position(string{ ".", config->video.driver, ".shader" })) name[position()] = 0; - } - if(config->video.shader == videoShaderName[n]) active = n; - settingsVideoShader[n].setText(name); - settingsVideoShader[n].onTick = [&, n] { + settingsVideoShaderList = new RadioItem[files.size()]; + for(unsigned n = 0; n < files.size(); n++) { + string name = files[n]; + videoShaderName.append({ application->userpath, "shaders/", name }); + if(auto position = name.position(string{ ".", config->video.driver, ".shader" })) name[position()] = 0; + + settingsVideoShaderList[n].setText(name); + settingsVideoShaderList[n].onTick = [&, n] { config->video.shader = videoShaderName[n]; utility->bindVideoShader(); }; } - for(unsigned n = 0; n < videoShaderCount; n++) group.append(settingsVideoShader[n]); + group.append(settingsVideoShaderNone); + group.append(settingsVideoShaderBlur); + for(unsigned n = 0; n < files.size(); n++) group.append(settingsVideoShaderList[n]); RadioItem::group(group); - settingsVideoShader[active].setChecked(); + + if(config->video.shader == "None") settingsVideoShaderNone.setChecked(); + if(config->video.shader == "Blur") settingsVideoShaderBlur.setChecked(); + for(unsigned n = 0; n < files.size(); n++) + if(config->video.shader == videoShaderName[n]) settingsVideoShaderList[n].setChecked(); } diff --git a/bsnes/ui/general/main-window.hpp b/bsnes/ui/general/main-window.hpp index ce6bbf2a..8ab0372a 100755 --- a/bsnes/ui/general/main-window.hpp +++ b/bsnes/ui/general/main-window.hpp @@ -40,15 +40,21 @@ struct MainWindow : Window { Item gameBoyCartridgeUnload; Menu settingsMenu; - Menu settingsVideoShaders; - RadioItem *settingsVideoShader; + Menu settingsVideoFilter; + RadioItem settingsVideoFilterNone; + Separator settingsVideoFilterSeparator; + RadioItem *settingsVideoFilterList; + Menu settingsVideoShader; + RadioItem settingsVideoShaderNone; + RadioItem settingsVideoShaderBlur; + Separator settingsVideoShaderSeparator; + RadioItem *settingsVideoShaderList; Separator settingsSeparator1; CheckItem settingsSynchronizeVideo; CheckItem settingsSynchronizeAudio; Separator settingsSeparator2; CheckItem settingsEnableOverscan; CheckItem settingsCorrectAspectRatio; - CheckItem settingsSmoothVideo; CheckItem settingsMuteAudio; Separator settingsSeparator3; Item settingsConfiguration; @@ -66,22 +72,19 @@ struct MainWindow : Window { Item toolsStateLoad3; Item toolsStateLoad4; Item toolsStateLoad5; - Separator toolsSeparator1; - Item toolsCaptureMouse; + Separator toolsSeparator; Item toolsShrinkWindow; - Separator toolsSeparator2; Item toolsCheatEditor; Item toolsStateManager; - Separator toolsSeparator3; - CheckItem toolsTest; void synchronize(); MainWindow(); private: - unsigned videoShaderCount; + lstring videoFilterName; lstring videoShaderName; + void setupVideoFilters(); void setupVideoShaders(); }; diff --git a/bsnes/ui/interface/interface.cpp b/bsnes/ui/interface/interface.cpp index d64ba9a5..f1012dcb 100755 --- a/bsnes/ui/interface/interface.cpp +++ b/bsnes/ui/interface/interface.cpp @@ -5,6 +5,23 @@ #include "gameboy.cpp" Interface *interface = 0; +Filter filter; + +void Filter::render(const uint16_t *input, unsigned inputPitch, unsigned inputWidth, unsigned inputHeight) { + width = inputWidth, height = inputHeight; + dl_size(width, height); + dl_render(data, pitch, input, inputPitch, inputWidth, inputHeight); +} + +Filter::Filter() { + data = new uint16_t[1024 * 1024]; + pitch = 1024 * sizeof(uint16_t); +} + +Filter::~Filter() { + delete[] data; +} + void Interface::bindControllers() { switch(mode()) { case Mode::NES: @@ -64,6 +81,7 @@ bool Interface::loadCartridge(const string &filename) { void Interface::unloadCartridge() { if(cartridgeLoaded() == false) return; + cheatDatabase->setVisible(false); cheatEditor->save({ baseName, ".cht" }); stateManager->save({ baseName, ".bsa" }, 0u); setCheatCodes(); @@ -151,6 +169,15 @@ void Interface::setCheatCodes(const lstring &list) { } } +string Interface::sha256() { + switch(mode()) { + case Mode::NES: return NES::cartridge.sha256(); + case Mode::SNES: return SNES::cartridge.sha256(); + case Mode::GameBoy: return GameBoy::cartridge.sha256(); + } + return "{None}"; +} + Interface::Interface() { mode = Mode::None; palette.update(); @@ -166,6 +193,14 @@ void Interface::videoRefresh(const uint16_t *input, unsigned inputPitch, unsigne uint32_t *output; unsigned outputPitch; + if(filter.opened()) { + filter.render(input, inputPitch, width, height); + input = filter.data; + inputPitch = filter.pitch; + width = filter.width; + height = filter.height; + } + if(video.lock(output, outputPitch, width, height)) { inputPitch >>= 1, outputPitch >>= 2; diff --git a/bsnes/ui/interface/interface.hpp b/bsnes/ui/interface/interface.hpp index 1b693ad7..26db893e 100755 --- a/bsnes/ui/interface/interface.hpp +++ b/bsnes/ui/interface/interface.hpp @@ -4,6 +4,21 @@ #include "snes.hpp" #include "gameboy.hpp" +struct Filter : public library { + function dl_size; + function dl_render; + void render(const uint16_t*, unsigned, unsigned, unsigned); + Filter(); + ~Filter(); + + uint16_t *data; + unsigned pitch; + unsigned width; + unsigned height; +}; + +extern Filter filter; + struct Interface : property { enum class Mode : unsigned { None, SNES, NES, GameBoy }; readonly mode; @@ -27,6 +42,7 @@ struct Interface : property { bool saveState(unsigned slot); bool loadState(unsigned slot); void setCheatCodes(const lstring &list = lstring{}); + string sha256(); Interface(); diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 69e73ef5..4fa1213d 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -41,7 +41,7 @@ Application::Application(int argc, char **argv) { inputManager = new InputManager; utility = new Utility; - title = "bsnes"; + title = "bsnes v082.19"; #if defined(PLATFORM_WIN) normalFont = "Tahoma, 8"; @@ -59,6 +59,7 @@ Application::Application(int argc, char **argv) { slotLoader = new SlotLoader; dipSwitches = new DipSwitches; settingsWindow = new SettingsWindow; + cheatDatabase = new CheatDatabase; cheatEditor = new CheatEditor; stateManager = new StateManager; windowManager->loadGeometry(); @@ -69,8 +70,8 @@ Application::Application(int argc, char **argv) { video.driver(config->video.driver); video.set(Video::Handle, mainWindow->viewport.handle()); video.set(Video::Synchronize, config->video.synchronize); - video.set(Video::Filter, config->video.smooth == false ? 0u : 1u); video.init(); + utility->bindVideoFilter(); utility->bindVideoShader(); audio.driver(config->audio.driver); @@ -104,6 +105,7 @@ Application::Application(int argc, char **argv) { Application::~Application() { delete stateManager; delete cheatEditor; + delete cheatDatabase; delete settingsWindow; delete dipSwitches; delete slotLoader; diff --git a/bsnes/ui/tools/cheat-database.cpp b/bsnes/ui/tools/cheat-database.cpp new file mode 100755 index 00000000..69c0410f --- /dev/null +++ b/bsnes/ui/tools/cheat-database.cpp @@ -0,0 +1,95 @@ +CheatDatabase *cheatDatabase = 0; + +CheatDatabase::CheatDatabase() { + setGeometry({ 128, 128, 640, 400 }); + windowManager->append(this, "CheatDatabase"); + + layout.setMargin(5); + cheatList.setCheckable(); + selectAllButton.setText("Select All"); + unselectAllButton.setText("Unselect All"); + acceptButton.setText("Add Codes"); + + append(layout); + layout.append(cheatList, ~0, ~0, 5); + layout.append(controlLayout, ~0, 0); + controlLayout.append(selectAllButton, 100, 0, 5); + controlLayout.append(unselectAllButton, 100, 0); + controlLayout.append(spacer, ~0, 0); + controlLayout.append(acceptButton, 80, 0); + + selectAllButton.onTick = [&] { + foreach(item, cheatCode, n) cheatList.setChecked(n, true); + }; + + unselectAllButton.onTick = [&] { + foreach(item, cheatCode, n) cheatList.setChecked(n, false); + }; + + acceptButton.onTick = { &CheatDatabase::addCodes, this }; +} + +void CheatDatabase::findCodes() { + string data; + data.readfile({ application->userpath, "cheats.xml" }); + if(auto position = data.position(interface->sha256())) { + auto startPosition = strpos((const char*)data + position(), ">"); + auto endPosition = strpos((const char*)data + position(), ""); + string xmlData = { + "\n", + substr((const char*)data + position() + 1, startPosition(), endPosition() - startPosition() - 1), + "\n" + }; + + setTitle(""); + cheatList.reset(); + cheatCode.reset(); + + xml_element document = xml_parse(xmlData); + foreach(root, document.element) { + if(root.name == "cartridge") { + foreach(node, root.element) { + if(node.name == "name") { + setTitle(node.parse()); + } else if(node.name == "cheat") { + string description, code; + foreach(element, node.element) { + if(element.name == "description") { + description = element.parse(); + } else if(element.name == "code") { + code.append(element.parse(), "+"); + } + } + code.rtrim<1>("+"); + code.append("\t"); + code.append(description); + cheatList.append(description); + cheatCode.append(code); + } + } + } + } + + setVisible(); + } else { + MessageWindow::information(*cheatEditor, "Sorry, no cheat codes were found for this cartridge."); + } +} + +void CheatDatabase::addCodes() { + foreach(code, cheatCode, n) { + if(cheatList.checked(n)) { + lstring part; + part.split<1>("\t", code); + if(cheatEditor->addCode(part[0], part[1]) == false) { + MessageWindow::warning(*this, "Ran out of empty slots for cheat codes.\nNot all cheat codes were added."); + break; + } + } + } + + setVisible(false); + cheatEditor->updateUI(); + cheatEditor->updateInterface(); + cheatEditor->synchronize(); +} diff --git a/bsnes/ui/tools/cheat-database.hpp b/bsnes/ui/tools/cheat-database.hpp new file mode 100755 index 00000000..7c4a89c4 --- /dev/null +++ b/bsnes/ui/tools/cheat-database.hpp @@ -0,0 +1,18 @@ +struct CheatDatabase : Window { + VerticalLayout layout; + ListView cheatList; + HorizontalLayout controlLayout; + Button selectAllButton; + Button unselectAllButton; + Widget spacer; + Button acceptButton; + + void findCodes(); + void addCodes(); + CheatDatabase(); + +private: + lstring cheatCode; +}; + +extern CheatDatabase *cheatDatabase; diff --git a/bsnes/ui/tools/cheat-editor.cpp b/bsnes/ui/tools/cheat-editor.cpp index 0d71301d..67c0ae9b 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -11,7 +11,6 @@ CheatEditor::CheatEditor() { codeLabel.setText("Code(s):"); descLabel.setText("Description:"); findButton.setText("Find Codes ..."); - findButton.setEnabled(false); clearAllButton.setText("Clear All"); clearButton.setText("Clear"); @@ -38,6 +37,7 @@ CheatEditor::CheatEditor() { cheatList.onTick = [&](unsigned) { updateInterface(); }; codeEdit.onChange = { &CheatEditor::updateCode, this }; descEdit.onChange = { &CheatEditor::updateDesc, this }; + findButton.onTick = { &CheatDatabase::findCodes, cheatDatabase }; clearAllButton.onTick = { &CheatEditor::clearAll, this }; clearButton.onTick = { &CheatEditor::clearSelected, this }; } @@ -196,3 +196,15 @@ bool CheatEditor::save(const string &filename) { return true; } + +bool CheatEditor::addCode(const string &code, const string &description) { + for(unsigned n = 0; n < 128; n++) { + if(cheatText[n][Code] == "" && cheatText[n][Desc] == "") { + cheatList.setChecked(n, false); + cheatText[n][Code] = code; + cheatText[n][Desc] = description; + return true; + } + } + return false; +} diff --git a/bsnes/ui/tools/cheat-editor.hpp b/bsnes/ui/tools/cheat-editor.hpp index ad25abc1..39334337 100755 --- a/bsnes/ui/tools/cheat-editor.hpp +++ b/bsnes/ui/tools/cheat-editor.hpp @@ -24,6 +24,7 @@ struct CheatEditor : Window { void reset(); bool load(const string &filename); bool save(const string &filename); + bool addCode(const string &code, const string &description); CheatEditor(); diff --git a/bsnes/ui/tools/tools.cpp b/bsnes/ui/tools/tools.cpp index 5ec3021d..7dcad7cf 100755 --- a/bsnes/ui/tools/tools.cpp +++ b/bsnes/ui/tools/tools.cpp @@ -1,3 +1,4 @@ #include "../base.hpp" +#include "cheat-database.cpp" #include "cheat-editor.cpp" #include "state-manager.cpp" diff --git a/bsnes/ui/tools/tools.hpp b/bsnes/ui/tools/tools.hpp index e7834f88..d6df0ea7 100755 --- a/bsnes/ui/tools/tools.hpp +++ b/bsnes/ui/tools/tools.hpp @@ -1,2 +1,3 @@ +#include "cheat-database.hpp" #include "cheat-editor.hpp" #include "state-manager.hpp" diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index 72ad5761..5c8acfda 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -16,19 +16,19 @@ void Utility::setMode(Interface::Mode mode) { } else if(mode == Interface::Mode::NES) { - mainWindow->setTitle({ notdir(interface->baseName), " - ", NES::Info::Name, " v", NES::Info::Version }); + mainWindow->setTitle(notdir(interface->baseName)); mainWindow->nesMenu.setVisible(true); dspaudio.setChannels(1); } else if(mode == Interface::Mode::SNES) { - mainWindow->setTitle({ notdir(interface->baseName), " - ", SNES::Info::Name, " v", SNES::Info::Version }); + mainWindow->setTitle(notdir(interface->baseName)); mainWindow->snesMenu.setVisible(true); dspaudio.setChannels(2); } else if(mode == Interface::Mode::GameBoy) { - mainWindow->setTitle({ notdir(interface->baseName), " - ", GameBoy::Info::Name, " v", GameBoy::Info::Version }); + mainWindow->setTitle(notdir(interface->baseName)); mainWindow->gameBoyMenu.setVisible(true); dspaudio.setChannels(2); } @@ -107,10 +107,28 @@ void Utility::toggleFullScreen() { resizeMainWindow(); } +void Utility::bindVideoFilter() { + if(filter.opened()) filter.close(); + if(config->video.filter == "None") return; + if(filter.open_absolute(config->video.filter)) { + filter.dl_size = filter.sym("filter_size"); + filter.dl_render = filter.sym("filter_render"); + if(!filter.dl_size || !filter.dl_render) filter.close(); + } +} + void Utility::bindVideoShader() { - string data; - data.readfile(config->video.shader); - video.set(Video::Shader, (const char*)data); + if(config->video.shader == "None") { + video.set(Video::Filter, 0u); + video.set(Video::Shader, (const char*)""); + } else if(config->video.shader == "Blur") { + video.set(Video::Filter, 1u); + video.set(Video::Shader, (const char*)""); + } else { + string data; + data.readfile(config->video.shader); + video.set(Video::Shader, (const char*)data); + } } void Utility::updateStatus() { diff --git a/bsnes/ui/utility/utility.hpp b/bsnes/ui/utility/utility.hpp index 27c2c005..50cfc3b5 100755 --- a/bsnes/ui/utility/utility.hpp +++ b/bsnes/ui/utility/utility.hpp @@ -2,6 +2,7 @@ struct Utility { void setMode(Interface::Mode mode); void resizeMainWindow(bool shrink = false); void toggleFullScreen(); + void bindVideoFilter(); void bindVideoShader(); void updateStatus();