Files

124 lines
3.0 KiB
C++

#include <algorithm>
#include "Input.h"
#include "hostVmShared.h"
#include "PicoRam.h"
Input::Input(PicoRam* memory):
_currentKDown(0),
_currentKHeld(0)
{
_memory = memory;
std::fill(_framesHeld, _framesHeld + 8, 0);
}
void Input::SetState(uint8_t kdown, uint8_t kheld){
_currentKDown = kdown;
_currentKHeld = kheld;
//key 6 (PAUSE MENU) only fires for one frame, even if held
if ((_currentKHeld & BITMASK(6)) && !(_currentKDown & BITMASK(6))) {
_currentKHeld = _currentKHeld & ~(BITMASK(6));
}
//memory only stores buttons 0-5, not 6 or 7
_memory->hwState.buttonStates[0] = kheld & 0x3F;
uint8_t repeatDelay = _memory->hwState.btnpRepeatDelay == 0
? 15
: _memory->hwState.btnpRepeatDelay;
if (repeatDelay == 255){
return;
}
uint8_t repeatInterval = _memory->hwState.btnpRepeatInterval == 0
? 4
: _memory->hwState.btnpRepeatDelay;
for (int i = 0; i < 7; i ++) {
bool down = BITMASK(i) & kheld;
_framesHeld[i] = down ? _framesHeld[i] + 1 : 0;
//update kdown to be true if held for 15 frames, then every 4th after that.
//from wiki:
//btnp() implements a keyboard-like repeat mechanism: if the player holds
//the button for 15 frames, it registers as on again for one frame, then
//again every four frames after that. The frame counter resets when the
//player releases the button.
bool repeatPressed =
(_framesHeld[i] == repeatDelay) ||
(_framesHeld[i] / repeatDelay >= 1 && _framesHeld[i] % repeatInterval == 0);
if (repeatPressed) {
_currentKDown = _currentKDown | BITMASK(i);
}
}
}
void Input::SetMouse(int16_t mouseX, int16_t mouseY, uint8_t mouseBtnState){
_mouseX = mouseX;
_mouseY = mouseY;
_mouseBtnState = mouseBtnState;
}
void Input::SetKeyboard(bool kbDown, std::string kbKey){
_kbDown = kbDown;
_kbKey = kbKey;
}
uint8_t Input::btn(){
return _currentKHeld;
}
//todo: repetition behavior to match pico 8
uint8_t Input::btnp(){
return _currentKDown;
}
bool Input::btn(uint8_t i){
return BITMASK(i) & btn();
}
//todo: repetition behavior to match pico 8
bool Input::btnp(uint8_t i){
return BITMASK(i) & btnp();
}
bool Input::btn(uint8_t i, uint8_t p){
//no multiplayer support for now
return p == 0 ? btn(i) : 0;
}
//todo: repetition behavior to match pico 8
bool Input::btnp(uint8_t i, uint8_t p){
//no multiplayer support for now
return p == 0 ? btnp(i) : 0;
}
int16_t Input::getMouseX() {
return _mouseX;
}
int16_t Input::getMouseY() {
return _mouseY;
}
uint8_t Input::getMouseBtnState() {
return _mouseBtnState;
}
bool Input::getKeyDown() {
return _kbDown;
}
const char* Input::getKey() {
// Found this bug in Terra
// PICO-8 behavior: stat(31) appears to consume the key from the buffer
// After reading, stat(30) should return false until next key press
_kbDown = false;
return _kbKey.c_str();
}