add lua console, and add/replace print, tostring, addressof, and copytable.
This commit is contained in:
parent
972e87ca32
commit
25cdffc734
|
@ -0,0 +1,207 @@
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "main.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "../../fceulua.h"
|
||||||
|
|
||||||
|
extern HWND hAppWnd;
|
||||||
|
|
||||||
|
HWND LuaConsoleHWnd = NULL;
|
||||||
|
|
||||||
|
void PrintToWindowConsole(int hDlgAsInt, const char* str)
|
||||||
|
{
|
||||||
|
HWND hDlg = (HWND)hDlgAsInt;
|
||||||
|
HWND hConsole = GetDlgItem(hDlg, IDC_LUACONSOLE);
|
||||||
|
|
||||||
|
int length = GetWindowTextLength(hConsole);
|
||||||
|
if(length >= 250000)
|
||||||
|
{
|
||||||
|
// discard first half of text if it's getting too long
|
||||||
|
SendMessage(hConsole, EM_SETSEL, 0, length/2);
|
||||||
|
SendMessage(hConsole, EM_REPLACESEL, false, (LPARAM)"");
|
||||||
|
length = GetWindowTextLength(hConsole);
|
||||||
|
}
|
||||||
|
SendMessage(hConsole, EM_SETSEL, length, length);
|
||||||
|
|
||||||
|
//LuaPerWindowInfo& info = LuaWindowInfo[hDlg];
|
||||||
|
|
||||||
|
{
|
||||||
|
SendMessage(hConsole, EM_REPLACESEL, false, (LPARAM)str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinLuaOnStart(int hDlgAsInt)
|
||||||
|
{
|
||||||
|
HWND hDlg = (HWND)hDlgAsInt;
|
||||||
|
//LuaPerWindowInfo& info = LuaWindowInfo[hDlg];
|
||||||
|
//info.started = true;
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_LUABROWSE), false); // disable browse while running because it misbehaves if clicked in a frameadvance loop
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_LUASTOP), true);
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_BUTTON_LUARUN), "Restart");
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_LUACONSOLE), ""); // clear the console
|
||||||
|
// Show_Genesis_Screen(HWnd); // otherwise we might never show the first thing the script draws
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinLuaOnStop(int hDlgAsInt)
|
||||||
|
{
|
||||||
|
HWND hDlg = (HWND)hDlgAsInt;
|
||||||
|
//LuaPerWindowInfo& info = LuaWindowInfo[hDlg];
|
||||||
|
|
||||||
|
HWND prevWindow = GetActiveWindow();
|
||||||
|
SetActiveWindow(hDlg); // bring to front among other script/secondary windows, since a stopped script will have some message for the user that would be easier to miss otherwise
|
||||||
|
if(prevWindow == hAppWnd) SetActiveWindow(prevWindow);
|
||||||
|
|
||||||
|
//info.started = false;
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_LUABROWSE), true);
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDC_BUTTON_LUASTOP), false);
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_BUTTON_LUARUN), "Run");
|
||||||
|
// if(statusOK)
|
||||||
|
// Show_Genesis_Screen(MainWindow->getHWnd()); // otherwise we might never show the last thing the script draws
|
||||||
|
//if(info.closeOnStop)
|
||||||
|
// PostMessage(hDlg, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
INT_PTR CALLBACK DlgLuaScriptDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
RECT r2;
|
||||||
|
int dx1, dy1, dx2, dy2;
|
||||||
|
|
||||||
|
switch (msg) {
|
||||||
|
|
||||||
|
case WM_INITDIALOG:
|
||||||
|
{
|
||||||
|
// disable resizing
|
||||||
|
LONG wndStyle = GetWindowLong(hDlg, GWL_STYLE);
|
||||||
|
wndStyle &= ~WS_THICKFRAME;
|
||||||
|
SetWindowLong(hDlg, GWL_STYLE, wndStyle);
|
||||||
|
|
||||||
|
// remove the 30000 character limit from the console control
|
||||||
|
SendMessage(GetDlgItem(hDlg, IDC_LUACONSOLE),EM_LIMITTEXT,0,0);
|
||||||
|
|
||||||
|
GetWindowRect(hAppWnd, &r);
|
||||||
|
dx1 = (r.right - r.left) / 2;
|
||||||
|
dy1 = (r.bottom - r.top) / 2;
|
||||||
|
|
||||||
|
GetWindowRect(hDlg, &r2);
|
||||||
|
dx2 = (r2.right - r2.left) / 2;
|
||||||
|
dy2 = (r2.bottom - r2.top) / 2;
|
||||||
|
|
||||||
|
int windowIndex = 0;//std::find(LuaScriptHWnds.begin(), LuaScriptHWnds.end(), hDlg) - LuaScriptHWnds.begin();
|
||||||
|
int staggerOffset = windowIndex * 24;
|
||||||
|
r.left += staggerOffset;
|
||||||
|
r.right += staggerOffset;
|
||||||
|
r.top += staggerOffset;
|
||||||
|
r.bottom += staggerOffset;
|
||||||
|
|
||||||
|
// push it away from the main window if we can
|
||||||
|
const int width = (r.right-r.left);
|
||||||
|
const int width2 = (r2.right-r2.left);
|
||||||
|
if(r.left+width2 + width < GetSystemMetrics(SM_CXSCREEN))
|
||||||
|
{
|
||||||
|
r.right += width;
|
||||||
|
r.left += width;
|
||||||
|
}
|
||||||
|
else if((int)r.left - (int)width2 > 0)
|
||||||
|
{
|
||||||
|
r.right -= width2;
|
||||||
|
r.left -= width2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowPos(hDlg, NULL, r.left, r.top, NULL, NULL, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW);
|
||||||
|
|
||||||
|
DragAcceptFiles(hDlg, true);
|
||||||
|
SetDlgItemText(hDlg, IDC_EDIT_LUAPATH, FCEU_GetLuaScriptName());
|
||||||
|
return true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WM_COMMAND:
|
||||||
|
switch (LOWORD(wParam)) {
|
||||||
|
case IDOK:
|
||||||
|
case IDCANCEL: {
|
||||||
|
EndDialog(hDlg, true); // goto case WM_CLOSE;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IDC_BUTTON_LUARUN:
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
GetDlgItemText(hDlg, IDC_EDIT_LUAPATH, filename, MAX_PATH);
|
||||||
|
FCEU_LoadLuaCode(filename);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IDC_BUTTON_LUASTOP:
|
||||||
|
{
|
||||||
|
FCEU_LuaStop();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IDC_BUTTON_LUAEDIT:
|
||||||
|
{
|
||||||
|
char Str_Tmp [1024]; // shadow added because the global one is unreliable
|
||||||
|
SendDlgItemMessage(hDlg,IDC_EDIT_LUAPATH,WM_GETTEXT,(WPARAM)512,(LPARAM)Str_Tmp);
|
||||||
|
// tell the OS to open the file with its associated editor,
|
||||||
|
// without blocking on it or leaving a command window open.
|
||||||
|
ShellExecute(NULL, "edit", Str_Tmp, NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IDC_BUTTON_LUABROWSE:
|
||||||
|
{
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
char szFileName[MAX_PATH];
|
||||||
|
szFileName[0] = '\0';
|
||||||
|
ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) );
|
||||||
|
ofn.lStructSize = sizeof(OPENFILENAME);
|
||||||
|
ofn.hwndOwner = hAppWnd;
|
||||||
|
ofn.lpstrFilter = "Lua scripts (*.lua)\0*.lua\0All files (*.*)\0*.*\0\0";
|
||||||
|
ofn.lpstrFile = szFileName;
|
||||||
|
ofn.lpstrDefExt = "lua";
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; // hide previously-ignored read-only checkbox (the real read-only box is in the open-movie dialog itself)
|
||||||
|
std::string initdir = FCEU_GetPath(FCEUMKF_LUA);
|
||||||
|
ofn.lpstrInitialDir=initdir.c_str();
|
||||||
|
if(GetOpenFileName( &ofn ))
|
||||||
|
{
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_EDIT_LUAPATH), szFileName);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case IDC_EDIT_LUAPATH:
|
||||||
|
{
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
GetDlgItemText(hDlg, IDC_EDIT_LUAPATH, filename, MAX_PATH);
|
||||||
|
FILE* file = fopen(filename, "rb");
|
||||||
|
EnableWindow(GetDlgItem(hDlg, IDOK), file != NULL);
|
||||||
|
if(file)
|
||||||
|
fclose(file);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CLOSE: {
|
||||||
|
FCEU_LuaStop();
|
||||||
|
DragAcceptFiles(hDlg, FALSE);
|
||||||
|
LuaConsoleHWnd = NULL;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WM_DROPFILES: {
|
||||||
|
HDROP hDrop;
|
||||||
|
//UINT fileNo;
|
||||||
|
UINT fileCount;
|
||||||
|
char filename[MAX_PATH];
|
||||||
|
|
||||||
|
hDrop = (HDROP)wParam;
|
||||||
|
fileCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
|
||||||
|
if (fileCount > 0) {
|
||||||
|
DragQueryFile(hDrop, 0, filename, sizeof(filename));
|
||||||
|
SetWindowText(GetDlgItem(hDlg, IDC_EDIT_LUAPATH), filename);
|
||||||
|
}
|
||||||
|
DragFinish(hDrop);
|
||||||
|
return true;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
// Generated from the TEXTINCLUDE 2 resource.
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
//
|
//
|
||||||
#include "afxres.h"
|
#include "afxres.h"
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
#undef APSTUDIO_READONLY_SYMBOLS
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
@ -74,9 +75,8 @@ BEGIN
|
||||||
POPUP "&Lua"
|
POPUP "&Lua"
|
||||||
BEGIN
|
BEGIN
|
||||||
MENUITEM "&Recent", MENU_LUA_RECENT
|
MENUITEM "&Recent", MENU_LUA_RECENT
|
||||||
MENUITEM "Run &Lua Script...", ID_FILE_RUNLUASCRIPT
|
MENUITEM "&New Lua Script Window...", ID_FILE_OPENLUAWINDOW
|
||||||
MENUITEM "&Stop Lua Script", ID_FILE_STOPLUASCRIPT
|
MENUITEM "&Close All Script Windows", ID_FILE_CLOSELUAWINDOWS
|
||||||
MENUITEM "&Reload Lua Script", ID_FILE_LUA_RELOADLUASCRIPT
|
|
||||||
END
|
END
|
||||||
MENUITEM "&Screenshot", ID_FILE_SCREENSHOT
|
MENUITEM "&Screenshot", ID_FILE_SCREENSHOT
|
||||||
MENUITEM SEPARATOR
|
MENUITEM SEPARATOR
|
||||||
|
@ -1446,15 +1446,19 @@ BEGIN
|
||||||
LTEXT "(Hex)",IDC_STATIC,226,34,19,8
|
LTEXT "(Hex)",IDC_STATIC,226,34,19,8
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_LUA_ADD DIALOGEX 0, 0, 186, 66
|
IDD_LUA DIALOGEX 0, 0, 270, 150
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_FIXEDSYS | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||||
CAPTION "Load Lua Script..."
|
CAPTION "Lua Script"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Load && Run",1,70,44,50,14
|
PUSHBUTTON "Browse...",IDC_BUTTON_LUABROWSE,7,31,48,16
|
||||||
PUSHBUTTON "Cancel",2,129,44,50,14
|
PUSHBUTTON "Run",IDC_BUTTON_LUARUN,213,31,50,16
|
||||||
EDITTEXT 1096,7,7,116,14,ES_AUTOHSCROLL | ES_READONLY,WS_EX_NOPARENTNOTIFY
|
PUSHBUTTON "Stop",IDC_BUTTON_LUASTOP,160,31,50,16
|
||||||
PUSHBUTTON "Browse...",1359,129,7,50,14
|
EDITTEXT IDC_EDIT_LUAPATH,7,16,256,14,ES_AUTOHSCROLL
|
||||||
|
EDITTEXT IDC_LUACONSOLE,7,61,256,81,ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY
|
||||||
|
LTEXT "Output Console",IDC_STATIC,7,51,51,8
|
||||||
|
LTEXT "Script File",IDC_STATIC,7,7,32,8
|
||||||
|
PUSHBUTTON "Edit",IDC_BUTTON_LUAEDIT,58,31,46,16
|
||||||
END
|
END
|
||||||
|
|
||||||
VIDEOCONFIG DIALOGEX 65520, 76, 384, 296
|
VIDEOCONFIG DIALOGEX 65520, 76, 384, 296
|
||||||
|
@ -1787,14 +1791,6 @@ BEGIN
|
||||||
BOTTOMMARGIN, 171
|
BOTTOMMARGIN, 171
|
||||||
END
|
END
|
||||||
|
|
||||||
"IDD_LUA_ADD", DIALOG
|
|
||||||
BEGIN
|
|
||||||
LEFTMARGIN, 7
|
|
||||||
RIGHTMARGIN, 179
|
|
||||||
TOPMARGIN, 7
|
|
||||||
BOTTOMMARGIN, 59
|
|
||||||
END
|
|
||||||
|
|
||||||
"VIDEOCONFIG", DIALOG
|
"VIDEOCONFIG", DIALOG
|
||||||
BEGIN
|
BEGIN
|
||||||
LEFTMARGIN, 10
|
LEFTMARGIN, 10
|
||||||
|
@ -1927,6 +1923,7 @@ IDB_TE_ARROW BITMAP "res/te_arrow.bmp"
|
||||||
// Generated from the TEXTINCLUDE 3 resource.
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
#endif // not APSTUDIO_INVOKED
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@
|
||||||
#define IDD_EDITWATCH 156
|
#define IDD_EDITWATCH 156
|
||||||
#define IDD_PROMPT 157
|
#define IDD_PROMPT 157
|
||||||
#define IDR_RWACCELERATOR 158
|
#define IDR_RWACCELERATOR 158
|
||||||
|
#define IDD_LUA 159
|
||||||
#define MENU_RESET 200
|
#define MENU_RESET 200
|
||||||
#define BUTTON_ROMS 200
|
#define BUTTON_ROMS 200
|
||||||
#define TXT_PAD1 200
|
#define TXT_PAD1 200
|
||||||
|
@ -456,6 +457,12 @@
|
||||||
#define IDC_PROMPT_TEXT 1245
|
#define IDC_PROMPT_TEXT 1245
|
||||||
#define IDC_PROMPT_TEXT2 1246
|
#define IDC_PROMPT_TEXT2 1246
|
||||||
#define IDC_PROMPT_EDIT 1247
|
#define IDC_PROMPT_EDIT 1247
|
||||||
|
#define IDC_BUTTON_LUABROWSE 1248
|
||||||
|
#define IDC_BUTTON_LUARUN 1249
|
||||||
|
#define IDC_BUTTON_LUASTOP 1250
|
||||||
|
#define IDC_EDIT_LUAPATH 1251
|
||||||
|
#define IDC_LUACONSOLE 1252
|
||||||
|
#define IDC_BUTTON_LUAEDIT 1253
|
||||||
#define MENU_NETWORK 40040
|
#define MENU_NETWORK 40040
|
||||||
#define MENU_PALETTE 40041
|
#define MENU_PALETTE 40041
|
||||||
#define MENU_SOUND 40042
|
#define MENU_SOUND 40042
|
||||||
|
@ -605,8 +612,8 @@
|
||||||
#define ID_MEMWVIEW_FILE_CLOSE 40217
|
#define ID_MEMWVIEW_FILE_CLOSE 40217
|
||||||
#define ID_FILE_CLOSE40218 40218
|
#define ID_FILE_CLOSE40218 40218
|
||||||
#define MENU_BASIC_BOT2 40220
|
#define MENU_BASIC_BOT2 40220
|
||||||
#define ID_FILE_RUNLUASCRIPT 40229
|
#define ID_FILE_OPENLUAWINDOW 40229
|
||||||
#define ID_FILE_STOPLUASCRIPT 40230
|
#define ID_FILE_CLOSELUAWINDOWS 40230
|
||||||
#define ID_CONFIG_DISPLAY 40231
|
#define ID_CONFIG_DISPLAY 40231
|
||||||
#define ID_DISPLAY_INPUTDISPLAY 40232
|
#define ID_DISPLAY_INPUTDISPLAY 40232
|
||||||
#define ID_DISPLAY_LAGCOUNTER 40233
|
#define ID_DISPLAY_LAGCOUNTER 40233
|
||||||
|
@ -764,9 +771,9 @@
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 159
|
#define _APS_NEXT_RESOURCE_VALUE 160
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40401
|
#define _APS_NEXT_COMMAND_VALUE 40401
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1248
|
#define _APS_NEXT_CONTROL_VALUE 1254
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -77,7 +77,7 @@ using namespace std;
|
||||||
//----Context Menu - Some dynamically added menu items
|
//----Context Menu - Some dynamically added menu items
|
||||||
#define FCEUX_CONTEXT_UNHIDEMENU 60000
|
#define FCEUX_CONTEXT_UNHIDEMENU 60000
|
||||||
#define FCEUX_CONTEXT_LOADLASTLUA 60001
|
#define FCEUX_CONTEXT_LOADLASTLUA 60001
|
||||||
#define FCEUX_CONTEXT_STOPLUA 60002
|
#define FCEUX_CONTEXT_CLOSELUAWINDOWS 60002
|
||||||
|
|
||||||
//********************************************************************************
|
//********************************************************************************
|
||||||
//Globals
|
//Globals
|
||||||
|
@ -99,7 +99,6 @@ extern FCEUGI *GameInfo;
|
||||||
extern int EnableAutosave;
|
extern int EnableAutosave;
|
||||||
extern bool frameAdvanceLagSkip;
|
extern bool frameAdvanceLagSkip;
|
||||||
extern bool turbo;
|
extern bool turbo;
|
||||||
extern int luaRunning;
|
|
||||||
extern bool movie_readonly;
|
extern bool movie_readonly;
|
||||||
extern bool AutoSS; //flag for whether an auto-save has been made
|
extern bool AutoSS; //flag for whether an auto-save has been made
|
||||||
extern int newppu;
|
extern int newppu;
|
||||||
|
@ -143,6 +142,10 @@ char *recent_files[] = { 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 };
|
||||||
const unsigned int MENU_FIRST_RECENT_FILE = 600;
|
const unsigned int MENU_FIRST_RECENT_FILE = 600;
|
||||||
const unsigned int MAX_NUMBER_OF_RECENT_FILES = sizeof(recent_files)/sizeof(*recent_files);
|
const unsigned int MAX_NUMBER_OF_RECENT_FILES = sizeof(recent_files)/sizeof(*recent_files);
|
||||||
|
|
||||||
|
//Lua Console --------------------------------------------
|
||||||
|
extern HWND LuaConsoleHWnd;
|
||||||
|
extern INT_PTR CALLBACK DlgLuaScriptDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
//Recent Lua Menu ----------------------------------------
|
//Recent Lua Menu ----------------------------------------
|
||||||
char *recent_lua[] = {0,0,0,0,0};
|
char *recent_lua[] = {0,0,0,0,0};
|
||||||
const unsigned int LUA_FIRST_RECENT_FILE = 50000;
|
const unsigned int LUA_FIRST_RECENT_FILE = 50000;
|
||||||
|
@ -371,6 +374,7 @@ void UpdateCheckedMenuItems()
|
||||||
}
|
}
|
||||||
//File Maneu
|
//File Maneu
|
||||||
CheckMenuItem(fceumenu, ID_FILE_MOVIE_TOGGLEREAD, movie_readonly ? MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(fceumenu, ID_FILE_MOVIE_TOGGLEREAD, movie_readonly ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
CheckMenuItem(fceumenu, ID_FILE_OPENLUAWINDOW, LuaConsoleHWnd ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
|
||||||
//NES Menu
|
//NES Menu
|
||||||
CheckMenuItem(fceumenu, ID_NES_PAUSE, EmulationPaused ? MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(fceumenu, ID_NES_PAUSE, EmulationPaused ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
@ -507,7 +511,7 @@ void UpdateContextMenuItems(HMENU context, int whichContext)
|
||||||
EnableMenuItem(context,FCEUX_CONTEXT_RECENTROM1,MF_BYCOMMAND | MF_GRAYED);
|
EnableMenuItem(context,FCEUX_CONTEXT_RECENTROM1,MF_BYCOMMAND | MF_GRAYED);
|
||||||
|
|
||||||
//Add Lua separator if either lua condition is true (yeah, a little ugly but it works)
|
//Add Lua separator if either lua condition is true (yeah, a little ugly but it works)
|
||||||
if (recent_lua[0] || luaRunning)
|
if (recent_lua[0] || FCEU_LuaRunning())
|
||||||
InsertMenu(context, 0xFFFF, MF_SEPARATOR, 0, "");
|
InsertMenu(context, 0xFFFF, MF_SEPARATOR, 0, "");
|
||||||
|
|
||||||
//If a recent lua file exists, add Load Last Lua
|
//If a recent lua file exists, add Load Last Lua
|
||||||
|
@ -515,8 +519,8 @@ void UpdateContextMenuItems(HMENU context, int whichContext)
|
||||||
InsertMenu(context, 0xFFFF, MF_BYCOMMAND, FCEUX_CONTEXT_LOADLASTLUA, "Load last Lua");
|
InsertMenu(context, 0xFFFF, MF_BYCOMMAND, FCEUX_CONTEXT_LOADLASTLUA, "Load last Lua");
|
||||||
|
|
||||||
//If lua is loaded, add a stop lua item
|
//If lua is loaded, add a stop lua item
|
||||||
if (luaRunning)
|
if (FCEU_LuaRunning())
|
||||||
InsertMenu(context, 0xFFFF, MF_BYCOMMAND, FCEUX_CONTEXT_STOPLUA, "Stop Lua script");
|
InsertMenu(context, 0xFFFF, MF_BYCOMMAND, FCEUX_CONTEXT_CLOSELUAWINDOWS, "Close All Script Windows");
|
||||||
|
|
||||||
//If menu is hidden, add an Unhide menu option
|
//If menu is hidden, add an Unhide menu option
|
||||||
if (tog)
|
if (tog)
|
||||||
|
@ -1500,15 +1504,31 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Lua submenu
|
//Lua submenu
|
||||||
case ID_FILE_RUNLUASCRIPT:
|
case ID_FILE_OPENLUAWINDOW:
|
||||||
FCEUD_LuaRunFrom();
|
if(!LuaConsoleHWnd)
|
||||||
|
LuaConsoleHWnd = CreateDialog(fceu_hInstance, MAKEINTRESOURCE(IDD_LUA), hWnd, (DLGPROC) DlgLuaScriptDialog);
|
||||||
|
else
|
||||||
|
SetForegroundWindow(LuaConsoleHWnd);
|
||||||
break;
|
break;
|
||||||
case FCEUX_CONTEXT_STOPLUA:
|
case FCEUX_CONTEXT_CLOSELUAWINDOWS:
|
||||||
case ID_FILE_STOPLUASCRIPT:
|
case ID_FILE_CLOSELUAWINDOWS:
|
||||||
FCEU_LuaStop();
|
if(LuaConsoleHWnd)
|
||||||
|
PostMessage(LuaConsoleHWnd, WM_CLOSE, 0, 0);
|
||||||
break;
|
break;
|
||||||
case ID_FILE_LUA_RELOADLUASCRIPT:
|
//Recent Lua 1
|
||||||
FCEU_ReloadLuaCode();
|
case FCEUX_CONTEXT_LOADLASTLUA:
|
||||||
|
if(recent_lua[0])
|
||||||
|
{
|
||||||
|
if (!FCEU_LoadLuaCode(recent_lua[0]))
|
||||||
|
{
|
||||||
|
int result = MessageBox(hWnd,"Remove from list?", "Could Not Open Recent File", MB_YESNO);
|
||||||
|
if (result == IDYES)
|
||||||
|
{
|
||||||
|
RemoveRecentItem(0, recent_lua, MAX_NUMBER_OF_LUA_RECENT_FILES);
|
||||||
|
UpdateLuaRMenu(recentluamenu, recent_lua, MENU_LUA_RECENT, LUA_FIRST_RECENT_FILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MENU_EXIT:
|
case MENU_EXIT:
|
||||||
|
@ -1864,22 +1884,6 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Recent Lua 1
|
|
||||||
case FCEUX_CONTEXT_LOADLASTLUA:
|
|
||||||
if(recent_lua[0])
|
|
||||||
{
|
|
||||||
if (!FCEU_LoadLuaCode(recent_lua[0]))
|
|
||||||
{
|
|
||||||
int result = MessageBox(hWnd,"Remove from list?", "Could Not Open Recent File", MB_YESNO);
|
|
||||||
if (result == IDYES)
|
|
||||||
{
|
|
||||||
RemoveRecentItem(0, recent_lua, MAX_NUMBER_OF_LUA_RECENT_FILES);
|
|
||||||
UpdateLuaRMenu(recentluamenu, recent_lua, MENU_LUA_RECENT, LUA_FIRST_RECENT_FILE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
//Recent Movie 1
|
//Recent Movie 1
|
||||||
case FCEUX_CONTEXT_LOADLASTMOVIE:
|
case FCEUX_CONTEXT_LOADLASTMOVIE:
|
||||||
if(recent_movie[0])
|
if(recent_movie[0])
|
||||||
|
@ -2052,7 +2056,7 @@ adelikat: Outsourced this to a remappable hotkey
|
||||||
EnableMenuItem(fceumenu,MENU_VIEWSAVESLOTS,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_VIEWSLOTS)?MF_ENABLED:MF_GRAYED));
|
EnableMenuItem(fceumenu,MENU_VIEWSAVESLOTS,MF_BYCOMMAND | (FCEU_IsValidUI(FCEUI_VIEWSLOTS)?MF_ENABLED:MF_GRAYED));
|
||||||
EnableMenuItem(fceumenu,MENU_STOP_AVI,MF_BYCOMMAND | (FCEUI_AviIsRecording()?MF_ENABLED:MF_GRAYED));
|
EnableMenuItem(fceumenu,MENU_STOP_AVI,MF_BYCOMMAND | (FCEUI_AviIsRecording()?MF_ENABLED:MF_GRAYED));
|
||||||
EnableMenuItem(fceumenu,MENU_STOP_WAV,MF_BYCOMMAND | (loggingSound?MF_ENABLED:MF_GRAYED));
|
EnableMenuItem(fceumenu,MENU_STOP_WAV,MF_BYCOMMAND | (loggingSound?MF_ENABLED:MF_GRAYED));
|
||||||
EnableMenuItem(fceumenu,ID_FILE_STOPLUASCRIPT,MF_BYCOMMAND | (luaRunning?MF_ENABLED:MF_GRAYED));
|
EnableMenuItem(fceumenu,ID_FILE_CLOSELUAWINDOWS,MF_BYCOMMAND | (LuaConsoleHWnd?MF_ENABLED:MF_GRAYED));
|
||||||
|
|
||||||
CheckMenuItem(fceumenu, ID_NEWPPU, newppu ? MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(fceumenu, ID_NEWPPU, newppu ? MF_CHECKED : MF_UNCHECKED);
|
||||||
CheckMenuItem(fceumenu, ID_OLDPPU, !newppu ? MF_CHECKED : MF_UNCHECKED);
|
CheckMenuItem(fceumenu, ID_OLDPPU, !newppu ? MF_CHECKED : MF_UNCHECKED);
|
||||||
|
@ -2376,102 +2380,6 @@ bool FCEUD_PauseAfterPlayback()
|
||||||
return pauseAfterPlayback!=0;
|
return pauseAfterPlayback!=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR CALLBACK DlgLuaScriptDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
|
|
||||||
|
|
||||||
static int *success;
|
|
||||||
|
|
||||||
switch (msg) {
|
|
||||||
case WM_INITDIALOG:
|
|
||||||
{
|
|
||||||
|
|
||||||
// Nothing very useful to do
|
|
||||||
success = (int*)lParam;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WM_COMMAND:
|
|
||||||
switch (LOWORD(wParam)) {
|
|
||||||
case IDOK:
|
|
||||||
{
|
|
||||||
char filename[MAX_PATH];
|
|
||||||
GetDlgItemText(hDlg, 1096, filename, MAX_PATH);
|
|
||||||
if (FCEU_LoadLuaCode(filename)) {
|
|
||||||
*success = 1;
|
|
||||||
// For user's convenience, don't close dialog unless we're done.
|
|
||||||
// Users who make syntax errors and fix/reload will thank us.
|
|
||||||
EndDialog(hDlg, 1);
|
|
||||||
} else {
|
|
||||||
//MessageBox(hDlg, "Couldn't load script.", "Oops", MB_OK); // XXX better if errors are displayed by the Lua code.
|
|
||||||
*success = 0;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
case IDCANCEL:
|
|
||||||
{
|
|
||||||
EndDialog(hDlg, 0);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
case 1359:
|
|
||||||
{
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
char szFileName[MAX_PATH];
|
|
||||||
szFileName[0] = '\0';
|
|
||||||
ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) );
|
|
||||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
||||||
ofn.hwndOwner = hDlg;
|
|
||||||
ofn.lpstrFilter = "Lua scripts\0*.lua\0All files\0*.*\0\0";
|
|
||||||
ofn.lpstrFile = szFileName;
|
|
||||||
ofn.lpstrDefExt = "lua";
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; // hide previously-ignored read-only checkbox (the real read-only box is in the open-movie dialog itself)
|
|
||||||
if(GetOpenFileName( &ofn ))
|
|
||||||
{
|
|
||||||
SetWindowText(GetDlgItem(hDlg, 1096), szFileName);
|
|
||||||
}
|
|
||||||
//SetCurrentDirectory(movieDirectory);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
//char message[1024];
|
|
||||||
// sprintf(message, "Unkonwn command %d,%d",msg,wParam);
|
|
||||||
//MessageBox(hDlg, message, TEXT("Range Error"), MB_OK);
|
|
||||||
|
|
||||||
// printf("Unknown entry %d,%d,%d\n",msg,wParam,lParam);
|
|
||||||
// All else, fall off
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCEUD_LuaRunFrom(void)
|
|
||||||
{
|
|
||||||
int success = 0;
|
|
||||||
|
|
||||||
//mbg 8/2/08 - i decided i didnt like this dialog box. so for now we are just going to run the script directly
|
|
||||||
//DialogBoxParam(fceu_hInstance, "IDD_LUA_ADD", hAppWnd, DlgLuaScriptDialog,(LPARAM) &success);
|
|
||||||
|
|
||||||
OPENFILENAME ofn;
|
|
||||||
char szFileName[MAX_PATH];
|
|
||||||
szFileName[0] = '\0';
|
|
||||||
ZeroMemory( (LPVOID)&ofn, sizeof(OPENFILENAME) );
|
|
||||||
ofn.lStructSize = sizeof(OPENFILENAME);
|
|
||||||
ofn.hwndOwner = hAppWnd;
|
|
||||||
ofn.lpstrFilter = "Lua scripts (*.lua)\0*.lua\0All files (*.*)\0*.*\0\0";
|
|
||||||
ofn.lpstrFile = szFileName;
|
|
||||||
ofn.lpstrDefExt = "lua";
|
|
||||||
ofn.nMaxFile = MAX_PATH;
|
|
||||||
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; // hide previously-ignored read-only checkbox (the real read-only box is in the open-movie dialog itself)
|
|
||||||
std::string initdir = FCEU_GetPath(FCEUMKF_LUA);
|
|
||||||
ofn.lpstrInitialDir=initdir.c_str();
|
|
||||||
if(GetOpenFileName( &ofn ))
|
|
||||||
{
|
|
||||||
AddRecentLuaFile(szFileName);
|
|
||||||
FCEU_LoadLuaCode(szFileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChangeContextMenuItemText(int menuitem, string text, HMENU menu)
|
void ChangeContextMenuItemText(int menuitem, string text, HMENU menu)
|
||||||
{
|
{
|
||||||
MENUITEMINFO moo;
|
MENUITEMINFO moo;
|
||||||
|
@ -2585,11 +2493,6 @@ void UpdateMenuHotkeys()
|
||||||
combined = "&Stop AVI\t" + combo;
|
combined = "&Stop AVI\t" + combo;
|
||||||
ChangeMenuItemText(MENU_STOP_AVI, combined);
|
ChangeMenuItemText(MENU_STOP_AVI, combined);
|
||||||
|
|
||||||
//Reload Lua Script
|
|
||||||
combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_SCRIPT_RELOAD]);
|
|
||||||
combined = "&Reload Lua Script\t" + combo;
|
|
||||||
ChangeMenuItemText(ID_FILE_LUA_RELOADLUASCRIPT, combined);
|
|
||||||
|
|
||||||
//-------------------------------NES----------------------------------------
|
//-------------------------------NES----------------------------------------
|
||||||
//Reset
|
//Reset
|
||||||
combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_RESET]);
|
combo = GetKeyComboName(FCEUD_CommandMapping[EMUCMD_RESET]);
|
||||||
|
|
|
@ -40,6 +40,8 @@ int FCEU_LuaRerecordCountSkip();
|
||||||
void FCEU_LuaGui(uint8 *XBuf);
|
void FCEU_LuaGui(uint8 *XBuf);
|
||||||
void FCEU_LuaUpdatePalette();
|
void FCEU_LuaUpdatePalette();
|
||||||
|
|
||||||
|
char* FCEU_GetLuaScriptName();
|
||||||
|
|
||||||
// And some interesting REVERSE declarations!
|
// And some interesting REVERSE declarations!
|
||||||
char *FCEU_GetFreezeFilename(int slot);
|
char *FCEU_GetFreezeFilename(int slot);
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,18 @@ struct LuaSaveState {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void(*info_print)(int uid, const char* str);
|
||||||
|
static void(*info_onstart)(int uid);
|
||||||
|
static void(*info_onstop)(int uid);
|
||||||
|
static int info_uid;
|
||||||
|
#ifdef WIN32
|
||||||
|
extern HWND LuaConsoleHWnd;
|
||||||
|
extern INT_PTR CALLBACK DlgLuaScriptDialog(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||||
|
extern void PrintToWindowConsole(int hDlgAsInt, const char* str);
|
||||||
|
extern void WinLuaOnStart(int hDlgAsInt);
|
||||||
|
extern void WinLuaOnStop(int hDlgAsInt);
|
||||||
|
#endif
|
||||||
|
|
||||||
static lua_State *L;
|
static lua_State *L;
|
||||||
|
|
||||||
// Are we running any code right now?
|
// Are we running any code right now?
|
||||||
|
@ -148,6 +160,14 @@ static const char *button_mappings[] = {
|
||||||
"A", "B", "select", "start", "up", "down", "left", "right"
|
"A", "B", "select", "start", "up", "down", "left", "right"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define vscprintf _vscprintf
|
||||||
|
#else
|
||||||
|
#define stricmp strcasecmp
|
||||||
|
#define strnicmp strncasecmp
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char* luaCallIDStrings [] =
|
static const char* luaCallIDStrings [] =
|
||||||
{
|
{
|
||||||
"CALL_BEFOREEMULATION",
|
"CALL_BEFOREEMULATION",
|
||||||
|
@ -172,6 +192,9 @@ static const char* luaMemHookTypeStrings [] =
|
||||||
//make sure we have the right number of strings
|
//make sure we have the right number of strings
|
||||||
CTASSERT(sizeof(luaMemHookTypeStrings)/sizeof(*luaMemHookTypeStrings) == LUAMEMHOOK_COUNT)
|
CTASSERT(sizeof(luaMemHookTypeStrings)/sizeof(*luaMemHookTypeStrings) == LUAMEMHOOK_COUNT)
|
||||||
|
|
||||||
|
static char* rawToCString(lua_State* L, int idx=0);
|
||||||
|
static const char* toCString(lua_State* L, int idx=0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets emulator speed / pause states after script exit.
|
* Resets emulator speed / pause states after script exit.
|
||||||
*/
|
*/
|
||||||
|
@ -435,6 +458,320 @@ static int memory_readbyterange(lua_State *L) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isalphaorunderscore(char c)
|
||||||
|
{
|
||||||
|
return isalpha(c) || c == '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<const void*> s_tableAddressStack; // prevents infinite recursion of a table within a table (when cycle is found, print something like table:parent)
|
||||||
|
static std::vector<const void*> s_metacallStack; // prevents infinite recursion if something's __tostring returns another table that contains that something (when cycle is found, print the inner result without using __tostring)
|
||||||
|
|
||||||
|
#define APPENDPRINT { int _n = snprintf(ptr, remaining,
|
||||||
|
#define END ); if(_n >= 0) { ptr += _n; remaining -= _n; } else { remaining = 0; } }
|
||||||
|
static void toCStringConverter(lua_State* L, int i, char*& ptr, int& remaining)
|
||||||
|
{
|
||||||
|
if(remaining <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char* str = ptr; // for debugging
|
||||||
|
|
||||||
|
// if there is a __tostring metamethod then call it
|
||||||
|
int usedMeta = luaL_callmeta(L, i, "__tostring");
|
||||||
|
if(usedMeta)
|
||||||
|
{
|
||||||
|
std::vector<const void*>::const_iterator foundCycleIter = std::find(s_metacallStack.begin(), s_metacallStack.end(), lua_topointer(L,i));
|
||||||
|
if(foundCycleIter != s_metacallStack.end())
|
||||||
|
{
|
||||||
|
lua_pop(L, 1);
|
||||||
|
usedMeta = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_metacallStack.push_back(lua_topointer(L,i));
|
||||||
|
i = lua_gettop(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(lua_type(L, i))
|
||||||
|
{
|
||||||
|
case LUA_TNONE: break;
|
||||||
|
case LUA_TNIL: APPENDPRINT "nil" END break;
|
||||||
|
case LUA_TBOOLEAN: APPENDPRINT lua_toboolean(L,i) ? "true" : "false" END break;
|
||||||
|
case LUA_TSTRING: APPENDPRINT "%s",lua_tostring(L,i) END break;
|
||||||
|
case LUA_TNUMBER: APPENDPRINT "%.12Lg",lua_tonumber(L,i) END break;
|
||||||
|
case LUA_TFUNCTION:
|
||||||
|
/*if((L->base + i-1)->value.gc->cl.c.isC)
|
||||||
|
{
|
||||||
|
//lua_CFunction func = lua_tocfunction(L, i);
|
||||||
|
//std::map<lua_CFunction, const char*>::iterator iter = s_cFuncInfoMap.find(func);
|
||||||
|
//if(iter == s_cFuncInfoMap.end())
|
||||||
|
goto defcase;
|
||||||
|
//APPENDPRINT "function(%s)", iter->second END
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
APPENDPRINT "function(" END
|
||||||
|
Proto* p = (L->base + i-1)->value.gc->cl.l.p;
|
||||||
|
int numParams = p->numparams + (p->is_vararg?1:0);
|
||||||
|
for (int n=0; n<p->numparams; n++)
|
||||||
|
{
|
||||||
|
APPENDPRINT "%s", getstr(p->locvars[n].varname) END
|
||||||
|
if(n != numParams-1)
|
||||||
|
APPENDPRINT "," END
|
||||||
|
}
|
||||||
|
if(p->is_vararg)
|
||||||
|
APPENDPRINT "..." END
|
||||||
|
APPENDPRINT ")" END
|
||||||
|
}*/
|
||||||
|
goto defcase;
|
||||||
|
break;
|
||||||
|
defcase:default: APPENDPRINT "%s:%p",luaL_typename(L,i),lua_topointer(L,i) END break;
|
||||||
|
case LUA_TTABLE:
|
||||||
|
{
|
||||||
|
// first make sure there's enough stack space
|
||||||
|
if(!lua_checkstack(L, 4))
|
||||||
|
{
|
||||||
|
// note that even if lua_checkstack never returns false,
|
||||||
|
// that doesn't mean we didn't need to call it,
|
||||||
|
// because calling it retrieves stack space past LUA_MINSTACK
|
||||||
|
goto defcase;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const void*>::const_iterator foundCycleIter = std::find(s_tableAddressStack.begin(), s_tableAddressStack.end(), lua_topointer(L,i));
|
||||||
|
if(foundCycleIter != s_tableAddressStack.end())
|
||||||
|
{
|
||||||
|
int parentNum = s_tableAddressStack.end() - foundCycleIter;
|
||||||
|
if(parentNum > 1)
|
||||||
|
APPENDPRINT "%s:parent^%d",luaL_typename(L,i),parentNum END
|
||||||
|
else
|
||||||
|
APPENDPRINT "%s:parent",luaL_typename(L,i) END
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_tableAddressStack.push_back(lua_topointer(L,i));
|
||||||
|
struct Scope { ~Scope(){ s_tableAddressStack.pop_back(); } } scope;
|
||||||
|
|
||||||
|
APPENDPRINT "{" END
|
||||||
|
|
||||||
|
lua_pushnil(L); // first key
|
||||||
|
int keyIndex = lua_gettop(L);
|
||||||
|
int valueIndex = keyIndex + 1;
|
||||||
|
bool first = true;
|
||||||
|
bool skipKey = true; // true if we're still in the "array part" of the table
|
||||||
|
lua_Number arrayIndex = (lua_Number)0;
|
||||||
|
while(lua_next(L, i))
|
||||||
|
{
|
||||||
|
if(first)
|
||||||
|
first = false;
|
||||||
|
else
|
||||||
|
APPENDPRINT ", " END
|
||||||
|
if(skipKey)
|
||||||
|
{
|
||||||
|
arrayIndex += (lua_Number)1;
|
||||||
|
bool keyIsNumber = (lua_type(L, keyIndex) == LUA_TNUMBER);
|
||||||
|
skipKey = keyIsNumber && (lua_tonumber(L, keyIndex) == arrayIndex);
|
||||||
|
}
|
||||||
|
if(!skipKey)
|
||||||
|
{
|
||||||
|
bool keyIsString = (lua_type(L, keyIndex) == LUA_TSTRING);
|
||||||
|
bool invalidLuaIdentifier = (!keyIsString || !isalphaorunderscore(*lua_tostring(L, keyIndex)));
|
||||||
|
if(invalidLuaIdentifier)
|
||||||
|
if(keyIsString)
|
||||||
|
APPENDPRINT "['" END
|
||||||
|
else
|
||||||
|
APPENDPRINT "[" END
|
||||||
|
|
||||||
|
toCStringConverter(L, keyIndex, ptr, remaining); // key
|
||||||
|
|
||||||
|
if(invalidLuaIdentifier)
|
||||||
|
if(keyIsString)
|
||||||
|
APPENDPRINT "']=" END
|
||||||
|
else
|
||||||
|
APPENDPRINT "]=" END
|
||||||
|
else
|
||||||
|
APPENDPRINT "=" END
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valueIsString = (lua_type(L, valueIndex) == LUA_TSTRING);
|
||||||
|
if(valueIsString)
|
||||||
|
APPENDPRINT "'" END
|
||||||
|
|
||||||
|
toCStringConverter(L, valueIndex, ptr, remaining); // value
|
||||||
|
|
||||||
|
if(valueIsString)
|
||||||
|
APPENDPRINT "'" END
|
||||||
|
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
if(remaining <= 0)
|
||||||
|
{
|
||||||
|
lua_settop(L, keyIndex-1); // stack might not be clean yet if we're breaking early
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
APPENDPRINT "}" END
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(usedMeta)
|
||||||
|
{
|
||||||
|
s_metacallStack.pop_back();
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int s_tempStrMaxLen = 64 * 1024;
|
||||||
|
static char s_tempStr [s_tempStrMaxLen];
|
||||||
|
|
||||||
|
static char* rawToCString(lua_State* L, int idx)
|
||||||
|
{
|
||||||
|
int a = idx>0 ? idx : 1;
|
||||||
|
int n = idx>0 ? idx : lua_gettop(L);
|
||||||
|
|
||||||
|
char* ptr = s_tempStr;
|
||||||
|
*ptr = 0;
|
||||||
|
|
||||||
|
int remaining = s_tempStrMaxLen;
|
||||||
|
for(int i = a; i <= n; i++)
|
||||||
|
{
|
||||||
|
toCStringConverter(L, i, ptr, remaining);
|
||||||
|
if(i != n)
|
||||||
|
APPENDPRINT " " END
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remaining < 3)
|
||||||
|
{
|
||||||
|
while(remaining < 6)
|
||||||
|
remaining++, ptr--;
|
||||||
|
APPENDPRINT "..." END
|
||||||
|
}
|
||||||
|
APPENDPRINT "\r\n" END
|
||||||
|
// the trailing newline is so print() can avoid having to do wasteful things to print its newline
|
||||||
|
// (string copying would be wasteful and calling info.print() twice can be extremely slow)
|
||||||
|
// at the cost of functions that don't want the newline needing to trim off the last two characters
|
||||||
|
// (which is a very fast operation and thus acceptable in this case)
|
||||||
|
|
||||||
|
return s_tempStr;
|
||||||
|
}
|
||||||
|
#undef APPENDPRINT
|
||||||
|
#undef END
|
||||||
|
|
||||||
|
|
||||||
|
// replacement for luaB_tostring() that is able to show the contents of tables (and formats numbers better, and show function prototypes)
|
||||||
|
// can be called directly from lua via tostring(), assuming tostring hasn't been reassigned
|
||||||
|
static int tostring(lua_State *L)
|
||||||
|
{
|
||||||
|
char* str = rawToCString(L);
|
||||||
|
str[strlen(str)-2] = 0; // hack: trim off the \r\n (which is there to simplify the print function's task)
|
||||||
|
lua_pushstring(L, str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// like rawToCString, but will check if the global Lua function tostring()
|
||||||
|
// has been replaced with a custom function, and call that instead if so
|
||||||
|
static const char* toCString(lua_State* L, int idx)
|
||||||
|
{
|
||||||
|
int a = idx>0 ? idx : 1;
|
||||||
|
int n = idx>0 ? idx : lua_gettop(L);
|
||||||
|
lua_getglobal(L, "tostring");
|
||||||
|
lua_CFunction cf = lua_tocfunction(L,-1);
|
||||||
|
if(cf == tostring) // optimization: if using our own C tostring function, we can bypass the call through Lua and all the string object allocation that would entail
|
||||||
|
{
|
||||||
|
lua_pop(L,1);
|
||||||
|
return rawToCString(L, idx);
|
||||||
|
}
|
||||||
|
else // if the user overrided the tostring function, we have to actually call it and store the temporarily allocated string it returns
|
||||||
|
{
|
||||||
|
lua_pushstring(L, "");
|
||||||
|
for (int i=a; i<=n; i++) {
|
||||||
|
lua_pushvalue(L, -2); // function to be called
|
||||||
|
lua_pushvalue(L, i); // value to print
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
if(lua_tostring(L, -1) == NULL)
|
||||||
|
luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print"));
|
||||||
|
lua_pushstring(L, (i<n) ? " " : "\r\n");
|
||||||
|
lua_concat(L, 3);
|
||||||
|
}
|
||||||
|
const char* str = lua_tostring(L, -1);
|
||||||
|
strncpy(s_tempStr, str, s_tempStrMaxLen);
|
||||||
|
s_tempStr[s_tempStrMaxLen-1] = 0;
|
||||||
|
lua_pop(L, 2);
|
||||||
|
return s_tempStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// replacement for luaB_print() that goes to the appropriate textbox instead of stdout
|
||||||
|
static int print(lua_State *L)
|
||||||
|
{
|
||||||
|
const char* str = toCString(L);
|
||||||
|
|
||||||
|
int uid = info_uid;//luaStateToUIDMap[L->l_G->mainthread];
|
||||||
|
//LuaContextInfo& info = GetCurrentInfo();
|
||||||
|
|
||||||
|
if(info_print)
|
||||||
|
info_print(uid, str);
|
||||||
|
else
|
||||||
|
puts(str);
|
||||||
|
|
||||||
|
//worry(L, 100);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// provides an easy way to copy a table from Lua
|
||||||
|
// (simple assignment only makes an alias, but sometimes an independent table is desired)
|
||||||
|
// currently this function only performs a shallow copy,
|
||||||
|
// but I think it should be changed to do a deep copy (possibly of configurable depth?)
|
||||||
|
// that maintains the internal table reference structure
|
||||||
|
static int copytable(lua_State *L)
|
||||||
|
{
|
||||||
|
int origIndex = 1; // we only care about the first argument
|
||||||
|
int origType = lua_type(L, origIndex);
|
||||||
|
if(origType == LUA_TNIL)
|
||||||
|
{
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(origType != LUA_TTABLE)
|
||||||
|
{
|
||||||
|
luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE));
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_createtable(L, lua_objlen(L,1), 0);
|
||||||
|
int copyIndex = lua_gettop(L);
|
||||||
|
|
||||||
|
lua_pushnil(L); // first key
|
||||||
|
int keyIndex = lua_gettop(L);
|
||||||
|
int valueIndex = keyIndex + 1;
|
||||||
|
|
||||||
|
while(lua_next(L, origIndex))
|
||||||
|
{
|
||||||
|
lua_pushvalue(L, keyIndex);
|
||||||
|
lua_pushvalue(L, valueIndex);
|
||||||
|
lua_rawset(L, copyIndex); // copytable[key] = value
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy the reference to the metatable as well, if any
|
||||||
|
if(lua_getmetatable(L, origIndex))
|
||||||
|
lua_setmetatable(L, copyIndex);
|
||||||
|
|
||||||
|
return 1; // return the new table
|
||||||
|
}
|
||||||
|
|
||||||
|
// because print traditionally shows the address of tables,
|
||||||
|
// and the print function I provide instead shows the contents of tables,
|
||||||
|
// I also provide this function
|
||||||
|
// (otherwise there would be no way to see a table's address, AFAICT)
|
||||||
|
static int addressof(lua_State *L)
|
||||||
|
{
|
||||||
|
const void* ptr = lua_topointer(L,-1);
|
||||||
|
lua_pushinteger(L, (lua_Integer)ptr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
struct registerPointerMap
|
struct registerPointerMap
|
||||||
{
|
{
|
||||||
const char* registerName;
|
const char* registerName;
|
||||||
|
@ -875,7 +1212,7 @@ static int memory_registerexec(lua_State *L)
|
||||||
|
|
||||||
//adelikat: table pulled from GENS. credz nitsuja!
|
//adelikat: table pulled from GENS. credz nitsuja!
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef WIN32
|
||||||
const char* s_keyToName[256] =
|
const char* s_keyToName[256] =
|
||||||
{
|
{
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -989,7 +1326,7 @@ const char* s_keyToName[256] =
|
||||||
static int input_get(lua_State *L) {
|
static int input_get(lua_State *L) {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef WIN32
|
||||||
// keyboard and mouse button status
|
// keyboard and mouse button status
|
||||||
{
|
{
|
||||||
extern int EnableBackgroundInput;
|
extern int EnableBackgroundInput;
|
||||||
|
@ -2967,7 +3304,7 @@ bool luabitop_validate(lua_State *L) // originally named as luaopen_bit
|
||||||
if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */
|
if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */
|
||||||
const char *msg = "compiled with incompatible luaconf.h";
|
const char *msg = "compiled with incompatible luaconf.h";
|
||||||
#ifdef LUA_NUMBER_DOUBLE
|
#ifdef LUA_NUMBER_DOUBLE
|
||||||
#ifdef _WIN32
|
#ifdef WIN32
|
||||||
if (b == (UBits)1610612736L)
|
if (b == (UBits)1610612736L)
|
||||||
msg = "use D3DCREATE_FPU_PRESERVE with DirectX";
|
msg = "use D3DCREATE_FPU_PRESERVE with DirectX";
|
||||||
#endif
|
#endif
|
||||||
|
@ -3144,6 +3481,7 @@ static const struct luaL_reg emulib [] = {
|
||||||
{"registerexit", emu_registerexit},
|
{"registerexit", emu_registerexit},
|
||||||
{"readonly", movie_getreadonly},
|
{"readonly", movie_getreadonly},
|
||||||
{"setreadonly", movie_setreadonly},
|
{"setreadonly", movie_setreadonly},
|
||||||
|
{"print", print}, // sure, why not
|
||||||
{NULL,NULL}
|
{NULL,NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3324,7 +3662,7 @@ void FCEU_LuaFrameBoundary() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
FCEU_LuaStop();
|
FCEU_LuaOnStop();
|
||||||
FCEU_DispMessage("Script died of natural causes.\n");
|
FCEU_DispMessage("Script died of natural causes.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3383,6 +3721,12 @@ int FCEU_LoadLuaCode(const char *filename) {
|
||||||
luaL_register(L, "bit", bit_funcs); // LuaBitOp library
|
luaL_register(L, "bit", bit_funcs); // LuaBitOp library
|
||||||
lua_settop(L, 0); // clean the stack, because each call to luaL_register leaves a table on top
|
lua_settop(L, 0); // clean the stack, because each call to luaL_register leaves a table on top
|
||||||
|
|
||||||
|
// register a few utility functions outside of libraries (in the global namespace)
|
||||||
|
lua_register(L, "print", print);
|
||||||
|
lua_register(L, "tostring", tostring);
|
||||||
|
lua_register(L, "addressof", addressof);
|
||||||
|
lua_register(L, "copytable", copytable);
|
||||||
|
|
||||||
// old bit operation functions
|
// old bit operation functions
|
||||||
lua_register(L, "AND", bit_band);
|
lua_register(L, "AND", bit_band);
|
||||||
lua_register(L, "OR", bit_bor);
|
lua_register(L, "OR", bit_bor);
|
||||||
|
@ -3446,6 +3790,21 @@ int FCEU_LoadLuaCode(const char *filename) {
|
||||||
// Set up our protection hook to be executed once every 10,000 bytecode instructions.
|
// Set up our protection hook to be executed once every 10,000 bytecode instructions.
|
||||||
//lua_sethook(thread, FCEU_LuaHookFunction, LUA_MASKCOUNT, 10000);
|
//lua_sethook(thread, FCEU_LuaHookFunction, LUA_MASKCOUNT, 10000);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
info_print = PrintToWindowConsole;
|
||||||
|
info_onstart = WinLuaOnStart;
|
||||||
|
info_onstop = WinLuaOnStop;
|
||||||
|
if(!LuaConsoleHWnd)
|
||||||
|
LuaConsoleHWnd = CreateDialog(fceu_hInstance, MAKEINTRESOURCE(IDD_LUA), hAppWnd, (DLGPROC) DlgLuaScriptDialog);
|
||||||
|
info_uid = (int)LuaConsoleHWnd;
|
||||||
|
#else
|
||||||
|
info_print = NULL;
|
||||||
|
info_onstart = NULL;
|
||||||
|
info_onstop = NULL;
|
||||||
|
#endif
|
||||||
|
if (info_onstart)
|
||||||
|
info_onstart(info_uid);
|
||||||
|
|
||||||
// We're done.
|
// We're done.
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -3486,6 +3845,9 @@ void FCEU_LuaStop() {
|
||||||
CoInitialize(0);
|
CoInitialize(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (info_onstop)
|
||||||
|
info_onstop(info_uid);
|
||||||
|
|
||||||
//lua_gc(L,LUA_GCCOLLECT,0);
|
//lua_gc(L,LUA_GCCOLLECT,0);
|
||||||
|
|
||||||
|
|
||||||
|
@ -3499,7 +3861,8 @@ void FCEU_LuaStop() {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int FCEU_LuaRunning() {
|
int FCEU_LuaRunning() {
|
||||||
return L && luaRunning;
|
// FIXME: return false when no callback functions are registered.
|
||||||
|
return (int) (L != NULL); // should return true if callback functions are active.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3542,6 +3905,7 @@ uint8 FCEU_LuaReadJoypad(int which, uint8 joyl) {
|
||||||
* This function will not return true if a script is not running.
|
* This function will not return true if a script is not running.
|
||||||
*/
|
*/
|
||||||
int FCEU_LuaRerecordCountSkip() {
|
int FCEU_LuaRerecordCountSkip() {
|
||||||
|
// FIXME: return true if (there are any active callback functions && skipRerecords)
|
||||||
return L && luaRunning && skipRerecords;
|
return L && luaRunning && skipRerecords;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3554,7 +3918,7 @@ int FCEU_LuaRerecordCountSkip() {
|
||||||
*/
|
*/
|
||||||
void FCEU_LuaGui(uint8 *XBuf) {
|
void FCEU_LuaGui(uint8 *XBuf) {
|
||||||
|
|
||||||
if (!L || !luaRunning)
|
if (!L/* || !luaRunning*/)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// First, check if we're being called by anybody
|
// First, check if we're being called by anybody
|
||||||
|
@ -3623,3 +3987,10 @@ void FCEU_LuaGui(uint8 *XBuf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
lua_State* FCEU_GetLuaState() {
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
char* FCEU_GetLuaScriptName() {
|
||||||
|
return luaScriptName;
|
||||||
|
}
|
||||||
|
|
|
@ -1076,6 +1076,10 @@
|
||||||
RelativePath="..\src\drivers\win\log.h"
|
RelativePath="..\src\drivers\win\log.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\drivers\win\luaconsole.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\drivers\win\main.cpp"
|
RelativePath="..\src\drivers\win\main.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1075,6 +1075,10 @@
|
||||||
RelativePath="..\src\drivers\win\log.h"
|
RelativePath="..\src\drivers\win\log.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\src\drivers\win\luaconsole.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\src\drivers\win\main.cpp"
|
RelativePath="..\src\drivers\win\main.cpp"
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in New Issue