Added joypad button override functionality to JS API.

This commit is contained in:
harry 2024-02-15 22:04:11 -05:00
parent f85f93c5bd
commit af9b53ba75
3 changed files with 206 additions and 42 deletions

View File

@ -101,6 +101,11 @@ ColorScriptObject::~ColorScriptObject()
//---- Joypad Object //---- Joypad Object
//---------------------------------------------------- //----------------------------------------------------
int JoypadScriptObject::numInstances = 0; int JoypadScriptObject::numInstances = 0;
/* Joypad Override Logic True Table
11 - true 01 - pass-through (default)
00 - false 10 - invert */
uint8_t JoypadScriptObject::jsOverrideMask1[MAX_JOYPAD_PLAYERS]= { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t JoypadScriptObject::jsOverrideMask2[MAX_JOYPAD_PLAYERS]= { 0x00, 0x00, 0x00, 0x00 };
JoypadScriptObject::JoypadScriptObject(int playerIdx, bool immediate) JoypadScriptObject::JoypadScriptObject(int playerIdx, bool immediate)
: QObject() : QObject()
@ -132,35 +137,51 @@ JoypadScriptObject::~JoypadScriptObject()
//printf("JoypadScriptObject %p Destructor: %i\n", this, numInstances); //printf("JoypadScriptObject %p Destructor: %i\n", this, numInstances);
} }
//---------------------------------------------------- //----------------------------------------------------
uint8_t JoypadScriptObject::readOverride(int which, uint8_t joyl)
{
joyl = (joyl & jsOverrideMask1[which]) | (~joyl & jsOverrideMask2[which]);
jsOverrideMask1[which] = 0xFF;
jsOverrideMask2[which] = 0x00;
return joyl;
}
//----------------------------------------------------
void JoypadScriptObject::refreshData(bool immediate) void JoypadScriptObject::refreshData(bool immediate)
{ {
uint8_t buttons = 0;
if (immediate) if (immediate)
{ {
uint32_t gpData = GetGamepadPressedImmediate(); uint32_t gpData = GetGamepadPressedImmediate();
uint8_t buttons = gpData >> (player * 8); buttons = gpData >> (player * 8);
a = (buttons & 0x01) ? true : false;
b = (buttons & 0x02) ? true : false;
select = (buttons & 0x04) ? true : false;
start = (buttons & 0x08) ? true : false;
up = (buttons & 0x10) ? true : false;
down = (buttons & 0x20) ? true : false;
left = (buttons & 0x40) ? true : false;
right = (buttons & 0x80) ? true : false;
} }
else else
{ {
uint8_t buttons = joy[player]; buttons = joy[player];
a = (buttons & 0x01) ? true : false;
b = (buttons & 0x02) ? true : false;
select = (buttons & 0x04) ? true : false;
start = (buttons & 0x08) ? true : false;
up = (buttons & 0x10) ? true : false;
down = (buttons & 0x20) ? true : false;
left = (buttons & 0x40) ? true : false;
right = (buttons & 0x80) ? true : false;
} }
prev = current;
current.buttonMask = buttons;
current._immediate = immediate;
}
//----------------------------------------------------
bool JoypadScriptObject::getButton(enum Button b)
{
bool isPressed = false;
uint8_t mask = 0x01 << b;
//printf("mask=%08x buttons=%08x\n", mask, current.buttonMask);
isPressed = (current.buttonMask & mask) ? true : false;
return isPressed;
}
//----------------------------------------------------
bool JoypadScriptObject::buttonChanged(enum Button b)
{
bool hasChanged = false;
uint8_t mask = 0x01 << b;
//printf("mask=%08x buttons=%08x\n", mask, current.buttonMask);
hasChanged = ((current.buttonMask ^ prev.buttonMask) & mask) ? true : false;
return hasChanged;
} }
//---------------------------------------------------- //----------------------------------------------------
//---- EMU State Object //---- EMU State Object
@ -2610,4 +2631,9 @@ void QScriptDialog_t::logOutput(const QString& text)
} }
} }
//---------------------------------------------------- //----------------------------------------------------
uint8_t FCEU_JSReadJoypad(int which, uint8_t joyl)
{
return JS::JoypadScriptObject::readOverride(which, joyl);
}
//----------------------------------------------------
#endif // __FCEU_QSCRIPT_ENABLE__ #endif // __FCEU_QSCRIPT_ENABLE__

