From 5b4dcbfdfe9adce86ccb1b29cc73071cddbeb6f9 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 22 Sep 2011 10:00:21 +1000 Subject: [PATCH] Update to v082r19 release. byuu says: This will be the last release with the ui-snes folder (it's broken now anyway.) Re-added cheat code database searching + add window. It hashes NES+SNES+GB images now and will look them up in the database. Re-added filter support, all filters now output at RGB555. Stacking is possible, but I don't currently allow it. Removed mouse capture + test options from tools menu. Removed smooth video output from settings menu. There are now two built-in "shaders": "None" (point filtering) and "Blur" (linear filtering). OpenGL shaders can now use (or "linear") to specify their filtering mode. Individual emulator versions are gone, and names are hidden from the GUI: you just see bsnes v082.19 now. A new release bumps all core versions. I cannot for the life of me get the video to clear properly when toggling the shaders. Say you set pixellate2x filter, then turn on curvature shader, then turn off the filter, you get junk at the bottom right. I have tried clearing and flipping the OpenGL surface 64x in a row ... I don't know where the hell it's getting the data from. If anyone can make a small patch to fix that, I'd greatly appreciate it. --- bsnes/gameboy/cartridge/cartridge.cpp | 2 + bsnes/gameboy/cartridge/cartridge.hpp | 1 + bsnes/gameboy/gameboy.hpp | 1 - bsnes/nes/cartridge/cartridge.cpp | 1 + bsnes/nes/cartridge/cartridge.hpp | 1 + bsnes/nes/nes.hpp | 1 - bsnes/ruby/video/glx.cpp | 1 + bsnes/ruby/video/opengl.hpp | 4 + bsnes/ruby/video/wgl.cpp | 1 + bsnes/snes/snes.hpp | 1 - bsnes/ui/config/config.cpp | 4 +- bsnes/ui/config/config.hpp | 2 +- bsnes/ui/general/main-window.cpp | 123 ++++++++++++++++---------- bsnes/ui/general/main-window.hpp | 21 +++-- bsnes/ui/interface/interface.cpp | 35 ++++++++ bsnes/ui/interface/interface.hpp | 16 ++++ bsnes/ui/main.cpp | 6 +- bsnes/ui/tools/cheat-database.cpp | 95 ++++++++++++++++++++ bsnes/ui/tools/cheat-database.hpp | 18 ++++ bsnes/ui/tools/cheat-editor.cpp | 14 ++- bsnes/ui/tools/cheat-editor.hpp | 1 + bsnes/ui/tools/tools.cpp | 1 + bsnes/ui/tools/tools.hpp | 1 + bsnes/ui/utility/utility.cpp | 30 +++++-- bsnes/ui/utility/utility.hpp | 1 + 25 files changed, 313 insertions(+), 69 deletions(-) create mode 100755 bsnes/ui/tools/cheat-database.cpp create mode 100755 bsnes/ui/tools/cheat-database.hpp 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();