Added more movie JS interface functions. Hooked up lua joypad.getimmediate functionality for Qt GUI.

This commit is contained in:
harry 2024-02-16 22:52:04 -05:00
parent aaa519d29c
commit df12fa2a85
6 changed files with 173 additions and 22 deletions

View File

@ -1096,10 +1096,10 @@ void consoleWin_t::createMainMenu(void)
loadLuaAct = nullptr;
#endif
#ifdef _S9XLUA_H
// File -> Load QScript
loadJsAct = new QAction(tr("Load &Qt Script"), this);
loadJsAct->setStatusTip(tr("Load Qt Script"));
#ifdef __FCEU_QSCRIPT_ENABLE__
// File -> Load JavaScript
loadJsAct = new QAction(tr("Load &JavaScript"), this);
loadJsAct->setStatusTip(tr("Load JavaScript"));
connect(loadJsAct, SIGNAL(triggered()), this, SLOT(loadJs(void)) );
fileMenu->addAction(loadJsAct);

View File

@ -29,6 +29,7 @@
#endif
#include <QTextEdit>
#include <QFileInfo>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
@ -184,6 +185,15 @@ bool JoypadScriptObject::buttonChanged(enum Button b)
return hasChanged;
}
//----------------------------------------------------
Q_INVOKABLE void JoypadScriptObject::ovrdResetAll()
{
for (int i=0; i<MAX_JOYPAD_PLAYERS; i++)
{
jsOverrideMask1[i] = 0xFF;
jsOverrideMask2[i] = 0x00;
}
}
//----------------------------------------------------
//---- EMU State Object
//----------------------------------------------------
int EmuStateScriptObject::numInstances = 0;
@ -924,6 +934,111 @@ bool MovieScriptObject::isFromSaveState()
return flag;
}
//----------------------------------------------------
void MovieScriptObject::replay()
{
FCEUI_MoviePlayFromBeginning();
}
//----------------------------------------------------
bool MovieScriptObject::readOnly()
{
return FCEUI_GetMovieToggleReadOnly();
}
//----------------------------------------------------
void MovieScriptObject::setReadOnly(bool which)
{
FCEUI_SetMovieToggleReadOnly(which);
}
//----------------------------------------------------
int MovieScriptObject::mode()
{
int _mode = IDLE;
if (FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
_mode = TAS_EDITOR;
}
else if (FCEUMOV_IsRecording())
{
_mode = RECORD;
}
else if (FCEUMOV_IsFinished())
{
_mode = FINISHED; //Note: this comes before playback since playback checks for finished as well
}
else if (FCEUMOV_IsPlaying())
{
_mode = PLAYBACK;
}
else
{
_mode = IDLE;
}
return _mode;
}
//----------------------------------------------------
void MovieScriptObject::stop()
{
FCEUI_StopMovie();
}
//----------------------------------------------------
int MovieScriptObject::frameCount()
{
return FCEUMOV_GetFrame();
}
//----------------------------------------------------
int MovieScriptObject::length()
{
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
script->throwError(QJSValue::GenericError, "No movie loaded.");
}
return FCEUI_GetMovieLength();
}
//----------------------------------------------------
int MovieScriptObject::rerecordCount()
{
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
script->throwError(QJSValue::GenericError, "No movie loaded.");
}
return FCEUI_GetMovieRerecordCount();
}
//----------------------------------------------------
QString MovieScriptObject::getFilepath()
{
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
script->throwError(QJSValue::GenericError, "No movie loaded.");
}
return QString::fromStdString(FCEUI_GetMovieName());
}
//----------------------------------------------------
QString MovieScriptObject::getFilename()
{
if (!FCEUMOV_IsRecording() && !FCEUMOV_IsPlaying() && !FCEUMOV_Mode(MOVIEMODE_TASEDITOR))
{
script->throwError(QJSValue::GenericError, "No movie loaded.");
}
QFileInfo fi( QString::fromStdString(FCEUI_GetMovieName()) );
return fi.fileName();
}
//----------------------------------------------------
bool MovieScriptObject::skipRerecords = false;
//----------------------------------------------------
void MovieScriptObject::rerecordCounting(bool counting)
{
skipRerecords = counting;
}
//----------------------------------------------------
bool MovieScriptObject::play(const QString& filename, bool readOnly, int pauseFrame)
{
if (pauseFrame < 0) pauseFrame = 0;
// Load it!
bool loaded = FCEUI_LoadMovie(filename.toLocal8Bit().data(), readOnly, pauseFrame);
return loaded;
}
//----------------------------------------------------
bool MovieScriptObject::record(const QString& filename, int saveType, const QString author)
{
if (filename.isEmpty())
@ -1751,6 +1866,7 @@ bool QtScriptInstance::onGuiThread()
int QtScriptInstance::throwError(QJSValue::ErrorType errorType, const QString &message)
{
running = false;
mem->reset();
engine->throwError(errorType, message);
return 0;
}
@ -2075,6 +2191,13 @@ void QtScriptManager::removeScriptInstance(QtScriptInstance* script)
it++;
}
}
// If no scripts are loaded, reset globals
if (scriptList.size() == 0)
{
JS::MovieScriptObject::skipRerecords = false;
JS::JoypadScriptObject::ovrdResetAll();
}
}
//----------------------------------------------------
void QtScriptManager::frameBeginUpdate()
@ -2713,6 +2836,11 @@ void QScriptDialog_t::logOutput(const QString& text)
}
}
//----------------------------------------------------
bool FCEU_JSRerecordCountSkip()
{
return JS::MovieScriptObject::skipRerecords;
}
//----------------------------------------------------
uint8_t FCEU_JSReadJoypad(int which, uint8_t joyl)
{
return JS::JoypadScriptObject::readOverride(which, joyl);

View File

@ -270,14 +270,7 @@ public slots:
jsOverrideMask2[player] = 0x00;
}
Q_INVOKABLE void ovrdResetAll()
{
for (int i=0; i<MAX_JOYPAD_PLAYERS; i++)
{
jsOverrideMask1[i] = 0xFF;
jsOverrideMask2[i] = 0x00;
}
}
Q_INVOKABLE static void ovrdResetAll();
};
class EmuStateScriptObject: public QObject
@ -408,6 +401,7 @@ public:
QJSValue* getReadFunc(int address) { return readFunc[address]; }
QJSValue* getWriteFunc(int address) { return writeFunc[address]; }
QJSValue* getExecFunc(int address) { return execFunc[address]; }
private:
static constexpr int AddressRange = 0x10000;
FCEU::JSEngine* engine = nullptr;
@ -483,6 +477,16 @@ public:
void setEngine(FCEU::JSEngine* _engine){ engine = _engine; }
enum Mode
{
IDLE = 0,
RECORD,
PLAYBACK,
FINISHED,
TAS_EDITOR
};
Q_ENUM(Mode);
enum SaveType
{
FROM_POWERON = 0,
@ -490,6 +494,8 @@ public:
FROM_SAVERAM,
};
Q_ENUM(SaveType);
static bool skipRerecords;
private:
FCEU::JSEngine* engine = nullptr;
QtScriptInstance* script = nullptr;
@ -500,7 +506,20 @@ public slots:
Q_INVOKABLE bool isRecording();
Q_INVOKABLE bool isPowerOn();
Q_INVOKABLE bool isFromSaveState();
Q_INVOKABLE void replay();
Q_INVOKABLE bool readOnly();
Q_INVOKABLE void setReadOnly(bool which);
Q_INVOKABLE bool play(const QString& filename, bool readOnly = false, int pauseFrame = 0);
Q_INVOKABLE bool record(const QString& filename, int saveType = FROM_POWERON, const QString author = QString());
Q_INVOKABLE int frameCount();
Q_INVOKABLE int mode();
Q_INVOKABLE void stop();
Q_INVOKABLE int length();
Q_INVOKABLE int rerecordCount();
Q_INVOKABLE void rerecordCounting(bool counting);
Q_INVOKABLE QString getFilename();
Q_INVOKABLE QString getFilepath();
};
class InputScriptObject: public QObject
@ -733,6 +752,8 @@ private slots:
void stopScript(void);
};
bool FCEU_JSRerecordCountSkip();
uint8_t FCEU_JSReadJoypad(int which, uint8_t phyState);
#endif // __FCEU_QSCRIPT_ENABLE__

