New Class "LuaBundle"

Refactored code to make use of new LuaBundle class, this is to bring the implementation closer inline with how EmuThread is implemented, and should now be compatible with multiple emuInstances, if needed. also should make adding support for multiple lua scripts a bit easier as well.
This commit is contained in:
NPO 2024-09-27 14:35:36 -04:00
parent 2f19ab8bb5
commit 8d0de893dd
6 changed files with 209 additions and 172 deletions

View File

@ -442,10 +442,15 @@ void EmuThread::run()
handleMessages(); handleMessages();
//Lua Script Stuff (-for now happens at the end of each frame regardless of emuStatus)
LuaScript::createLuaState();//Create LuaState if needed
LuaScript::luaUpdate(); //"_Update()" gets called in current lua script
LuaConsoleDialog* dialog = emuInstance->getMainWindow()->getLuaDialog();
//Lua Script Stuff (-for now happens at the end of each frame regardless of emuStatus)
if(dialog!=nullptr)
{
LuaBundle* lua = dialog->getLuaBundle();
lua->createLuaState();//Create LuaState if needed
lua->luaUpdate(); //"_Update()" gets called in current lua script
}
} }
file = Platform::OpenLocalFile("rtc.bin", Platform::FileMode::Write); file = Platform::OpenLocalFile("rtc.bin", Platform::FileMode::Write);

View File

@ -12,8 +12,7 @@
#include <NDS_Header.h> #include <NDS_Header.h>
#include "main.h" #include "main.h"
// #include "Input.h" --Need to fix keyboard inputs //EmuThread Signals
void EmuThread::onLuaPrint(const QString& string) void EmuThread::onLuaPrint(const QString& string)
{ {
emit signalLuaPrint(string); emit signalLuaPrint(string);
@ -29,29 +28,41 @@ void EmuThread::onLuaLoadState(const QString& string)
emit signalLuaLoadState(string); emit signalLuaLoadState(string);
} }
/*
void EmuThread::onLuaLayoutChange() void EmuThread::onLuaLayoutChange()
{ {
//TODO: //TODO:
//emit screenLayoutChange(); //emit screenLayoutChange();
} }
*/
void EmuThread::onLuaSaveState(const QString& string) void EmuThread::onLuaSaveState(const QString& string)
{ {
emit signalLuaSaveState(string); emit signalLuaSaveState(string);
} }
namespace LuaScript std::vector<LuaBundle*> LuaBasket; //Currently only supporting one lua bundle at a time
{
LuaConsoleDialog* LuaDialog=nullptr; LuaBundle::LuaBundle(LuaConsoleDialog* dialog, EmuInstance* inst)
{
emuInstance = inst;
emuThread = emuInstance->getEmuThread();
luaDialog = dialog;
overlays = new std::vector<OverlayCanvas>;
imageHash = new QHash<QString, QImage>;
LuaBasket.clear(); //Only one bundle at a time for now
basketID = LuaBasket.size();
LuaBasket.push_back(this);
}
//Currently only supporting one EmuInstance
EmuInstance* CurrentInstance = nullptr;
EmuThread* CurrentThread = nullptr;
LuaConsoleDialog::LuaConsoleDialog(QWidget* parent) : QDialog(parent) LuaConsoleDialog::LuaConsoleDialog(QWidget* parent) : QDialog(parent)
{ {
QWidget* w = parent; QWidget* w = parent;
MainWindow* mainWindow;
//Yoinked from ScreenPanel in Screen.cpp //Yoinked from ScreenPanel in Screen.cpp
for (;;) for (;;)
{ {
@ -60,9 +71,7 @@ LuaConsoleDialog::LuaConsoleDialog(QWidget* parent) : QDialog(parent)
w = w->parentWidget(); w = w->parentWidget();
if (!w) break; if (!w) break;
} }
bundle = new LuaBundle(this,mainWindow->getEmuInstance());
CurrentInstance = mainWindow->getEmuInstance();
CurrentThread = CurrentInstance->getEmuThread();
console = new LuaConsole(this); console = new LuaConsole(this);
console->setGeometry(0,20,302,80); console->setGeometry(0,20,302,80);
bar = console->verticalScrollBar(); bar = console->verticalScrollBar();
@ -75,16 +84,15 @@ LuaConsoleDialog::LuaConsoleDialog(QWidget* parent) : QDialog(parent)
connect(buttonOpenScript,&QPushButton::clicked,this,&LuaConsoleDialog::onOpenScript); connect(buttonOpenScript,&QPushButton::clicked,this,&LuaConsoleDialog::onOpenScript);
connect(buttonStartStop,&QPushButton::clicked,this,&LuaConsoleDialog::onStop); connect(buttonStartStop,&QPushButton::clicked,this,&LuaConsoleDialog::onStop);
connect(buttonPausePlay,&QPushButton::clicked,this,&LuaConsoleDialog::onPausePlay); connect(buttonPausePlay,&QPushButton::clicked,this,&LuaConsoleDialog::onPausePlay);
connect(CurrentThread,&EmuThread::signalLuaPrint,console,&LuaConsole::onGetText); connect(bundle->getEmuThread(),&EmuThread::signalLuaPrint,console,&LuaConsole::onGetText);
connect(CurrentThread,&EmuThread::signalLuaClearConsole,console,&LuaConsole::onClear); connect(bundle->getEmuThread(),&EmuThread::signalLuaClearConsole,console,&LuaConsole::onClear);
this->setWindowTitle("Lua Script"); this->setWindowTitle("Lua Script");
} }
void LuaConsoleDialog::closeEvent(QCloseEvent *event) void LuaConsoleDialog::closeEvent(QCloseEvent *event)
{ {
onStop(); onStop();
LuaDialog = nullptr; bundle->overlays->clear();
LuaOverlays.clear();
event->accept(); event->accept();
} }
@ -94,7 +102,7 @@ void LuaConsoleDialog::onOpenScript()
if (!file.exists()) if (!file.exists())
return; return;
currentScript = file; currentScript = file;
FlagNewLua = true; bundle->flagNewLua = true;
} }
LuaConsole::LuaConsole(QWidget* parent) LuaConsole::LuaConsole(QWidget* parent)
@ -114,16 +122,6 @@ void LuaConsole::onClear()
this->clear(); this->clear();
} }
void luaClearConsole()
{
LuaDialog->console->clear();
}
std::vector<LuaFunction*> LuaFunctionList; // List of all lua functions.
lua_State* MainLuaState = nullptr;
bool FlagPause = false;
bool FlagStop = false;
bool FlagNewLua = false;
LuaFunction::LuaFunction(luaFunctionPointer cf,const char* n,std::vector<LuaFunction*>* container) LuaFunction::LuaFunction(luaFunctionPointer cf,const char* n,std::vector<LuaFunction*>* container)
{ {
@ -135,75 +133,74 @@ LuaFunction::LuaFunction(luaFunctionPointer cf,const char* n,std::vector<LuaFunc
#define MELON_LUA_HOOK_INSTRUCTION_COUNT 50 //number of vm instructions between hook calls #define MELON_LUA_HOOK_INSTRUCTION_COUNT 50 //number of vm instructions between hook calls
void luaHookFunction(lua_State* L, lua_Debug *arg) void luaHookFunction(lua_State* L, lua_Debug *arg)
{ {
if(FlagStop and (arg->event == LUA_HOOKCOUNT)) if(L->flagStop and (arg->event == LUA_HOOKCOUNT))
luaL_error(L, "Force Stopped"); luaL_error(L, "Force Stopped");
} }
void createLuaState()
std::vector<LuaFunction*> definedLuaFunctions;//List of all defined lua functions
void LuaBundle::createLuaState()
{ {
if(!FlagNewLua) if(!flagNewLua)
return; return;
printf("Creating LuaState"); overlays->clear();
LuaOverlays.clear(); flagNewLua = false;
FlagNewLua = false; luaState = nullptr;
MainLuaState = nullptr; QString qfilename = luaDialog->currentScript.fileName();
std::string fileName = LuaDialog->currentScript.fileName().toStdString(); std::string fileName = luaDialog->currentScript.fileName().toStdString();
std::string filedir = LuaDialog->currentScript.dir().path().toStdString(); std::string filedir = luaDialog->currentScript.dir().path().toStdString();
lua_State* L = luaL_newstate(); lua_State* L = luaL_newstate();
luaL_openlibs(L); luaL_openlibs(L);
for(LuaFunction* function : LuaFunctionList) L->basketID = basketID;
for(LuaFunction* function : definedLuaFunctions)
lua_register(L,function->name,function->cfunction); lua_register(L,function->name,function->cfunction);
std::filesystem::current_path(filedir.c_str()); std::filesystem::current_path(filedir.c_str());
lua_sethook(L,&luaHookFunction,LUA_MASKCOUNT,MELON_LUA_HOOK_INSTRUCTION_COUNT); lua_sethook(L,&luaHookFunction,LUA_MASKCOUNT,MELON_LUA_HOOK_INSTRUCTION_COUNT);
FlagStop = false;
if (luaL_dofile(L,&fileName[0])==LUA_OK) if (luaL_dofile(L,&fileName[0])==LUA_OK)
{ {
MainLuaState = L; luaState = L;
FlagPause = false;
} }
else //Error loading script else //Error loading script
{ {
CurrentThread->onLuaPrint(lua_tostring(L,-1)); emuThread->onLuaPrint(lua_tostring(L,-1));
MainLuaState = nullptr;
} }
} }
void LuaConsoleDialog::onStop() void LuaConsoleDialog::onStop()
{ {
FlagStop = true; lua_State* L = bundle->getLuaState();
if(L)
L->flagStop = true;
} }
void LuaConsoleDialog::onPausePlay() void LuaConsoleDialog::onPausePlay()
{ {
FlagPause = !FlagPause; bundle->flagPause = !bundle->flagPause;
} }
//Gets Called once a frame //Gets Called once a frame
void luaUpdate() void LuaBundle::luaUpdate()
{ {
if(!MainLuaState || FlagPause) if(!luaState || flagPause)
return; return;
if (lua_getglobal(MainLuaState,"_Update")!=LUA_TFUNCTION) if (lua_getglobal(luaState,"_Update")!=LUA_TFUNCTION)
{ {
CurrentThread->onLuaPrint("No \"_Update\" Function found, pausing script..."); emuThread->onLuaPrint("No \"_Update\" Function found, pausing script...");
FlagPause = true; flagPause = true;
return; return;
} }
if(lua_pcall(MainLuaState,0,0,0)!=0) if(lua_pcall(luaState,0,0,0)!=0)
{ {
//Handel Errors //Handel Errors
CurrentThread->onLuaPrint(lua_tostring(MainLuaState,-1)); emuThread->onLuaPrint(lua_tostring(luaState,-1));
MainLuaState = nullptr; luaState = nullptr;
} }
} }
/* OverlayCanvas::OverlayCanvas(int x,int y,int width,int height,LuaCanvasTarget t)
* Front End Stuff
*/
OverlayCanvas::OverlayCanvas(int x,int y,int width,int height,bool isActive)
{ {
this->isActive=isActive; target = t;
buffer1 = new QImage(width,height,QImage::Format_ARGB32_Premultiplied); buffer1 = new QImage(width,height,QImage::Format_ARGB32_Premultiplied);
buffer2 = new QImage(width,height,QImage::Format_ARGB32_Premultiplied); buffer2 = new QImage(width,height,QImage::Format_ARGB32_Premultiplied);
buffer1->fill(0xffffff00); //initializes buffer with yellow pixels (probably should change this to transparent black pixels at some point...) buffer1->fill(0xffffff00); //initializes buffer with yellow pixels (probably should change this to transparent black pixels at some point...)
@ -214,6 +211,7 @@ OverlayCanvas::OverlayCanvas(int x,int y,int width,int height,bool isActive)
flipped = false; flipped = false;
GLTextureLoaded = false; GLTextureLoaded = false;
} }
void OverlayCanvas::flip() void OverlayCanvas::flip()
{ {
if (imageBuffer == buffer1) if (imageBuffer == buffer1)
@ -229,13 +227,9 @@ void OverlayCanvas::flip()
flipped = true; flipped = true;
} }
std::vector<OverlayCanvas> LuaOverlays; void LuaBundle::luaResetOSD()
OverlayCanvas* CurrentCanvas;
QHash<QString , QImage> ImageHash;
void luaResetOSD()
{ {
for (auto lo = LuaOverlays.begin(); lo != LuaOverlays.end();) for (auto lo = overlays->begin(); lo != overlays->end();)
{ {
OverlayCanvas& overlay = *lo; OverlayCanvas& overlay = *lo;
overlay.GLTextureLoaded = false; overlay.GLTextureLoaded = false;
@ -243,30 +237,28 @@ void luaResetOSD()
} }
} }
int RightPadding = 0; /*--------------------------------------------------------------------------------------------------
int BottomPadding = 0; Start of lua function definitions
int LeftPadding = 0; --------------------------------------------------------------------------------------------------*/
int TopPadding = 0;
#define AddLuaFunction(functPointer,name)LuaFunction name(functPointer,#name,&LuaFunctionList) namespace luaDefinitions
/*
* Start Defining Lua Functions:
*/
namespace LuaFunctionDefinition
{ {
#define AddLuaFunction(functPointer,name)LuaFunction name(functPointer,#name,&definedLuaFunctions)
int lua_MelonPrint(lua_State* L) int lua_MelonPrint(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
QString string = luaL_checkstring(L,1); QString string = luaL_checkstring(L,1);
CurrentThread->onLuaPrint(string); bundle->getEmuThread()->onLuaPrint(string);
return 0; return 0;
} }
AddLuaFunction(lua_MelonPrint,MelonPrint); AddLuaFunction(lua_MelonPrint,MelonPrint);
int lua_MelonClear(lua_State* L) int lua_MelonClear(lua_State* L)
{ {
CurrentThread->onLuaClearConsole(); LuaBundle* bundle = LuaBasket[L->basketID];
bundle->getEmuThread()->onLuaClearConsole();
return 0; return 0;
} }
AddLuaFunction(lua_MelonClear,MelonClear); AddLuaFunction(lua_MelonClear,MelonClear);
@ -278,10 +270,10 @@ enum ramInfo_ByteType
ramInfo_FourBytes = 4 ramInfo_FourBytes = 4
}; };
melonDS::u32 GetMainRAMValueU(const melonDS::u32& addr, const ramInfo_ByteType& byteType) melonDS::u32 GetMainRAMValueU(const melonDS::u32& addr, const ramInfo_ByteType& byteType,LuaBundle* bundle)
{ {
melonDS::NDS* nds = CurrentInstance->getNDS(); melonDS::NDS* nds = bundle->getEmuInstance()->getNDS();
switch (byteType) switch (byteType)
{ {
case ramInfo_OneByte: case ramInfo_OneByte:
@ -296,9 +288,9 @@ melonDS::u32 GetMainRAMValueU(const melonDS::u32& addr, const ramInfo_ByteType&
} }
melonDS::s32 GetMainRAMValueS(const melonDS::u32& addr, const ramInfo_ByteType& byteType) melonDS::s32 GetMainRAMValueS(const melonDS::u32& addr, const ramInfo_ByteType& byteType,LuaBundle* bundle)
{ {
melonDS::NDS* nds = CurrentInstance->getNDS(); melonDS::NDS* nds = bundle->getEmuInstance()->getNDS();
switch (byteType) switch (byteType)
{ {
case ramInfo_OneByte: case ramInfo_OneByte:
@ -314,16 +306,18 @@ melonDS::s32 GetMainRAMValueS(const melonDS::u32& addr, const ramInfo_ByteType&
int Lua_ReadDatau(lua_State* L,ramInfo_ByteType byteType) int Lua_ReadDatau(lua_State* L,ramInfo_ByteType byteType)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
melonDS::u32 address = luaL_checkinteger(L,1); melonDS::u32 address = luaL_checkinteger(L,1);
melonDS::u32 value = GetMainRAMValueU(address,byteType); melonDS::u32 value = GetMainRAMValueU(address,byteType,bundle);
lua_pushinteger(L, value); lua_pushinteger(L, value);
return 1; return 1;
} }
int Lua_ReadDatas(lua_State* L,ramInfo_ByteType byteType) int Lua_ReadDatas(lua_State* L,ramInfo_ByteType byteType)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
melonDS::u32 address = luaL_checkinteger(L,1); melonDS::u32 address = luaL_checkinteger(L,1);
melonDS::s32 value = GetMainRAMValueS(address,byteType); melonDS::s32 value = GetMainRAMValueS(address,byteType,bundle);
lua_pushinteger(L, value); lua_pushinteger(L, value);
return 1; return 1;
} }
@ -384,16 +378,18 @@ AddLuaFunction(Lua_NDSTapUp,NDSTapUp);
int Lua_StateSave(lua_State* L) int Lua_StateSave(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
QString filename = luaL_checkstring(L,1); QString filename = luaL_checkstring(L,1);
CurrentThread->onLuaSaveState(filename); bundle->getEmuThread()->onLuaSaveState(filename);
return 0; return 0;
} }
AddLuaFunction(Lua_StateSave,StateSave); AddLuaFunction(Lua_StateSave,StateSave);
int Lua_StateLoad(lua_State* L) int Lua_StateLoad(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
QString filename = luaL_checkstring(L,1); QString filename = luaL_checkstring(L,1);
CurrentThread->onLuaLoadState(filename); bundle->getEmuThread()->onLuaLoadState(filename);
return 0; return 0;
} }
AddLuaFunction(Lua_StateLoad,StateLoad); AddLuaFunction(Lua_StateLoad,StateLoad);
@ -401,7 +397,8 @@ AddLuaFunction(Lua_StateLoad,StateLoad);
int Lua_getMouse(lua_State* L) int Lua_getMouse(lua_State* L)
{ {
Qt::MouseButtons btns = QGuiApplication::mouseButtons(); Qt::MouseButtons btns = QGuiApplication::mouseButtons();
QPoint pos = CurrentInstance->getMainWindow()->panel->mapFromGlobal(QCursor::pos(QGuiApplication::primaryScreen())); LuaBundle* bundle = LuaBasket[L->basketID];
QPoint pos = bundle->getEmuInstance()->getMainWindow()->panel->mapFromGlobal(QCursor::pos(QGuiApplication::primaryScreen()));
const char* keys[6] = {"Left","Middle","Right","XButton1","XButton2","Wheel"}; const char* keys[6] = {"Left","Middle","Right","XButton1","XButton2","Wheel"};
bool vals[6] = bool vals[6] =
{ {
@ -426,14 +423,15 @@ int Lua_getMouse(lua_State* L)
} }
AddLuaFunction(Lua_getMouse,GetMouse); AddLuaFunction(Lua_getMouse,GetMouse);
/* /*--------------------------------------------------------------------------------------------------
* Front end lua functions Front-end lua function definitions
*/ --------------------------------------------------------------------------------------------------*/
//TODO: Lua Colors //TODO: Lua Colors
//MakeCanvas(int x,int y,int width,int height,[int target,topScreen=0,bottomScreen=1,OSD(default)>=2)],[bool active = true]) //MakeCanvas(int x,int y,int width,int height,[int target,topScreen=0,bottomScreen=1,OSD(default)>=2)],[bool active = true])
int Lua_MakeCanvas(lua_State* L) int Lua_MakeCanvas(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
int x = luaL_checknumber(L,1); int x = luaL_checknumber(L,1);
int y = luaL_checknumber(L,2); int y = luaL_checknumber(L,2);
int w = luaL_checknumber(L,3); int w = luaL_checknumber(L,3);
@ -441,42 +439,34 @@ int Lua_MakeCanvas(lua_State* L)
int t = luaL_optinteger(L,5,2); int t = luaL_optinteger(L,5,2);
bool a = 0 != luaL_optinteger(L,6,1); bool a = 0 != luaL_optinteger(L,6,1);
OverlayCanvas canvas(x,y,w,h,a); OverlayCanvas canvas(x,y,w,h,(LuaCanvasTarget)t);
switch(t) canvas.isActive = a;
{ lua_pushinteger(L,bundle->overlays->size());
case 0: bundle->overlays->push_back(canvas);
canvas.target=LuaScript::CanvasTarget::TopScreen;
break;
case 1:
canvas.target=LuaScript::CanvasTarget::BottomScreen;
break;
default:
canvas.target=LuaScript::CanvasTarget::OSD;
}
lua_pushinteger(L,LuaOverlays.size());
LuaOverlays.push_back(canvas);
return 1; //returns index of the new overlay return 1; //returns index of the new overlay
} }
AddLuaFunction(Lua_MakeCanvas,MakeCanvas); AddLuaFunction(Lua_MakeCanvas,MakeCanvas);
int Lua_SetCanvas(lua_State* L) //SetCanvas(int index) int Lua_SetCanvas(lua_State* L) //SetCanvas(int index)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
int index = luaL_checknumber(L,1); int index = luaL_checknumber(L,1);
CurrentCanvas = &LuaOverlays.at(index); bundle->luaCanvas = &bundle->overlays->at(index);
return 0; return 0;
} }
AddLuaFunction(Lua_SetCanvas,SetCanvas); AddLuaFunction(Lua_SetCanvas,SetCanvas);
int Lua_ClearOverlay(lua_State* L) int Lua_ClearOverlay(lua_State* L)
{ {
CurrentCanvas->imageBuffer->fill(0x00000000); LuaBundle* bundle = LuaBasket[L->basketID];
bundle->luaCanvas->imageBuffer->fill(0x00000000);
return 0; return 0;
} }
AddLuaFunction(Lua_ClearOverlay,ClearOverlay); AddLuaFunction(Lua_ClearOverlay,ClearOverlay);
int Lua_Flip(lua_State* L) int Lua_Flip(lua_State* L)
{ {
CurrentCanvas->flip(); LuaBundle* bundle = LuaBasket[L->basketID];
bundle->luaCanvas->flip();
return 0; return 0;
} }
AddLuaFunction(Lua_Flip,Flip); AddLuaFunction(Lua_Flip,Flip);
@ -484,13 +474,14 @@ AddLuaFunction(Lua_Flip,Flip);
//text(int x, int y, string message, [u32 color = 'black'], [int fontsize = 9], [string fontfamily = Franklin Gothic Medium]) //text(int x, int y, string message, [u32 color = 'black'], [int fontsize = 9], [string fontfamily = Franklin Gothic Medium])
int Lua_text(lua_State* L) int Lua_text(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
int x = luaL_checknumber(L,1); int x = luaL_checknumber(L,1);
int y = luaL_checknumber(L,2); int y = luaL_checknumber(L,2);
const char* message = luaL_checklstring(L,3,NULL); const char* message = luaL_checklstring(L,3,NULL);
melonDS::u32 color = luaL_optnumber(L,4,0x00000000); melonDS::u32 color = luaL_optnumber(L,4,0x00000000);
QString FontFamily = luaL_optlstring(L,6,"Franklin Gothic Medium",NULL); QString FontFamily = luaL_optlstring(L,6,"Franklin Gothic Medium",NULL);
int size = luaL_optnumber(L,5,9); int size = luaL_optnumber(L,5,9);
QPainter painter(CurrentCanvas->imageBuffer); QPainter painter(bundle->luaCanvas->imageBuffer);
QFont font(FontFamily,size,0,false); QFont font(FontFamily,size,0,false);
font.setStyleStrategy(QFont::NoAntialias); font.setStyleStrategy(QFont::NoAntialias);
font.setLetterSpacing(QFont::AbsoluteSpacing,-1); font.setLetterSpacing(QFont::AbsoluteSpacing,-1);
@ -503,12 +494,13 @@ AddLuaFunction(Lua_text,Text);
int Lua_line(lua_State* L) int Lua_line(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
int x1 = luaL_checknumber(L,1); int x1 = luaL_checknumber(L,1);
int y1 = luaL_checknumber(L,2); int y1 = luaL_checknumber(L,2);
int x2 = luaL_checknumber(L,3); int x2 = luaL_checknumber(L,3);
int y2 = luaL_checknumber(L,4); int y2 = luaL_checknumber(L,4);
melonDS::u32 color = luaL_checknumber(L,5); melonDS::u32 color = luaL_checknumber(L,5);
QPainter painter(CurrentCanvas->imageBuffer); QPainter painter(bundle->luaCanvas->imageBuffer);
painter.setPen(color); painter.setPen(color);
painter.drawLine(x1,y1,x2,y2); painter.drawLine(x1,y1,x2,y2);
return 0; return 0;
@ -517,12 +509,13 @@ AddLuaFunction(Lua_line,Line);
int Lua_rect(lua_State* L) int Lua_rect(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
melonDS::u32 color = luaL_checknumber(L,5); melonDS::u32 color = luaL_checknumber(L,5);
int x = luaL_checknumber(L,1); int x = luaL_checknumber(L,1);
int y = luaL_checknumber(L,2); int y = luaL_checknumber(L,2);
int width = luaL_checknumber(L,3); int width = luaL_checknumber(L,3);
int height = luaL_checknumber(L,4); int height = luaL_checknumber(L,4);
QPainter painter(CurrentCanvas->imageBuffer); QPainter painter(bundle->luaCanvas->imageBuffer);
painter.setPen(color); painter.setPen(color);
painter.drawRect(x,y,width,height); painter.drawRect(x,y,width,height);
return 0; return 0;
@ -531,12 +524,13 @@ AddLuaFunction(Lua_rect,Rect);
int Lua_fillrect(lua_State* L) int Lua_fillrect(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
melonDS::u32 color = luaL_checknumber(L,5); melonDS::u32 color = luaL_checknumber(L,5);
int x = luaL_checknumber(L,1); int x = luaL_checknumber(L,1);
int y = luaL_checknumber(L,2); int y = luaL_checknumber(L,2);
int width = luaL_checknumber(L,3); int width = luaL_checknumber(L,3);
int height = luaL_checknumber(L,4); int height = luaL_checknumber(L,4);
QPainter painter(CurrentCanvas->imageBuffer); QPainter painter(bundle->luaCanvas->imageBuffer);
painter.setPen(color); painter.setPen(color);
painter.fillRect(x,y,width,height,color); painter.fillRect(x,y,width,height,color);
return 0; return 0;
@ -545,13 +539,14 @@ AddLuaFunction(Lua_fillrect,FillRect);
int Lua_keystrokes(lua_State* L) int Lua_keystrokes(lua_State* L)
{ {
lua_createtable(L,0,CurrentInstance->keyStrokes.size()); LuaBundle* bundle = LuaBasket[L->basketID];
for (int i = 0; i<CurrentInstance->keyStrokes.size(); i++) lua_createtable(L,0,bundle->getEmuInstance()->keyStrokes.size());
for (int i = 0; i<bundle->getEmuInstance()->keyStrokes.size(); i++)
{ {
lua_pushinteger(L,CurrentInstance->keyStrokes.at(i)); lua_pushinteger(L,bundle->getEmuInstance()->keyStrokes.at(i));
lua_seti(L,-2,i); lua_seti(L,-2,i);
} }
CurrentInstance->keyStrokes.clear(); bundle->getEmuInstance()->keyStrokes.clear();
lua_createtable(L,0,1); lua_createtable(L,0,1);
return 1; return 1;
} }
@ -560,6 +555,7 @@ AddLuaFunction(Lua_keystrokes,Keys);
//DrawImage(string path, int x, int y,[int source x=0], [int source y=0], [int source w=-1],[int source h=-1]) //DrawImage(string path, int x, int y,[int source x=0], [int source y=0], [int source w=-1],[int source h=-1])
int Lua_drawImage(lua_State* L) int Lua_drawImage(lua_State* L)
{ {
LuaBundle* bundle = LuaBasket[L->basketID];
QString path = luaL_checklstring(L,1,NULL); QString path = luaL_checklstring(L,1,NULL);
int x = luaL_checkinteger(L,2); int x = luaL_checkinteger(L,2);
int y = luaL_checkinteger(L,3); int y = luaL_checkinteger(L,3);
@ -567,16 +563,16 @@ int Lua_drawImage(lua_State* L)
int sy = luaL_optinteger(L,5,0); int sy = luaL_optinteger(L,5,0);
int sw = luaL_optinteger(L,6,-1); int sw = luaL_optinteger(L,6,-1);
int sh = luaL_optinteger(L,7,-1); int sh = luaL_optinteger(L,7,-1);
QPainter painter(CurrentCanvas->imageBuffer); QPainter painter(bundle->luaCanvas->imageBuffer);
QImage image; QImage image;
if(ImageHash.contains(path)) if(bundle->imageHash->contains(path))
{ {
image=ImageHash[path]; image=(*bundle->imageHash)[path];
} }
else else
{ {
image=QImage(path); image=QImage(path);
ImageHash[path] = image; (*bundle->imageHash)[path] = image;
} }
painter.drawImage(x,y,image,sx,sy,sw,sh); painter.drawImage(x,y,image,sx,sy,sw,sh);
return 0; return 0;
@ -585,7 +581,8 @@ AddLuaFunction(Lua_drawImage,DrawImage);
int Lua_clearImageHash(lua_State* L) int Lua_clearImageHash(lua_State* L)
{ {
ImageHash.clear(); LuaBundle* bundle = LuaBasket[L->basketID];
bundle->imageHash->clear();
return 0; return 0;
} }
AddLuaFunction(Lua_clearImageHash,ClearHash); AddLuaFunction(Lua_clearImageHash,ClearHash);
@ -593,7 +590,8 @@ AddLuaFunction(Lua_clearImageHash,ClearHash);
int Lua_getJoy(lua_State* L) int Lua_getJoy(lua_State* L)
{ {
//TODO: //TODO:
melonDS::u32 buttonMask=CurrentInstance->getInputMask();//current button state. LuaBundle* bundle = LuaBasket[L->basketID];
melonDS::u32 buttonMask=bundle->getEmuInstance()->getInputMask();//current button state.
const char* keys[12] = const char* keys[12] =
{//Buttons in order of mask. {//Buttons in order of mask.
"A","B","Select","Start", "A","B","Select","Start",
@ -622,7 +620,4 @@ int Lua_setPadding(lua_State* L) //TODO: Currently only works well with force in
} }
AddLuaFunction(Lua_setPadding,SetPadding); AddLuaFunction(Lua_setPadding,SetPadding);
*/ */
}
}//LuaFunctionDefinition
}//LuaScript

View File

@ -1,13 +1,11 @@
#ifndef LUASCRIPT_H #ifndef LUAMAIN_H
#define LUASCRIPT_H #define LUAMAIN_H
#include <QDialog> #include <QDialog>
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QFileInfo> #include <QFileInfo>
#include <lua.hpp> #include <lua.hpp>
#include "Window.h" #include "EmuInstance.h"
namespace LuaScript
{
class LuaConsole: public QPlainTextEdit class LuaConsole: public QPlainTextEdit
{ {
Q_OBJECT Q_OBJECT
@ -18,11 +16,14 @@ public slots:
void onClear(); void onClear();
}; };
class LuaBundle;
class LuaConsoleDialog: public QDialog class LuaConsoleDialog: public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
LuaConsoleDialog(QWidget* parent); LuaConsoleDialog(QWidget* parent);
LuaBundle* getLuaBundle(){return bundle;};
LuaConsole* console; LuaConsole* console;
QFileInfo currentScript; QFileInfo currentScript;
QPushButton* buttonOpenScript; QPushButton* buttonOpenScript;
@ -31,7 +32,7 @@ public:
QScrollBar* bar; QScrollBar* bar;
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
MainWindow* mainWindow; LuaBundle* bundle;
signals: signals:
void signalNewLua(); void signalNewLua();
void signalClosing(); void signalClosing();
@ -43,7 +44,7 @@ public slots:
}; };
//Based on ScreenLayout::GetScreenTransforms //Based on ScreenLayout::GetScreenTransforms
enum CanvasTarget enum LuaCanvasTarget
{ {
TopScreen = 0, TopScreen = 0,
BottomScreen = 1, BottomScreen = 1,
@ -57,24 +58,16 @@ struct OverlayCanvas
QImage* buffer1; QImage* buffer1;
QImage* buffer2; QImage* buffer2;
QRect rectangle; QRect rectangle;
CanvasTarget target = OSD; LuaCanvasTarget target = OSD;
bool isActive = true; // only active overlays are drawn bool isActive = true; // only active overlays are drawn
unsigned int GLTexture; // used by GL rendering unsigned int GLTexture; // used by GL rendering
bool GLTextureLoaded; bool GLTextureLoaded;
OverlayCanvas(int x,int y,int w, int h, bool active); OverlayCanvas(int x, int y,int w, int h, LuaCanvasTarget target = LuaCanvasTarget::OSD);
void flip();//used to swap buffers void flip();//used to swap buffers / update canvas
bool flipped; //used to signal update to graphics. bool flipped; //used to signal update to graphics.
}; };
void luaResetOSD();
void luaUpdate();
void luaPrint(QString string);
void luaClearConsole();
void luaHookFunction(lua_State*,lua_Debug*);
extern QWidget* panel;
extern lua_State* MainLuaState;
extern bool FlagPause;
extern bool FlagStop;
extern bool FlagNewLua;
typedef int(*luaFunctionPointer)(lua_State*); typedef int(*luaFunctionPointer)(lua_State*);
struct LuaFunction struct LuaFunction
{ {
@ -82,14 +75,41 @@ struct LuaFunction
const char* name; const char* name;
LuaFunction(luaFunctionPointer,const char*,std::vector<LuaFunction*>*); LuaFunction(luaFunctionPointer,const char*,std::vector<LuaFunction*>*);
}; };
extern LuaConsoleDialog* LuaDialog;
void createLuaState(); struct lua_State
extern std::vector<OverlayCanvas> LuaOverlays; {
extern OverlayCanvas* CurrentCanvas; bool flagStop = false;
extern QHash<QString, QImage> ImageHash; int basketID;
extern int RightPadding; };
extern int BottomPadding;
extern int TopPadding; class LuaBundle
extern int LeftPadding; {
} EmuInstance* emuInstance;
EmuThread* emuThread;
LuaConsoleDialog* luaDialog;
lua_State* luaState = nullptr;
int basketID;
void luaResetOSD();
void luaPrint(QString string);
void luaClearConsole();
OverlayCanvas* currentCanvas = nullptr;
friend class LuaConsolDialog;
public:
LuaBundle(LuaConsoleDialog* dialog,EmuInstance* inst);
lua_State* getLuaState(){return luaState;};
EmuThread* getEmuThread(){return emuThread;};
EmuInstance* getEmuInstance(){return emuInstance;};
void createLuaState();
void luaUpdate();
bool flagPause = false;
bool flagNewLua = false;
OverlayCanvas* luaCanvas = nullptr;
std::vector<OverlayCanvas>* overlays;
QHash<QString, QImage>* imageHash;
};
#endif #endif

View File

@ -672,12 +672,16 @@ void ScreenPanelNative::setupScreenLayout()
// From ScreenLayout::GetScreenTransforms // From ScreenLayout::GetScreenTransforms
// TopScreen = 0 // TopScreen = 0
// BottomScreen = 1 // BottomScreen = 1
// OSD / non-screen target = 2 (used by LuaScript stuff) // OSD / non-screen target = 2 (used by Lua stuff)
void ScreenPanelNative::drawOverlays(QPainter* painter,int type) void ScreenPanelNative::drawOverlays(QPainter* painter,int type)
{ {
for (auto lo = LuaScript::LuaOverlays.begin(); lo != LuaScript::LuaOverlays.end();) LuaConsoleDialog* dialog = mainWindow->getLuaDialog();
if (!dialog)
return;
LuaBundle* lua = dialog->getLuaBundle();
for (auto lo = lua->overlays->begin(); lo != lua->overlays->end();)
{ {
LuaScript::OverlayCanvas& overlay = *lo; OverlayCanvas& overlay = *lo;
if ((overlay.target == type) && overlay.isActive) if ((overlay.target == type) && overlay.isActive)
painter->drawImage(overlay.rectangle,*overlay.displayBuffer); painter->drawImage(overlay.rectangle,*overlay.displayBuffer);
lo++; lo++;
@ -732,7 +736,7 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
painter.resetTransform(); painter.resetTransform();
drawOverlays(&painter,LuaScript::CanvasTarget::OSD); drawOverlays(&painter,LuaCanvasTarget::OSD);
for (auto it = osdItems.begin(); it != osdItems.end(); ) for (auto it = osdItems.begin(); it != osdItems.end(); )
{ {
@ -941,9 +945,14 @@ void ScreenPanelGL::deinitOpenGL()
glDeleteProgram(osdShader); glDeleteProgram(osdShader);
glDeleteProgram(overlayShader); glDeleteProgram(overlayShader);
for (auto lo = LuaScript::LuaOverlays.begin(); lo != LuaScript::LuaOverlays.end();)
//Double Check that this actually works lol...
std::vector<OverlayCanvas>* overlays=nullptr;
if (mainWindow->getLuaDialog())
overlays = mainWindow->getLuaDialog()->getLuaBundle()->overlays;
for (auto lo = overlays->begin(); lo != overlays->end();)
{ {
LuaScript::OverlayCanvas& overlay = *lo; OverlayCanvas& overlay = *lo;
lo++; lo++;
if (!overlay.GLTextureLoaded) if (!overlay.GLTextureLoaded)
continue; continue;
@ -993,9 +1002,14 @@ void ScreenPanelGL::osdDeleteItem(OSDItem* item)
void ScreenPanelGL::drawOverlays(int type,int screen) void ScreenPanelGL::drawOverlays(int type,int screen)
{ {
for (auto lo = LuaScript::LuaOverlays.begin(); lo != LuaScript::LuaOverlays.end();) LuaConsoleDialog* dialog = mainWindow->getLuaDialog();
if (!dialog)
return;
LuaBundle* lua = dialog->getLuaBundle();
for (auto lo = lua->overlays->begin(); lo != lua->overlays->end();)
{ {
LuaScript::OverlayCanvas& overlay = *lo; OverlayCanvas& overlay = *lo;
lo++; lo++;
if (!overlay.isActive || overlay.target != type) if (!overlay.isActive || overlay.target != type)
continue; continue;
@ -1016,7 +1030,7 @@ void ScreenPanelGL::drawOverlays(int type,int screen)
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,overlay.rectangle.width(),overlay.rectangle.height(),GL_RGBA,GL_UNSIGNED_BYTE,overlay.displayBuffer->bits()); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,overlay.rectangle.width(),overlay.rectangle.height(),GL_RGBA,GL_UNSIGNED_BYTE,overlay.displayBuffer->bits());
overlay.flipped = false; overlay.flipped = false;
} }
if(type == LuaScript::CanvasTarget::OSD) // OSD gets drawn differently then top or bottom screen target if(type == LuaCanvasTarget::OSD) // OSD gets drawn differently then top or bottom screen target
{ {
glBindTexture(GL_TEXTURE_2D, overlay.GLTexture); glBindTexture(GL_TEXTURE_2D, overlay.GLTexture);
glUniform2i(osdPosULoc,overlay.rectangle.left(),overlay.rectangle.top()); glUniform2i(osdPosULoc,overlay.rectangle.left(),overlay.rectangle.top());
@ -1148,7 +1162,7 @@ void ScreenPanelGL::drawScreenGL()
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
drawOverlays(LuaScript::CanvasTarget::OSD,0); drawOverlays(LuaCanvasTarget::OSD,0);
for (auto it = osdItems.begin(); it != osdItems.end(); ) for (auto it = osdItems.begin(); it != osdItems.end(); )
{ {

View File

@ -1681,10 +1681,10 @@ void MainWindow::onOpenPowerManagement()
void MainWindow::onOpenLuaScript() void MainWindow::onOpenLuaScript()
{ {
if (LuaScript::LuaDialog) // only one at a time. if (this->luaDialog) // only one at a time.
return; return;
LuaScript::LuaDialog = new LuaScript::LuaConsoleDialog(this); this->luaDialog = new LuaConsoleDialog(this);
LuaScript::LuaDialog->show(); this->luaDialog->show();
//connect(emuThread,&EmuThread::signalLuaSaveState,mainWindow,&MainWindow::onLuaSaveState); //connect(emuThread,&EmuThread::signalLuaSaveState,mainWindow,&MainWindow::onLuaSaveState);
//connect(emuThread,&EmuThread::signalLuaLoadState,mainWindow,&MainWindow::onLuaLoadState); //connect(emuThread,&EmuThread::signalLuaLoadState,mainWindow,&MainWindow::onLuaLoadState);
} }

View File

@ -40,6 +40,7 @@
class EmuInstance; class EmuInstance;
class EmuThread; class EmuThread;
class LuaConsoleDialog;
const int kMaxRecentROMs = 10; const int kMaxRecentROMs = 10;
@ -110,6 +111,7 @@ public:
EmuInstance* getEmuInstance() { return emuInstance; } EmuInstance* getEmuInstance() { return emuInstance; }
Config::Table& getWindowConfig() { return windowCfg; } Config::Table& getWindowConfig() { return windowCfg; }
LuaConsoleDialog* getLuaDialog() {return luaDialog;}
bool hasOpenGL() { return hasOGL; } bool hasOpenGL() { return hasOGL; }
GL::Context* getOGLContext(); GL::Context* getOGLContext();
@ -257,6 +259,7 @@ private:
EmuInstance* emuInstance; EmuInstance* emuInstance;
EmuThread* emuThread; EmuThread* emuThread;
LuaConsoleDialog* luaDialog=nullptr;
Config::Table& globalCfg; Config::Table& globalCfg;
Config::Table& localCfg; Config::Table& localCfg;