pureikyubu/SRC/UI/UserMain.cpp
2020-05-03 19:54:09 +03:00

181 lines
4.6 KiB
C++

// Dolwin entrypoint (WinMain) and fail-safe application messages.
// WinMain() should never return.
#include "pch.h"
// ---------------------------------------------------------------------------
// basic application output
namespace UI
{
// fatal error
void DolwinError(const TCHAR* title, const TCHAR* fmt, ...)
{
va_list arg;
TCHAR buf[0x1000];
va_start(arg, fmt);
_vstprintf_s(buf, _countof(buf) - 1, fmt, arg);
va_end(arg);
if (emu.doldebug)
{
char ansiText[0x1000] = { 0, }, * ansiPtr = ansiText;
TCHAR* tcharPtr = buf;
while (*tcharPtr)
{
*ansiPtr++ = (char)*tcharPtr++;
}
*ansiPtr++ = 0;
DBHalt(ansiPtr);
}
else
{
MessageBox(NULL, buf, title, MB_ICONHAND | MB_OK | MB_TOPMOST);
std::vector<std::string> cmd{ "exit" };
Debug::Hub.Execute(cmd);
}
}
// fatal error, if user answers no
// return TRUE if "yes", and FALSE if "no"
BOOL DolwinQuestion(const TCHAR* title, const TCHAR* fmt, ...)
{
va_list arg;
TCHAR buf[0x1000];
va_start(arg, fmt);
_vstprintf_s(buf, _countof(buf) - 1, fmt, arg);
va_end(arg);
int btn = MessageBox(
NULL,
buf,
title,
MB_RETRYCANCEL | MB_ICONHAND | MB_TOPMOST
);
if (btn == IDCANCEL)
{
SendMessage(wnd.hMainWindow, WM_COMMAND, ID_FILE_UNLOAD, 0);
return FALSE;
}
else return TRUE;
}
// application message
void DolwinReport(const TCHAR* fmt, ...)
{
va_list arg;
TCHAR buf[0x1000];
va_start(arg, fmt);
_vstprintf_s(buf, _countof(buf) - 1, fmt, arg);
va_end(arg);
MessageBox(NULL, buf, APPNAME _T(" Reports"), MB_ICONINFORMATION | MB_OK | MB_TOPMOST);
}
}
// ---------------------------------------------------------------------------
// WinMain (very first run-time initialization and main loop)
// check for multiple instancies
static void LockMultipleCalls()
{
static HANDLE dolwinsem;
// mutex will fail if semephore already exists
dolwinsem = CreateMutex(NULL, 0, APPNAME);
if(dolwinsem == NULL)
{
UI::DolwinReport(_T("We are already running ") APPNAME _T("!!"));
exit(0); // return good
}
CloseHandle(dolwinsem);
dolwinsem = CreateSemaphore(NULL, 0, 1, APPNAME);
}
// set proper current working directory, create missing directories
static void InitFileSystem(HINSTANCE hInst)
{
// set current working directory relative to Dolwin executable
GetModuleFileName(hInst, ldat.cwd, sizeof(ldat.cwd));
*(_tcsrchr(ldat.cwd, _T('\\')) + 1) = 0;
SetCurrentDirectory(ldat.cwd);
// make sure, that Dolwin has data directory.
CreateDirectory(_T(".\\Data"), NULL);
}
// return file name without quotes
char * FixCommandLine(char *lpCmdLine)
{
if(*lpCmdLine == '\"' || *lpCmdLine == '\'')
{
lpCmdLine++;
}
size_t len = strlen(lpCmdLine);
if(lpCmdLine[len-1] == '\"' || lpCmdLine[len-1] == '\'')
{
lpCmdLine[len-1] = 0;
}
return lpCmdLine;
}
// keyboard accelerators (no need to be shared)
HACCEL hAccel;
// entrypoint
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(nShowCmd);
// Required by HLE Subsystem
assert((uint64_t)hInstance <= 0x400000);
// prepare file system
InitFileSystem(hInstance);
// run Dolwin once ?
if(GetConfigBool(USER_RUNONCE, USER_UI))
{
LockMultipleCalls();
}
hAccel = LoadAccelerators(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_ACCELERATOR));
// init emu and user interface (emulator will be initialized
// during main window creation).
CreateMainWindow(hInstance);
// Idle loop
for(;;)
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) == 0)
{
UpdateProfiler();
Sleep(1);
}
// Idle loop
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (!TranslateAccelerator(wnd.hMainWindow, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
// should never reach this point. Dolwin always exit()'s.
UI::DolwinError(_T("ERROR"), APPNAME _T(" ERROR >>> SHOULD NEVER REACH HERE :)"));
return 1; // return bad
}