View File

@ -73,7 +73,7 @@ void FCEU_LuaReadZapper(const uint32* mouse_in, uint32* mouse_out);
uint8 FCEU_LuaReadJoypad(int,uint8); // HACK - Function needs controller input
int FCEU_LuaSpeed();
int FCEU_LuaFrameskip();
int FCEU_LuaRerecordCountSkip();
bool FCEU_LuaRerecordCountSkip();
void FCEU_LuaGui(uint8 *XBuf);
void FCEU_LuaUpdatePalette();

View File

@ -2899,7 +2899,7 @@ static int joypad_getimmediate(lua_State *L)
luaL_error(L,"Invalid input port (valid range 1-4, specified %d)", which);
}
// Currently only supports Windows, sorry...
#ifdef __WIN_DRIVER__
#if defined(__WIN_DRIVER__) || defined(__QT_DRIVER__)
extern uint32 GetGamepadPressedImmediate();
uint8 buttons = GetGamepadPressedImmediate() >> ((which - 1) * 8);
@ -6738,7 +6738,7 @@ uint8 FCEU_LuaReadJoypad(int which, uint8 joyl) {
*
* This function will not return true if a script is not running.
*/
int FCEU_LuaRerecordCountSkip() {
bool FCEU_LuaRerecordCountSkip() {
// FIXME: return true if (there are any active callback functions && skipRerecords)
return L && luaRunning && skipRerecords;
}

View File

@ -1645,18 +1645,20 @@ bool FCEUMOV_PostLoad(void)
void FCEUMOV_IncrementRerecordCount()
{
bool skip = false;
#ifdef _S9XLUA_H
if(!FCEU_LuaRerecordCountSkip())
skip = skip || FCEU_LuaRerecordCountSkip();
#endif
#ifdef __FCEU_QSCRIPT_ENABLE__
extern bool FCEU_JSRerecordCountSkip();
skip = skip || FCEU_JSRerecordCountSkip();
#endif
if(!skip)
if (movieMode != MOVIEMODE_TASEDITOR)
currRerecordCount++;
else
currMovieData.rerecordCount++;
#else
if (movieMode != MOVIEMODE_TASEDITOR)
currRerecordCount++;
else
currMovieData.rerecordCount++;
#endif
if (movieMode != MOVIEMODE_TASEDITOR)
currMovieData.rerecordCount = currRerecordCount;
}