View File

@ -122,31 +122,160 @@ public:
~JoypadScriptObject(); ~JoypadScriptObject();
static constexpr int MAX_JOYPAD_PLAYERS = 4; static constexpr int MAX_JOYPAD_PLAYERS = 4;
enum Button
{
FIRST_BUTTON = 0,
A_BUTTON = FIRST_BUTTON,
B_BUTTON,
SELECT_BUTTON,
START_BUTTON,
UP_BUTTON,
DOWN_BUTTON,
LEFT_BUTTON,
RIGHT_BUTTON,
LAST_BUTTON = RIGHT_BUTTON,
END_BUTTON
};
Q_ENUM(Button);
// Joypad Override Function
static uint8_t readOverride(int which, uint8_t joyl);
private: private:
bool up = false; // Joypad Override Bit Masks
bool down = false; static uint8_t jsOverrideMask1[MAX_JOYPAD_PLAYERS];
bool left = false; static uint8_t jsOverrideMask2[MAX_JOYPAD_PLAYERS];
bool right = false;
bool select = false; struct buttonState
bool start = false; {
bool a = false; uint32_t buttonMask = 0;
bool b = false; bool _immediate = false;
};
buttonState current;
buttonState prev;
int player = 0; int player = 0;
static int numInstances; static int numInstances;
static constexpr uint32_t ButtonMaskA = 0x01;
static constexpr uint32_t ButtonMaskB = 0x02;
static constexpr uint32_t ButtonMaskSelect = 0x04;
static constexpr uint32_t ButtonMaskStart = 0x08;
static constexpr uint32_t ButtonMaskUp = 0x10;
static constexpr uint32_t ButtonMaskDown = 0x20;
static constexpr uint32_t ButtonMaskLeft = 0x40;
static constexpr uint32_t ButtonMaskRight = 0x80;
template <uint32_t mask> bool isBitSet(uint32_t& byte)
{
return (byte & mask) ? true : false;
}
template <uint32_t mask> bool isChanged()
{
return ((current.buttonMask ^ prev.buttonMask) & mask) ? true : false;
}
template <uint32_t mask> void setButtonOverride(bool value)
{
if (value)
{
jsOverrideMask1[player] |= mask;
jsOverrideMask2[player] |= mask;
}
else
{
jsOverrideMask1[player] &= ~mask;
jsOverrideMask2[player] &= ~mask;
}
}
template <uint32_t mask> void clearButtonOverride()
{
jsOverrideMask1[player] |= mask;
jsOverrideMask2[player] &= ~mask;
}
template <uint32_t mask> void invertButtonOverride()
{
jsOverrideMask1[player] &= ~mask;
jsOverrideMask2[player] |= mask;
}
public slots: public slots:
Q_INVOKABLE void refreshData(bool immediate = false); Q_INVOKABLE void refreshData(bool immediate = false);
Q_INVOKABLE bool getUp(){ return up; }
Q_INVOKABLE bool getDown(){ return down; } Q_INVOKABLE bool getUp(){ return isBitSet<ButtonMaskUp>(current.buttonMask); }
Q_INVOKABLE bool getLeft(){ return left; } Q_INVOKABLE bool getDown(){ return isBitSet<ButtonMaskDown>(current.buttonMask); }
Q_INVOKABLE bool getRight(){ return right; } Q_INVOKABLE bool getLeft(){ return isBitSet<ButtonMaskLeft>(current.buttonMask); }
Q_INVOKABLE bool getSelect(){ return select; } Q_INVOKABLE bool getRight(){ return isBitSet<ButtonMaskRight>(current.buttonMask); }
Q_INVOKABLE bool getStart(){ return start; } Q_INVOKABLE bool getSelect(){ return isBitSet<ButtonMaskSelect>(current.buttonMask); }
Q_INVOKABLE bool getA(){ return a; } Q_INVOKABLE bool getStart(){ return isBitSet<ButtonMaskStart>(current.buttonMask); }
Q_INVOKABLE bool getB(){ return b; } Q_INVOKABLE bool getA(){ return isBitSet<ButtonMaskA>(current.buttonMask); }
Q_INVOKABLE bool getB(){ return isBitSet<ButtonMaskB>(current.buttonMask); }
Q_INVOKABLE bool upChanged(){ return isChanged<ButtonMaskUp>(); }
Q_INVOKABLE bool downChanged(){ return isChanged<ButtonMaskDown>(); }
Q_INVOKABLE bool leftChanged(){ return isChanged<ButtonMaskLeft>(); }
Q_INVOKABLE bool rightChanged(){ return isChanged<ButtonMaskRight>(); }
Q_INVOKABLE bool selectChanged(){ return isChanged<ButtonMaskSelect>(); }
Q_INVOKABLE bool startChanged(){ return isChanged<ButtonMaskStart>(); }
Q_INVOKABLE bool aChanged(){ return isChanged<ButtonMaskA>(); }
Q_INVOKABLE bool bChanged(){ return isChanged<ButtonMaskB>(); }
Q_INVOKABLE bool isImmediate(){ return current._immediate; }
Q_INVOKABLE bool getButton(enum Button b);
Q_INVOKABLE bool buttonChanged(enum Button b);
Q_INVOKABLE bool stateChanged(){ return prev.buttonMask != current.buttonMask; }
Q_INVOKABLE void setState(int mask){ prev.buttonMask = current.buttonMask; current.buttonMask = mask; }
Q_INVOKABLE int getState(){ return current.buttonMask; }
Q_INVOKABLE int maxPlayers(){ return MAX_JOYPAD_PLAYERS; } Q_INVOKABLE int maxPlayers(){ return MAX_JOYPAD_PLAYERS; }
Q_INVOKABLE int getPlayer(){ return player; } Q_INVOKABLE int getPlayer(){ return player; }
Q_INVOKABLE void setPlayer(int newPlayerIdx){ player = newPlayerIdx; } Q_INVOKABLE void setPlayer(int newPlayerIdx){ player = newPlayerIdx; }
Q_INVOKABLE void ovrdClearA(){ clearButtonOverride<ButtonMaskA>(); }
Q_INVOKABLE void ovrdClearB(){ clearButtonOverride<ButtonMaskB>(); }
Q_INVOKABLE void ovrdClearStart(){ clearButtonOverride<ButtonMaskStart>(); }
Q_INVOKABLE void ovrdClearSelect(){ clearButtonOverride<ButtonMaskSelect>(); }
Q_INVOKABLE void ovrdClearUp(){ clearButtonOverride<ButtonMaskUp>(); }
Q_INVOKABLE void ovrdClearDown(){ clearButtonOverride<ButtonMaskDown>(); }
Q_INVOKABLE void ovrdClearLeft(){ clearButtonOverride<ButtonMaskLeft>(); }
Q_INVOKABLE void ovrdClearRight(){ clearButtonOverride<ButtonMaskRight>(); }
Q_INVOKABLE void ovrdClear(){ ovrdReset(); }
Q_INVOKABLE void ovrdInvertA(){ invertButtonOverride<ButtonMaskA>(); }
Q_INVOKABLE void ovrdInvertB(){ invertButtonOverride<ButtonMaskB>(); }
Q_INVOKABLE void ovrdInvertStart(){ invertButtonOverride<ButtonMaskStart>(); }
Q_INVOKABLE void ovrdInvertSelect(){ invertButtonOverride<ButtonMaskSelect>(); }
Q_INVOKABLE void ovrdInvertUp(){ invertButtonOverride<ButtonMaskUp>(); }
Q_INVOKABLE void ovrdInvertDown(){ invertButtonOverride<ButtonMaskDown>(); }
Q_INVOKABLE void ovrdInvertLeft(){ invertButtonOverride<ButtonMaskLeft>(); }
Q_INVOKABLE void ovrdInvertRight(){ invertButtonOverride<ButtonMaskRight>(); }
Q_INVOKABLE void ovrdA(bool value){ setButtonOverride<ButtonMaskA>(value); }
Q_INVOKABLE void ovrdB(bool value){ setButtonOverride<ButtonMaskB>(value); }
Q_INVOKABLE void ovrdStart(bool value){ setButtonOverride<ButtonMaskStart>(value); }
Q_INVOKABLE void ovrdSelect(bool value){ setButtonOverride<ButtonMaskSelect>(value); }
Q_INVOKABLE void ovrdUp(bool value){ setButtonOverride<ButtonMaskUp>(value); }
Q_INVOKABLE void ovrdDown(bool value){ setButtonOverride<ButtonMaskDown>(value); }
Q_INVOKABLE void ovrdLeft(bool value){ setButtonOverride<ButtonMaskLeft>(value); }
Q_INVOKABLE void ovrdRight(bool value){ setButtonOverride<ButtonMaskRight>(value); }
Q_INVOKABLE void ovrdReset()
{
jsOverrideMask1[player] = 0xFF;
jsOverrideMask2[player] = 0x00;
}
Q_INVOKABLE void ovrdResetAll()
{
for (int i=0; i<MAX_JOYPAD_PLAYERS; i++)
{
jsOverrideMask1[i] = 0xFF;
jsOverrideMask2[i] = 0x00;
}
}
}; };
class EmuStateScriptObject: public QObject class EmuStateScriptObject: public QObject
@ -574,11 +703,6 @@ private slots:
void stopScript(void); void stopScript(void);
}; };
// Formatted print uint8_t FCEU_JSReadJoypad(int which, uint8_t phyState);
//int LuaPrintfToWindowConsole( __FCEU_PRINTF_FORMAT const char *format, ...) __FCEU_PRINTF_ATTRIBUTE( 1, 2 );
//void PrintToWindowConsole(intptr_t hDlgAsInt, const char *str);
//int LuaKillMessageBox(void);
#endif // __FCEU_QSCRIPT_ENABLE__ #endif // __FCEU_QSCRIPT_ENABLE__

