2015-03-02 09:13:28 +00:00
|
|
|
#include "../tomoko.hpp"
|
2015-04-13 11:16:33 +00:00
|
|
|
#include "hotkeys.cpp"
|
Update to v097r02 release.
byuu says:
Note: balanced/performance profiles still broken, sorry.
Changelog:
- added nall/GNUmakefile unique() function; used on linking phase of
higan
- added nall/unique_pointer
- target-tomoko and {System}::Video updated to use
unique_pointer<ClassName> instead of ClassName* [1]
- locate() updated to search multiple paths [2]
- GB: pass gekkio's if_ie_registers and boot_hwio-G test ROMs
- FC, GB, GBA: merge video/ into the PPU cores
- ruby: fixed ~AudioXAudio2() typo
[1] I expected this to cause new crashes on exit due to changing the
order of destruction of objects (and deleting things that weren't
deleted before), but ... so far, so good. I guess we'll see what crops
up, especially on OS X (which is already crashing for unknown reasons on
exit.)
[2] right now, the search paths are: programpath(), {configpath(),
"higan/"}, {localpath(), "higan/"}; but we can add as many more as we
want, and we can also add platform-specific versions.
2016-01-25 11:27:18 +00:00
|
|
|
unique_pointer<InputManager> inputManager;
|
2015-03-02 09:13:28 +00:00
|
|
|
|
|
|
|
auto InputMapping::bind() -> void {
|
|
|
|
auto token = assignment.split("/");
|
2015-05-23 05:29:18 +00:00
|
|
|
if(token.size() < 3) return unbind();
|
2015-12-21 09:16:47 +00:00
|
|
|
uint64 id = token[0].natural();
|
|
|
|
uint group = token[1].natural();
|
|
|
|
uint input = token[2].natural();
|
2015-05-23 05:29:18 +00:00
|
|
|
string qualifier = token(3, "None");
|
2015-03-02 09:13:28 +00:00
|
|
|
|
|
|
|
for(auto& device : inputManager->devices) {
|
2015-05-24 09:44:28 +00:00
|
|
|
if(id != device->id()) continue;
|
2015-03-02 09:13:28 +00:00
|
|
|
|
|
|
|
this->device = device;
|
|
|
|
this->group = group;
|
|
|
|
this->input = input;
|
2015-05-23 05:29:18 +00:00
|
|
|
this->qualifier = Qualifier::None;
|
|
|
|
if(qualifier == "Lo") this->qualifier = Qualifier::Lo;
|
|
|
|
if(qualifier == "Hi") this->qualifier = Qualifier::Hi;
|
|
|
|
if(qualifier == "Rumble") this->qualifier = Qualifier::Rumble;
|
2015-03-02 09:13:28 +00:00
|
|
|
break;
|
|
|
|
}
|
2015-11-16 08:38:05 +00:00
|
|
|
|
|
|
|
settings[path].setValue(assignment);
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
|
2015-12-21 09:16:47 +00:00
|
|
|
auto InputMapping::bind(shared_pointer<HID::Device> device, uint group, uint input, int16 oldValue, int16 newValue) -> bool {
|
2015-05-24 09:44:28 +00:00
|
|
|
if(device->isNull() || (device->isKeyboard() && device->group(group).input(input).name() == "Escape")) {
|
2015-05-23 05:29:18 +00:00
|
|
|
return unbind(), true;
|
|
|
|
}
|
|
|
|
|
2015-05-24 09:44:28 +00:00
|
|
|
string encoding = {"0x", hex(device->id()), "/", group, "/", input};
|
2015-05-23 05:29:18 +00:00
|
|
|
|
|
|
|
if(isDigital()) {
|
2015-05-24 09:44:28 +00:00
|
|
|
if((device->isKeyboard() && group == HID::Keyboard::GroupID::Button)
|
|
|
|
|| (device->isMouse() && group == HID::Mouse::GroupID::Button)
|
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Button)) {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(newValue) {
|
|
|
|
this->assignment = encoding;
|
|
|
|
return bind(), true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-24 09:44:28 +00:00
|
|
|
if((device->isJoypad() && group == HID::Joypad::GroupID::Axis)
|
2015-08-24 09:42:11 +00:00
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Hat)
|
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Trigger)) {
|
|
|
|
if(newValue < -16384 && group != HID::Joypad::GroupID::Trigger) { //triggers are always hi
|
2015-05-23 05:29:18 +00:00
|
|
|
this->assignment = {encoding, "/Lo"};
|
|
|
|
return bind(), true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(newValue > +16384) {
|
|
|
|
this->assignment = {encoding, "/Hi"};
|
|
|
|
return bind(), true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isAnalog()) {
|
2015-05-24 09:44:28 +00:00
|
|
|
if((device->isMouse() && group == HID::Mouse::GroupID::Axis)
|
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Axis)
|
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Hat)) {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(newValue < -16384 || newValue > +16384) {
|
|
|
|
this->assignment = encoding;
|
|
|
|
return bind(), true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Update to v094r13 release.
byuu says:
This version polishes up the input dialogue (reset, erase, disable
button when item not focused, split device ID from mapping name), adds
color emulation toggle, and add dummy menu items for remaining features
(to be filled in later.)
Also, it now compiles cleanly on Windows with GTK.
I didn't test with TDM-GCC-32, because for god knows what reason, the
32-bit version ships with headers from Windows 95 OSR2 only. So I built
with TDM-GCC-64 with arch=x86.
And uh, apparently, moving or resizing a window causes a Visual C++
runtime exception in the GTK+ DLLs. This doesn't happen with trance or
renshuu built with TDM-GCC-32. So, yeah, like I said, don't use -m32.
2015-03-07 10:21:47 +00:00
|
|
|
|
2015-05-23 05:29:18 +00:00
|
|
|
if(isRumble()) {
|
2015-05-24 09:44:28 +00:00
|
|
|
if(device->isJoypad() && group == HID::Joypad::GroupID::Button) {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(newValue) {
|
2015-08-24 09:42:11 +00:00
|
|
|
this->assignment = {encoding, "/Rumble"};
|
2015-05-23 05:29:18 +00:00
|
|
|
return bind(), true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto InputMapping::poll() -> int16 {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(!device) return 0;
|
2015-05-24 09:44:28 +00:00
|
|
|
auto value = device->group(group).input(input).value();
|
2015-05-23 05:29:18 +00:00
|
|
|
|
|
|
|
if(isDigital()) {
|
|
|
|
if(device->isKeyboard() && group == HID::Keyboard::GroupID::Button) return value != 0;
|
|
|
|
if(device->isMouse() && group == HID::Mouse::GroupID::Button) return value != 0;
|
|
|
|
if(device->isJoypad() && group == HID::Joypad::GroupID::Button) return value != 0;
|
|
|
|
if((device->isJoypad() && group == HID::Joypad::GroupID::Axis)
|
2015-08-24 09:42:11 +00:00
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Hat)
|
|
|
|
|| (device->isJoypad() && group == HID::Joypad::GroupID::Trigger)) {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(qualifier == Qualifier::Lo) return value < -16384;
|
|
|
|
if(qualifier == Qualifier::Hi) return value > +16384;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isAnalog()) {
|
|
|
|
if(device->isMouse() && group == HID::Mouse::GroupID::Axis) return value;
|
|
|
|
if(device->isJoypad() && group == HID::Joypad::GroupID::Axis) return value >> 8;
|
|
|
|
if(device->isJoypad() && group == HID::Joypad::GroupID::Hat) return value < 0 ? -1 : value > 0 ? +1 : 0;
|
|
|
|
}
|
|
|
|
|
2015-03-02 09:13:28 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-08-24 09:42:11 +00:00
|
|
|
auto InputMapping::rumble(bool enable) -> void {
|
|
|
|
if(!device) return;
|
|
|
|
::input->rumble(device->id(), enable);
|
|
|
|
}
|
|
|
|
|
Update to v094r13 release.
byuu says:
This version polishes up the input dialogue (reset, erase, disable
button when item not focused, split device ID from mapping name), adds
color emulation toggle, and add dummy menu items for remaining features
(to be filled in later.)
Also, it now compiles cleanly on Windows with GTK.
I didn't test with TDM-GCC-32, because for god knows what reason, the
32-bit version ships with headers from Windows 95 OSR2 only. So I built
with TDM-GCC-64 with arch=x86.
And uh, apparently, moving or resizing a window causes a Visual C++
runtime exception in the GTK+ DLLs. This doesn't happen with trance or
renshuu built with TDM-GCC-32. So, yeah, like I said, don't use -m32.
2015-03-07 10:21:47 +00:00
|
|
|
auto InputMapping::unbind() -> void {
|
2015-11-16 08:38:05 +00:00
|
|
|
assignment = "None";
|
|
|
|
device = nullptr;
|
|
|
|
group = 0;
|
|
|
|
input = 0;
|
|
|
|
qualifier = Qualifier::None;
|
|
|
|
settings[path].setValue(assignment);
|
2015-05-23 05:29:18 +00:00
|
|
|
}
|
|
|
|
|
2015-05-24 09:44:28 +00:00
|
|
|
auto InputMapping::assignmentName() -> string {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(!device) return "None";
|
|
|
|
string path;
|
2015-05-24 09:44:28 +00:00
|
|
|
path.append(device->name());
|
Update to v097r02 release.
byuu says:
Note: balanced/performance profiles still broken, sorry.
Changelog:
- added nall/GNUmakefile unique() function; used on linking phase of
higan
- added nall/unique_pointer
- target-tomoko and {System}::Video updated to use
unique_pointer<ClassName> instead of ClassName* [1]
- locate() updated to search multiple paths [2]
- GB: pass gekkio's if_ie_registers and boot_hwio-G test ROMs
- FC, GB, GBA: merge video/ into the PPU cores
- ruby: fixed ~AudioXAudio2() typo
[1] I expected this to cause new crashes on exit due to changing the
order of destruction of objects (and deleting things that weren't
deleted before), but ... so far, so good. I guess we'll see what crops
up, especially on OS X (which is already crashing for unknown reasons on
exit.)
[2] right now, the search paths are: programpath(), {configpath(),
"higan/"}, {localpath(), "higan/"}; but we can add as many more as we
want, and we can also add platform-specific versions.
2016-01-25 11:27:18 +00:00
|
|
|
if(device->name() != "Keyboard") {
|
|
|
|
//keyboards only have one group; no need to append group name
|
|
|
|
path.append(".", device->group(group).name());
|
|
|
|
}
|
2015-05-24 09:44:28 +00:00
|
|
|
path.append(".", device->group(group).input(input).name());
|
2015-05-23 05:29:18 +00:00
|
|
|
if(qualifier == Qualifier::Lo) path.append(".Lo");
|
|
|
|
if(qualifier == Qualifier::Hi) path.append(".Hi");
|
|
|
|
if(qualifier == Qualifier::Rumble) path.append(".Rumble");
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2015-05-24 09:44:28 +00:00
|
|
|
auto InputMapping::deviceName() -> string {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(!device) return "";
|
2015-05-24 09:44:28 +00:00
|
|
|
return hex(device->id());
|
Update to v094r13 release.
byuu says:
This version polishes up the input dialogue (reset, erase, disable
button when item not focused, split device ID from mapping name), adds
color emulation toggle, and add dummy menu items for remaining features
(to be filled in later.)
Also, it now compiles cleanly on Windows with GTK.
I didn't test with TDM-GCC-32, because for god knows what reason, the
32-bit version ships with headers from Windows 95 OSR2 only. So I built
with TDM-GCC-64 with arch=x86.
And uh, apparently, moving or resizing a window causes a Visual C++
runtime exception in the GTK+ DLLs. This doesn't happen with trance or
renshuu built with TDM-GCC-32. So, yeah, like I said, don't use -m32.
2015-03-07 10:21:47 +00:00
|
|
|
}
|
|
|
|
|
2015-03-02 09:13:28 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
InputManager::InputManager() {
|
|
|
|
inputManager = this;
|
Update to v100r16 release.
byuu says:
(Windows users may need to include <sys/time.h> at the top of
nall/chrono.hpp, not sure.)
Unchangelog:
- forgot to add the Scheduler clock=0 fix because I have the memory of
a goldfish
Changelog:
- new icarus database with nine additional games
- hiro(GTK,Qt) won't constantly write its settings.bml file to disk
anymore
- added latency simulator for fun (settings.bml => Input/Latency in
milliseconds)
So the last one ... I wanted to test out nall::chrono, and I was also
thinking that by polling every emulated frame, it's pretty wasteful when
you are using Fast Forward and hitting 200+fps. As I've said before,
calls to ruby::input::poll are not cheap.
So to get around this, I added a limiter so that if you called the
hardware poll function within N milliseconds, it'll return without
doing any actual work. And indeed, that increases my framerate of Zelda
3 uncapped from 133fps to 142fps. Yay. But it's not a "real" speedup,
as it only helps you when you exceed 100% speed (theoretically, you'd
need to crack 300% speed since the game itself will poll at 16ms at 100%
speed, but yet it sped up Zelda 3, so who am I to complain?)
I threw the latency value into the settings file. It should be 16,
but I set it to 5 since that was the lowest before it started negatively
impacting uncapped speeds. You're wasting your time and CPU cycles setting
it lower than 5, but if people like placebo effects it might work. Maybe
I should let it be a signed integer so people can set it to -16 and think
it's actually faster :P (I'm only joking. I took out the 96000hz audio
placebo effect as well. Not really into psychological tricks anymore.)
But yeah seriously, I didn't do this to start this discussion again for
the billionth time. Please don't go there. And please don't tell me this
WIP has higher/lower latency than before. I don't want to hear it.
The only reason I bring it up is for the fun part that is worth
discussing: put up or shut up time on how sensitive you are to
latency! You can set the value above 5 to see how games feel.
I personally can't really tell a difference until about 50. And I can't
be 100% confident it's worse until about 75. But ... when I set it to
150, games become "extra difficult" ... the higher it goes, the worse
it gets :D
For this WIP, I've left no upper limit cap. I'll probably set a cap of
something like 500ms or 1000ms for the official release. Need to balance
user error/trolling with enjoyability. I'll think about it.
[...]
Now, what I worry about is stupid people seeing it and thinking it's an
"added latency" setting, as if anyone would intentionally make things
worse by default. This is a limiter. So if 5ms have passed since the
game last polled, and that will be the case 99.9% of the time in games,
the next poll will happen just in time, immediately when the game polls
the inputs. Thus, a value below 1/<framerate>ms is not only pointless,
if you go too low it will ruin your fast forward max speeds.
I did say I didn't want to resort to placebo tricks, but I also don't
want to spark up public discussion on this again either. So it might
be best to default Input/Latency to 0ms, and internally have a max(5,
latency) wrapper around the value.
2016-08-03 12:32:40 +00:00
|
|
|
latency = max(1u, settings["Input/Latency"].natural());
|
2015-03-02 09:13:28 +00:00
|
|
|
|
|
|
|
for(auto& emulator : program->emulators) {
|
2016-06-26 08:54:12 +00:00
|
|
|
auto& inputEmulator = emulators(emulators.size());
|
|
|
|
inputEmulator.interface = emulator;
|
2015-03-02 09:13:28 +00:00
|
|
|
inputEmulator.name = emulator->information.name;
|
|
|
|
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
for(auto& port : emulator->ports) {
|
2016-06-25 08:53:11 +00:00
|
|
|
auto& inputPort = inputEmulator.ports(port.id);
|
2015-03-02 09:13:28 +00:00
|
|
|
inputPort.name = port.name;
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
for(auto& device : port.devices) {
|
2016-06-25 08:53:11 +00:00
|
|
|
auto& inputDevice = inputPort.devices(device.id);
|
2015-03-02 09:13:28 +00:00
|
|
|
inputDevice.name = device.name;
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
for(auto& input : device.inputs) {
|
2016-06-26 08:54:12 +00:00
|
|
|
auto& inputMapping = inputDevice.mappings(inputDevice.mappings.size());
|
|
|
|
inputMapping.name = input.name;
|
|
|
|
inputMapping.type = input.type;
|
2016-06-25 08:53:11 +00:00
|
|
|
|
2016-06-26 08:54:12 +00:00
|
|
|
inputMapping.path = string{inputEmulator.name, "/", inputPort.name, "/", inputDevice.name, "/", inputMapping.name}.replace(" ", "");
|
|
|
|
inputMapping.assignment = settings(inputMapping.path).text();
|
|
|
|
inputMapping.bind();
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-13 11:16:33 +00:00
|
|
|
appendHotkeys();
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
|
2016-06-26 08:54:12 +00:00
|
|
|
//Emulator::Interface::inputPoll() needs to call into InputManager::InputEmulator
|
|
|
|
//this function is calling during Program::loadMedium() to link the two together
|
|
|
|
auto InputManager::bind(Emulator::Interface* interface) -> void {
|
|
|
|
this->emulator = nullptr;
|
|
|
|
for(auto& emulator : emulators) {
|
|
|
|
if(emulator.interface == interface) {
|
|
|
|
this->emulator = &emulator;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(this->emulator != nullptr);
|
|
|
|
}
|
|
|
|
|
2015-03-02 09:13:28 +00:00
|
|
|
auto InputManager::bind() -> void {
|
|
|
|
for(auto& emulator : emulators) {
|
|
|
|
for(auto& port : emulator.ports) {
|
|
|
|
for(auto& device : port.devices) {
|
|
|
|
for(auto& mapping : device.mappings) {
|
2016-06-26 08:54:12 +00:00
|
|
|
mapping.bind();
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-13 11:16:33 +00:00
|
|
|
|
|
|
|
for(auto& hotkey : hotkeys) {
|
|
|
|
hotkey->bind();
|
|
|
|
}
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto InputManager::poll() -> void {
|
Update to v100r16 release.
byuu says:
(Windows users may need to include <sys/time.h> at the top of
nall/chrono.hpp, not sure.)
Unchangelog:
- forgot to add the Scheduler clock=0 fix because I have the memory of
a goldfish
Changelog:
- new icarus database with nine additional games
- hiro(GTK,Qt) won't constantly write its settings.bml file to disk
anymore
- added latency simulator for fun (settings.bml => Input/Latency in
milliseconds)
So the last one ... I wanted to test out nall::chrono, and I was also
thinking that by polling every emulated frame, it's pretty wasteful when
you are using Fast Forward and hitting 200+fps. As I've said before,
calls to ruby::input::poll are not cheap.
So to get around this, I added a limiter so that if you called the
hardware poll function within N milliseconds, it'll return without
doing any actual work. And indeed, that increases my framerate of Zelda
3 uncapped from 133fps to 142fps. Yay. But it's not a "real" speedup,
as it only helps you when you exceed 100% speed (theoretically, you'd
need to crack 300% speed since the game itself will poll at 16ms at 100%
speed, but yet it sped up Zelda 3, so who am I to complain?)
I threw the latency value into the settings file. It should be 16,
but I set it to 5 since that was the lowest before it started negatively
impacting uncapped speeds. You're wasting your time and CPU cycles setting
it lower than 5, but if people like placebo effects it might work. Maybe
I should let it be a signed integer so people can set it to -16 and think
it's actually faster :P (I'm only joking. I took out the 96000hz audio
placebo effect as well. Not really into psychological tricks anymore.)
But yeah seriously, I didn't do this to start this discussion again for
the billionth time. Please don't go there. And please don't tell me this
WIP has higher/lower latency than before. I don't want to hear it.
The only reason I bring it up is for the fun part that is worth
discussing: put up or shut up time on how sensitive you are to
latency! You can set the value above 5 to see how games feel.
I personally can't really tell a difference until about 50. And I can't
be 100% confident it's worse until about 75. But ... when I set it to
150, games become "extra difficult" ... the higher it goes, the worse
it gets :D
For this WIP, I've left no upper limit cap. I'll probably set a cap of
something like 500ms or 1000ms for the official release. Need to balance
user error/trolling with enjoyability. I'll think about it.
[...]
Now, what I worry about is stupid people seeing it and thinking it's an
"added latency" setting, as if anyone would intentionally make things
worse by default. This is a limiter. So if 5ms have passed since the
game last polled, and that will be the case 99.9% of the time in games,
the next poll will happen just in time, immediately when the game polls
the inputs. Thus, a value below 1/<framerate>ms is not only pointless,
if you go too low it will ruin your fast forward max speeds.
I did say I didn't want to resort to placebo tricks, but I also don't
want to spark up public discussion on this again either. So it might
be best to default Input/Latency to 0ms, and internally have a max(5,
latency) wrapper around the value.
2016-08-03 12:32:40 +00:00
|
|
|
//polling actual hardware is very time-consuming: skip call if poll was called too recently
|
|
|
|
auto thisPoll = chrono::millisecond();
|
|
|
|
if(thisPoll - lastPoll < latency) return;
|
|
|
|
lastPoll = thisPoll;
|
|
|
|
|
2015-06-20 05:44:05 +00:00
|
|
|
auto devices = input->poll();
|
2015-03-02 09:13:28 +00:00
|
|
|
bool changed = devices.size() != this->devices.size();
|
2016-06-26 08:54:12 +00:00
|
|
|
if(!changed) {
|
2015-03-02 09:13:28 +00:00
|
|
|
for(auto n : range(devices)) {
|
|
|
|
changed = devices[n] != this->devices[n];
|
|
|
|
if(changed) break;
|
|
|
|
}
|
|
|
|
}
|
2016-06-26 08:54:12 +00:00
|
|
|
if(changed) {
|
2015-03-02 09:13:28 +00:00
|
|
|
this->devices = devices;
|
|
|
|
bind();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Update to v097r14 release.
byuu says:
This is a few days old, but oh well.
This WIP changes nall,hiro,ruby,icarus back to (u)int(8,16,32,64)_t.
I'm slowly pushing for (u)int(8,16,32,64) to use my custom
Integer<Size>/Natural<Size> classes instead. But it's going to be one
hell of a struggle to get that into higan.
2016-02-16 09:11:58 +00:00
|
|
|
auto InputManager::onChange(shared_pointer<HID::Device> device, uint group, uint input, int16_t oldValue, int16_t newValue) -> void {
|
2015-03-02 09:13:28 +00:00
|
|
|
if(settingsManager->focused()) {
|
|
|
|
settingsManager->input.inputEvent(device, group, input, oldValue, newValue);
|
2015-04-13 11:16:33 +00:00
|
|
|
settingsManager->hotkeys.inputEvent(device, group, input, oldValue, newValue);
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto InputManager::quit() -> void {
|
2015-04-13 11:16:33 +00:00
|
|
|
emulators.reset();
|
|
|
|
hotkeys.reset();
|
2015-03-02 09:13:28 +00:00
|
|
|
}
|
2015-05-23 05:29:18 +00:00
|
|
|
|
2015-05-24 09:44:28 +00:00
|
|
|
auto InputManager::findMouse() -> shared_pointer<HID::Device> {
|
|
|
|
for(auto& device : devices) {
|
2015-05-23 05:29:18 +00:00
|
|
|
if(device->isMouse()) return device;
|
|
|
|
}
|
2015-05-24 09:44:28 +00:00
|
|
|
return {};
|
2015-05-23 05:29:18 +00:00
|
|
|
}
|