commit
f79ebce55a
4
INSTALL
4
INSTALL
|
@ -1,9 +1,9 @@
|
|||
To compile and install FCEUX for SDL, follow the instructions in the README-SDL.md file.
|
||||
To compile and install FCEUX for SDL, follow the instructions in the README file.
|
||||
|
||||
Users of Microsoft Visual Studio can use the solution files within the vc directory. The Windows XP toolset is required to open and build this solution. If it
|
||||
is not installed, go to "Tools" > "Get Tools and Features". Select "Individual Components" and then install "C++ Windows XP Support for VS 2017 (v141) tools".
|
||||
These solution files will compile FCEUX and some included libraries for full functionality.
|
||||
|
||||
The SDL port build tool of choice has come full circle back to Cmake. The cmake build tool will compile the new Qt version of the SDL GUI.
|
||||
The scons build tool will build the older GTK based GUI which currently only builds on Linux.
|
||||
Building of the SDL fceux no longer supports use of the scons build tool.
|
||||
|
||||
|
|
26
README
26
README
|
@ -7,7 +7,7 @@ Updated By mjbudd77
|
|||
|
||||
http://www.fceux.com
|
||||
|
||||
Last Modified: July 12, 2020
|
||||
Last Modified: October 21, 2020
|
||||
|
||||
Table of Contents
|
||||
-----------------
|
||||
|
@ -22,7 +22,7 @@ Table of Contents
|
|||
|
||||
1 - Requirements
|
||||
----------------
|
||||
* sdl2 - Version >= 2.0
|
||||
* sdl2 - Version >= 2.0 (sdl2 >= 2.8 recommended)
|
||||
* cmake - Required to build fceux.
|
||||
* qt5 OR gtk3 - (qt version >= 5.11 recommended) (gtk3 >= 3.22 recommended)
|
||||
* liblua5.1 (optional) - Will statically link internally if the system cannot provide this.
|
||||
|
@ -37,15 +37,19 @@ The old scons build system is no longer supported.
|
|||
Fceux can be compiled and built using the cmake build system. To compile, run:
|
||||
|
||||
mkdir build; cd build;
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .. # For a release build
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release .. # For a release build
|
||||
|
||||
To build a binary with debug information included in it:
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
|
||||
The Qt version of the GUI builds by default and this is the preferred GUI for use.
|
||||
For those who must have GTK/Gnome style,
|
||||
the GTK version of the GUI can be selected to build with:
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DGTK=1 .. # Release build using GTK GUI
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DGTK=1 .. # Release build using GTK GUI
|
||||
|
||||
The Qt version GUI by far exceeds the GTK gui in capability and performance.
|
||||
I HIGHLY RECOMMEND USING THE Qt GUI instead of the GTK. See the TODO-SDL file for
|
||||
a capability matrix that compares what the two GUIs can do.
|
||||
|
||||
To do the actual compiling:
|
||||
make
|
||||
|
@ -58,9 +62,8 @@ After a sucessful compilation, the fceux binary will be generated to
|
|||
|
||||
sudo make install
|
||||
|
||||
You can optionally define a install prefix when running cmake from the previous step:
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr/local install
|
||||
By default cmake will use an installation prefix of /usr/local.
|
||||
The recommended installation prefix is /usr (this is where the installed fceux.desktop file expects everything to be)
|
||||
|
||||
You can choose to install the lua scripts (located in output/luaScripts) to a directory of your choosing:
|
||||
|
||||
|
@ -88,6 +91,13 @@ OpenGL options:
|
|||
For Linux builds, the OpenGL library preference can be either GLVND or LEGACY (default).
|
||||
To use GLVND OpenGL, add a -DGLVND=1 on the cmake command line.
|
||||
|
||||
Qt Styling Options:
|
||||
The Qt GUI can use custom Qt widget styling by providing it a Qt stylesheet file. At startup, the GUI will look
|
||||
for an environment variable named FCEUX_QT_STYLESHEET that must contain the full path to the file. If the variable
|
||||
is defined and the file is readable by the program, then the styling settings will be used by the GUI.
|
||||
Bash Shell Setup Example:
|
||||
export FCEUX_QT_STYLESHEET=/home/me/myQt.stylesheet
|
||||
|
||||
5 - LUA Scripting
|
||||
-----------------
|
||||
FCEUX provides a LUA 5.1 engine that allows for in-game scripting capabilities. LUA is enabled either way. It is just a matter of whether LUA is statically linked internally or dynamically linked to a system library.
|
||||
|
|
2
TODO-SDL
2
TODO-SDL
|
@ -4,6 +4,8 @@ Priorities
|
|||
* GTK GUI was not cross-platform. A Qt5 version of the GUI has been created to meet this need.
|
||||
I will keep the GTK GUI around for Linux users who prefer it, but when it comes to adding new features
|
||||
the Qt GUI is where I plan to add them first (if at all).
|
||||
* The Qt GUI has by far exceeded the capabilities of the older GTK version. Below is a GUI capability
|
||||
matrix showing the differences between the two. I HIGHLY RECOMMEND USING THE Qt GUI.
|
||||
* Code cleanup. Lots of compiler warnings with newer GCC. Maybe I'm OCD... but these warnings bother me.
|
||||
|
||||
Features
|
||||
|
|
|
@ -81,7 +81,7 @@ else(WIN32)
|
|||
pkg_check_modules( SDL2 REQUIRED sdl2)
|
||||
|
||||
if ( ${SDL2_FOUND} )
|
||||
add_definitions( ${SDL2_CFLAGS} )
|
||||
add_definitions( ${SDL2_CFLAGS} -D__SDL__ )
|
||||
endif()
|
||||
|
||||
# Check for LUA
|
||||
|
|
|
@ -44,7 +44,7 @@ void LockConsole(void);
|
|||
void UnlockConsole(void);
|
||||
void ToggleFS(); /* SDL */
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent = false);
|
||||
int CloseGame(void);
|
||||
int GUI_Init(int argc, char **argv, int (*dofunc)(void));
|
||||
int GUI_Idle(void);
|
||||
|
|
|
@ -275,12 +275,12 @@ static void DoArgs(int argc, char *argv[])
|
|||
provides data necessary for the driver code(number of scanlines to
|
||||
render, what virtual input devices to use, etc.).
|
||||
*/
|
||||
int LoadGame(const char *path)
|
||||
int LoadGame(const char *path, bool silent)
|
||||
{
|
||||
FCEUGI *tmp;
|
||||
|
||||
CloseGame();
|
||||
if(!(tmp=FCEUI_LoadGame(path,1)))
|
||||
if(!(tmp=FCEUI_LoadGame(path,1,silent)))
|
||||
return 0;
|
||||
CurGame=tmp;
|
||||
ParseGI(tmp);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include <QUrl>
|
||||
#include <QTextEdit>
|
||||
#include <QDesktopServices>
|
||||
//#include "Qt/icon.xpm"
|
||||
#include "Qt/AboutWindow.h"
|
||||
#include "Qt/fceux_git_info.h"
|
||||
#include "../../version.h"
|
||||
|
@ -41,7 +40,6 @@ AboutWindow::AboutWindow(QWidget *parent)
|
|||
int i;
|
||||
QVBoxLayout *mainLayout;
|
||||
QHBoxLayout *hbox1;
|
||||
//QPixmap pm( icon_xpm );
|
||||
QPixmap pm(":fceux1.png");
|
||||
QPixmap pm2;
|
||||
QLabel *lbl;
|
||||
|
|
|
@ -3010,19 +3010,19 @@ void QAsmView::contextMenuEvent(QContextMenuEvent *event)
|
|||
|
||||
ctxMenuAddr = addr = asmEntry[line]->addr;
|
||||
|
||||
act = new QAction(tr("Add Breakpoint"), this);
|
||||
act = new QAction(tr("Add Breakpoint"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddBP(void)) );
|
||||
|
||||
act = new QAction(tr("Add Symbolic Debug Marker"), this);
|
||||
act = new QAction(tr("Add Symbolic Debug Marker"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddSym(void)) );
|
||||
|
||||
act = new QAction(tr("Add Bookmark"), this);
|
||||
act = new QAction(tr("Add Bookmark"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuAddBM(void)) );
|
||||
|
||||
act = new QAction(tr("Open Hex Editor"), this);
|
||||
act = new QAction(tr("Open Hex Editor"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), parent, SLOT(asmViewCtxMenuOpenHexEdit(void)) );
|
||||
|
||||
|
@ -3294,7 +3294,7 @@ void DebuggerStackDisplay::contextMenuEvent(QContextMenuEvent *event)
|
|||
menu.addAction( act );
|
||||
|
||||
subMenu = menu.addMenu(tr("Display Bytes Per Line"));
|
||||
group = new QActionGroup(this);
|
||||
group = new QActionGroup(&menu);
|
||||
|
||||
group->setExclusive(true);
|
||||
|
||||
|
|
|
@ -1753,22 +1753,22 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
|
|||
{
|
||||
case MODE_NES_RAM:
|
||||
{
|
||||
act = new QAction(tr("Add Symbolic Debug Name"), this);
|
||||
act = new QAction(tr("Add Symbolic Debug Name"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addDebugSym(void)) );
|
||||
|
||||
sprintf( stmp, "Add Read Breakpoint for Address $%04X", addr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamReadBP(void)) );
|
||||
|
||||
sprintf( stmp, "Add Write Breakpoint for Address $%04X", addr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamWriteBP(void)) );
|
||||
|
||||
sprintf( stmp, "Add Execute Breakpoint for Address $%04X", addr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addRamExecuteBP(void)) );
|
||||
|
||||
|
@ -1780,13 +1780,13 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
|
|||
{
|
||||
jumpToRomValue = romAddr;
|
||||
sprintf( stmp, "Go Here in ROM File: (%08X)", romAddr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(jumpToROM(void)) );
|
||||
}
|
||||
}
|
||||
|
||||
act = new QAction(tr("Add Bookmark"), this);
|
||||
act = new QAction(tr("Add Bookmark"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
|
||||
}
|
||||
|
@ -1794,30 +1794,30 @@ void QHexEdit::contextMenuEvent(QContextMenuEvent *event)
|
|||
case MODE_NES_PPU:
|
||||
{
|
||||
sprintf( stmp, "Add Read Breakpoint for Address $%04X", addr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addPpuReadBP(void)) );
|
||||
|
||||
sprintf( stmp, "Add Write Breakpoint for Address $%04X", addr );
|
||||
act = new QAction(tr(stmp), this);
|
||||
act = new QAction(tr(stmp), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addPpuWriteBP(void)) );
|
||||
|
||||
act = new QAction(tr("Add Bookmark"), this);
|
||||
act = new QAction(tr("Add Bookmark"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
|
||||
}
|
||||
break;
|
||||
case MODE_NES_OAM:
|
||||
{
|
||||
act = new QAction(tr("Add Bookmark"), this);
|
||||
act = new QAction(tr("Add Bookmark"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
|
||||
}
|
||||
break;
|
||||
case MODE_NES_ROM:
|
||||
{
|
||||
act = new QAction(tr("Add Bookmark"), this);
|
||||
act = new QAction(tr("Add Bookmark"), &menu);
|
||||
menu.addAction(act);
|
||||
connect( act, SIGNAL(triggered(void)), this, SLOT(addBookMarkCB(void)) );
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ void LockConsole(void);
|
|||
void UnlockConsole(void);
|
||||
void ToggleFS(); /* SDL */
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent);
|
||||
//int CloseGame(void);
|
||||
|
||||
void Giggles(int);
|
||||
|
|
|
@ -206,13 +206,23 @@ DriverKill()
|
|||
inited=0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads last game
|
||||
*/
|
||||
int reloadLastGame(void)
|
||||
{
|
||||
std::string lastRom;
|
||||
g_config->getOption(std::string("SDL.LastOpenFile"), &lastRom);
|
||||
return LoadGame(lastRom.c_str(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a game, given a full path/filename. The driver code must be
|
||||
* initialized after the game is loaded, because the emulator code
|
||||
* provides data necessary for the driver code(number of scanlines to
|
||||
* render, what virtual input devices to use, etc.).
|
||||
*/
|
||||
int LoadGame(const char *path)
|
||||
int LoadGame(const char *path, bool silent)
|
||||
{
|
||||
int gg_enabled, autoLoadDebug, autoOpenDebugger;
|
||||
|
||||
|
@ -227,7 +237,7 @@ int LoadGame(const char *path)
|
|||
|
||||
FCEUI_SetGameGenie (gg_enabled);
|
||||
|
||||
if(!FCEUI_LoadGame(path, 1)) {
|
||||
if(!FCEUI_LoadGame(path, 1, silent)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,9 @@ extern unsigned int gui_draw_area_height;
|
|||
// global configuration object
|
||||
extern Config *g_config;
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent = false);
|
||||
int CloseGame(void);
|
||||
int reloadLastGame(void);
|
||||
|
||||
int fceuWrapperInit( int argc, char *argv[] );
|
||||
int fceuWrapperClose( void );
|
||||
|
|
|
@ -417,7 +417,7 @@ void ppuPatternView_t::contextMenuEvent(QContextMenuEvent *event)
|
|||
menu.addAction( act );
|
||||
|
||||
subMenu = menu.addMenu(tr("Palette Select"));
|
||||
group = new QActionGroup(this);
|
||||
group = new QActionGroup(&menu);
|
||||
|
||||
group->setExclusive(true);
|
||||
|
||||
|
|
|
@ -143,13 +143,13 @@ int CustomEmulationSpeed(int spdPercent)
|
|||
g_fpsScale = ((double)spdPercent) / 100.0f;
|
||||
|
||||
if (g_fpsScale < Slowest)
|
||||
{
|
||||
g_fpsScale = Slowest;
|
||||
}
|
||||
else if (g_fpsScale > Fastest)
|
||||
{
|
||||
g_fpsScale = Fastest;
|
||||
}
|
||||
{
|
||||
g_fpsScale = Slowest;
|
||||
}
|
||||
else if (g_fpsScale > Fastest)
|
||||
{
|
||||
g_fpsScale = Fastest;
|
||||
}
|
||||
|
||||
RefreshThrottleFPS();
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include "utils/memory.h"
|
||||
|
||||
//#include "sdl-icon.h"
|
||||
#include "Qt/dface.h"
|
||||
|
||||
#include "common/configSys.h"
|
||||
|
|
|
@ -24,7 +24,7 @@ extern int dendy;
|
|||
extern int pal_emulation;
|
||||
extern bool swapDuty;
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent);
|
||||
int CloseGame(void);
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
|
||||
uint64 FCEUD_GetTime();
|
||||
|
|
|
@ -29,7 +29,7 @@ void LockConsole(void);
|
|||
void UnlockConsole(void);
|
||||
void ToggleFS(); /* SDL */
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent);
|
||||
//int CloseGame(void);
|
||||
|
||||
void Giggles(int);
|
||||
|
|
|
@ -189,18 +189,27 @@ static void ShowUsage(char *prog)
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads last game.
|
||||
*/
|
||||
int reloadLastGame() {
|
||||
std::string lastRom;
|
||||
g_config->getOption(std::string("SDL.LastOpenFile"), &lastRom);
|
||||
return LoadGame(lastRom.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a game, given a full path/filename. The driver code must be
|
||||
* initialized after the game is loaded, because the emulator code
|
||||
* provides data necessary for the driver code(number of scanlines to
|
||||
* render, what virtual input devices to use, etc.).
|
||||
*/
|
||||
int LoadGame(const char *path)
|
||||
int LoadGame(const char *path, bool silent)
|
||||
{
|
||||
if (isloaded){
|
||||
CloseGame();
|
||||
}
|
||||
if(!FCEUI_LoadGame(path, 1)) {
|
||||
if(!FCEUI_LoadGame(path, 1, silent)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ extern int dendy;
|
|||
extern int pal_emulation;
|
||||
extern bool swapDuty;
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int LoadGame(const char *path, bool silent = false);
|
||||
int CloseGame(void);
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
|
||||
uint64 FCEUD_GetTime();
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
#ifdef __linux
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#define SetCurrentDir chdir
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <libgen.h>
|
||||
#elif __APPLE__
|
||||
#include <stdlib.h>
|
||||
#include <libgen.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -42,6 +48,17 @@ extern char FileBase[];
|
|||
extern TASEDITOR_LUA taseditor_lua;
|
||||
#endif
|
||||
|
||||
#ifdef __SDL__
|
||||
|
||||
#ifdef __QT_DRIVER__
|
||||
#include "drivers/Qt/fceuWrapper.h"
|
||||
#else
|
||||
int LoadGame(const char *path, bool silent = false);
|
||||
int reloadLastGame(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
@ -514,6 +531,45 @@ static int emu_getdir(lua_State *L) {
|
|||
lua_pushstring(L, finalPath);
|
||||
|
||||
return 1;
|
||||
#elif __linux__
|
||||
char exePath[ 2048 ];
|
||||
ssize_t count = ::readlink( "/proc/self/exe", exePath, sizeof(exePath)-1 );
|
||||
|
||||
if ( count > 0 )
|
||||
{
|
||||
char *dir;
|
||||
exePath[count] = 0;
|
||||
//printf("EXE Path: '%s' \n", exePath );
|
||||
|
||||
dir = ::dirname( exePath );
|
||||
|
||||
if ( dir )
|
||||
{
|
||||
//printf("DIR Path: '%s' \n", dir );
|
||||
lua_pushstring(L, dir);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#elif __APPLE__
|
||||
char exePath[ 2048 ];
|
||||
uint32_t bufSize = sizeof(exePath);
|
||||
int result = _NSGetExecutablePath( exePath, &bufSize );
|
||||
|
||||
if ( result == 0 )
|
||||
{
|
||||
char *dir;
|
||||
exePath[ bufSize ] = 0;
|
||||
//printf("EXE Path: '%s' \n", exePath );
|
||||
|
||||
dir = ::dirname( exePath );
|
||||
|
||||
if ( dir )
|
||||
{
|
||||
//printf("DIR Path: '%s' \n", dir );
|
||||
lua_pushstring(L, dir);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
@ -521,11 +577,13 @@ static int emu_getdir(lua_State *L) {
|
|||
|
||||
extern void ReloadRom(void);
|
||||
|
||||
|
||||
// emu.loadrom(string filename)
|
||||
//
|
||||
// Loads the rom from the directory relative to the lua script or from the absolute path.
|
||||
// If the rom can't be loaded, loads the most recent one.
|
||||
static int emu_loadrom(lua_State *L) {
|
||||
static int emu_loadrom(lua_State *L)
|
||||
{
|
||||
#ifdef WIN32
|
||||
const char* str = lua_tostring(L,1);
|
||||
|
||||
|
@ -545,6 +603,17 @@ static int emu_loadrom(lua_State *L) {
|
|||
} else {
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
const char *nameo2 = luaL_checkstring(L,1);
|
||||
char nameo[2048];
|
||||
strncpy(nameo, nameo2, sizeof(nameo));
|
||||
if (!LoadGame(nameo, true))
|
||||
{
|
||||
reloadLastGame();
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
@ -6011,7 +6080,8 @@ static const struct luaL_reg cdloglib[] = {
|
|||
{ NULL,NULL }
|
||||
};
|
||||
|
||||
void CallExitFunction() {
|
||||
void CallExitFunction()
|
||||
{
|
||||
if (!L)
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue