mirror of
https://github.com/mupen64plus/mupen64plus-oldsvn.git
synced 2025-04-02 10:52:35 -04:00
652 lines
19 KiB
C
652 lines
19 KiB
C
/**
|
|
* Mupen64 - main.c
|
|
* Copyright (C) 2002 Hacktarux
|
|
*
|
|
* Mupen64 homepage: http://mupen64.emulation64.com
|
|
* email address: hacktarux@yahoo.fr
|
|
*
|
|
* If you want to contribute to the project please contact
|
|
* me first (maybe someone is already making what you are
|
|
* planning to do).
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/
|
|
* or modify it under the terms of the GNU General Public Li-
|
|
* cence as published by the Free Software Foundation; either
|
|
* version 2 of the Licence, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be use-
|
|
* ful, but WITHOUT ANY WARRANTY; without even the implied war-
|
|
* ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public Licence for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* Licence along with this program; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
|
* USA.
|
|
*
|
|
**/
|
|
|
|
#include <specific.h>
|
|
#include <stdlib.h>
|
|
HWND hwnd;
|
|
|
|
/* This is MUPEN64's main entry point. It contains code that is common
|
|
* to both the gui and non-gui versions of mupen64. See
|
|
* gui subdirectories for the gui-specific code.
|
|
* if you want to implement an interface, you should look here
|
|
*/
|
|
|
|
/** function prototypes **/
|
|
static void *emulationThread( void *_arg );
|
|
static void sighandler( int signal, int signalfpe ); // signal handler
|
|
|
|
/** globals **/
|
|
HANDLE g_EmulationThread = 0; // core thread handle
|
|
|
|
|
|
/** emulation **/
|
|
/* startEmulation
|
|
* Begins emulation thread
|
|
*/
|
|
void startEmulation(void)
|
|
{
|
|
const char *gfx_plugin = NULL,
|
|
*audio_plugin = NULL,
|
|
*input_plugin = NULL,
|
|
*RSP_plugin = NULL;
|
|
|
|
// make sure rom is loaded before running
|
|
if(!rom)
|
|
{
|
|
alert_message(tr("There is no Rom loaded."));
|
|
return;
|
|
}
|
|
|
|
// make sure all plugins are specified before running
|
|
if(g_GfxPlugin)
|
|
gfx_plugin = plugin_name_by_filename(g_GfxPlugin);
|
|
else
|
|
gfx_plugin = plugin_name_by_filename(config_get_string("Gfx Plugin", ""));
|
|
|
|
if(!gfx_plugin)
|
|
{
|
|
alert_message(tr("No graphics plugin specified."));
|
|
return;
|
|
}
|
|
|
|
if(g_AudioPlugin)
|
|
audio_plugin = plugin_name_by_filename(g_AudioPlugin);
|
|
else
|
|
audio_plugin = plugin_name_by_filename(config_get_string("Audio Plugin", ""));
|
|
|
|
if(!audio_plugin)
|
|
{
|
|
alert_message(tr("No audio plugin specified."));
|
|
return;
|
|
}
|
|
|
|
if(g_InputPlugin)
|
|
input_plugin = plugin_name_by_filename(g_InputPlugin);
|
|
else
|
|
input_plugin = plugin_name_by_filename(config_get_string("Input Plugin", ""));
|
|
|
|
if(!input_plugin)
|
|
{
|
|
alert_message(tr("No input plugin specified."));
|
|
return;
|
|
}
|
|
|
|
if(g_RspPlugin)
|
|
RSP_plugin = plugin_name_by_filename(g_RspPlugin);
|
|
else
|
|
RSP_plugin = plugin_name_by_filename(config_get_string("RSP Plugin", ""));
|
|
|
|
if(!RSP_plugin)
|
|
{
|
|
alert_message(tr("No RSP plugin specified."));
|
|
return;
|
|
}
|
|
|
|
// in nogui mode, just start the emulator in the main thread
|
|
if(!g_GuiEnabled)
|
|
{
|
|
emulationThread(NULL);
|
|
}
|
|
else if(!g_EmulationThread)
|
|
{
|
|
// spawn emulation thread
|
|
if((g_EmulationThread = CreateThread(NULL, 0, emulationThread, NULL, CREATE_SUSPENDED, NULL)) == 0)
|
|
{
|
|
g_EmulationThread = 0;
|
|
alert_message(tr("Couldn't spawn core thread!"));
|
|
return;
|
|
}
|
|
ResumeThread(g_EmulationThread);
|
|
info_message(tr("Emulation started (PID: %d)"), g_EmulationThread);
|
|
}
|
|
|
|
}
|
|
|
|
void stopEmulation(void)
|
|
{
|
|
if(g_EmulationThread || g_EmulatorRunning)
|
|
{
|
|
info_message(tr("Stopping emulation."));
|
|
rompause = 0;
|
|
stop_it();
|
|
|
|
Sleep(500);
|
|
if(g_EmulationThread)
|
|
TerminateThread(g_EmulationThread, 0);
|
|
|
|
g_EmulationThread = 0;
|
|
|
|
info_message(tr("Emulation stopped."));
|
|
}
|
|
}
|
|
|
|
|
|
/*********************************************************************************************************
|
|
* emulation thread - runs the core
|
|
*/
|
|
static void * emulationThread( void *_arg )
|
|
{
|
|
const char *gfx_plugin = NULL, *audio_plugin = NULL, *input_plugin = NULL, *RSP_plugin = NULL;
|
|
|
|
signal( SIGSEGV, sighandler );
|
|
signal( SIGILL, sighandler );
|
|
signal( SIGFPE, sighandler );
|
|
|
|
g_EmulatorRunning = 1;
|
|
g_LimitFPS = config_get_bool("LimitFPS", TRUE);
|
|
|
|
// if emu mode wasn't specified at the commandline, set from config file
|
|
if(!g_EmuMode)
|
|
dynacore = config_get_number( "Core", CORE_DYNAREC );
|
|
|
|
no_audio_delay = config_get_bool("NoAudioDelay", FALSE);
|
|
no_compiled_jump = config_get_bool("NoCompiledJump", FALSE);
|
|
|
|
// init sdl
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
SDL_SetVideoMode (640, 480, 0, NULL);
|
|
|
|
SDL_ShowCursor(0);
|
|
SDL_EnableKeyRepeat(0, 0);
|
|
|
|
SDL_SetEventFilter(sdl_event_filter);
|
|
SDL_EnableUNICODE(1);
|
|
|
|
/* Determine which plugins to use:
|
|
* -If valid plugin was specified at the commandline, use it
|
|
* -Else, get plugin from config. NOTE: gui code must change config if user switches plugin in the gui)
|
|
*/
|
|
if(g_GfxPlugin)
|
|
gfx_plugin = plugin_name_by_filename(g_GfxPlugin);
|
|
else
|
|
gfx_plugin = plugin_name_by_filename(config_get_string("Gfx Plugin", ""));
|
|
|
|
if(g_AudioPlugin)
|
|
audio_plugin = plugin_name_by_filename(g_AudioPlugin);
|
|
else
|
|
audio_plugin = plugin_name_by_filename(config_get_string("Audio Plugin", ""));
|
|
|
|
if(g_InputPlugin)
|
|
input_plugin = plugin_name_by_filename(g_InputPlugin);
|
|
else
|
|
input_plugin = plugin_name_by_filename(config_get_string("Input Plugin", ""));
|
|
|
|
if(g_RspPlugin)
|
|
RSP_plugin = plugin_name_by_filename(g_RspPlugin);
|
|
else
|
|
RSP_plugin = plugin_name_by_filename(config_get_string("RSP Plugin", ""));
|
|
|
|
// initialize memory, and do byte-swapping if it's not been done yet
|
|
if (g_MemHasBeenBSwapped == 0)
|
|
{
|
|
init_memory(1);
|
|
g_MemHasBeenBSwapped = 1;
|
|
}
|
|
else
|
|
{
|
|
init_memory(0);
|
|
}
|
|
|
|
// load the plugins and attach the ROM to them
|
|
plugin_load_plugins(gfx_plugin, audio_plugin, input_plugin, RSP_plugin);
|
|
|
|
romOpen_gfx();
|
|
romOpen_audio();
|
|
romOpen_input();
|
|
|
|
if (g_Fullscreen)
|
|
changeWindow();
|
|
|
|
#ifdef WITH_LIRC
|
|
lircStart();
|
|
#endif // WITH_LIRC
|
|
|
|
#ifdef DBG
|
|
if( g_DebuggerEnabled )
|
|
init_debugger();
|
|
#endif
|
|
// load cheats for the current rom
|
|
cheat_load_current_rom();
|
|
|
|
go(); /* core func */
|
|
|
|
#ifdef WITH_LIRC
|
|
lircStop();
|
|
#endif // WITH_LIRC
|
|
|
|
romClosed_RSP();
|
|
romClosed_input();
|
|
romClosed_audio();
|
|
romClosed_gfx();
|
|
closeDLL_RSP();
|
|
closeDLL_input();
|
|
closeDLL_audio();
|
|
closeDLL_gfx();
|
|
free_memory();
|
|
|
|
// clean up
|
|
g_EmulationThread = 0;
|
|
|
|
SDL_Quit();
|
|
|
|
if (g_Filename != 0)
|
|
{
|
|
// the following doesn't work - it wouldn't exit immediately but when the next event is
|
|
// recieved (i.e. mouse movement)
|
|
/* gdk_threads_enter();
|
|
gtk_main_quit();
|
|
gdk_threads_leave();*/
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*********************************************************************************************************
|
|
* signal handler
|
|
*/
|
|
static void sighandler(int signal, int fpesignal)
|
|
{
|
|
switch( signal )
|
|
{
|
|
case SIGSEGV:
|
|
alert_message(tr("The core thread recieved a SIGSEGV signal.\n"
|
|
"This means it tried to access protected memory.\n"
|
|
"This nearly always indicates a bug in the code.\n"
|
|
"Please report the bug at the Issue Tracker.\n"
|
|
"http://code.google.com/p/mupen64plus/issues"));
|
|
printf( "SIGSEGV in core thread caught\n" );
|
|
break;
|
|
case SIGILL:
|
|
printf( "SIGILL in core thread caught\n" );
|
|
break;
|
|
case SIGFPE:
|
|
printf( "SIGFPE in core thread caught:\n" );
|
|
switch( fpesignal )
|
|
{
|
|
case _FPE_INVALID: printf( "\tfloating point invalid operation\n" ); break;
|
|
case _FPE_DENORMAL: printf( "\tfloating point denormal operation\n" ); break;
|
|
case _FPE_ZERODIVIDE: printf( "\tfloating point division by zero\n" ); break;
|
|
case _FPE_OVERFLOW: printf( "\tfloating point overflow\n" ); break;
|
|
case _FPE_UNDERFLOW: printf( "\tfloating point underflow\n" ); break;
|
|
case _FPE_INEXACT: printf( "\tfloating point inexact result\n" ); break;
|
|
case _FPE_UNEMULATED: printf( "\tfloating point unemulated operation\n" ); break;
|
|
case _FPE_SQRTNEG: printf( "\tfloating point negative square root\n" ); break;
|
|
case _FPE_STACKOVERFLOW: printf( "\tfloating point stack overflow\n" ); break;
|
|
case _FPE_STACKUNDERFLOW: printf( "\tfloating point stack udnerflow\n" ); break;
|
|
case _FPE_EXPLICITGEN: printf( "\tsomeone rose SIGFPE on explicitly\n" ); break;
|
|
}
|
|
break;
|
|
default:
|
|
printf( "Signal number %d in core thread caught:\n", signal );
|
|
}
|
|
g_EmulationThread = 0;
|
|
g_EmulatorRunning = 0;
|
|
}
|
|
|
|
HINSTANCE hinst;
|
|
int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev_instance, char* command_line, int show_command)
|
|
{
|
|
//if (!InitInstance())
|
|
// fprintf(stderr,"Win32 Error: Unable to initalize instance.\n");
|
|
|
|
//if (!InitWindow())
|
|
// fprintf(stderr,"Win32 Error: Unable to initalize instance.\n");
|
|
|
|
fflush(stderr);
|
|
int argc;
|
|
char** argv;
|
|
char* arg;
|
|
int index;
|
|
int result;
|
|
hinst = instance;
|
|
|
|
argc = 1;
|
|
arg = command_line;
|
|
|
|
while (arg[0] != 0)
|
|
{
|
|
while (arg[0] != 0 && arg[0] == ' ')
|
|
{
|
|
arg++;
|
|
}
|
|
if (arg[0] != 0)
|
|
{
|
|
argc++;
|
|
while (arg[0] != 0 && arg[0] != ' ')
|
|
{
|
|
arg++;
|
|
}
|
|
}
|
|
}
|
|
argv = (char**)malloc(argc * sizeof(char*));
|
|
arg = command_line;
|
|
index = 1;
|
|
while (arg[0] != 0)
|
|
{
|
|
while (arg[0] != 0 && arg[0] == ' ')
|
|
{
|
|
arg++;
|
|
}
|
|
if (arg[0] != 0)
|
|
{
|
|
argv[index] = arg;
|
|
index++;
|
|
while (arg[0] != 0 && arg[0] != ' ')
|
|
{
|
|
arg++;
|
|
}
|
|
if (arg[0] != 0)
|
|
{
|
|
arg[0] = 0;
|
|
arg++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// put the program name into argv[0]
|
|
char filename[_MAX_PATH];
|
|
GetModuleFileName(NULL, filename, _MAX_PATH);
|
|
argv[0] = filename;
|
|
|
|
// call the user specified main function
|
|
result = main(argc, (const char **)argv);
|
|
free(argv);
|
|
return result;
|
|
}
|
|
|
|
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch( uMsg )
|
|
{
|
|
/*case WM_KeyDown:
|
|
keyDown(wParam, lParam);
|
|
break;
|
|
case WM_KeyUp:
|
|
keyUp(wParam, lParam);
|
|
break;*/
|
|
default:
|
|
return( DefWindowProc( hWnd, uMsg, wParam, lParam ));
|
|
}
|
|
return( DefWindowProc( hWnd, uMsg, wParam, lParam ));
|
|
}
|
|
|
|
void ErrorExit(char * lpszFunction)
|
|
{
|
|
// Retrieve the system error message for the last-error code
|
|
fprintf(stderr,"Reporting error in %s...\n", lpszFunction);
|
|
LPVOID lpMsgBuf;
|
|
LPVOID lpDisplayBuf;
|
|
DWORD dw = GetLastError();
|
|
|
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,dw,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0, NULL);
|
|
|
|
// Display the error message and exit the process
|
|
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
|
|
sprintf(lpDisplayBuf, "%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);
|
|
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
|
|
|
|
LocalFree(lpMsgBuf);
|
|
LocalFree(lpDisplayBuf);
|
|
ExitProcess(dw);
|
|
}
|
|
|
|
|
|
BOOL InitInstance()
|
|
{
|
|
WNDCLASSEX wcx;
|
|
|
|
wcx.cbSize = sizeof(wcx);
|
|
wcx.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcx.lpfnWndProc = MainWndProc;
|
|
wcx.cbClsExtra = 0;
|
|
wcx.cbWndExtra = 0;
|
|
wcx.hInstance = hinst;
|
|
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
if(!wcx.hIcon) ErrorExit("IDI_APPLICATION");
|
|
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
if(!wcx.hCursor) ErrorExit("LoadCursor");
|
|
wcx.hbrBackground = GetStockObject(BLACK_BRUSH);
|
|
if(!wcx.hbrBackground) ErrorExit("GetStockObject");
|
|
wcx.lpszMenuName = "MainMenu";
|
|
wcx.lpszClassName = "MainWClass";
|
|
//wcx.hIconSm = LoadImage(hinstance, MAKEINTRESOURCE(5), IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
|
|
wcx.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
|
if(!wcx.hIconSm) ErrorExit("LoadImage");
|
|
|
|
if(!RegisterClassEx(&wcx)) ErrorExit("RegisterClassEx");
|
|
}
|
|
|
|
HWND InitWindow()
|
|
{
|
|
if(hwnd) KillWindow();
|
|
hwnd = CreateWindow("MainWClass", "Mupen64Plus for Windows", WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, (HWND) NULL, (HMENU) NULL, hinst, (LPVOID) NULL);
|
|
if (!hwnd) ErrorExit("CreateWindow");
|
|
|
|
ShowWindow(hwnd, 0);
|
|
UpdateWindow(hwnd);
|
|
return hwnd;
|
|
|
|
}
|
|
BOOL KillWindow()
|
|
{
|
|
DestroyWindow(hwnd);
|
|
hwnd = NULL;
|
|
}
|
|
HWND ShowVideo()
|
|
{
|
|
ShowWindow(hwnd, 1);
|
|
UpdateWindow(hwnd);
|
|
return hwnd;
|
|
}
|
|
HWND HideVideo()
|
|
{
|
|
ShowWindow(hwnd, 0);
|
|
UpdateWindow(hwnd);
|
|
return hwnd;
|
|
}
|
|
HWND GetVideo()
|
|
{
|
|
return hwnd;
|
|
}
|
|
|
|
int file_exists(const char *fileName)
|
|
{
|
|
DWORD fileAttr;
|
|
|
|
fileAttr = GetFileAttributesA(fileName);
|
|
if (0xFFFFFFFF == fileAttr)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
|
|
/** setPaths
|
|
* setup paths to config/install/screenshot directories. The config dir is the dir where all
|
|
* user config information is stored, e.g. mupen64plus.conf, save files, and plugin conf files.
|
|
* The install dir is where mupen64plus looks for common files, e.g. plugins, icons, language
|
|
* translation files.
|
|
*/
|
|
static void setPaths(void)
|
|
{
|
|
char buf[PATH_MAX], buf2[PATH_MAX];
|
|
|
|
strncpy(g_ConfigDir, gethomedir(), PATH_MAX);
|
|
|
|
if (strlen(g_ConfigDir) == 0)
|
|
{
|
|
strncpy(g_ConfigDir, getexedir(), PATH_MAX);
|
|
strncat(g_ConfigDir, dirsep, PATH_MAX-strlen(g_ConfigDir));
|
|
strncat(g_ConfigDir, "config", PATH_MAX-strlen(g_ConfigDir));
|
|
strncat(g_ConfigDir, dirsep, PATH_MAX-strlen(g_ConfigDir));
|
|
}
|
|
|
|
// if the home dir is not found, create it
|
|
if(!isdir(g_ConfigDir))
|
|
{
|
|
printf("Creating %s to store user data\n", g_ConfigDir);
|
|
if(mkdirwp(g_ConfigDir, 0755) != 0)
|
|
{
|
|
printf("Warning: Could not create %s\n: ", g_ConfigDir);
|
|
goto nocreate;
|
|
}
|
|
|
|
// create save subdir
|
|
strncpy(buf, g_ConfigDir, PATH_MAX);
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, "save", PATH_MAX - strlen(buf));
|
|
if(mkdirwp(buf, 0755) != 0)
|
|
{
|
|
// report error, but don't exit
|
|
printf("Warning: Could not create %s: %s\n", buf, strerror(errno));
|
|
}
|
|
|
|
// create screenshots subdir
|
|
strncpy(buf, g_ConfigDir, PATH_MAX);
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, "screenshots", PATH_MAX - strlen(buf));
|
|
if(mkdirwp(buf, 0755) != 0)
|
|
{
|
|
// report error, but don't exit
|
|
printf("Warning: Could not create %s: %s\n", buf, strerror(errno));
|
|
}
|
|
}
|
|
nocreate:
|
|
// make sure config dir has a '/' on the end.
|
|
if(g_ConfigDir[strlen(g_ConfigDir)-1] != dirsep[0])
|
|
strncat(g_ConfigDir, dirsep, 1);
|
|
|
|
// if install dir was not specified at the commandline, look for it in the default location
|
|
if(strlen(g_InstallDir) == 0)
|
|
{
|
|
memset(buf,0,PATH_MAX);
|
|
strncpy(buf,getexedir(),PATH_MAX);
|
|
fprintf(stderr, "EXE dir: %s\n", buf);
|
|
|
|
// if install dir is not in the default location, try the same dir as the binary
|
|
if(!isdir(g_InstallDir))
|
|
{
|
|
memset(buf,0,PATH_MAX);
|
|
strncpy(buf,getexedir(),PATH_MAX);
|
|
|
|
if(buf)
|
|
{
|
|
dirname(buf);
|
|
strncpy(g_InstallDir, buf, PATH_MAX);
|
|
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, "config", PATH_MAX - strlen(buf));
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, "mupen64plus.conf", PATH_MAX - strlen(buf));
|
|
if(!isfile(buf))
|
|
{
|
|
// try cwd as last resort
|
|
getcwd(g_InstallDir, PATH_MAX);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// try cwd as last resort
|
|
getcwd(g_InstallDir, PATH_MAX);
|
|
}
|
|
}
|
|
}
|
|
|
|
// make sure install dir has a '/' on the end.
|
|
if(g_InstallDir[strlen(g_InstallDir)-1] != dirsep[0])
|
|
strncat(g_InstallDir, dirsep, PATH_MAX - strlen(g_InstallDir));
|
|
|
|
// make sure install dir is valid
|
|
strncpy(buf, g_InstallDir, PATH_MAX);
|
|
strncat(buf, "config", PATH_MAX - strlen(buf));
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, "mupen64plus.conf", PATH_MAX - strlen(buf));
|
|
if(!file_exists(buf))
|
|
{
|
|
printf("Could not locate valid install directory\n");
|
|
}
|
|
|
|
// check user config dir for mupen64plus.conf file. If it's not there, copy all
|
|
// config files from install dir over to user dir.
|
|
strncpy(buf, g_ConfigDir, PATH_MAX);
|
|
strncat(buf, "mupen64plus.conf", PATH_MAX - strlen(buf));
|
|
if(!file_exists(buf))
|
|
{
|
|
DIR *dir;
|
|
struct dirent *entry;
|
|
|
|
strncpy(buf, g_InstallDir, PATH_MAX);
|
|
strncat(buf, "config", PATH_MAX - strlen(buf));
|
|
dir = opendir(buf);
|
|
|
|
// should never hit this error because of previous checks
|
|
if(!dir)
|
|
{
|
|
perror(buf);
|
|
return;
|
|
}
|
|
|
|
while((entry = readdir(dir)) != NULL)
|
|
{
|
|
strncpy(buf, g_InstallDir, PATH_MAX);
|
|
strncat(buf, "config", PATH_MAX - strlen(buf));
|
|
strncat(buf, dirsep, PATH_MAX - strlen(buf));
|
|
strncat(buf, entry->d_name, PATH_MAX - strlen(buf));
|
|
|
|
// only copy regular files
|
|
if(isfile(buf))
|
|
{
|
|
strncpy(buf2, g_ConfigDir, PATH_MAX);
|
|
strncat(buf2, entry->d_name, PATH_MAX - strlen(buf2));
|
|
|
|
printf("Copying %s to %s\n", buf, g_ConfigDir);
|
|
if(copyfile(buf, buf2) != 0)
|
|
printf("Error copying file\n");
|
|
}
|
|
}
|
|
|
|
closedir(dir);
|
|
}
|
|
|
|
// set screenshot dir if it wasn't specified by the user
|
|
if(strlen(g_SshotDir) == 0)
|
|
{
|
|
snprintf(g_SshotDir, PATH_MAX, "%sscreenshots%c", g_ConfigDir, dirsep[0]);
|
|
if(!isdir(g_SshotDir))
|
|
{
|
|
printf("Warning: Could not find screenshot dir: %s\n", g_SshotDir);
|
|
g_SshotDir[0] = '\0';
|
|
}
|
|
}
|
|
|
|
// make sure screenshots dir has a '/' on the end.
|
|
if(g_SshotDir[strlen(g_SshotDir)-1] != dirsep[0])
|
|
strncat(g_SshotDir, dirsep, PATH_MAX - strlen(g_SshotDir));
|
|
|
|
fprintf(stderr, "config dir: %s\n", g_ConfigDir);
|
|
}
|