View File

@ -234,6 +234,10 @@ static uint8 ReadGPVS(int w)
return ret; return ret;
} }
#ifdef __FCEU_QSCRIPT_ENABLE__
extern uint8_t FCEU_JSReadJoypad(int which, uint8_t phyState);
#endif
static void UpdateGP(int w, void *data, int arg) static void UpdateGP(int w, void *data, int arg)
{ {
if(w==0) //adelikat, 3/14/09: Changing the joypads to inclusive OR the user's joypad + the Lua joypad, this way lua only takes over the buttons it explicity says to if(w==0) //adelikat, 3/14/09: Changing the joypads to inclusive OR the user's joypad + the Lua joypad, this way lua only takes over the buttons it explicity says to
@ -247,6 +251,11 @@ static void UpdateGP(int w, void *data, int arg)
joy[0] = *(uint32 *)joyports[0].ptr;; joy[0] = *(uint32 *)joyports[0].ptr;;
joy[2] = *(uint32 *)joyports[0].ptr >> 16; joy[2] = *(uint32 *)joyports[0].ptr >> 16;
#endif #endif
#ifdef __FCEU_QSCRIPT_ENABLE__
joy[0]= FCEU_JSReadJoypad(0,joy[0]);
joy[2]= FCEU_JSReadJoypad(2,joy[2]);
#endif
} }
else else
{ {
@ -259,6 +268,11 @@ static void UpdateGP(int w, void *data, int arg)
joy[1] = *(uint32 *)joyports[1].ptr >> 8; joy[1] = *(uint32 *)joyports[1].ptr >> 8;
joy[3] = *(uint32 *)joyports[1].ptr >> 24; joy[3] = *(uint32 *)joyports[1].ptr >> 24;
#endif #endif
#ifdef __FCEU_QSCRIPT_ENABLE__
joy[1]= FCEU_JSReadJoypad(1,joy[1]);
joy[3]= FCEU_JSReadJoypad(3,joy[3]);
#endif
} }
} }