Added JS joypad object functionality.

This commit is contained in:
harry 2024-02-11 14:56:58 -05:00
parent 6248b0ee64
commit 446763b232
2 changed files with 178 additions and 1 deletions

View File

@ -71,6 +71,8 @@
// File Base Name from Core // File Base Name from Core
extern char FileBase[]; extern char FileBase[];
extern uint8 joy[4];
extern uint32 GetGamepadPressedImmediate();
static thread_local FCEU::JSEngine* currentEngine = nullptr; static thread_local FCEU::JSEngine* currentEngine = nullptr;
@ -96,6 +98,56 @@ ColorScriptObject::~ColorScriptObject()
//printf("ColorScriptObject %p Destructor: %i\n", this, numInstances); //printf("ColorScriptObject %p Destructor: %i\n", this, numInstances);
} }
//---------------------------------------------------- //----------------------------------------------------
//---- Joypad Object
//----------------------------------------------------
int JoypadScriptObject::numInstances = 0;
JoypadScriptObject::JoypadScriptObject(int playerIdx)
: QObject()
{
numInstances++;
//printf("JoypadScriptObject %p Constructor: %i\n", this, numInstances);
moveToThread(QApplication::instance()->thread());
player = playerIdx;
}
//----------------------------------------------------
JoypadScriptObject::~JoypadScriptObject()
{
numInstances--;
//printf("JoypadScriptObject %p Destructor: %i\n", this, numInstances);
}
//----------------------------------------------------
void JoypadScriptObject::readData()
{
uint8_t 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;
}
//----------------------------------------------------
void JoypadScriptObject::readDataPhy()
{
uint32_t gpData = GetGamepadPressedImmediate();
uint8_t 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;
}
//----------------------------------------------------
//---- EMU State Object //---- EMU State Object
//---------------------------------------------------- //----------------------------------------------------
int EmuStateScriptObject::numInstances = 0; int EmuStateScriptObject::numInstances = 0;
@ -784,6 +836,50 @@ void PpuScriptObject::writeByte(int address, int value)
} }
} }
//---------------------------------------------------- //----------------------------------------------------
//---- Input Script Object
//----------------------------------------------------
//----------------------------------------------------
InputScriptObject::InputScriptObject(QObject* parent)
: QObject(parent)
{
script = qobject_cast<QtScriptInstance*>(parent);
engine = script->getEngine();
for (int i=0; i<MAX_NUM_JOYPADS; i++)
{
joypad[i].qObj = new JoypadScriptObject(i);
joypad[i].jsObj = engine->newQObject( joypad[i].qObj );
//#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
// QJSEngine::setObjectOwnership( joypad[i].qObj, QJSEngine::CppScriptOwnership);
//#endif
}
}
//----------------------------------------------------
InputScriptObject::~InputScriptObject()
{
}
//----------------------------------------------------
QJSValue InputScriptObject::readJoypad(int player, bool immediate)
{
if ( (player < 0) || (player >= MAX_NUM_JOYPADS) )
{
QString msg = "Error: Joypad player index (" + QString::number(player) + ") is out of bounds!\n";
engine->throwError(QJSValue::RangeError, msg);
player = 0;
}
if (immediate)
{
joypad[player].qObj->readDataPhy();
}
else
{
joypad[player].qObj->readData();
}
return joypad[player].jsObj;
}
//----------------------------------------------------
//---- Memory Script Object //---- Memory Script Object
//---------------------------------------------------- //----------------------------------------------------
//---------------------------------------------------- //----------------------------------------------------
@ -1317,6 +1413,11 @@ void QtScriptInstance::shutdownEngine()
delete mem; delete mem;
mem = nullptr; mem = nullptr;
} }
if (input != nullptr)
{
delete input;
input = nullptr;
}
if (ui_rootWidget != nullptr) if (ui_rootWidget != nullptr)
{ {
@ -1343,6 +1444,7 @@ int QtScriptInstance::initEngine()
rom = new JS::RomScriptObject(this); rom = new JS::RomScriptObject(this);
ppu = new JS::PpuScriptObject(this); ppu = new JS::PpuScriptObject(this);
mem = new JS::MemoryScriptObject(this); mem = new JS::MemoryScriptObject(this);
input = new JS::InputScriptObject(this);
emu->setDialog(dialog); emu->setDialog(dialog);
rom->setDialog(dialog); rom->setDialog(dialog);
@ -1374,6 +1476,11 @@ int QtScriptInstance::initEngine()
engine->globalObject().setProperty("memory", memObject); engine->globalObject().setProperty("memory", memObject);
// input
QJSValue inputObject = engine->newQObject(input);
engine->globalObject().setProperty("input", inputObject);
// gui // gui
QJSValue guiObject = engine->newQObject(this); QJSValue guiObject = engine->newQObject(this);
@ -1778,7 +1885,7 @@ QtScriptManager::QtScriptManager(QObject* parent)
: QObject(parent) : QObject(parent)
{ {
_instance = this; _instance = this;
monitorThread = new ScriptMonitorThread_t(); monitorThread = new ScriptMonitorThread_t(this);
monitorThread->start(); monitorThread->start();
periodicUpdateTimer = new QTimer(this); periodicUpdateTimer = new QTimer(this);

View File

@ -105,6 +105,49 @@ public slots:
Q_INVOKABLE void setPalette(int p){ _palette = p; } Q_INVOKABLE void setPalette(int p){ _palette = p; }
}; };
class JoypadScriptObject: public QObject
{
Q_OBJECT
Q_PROPERTY(bool up READ getUp)
Q_PROPERTY(bool down READ getDown)
Q_PROPERTY(bool left READ getLeft)
Q_PROPERTY(bool right READ getRight)
Q_PROPERTY(bool select READ getSelect)
Q_PROPERTY(bool start READ getStart)
Q_PROPERTY(bool a READ getA)
Q_PROPERTY(bool b READ getB)
Q_PROPERTY(int player READ getPlayer)
public:
JoypadScriptObject(int playerIdx);
~JoypadScriptObject();
void readData();
void readDataPhy();
private:
bool up = false;
bool down = false;
bool left = false;
bool right = false;
bool select = false;
bool start = false;
bool a = false;
bool b = false;
int player = 0;
static int numInstances;
public slots:
Q_INVOKABLE bool getUp(){ return up; }
Q_INVOKABLE bool getDown(){ return down; }
Q_INVOKABLE bool getLeft(){ return left; }
Q_INVOKABLE bool getRight(){ return right; }
Q_INVOKABLE bool getSelect(){ return select; }
Q_INVOKABLE bool getStart(){ return start; }
Q_INVOKABLE bool getA(){ return a; }
Q_INVOKABLE bool getB(){ return b; }
Q_INVOKABLE int getPlayer(){ return player; }
};
class EmuStateScriptObject: public QObject class EmuStateScriptObject: public QObject
{ {
Q_OBJECT Q_OBJECT
@ -299,6 +342,32 @@ public slots:
Q_INVOKABLE void writeByte(int address, int value); Q_INVOKABLE void writeByte(int address, int value);
}; };
class InputScriptObject: public QObject
{
Q_OBJECT
public:
InputScriptObject(QObject* parent = nullptr);
~InputScriptObject();
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
void setDialog(QScriptDialog_t* _dialog){ dialog = _dialog; }
static constexpr int MAX_NUM_JOYPADS = 4;
private:
FCEU::JSEngine* engine = nullptr;
QScriptDialog_t* dialog = nullptr;
QtScriptInstance* script = nullptr;
struct
{
JoypadScriptObject* qObj;
QJSValue jsObj;
} joypad[MAX_NUM_JOYPADS];
public slots:
Q_INVOKABLE QJSValue readJoypad(int player, bool immediate = false);
};
} // JS } // JS
class ScriptExecutionState class ScriptExecutionState
@ -369,6 +438,7 @@ private:
JS::RomScriptObject* rom = nullptr; JS::RomScriptObject* rom = nullptr;
JS::PpuScriptObject* ppu = nullptr; JS::PpuScriptObject* ppu = nullptr;
JS::MemoryScriptObject* mem = nullptr; JS::MemoryScriptObject* mem = nullptr;
JS::InputScriptObject* input = nullptr;
QWidget* ui_rootWidget = nullptr; QWidget* ui_rootWidget = nullptr;
QJSValue *onFrameBeginCallback = nullptr; QJSValue *onFrameBeginCallback = nullptr;
QJSValue *onFrameFinishCallback = nullptr; QJSValue *onFrameFinishCallback = nullptr;