From 80c1c9c2ef62fe635d555d48f32af14a8a9861fb Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sat, 28 Feb 2015 12:51:53 +1100 Subject: [PATCH] Update to v094r10 release. byuu says: This starts the tomoko UI. So far I have basic library loading and video+audio output. Basically just enough to take the below screenshot. (aside from Library, the menus are empty stubs.) The .sys (system) game folders are now going under ~/Emulation/System, to avoid needing root privileges to stick them into /usr/share. The game library now shows all bootable media types, and the drop-down subtype is gone. I'm going to display a separate modal dialog for loading slotted games this time around. Much cleaner this way, less clutter. tomoko's starting off a lot cleaner than ethos was, and I'm scaling back the number of abstracted classes. What was Utility, Interface, etc are now being merged all into Program. Of course, the real hell is the input system. That has so many layers of bullshit that there's really no sane way to write it. --- GNUmakefile | 2 +- emulator/emulator.hpp | 2 +- out/.gitignore | 1 + target-higan/higan.cpp | 25 ------ {target-higan => target-tomoko}/GNUmakefile | 31 +++++-- target-tomoko/library/browser.cpp | 35 ++++++++ target-tomoko/library/library.cpp | 3 + target-tomoko/library/library.hpp | 21 +++++ target-tomoko/library/manager.cpp | 29 +++++++ target-tomoko/presentation/presentation.cpp | 33 ++++++++ target-tomoko/presentation/presentation.hpp | 17 ++++ target-tomoko/program/interface.cpp | 78 ++++++++++++++++++ target-tomoko/program/media.cpp | 25 ++++++ target-tomoko/program/program.cpp | 80 +++++++++++++++++++ target-tomoko/program/program.hpp | 32 ++++++++ target-tomoko/tomoko.cpp | 8 ++ .../higan.hpp => target-tomoko/tomoko.hpp | 4 + 17 files changed, 393 insertions(+), 33 deletions(-) delete mode 100644 target-higan/higan.cpp rename {target-higan => target-tomoko}/GNUmakefile (52%) create mode 100644 target-tomoko/library/browser.cpp create mode 100644 target-tomoko/library/library.cpp create mode 100644 target-tomoko/library/library.hpp create mode 100644 target-tomoko/library/manager.cpp create mode 100644 target-tomoko/presentation/presentation.cpp create mode 100644 target-tomoko/presentation/presentation.hpp create mode 100644 target-tomoko/program/interface.cpp create mode 100644 target-tomoko/program/media.cpp create mode 100644 target-tomoko/program/program.cpp create mode 100644 target-tomoko/program/program.hpp create mode 100644 target-tomoko/tomoko.cpp rename target-higan/higan.hpp => target-tomoko/tomoko.hpp (62%) diff --git a/GNUmakefile b/GNUmakefile index 616430e8..55721904 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,7 +6,7 @@ gb := gb gba := gba profile := accuracy -target := higan +target := tomoko # arch := x86 # console := true diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index efa5b2b4..2582fcda 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.09"; + static const char Version[] = "094.10"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/out/.gitignore b/out/.gitignore index 98f54497..827a1ea8 100644 --- a/out/.gitignore +++ b/out/.gitignore @@ -1 +1,2 @@ higan +tomoko diff --git a/target-higan/higan.cpp b/target-higan/higan.cpp deleted file mode 100644 index ee967a88..00000000 --- a/target-higan/higan.cpp +++ /dev/null @@ -1,25 +0,0 @@ -#include "higan.hpp" - -struct Presentation : Window { - MenuBar menuBar{this}; - Menu menuSystem{&menuBar}; - StatusBar statusBar{this}; - - Presentation() { - menuSystem.setText("System"); - onClose(&Application::quit); - - setBackgroundColor({0, 0, 0}); - setTitle({Emulator::Name, " v", Emulator::Version}); - setSize({640, 480}); - setCentered(); - setVisible(); - } -}; - -#include -auto nall::main(lstring args) -> void { - Application::setName("higan"); - new Presentation; - Application::run(); -} diff --git a/target-higan/GNUmakefile b/target-tomoko/GNUmakefile similarity index 52% rename from target-higan/GNUmakefile rename to target-tomoko/GNUmakefile index 2f741edc..48bdf8ff 100644 --- a/target-higan/GNUmakefile +++ b/target-tomoko/GNUmakefile @@ -1,13 +1,15 @@ -name := higan +name := tomoko processors := arm gsu hg51b lr35902 r6502 r65816 spc700 upd96050 include processor/GNUmakefile + include fc/GNUmakefile include sfc/GNUmakefile include gb/GNUmakefile include gba/GNUmakefile -ui_objects := ui-higan +ui_objects := ui-tomoko ui-program +ui_objects += ui-library ui-presentation ui_objects += ruby hiro # platform @@ -38,16 +40,33 @@ obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/) obj/hiro.o: hiro/hiro.cpp $(call rwildcard,hiro/) $(compiler) $(hiroflags) -c $< -o $@ -obj/ui-higan.o: $(ui)/higan.cpp $(call rwildcard,$(ui)/) +obj/ui-tomoko.o: $(ui)/tomoko.cpp $(call rwildcard,$(ui)/) +obj/ui-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/) +obj/ui-library.o: $(ui)/library/library.cpp $(call rwildcard,$(ui)/) +obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/) -# build +# targets build: $(objects) $(strip $(compiler) -o out/$(name) $(objects) $(link)) install: +ifeq ($(shell id -un),root) + $(error "make install should not be run as root") +else ifeq ($(platform),windows) +else ifeq ($(platform),macosx) +else cp out/$(name) $(prefix)/bin/$(name) - cp data/higan.png $(prefix)/share/icons/higan.png + cp data/higan.png $(prefix)/share/icons/$(name).png + mkdir -p ~/Emulation/System/ + cp -R profile/* ~/Emulation/System/ +endif uninstall: +ifeq ($(shell id -un),root) + $(error "make uninstall should not be run as root") +else ifeq ($(platform),windows) +else ifeq ($(platform),macosx) +else if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi - if [ -f $(prefix)/share/icons/higan.png ]; then rm $(prefix)/share/icons/higan.png + if [ -f $(prefix)/share/icons/$(name).png ]; then rm $(prefix)/share/icons/$(name).png; fi +endif diff --git a/target-tomoko/library/browser.cpp b/target-tomoko/library/browser.cpp new file mode 100644 index 00000000..f994f5c7 --- /dev/null +++ b/target-tomoko/library/browser.cpp @@ -0,0 +1,35 @@ +LibraryBrowser::LibraryBrowser(TabFrame& parent, Emulator::Interface::Media& media) : TabFrameItem{&parent} { + this->media = media; + setText(media.name); + layout.setMargin(5); + gameList.onActivate([&] { + libraryManager->setVisible(false); + program->loadMedia({userpath(), "Emulation/", this->media.name, "/", gameList.selected()->text(), ".", this->media.type, "/"}); + }); +} + +auto LibraryBrowser::reload() -> void { + string path = {userpath(), "Emulation/", media.name}; + directory::create(path); + + gameList.reset(); + gameList.append(ListViewColumn()); + bool first = true; + auto folders = directory::folders(path, {"*.", media.type}); + for(auto& folder : folders) { + ListViewItem item; + item.setIcon(0, Icon::Emblem::Program); + item.setText(folder.rtrim({".", media.type, "/"})); + gameList.append(item); + if(first) { + first = false; + item.setFocused(); + } + } +} + +auto LibraryBrowser::select() -> void { + reload(); + setSelected(); + gameList.setFocused(); +} diff --git a/target-tomoko/library/library.cpp b/target-tomoko/library/library.cpp new file mode 100644 index 00000000..508041eb --- /dev/null +++ b/target-tomoko/library/library.cpp @@ -0,0 +1,3 @@ +#include "../tomoko.hpp" +#include "browser.cpp" +#include "manager.cpp" diff --git a/target-tomoko/library/library.hpp b/target-tomoko/library/library.hpp new file mode 100644 index 00000000..c79383c6 --- /dev/null +++ b/target-tomoko/library/library.hpp @@ -0,0 +1,21 @@ +struct LibraryBrowser : TabFrameItem { + LibraryBrowser(TabFrame& parent, Emulator::Interface::Media& media); + auto reload() -> void; + auto select() -> void; + + Emulator::Interface::Media media; + + VerticalLayout layout{this}; + ListView gameList{&layout, Size{~0, ~0}}; +}; + +struct LibraryManager : Window { + LibraryManager(); + auto show(const string& type) -> void; + + VerticalLayout layout{this}; + TabFrame libraryFrame{&layout, Size{~0, ~0}}; + vector libraryBrowsers; +}; + +extern LibraryManager* libraryManager; diff --git a/target-tomoko/library/manager.cpp b/target-tomoko/library/manager.cpp new file mode 100644 index 00000000..731469a7 --- /dev/null +++ b/target-tomoko/library/manager.cpp @@ -0,0 +1,29 @@ +LibraryManager* libraryManager = nullptr; + +LibraryManager::LibraryManager() { + libraryManager = this; + + layout.setMargin(5); + + for(auto& emulator : program->emulators) { + for(auto& media : emulator->media) { + if(media.bootable == false) continue; + auto browser = new LibraryBrowser(libraryFrame, media); + libraryBrowsers.append(browser); + } + } + + setTitle("Library"); + setSize({640, 800}); + setPosition({0, 0}); +} + +auto LibraryManager::show(const string& type) -> void { + for(auto& browser : libraryBrowsers) { + if(type != browser->media.type) continue; + browser->select(); + } + + setVisible(); + setFocused(); +} diff --git a/target-tomoko/presentation/presentation.cpp b/target-tomoko/presentation/presentation.cpp new file mode 100644 index 00000000..a5b172d6 --- /dev/null +++ b/target-tomoko/presentation/presentation.cpp @@ -0,0 +1,33 @@ +#include "../tomoko.hpp" +Presentation* presentation = nullptr; + +Presentation::Presentation() { + presentation = this; + + libraryMenu.setText("Library"); + for(auto& emulator : program->emulators) { + for(auto& media : emulator->media) { + if(media.bootable == false) continue; + auto item = new MenuItem{&libraryMenu}; + item->setText({media.name, " ..."}).onActivate([=] { + libraryManager->show(media.type); + }); + loadBootableMedia.append(item); + } + } + + superFamicomMenu.setText("Super Famicom"); + + settingsMenu.setText("Settings"); + + toolsMenu.setText("Tools"); + + statusBar.setFont(Font::sans(8, "Bold")); + + onClose(&Application::quit); + + setTitle({"tomoko v", Emulator::Version}); + setResizable(false); + setSize({640, 480}); + setCentered(); +} diff --git a/target-tomoko/presentation/presentation.hpp b/target-tomoko/presentation/presentation.hpp new file mode 100644 index 00000000..dfccbf18 --- /dev/null +++ b/target-tomoko/presentation/presentation.hpp @@ -0,0 +1,17 @@ +struct Presentation : Window { + Presentation(); + + MenuBar menuBar{this}; + Menu libraryMenu{&menuBar}; + vector loadBootableMedia; + Menu superFamicomMenu{&menuBar}; + Menu settingsMenu{&menuBar}; + Menu toolsMenu{&menuBar}; + + VerticalLayout layout{this}; + Viewport viewport{&layout, Size{~0, ~0}}; + + StatusBar statusBar{this}; +}; + +extern Presentation* presentation; diff --git a/target-tomoko/program/interface.cpp b/target-tomoko/program/interface.cpp new file mode 100644 index 00000000..8fa24a62 --- /dev/null +++ b/target-tomoko/program/interface.cpp @@ -0,0 +1,78 @@ +//request from emulation core to load non-volatile media folder +auto Program::loadRequest(unsigned id, string name, string type) -> void { +} + +//request from emulation core to load non-volatile media file +auto Program::loadRequest(unsigned id, string path) -> void { + string location = {mediaPaths(emulator().group(id)), path}; + if(!file::exists(location)) return; + mmapstream stream{location}; + return emulator().load(id, stream); +} + +auto Program::saveRequest(unsigned id, string path) -> void { +} + +auto Program::videoColor(unsigned source, uint16 alpha, uint16 red, uint16 green, uint16 blue) -> uint32 { + alpha >>= 8; + red >>= 8; + green >>= 8; + blue >>= 8; + return alpha << 24 | red << 16 | green << 8 | blue << 0; +} + +auto Program::videoRefresh(const uint32* palette, const uint32* data, unsigned pitch, unsigned width, unsigned height) -> void { + uint32* output; + unsigned length; + + if(video.lock(output, length, width, height)) { + pitch >>= 2, length >>= 2; + + for(auto y : range(height)) { + const uint32* sp = data + y * pitch; + uint32* dp = output + y * length; + for(auto x : range(width)) { + *dp++ = palette[*sp++]; + } + } + + video.unlock(); + video.refresh(); + } + + static unsigned frameCounter = 0; + static time_t previous, current; + frameCounter++; + + time(¤t); + if(current != previous) { + previous = current; + presentation->statusBar.setText({"FPS: ", frameCounter}); + frameCounter = 0; + } +} + +auto Program::audioSample(int16 lsample, int16 rsample) -> void { + signed samples[] = {lsample, rsample}; + dsp.sample(samples); + while(dsp.pending()) { + dsp.read(samples); + audio.sample(samples[0], samples[1]); + } +} + +auto Program::inputPoll(unsigned port, unsigned device, unsigned input) -> int16 { +} + +auto Program::inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void { +} + +auto Program::dipSettings(const Markup::Node& node) -> unsigned { +} + +auto Program::path(unsigned group) -> string { + return mediaPaths(group); +} + +auto Program::notify(string text) -> void { +} diff --git a/target-tomoko/program/media.cpp b/target-tomoko/program/media.cpp new file mode 100644 index 00000000..1c83370d --- /dev/null +++ b/target-tomoko/program/media.cpp @@ -0,0 +1,25 @@ +auto Program::loadMedia(string location) -> void { + location.transform("\\", "/"); + if(!directory::exists(location)) return; + + string type = suffixname(location).ltrim("."); + for(auto& emulator : emulators) { + for(auto& media : emulator->media) { + if(media.bootable == false) continue; + if(media.type != type) continue; + return loadMedia(*emulator, media, location); + } + } +} + +auto Program::loadMedia(Emulator::Interface& _emulator, Emulator::Interface::Media& media, const string& location) -> void { + mediaPaths(0) = {userpath(), "Emulation/System/", media.name, ".sys/"}; + mediaPaths(media.id) = location; + + setEmulator(_emulator); + emulator().paletteUpdate(Emulator::Interface::PaletteMode::Standard); + emulator().load(media.id); + emulator().power(); + + presentation->setTitle(emulator().title()); +} diff --git a/target-tomoko/program/program.cpp b/target-tomoko/program/program.cpp new file mode 100644 index 00000000..6a6d38e6 --- /dev/null +++ b/target-tomoko/program/program.cpp @@ -0,0 +1,80 @@ +#include "../tomoko.hpp" +#include +#include +#include +#include +#include "interface.cpp" +#include "media.cpp" +Program* program = nullptr; + +Program::Program() { + program = this; + Application::onMain({&Program::main, this}); + + emulators.append(new Famicom::Interface); + emulators.append(new SuperFamicom::Interface); + emulators.append(new GameBoy::Interface); + emulators.append(new GameBoyAdvance::Interface); + for(auto& emulator : emulators) emulator->bind = this; + + new LibraryManager; + new Presentation; + + presentation->setVisible(); + + video.driver("XShm"); + video.set(Video::Handle, presentation->viewport.handle()); + video.set(Video::Synchronize, false); + if(!video.init()) { video.driver("None"); video.init(); } + + audio.driver("OpenAL"); + audio.set(Audio::Handle, presentation->viewport.handle()); + audio.set(Audio::Synchronize, false); + audio.set(Audio::Frequency, 96000u); + audio.set(Audio::Latency, 80u); + if(!audio.init()) { audio.driver("None"); audio.init(); } + + input.driver("XInput"); + input.set(Input::Handle, presentation->viewport.handle()); + if(!input.init()) { input.driver("None"); input.init(); } + + dsp.setPrecision(16); + dsp.setBalance(0.0); + dsp.setVolume(1.0); + dsp.setFrequency(32040); + dsp.setResampler(DSP::ResampleEngine::Sinc); + dsp.setResamplerFrequency(96000); + + uint32* output; + unsigned length; + if(video.lock(output, length, 640, 480)) { + for(auto y : range(480)) { + uint32* dp = output + y * (length >> 2); + for(auto x : range(640)) { + *dp++ = 0xff401010; + } + } + + video.unlock(); + video.refresh(); + } +} + +auto Program::emulator() -> Emulator::Interface& { + if(activeEmulator == nullptr) throw; + return *activeEmulator; +} + +auto Program::main() -> void { + if(activeEmulator == nullptr || emulator().loaded() == false) { + audio.clear(); + usleep(20 * 1000); + return; + } + + emulator().run(); +} + +auto Program::setEmulator(Emulator::Interface& emulator) -> void { + activeEmulator = &emulator; +} diff --git a/target-tomoko/program/program.hpp b/target-tomoko/program/program.hpp new file mode 100644 index 00000000..d3706073 --- /dev/null +++ b/target-tomoko/program/program.hpp @@ -0,0 +1,32 @@ +struct Program : Emulator::Interface::Bind { + //program.cpp + Program(); + auto emulator() -> Emulator::Interface&; + auto main() -> void; + auto setEmulator(Emulator::Interface&) -> void; + + //interface.cpp + auto loadRequest(unsigned id, string name, string type) -> void override; + auto loadRequest(unsigned id, string path) -> void override; + auto saveRequest(unsigned id, string path) -> void override; + auto videoColor(unsigned source, uint16 alpha, uint16 red, uint16 green, uint16 blue) -> uint32 override; + auto videoRefresh(const uint32* palette, const uint32* data, unsigned pitch, unsigned width, unsigned height) -> void override; + auto audioSample(int16 lsample, int16 rsample) -> void override; + auto inputPoll(unsigned port, unsigned device, unsigned input) -> int16 override; + auto inputRumble(unsigned port, unsigned device, unsigned input, bool enable) -> void override; + auto dipSettings(const Markup::Node& node) -> unsigned override; + auto path(unsigned group) -> string override; + auto notify(string text) -> void override; + + //media.cpp + auto loadMedia(string location) -> void; + auto loadMedia(Emulator::Interface& interface, Emulator::Interface::Media& media, const string& location) -> void; + + DSP dsp; + + vector emulators; + Emulator::Interface* activeEmulator = nullptr; + vector mediaPaths; +}; + +extern Program* program; diff --git a/target-tomoko/tomoko.cpp b/target-tomoko/tomoko.cpp new file mode 100644 index 00000000..4e822626 --- /dev/null +++ b/target-tomoko/tomoko.cpp @@ -0,0 +1,8 @@ +#include "tomoko.hpp" + +#include +auto nall::main(lstring args) -> void { + Application::setName("tomoko"); + new Program; + Application::run(); +} diff --git a/target-higan/higan.hpp b/target-tomoko/tomoko.hpp similarity index 62% rename from target-higan/higan.hpp rename to target-tomoko/tomoko.hpp index 97b63a1f..ad45ac1e 100644 --- a/target-higan/higan.hpp +++ b/target-tomoko/tomoko.hpp @@ -6,3 +6,7 @@ using namespace nall; using namespace ruby; using namespace hiro; + +#include "program/program.hpp" +#include "library/library.hpp" +#include "presentation/presentation.hpp"