#include "cartridge.cpp" #include "window.cpp" //returns true if requested code is a button, and it has just been pressed down bool Utility::isButtonDown(uint16_t inputCode, InputObject &object) { if(inputCode != object.code) return false; if(object.codetype != InputCode::KeyboardButton && object.codetype != InputCode::MouseButton && object.codetype != InputCode::JoypadHat && object.codetype != InputCode::JoypadAxis && object.codetype != InputCode::JoypadButton) return false; int16_t state = inputManager.state(object.code); int16_t lastState = inputManager.lastState(object.code); if(object.codetype == InputCode::JoypadHat) { switch(object.modifier) { case InputObject::Up: return (state & joypad<>::hat_up ) && !(lastState & joypad<>::hat_up ); case InputObject::Down: return (state & joypad<>::hat_down ) && !(lastState & joypad<>::hat_down ); case InputObject::Left: return (state & joypad<>::hat_left ) && !(lastState & joypad<>::hat_left ); case InputObject::Right: return (state & joypad<>::hat_right) && !(lastState & joypad<>::hat_right); } } else if(object.codetype == InputCode::JoypadAxis) { switch(object.modifier) { case InputObject::Lo: return (state < -16384) && !(lastState < -16384); case InputObject::Hi: return (state > +16384) && !(lastState > +16384); case InputObject::Trigger: return (state < 0) && !(lastState < 0); } } else { return (state == 1) && !(lastState == 1); } return false; //fall-through for modifier-less hats / axes } void Utility::inputEvent(uint16_t code) { //forward key-press event //(in case window is currently active and capturing a new button / axis assignment) winInputCapture->inputEvent(code); //if escape key is pressed on *any* keyboard; release the mouse if it is acquired for(unsigned i = 0; i < keyboard<>::count; i++) { if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code) && input.acquired()) { input.unacquire(); return; //do not trigger other UI actions that may be bound to escape key } } if(winMain->window->isActiveWindow()) { bool resizeWindow = false; if(isButtonDown(code, inputUiGeneral.loadCartridge)) { string filename = selectCartridge(); if(filename.length() > 0) loadCartridge(filename); } if(isButtonDown(code, inputUiGeneral.pauseEmulation)) { application.pause = !application.pause; } if(isButtonDown(code, inputUiGeneral.resetSystem)) { modifySystemState(Reset); } if(isButtonDown(code, inputUiGeneral.powerCycleSystem)) { modifySystemState(PowerCycle); } if(isButtonDown(code, inputUiGeneral.lowerSpeed)) { config.system.speed--; updateEmulationSpeed(); winMain->syncUi(); } if(isButtonDown(code, inputUiGeneral.raiseSpeed)) { config.system.speed++; updateEmulationSpeed(); winMain->syncUi(); } if(isButtonDown(code, inputUiGeneral.toggleCheatSystem)) { if(cheat.enabled() == false) { cheat.enable(); showMessage("Cheat system enabled."); } else { cheat.disable(); showMessage("Cheat system disabled."); } } if(isButtonDown(code, inputUiGeneral.toggleFullscreen)) { config.video.isFullscreen = !config.video.isFullscreen; updateFullscreenState(); winMain->syncUi(); } if(isButtonDown(code, inputUiGeneral.toggleMenu)) { winMain->window->menuBar()->setVisible(!winMain->window->menuBar()->isVisibleTo(winMain->window)); resizeWindow = true; } if(isButtonDown(code, inputUiGeneral.toggleStatus)) { winMain->window->statusBar()->setVisible(!winMain->window->statusBar()->isVisibleTo(winMain->window)); resizeWindow = true; } //prevent calling twice when toggleMenu == toggleStatus if(resizeWindow == true) { resizeMainWindow(); } if(isButtonDown(code, inputUiGeneral.exitEmulator)) { application.terminate = true; } } } //display message in main window statusbar area for three seconds void Utility::showMessage(const char *message) { winMain->window->statusBar()->showMessage(utf8() << message, 3000); } //updates system state text at bottom-right of main window statusbar void Utility::updateSystemState() { string text; if(cartridge.loaded() == false) { text = "No cartridge loaded"; } else if(application.power == false) { text = "Power off"; } else if(application.pause == true || application.autopause == true) { text = "Paused"; } else if(ppu.status.frames_updated == true) { ppu.status.frames_updated = false; text << (int)ppu.status.frames_executed; text << " fps"; } else { //nothing to update return; } winMain->systemState->setText(utf8() << text); } void Utility::acquireMouse() { if(cartridge.loaded()) { if(snes.config.controller_port1 == SNES::Input::DeviceMouse || snes.config.controller_port2 == SNES::Input::DeviceMouse || snes.config.controller_port2 == SNES::Input::DeviceSuperScope || snes.config.controller_port2 == SNES::Input::DeviceJustifier || snes.config.controller_port2 == SNES::Input::DeviceJustifiers ) input.acquire(); } } void Utility::unacquireMouse() { input.unacquire(); } void Utility::updateAvSync() { video.set(Video::Synchronize, config.video.synchronize); audio.set(Audio::Synchronize, config.audio.synchronize); } void Utility::updateVideoMode() { if(config.video.context->region == 0) { snes.video.set_mode(SNES::Video::ModeNTSC); } else { snes.video.set_mode(SNES::Video::ModePAL); } } void Utility::updateColorFilter() { libfilter::colortable.set_format(libfilter::Colortable::RGB888); libfilter::colortable.set_contrast(config.video.contrastAdjust); libfilter::colortable.set_brightness(config.video.brightnessAdjust); libfilter::colortable.set_gamma(100 + config.video.gammaAdjust); libfilter::colortable.enable_gamma_ramp(config.video.enableGammaRamp); libfilter::colortable.update(); } void Utility::updateHardwareFilter() { video.set(Video::Filter, config.video.context->hwFilter); } void Utility::updateSoftwareFilter() { libfilter::FilterInterface::FilterType type; switch(config.video.context->swFilter) { default: case 0: type = libfilter::FilterInterface::Direct; break; case 1: type = libfilter::FilterInterface::Scanline; break; case 2: type = libfilter::FilterInterface::Scale2x; break; case 3: type = libfilter::FilterInterface::HQ2x; break; case 4: type = libfilter::FilterInterface::NTSC; break; } libfilter::filter.set(type); if(type == libfilter::FilterInterface::NTSC) { libfilter::filter_ntsc.adjust(0, 0, 0, 0, 0, config.video.enableNtscMergeFields); } } void Utility::updateEmulationSpeed() { config.system.speed = max(0, min(4, (signed)config.system.speed)); double scale[] = { 0.50, 0.75, 1.00, 1.50, 2.00 }; unsigned outfreq = config.audio.outputFrequency; unsigned infreq = config.audio.inputFrequency * scale[config.system.speed] + 0.5; audio.set(Audio::Resample, outfreq != infreq); //only resample when necessary audio.set(Audio::ResampleOutputFrequency, outfreq); audio.set(Audio::ResampleInputFrequency, infreq); } void Utility::updateControllers() { snes.input.port_set_device(0, snes.config.controller_port1); snes.input.port_set_device(1, snes.config.controller_port2); }