Update to v106r26 release.

byuu says:

Changelog:

  - nall: added -static-libgcc -static-libstdc++ to Windows/GCC link
    flags
  - bsnes, higan: added program icons to main window when game isn't
    loaded
  - bsnes: improved recent games menu sorting
  - bsnes: fixed multi-game recent game loading on Windows
  - bsnes: completed path override support
  - bsnes, higan: added screensaver suppression on Windows
  - icarus: add 32K volatile RAM to SuperFX boards that report no RAM
    (fixes Starfox)
  - bsnes, higan: added automatic dependency generation [Talarubi]
  - hiro/GTK: appending actions to menus restores enabled() state
  - higan: use board node inside manifest.bml if it exists
  - bsnes: added blur emulation and color emulation options to view menu
  - ruby: upgraded input.sdl to SDL 2.0 (though it makes no functional
    difference sadly)
  - ruby: removed video.sdl (due to deprecating SDL 1.2)
  - nall, ruby: improvements to HID class (generic vendor and product
    IDs)

Errata:

  - bsnes, higan: on Windows, Application::Windows::onScreenSaver needs
    `[&]` lambda capture, not `[]`
      - find it in presentation/presentation.cpp
This commit is contained in:
Tim Allen 2018-05-24 12:14:17 +10:00
parent 3353efd3a1
commit 5961ea9c03
80 changed files with 745 additions and 519 deletions

View File

@ -39,9 +39,9 @@ endif
compile = \
$(strip \
$(if $(filter %.c,$<), \
$(compiler) $(cflags) $(flags) $1 -c $< -o $@, \
$(compiler) $(cflags) $(flags) $1 -c $< -o $@ -MMD -MP -MF $(@:.o=.d), \
$(if $(filter %.cpp,$<), \
$(compiler) $(cppflags) $(flags) $1 -c $< -o $@ \
$(compiler) $(cppflags) $(flags) $1 -c $< -o $@ -MMD -MP -MF $(@:.o=.d) \
) \
) \
)
@ -50,14 +50,15 @@ compile = \
all: build;
obj/libco.o: ../libco/libco.c $(call rwildcard,../libco)
obj/emulator.o: emulator/emulator.cpp $(call rwildcard,emulator)
obj/audio.o: audio/audio.cpp $(call rwildcard,audio)
obj/video.o: video/video.cpp $(call rwildcard,video)
obj/resource.o: resource/resource.cpp $(call rwildcard,resource)
obj/libco.o: ../libco/libco.c
obj/emulator.o: emulator/emulator.cpp
obj/audio.o: audio/audio.cpp
obj/video.o: video/video.cpp
obj/resource.o: resource/resource.cpp
ui := target-$(target)
include $(ui)/GNUmakefile
-include obj/*.d
clean:
$(call rm,out/*)

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "106.25";
static const string Version = "106.26";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -3,11 +3,11 @@ processors += mos6502
objects += fc-interface fc-system fc-controller
objects += fc-memory fc-cartridge fc-cpu fc-apu fc-ppu
obj/fc-interface.o: fc/interface/interface.cpp $(call rwildcard,fc/interface/)
obj/fc-system.o: fc/system/system.cpp $(call rwildcard,fc/system/)
obj/fc-controller.o: fc/controller/controller.cpp $(call rwildcard,fc/controller/)
obj/fc-memory.o: fc/memory/memory.cpp $(call rwildcard,fc/memory/)
obj/fc-cartridge.o: fc/cartridge/cartridge.cpp $(call rwildcard,fc/cartridge/)
obj/fc-cpu.o: fc/cpu/cpu.cpp $(call rwildcard,fc/cpu/)
obj/fc-apu.o: fc/apu/apu.cpp $(call rwildcard,fc/apu/)
obj/fc-ppu.o: fc/ppu/ppu.cpp $(call rwildcard,fc/ppu/)
obj/fc-interface.o: fc/interface/interface.cpp
obj/fc-system.o: fc/system/system.cpp
obj/fc-controller.o: fc/controller/controller.cpp
obj/fc-memory.o: fc/memory/memory.cpp
obj/fc-cartridge.o: fc/cartridge/cartridge.cpp
obj/fc-cpu.o: fc/cpu/cpu.cpp
obj/fc-apu.o: fc/apu/apu.cpp
obj/fc-ppu.o: fc/ppu/ppu.cpp

View File

@ -4,10 +4,10 @@ objects += gb-interface gb-system
objects += gb-memory gb-cartridge
objects += gb-cpu gb-ppu gb-apu
obj/gb-interface.o: gb/interface/interface.cpp $(call rwildcard,gb/interface/)
obj/gb-system.o: gb/system/system.cpp $(call rwildcard,gb/system/)
obj/gb-cartridge.o: gb/cartridge/cartridge.cpp $(call rwildcard,gb/cartridge/)
obj/gb-memory.o: gb/memory/memory.cpp $(call rwildcard,gb/memory/)
obj/gb-cpu.o: gb/cpu/cpu.cpp $(call rwildcard,gb/cpu/)
obj/gb-ppu.o: gb/ppu/ppu.cpp $(call rwildcard,gb/ppu/)
obj/gb-apu.o: gb/apu/apu.cpp $(call rwildcard,gb/apu/)
obj/gb-interface.o: gb/interface/interface.cpp
obj/gb-system.o: gb/system/system.cpp
obj/gb-cartridge.o: gb/cartridge/cartridge.cpp
obj/gb-memory.o: gb/memory/memory.cpp
obj/gb-cpu.o: gb/cpu/cpu.cpp
obj/gb-ppu.o: gb/ppu/ppu.cpp
obj/gb-apu.o: gb/apu/apu.cpp

View File

@ -4,11 +4,11 @@ objects += gba-memory gba-interface gba-system
objects += gba-cartridge gba-player
objects += gba-cpu gba-ppu gba-apu
obj/gba-memory.o: gba/memory/memory.cpp $(call rwildcard,gba/memory)
obj/gba-interface.o: gba/interface/interface.cpp $(call rwildcard,gba/interface)
obj/gba-system.o: gba/system/system.cpp $(call rwildcard,gba/system)
obj/gba-cartridge.o: gba/cartridge/cartridge.cpp $(call rwildcard,gba/cartridge)
obj/gba-player.o: gba/player/player.cpp $(call rwildcard,gba/player)
obj/gba-cpu.o: gba/cpu/cpu.cpp $(call rwildcard,gba/cpu)
obj/gba-ppu.o: gba/ppu/ppu.cpp $(call rwildcard,gba/ppu)
obj/gba-apu.o: gba/apu/apu.cpp $(call rwildcard,gba/apu)
obj/gba-memory.o: gba/memory/memory.cpp
obj/gba-interface.o: gba/interface/interface.cpp
obj/gba-system.o: gba/system/system.cpp
obj/gba-cartridge.o: gba/cartridge/cartridge.cpp
obj/gba-player.o: gba/player/player.cpp
obj/gba-cpu.o: gba/cpu/cpu.cpp
obj/gba-ppu.o: gba/ppu/ppu.cpp
obj/gba-apu.o: gba/apu/apu.cpp

View File

@ -5,12 +5,12 @@ objects += md-cpu md-apu md-vdp md-psg md-ym2612
objects += md-system md-cartridge
objects += md-controller
obj/md-interface.o: md/interface/interface.cpp $(call rwildcard,md/interface)
obj/md-cpu.o: md/cpu/cpu.cpp $(call rwildcard,md/cpu)
obj/md-apu.o: md/apu/apu.cpp $(call rwildcard,md/apu)
obj/md-vdp.o: md/vdp/vdp.cpp $(call rwildcard,md/vdp)
obj/md-psg.o: md/psg/psg.cpp $(call rwildcard,md/psg)
obj/md-ym2612.o: md/ym2612/ym2612.cpp $(call rwildcard,md/ym2612)
obj/md-system.o: md/system/system.cpp $(call rwildcard,md/system)
obj/md-cartridge.o: md/cartridge/cartridge.cpp $(call rwildcard,md/cartridge)
obj/md-controller.o: md/controller/controller.cpp $(call rwildcard,md/controller)
obj/md-interface.o: md/interface/interface.cpp
obj/md-cpu.o: md/cpu/cpu.cpp
obj/md-apu.o: md/apu/apu.cpp
obj/md-vdp.o: md/vdp/vdp.cpp
obj/md-psg.o: md/psg/psg.cpp
obj/md-ym2612.o: md/ym2612/ym2612.cpp
obj/md-system.o: md/system/system.cpp
obj/md-cartridge.o: md/cartridge/cartridge.cpp
obj/md-controller.o: md/controller/controller.cpp

View File

@ -5,10 +5,10 @@ objects += ms-cpu ms-vdp ms-psg
objects += ms-system ms-cartridge
objects += ms-controller
obj/ms-interface.o: ms/interface/interface.cpp $(call rwildcard,ms/interface)
obj/ms-cpu.o: ms/cpu/cpu.cpp $(call rwildcard,ms/cpu)
obj/ms-vdp.o: ms/vdp/vdp.cpp $(call rwildcard,ms/vdp)
obj/ms-psg.o: ms/psg/psg.cpp $(call rwildcard,ms/psg)
obj/ms-system.o: ms/system/system.cpp $(call rwildcard,ms/system)
obj/ms-cartridge.o: ms/cartridge/cartridge.cpp $(call rwildcard,ms/cartridge)
obj/ms-controller.o: ms/controller/controller.cpp $(call rwildcard,ms/controller)
obj/ms-interface.o: ms/interface/interface.cpp
obj/ms-cpu.o: ms/cpu/cpu.cpp
obj/ms-vdp.o: ms/vdp/vdp.cpp
obj/ms-psg.o: ms/psg/psg.cpp
obj/ms-system.o: ms/system/system.cpp
obj/ms-cartridge.o: ms/cartridge/cartridge.cpp
obj/ms-controller.o: ms/controller/controller.cpp

View File

@ -5,12 +5,12 @@ objects += pce-cpu pce-vpc pce-vce pce-vdc pce-psg
objects += pce-system pce-cartridge
objects += pce-controller
obj/pce-interface.o: pce/interface/interface.cpp $(call rwildcard,pce/interface)
obj/pce-cpu.o: pce/cpu/cpu.cpp $(call rwildcard,pce/cpu)
obj/pce-vpc.o: pce/vpc/vpc.cpp $(call rwildcard,pce/vpc)
obj/pce-vce.o: pce/vce/vce.cpp $(call rwildcard,pce/vce)
obj/pce-vdc.o: pce/vdc/vdc.cpp $(call rwildcard,pce/vdc)
obj/pce-psg.o: pce/psg/psg.cpp $(call rwildcard,pce/psg)
obj/pce-system.o: pce/system/system.cpp $(call rwildcard,pce/system)
obj/pce-cartridge.o: pce/cartridge/cartridge.cpp $(call rwildcard,pce/cartridge)
obj/pce-controller.o: pce/controller/controller.cpp $(call rwildcard,pce/controller)
obj/pce-interface.o: pce/interface/interface.cpp
obj/pce-cpu.o: pce/cpu/cpu.cpp
obj/pce-vpc.o: pce/vpc/vpc.cpp
obj/pce-vce.o: pce/vce/vce.cpp
obj/pce-vdc.o: pce/vdc/vdc.cpp
obj/pce-psg.o: pce/psg/psg.cpp
obj/pce-system.o: pce/system/system.cpp
obj/pce-cartridge.o: pce/cartridge/cartridge.cpp
obj/pce-controller.o: pce/controller/controller.cpp

View File

@ -13,15 +13,15 @@ objects += $(if $(findstring v30mz,$(processors)),processor-v30mz)
objects += $(if $(findstring wdc65816,$(processors)),processor-wdc65816)
objects += $(if $(findstring z80,$(processors)),processor-z80)
obj/processor-arm7tdmi.o: processor/arm7tdmi/arm7tdmi.cpp $(call rwildcard,processor/arm7tdmi/)
obj/processor-gsu.o: processor/gsu/gsu.cpp $(call rwildcard,processor/gsu/)
obj/processor-hg51b.o: processor/hg51b/hg51b.cpp $(call rwildcard,processor/hg51b/)
obj/processor-huc6280.o: processor/huc6280/huc6280.cpp $(call rwildcard,processor/huc6280/)
obj/processor-lr35902.o: processor/lr35902/lr35902.cpp $(call rwildcard,processor/lr35902/)
obj/processor-m68k.o: processor/m68k/m68k.cpp $(call rwildcard,processor/m68k/)
obj/processor-mos6502.o: processor/mos6502/mos6502.cpp $(call rwildcard,processor/mos6502/)
obj/processor-spc700.o: processor/spc700/spc700.cpp $(call rwildcard,processor/spc700/)
obj/processor-upd96050.o: processor/upd96050/upd96050.cpp $(call rwildcard,processor/upd96050/)
obj/processor-v30mz.o: processor/v30mz/v30mz.cpp $(call rwildcard,processor/v30mz/)
obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp $(call rwildcard,processor/wdc65816/)
obj/processor-z80.o: processor/z80/z80.cpp $(call rwildcard,processor/z80/)
obj/processor-arm7tdmi.o: processor/arm7tdmi/arm7tdmi.cpp
obj/processor-gsu.o: processor/gsu/gsu.cpp
obj/processor-hg51b.o: processor/hg51b/hg51b.cpp
obj/processor-huc6280.o: processor/huc6280/huc6280.cpp
obj/processor-lr35902.o: processor/lr35902/lr35902.cpp
obj/processor-m68k.o: processor/m68k/m68k.cpp
obj/processor-mos6502.o: processor/mos6502/mos6502.cpp
obj/processor-spc700.o: processor/spc700/spc700.cpp
obj/processor-upd96050.o: processor/upd96050/upd96050.cpp
obj/processor-v30mz.o: processor/v30mz/v30mz.cpp
obj/processor-wdc65816.o: processor/wdc65816/wdc65816.cpp
obj/processor-z80.o: processor/z80/z80.cpp

View File

@ -12,41 +12,41 @@ objects += sfc-spc7110 sfc-sdd1
objects += sfc-obc1 sfc-msu1
objects += sfc-bsmemory sfc-sufamiturbo
obj/sfc-interface.o: sfc/interface/interface.cpp $(call rwildcard,sfc/interface)
obj/sfc-system.o: sfc/system/system.cpp $(call rwildcard,sfc/system/)
obj/sfc-controller.o: sfc/controller/controller.cpp $(call rwildcard,sfc/controller/)
obj/sfc-cartridge.o: sfc/cartridge/cartridge.cpp $(call rwildcard,sfc/cartridge/)
obj/sfc-memory.o: sfc/memory/memory.cpp $(call rwildcard,sfc/memory/)
obj/sfc-interface.o: sfc/interface/interface.cpp
obj/sfc-system.o: sfc/system/system.cpp
obj/sfc-controller.o: sfc/controller/controller.cpp
obj/sfc-cartridge.o: sfc/cartridge/cartridge.cpp
obj/sfc-memory.o: sfc/memory/memory.cpp
obj/sfc-cpu.o: sfc/cpu/cpu.cpp $(call rwildcard,sfc/cpu/)
obj/sfc-smp.o: sfc/smp/smp.cpp $(call rwildcard,sfc/smp/)
obj/sfc-dsp.o: sfc/dsp/dsp.cpp $(call rwildcard,sfc/dsp/)
obj/sfc-ppu.o: sfc/ppu/ppu.cpp $(call rwildcard,sfc/ppu/)
obj/sfc-cpu.o: sfc/cpu/cpu.cpp
obj/sfc-smp.o: sfc/smp/smp.cpp
obj/sfc-dsp.o: sfc/dsp/dsp.cpp
obj/sfc-ppu.o: sfc/ppu/ppu.cpp
obj/sfc-expansion.o: sfc/expansion/expansion.cpp $(call rwildcard,sfc/expansion/)
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansion/21fx/)
obj/sfc-expansion.o: sfc/expansion/expansion.cpp
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp
obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp
obj/sfc-icd.o: sfc/coprocessor/icd/icd.cpp $(call rwildcard,sfc/coprocessor/icd/)
obj/sfc-mcc.o: sfc/coprocessor/mcc/mcc.cpp $(call rwildcard,sfc/coprocessor/mcc/)
obj/sfc-dip.o: sfc/coprocessor/dip/dip.cpp $(call rwildcard,sfc/coprocessor/dip/)
obj/sfc-event.o: sfc/coprocessor/event/event.cpp $(call rwildcard,sfc/coprocessor/event/)
obj/sfc-icd.o: sfc/coprocessor/icd/icd.cpp
obj/sfc-mcc.o: sfc/coprocessor/mcc/mcc.cpp
obj/sfc-dip.o: sfc/coprocessor/dip/dip.cpp
obj/sfc-event.o: sfc/coprocessor/event/event.cpp
obj/sfc-sa1.o: sfc/coprocessor/sa1/sa1.cpp $(call rwildcard,sfc/coprocessor/sa1/)
obj/sfc-superfx.o: sfc/coprocessor/superfx/superfx.cpp $(call rwildcard,sfc/coprocessor/superfx/)
obj/sfc-sa1.o: sfc/coprocessor/sa1/sa1.cpp
obj/sfc-superfx.o: sfc/coprocessor/superfx/superfx.cpp
obj/sfc-armdsp.o: sfc/coprocessor/armdsp/armdsp.cpp $(call rwildcard,sfc/coprocessor/armdsp/)
obj/sfc-hitachidsp.o: sfc/coprocessor/hitachidsp/hitachidsp.cpp $(call rwildcard,sfc/coprocessor/hitachidsp/)
obj/sfc-necdsp.o: sfc/coprocessor/necdsp/necdsp.cpp $(call rwildcard,sfc/coprocessor/necdsp/)
obj/sfc-armdsp.o: sfc/coprocessor/armdsp/armdsp.cpp
obj/sfc-hitachidsp.o: sfc/coprocessor/hitachidsp/hitachidsp.cpp
obj/sfc-necdsp.o: sfc/coprocessor/necdsp/necdsp.cpp
obj/sfc-epsonrtc.o: sfc/coprocessor/epsonrtc/epsonrtc.cpp $(call rwildcard,sfc/coprocessor/epsonrtc/)
obj/sfc-sharprtc.o: sfc/coprocessor/sharprtc/sharprtc.cpp $(call rwildcard,sfc/coprocessor/sharprtc/)
obj/sfc-epsonrtc.o: sfc/coprocessor/epsonrtc/epsonrtc.cpp
obj/sfc-sharprtc.o: sfc/coprocessor/sharprtc/sharprtc.cpp
obj/sfc-spc7110.o: sfc/coprocessor/spc7110/spc7110.cpp $(call rwildcard,sfc/coprocessor/spc7110/)
obj/sfc-sdd1.o: sfc/coprocessor/sdd1/sdd1.cpp $(call rwildcard,sfc/coprocessor/sdd1/)
obj/sfc-obc1.o: sfc/coprocessor/obc1/obc1.cpp $(call rwildcard,sfc/coprocessor/obc1/)
obj/sfc-spc7110.o: sfc/coprocessor/spc7110/spc7110.cpp
obj/sfc-sdd1.o: sfc/coprocessor/sdd1/sdd1.cpp
obj/sfc-obc1.o: sfc/coprocessor/obc1/obc1.cpp
obj/sfc-msu1.o: sfc/coprocessor/msu1/msu1.cpp $(call rwildcard,sfc/coprocessor/msu1/)
obj/sfc-msu1.o: sfc/coprocessor/msu1/msu1.cpp
obj/sfc-bsmemory.o: sfc/slot/bsmemory/bsmemory.cpp $(call rwildcard,sfc/slot/bsmemory/)
obj/sfc-sufamiturbo.o: sfc/slot/sufamiturbo/sufamiturbo.cpp $(call rwildcard,sfc/slot/sufamiturbo/)
obj/sfc-bsmemory.o: sfc/slot/bsmemory/bsmemory.cpp
obj/sfc-sufamiturbo.o: sfc/slot/sufamiturbo/sufamiturbo.cpp

View File

@ -5,6 +5,7 @@ auto Cartridge::loadBoard(string board) -> Markup::Node {
if(board.beginsWith("MAXI-")) board.replace("MAXI-", "SHVC-", 1L);
if(board.beginsWith("MJSC-")) board.replace("MJSC-", "SHVC-", 1L);
if(board.beginsWith("EA-" )) board.replace("EA-", "SHVC-", 1L);
if(board.beginsWith("WEI-" )) board.replace("WEI-", "SHVC-", 1L);
if(auto fp = platform->open(ID::System, "boards.bml", File::Read, File::Required)) {
auto document = BML::unserialize(fp->reads());
@ -25,7 +26,8 @@ auto Cartridge::loadBoard(string board) -> Markup::Node {
}
auto Cartridge::loadCartridge(Markup::Node node) -> void {
board = loadBoard(game.board);
board = node["board"];
if(!board) board = loadBoard(game.board);
if(region() == "Auto") {
auto region = game.region;

View File

@ -19,11 +19,11 @@ else ifeq ($(platform),macos)
ruby += audio.openal
ruby += input.quartz input.carbon
else ifeq ($(platform),linux)
ruby += video.glx video.xvideo video.xshm video.sdl
ruby += video.glx video.xvideo video.xshm
ruby += audio.oss audio.alsa audio.openal audio.pulseaudio audio.pulseaudiosimple audio.ao
ruby += input.sdl input.xlib input.udev
else ifeq ($(platform),bsd)
ruby += video.glx video.xvideo video.xshm video.sdl
ruby += video.glx video.xvideo video.xshm
ruby += audio.oss audio.openal
ruby += input.sdl input.xlib
endif
@ -38,7 +38,7 @@ link += $(hirolink)
# rules
objects := $(ui_objects) $(objects)
objects := $(patsubst %,obj/%.o,$(objects))
objects := $(objects:%=obj/%.o)
obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/)
$(compiler) $(rubyflags) -c $< -o $@
@ -46,15 +46,15 @@ obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/)
obj/hiro.o: ../hiro/hiro.cpp $(call rwildcard,../hiro/)
$(compiler) $(hiroflags) -c $< -o $@
obj/ui-bsnes.o: $(ui)/bsnes.cpp $(call rwildcard,$(ui)/)
obj/ui-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/)
obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/)
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/)
obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/)
obj/ui-resource.o: $(ui)/resource/resource.cpp $(call rwildcard,$(ui)/)
obj/ui-bsnes.o: $(ui)/bsnes.cpp
obj/ui-program.o: $(ui)/program/program.cpp
obj/ui-input.o: $(ui)/input/input.cpp
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp
obj/ui-settings.o: $(ui)/settings/settings.cpp
obj/ui-resource.o: $(ui)/resource/resource.cpp
obj/ui-windows.o:
$(windres) data/bsnes.rc obj/ui-resource.o
$(windres) $(ui)/resource/bsnes.rc obj/ui-windows.o
# targets
build: $(objects)
@ -64,8 +64,8 @@ ifeq ($(platform),macos)
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
cp data/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
cp $(ui)/resource/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
endif
install:
@ -81,8 +81,8 @@ else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/share/icons/
mkdir -p $(prefix)/share/$(name)/
cp out/$(name) $(prefix)/bin/$(name)
cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp data/$(name).png $(prefix)/share/icons/$(name).png
cp $(ui)/resource/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp $(ui)/resource/$(name).png $(prefix)/share/icons/$(name).png
endif
uninstall:

View File

@ -78,6 +78,14 @@ Presentation::Presentation() {
settings["View/IntegralScaling"].setValue(integralScaling.checked());
resizeViewport();
});
blurEmulation.setText("Blur Emulation").setChecked(settings["View/BlurEmulation"].boolean()).onToggle([&] {
settings["View/BlurEmulation"].setValue(blurEmulation.checked());
emulator->set("Blur Emulation", blurEmulation.checked());
}).doToggle();
colorEmulation.setText("Color Emulation").setChecked(settings["View/ColorEmulation"].boolean()).onToggle([&] {
settings["View/ColorEmulation"].setValue(colorEmulation.checked());
emulator->set("Color Emulation", colorEmulation.checked());
}).doToggle();
shaderMenu.setText("Shader");
updateShaders();
muteAudio.setText("Mute Audio").setChecked(settings["Audio/Mute"].boolean()).onToggle([&] {
@ -86,6 +94,7 @@ Presentation::Presentation() {
showStatusBar.setText("Show Status Bar").setChecked(settings["UserInterface/ShowStatusBar"].boolean()).onToggle([&] {
settings["UserInterface/ShowStatusBar"].setValue(showStatusBar.checked());
statusBar.setVisible(showStatusBar.checked());
if(visible()) resizeWindow();
});
inputSettings.setText("Input ...").onActivate([&] { settingsWindow->show(0); });
hotkeySettings.setText("Hotkeys ...").onActivate([&] { settingsWindow->show(1); });
@ -113,6 +122,10 @@ Presentation::Presentation() {
aboutWindow->setCentered(*this).setVisible().setFocused();
});
image icon{Resource::Icon};
icon.alphaBlend(0xff000000);
canvas.setIcon(icon).setVisible(false);
viewport.setDroppable().onDrop([&](auto locations) {
program->gameQueue = locations;
program->load();
@ -139,6 +152,14 @@ Presentation::Presentation() {
Application::Windows::onModalChange([](bool modal) {
if(modal && audio) audio->clear();
});
Application::Windows::onScreenSaver([]() -> bool {
if(emulator->loaded()) {
if(pauseEmulation.checked()) return true;
if(!program->focused() && settingsWindow->input.pauseEmulation.checked()) return true;
return false;
}
return true;
});
#endif
#if defined(PLATFORM_MACOS)
@ -149,8 +170,24 @@ Presentation::Presentation() {
#endif
}
auto Presentation::showIcon() -> void {
Application::processEvents();
int width = geometry().width();
int height = geometry().height();
int x = width - 144;
int y = height - 128;
if(x >= 0 && y >= 0) {
canvas.setVisible(true).setGeometry({x, y, 128, 128});
} else {
canvas.setVisible(false);
}
viewport.setGeometry({0, 0, 1, 1});
}
auto Presentation::clearViewport() -> void {
if(!emulator->loaded()) showIcon();
if(!video) return;
uint32_t* output;
uint length;
uint width = viewport.geometry().width();
@ -166,6 +203,8 @@ auto Presentation::clearViewport() -> void {
}
auto Presentation::resizeViewport() -> void {
if(emulator->loaded()) canvas.setVisible(false);
uint windowWidth = geometry().width();
uint windowHeight = geometry().height();
@ -235,19 +274,19 @@ auto Presentation::updateRecentGames() -> void {
MenuItem item;
if(auto game = settings[string{"Game/Recent/", 1 + index}].text()) {
string displayName;
for(auto part : game.split(":")) {
auto games = game.split("|");
for(auto& part : games) {
displayName.append(Location::prefix(part), " + ");
}
displayName.trimRight(" + ", 1L);
item.setText(displayName).onActivate([=] {
program->gameQueue = game.split(":");
program->gameQueue = games;
program->load();
});
} else {
item.setText("<empty>").setEnabled(false);
}
loadRecentGame.append(item);
if(item.text() == "<empty>") item.setEnabled(false); //todo: temporary hack; fix hiro/GTK!!
}
loadRecentGame.append(MenuSeparator());
loadRecentGame.append(MenuItem().setText("Clear List").onActivate([&] {
@ -267,12 +306,21 @@ auto Presentation::addRecentGame(string location) -> void {
auto game4 = settings["Game/Recent/4"].text();
auto game5 = settings["Game/Recent/5"].text();
if(game1 == location);
else if(game2 == location) swap(game1, game2);
else if(game3 == location) swap(game1, game3);
else if(game4 == location) swap(game1, game4);
else if(game5 == location) swap(game1, game5);
else {
if(game1 == location) {
game1 = location;
} else if(game2 == location) {
game2 = game1;
game1 = location;
} else if(game3 == location) {
game3 = game2;
game2 = game1;
game1 = location;
} else if(game4 == location) {
game4 = game3;
game3 = game2;
game2 = game1;
game1 = location;
} else {
game5 = game4;
game4 = game3;
game3 = game2;

View File

@ -10,6 +10,7 @@ struct AboutWindow : Window {
struct Presentation : Window {
Presentation();
auto showIcon() -> void;
auto clearViewport() -> void;
auto resizeViewport() -> void;
auto resizeWindow() -> void;
@ -39,6 +40,8 @@ struct Presentation : Window {
MenuCheckItem aspectCorrection{&viewMenu};
MenuCheckItem overscanCropping{&viewMenu};
MenuCheckItem integralScaling{&viewMenu};
MenuCheckItem blurEmulation{&viewMenu};
MenuCheckItem colorEmulation{&viewMenu};
Menu shaderMenu{&settingsMenu};
MenuCheckItem muteAudio{&settingsMenu};
MenuCheckItem showStatusBar{&settingsMenu};
@ -64,6 +67,7 @@ struct Presentation : Window {
MenuItem about{&helpMenu};
FixedLayout layout{this};
Canvas canvas{&layout, Geometry{0, 0, 1, 1}};
Viewport viewport{&layout, Geometry{0, 0, 1, 1}};
StatusBar statusBar{this};

View File

@ -14,9 +14,10 @@ auto Program::load() -> void {
presentation->unloadGame.setEnabled(true);
presentation->saveState.setEnabled(true);
presentation->loadState.setEnabled(true);
presentation->resizeViewport();
string locations = superNintendo.location;
if(auto location = gameBoy.location) locations.append(":", location);
if(auto location = gameBoy.location) locations.append("|", location);
presentation->addRecentGame(locations);
}

View File

@ -119,38 +119,31 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
}
if(id == 1 && name == "save.ram") {
string location = {Location::notsuffix(superNintendo.location), ".srm"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".srm"), mode);
}
if(id == 1 && name == "download.ram") {
string location = {Location::notsuffix(superNintendo.location), ".psr"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".psr"), mode);
}
if(id == 1 && name == "time.rtc") {
string location = {Location::notsuffix(superNintendo.location), ".rtc"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".rtc"), mode);
}
if(id == 1 && name == "arm6.data.ram") {
string location = {Location::notsuffix(superNintendo.location), ".srm"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".srm"), mode);
}
if(id == 1 && name == "hg51bs169.data.ram") {
string location = {Location::notsuffix(superNintendo.location), ".srm"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".srm"), mode);
}
if(id == 1 && name == "upd7725.data.ram") {
string location = {Location::notsuffix(superNintendo.location), ".srm"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".srm"), mode);
}
if(id == 1 && name == "upd96050.data.ram") {
string location = {Location::notsuffix(superNintendo.location), ".srm"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", superNintendo.location, ".srm"), mode);
}
//Game Boy
@ -164,13 +157,11 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) ->
}
if(id == 2 && name == "save.ram") {
string location = {Location::path(gameBoy.location), Location::prefix(gameBoy.location), ".sav"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", gameBoy.location, ".sav"), mode);
}
if(id == 2 && name == "time.rtc") {
string location = {Location::path(gameBoy.location), Location::prefix(gameBoy.location), ".rtc"};
return vfs::fs::file::open(location, mode);
return vfs::fs::file::open(path("Saves", gameBoy.location, ".sav"), mode);
}
return {};
@ -183,7 +174,7 @@ auto Program::load(uint id, string name, string type, string_vector options) ->
} else {
BrowserDialog dialog;
dialog.setTitle("Load Super Nintendo");
dialog.setPath(settings["Path/Recent/SuperNintendo"].text());
dialog.setPath(path("Games", settings["Path/Recent/SuperNintendo"].text()));
dialog.setFilters({string{"Super Nintendo Games|*.sfc:*.smc:*.zip"}});
superNintendo.location = dialog.openFile();
}
@ -200,7 +191,7 @@ auto Program::load(uint id, string name, string type, string_vector options) ->
} else {
BrowserDialog dialog;
dialog.setTitle("Load Game Boy");
dialog.setPath(settings["Path/Recent/GameBoy"].text());
dialog.setPath(path("Games", settings["Path/Recent/GameBoy"].text()));
dialog.setFilters({string{"Game Boy Games|*.gb:*.gbc:*.zip"}});
gameBoy.location = dialog.openFile();
}

View File

@ -0,0 +1,42 @@
auto Program::path(string type, string location, string extension) -> string {
auto pathname = Location::path(location);
auto filename = Location::file(location);
auto prefix = Location::prefix(filename);
auto suffix = Location::suffix(filename);
if(type == "Games") {
if(auto path = settings["Path/Games"].text()) {
pathname = path;
}
}
if(type == "Patches") {
if(auto path = settings["Path/Patches"].text()) {
pathname = path;
}
}
if(type == "Saves") {
if(auto path = settings["Path/Saves"].text()) {
pathname = path;
}
}
if(type == "States") {
if(auto path = settings["Path/States"].text()) {
pathname = path;
}
}
if(type == "Cheats") {
if(auto path = settings["Path/Cheats"].text()) {
pathname = path;
}
}
if(extension) {
suffix = extension;
}
return {pathname, prefix, suffix};
}

View File

@ -1,6 +1,7 @@
#include "../bsnes.hpp"
#include "interface.cpp"
#include "game.cpp"
#include "paths.cpp"
#include "state.cpp"
#include "utility.cpp"
unique_pointer<Program> program;

View File

@ -20,6 +20,9 @@ struct Program : Emulator::Platform {
auto save() -> void;
auto unload() -> void;
//paths.cpp
auto path(string type, string location, string extension = "") -> string;
//state.cpp
auto loadState(uint slot) -> bool;
auto saveState(uint slot) -> bool;

View File

@ -1,6 +1,6 @@
auto Program::loadState(uint slot) -> bool {
if(!emulator->loaded()) return false;
string location = {Location::notsuffix(superNintendo.location), ".bs", slot};
auto location = path("States", superNintendo.location, {".bs", slot});
if(!file::exists(location)) return showMessage({"Slot ", slot, " state does not exist"}), false;
auto memory = file::read(location);
serializer s{memory.data(), memory.size()};
@ -10,7 +10,7 @@ auto Program::loadState(uint slot) -> bool {
auto Program::saveState(uint slot) -> bool {
if(!emulator->loaded()) return false;
string location = {Location::notsuffix(superNintendo.location), ".bs", slot};
auto location = path("States", superNintendo.location, {".bs", slot});
serializer s = emulator->serialize();
if(!s.size()) return showMessage({"Failed to save state to slot ", slot}), false;
if(!file::write(location, s.data(), s.size())) return showMessage({"Unable to write state to slot ", slot}), false;

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

View File

Before

Width:  |  Height:  |  Size: 954 B

After

Width:  |  Height:  |  Size: 954 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -1,5 +1,6 @@
namespace name=Resource
binary name=Logo file="logo.png"
binary name=Icon file=icon.png
binary name=Logo file=logo.png
namespace name=System
binary name=Manifest file="../../systems/Super Famicom.sys/manifest.bml"
binary name=Boards file="../../systems/Super Famicom.sys/boards.bml"

View File

@ -2,6 +2,117 @@
#include "resource.hpp"
namespace Resource {
const nall::vector<uint8_t> Icon = { //size: 3463
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,128,0,0,0,128,8,6,0,0,0,195,62,97,
203,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,32,99,72,82,77,0,0,122,38,0,0,128,
132,0,0,250,0,0,0,128,232,0,0,117,48,0,0,234,96,0,0,58,152,0,0,23,112,156,186,81,60,0,0,0,
9,112,72,89,115,0,0,0,90,0,0,0,90,0,112,35,184,125,0,0,0,6,98,75,71,68,0,0,0,0,0,0,
249,67,187,127,0,0,12,67,73,68,65,84,120,218,237,157,9,144,84,213,21,134,223,44,56,12,204,2,204,244,52,8,
34,171,36,65,217,75,16,152,133,145,17,45,64,194,162,144,136,90,98,130,82,166,64,4,37,130,5,21,41,147,88,24,
49,36,26,16,144,97,16,17,130,134,45,154,40,132,93,9,48,3,72,72,81,26,22,17,18,246,77,96,96,182,151,255,
188,62,221,211,52,211,51,189,188,215,253,222,235,115,170,190,26,138,101,166,125,255,127,207,61,247,222,243,174,138,34,33,
33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,
97,246,104,242,158,170,52,89,168,42,142,66,53,62,107,177,154,144,85,164,38,58,241,213,89,164,198,53,165,63,91,166,
202,67,178,75,56,22,67,204,71,84,5,66,39,131,246,96,32,152,8,102,131,34,176,18,124,12,62,4,243,192,12,240,
56,232,9,50,97,12,50,137,60,72,43,69,179,34,77,112,226,54,208,5,76,6,159,130,99,224,58,80,235,160,18,92,
0,123,192,159,192,143,129,35,3,223,215,81,36,102,48,239,104,127,223,35,124,125,80,0,150,130,147,160,42,0,209,107,
131,76,179,11,76,2,119,100,174,129,17,150,136,17,76,21,36,188,195,149,174,187,179,240,151,194,20,221,95,102,248,10,
60,3,210,179,10,85,197,41,70,136,110,164,46,244,140,250,52,30,161,223,25,32,188,47,55,192,106,208,45,107,129,235,
231,75,68,169,192,99,241,91,241,168,47,139,128,248,222,28,2,163,240,57,18,197,4,209,19,191,19,216,18,97,225,189,
185,160,173,42,10,81,112,22,138,9,34,51,223,87,87,249,93,184,56,83,163,204,21,240,75,94,117,136,64,70,70,163,
234,57,191,29,216,110,2,241,189,77,240,139,44,217,55,48,190,218,7,141,121,3,71,53,25,103,192,195,52,61,53,21,
19,24,147,250,29,69,218,8,155,14,42,76,104,0,98,31,184,75,178,128,206,225,172,46,250,242,192,41,147,138,239,102,
62,72,18,19,232,159,250,83,193,90,147,139,175,242,38,212,32,237,51,47,18,19,232,89,245,143,4,165,22,48,128,202,
103,15,105,146,5,244,27,253,41,224,111,22,17,159,184,10,134,208,103,207,144,44,160,139,1,238,7,151,45,100,0,98,
153,236,13,132,43,126,33,196,95,161,25,96,182,197,196,39,142,131,31,137,1,194,31,253,153,160,196,130,6,160,99,232,
177,244,223,224,148,109,226,176,12,208,199,160,227,221,72,80,36,187,131,33,198,237,11,60,213,255,56,139,138,175,114,230,
202,16,3,132,58,250,93,75,192,57,22,54,0,117,36,117,20,3,132,178,251,7,241,65,61,60,188,85,22,54,192,53,
94,193,136,160,97,172,255,183,90,216,0,21,188,129,37,130,134,104,128,70,96,3,56,15,46,242,78,96,165,197,86,2,
63,19,3,132,186,5,92,164,181,91,117,0,93,185,87,255,1,240,36,152,201,83,195,55,1,182,122,71,147,103,245,54,
128,218,173,219,45,196,76,100,98,77,221,121,149,167,239,191,37,24,204,47,117,28,49,97,118,160,12,240,116,168,6,80,
115,115,21,53,39,39,1,95,29,224,94,48,10,76,1,179,192,59,96,46,152,3,102,130,113,96,0,104,7,26,168,189,
123,211,191,141,153,76,145,192,111,254,76,5,7,117,120,23,64,207,26,96,68,48,6,32,209,64,28,68,108,14,126,10,
222,3,251,192,5,80,1,84,63,84,129,82,240,29,248,28,76,7,189,64,178,154,151,103,127,51,56,93,59,110,113,120,
216,109,193,44,112,214,36,173,98,185,129,24,64,27,237,121,121,36,252,15,192,171,224,95,160,172,22,193,3,225,28,88,
5,134,131,84,205,8,217,217,246,54,130,195,213,57,148,200,245,194,151,81,54,192,9,174,97,252,11,207,163,19,2,57,
193,52,112,152,71,179,170,35,215,192,58,144,15,18,201,108,246,63,68,114,109,34,221,9,150,128,242,40,25,96,7,175,
100,106,155,227,227,241,181,63,216,10,42,117,22,190,166,140,240,27,144,165,253,236,126,253,98,98,41,153,14,222,228,55,
122,34,109,128,185,14,63,111,15,177,248,201,248,58,1,156,50,88,120,111,200,100,127,7,157,200,0,182,159,18,52,19,
20,170,13,185,46,136,228,219,67,148,117,30,163,159,159,228,211,20,162,137,79,115,178,171,154,47,141,160,248,222,236,7,
185,252,89,98,34,19,80,79,225,187,17,92,33,208,171,99,109,124,71,63,63,240,20,48,91,135,34,47,92,190,214,76,
64,117,72,140,152,160,25,248,60,82,233,223,247,40,152,197,191,141,215,237,209,22,223,59,19,116,181,125,38,200,172,110,
45,239,197,151,69,24,253,206,96,222,77,226,243,18,12,15,249,41,112,197,36,226,187,89,15,154,197,68,22,104,50,95,
51,193,100,131,95,46,249,192,185,88,77,114,178,1,88,120,162,59,47,243,84,147,65,203,206,223,129,122,177,50,21,56,
12,60,101,60,197,93,76,138,99,161,234,59,239,175,52,161,248,110,46,130,129,182,159,10,188,222,51,24,109,192,210,144,
10,204,215,232,6,50,199,226,155,196,87,120,91,183,212,196,6,32,54,128,38,177,146,5,50,12,120,195,120,35,23,154,
190,133,31,61,212,205,38,23,159,184,1,158,176,125,22,160,110,35,190,100,98,146,206,203,190,94,238,86,54,159,185,127,
36,184,110,1,3,184,11,194,212,88,201,2,247,128,255,233,52,239,15,211,182,160,111,29,253,73,224,207,22,17,159,184,
12,238,15,207,0,37,96,23,40,86,226,65,10,104,1,186,128,2,48,18,140,3,147,193,203,224,21,48,21,188,4,198,
131,39,192,32,208,11,180,5,141,65,162,114,0,223,111,175,238,199,200,201,252,30,95,56,226,159,166,122,2,203,204,56,
71,205,155,62,29,193,9,11,25,64,213,118,40,251,247,15,242,137,238,246,8,238,4,185,96,2,88,4,54,131,255,128,
179,160,20,84,2,181,22,232,207,203,192,69,112,12,236,6,31,129,95,129,33,160,61,72,210,76,86,28,222,52,192,35,
118,70,24,226,83,19,202,8,136,31,127,139,248,125,251,186,13,240,180,1,167,123,70,179,3,100,214,253,20,139,53,226,
64,115,240,40,152,15,246,131,239,65,85,29,66,135,194,13,54,197,26,54,88,39,205,12,197,161,153,129,167,129,33,33,
156,17,84,113,1,217,167,241,59,46,35,213,120,216,147,155,75,231,251,243,45,38,62,113,6,244,174,75,248,122,160,7,
152,5,14,240,168,85,35,8,25,236,36,88,1,134,129,116,45,43,236,14,218,0,157,249,122,151,96,118,249,126,79,183,
134,146,240,254,174,143,101,3,164,129,47,44,104,128,114,240,108,205,194,151,104,105,158,230,243,121,224,84,132,69,247,7,
77,45,27,192,112,208,128,63,103,160,6,104,14,190,14,240,149,239,191,130,1,160,94,93,93,62,108,128,86,224,168,5,
13,64,188,229,59,191,43,92,144,77,225,52,172,154,144,171,224,3,112,143,242,239,186,167,5,175,75,167,118,213,146,234,
169,200,91,193,83,69,170,86,60,46,10,176,197,203,181,245,123,206,162,6,248,75,117,69,239,18,191,29,23,99,229,38,
21,223,155,131,96,40,23,165,117,25,32,197,235,178,73,234,42,254,158,215,244,235,192,139,218,149,176,69,174,59,127,110,
127,63,136,230,78,151,1,242,185,29,203,138,6,216,162,120,138,171,98,229,110,176,221,2,194,123,115,6,60,197,83,86,
109,6,160,246,242,49,124,217,35,253,191,2,178,185,221,60,169,225,50,85,113,134,211,210,237,106,240,124,19,188,13,10,
185,47,175,4,156,52,209,113,176,63,118,187,197,111,206,243,171,106,65,78,131,193,218,20,86,18,157,13,39,173,225,211,
213,112,17,135,95,83,47,64,6,239,13,60,66,243,44,216,99,210,51,130,93,244,208,18,241,0,223,176,168,248,110,74,
64,171,112,246,12,12,49,70,245,50,145,26,52,135,241,110,225,69,19,25,96,35,141,254,222,224,191,22,55,128,170,237,
52,6,185,68,140,152,17,184,29,11,212,7,5,96,181,73,206,13,150,147,1,94,183,129,248,42,215,47,233,102,203,2,
53,100,4,119,179,232,88,112,40,202,6,248,45,25,96,189,77,12,64,89,172,131,153,13,112,83,70,40,40,32,35,116,
3,159,69,105,27,153,50,208,227,100,128,93,54,49,192,89,222,188,178,68,120,101,131,102,188,122,168,136,176,1,232,240,
170,43,25,96,173,77,12,112,20,180,177,138,1,124,140,208,24,204,139,176,9,180,158,0,50,192,139,160,194,6,6,248,
4,36,91,205,0,62,29,69,75,35,104,128,87,92,253,0,197,202,93,124,208,99,101,241,203,180,13,161,98,115,174,2,
130,48,65,75,218,157,139,128,248,167,65,15,151,1,92,77,29,207,241,49,172,85,13,64,211,88,35,43,142,254,155,54,
147,92,38,200,6,199,13,54,192,135,220,197,228,217,6,78,225,147,191,74,11,138,255,21,232,28,106,191,128,233,178,0,
221,250,225,186,33,196,168,122,224,18,120,240,230,166,80,215,195,203,0,11,44,114,16,228,102,15,184,79,75,251,123,236,
209,199,200,194,56,248,85,114,35,12,176,132,55,164,106,108,0,73,3,211,121,73,101,102,225,201,164,171,65,71,59,140,
124,63,203,195,199,12,216,45,252,150,143,175,181,118,54,127,93,64,9,96,0,216,24,133,14,160,64,56,2,38,113,223,
130,173,196,175,97,85,176,77,231,247,1,198,215,253,62,192,14,78,167,174,41,97,44,216,6,174,71,89,116,170,77,14,
113,107,90,71,165,68,137,139,214,201,95,132,179,192,243,58,26,96,33,104,24,120,43,120,177,103,133,208,4,140,224,46,
156,227,17,46,20,47,131,77,224,5,173,83,152,206,253,117,22,94,85,53,226,64,3,224,4,237,65,15,208,15,12,4,
67,193,163,204,80,254,189,60,208,157,255,174,147,255,45,125,15,189,77,160,87,187,249,167,124,35,89,8,159,100,167,167,
99,136,26,68,127,8,198,128,37,92,125,95,210,185,51,248,58,239,232,209,166,206,52,144,173,29,240,108,215,231,172,159,
197,38,146,65,91,240,16,152,8,230,131,127,128,3,224,4,56,15,174,130,50,80,14,42,152,114,254,61,250,179,115,252,
119,233,223,108,0,243,192,4,240,0,104,13,234,187,127,94,24,6,160,98,109,173,14,59,126,109,245,121,21,108,167,103,
122,160,58,33,11,244,225,13,24,234,39,88,5,254,201,169,250,36,247,252,95,101,81,203,120,159,225,26,143,234,51,220,
115,184,23,124,198,173,230,19,193,67,188,157,91,95,217,167,187,232,233,160,47,152,6,62,1,223,130,235,64,213,153,82,
112,4,172,3,83,192,125,32,173,170,42,56,51,120,77,3,211,194,184,39,136,142,157,219,24,251,30,224,30,143,41,234,
241,102,76,11,206,20,61,65,30,191,41,244,32,23,150,249,108,26,234,245,111,13,50,53,177,75,180,247,14,140,72,237,
9,160,3,120,9,108,5,151,12,16,188,46,46,128,77,224,5,208,14,196,7,106,4,22,110,80,8,171,129,43,220,137,
228,208,190,71,126,190,18,51,193,194,211,67,238,4,102,131,163,160,42,10,194,251,82,9,14,129,89,160,99,32,53,3,
27,224,238,32,110,24,171,226,235,96,70,171,57,57,73,182,127,249,211,79,170,167,162,108,58,56,102,2,209,253,65,83,
196,203,192,81,91,157,224,117,92,124,48,0,225,143,81,131,7,104,173,245,26,196,194,29,194,53,84,242,125,57,221,86,
154,88,124,55,84,84,174,7,61,253,153,128,13,208,8,236,172,165,169,99,31,95,72,69,43,134,248,152,26,245,62,41,
127,148,201,71,189,63,14,131,225,53,77,9,94,215,206,108,246,154,219,233,162,232,77,224,13,240,48,104,170,221,63,156,
151,167,196,92,120,165,253,145,224,180,5,197,119,115,18,12,243,205,4,108,128,68,190,215,135,46,160,200,225,171,226,83,
212,236,236,184,152,74,243,181,136,127,47,207,169,170,197,249,6,116,13,103,239,32,22,13,208,16,124,100,3,241,221,44,
227,77,42,137,0,13,208,31,92,182,145,1,104,207,32,71,12,16,120,250,127,205,70,226,187,153,33,211,64,224,187,124,
43,109,104,128,165,193,236,22,198,178,1,18,193,26,27,26,96,37,155,91,34,128,41,96,174,13,13,48,71,166,128,192,
13,240,36,239,168,217,69,124,58,106,254,137,24,32,112,19,180,0,123,109,100,128,221,160,153,136,31,92,22,24,3,174,
217,64,252,43,96,180,140,254,224,77,64,27,39,111,89,124,42,168,224,99,226,36,17,63,52,19,52,230,150,172,114,139,
206,251,127,224,142,37,137,48,76,144,198,155,40,231,45,36,62,245,21,78,5,41,34,190,126,123,3,131,193,151,38,159,
18,232,179,109,227,166,212,68,17,95,255,194,176,41,152,204,29,187,149,38,19,126,63,120,30,100,73,193,103,172,17,168,
193,162,37,183,106,111,137,242,161,17,53,163,110,4,207,129,59,68,248,200,103,4,170,15,242,193,235,224,11,62,117,51,
178,81,180,146,107,17,74,243,191,230,23,73,82,69,120,115,100,133,70,220,135,247,12,88,0,54,115,67,201,229,16,235,
134,114,30,225,135,185,31,241,93,240,115,110,84,73,23,209,205,157,25,226,185,2,167,55,121,250,128,17,60,101,204,4,
111,131,37,96,57,248,152,89,206,191,247,71,240,42,24,207,253,124,189,193,157,220,160,18,39,130,219,203,32,9,92,169,
39,242,175,227,101,84,75,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,72,
72,72,72,72,72,72,72,152,54,254,15,126,72,246,126,174,120,107,6,0,0,0,37,116,69,88,116,100,97,116,101,58,
99,114,101,97,116,101,0,50,48,49,56,45,48,53,45,49,55,84,49,48,58,51,53,58,49,48,45,48,52,58,48,48,
240,186,255,164,0,0,0,37,116,69,88,116,100,97,116,101,58,109,111,100,105,102,121,0,50,48,49,56,45,48,53,45,
49,55,84,49,48,58,51,53,58,49,48,45,48,52,58,48,48,129,231,71,24,0,0,0,58,116,69,88,116,115,118,103,
58,98,97,115,101,45,117,114,105,0,102,105,108,101,58,47,47,47,99,111,114,101,47,102,105,108,101,115,47,109,101,100,
105,97,47,98,115,110,101,115,47,105,99,111,110,47,98,115,110,101,115,46,115,118,103,188,87,222,120,0,0,0,0,73,
69,78,68,174,66,96,130,
};
const nall::vector<uint8_t> Logo = { //size: 23165
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,144,0,0,0,86,8,6,0,0,0,225,121,192,
209,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,32,99,72,82,77,0,0,122,38,0,0,128,

View File

@ -1,4 +1,5 @@
namespace Resource {
extern const nall::vector<uint8_t> Icon;
extern const nall::vector<uint8_t> Logo;
namespace System {
extern const nall::vector<uint8_t> Manifest;

View File

@ -34,6 +34,8 @@ Settings::Settings() {
set("View/AspectCorrection", true);
set("View/OverscanCropping", true);
set("View/IntegralScaling", true);
set("View/BlurEmulation", true);
set("View/ColorEmulation", true);
set("Path/Games", "");
set("Path/Patches", "");

View File

@ -11,7 +11,7 @@ include gba/GNUmakefile
include ws/GNUmakefile
include processor/GNUmakefile
ui_objects := ui-higan ui-program ui-configuration ui-input
ui_objects := ui-higan ui-program ui-input
ui_objects += ui-settings ui-tools ui-presentation ui-resource
ui_objects += ruby hiro
ui_objects += $(if $(call streq,$(platform),windows),ui-windows)
@ -26,11 +26,11 @@ else ifeq ($(platform),macos)
ruby += audio.openal
ruby += input.quartz input.carbon
else ifeq ($(platform),linux)
ruby += video.glx video.xvideo video.xshm video.sdl
ruby += video.glx video.xvideo video.xshm
ruby += audio.oss audio.alsa audio.openal audio.pulseaudio audio.pulseaudiosimple audio.ao
ruby += input.sdl input.xlib input.udev
else ifeq ($(platform),bsd)
ruby += video.glx video.xvideo video.xshm video.sdl
ruby += video.glx video.xvideo video.xshm
ruby += audio.oss audio.openal
ruby += input.sdl input.xlib
endif
@ -45,7 +45,7 @@ link += $(hirolink)
# rules
objects := $(ui_objects) $(objects)
objects := $(patsubst %,obj/%.o,$(objects))
objects := $(objects:%=obj/%.o)
obj/ruby.o: ../ruby/ruby.cpp $(call rwildcard,../ruby/)
$(compiler) $(rubyflags) -c $< -o $@
@ -53,18 +53,16 @@ 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-program.o: $(ui)/program/program.cpp $(call rwildcard,$(ui)/)
obj/ui-configuration.o: $(ui)/configuration/configuration.cpp $(call rwildcard,$(ui)/)
obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/)
obj/ui-library.o: $(ui)/library/library.cpp $(call rwildcard,$(ui)/)
obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/)
obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/)
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp $(call rwildcard,$(ui)/)
obj/ui-resource.o: $(ui)/resource/resource.cpp $(call rwildcard,$(ui)/)
obj/ui-higan.o: $(ui)/higan.cpp
obj/ui-program.o: $(ui)/program/program.cpp
obj/ui-input.o: $(ui)/input/input.cpp
obj/ui-settings.o: $(ui)/settings/settings.cpp
obj/ui-tools.o: $(ui)/tools/tools.cpp
obj/ui-presentation.o: $(ui)/presentation/presentation.cpp
obj/ui-resource.o: $(ui)/resource/resource.cpp
obj/ui-windows.o:
$(windres) data/higan.rc obj/ui-resource.o
$(windres) $(ui)/resource/higan.rc obj/ui-windows.o
# targets
build: $(objects)
@ -74,8 +72,8 @@ ifeq ($(platform),macos)
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
cp data/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
cp $(ui)/resource/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns $(ui)/resource/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
endif
install:
@ -96,8 +94,8 @@ else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/share/$(name)/systems/
cp out/$(name) $(prefix)/bin/$(name)
cp -R systems/* $(prefix)/share/$(name)/systems/
cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp data/$(name).png $(prefix)/share/icons/$(name).png
cp $(ui)/resource/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp $(ui)/resource/$(name).png $(prefix)/share/icons/$(name).png
endif
uninstall:

View File

@ -1,69 +0,0 @@
#include "../higan.hpp"
Settings settings;
Settings::Settings() {
Markup::Node::operator=(BML::unserialize(string::read(locate("settings.bml"))));
auto set = [&](const string& name, const string& value) {
//create node and set to default value only if it does not already exist
if(!operator[](name)) operator()(name).setValue(value);
};
set("UserInterface/ShowStatusBar", true);
set("Library/Location", {Path::user(), "Emulation/"});
set("Library/IgnoreManifests", false);
set("Video/Driver", ruby::Video::safestDriver());
set("Video/Synchronize", false);
set("Video/Shader", "Blur");
set("Video/BlurEmulation", true);
set("Video/ColorEmulation", true);
set("Video/ScanlineEmulation", false);
set("Video/Saturation", 100);
set("Video/Gamma", 100);
set("Video/Luminance", 100);
set("Video/Overscan/Horizontal", 0);
set("Video/Overscan/Vertical", 0);
set("Video/Windowed/AspectCorrection", true);
set("Video/Windowed/IntegralScaling", true);
set("Video/Windowed/Adaptive", true);
set("Video/Windowed/Scale", "Small");
set("Video/Windowed/Scale/Small", "640x480");
set("Video/Windowed/Scale/Medium", "960x720");
set("Video/Windowed/Scale/Large", "1280x960");
set("Video/Fullscreen/AspectCorrection", true);
set("Video/Fullscreen/IntegralScaling", true);
set("Video/Fullscreen/Exclusive", false);
set("Audio/Driver", ruby::Audio::safestDriver());
set("Audio/Device", "");
set("Audio/Frequency", 48000);
set("Audio/Latency", 0);
set("Audio/Exclusive", false);
set("Audio/Synchronize", true);
set("Audio/Mute", false);
set("Audio/Volume", 100);
set("Audio/Balance", 50);
set("Audio/Reverb/Enable", false);
set("Input/Driver", ruby::Input::safestDriver());
set("Input/Frequency", 5);
set("Input/FocusLoss/Pause", false);
set("Input/FocusLoss/AllowInput", false);
set("Emulation/AutoSaveMemory/Enable", true);
set("Emulation/AutoSaveMemory/Interval", 30);
set("Systems", "");
set("Crashed", false);
}
auto Settings::save() -> void {
file::write(locate("settings.bml"), BML::serialize(*this));
}

View File

@ -1,6 +0,0 @@
struct Settings : Markup::Node {
Settings();
auto save() -> void;
};
extern Settings settings;

View File

@ -12,7 +12,6 @@ extern unique_pointer<Input> input;
extern Emulator::Interface* emulator;
#include "program/program.hpp"
#include "configuration/configuration.hpp"
#include "input/input.hpp"
#include "settings/settings.hpp"
#include "tools/tools.hpp"

View File

@ -104,7 +104,7 @@ auto InputManager::appendHotkeys() -> void {
}
auto InputManager::pollHotkeys() -> void {
if(!program->focused() && !settings["Input/FocusLoss/AllowInput"].boolean()) return;
if(!program->focused()) return;
for(auto& hotkey : hotkeys) {
int16 state = hotkey->poll();

View File

@ -119,6 +119,10 @@ Presentation::Presentation() {
statusBar.setFont(Font().setBold());
statusBar.setVisible(settings["UserInterface/ShowStatusBar"].boolean());
image icon{Resource::Icon};
icon.alphaBlend(0xff000000);
canvas.setIcon(icon).setVisible(false);
viewport.setDroppable().onDrop([&](auto locations) {
if(!directory::exists(locations(0))) return;
program->mediumQueue.append(locations(0));
@ -139,7 +143,17 @@ Presentation::Presentation() {
setCentered();
#if defined(PLATFORM_WINDOWS)
Application::Windows::onModalChange([](bool modal) { if(modal && audio) audio->clear(); });
Application::Windows::onModalChange([](bool modal) {
if(modal && audio) audio->clear();
});
Application::Windows::onScreenSaver([]() -> bool {
if(emulator && emulator->loaded()) {
if(program->pause) return true;
if(!program->focused() && settingsManager->input.pauseEmulation.checked()) return true;
return false;
}
return true;
});
#endif
#if defined(PLATFORM_MACOS)
@ -191,7 +205,22 @@ auto Presentation::updateEmulator() -> void {
emulator->set("Scanline Emulation", scanlineEmulation.checked());
}
auto Presentation::showIcon() -> void {
Application::processEvents();
int width = geometry().width();
int height = geometry().height();
int x = width - 128;
int y = height - 128;
if(x >= 0 && y >= 0) {
canvas.setVisible(true).setGeometry({x, y, 112, 112});
} else {
canvas.setVisible(false);
}
viewport.setGeometry({0, 0, 1, 1});
}
auto Presentation::clearViewport() -> void {
if(!emulator || !emulator->loaded()) showIcon();
if(!video) return;
uint32_t* output;
@ -200,8 +229,8 @@ auto Presentation::clearViewport() -> void {
uint height = viewport.geometry().height();
if(video->lock(output, length, width, height)) {
for(uint y : range(height)) {
auto dp = output + y * (length >> 2);
for(uint x : range(width)) *dp++ = 0xff000000;
auto line = output + y * (length >> 2);
for(uint x : range(width)) *line++ = 0xff000000;
}
video->unlock();
@ -210,6 +239,8 @@ auto Presentation::clearViewport() -> void {
}
auto Presentation::resizeViewport(bool resizeWindow) -> void {
if(emulator && emulator->loaded()) canvas.setVisible(false);
//clear video area before resizing to avoid seeing distorted video momentarily
clearViewport();

View File

@ -11,6 +11,7 @@ struct AboutWindow : Window {
struct Presentation : Window {
Presentation();
auto updateEmulator() -> void;
auto showIcon() -> void;
auto clearViewport() -> void;
auto resizeViewport(bool resizeWindow = true) -> void;
auto toggleFullScreen() -> void;
@ -78,6 +79,7 @@ struct Presentation : Window {
MenuItem about{&helpMenu};
FixedLayout layout{this};
Canvas canvas{&layout, Geometry{0, 0, 1, 1}};
Viewport viewport{&layout, Geometry{0, 0, 1, 1}};
StatusBar statusBar{this};

View File

@ -95,7 +95,7 @@ auto Program::audioSample(const double* samples, uint channels) -> void {
}
auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
if(focused() || settings["Input/FocusLoss/AllowInput"].boolean()) {
if(focused() || settingsManager->input.allowInput.checked()) {
inputManager->poll();
if(auto mapping = inputManager->mapping(port, device, input)) {
return mapping->poll();
@ -105,7 +105,7 @@ auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
}
auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void {
if(focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) {
if(focused() || settingsManager->input.allowInput.checked() || !enable) {
if(auto mapping = inputManager->mapping(port, device, input)) {
return mapping->rumble(enable);
}

View File

@ -85,7 +85,11 @@ auto Program::main() -> void {
inputManager->poll();
inputManager->pollHotkeys();
if(!emulator || !emulator->loaded() || pause || (!focused() && settings["Input/FocusLoss/Pause"].boolean())) {
if(!emulator
|| !emulator->loaded()
|| pause
|| (!focused() && settingsManager->input.pauseEmulation.checked())
) {
audio->clear();
usleep(20 * 1000);
return;

View File

@ -120,8 +120,8 @@ auto Program::updateStatusText() -> void {
if((currentTime - statusTime) <= 2) {
text = statusMessage;
} else if(!emulator || emulator->loaded() == false) {
text = "No cartridge loaded";
} else if(pause || (!presentation->focused() && settings["Input/FocusLoss/Pause"].boolean())) {
text = "No game loaded";
} else if(pause || (!focused() && settingsManager->input.pauseEmulation.checked())) {
text = "Paused";
} else {
text = statusText;

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,2 +1,3 @@
namespace name=Resource
binary name=Icon file=icon.png
binary name=Logo file=logo.png

View File

@ -2,6 +2,105 @@
#include "resource.hpp"
namespace Resource {
const nall::vector<uint8_t> Icon = { //size: 3088
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,112,0,0,0,112,8,6,0,0,0,198,224,244,
75,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,32,99,72,82,77,0,0,122,38,0,0,128,
132,0,0,250,0,0,0,128,232,0,0,117,48,0,0,234,96,0,0,58,152,0,0,23,112,156,186,81,60,0,0,0,
9,112,72,89,115,0,0,0,90,0,0,0,90,0,112,35,184,125,0,0,0,6,98,75,71,68,0,0,0,0,0,0,
249,67,187,127,0,0,10,195,73,68,65,84,120,218,237,93,9,144,84,213,21,5,201,36,200,152,81,116,152,97,70,4,
151,138,154,42,17,81,199,141,12,150,22,184,27,68,145,224,46,110,8,106,161,40,106,84,18,141,152,224,146,136,82,70,
75,147,148,198,4,203,221,24,81,179,184,175,41,165,10,119,81,161,167,21,20,80,80,145,153,97,16,102,114,111,247,249,
244,99,104,186,239,125,255,119,247,159,158,123,171,78,81,5,244,239,215,239,252,247,222,221,95,143,30,38,38,38,38,38,
38,38,38,38,38,38,38,38,38,38,38,38,38,27,73,83,255,254,140,45,9,39,16,174,33,76,34,52,16,250,18,122,
242,191,155,196,155,188,31,17,102,17,190,39,116,16,218,9,43,8,111,18,254,72,24,67,216,150,176,153,145,25,79,2,
135,16,150,129,188,108,88,67,248,144,112,11,161,145,208,155,63,183,96,224,64,155,192,152,16,184,63,97,101,14,2,93,
124,67,120,152,48,154,183,216,4,125,62,105,171,178,228,4,214,19,222,23,18,24,96,53,225,57,194,8,59,39,75,76,
96,71,67,3,255,121,189,146,192,0,159,19,142,194,139,96,19,90,194,85,248,83,194,2,79,18,95,37,108,99,4,150,
144,192,68,154,68,223,85,248,45,97,63,35,176,244,171,240,32,194,119,30,4,242,103,126,102,4,150,158,192,254,30,202,
12,227,3,194,0,35,176,244,4,86,16,30,247,32,240,122,83,98,226,65,32,99,166,146,188,85,216,122,109,18,99,66,
224,84,143,237,179,206,8,140,15,137,167,43,9,124,130,240,67,35,48,62,4,142,118,156,218,18,220,20,245,249,151,172,
173,13,198,82,141,241,76,32,28,66,216,58,97,103,109,94,2,15,133,155,76,74,224,132,168,39,20,227,24,72,152,227,
188,76,173,132,23,9,199,33,122,98,132,109,98,226,14,198,100,73,200,107,197,202,136,118,12,233,21,248,187,28,74,211,
29,132,237,2,7,132,201,134,4,30,72,104,17,18,248,37,97,183,200,9,76,7,151,255,151,231,187,95,70,208,217,182,
212,78,147,55,76,225,141,153,31,181,6,138,49,112,240,248,19,225,247,143,72,26,137,27,76,94,3,98,126,18,2,95,
34,108,81,0,2,135,96,117,75,198,144,8,182,241,88,146,152,200,216,103,172,145,141,34,156,10,199,113,101,212,131,198,
243,246,32,44,23,78,222,131,132,94,81,141,193,177,69,47,83,154,50,188,90,135,199,146,68,12,138,183,169,127,66,35,
107,199,10,121,10,26,89,106,5,36,6,12,136,234,187,6,19,190,18,78,220,173,81,77,154,67,30,135,181,62,242,244,
199,14,139,21,137,206,234,155,8,226,58,15,154,149,141,39,9,71,6,121,42,17,76,226,110,138,237,235,151,17,175,190,
42,194,125,158,33,45,198,92,194,142,177,33,208,121,43,103,8,194,57,127,39,236,157,8,145,57,230,65,224,248,8,87,
31,123,115,174,85,58,17,178,225,218,216,172,66,135,192,243,132,131,95,76,184,50,136,142,39,234,234,124,190,111,119,225,
22,186,38,72,165,136,224,55,254,128,112,17,161,57,36,121,140,103,8,155,199,109,21,14,37,44,21,254,128,181,132,127,
19,246,89,76,231,162,230,135,56,74,204,10,193,247,52,195,102,12,247,219,234,234,120,199,56,87,145,21,151,15,255,136,
149,111,214,217,94,102,43,127,8,171,215,99,53,201,184,74,51,226,107,194,158,161,182,235,154,26,206,102,59,89,161,245,
230,3,191,4,227,226,170,200,140,80,216,103,1,120,98,206,144,146,168,52,228,151,16,118,241,153,168,212,246,158,118,151,
29,139,231,132,37,174,25,10,204,105,8,74,199,210,148,96,7,238,61,30,63,142,21,146,99,36,111,165,147,23,211,34,
92,225,131,180,147,229,156,235,124,126,46,10,65,218,119,56,239,166,98,204,253,240,82,196,218,152,223,203,243,71,191,71,
216,89,72,32,155,36,109,66,187,171,86,125,198,146,98,69,127,30,65,72,134,200,128,187,31,81,147,45,216,241,173,85,
214,74,173,145,78,219,132,77,152,15,51,18,245,245,57,223,80,60,255,120,40,66,18,155,171,175,230,124,93,152,126,62,
147,215,228,49,254,86,228,235,140,12,194,73,171,135,14,237,146,190,202,90,196,197,180,19,240,22,161,70,64,224,120,133,
31,180,82,122,182,194,225,124,52,225,83,229,184,219,241,178,156,20,120,157,186,108,45,134,179,10,15,81,24,219,1,86,
228,210,26,147,233,173,141,49,89,248,188,127,73,2,171,136,239,245,132,219,111,177,114,204,172,224,92,151,138,78,240,249,
214,21,182,74,33,137,172,85,254,154,176,78,49,25,45,185,178,199,156,151,227,87,194,231,61,10,3,92,50,214,147,149,
218,38,143,245,1,56,237,123,149,93,168,8,19,179,53,18,138,52,233,127,141,2,2,111,22,62,111,118,174,170,36,199,
195,114,174,194,206,91,139,64,238,47,8,125,82,219,101,57,172,186,28,90,233,16,20,94,74,38,231,11,194,174,185,38,
60,153,38,228,110,225,243,254,148,172,174,206,170,20,57,73,194,83,20,30,150,143,9,151,4,154,109,217,7,104,157,21,
115,140,208,119,249,58,97,171,60,43,166,2,174,40,201,132,207,202,54,209,248,59,126,17,46,192,170,151,156,115,191,103,
51,135,86,91,247,170,51,116,206,152,243,4,147,53,51,215,155,141,127,171,84,104,184,55,166,60,42,100,154,100,121,206,
254,130,51,143,93,113,127,225,8,74,89,158,115,74,18,43,224,145,88,149,195,71,56,82,160,112,112,212,255,109,77,216,
198,67,17,90,9,5,229,32,75,8,222,152,196,115,178,168,234,108,71,221,153,47,224,139,103,12,82,24,217,211,54,34,
48,99,138,76,202,162,33,179,31,247,17,152,64,189,203,86,65,9,73,98,79,68,19,238,128,241,203,26,221,213,88,89,
169,140,231,60,159,215,4,115,47,203,161,192,240,247,221,6,5,107,174,211,221,98,243,38,107,138,32,34,178,23,20,150,
42,105,3,2,143,110,21,23,11,20,162,90,184,219,172,191,76,145,136,63,92,232,200,238,128,199,198,38,46,102,4,158,
170,112,148,95,104,89,209,241,35,240,82,101,89,217,86,70,96,28,200,203,148,115,105,170,115,57,123,108,106,162,95,63,
91,133,49,89,125,236,183,124,200,163,201,207,112,219,74,227,65,96,21,220,109,218,56,227,243,232,110,97,19,89,98,2,
119,240,76,115,104,135,47,179,194,72,44,45,129,141,158,77,126,130,4,163,147,108,43,45,45,129,103,132,76,237,251,24,
9,200,169,148,65,147,226,146,167,9,228,230,194,211,249,242,110,76,10,67,32,251,40,255,27,1,129,237,240,123,90,19,
130,34,19,184,147,66,129,89,39,200,103,153,24,219,36,219,50,37,240,231,66,31,104,27,114,97,150,11,210,55,14,181,
46,18,197,59,255,102,8,87,223,34,132,156,110,20,252,223,119,80,237,107,36,22,193,128,127,73,72,224,83,56,223,234,
209,230,35,223,255,255,15,58,78,216,100,23,144,192,125,133,245,128,235,75,170,157,106,169,101,130,207,252,21,125,95,108,
194,11,180,125,94,161,184,110,96,152,243,57,14,20,95,37,168,163,88,139,45,183,183,145,24,61,129,91,42,182,207,87,
221,240,145,147,92,60,71,88,152,114,105,190,76,110,19,161,116,100,8,24,169,112,159,77,119,93,101,78,8,170,65,152,
8,197,101,97,103,39,44,189,34,178,213,215,11,217,106,210,237,179,49,91,26,97,50,211,6,69,210,225,240,43,92,176,
101,54,98,4,4,14,81,84,11,61,15,109,117,83,207,226,132,224,123,21,49,196,209,102,232,135,35,111,51,165,239,115,
202,166,86,141,83,167,193,245,242,239,42,72,28,147,176,43,123,148,228,101,18,111,247,129,183,68,50,217,159,161,253,149,
68,163,29,171,72,75,92,130,237,212,206,68,229,234,99,117,254,111,138,213,247,103,73,237,130,147,11,170,201,171,225,51,
241,172,110,93,27,33,38,47,163,53,142,83,116,68,90,9,131,93,148,6,239,244,250,124,69,217,180,224,34,139,96,228,
144,68,102,235,228,168,195,60,197,228,62,30,20,90,74,36,153,217,74,71,10,189,52,110,4,99,122,212,189,71,203,109,
235,236,131,114,46,77,243,156,81,65,15,107,205,119,37,229,94,154,206,189,215,238,90,95,224,105,81,253,141,38,116,178,
178,27,253,3,154,213,151,229,133,233,171,44,1,15,2,194,115,82,149,196,188,107,116,119,18,59,117,69,90,170,152,200,
197,112,114,231,172,104,18,156,183,123,163,163,147,54,178,63,15,219,112,247,53,51,156,243,104,95,52,7,151,78,30,111,
123,151,135,53,180,157,151,103,130,114,229,187,102,198,249,177,106,29,89,2,141,115,48,174,18,215,76,220,99,81,213,60,
56,103,239,221,158,57,54,173,56,23,7,117,27,247,155,243,230,115,228,252,53,229,132,189,31,68,209,163,168,158,117,180,
223,159,160,83,148,111,178,212,27,40,125,43,239,104,70,211,134,77,241,222,80,78,210,50,180,194,42,68,39,252,160,181,
228,183,33,72,92,129,212,143,250,178,92,141,206,68,29,140,238,132,218,59,0,39,21,74,105,112,138,103,110,240,108,212,
231,106,169,65,35,160,170,178,73,34,118,194,67,39,192,119,169,189,15,126,90,161,107,27,156,70,125,207,70,144,127,218,
138,94,109,199,5,68,54,117,241,6,120,125,208,229,232,107,229,68,172,193,245,169,5,215,244,156,29,162,209,163,233,93,
46,34,57,33,249,68,110,172,144,172,169,233,58,68,58,119,236,241,165,32,183,123,168,234,107,80,85,84,89,172,31,157,
218,242,210,237,185,46,196,247,119,68,132,54,108,173,147,81,101,21,239,8,71,160,37,34,44,244,172,199,185,178,26,10,
65,101,177,127,40,94,186,31,135,188,224,35,87,214,56,95,195,243,7,194,1,235,219,154,196,169,31,141,179,101,78,240,
172,231,91,133,51,175,36,6,114,18,93,131,97,90,204,45,0,137,110,43,47,118,203,157,73,216,190,228,171,50,200,112,
134,125,55,219,211,187,177,28,125,213,74,218,226,170,147,198,188,168,128,36,6,158,165,79,144,255,51,42,165,72,165,27,
208,22,221,171,178,13,206,142,133,158,63,100,1,167,49,36,99,114,62,240,24,150,166,143,129,83,60,174,83,240,197,106,
164,252,207,130,205,59,32,8,38,47,36,5,168,80,190,76,142,145,141,33,188,224,121,175,208,58,104,106,13,139,98,214,
81,194,49,127,166,40,110,13,141,146,204,143,112,149,195,241,65,59,178,208,243,19,132,81,144,116,123,44,110,39,107,9,
225,189,248,109,80,116,25,199,34,19,231,78,140,105,138,187,123,163,70,27,220,142,163,188,243,86,147,153,51,142,223,132,
179,209,183,179,53,196,190,255,2,74,188,98,239,63,116,114,117,174,16,54,137,45,20,150,4,109,83,124,223,194,49,200,
39,249,62,132,171,105,62,182,164,234,174,228,161,112,146,162,38,42,211,49,162,198,213,170,57,115,204,130,25,33,222,190,
192,254,249,13,242,94,186,164,107,9,169,20,188,133,29,134,48,88,123,145,201,91,7,243,76,24,110,201,104,152,99,61,
205,130,22,236,221,23,227,230,202,46,31,193,118,18,133,7,162,170,233,139,34,145,215,140,82,184,106,241,28,58,38,194,
85,202,158,44,243,160,10,115,140,172,239,2,190,39,176,204,186,223,58,26,234,30,200,88,123,5,25,221,205,202,251,50,
220,213,213,134,249,251,18,169,30,111,34,128,61,29,41,28,186,139,165,59,42,43,131,129,14,207,98,208,182,99,75,77,
98,149,221,131,252,201,225,169,183,164,155,116,120,119,106,17,171,112,129,215,129,216,177,38,162,224,148,39,255,38,148,10,
204,132,27,237,6,244,244,190,18,182,243,89,8,65,29,142,26,199,193,88,225,156,121,80,49,191,190,222,95,67,119,106,
21,14,192,96,110,193,65,58,30,158,251,237,225,59,76,169,183,47,143,27,215,195,196,196,196,196,196,196,196,196,196,196,
196,196,196,196,196,196,196,164,124,228,255,132,119,141,168,125,48,16,122,0,0,0,37,116,69,88,116,100,97,116,101,58,
99,114,101,97,116,101,0,50,48,49,56,45,48,53,45,50,51,84,49,51,58,48,53,58,48,56,45,48,52,58,48,48,
172,124,172,145,0,0,0,37,116,69,88,116,100,97,116,101,58,109,111,100,105,102,121,0,50,48,49,56,45,48,53,45,
50,51,84,49,51,58,48,53,58,48,56,45,48,52,58,48,48,221,33,20,45,0,0,0,67,116,69,88,116,115,118,103,
58,98,97,115,101,45,117,114,105,0,102,105,108,101,58,47,47,47,99,111,114,101,47,102,105,108,101,115,47,109,101,100,
105,97,47,104,105,103,97,110,47,105,99,111,110,47,104,105,103,97,110,45,110,111,99,105,114,99,108,101,46,115,118,103,
144,27,14,155,0,0,0,0,73,69,78,68,174,66,96,130,
};
const nall::vector<uint8_t> Logo = { //size: 25128
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,1,143,0,0,0,95,8,6,0,0,0,16,211,75,
124,0,0,0,4,103,65,77,65,0,0,177,143,11,252,97,5,0,0,0,32,99,72,82,77,0,0,122,38,0,0,128,

View File

@ -1,3 +1,4 @@
namespace Resource {
extern const nall::vector<uint8_t> Icon;
extern const nall::vector<uint8_t> Logo;
}

View File

@ -3,14 +3,20 @@ InputSettings::InputSettings(TabFrame* parent) : TabFrameItem(parent) {
setText("Input");
layout.setMargin(5);
focusLabel.setText("When Focus is Lost:");
pauseEmulation.setText("Pause Emulation").setChecked(settings["Input/FocusLoss/Pause"].boolean()).onToggle([&] {
settings["Input/FocusLoss/Pause"].setValue(pauseEmulation.checked());
defocusLabel.setText("When Focus is Lost:");
pauseEmulation.setText("Pause Emulation").onActivate([&] {
settings["Input/Defocus"].setValue("Pause");
allowInput.setEnabled(!pauseEmulation.checked());
}).doToggle();
allowInput.setText("Allow Input").setChecked(settings["Input/FocusLoss/AllowInput"].boolean()).onToggle([&] {
settings["Input/FocusLoss/AllowInput"].setValue(allowInput.checked());
});
blockInput.setText("Block Input").onActivate([&] {
settings["Input/Defocus"].setValue("Block");
});
allowInput.setText("Allow Input").onActivate([&] {
settings["Input/Defocus"].setValue("Allow");
});
if(settings["Input/Defocus"].text() == "Pause") pauseEmulation.setChecked();
if(settings["Input/Defocus"].text() == "Block") blockInput.setChecked();
if(settings["Input/Defocus"].text() == "Allow") allowInput.setChecked();
for(auto& emulator : inputManager->emulators) {
emulatorList.append(ComboButtonItem().setText(emulator.name));
}

View File

@ -1,15 +1,82 @@
#include "../higan.hpp"
#include "system-properties.cpp"
unique_pointer<SystemProperties> systemProperties;
#include "systems.cpp"
#include "video.cpp"
#include "audio.cpp"
#include "input.cpp"
#include "hotkeys.cpp"
#include "advanced.cpp"
Settings settings;
unique_pointer<SettingsManager> settingsManager;
unique_pointer<SystemProperties> systemProperties;
Settings::Settings() {
Markup::Node::operator=(BML::unserialize(string::read(locate("settings.bml"))));
auto set = [&](const string& name, const string& value) {
//create node and set to default value only if it does not already exist
if(!operator[](name)) operator()(name).setValue(value);
};
set("UserInterface/ShowStatusBar", true);
set("Library/Location", {Path::user(), "Emulation/"});
set("Library/IgnoreManifests", false);
set("Video/Driver", ruby::Video::safestDriver());
set("Video/Synchronize", false);
set("Video/Shader", "Blur");
set("Video/BlurEmulation", true);
set("Video/ColorEmulation", true);
set("Video/ScanlineEmulation", false);
set("Video/Saturation", 100);
set("Video/Gamma", 100);
set("Video/Luminance", 100);
set("Video/Overscan/Horizontal", 0);
set("Video/Overscan/Vertical", 0);
set("Video/Windowed/AspectCorrection", true);
set("Video/Windowed/IntegralScaling", true);
set("Video/Windowed/Adaptive", true);
set("Video/Windowed/Scale", "Small");
set("Video/Windowed/Scale/Small", "640x480");
set("Video/Windowed/Scale/Medium", "960x720");
set("Video/Windowed/Scale/Large", "1280x960");
set("Video/Fullscreen/AspectCorrection", true);
set("Video/Fullscreen/IntegralScaling", true);
set("Video/Fullscreen/Exclusive", false);
set("Audio/Driver", ruby::Audio::safestDriver());
set("Audio/Device", "");
set("Audio/Frequency", 48000);
set("Audio/Latency", 0);
set("Audio/Exclusive", false);
set("Audio/Synchronize", true);
set("Audio/Mute", false);
set("Audio/Volume", 100);
set("Audio/Balance", 50);
set("Audio/Reverb/Enable", false);
set("Input/Driver", ruby::Input::safestDriver());
set("Input/Frequency", 5);
set("Input/Defocus", "Pause");
set("Emulation/AutoSaveMemory/Enable", true);
set("Emulation/AutoSaveMemory/Interval", 30);
set("Systems", "");
set("Crashed", false);
}
auto Settings::save() -> void {
file::write(locate("settings.bml"), BML::serialize(*this));
}
//
SettingsManager::SettingsManager() {
settingsManager = this;

View File

@ -1,3 +1,8 @@
struct Settings : Markup::Node {
Settings();
auto save() -> void;
};
struct SystemProperties : Window {
SystemProperties();
auto append() -> void;
@ -115,9 +120,11 @@ struct InputSettings : TabFrameItem {
VerticalLayout layout{this};
HorizontalLayout focusLayout{&layout, Size{~0, 0}};
Label focusLabel{&focusLayout, Size{0, 0}};
CheckLabel pauseEmulation{&focusLayout, Size{0, 0}};
CheckLabel allowInput{&focusLayout, Size{0, 0}};
Label defocusLabel{&focusLayout, Size{0, 0}};
RadioLabel pauseEmulation{&focusLayout, Size{0, 0}};
RadioLabel blockInput{&focusLayout, Size{0, 0}};
RadioLabel allowInput{&focusLayout, Size{0, 0}};
Group focusGroup{&pauseEmulation, &blockInput, &allowInput};
HorizontalLayout selectionLayout{&layout, Size{~0, 0}};
ComboButton emulatorList{&selectionLayout, Size{~0, 0}};
ComboButton portList{&selectionLayout, Size{~0, 0}};
@ -205,5 +212,6 @@ struct SettingsManager : Window {
auto show(uint setting) -> void;
};
extern Settings settings;
extern unique_pointer<SystemProperties> systemProperties;
extern unique_pointer<SettingsManager> settingsManager;

View File

@ -1,12 +1,10 @@
#include "../higan.hpp"
#include "cheat-database.cpp"
unique_pointer<CheatDatabase> cheatDatabase;
#include "cheat-editor.cpp"
#include "state-manager.cpp"
#include "manifest-viewer.cpp"
#include "game-notes.cpp"
unique_pointer<CheatDatabase> cheatDatabase;
unique_pointer<ToolsManager> toolsManager;
ToolsManager::ToolsManager() {

View File

@ -4,11 +4,11 @@ objects += ws-interface ws-system
objects += ws-memory ws-eeprom ws-cartridge
objects += ws-cpu ws-ppu ws-apu
obj/ws-interface.o: ws/interface/interface.cpp $(call rwildcard,ws/interface/)
obj/ws-system.o: ws/system/system.cpp $(call rwildcard,ws/system/)
obj/ws-memory.o: ws/memory/memory.cpp $(call rwildcard,ws/memory/)
obj/ws-eeprom.o: ws/eeprom/eeprom.cpp $(call rwildcard,ws/eeprom/)
obj/ws-cartridge.o: ws/cartridge/cartridge.cpp $(call rwildcard,ws/cartridge/)
obj/ws-cpu.o: ws/cpu/cpu.cpp $(call rwildcard,ws/cpu/)
obj/ws-ppu.o: ws/ppu/ppu.cpp $(call rwildcard,ws/ppu/)
obj/ws-apu.o: ws/apu/apu.cpp $(call rwildcard,ws/apu/)
obj/ws-interface.o: ws/interface/interface.cpp
obj/ws-system.o: ws/system/system.cpp
obj/ws-memory.o: ws/memory/memory.cpp
obj/ws-eeprom.o: ws/eeprom/eeprom.cpp
obj/ws-cartridge.o: ws/cartridge/cartridge.cpp
obj/ws-cpu.o: ws/cpu/cpu.cpp
obj/ws-ppu.o: ws/ppu/ppu.cpp
obj/ws-apu.o: ws/apu/apu.cpp

View File

@ -66,10 +66,19 @@ auto Application::Windows::doModalChange(bool modal) -> void {
if(state.windows.onModalChange) return state.windows.onModalChange(modal);
}
auto Application::Windows::doScreenSaver() -> bool {
if(state.windows.onScreenSaver) return state.windows.onScreenSaver();
return true; //true = allow screen saver (default); false = suppress screen saver
}
auto Application::Windows::onModalChange(const function<void (bool)>& callback) -> void {
state.windows.onModalChange = callback;
}
auto Application::Windows::onScreenSaver(const function<bool ()>& callback) -> void {
state.windows.onScreenSaver = callback;
}
//Cocoa
//=====

View File

@ -389,7 +389,9 @@ struct Application {
struct Windows {
static auto doModalChange(bool modal) -> void;
static auto doScreenSaver() -> bool;
static auto onModalChange(const function<void (bool)>& callback = {}) -> void;
static auto onScreenSaver(const function<bool ()>& callback = {}) -> void;
};
struct Cocoa {
@ -413,6 +415,7 @@ struct Application {
struct Windows {
function<void (bool)> onModalChange;
function<bool ()> onScreenSaver;
} windows;
struct Cocoa {

View File

@ -20,6 +20,7 @@ auto pMenu::destruct() -> void {
auto pMenu::append(sAction action) -> void {
if(action->self()) {
gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), action->self()->widget);
action->self()->setEnabled(action->enabled(true));
action->self()->setFont(action->font(true));
action->self()->setVisible(action->visible()); //hidden parent will hide child; no need to inherit visibility
}

View File

@ -259,6 +259,10 @@ static auto CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wparam,
case WM_ERASEBKGND: if(pWindow->onEraseBackground()) return true; break;
case WM_ENTERMENULOOP: case WM_ENTERSIZEMOVE: pWindow->onModalBegin(); return false;
case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: pWindow->onModalEnd(); return false;
case WM_SYSCOMMAND:
if(wparam == SC_SCREENSAVE || wparam == SC_MONITORPOWER) {
if(!Application::Windows::doScreenSaver()) return 0;
}
}
return Shared_windowProc(DefWindowProc, hwnd, msg, wparam, lparam);

View File

@ -86,6 +86,11 @@ auto SuperFamicom::manifest() const -> string {
output.append(Memory{}.type("RAM").size(size).content("Save").text());
}
if(board(0) == "GSU" && !ramSize() && !expansionRamSize()) {
//Starfox / Starwing reports having no RAM; but all GSU boards contain expansion RAM
output.append(Memory{}.type("RAM").size(0x8000).content("Save").isVolatile().text());
}
if(0) {
} else if(board(0) == "ARM") {
output.append(Memory{}.type("ROM").size(0x20000).content("Program").manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text());

View File

@ -89,6 +89,7 @@ endif
# windows settings
ifeq ($(platform),windows)
link += -lws2_32 -lole32
link += $(if $(findstring $(compiler),g++),-static-libgcc -static-libstdc++)
link += $(if $(findstring $(console),true),-mconsole,-mwindows)
windres := windres
endif

View File

@ -37,10 +37,14 @@ private:
struct Device : vector<Group> {
Device(const string& name) : _name(name) {}
auto pathID() const -> uint32_t { return (uint32_t)(_id >> 32); }
auto deviceID() const -> uint32_t { return (uint32_t)(_id >> 0); }
auto vendorID() const -> uint16_t { return (uint16_t)(_id >> 16); }
auto productID() const -> uint16_t { return (uint16_t)(_id >> 0); }
//id => {pathID}-{vendorID}-{productID}
auto pathID() const -> uint32_t { return (uint32_t)(_id >> 32); } //32-63
auto vendorID() const -> uint16_t { return (uint16_t)(_id >> 16); } //16-31
auto productID() const -> uint16_t { return (uint16_t)(_id >> 0); } // 0-15
auto setPathID (uint32_t pathID ) -> void { _id = (uint64_t)pathID << 32 | vendorID() << 16 | productID() << 0; }
auto setVendorID (uint16_t vendorID ) -> void { _id = (uint64_t)pathID() << 32 | vendorID << 16 | productID() << 0; }
auto setProductID(uint16_t productID) -> void { _id = (uint64_t)pathID() << 32 | vendorID() << 16 | productID << 0; }
virtual auto isNull() const -> bool { return false; }
virtual auto isKeyboard() const -> bool { return false; }
@ -66,11 +70,14 @@ private:
};
struct Null : Device {
enum : uint16_t { GenericVendorID = 0x0000, GenericProductID = 0x0000 };
Null() : Device("Null") {}
auto isNull() const -> bool { return true; }
};
struct Keyboard : Device {
enum : uint16_t { GenericVendorID = 0x0000, GenericProductID = 0x0001 };
enum GroupID : uint { Button };
Keyboard() : Device("Keyboard") { append("Button"); }
@ -79,6 +86,7 @@ struct Keyboard : Device {
};
struct Mouse : Device {
enum : uint16_t { GenericVendorID = 0x0000, GenericProductID = 0x0002 };
enum GroupID : uint { Axis, Button };
Mouse() : Device("Mouse") { append("Axis"), append("Button"); }
@ -88,6 +96,7 @@ struct Mouse : Device {
};
struct Joypad : Device {
enum : uint16_t { GenericVendorID = 0x0000, GenericProductID = 0x0003 };
enum GroupID : uint { Axis, Hat, Trigger, Button };
Joypad() : Device("Joypad") { append("Axis"), append("Hat"), append("Trigger"), append("Button"); }

View File

@ -5,7 +5,7 @@ else
endif
rubyflags += $(foreach c,$(subst .,_,$(call strupper,$(ruby))),-D$c)
rubyflags += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --cflags))
rubyflags += $(if $(findstring input.sdl,$(ruby)),$(shell sdl2-config --cflags))
rubylink =
@ -24,11 +24,10 @@ rubylink += $(if $(findstring audio.pulseaudiosimple,$(ruby)),-lpulse-simple)
rubylink += $(if $(findstring audio.wasapi,$(ruby)),-lavrt -luuid)
rubylink += $(if $(findstring audio.xaudio2,$(ruby)),-lole32)
rubylink += $(if $(findstring input.sdl,$(ruby)),$(shell sdl2-config --libs))
rubylink += $(if $(findstring input.udev,$(ruby)),-ludev)
rubylink += $(if $(findstring input.windows,$(ruby)),-ldinput8 -ldxguid)
rubylink += $(if $(findstring .sdl,$(ruby)),$(shell sdl-config --libs))
ifeq ($(platform),windows)
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_JOYPAD_DIRECTINPUT
#define RUBY_INPUT_JOYPAD_DIRECTINPUT
#pragma once
auto CALLBACK DirectInput_EnumJoypadsCallback(const DIDEVICEINSTANCE* instance, void* p) -> BOOL;
auto CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL;
@ -26,9 +25,9 @@ struct InputJoypadDirectInput {
LPDIRECTINPUT8 context = nullptr;
LPDIRECTINPUTDEVICE8 device = nullptr;
bool xinputAvailable = false;
unsigned effects = 0;
uint effects = 0;
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto assign(shared_pointer<HID::Joypad> hid, uint groupID, uint inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
@ -42,7 +41,7 @@ struct InputJoypadDirectInput {
DIJOYSTATE2 state;
if(FAILED(jp.device->GetDeviceState(sizeof(DIJOYSTATE2), &state))) continue;
for(unsigned n = 0; n < 4; n++) {
for(auto n : range(4)) {
assign(jp.hid, HID::Joypad::GroupID::Axis, 0, state.lX);
assign(jp.hid, HID::Joypad::GroupID::Axis, 1, state.lY);
assign(jp.hid, HID::Joypad::GroupID::Axis, 2, state.lZ);
@ -50,7 +49,7 @@ struct InputJoypadDirectInput {
assign(jp.hid, HID::Joypad::GroupID::Axis, 4, state.lRy);
assign(jp.hid, HID::Joypad::GroupID::Axis, 5, state.lRz);
unsigned pov = state.rgdwPOV[n];
uint pov = state.rgdwPOV[n];
int16_t xaxis = 0;
int16_t yaxis = 0;
@ -65,7 +64,7 @@ struct InputJoypadDirectInput {
assign(jp.hid, HID::Joypad::GroupID::Hat, n * 2 + 1, yaxis);
}
for(unsigned n = 0; n < 128; n++) {
for(auto n : range(128)) {
assign(jp.hid, HID::Joypad::GroupID::Button, n, (bool)state.rgbButtons[n]);
}
@ -140,7 +139,9 @@ struct InputJoypadDirectInput {
device->GetProperty(DIPROP_GUIDANDPATH, &property.diph);
string devicePath = (const char*)utf8_t(property.wszPath);
jp.pathID = Hash::CRC32(devicePath.data(), devicePath.size()).value();
jp.hid->setID((uint64_t)jp.pathID << 32 | jp.vendorID << 16 | jp.productID << 0);
jp.hid->setVendorID(jp.vendorID);
jp.hid->setProductID(jp.productID);
jp.hid->setPathID(jp.pathID);
if(jp.hid->rumble()) {
//disable auto-centering spring for rumble support
@ -176,9 +177,9 @@ struct InputJoypadDirectInput {
device->CreateEffect(GUID_ConstantForce, &effect, &jp.effect, NULL);
}
for(unsigned n = 0; n < 6; n++) jp.hid->axes().append(n);
for(unsigned n = 0; n < 8; n++) jp.hid->hats().append(n);
for(unsigned n = 0; n < 128; n++) jp.hid->buttons().append(n);
for(auto n : range(6)) jp.hid->axes().append(n);
for(auto n : range(8)) jp.hid->hats().append(n);
for(auto n : range(128)) jp.hid->buttons().append(n);
joypads.append(jp);
return DIENUM_CONTINUE;
@ -214,5 +215,3 @@ auto CALLBACK DirectInput_EnumJoypadAxesCallback(const DIDEVICEOBJECTINSTANCE* i
auto CALLBACK DirectInput_EnumJoypadEffectsCallback(const DIDEVICEOBJECTINSTANCE* instance, void* p) -> BOOL {
return ((InputJoypadDirectInput*)p)->initEffect(instance);
}
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_JOYPAD_SDL
#define RUBY_INPUT_JOYPAD_SDL
#pragma once
struct InputJoypadSDL {
Input& input;
@ -8,12 +7,12 @@ struct InputJoypadSDL {
struct Joypad {
shared_pointer<HID::Joypad> hid{new HID::Joypad};
unsigned id = 0;
uint id = 0;
SDL_Joystick* handle = nullptr;
};
vector<Joypad> joypads;
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto assign(shared_pointer<HID::Joypad> hid, uint groupID, uint inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
@ -28,10 +27,10 @@ struct InputJoypadSDL {
assign(jp.hid, HID::Joypad::GroupID::Axis, n, (int16_t)SDL_JoystickGetAxis(jp.handle, n));
}
for(signed n = 0; n < (signed)jp.hid->hats().size() - 1; n += 2) {
for(int n = 0; n < (int)jp.hid->hats().size() - 1; n += 2) {
uint8_t state = SDL_JoystickGetHat(jp.handle, n >> 1);
assign(jp.hid, HID::Joypad::GroupID::Hat, n + 0, state & SDL_HAT_LEFT ? -32767 : state & SDL_HAT_RIGHT ? +32767 : 0);
assign(jp.hid, HID::Joypad::GroupID::Hat, n + 1, state & SDL_HAT_UP ? -32767 : state & SDL_HAT_DOWN ? +32767 : 0);
assign(jp.hid, HID::Joypad::GroupID::Hat, n + 1, state & SDL_HAT_UP ? -32767 : state & SDL_HAT_DOWN ? +32767 : 0);
}
for(auto n : range(jp.hid->buttons())) {
@ -49,13 +48,15 @@ struct InputJoypadSDL {
for(auto id : range(SDL_NumJoysticks())) {
Joypad jp;
jp.id = id;
jp.handle = SDL_JoystickOpen(id);
jp.handle = SDL_JoystickOpen(jp.id);
unsigned axes = SDL_JoystickNumAxes(jp.handle);
unsigned hats = SDL_JoystickNumHats(jp.handle) * 2;
unsigned buttons = 32; //there is no SDL_JoystickNumButtons()
uint axes = SDL_JoystickNumAxes(jp.handle);
uint hats = SDL_JoystickNumHats(jp.handle) * 2;
uint buttons = SDL_JoystickNumButtons(jp.handle);
jp.hid->setID(3 + jp.id);
jp.hid->setVendorID(HID::Joypad::GenericVendorID);
jp.hid->setProductID(HID::Joypad::GenericProductID);
jp.hid->setPathID(jp.id);
for(auto n : range(axes)) jp.hid->axes().append(n);
for(auto n : range(hats)) jp.hid->hats().append(n);
for(auto n : range(buttons)) jp.hid->buttons().append(n);
@ -75,5 +76,3 @@ struct InputJoypadSDL {
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
};
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_JOYPAD_UDEV
#define RUBY_INPUT_JOYPAD_UDEV
#pragma once
struct InputJoypadUdev {
Input& input;
@ -265,8 +264,9 @@ private:
}
auto createJoypadHID(Joypad& jp) -> void {
uint64_t pathID = Hash::CRC32(jp.deviceName.data(), jp.deviceName.size()).value();
jp.hid->setID(pathID << 32 | jp.vendorID.hex() << 16 | jp.productID.hex() << 0);
jp.hid->setVendorID(jp.vendorID.hex());
jp.hid->setProductID(jp.productID.hex());
jp.hid->setPathID(Hash::CRC32(jp.deviceName.data(), jp.deviceName.size()).value());
for(uint n : range(jp.axes.size())) jp.hid->axes().append(n);
for(uint n : range(jp.hats.size())) jp.hid->hats().append(n);
@ -284,5 +284,3 @@ private:
}
}
};
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_JOYPAD_XINPUT
#define RUBY_INPUT_JOYPAD_XINPUT
#pragma once
//documented functionality
#define oXInputGetState "XInputGetState"
@ -29,11 +28,11 @@ struct InputJoypadXInput {
struct Joypad {
shared_pointer<HID::Joypad> hid{new HID::Joypad};
unsigned id = 0;
uint id = 0;
};
vector<Joypad> joypads;
auto assign(shared_pointer<HID::Joypad> hid, unsigned groupID, unsigned inputID, int16_t value) -> void {
auto assign(shared_pointer<HID::Joypad> hid, uint groupID, uint inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
@ -116,10 +115,12 @@ struct InputJoypadXInput {
//XInput supports a maximum of four controllers
//add all four to devices list now. If they are not connected, they will not show up in poll() results
for(unsigned id = 0; id < 4; id++) {
for(auto id : range(4)) {
Joypad jp;
jp.id = id;
jp.hid->setID((uint64_t)(1 + id) << 32 | 0x045e << 16 | 0x028e << 0); //Xbox 360 Player# + VendorID + ProductID
jp.hid->setVendorID(0x045e);
jp.hid->setProductID(0x028e);
jp.hid->setPathID(id);
jp.hid->setRumble(true);
jp.hid->axes().append("LeftThumbX");
@ -158,5 +159,3 @@ struct InputJoypadXInput {
libxinput = nullptr;
}
};
#endif

View File

@ -1,3 +1,5 @@
#pragma once
struct InputKeyboardCarbon {
Input& input;
InputKeyboardCarbon(Input& input) : input(input) {}
@ -145,7 +147,9 @@ struct InputKeyboardCarbon {
keys.append({0x3a, "Alt"});
keys.append({0x37, "Super"});
hid->setID(1);
hid->setVendorID(HID::Keyboard::GenericVendorID);
hid->setProductID(HID::Keyboard::GenericProductID);
hid->setPathID(0);
for(auto& key : keys) {
hid->buttons().append(key.name);
}

View File

@ -1,3 +1,5 @@
#pragma once
struct InputKeyboardQuartz {
Input& input;
InputKeyboardQuartz(Input& input) : input(input) {}
@ -140,7 +142,9 @@ struct InputKeyboardQuartz {
keys.append({"Option", kVK_Option});
keys.append({"Command", kVK_Command});
hid->setID(1);
hid->setVendorID(HID::Keyboard::GenericVendorID);
hid->setProductID(HID::Keyboard::GenericProductID);
hid->setPath(0);
for(auto& key : keys) {
hid->buttons().append(key.name);
}

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_KEYBOARD_RAWINPUT
#define RUBY_INPUT_KEYBOARD_RAWINPUT
#pragma once
struct InputKeyboardRawInput {
Input& input;
@ -18,8 +17,8 @@ struct InputKeyboardRawInput {
} kb;
auto update(RAWINPUT* input) -> void {
unsigned code = input->data.keyboard.MakeCode;
unsigned flag = input->data.keyboard.Flags;
uint code = input->data.keyboard.MakeCode;
uint flag = input->data.keyboard.Flags;
for(auto& key : keys) {
if(key.code != code) continue;
@ -27,7 +26,7 @@ struct InputKeyboardRawInput {
}
}
auto assign(unsigned inputID, bool value) -> void {
auto assign(uint inputID, bool value) -> void {
auto& group = kb.hid->buttons();
if(group.input(inputID).value() == value) return;
input.doChange(kb.hid, HID::Keyboard::GroupID::Button, inputID, group.input(inputID).value(), value);
@ -35,7 +34,7 @@ struct InputKeyboardRawInput {
}
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
for(unsigned n = 0; n < keys.size(); n++) assign(n, keys[n].value);
for(auto n : range(keys)) assign(n, keys[n].value);
devices.append(kb.hid);
}
@ -164,7 +163,9 @@ struct InputKeyboardRawInput {
keys.append({0x005c, 2, "RightSuper"});
keys.append({0x005d, 2, "Menu"});
kb.hid->setID(1);
kb.hid->setVendorID(HID::Keyboard::GenericVendorID);
kb.hid->setProductID(HID::Keyboard::GenericProductID);
kb.hid->setPathID(0);
for(auto& key : keys) kb.hid->buttons().append(key.name);
return true;
@ -174,5 +175,3 @@ struct InputKeyboardRawInput {
rawinput.updateKeyboard.reset();
}
};
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_KEYBOARD_XLIB
#define RUBY_INPUT_KEYBOARD_XLIB
#pragma once
struct InputKeyboardXlib {
Input& input;
@ -153,7 +152,9 @@ struct InputKeyboardXlib {
keys.append({"RightSuper", XK_Super_R});
keys.append({"Menu", XK_Menu});
hid->setID(1);
hid->setVendorID(HID::Keyboard::GenericVendorID);
hid->setProductID(HID::Keyboard::GenericProductID);
hid->setPathID(0);
for(auto& key : keys) {
hid->buttons().append(key.name);
@ -170,5 +171,3 @@ struct InputKeyboardXlib {
}
}
};
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_MOUSE_RAWINPUT
#define RUBY_INPUT_MOUSE_RAWINPUT
#pragma once
struct InputMouseRawInput {
Input& input;
@ -11,9 +10,9 @@ struct InputMouseRawInput {
struct Mouse {
shared_pointer<HID::Mouse> hid{new HID::Mouse};
signed relativeX = 0;
signed relativeY = 0;
signed relativeZ = 0;
int relativeX = 0;
int relativeY = 0;
int relativeZ = 0;
bool buttons[5] = {0};
} ms;
@ -68,7 +67,7 @@ struct InputMouseRawInput {
if(input->data.mouse.usButtonFlags & RI_MOUSE_BUTTON_5_UP ) ms.buttons[4] = 0;
}
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
auto assign(uint groupID, uint inputID, int16_t value) -> void {
auto& group = ms.hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(ms.hid, groupID, inputID, group.input(inputID).value(), value);
@ -99,7 +98,9 @@ struct InputMouseRawInput {
if(!handle) return false;
this->handle = handle;
ms.hid->setID(2);
ms.hid->setVendorID(HID::Mouse::GenericVendorID);
ms.hid->setProductID(HID::Mouse::GenericProductID);
ms.hid->setPathID(0);
ms.hid->axes().append("X");
ms.hid->axes().append("Y");
@ -120,5 +121,3 @@ struct InputMouseRawInput {
release();
}
};
#endif

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_MOUSE_XLIB
#define RUBY_INPUT_MOUSE_XLIB
#pragma once
struct InputMouseXlib {
Input& input;
@ -12,16 +11,16 @@ struct InputMouseXlib {
Display* display = nullptr;
Window rootWindow = 0;
Cursor invisibleCursor = 0;
unsigned screenWidth = 0;
unsigned screenHeight = 0;
uint screenWidth = 0;
uint screenHeight = 0;
struct Mouse {
bool acquired = false;
signed numerator = 0;
signed denominator = 0;
signed threshold = 0;
unsigned relativeX = 0;
unsigned relativeY = 0;
int numerator = 0;
int denominator = 0;
int threshold = 0;
uint relativeX = 0;
uint relativeY = 0;
} ms;
auto acquired() -> bool {
@ -57,7 +56,7 @@ struct InputMouseXlib {
return true;
}
auto assign(unsigned groupID, unsigned inputID, int16_t value) -> void {
auto assign(uint groupID, uint inputID, int16_t value) -> void {
auto& group = hid->group(groupID);
if(group.input(inputID).value() == value) return;
input.doChange(hid, groupID, inputID, group.input(inputID).value(), value);
@ -67,11 +66,11 @@ struct InputMouseXlib {
auto poll(vector<shared_pointer<HID::Device>>& devices) -> void {
Window rootReturn;
Window childReturn;
signed rootXReturn = 0;
signed rootYReturn = 0;
signed windowXReturn = 0;
signed windowYReturn = 0;
unsigned maskReturn = 0;
int rootXReturn = 0;
int rootYReturn = 0;
int windowXReturn = 0;
int windowYReturn = 0;
uint maskReturn = 0;
XQueryPointer(display, handle, &rootReturn, &childReturn, &rootXReturn, &rootYReturn, &windowXReturn, &windowYReturn, &maskReturn);
if(acquired()) {
@ -132,7 +131,9 @@ struct InputMouseXlib {
ms.relativeX = 0;
ms.relativeY = 0;
hid->setID(2);
hid->setVendorID(HID::Mouse::GenericVendorID);
hid->setProductID(HID::Mouse::GenericProductID);
hid->setPathID(0);
hid->axes().append("X");
hid->axes().append("Y");
@ -158,5 +159,3 @@ struct InputMouseXlib {
}
}
};
#endif

View File

@ -1,4 +1,4 @@
#include <SDL/SDL.h>
#include <SDL2/SDL.h>
#include <sys/ipc.h>
#include <sys/shm.h>

View File

@ -1,5 +1,4 @@
#ifndef RUBY_INPUT_SHARED_RAWINPUT
#define RUBY_INPUT_SHARED_RAWINPUT
#pragma once
auto CALLBACK RawInputWindowProc(HWND, UINT, WPARAM, LPARAM) -> LRESULT;
@ -14,7 +13,7 @@ struct RawInput {
struct Device {
HANDLE handle = nullptr;
string path;
enum class Type : unsigned { Keyboard, Mouse, Joypad } type;
enum class Type : uint { Keyboard, Mouse, Joypad } type;
uint16_t vendorID = 0;
uint16_t productID = 0;
bool isXInputDevice = false;
@ -31,14 +30,14 @@ struct RawInput {
auto scanDevices() -> void {
devices.reset();
unsigned deviceCount = 0;
uint deviceCount = 0;
GetRawInputDeviceList(NULL, &deviceCount, sizeof(RAWINPUTDEVICELIST));
RAWINPUTDEVICELIST* list = new RAWINPUTDEVICELIST[deviceCount];
GetRawInputDeviceList(list, &deviceCount, sizeof(RAWINPUTDEVICELIST));
for(unsigned n = 0; n < deviceCount; n++) {
for(auto n : range(deviceCount)) {
wchar_t path[4096];
unsigned size = sizeof(path) - 1;
uint size = sizeof(path) - 1;
GetRawInputDeviceInfo(list[n].hDevice, RIDI_DEVICENAME, &path, &size);
RID_DEVICE_INFO info;
@ -80,7 +79,7 @@ struct RawInput {
auto windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
if(msg != WM_INPUT) return DefWindowProc(hwnd, msg, wparam, lparam);
unsigned size = 0;
uint size = 0;
GetRawInputData((HRAWINPUT)lparam, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
RAWINPUT* input = new RAWINPUT[size];
GetRawInputData((HRAWINPUT)lparam, RID_INPUT, input, &size, sizeof(RAWINPUTHEADER));
@ -154,5 +153,3 @@ auto WINAPI RawInputThreadProc(void*) -> DWORD {
auto CALLBACK RawInputWindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> LRESULT {
return rawinput.windowProc(hwnd, msg, wparam, lparam);
}
#endif

View File

@ -54,10 +54,6 @@ using namespace ruby;
#include <ruby/video/glx2.cpp>
#endif
#if defined(VIDEO_SDL)
#include <ruby/video/sdl.cpp>
#endif
#if defined(VIDEO_WGL)
#include <ruby/video/wgl.cpp>
#endif
@ -99,10 +95,6 @@ auto Video::create(const string& driver) -> Video* {
if(driver == "OpenGL2") return new VideoGLX2;
#endif
#if defined(VIDEO_SDL)
if(driver == "SDL") return new VideoSDL;
#endif
#if defined(VIDEO_WGL)
if(driver == "OpenGL") return new VideoWGL;
#endif
@ -137,8 +129,6 @@ auto Video::optimalDriver() -> string {
return "XVideo";
#elif defined(VIDEO_XSHM)
return "XShm";
#elif defined(VIDEO_SDL)
return "SDL";
#else
return "None";
#endif
@ -157,8 +147,6 @@ auto Video::safestDriver() -> string {
return "OpenGL";
#elif defined(VIDEO_XSHM)
return "XShm";
#elif defined(VIDEO_SDL)
return "SDL";
#elif defined(VIDEO_XVIDEO)
return "XVideo";
#elif defined(VIDEO_GLX2)
@ -209,10 +197,6 @@ auto Video::availableDrivers() -> string_vector {
"XShm",
#endif
#if defined(VIDEO_SDL)
"SDL",
#endif
"None"};
}

View File

@ -1,132 +0,0 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
#include <X11/extensions/XShm.h>
#include <SDL/SDL.h>
struct VideoSDL : Video {
VideoSDL() { initialize(); }
~VideoSDL() { terminate(); }
auto ready() -> bool { return _ready; }
auto context() -> uintptr { return _context; }
auto setContext(uintptr context) -> bool {
if(_context == context) return true;
_context = context;
return initialize();
}
auto clear() -> void {
if(!ready()) return;
if(SDL_MUSTLOCK(_buffer)) SDL_LockSurface(_buffer);
for(uint y : range(_bufferHeight)) {
uint32_t* data = (uint32_t*)_buffer->pixels + y * (_buffer->pitch >> 2);
for(uint x : range(_bufferWidth)) *data++ = 0xff000000;
}
if(SDL_MUSTLOCK(_buffer)) SDL_UnlockSurface(_buffer);
output();
}
auto lock(uint32_t*& data, uint& pitch, uint width, uint height) -> bool {
if(!ready()) return false;
if(width != _width || height != _height) resize(_width = width, _height = height);
if(SDL_MUSTLOCK(_buffer)) SDL_LockSurface(_buffer);
pitch = _buffer->pitch;
return data = (uint32_t*)_buffer->pixels;
}
auto unlock() -> void {
if(!ready()) return;
if(SDL_MUSTLOCK(_buffer)) SDL_UnlockSurface(_buffer);
}
auto output() -> void {
if(!ready()) return;
//ruby input is X8R8G8B8, top 8-bits are ignored.
//as SDL forces us to use a 32-bit buffer, we must set alpha to 255 (full opacity)
//to prevent blending against the window beneath when X window visual is 32-bits.
if(SDL_MUSTLOCK(_buffer)) SDL_LockSurface(_buffer);
for(uint y : range(_height)) {
uint32_t* data = (uint32_t*)_buffer->pixels + y * (_buffer->pitch >> 2);
for(uint x : range(_width)) *data++ |= 0xff000000;
}
if(SDL_MUSTLOCK(_buffer)) SDL_UnlockSurface(_buffer);
XWindowAttributes attributes;
XGetWindowAttributes(_display, _context, &attributes);
SDL_Rect source;
SDL_Rect target;
source.x = 0;
source.y = 0;
source.w = _width;
source.h = _height;
target.x = 0;
target.y = 0;
target.w = attributes.width;
target.h = attributes.height;
SDL_SoftStretch(_buffer, &source, _screen, &target);
SDL_UpdateRect(_screen, target.x, target.y, target.w, target.h);
}
private:
auto initialize() -> bool {
terminate();
if(!_context) return false;
_display = XOpenDisplay(0);
char env[512];
sprintf(env, "SDL_WINDOWID=%ld", (long)_context);
putenv(env);
SDL_InitSubSystem(SDL_INIT_VIDEO);
_screen = SDL_SetVideoMode(2560, 1600, 32, SDL_HWSURFACE);
XUndefineCursor(_display, _context);
_buffer = nullptr;
_bufferWidth = 0;
_bufferHeight = 0;
resize(_width = 256, _height = 256);
return _ready = true;
}
auto terminate() -> void {
_ready = false;
if(_buffer) SDL_FreeSurface(_buffer), _buffer = nullptr;
if(_screen) SDL_QuitSubSystem(SDL_INIT_VIDEO), _screen = nullptr;
if(_display) XCloseDisplay(_display), _display = nullptr;
}
auto resize(uint width, uint height) -> void {
if(_bufferWidth >= width && _bufferHeight >= height) return;
_bufferWidth = max(width, _bufferWidth);
_bufferHeight = max(height, _bufferHeight);
if(_buffer) SDL_FreeSurface(_buffer);
_buffer = SDL_CreateRGBSurface(
SDL_SWSURFACE, _bufferWidth, _bufferHeight, 32,
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000
);
}
bool _ready = false;
uintptr _context = 0;
Display* _display = nullptr;
SDL_Surface* _screen = nullptr;
SDL_Surface* _buffer = nullptr;
uint _bufferWidth = 0;
uint _bufferHeight = 0;
uint _width = 0;
uint _height = 0;
};