Added Single Instantiation mode, which makes starting a second copy of FCEUX with a path to a game make it load the file into the first, then exit. To enable, set SingleInstanceOnly 1 in the config file. If someone else wants to edit things to make this easy on the user, go for it. If started with nothing in the command line, it will simply start a second copy.

This commit is contained in:
ugetab 2010-05-19 21:51:25 +00:00
parent bca41a8c4b
commit b68d9a91b8
5 changed files with 101 additions and 6 deletions

View File

@ -1,3 +1,4 @@
19-may-2010 - ugetab - Win32 - Added single-instance mode, which makes starting a second copy of FCEUX load the file into the first, then exit.
18-may-2010 - adelikat - Movie + loadstate errors are handled more gracefully now, more informative error messages and the movie doesn't have to stop
18-may-2010 - adelikat - Implemented a "full savestate-movie load" mode similar to the implementation in VBA-rr & SNES9x-rr. In this mode loading a savestate in read+write doesn't truncate the movie to its frame count immediately. Instead it waits until input is recording into the movie (next frame). For win32 this feature is togglable in movie options and the context menu. For SDL this is off by default and a toggle will need to be added.
17-may-2010 - adelikat - Made gamepad 2 off by default.

View File

@ -63,6 +63,7 @@ extern int CurrentState;
extern bool pauseWhileActive; //adelikat: Cheats dialog
extern bool AVIdisableMovieMessages;
extern bool replaceP2StartWithMicrophone;
extern bool SingleInstanceOnly;
extern bool oldInputDisplay;
extern bool fullSaveStateLoads;
@ -313,6 +314,7 @@ static CFGSTRUCT fceuconfig[] = {
AC(pauseWhileActive),
AC(AVIdisableMovieMessages),
AC(replaceP2StartWithMicrophone),
AC(SingleInstanceOnly),
ENDCFGSTRUCT
};

View File

@ -185,11 +185,15 @@ int erendlinep = 239;
//mbg 6/30/06 - indicates that the main loop should close the game as soon as it can
bool closeGame = false;
// Counts the number of frames that have not been displayed.
// Used for the bot, to skip frames (makes things faster).
int BotFramesSkipped = 0;
// Instantiated FCEUX stuff:
bool SingleInstanceOnly=false; // Enable/disable option
bool DoInstantiatedExit=false;
HWND DoInstantiatedExitWindow;
// Internal functions
void SetDirs()
{
@ -580,6 +584,48 @@ void initDirectories()
}
}
*/
static BOOL CALLBACK EnumCallbackFCEUXInstantiated(HWND hWnd, LPARAM lParam)
{
//LPSTR lpClassName = '\0';
std::string TempString;
char buf[512];
bool PassedTest=true;
GetClassName(hWnd, buf, 511);
//Console.WriteLine(lpClassName.ToString());
TempString = buf;
if (TempString != "FCEUXWindowClass")
return true;
//memset(buf, 0, 512 * sizeof(char));
GetWindowText(hWnd, buf, 512 * sizeof(char));
if (hWnd != hAppWnd) {
PassedTest = (PassedTest & (buf[0] == 'F'));
PassedTest = (PassedTest & (buf[1] == 'C'));
PassedTest = (PassedTest & (buf[2] == 'E'));
PassedTest = (PassedTest & (buf[3] == 'U'));
PassedTest = (PassedTest & (buf[4] == 'X'));
PassedTest = (PassedTest & (buf[5] == ' '));
PassedTest = (PassedTest & ((buf[6] >= '2') & (buf[6] <= '9')));
PassedTest = (PassedTest & (buf[7] == '.'));
PassedTest = (PassedTest & ((buf[8] >= '1') & (buf[8] <= '9')));
PassedTest = (PassedTest & (buf[9] == '.'));
PassedTest = (PassedTest & ((buf[10] >= '4') & (buf[10] <= '9')));
if (PassedTest) {
DoInstantiatedExit=true;
DoInstantiatedExitWindow = hWnd;
}
}
//printf("[%03i] Found '%s'\n", ++WinCount, buf);
return true;
}
#include "x6502.h"
int main(int argc,char *argv[])
{
@ -624,8 +670,6 @@ int main(int argc,char *argv[])
sprintf(TempArray,"%s\\%s",BaseDirectory.c_str(),cfgFile.c_str());
LoadConfig(TempArray);
//Bleh, need to find a better place for this.
{
pal_emulation = !!pal_emulation;
@ -675,6 +719,33 @@ int main(int argc,char *argv[])
CreateMainWindow();
// Do single instance coding, since we now know if the user wants it,
// and we have a source window to send from
// http://wiki.github.com/ffi/ffi/windows-examples
if (SingleInstanceOnly) {
// Checks window names / hWnds, decides if there's going to be a conflict.
EnumDesktopWindows(NULL, EnumCallbackFCEUXInstantiated, (LPARAM)0);
if (DoInstantiatedExit) {
if(t)
{
COPYDATASTRUCT cData;
DATA tData;
sprintf(tData.strFilePath,"%s",t);
cData.dwData = 1;
cData.cbData = sizeof ( tData );
cData.lpData = &tData;
SendMessage(DoInstantiatedExitWindow,WM_COPYDATA,(WPARAM)(HWND)hAppWnd, (LPARAM)(LPVOID) &cData);
do_exit();
return 0;
}
}
}
if(!InitDInput())
{
do_exit();

View File

@ -23,6 +23,13 @@
#define GOO_CONFIRMEXIT 2 /* Confirmation before exiting. */
#define GOO_POWERRESET 4 /* Confirm on power/reset. */
//For single instance mode, transfers with WM_COPYDATA
//http://www.go4expert.com/forums/showthread.php?t=19730
typedef struct WMCopyStruct
{
char strFilePath[2048];
} DATA;
extern int maxconbskip;
extern int ffbskip;
extern void LoadNewGamey(HWND hParent, const char *initialdir);

View File

@ -1221,11 +1221,25 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
RECT file_rect;
RECT help_rect;
int x = 0;
char TempArray[2048];
PCOPYDATASTRUCT pcData;
switch(msg)
{
case WM_COPYDATA:
pcData = (PCOPYDATASTRUCT) lParam;
switch ( pcData->dwData )
{
case 1: //cData.dwData = 1; (can use for other types as well)
if (!ALoad((LPSTR) ( (DATA *) (pcData->lpData) )-> strFilePath))
MessageBox(hWnd,"File from second instance failed to open", "Failed to open file", MB_OK);
break;
}
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
@ -2360,7 +2374,7 @@ int CreateMainWindow()
winclass.hIconSm = LoadIcon(fceu_hInstance, "ICON_1");
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //mbg merge 7/17/06 added cast
winclass.lpszClassName = "FCEULTRA";
winclass.lpszClassName = "FCEUXWindowClass";
if(!RegisterClassEx(&winclass))
{
@ -2386,7 +2400,7 @@ int CreateMainWindow()
if (MainWindow_wndy==-32000) MainWindow_wndy=0;
hAppWnd = CreateWindowEx(
0,
"FCEULTRA",
"FCEUXWindowClass",
FCEU_NAME_AND_VERSION,
WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS, /* Style */
MainWindow_wndx,