#include #include "../lib/am/amInstall.h" #include "../lib/ami/amiMd5.h" #include "mxm.h" bool mxMasterInitPcp(MX_MASTER* mxMaster) { if (mxMaster->m_pcpaHasInit) return true; e_pcpa_t err; pcpa_t* stream = &mxMaster->m_pcp; if ((err = pcpaInitStream(stream)) != e_pcpa_ok) { amiDebugLog("pcpaInitStream Error. Code:%d", err); return false; } err = pcpaSetCallbackFuncBuffer( stream, mxMaster->m_pcpCallbacks, (sizeof mxMaster->m_pcpCallbacks) / (sizeof mxMaster->m_pcpCallbacks[0])); if (err != e_pcpa_ok) { amiDebugLog("pcpaSetCallBackFuncBuffer Error. Code:%d", err); return false; } // Misc pcpaSetCallbackFunc(stream, MXM_RECONNECT_USB, mxmPcpReconnectUsbDevice, mxMaster); pcpaSetCallbackFunc(stream, MXM_DEVELOP, mxmPcpCheckDevelopMode, mxMaster); // Logs pcpaSetCallbackFunc(stream, MXM_LOG_AVAILALBE, mxmPcpLogAvailable, mxMaster); pcpaSetCallbackFunc(stream, MXM_OUTPUT_LOG, mxmPcpOutputLog, mxMaster); pcpaSetCallbackFunc(stream, MXM_ERASE_LOG, mxmPcpEraseLog, mxMaster); // Foreground control pcpaSetCallbackFunc(stream, MXM_FG_CURRENT, mxmPcpCurrentFgprocess, mxMaster); pcpaSetCallbackFunc(stream, MXM_FG_NEXT, mxmPcpNextFgprocess, mxMaster); pcpaSetCallbackFunc(stream, MXM_FG_ACTIVE, mxmPcpActiveFgprocess, mxMaster); pcpaSetCallbackFunc(stream, MXM_FG_FAULT, mxmPcpFaultFgprocess, mxMaster); pcpaSetCallbackFunc(stream, MXM_FG_GETCOUNT, mxmPcpGetStartCount, mxMaster); pcpaSetCallbackFunc(stream, MXM_FG_SETCOUNT, mxmPcpSetStartCount, mxMaster); mxMaster->m_pcpaHasInit = true; return true; } bool mxMasterInit(MX_MASTER* mxMaster) { mxMaster->m_develop = 0; mxMaster->m_fault = 0; mxMaster->m_current = 0; mxMaster->m_next = 0; mxMaster->m_changeIsSpawn = false; mxMaster->m_processStateChange = false; mxMaster->m_backupMetadataChanged = false; mxMaster->m_loggingAvailable = false; mxMaster->m_backupCount = 0; mxMaster->m_clearCount = 0; mxMaster->m_interval = 0; mxMaster->m_countGameBoot = 0; mxMaster->m_countSystemBoot = 0; mxMaster->m_countGameTest = 0; mxMaster->m_countSystemTest = 0; mxMaster->m_binaryMessageLen = 0; ZeroMemory(mxMaster->m_binaryMessage, sizeof mxMaster->m_binaryMessage); mxmCopySystemFile("mxsegaboot.exe"); mxmCopySystemFile("mxauthdisc.exe"); mxmCopySystemFile("mxshellexecute.exe"); mxmCopySystemFile("ringmaster_pub.pem"); mxmCopySystemFile("develop_regset.txt"); mxmCopySystemFile("lockid.txt"); mxmCopySystemFile("d3dref9.dll"); mxmCopySystemFile("mxsegaboot_2052.dll"); #ifdef MXM_APM2 mxmCopySystemFile("nxAuth.exe"); mxmCopySystemFile("SBYG_Table.dat"); mxmCopySystemFirmwareFile("315-6691A.bin"); mxmCopySystemFirmwareFile("TN32MSEC003S_V12.hex"); #endif return mxMasterInitPcp(mxMaster); } bool mxMasterLoadKeychipInfo(MX_MASTER* mxMaster) { AM_DONGLE_STATUS err; amiDebugLog("Waiting for dongle setup"); if ((err = amDongleInit()) != AM_DONGLE_STATUS_OK) { amiDebugLog("Error amDongleInit. Code %d", err); return false; } if ((err = amDongleSetAuthConfig("toolmode")) != AM_DONGLE_STATUS_OK) { amiDebugLog("Error amDongleSetAuthConfig. Code %d", err); amDongleExit(); return false; } amtime_t start, now; int tDelta; amiTimerGet(&start); do { err = amDongleSetupKeychip(); amiTimerGet(&now); tDelta = amiTimerDiffSec(&start, &now); } while (err == AM_DONGLE_STATUS_PENDING && tDelta < 60); if (err == AM_DONGLE_STATUS_PENDING) { amiDebugLog("Error amDongleSetupKeychip timeout"); amDongleExit(); return false; } if (err != AM_DONGLE_STATUS_OK) { amiDebugLog("Error amDongleSetupKeychip. Code %d", err); amDongleExit(); return false; } if (!amDongleIsAvailable()) { amiDebugLog("Error amDongleIsAvailable"); amDongleExit(); return false; } mxMaster->m_develop = amDongleIsDevelop(); amiTimerGet(&start); do { err = amDongleGetGameId(mxMaster->m_gameId, AM_DONGLE_BLOCK); if (err == AM_DONGLE_STATUS_ERR_KEYCHIP) return false; if (err == AM_DONGLE_STATUS_NG) return false; if (err == AM_DONGLE_STATUS_ERR_KEYCHIP_DATA) return false; if (err == AM_DONGLE_STATUS_ERR_INVALID_PARAM) return false; if (err == AM_DONGLE_STATUS_ERR_NO_INIT) return false; if (err == AM_DONGLE_STATUS_ERR_NO_SERVER) return false; amiTimerGet(&now); tDelta = amiTimerDiffSec(&start, &now); if (tDelta > 30) return false; } while (err != AM_DONGLE_STATUS_OK); amiTimerGet(&start); do { err = amDongleGetPlatformId(mxMaster->m_platformId, AM_DONGLE_BLOCK); if (err == AM_DONGLE_STATUS_ERR_KEYCHIP) return false; if (err == AM_DONGLE_STATUS_NG) return false; if (err == AM_DONGLE_STATUS_ERR_KEYCHIP_DATA) return false; if (err == AM_DONGLE_STATUS_ERR_INVALID_PARAM) return false; if (err == AM_DONGLE_STATUS_ERR_NO_INIT) return false; if (err == AM_DONGLE_STATUS_ERR_NO_SERVER) return false; amiTimerGet(&now); tDelta = amiTimerDiffSec(&start, &now); if (tDelta > 30) return false; } while (err != AM_DONGLE_STATUS_OK); amiTimerGet(&start); do { err = amDongleGetNetworkAddress((unsigned int*)&(mxMaster->m_networkAddr.S_un.S_addr), AM_DONGLE_BLOCK); if (err == AM_DONGLE_STATUS_ERR_KEYCHIP) return false; if (err == AM_DONGLE_STATUS_NG) return false; if (err == AM_DONGLE_STATUS_ERR_KEYCHIP_DATA) return false; if (err == AM_DONGLE_STATUS_ERR_INVALID_PARAM) return false; if (err == AM_DONGLE_STATUS_ERR_NO_INIT) return false; if (err == AM_DONGLE_STATUS_ERR_NO_SERVER) return false; amiTimerGet(&now); tDelta = amiTimerDiffSec(&start, &now); if (tDelta > 30) return false; } while (err != AM_DONGLE_STATUS_OK); amiTimerGet(&start); do { err = amDongleBillingGetKeychipId(mxMaster->m_keychipId, AM_DONGLE_BLOCK); if (err == AM_DONGLE_STATUS_ERR_KEYCHIP) return false; if (err == AM_DONGLE_STATUS_NG) return false; if (err == AM_DONGLE_STATUS_ERR_KEYCHIP_DATA) return false; if (err == AM_DONGLE_STATUS_ERR_INVALID_PARAM) return false; if (err == AM_DONGLE_STATUS_ERR_NO_INIT) return false; if (err == AM_DONGLE_STATUS_ERR_NO_SERVER) return false; amiTimerGet(&now); tDelta = amiTimerDiffSec(&start, &now); if (tDelta > 30) return false; } while (err != AM_DONGLE_STATUS_OK); amDongleExit(); return true; } void mxMasterSysProcessesStart(MX_MASTER* mxMaster) { char startup[ #ifdef MXM_APM2 5 #else 4 #endif ][128]; strcpy_s(startup[0], sizeof startup[0], Config.binary.mxkeychip); strcpy_s(startup[1], sizeof startup[1], Config.binary.mxnetwork); strcpy_s(startup[2], sizeof startup[2], Config.binary.mxstorage); strcpy_s(startup[3], sizeof startup[3], Config.binary.mxjvs); #ifdef MXM_APM2 strcpy_s(startup[4], sizeof startup[4], Config.binary.nxMount); #endif STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; DWORD dwCreationFlags; BOOL ret; for (int i = 0; i < _countof(startup); i++) { dwCreationFlags = CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS; ZeroMemory(&startupInfo, sizeof startupInfo); startupInfo.cb = sizeof startupInfo; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = 0; if (strstr(startup[i], "mxjvs.exe") != NULL) { WIN32_FIND_DATAA findData; HANDLE hFindFile = FindFirstFileA(startup[i], &findData); if (hFindFile == INVALID_HANDLE_VALUE) continue; FindClose(hFindFile); if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) continue; dwCreationFlags = CREATE_NO_WINDOW | HIGH_PRIORITY_CLASS; } ret = CreateProcessA(NULL, startup[i], NULL, NULL, 0, dwCreationFlags, NULL, NULL, &startupInfo, &processInformation); if (!ret) amiDebugLog("Close Process %s", startup[i]); CloseHandle(processInformation.hProcess); CloseHandle(processInformation.hThread); } Sleep(2000); if (mxMasterLoadKeychipInfo(mxMaster)) { mxMaster->m_kcReady = true; } else { mxMaster->m_current = 1; mxMaster->m_kcReady = false; } char mxinstaller[128]; sprintf_s(mxinstaller, sizeof mxinstaller, mxMaster->m_develop ? "%s -openmode any" : "%s", Config.binary.mxinstaller); startupInfo.cb = sizeof startupInfo; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = 0; ret = CreateProcessA(NULL, mxinstaller, NULL, NULL, 0, 0x8000020, NULL, NULL, &startupInfo, &processInformation); if (!ret) amiDebugLog("Close Process %s", mxinstaller); CloseHandle(processInformation.hProcess); CloseHandle(processInformation.hThread); mxMaster->m_current = mxMaster->m_develop ? 5 : 1; } void mxMasterFdcProcessesStart(MX_MASTER* mxMaster) { char startup[3][128]; strcpy_s(startup[0], sizeof startup[0], Config.binary.mxgcatcher); strcpy_s(startup[1], sizeof startup[1], Config.binary.mxgfetcher); strcpy_s(startup[2], sizeof startup[2], Config.binary.mxgdeliver); if (mxMaster->m_kcReady) { char* format; char* networkAddr = inet_ntoa(mxMaster->m_networkAddr); if (mxMaster->m_develop == 0) { format = " %s %s %s %s"; } else { format = " -d %s %s %s %s"; } char workBuf[128]; sprintf_s(workBuf, sizeof workBuf, format, mxMaster->m_platformId, mxMaster->m_gameId, networkAddr, mxMaster->m_keychipId); for (int i = 0; i < 3; i++) { strcat_s(startup[i], sizeof startup[i], workBuf); } } STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation; DWORD dwCreationFlags; BOOL ret; for (int i = 0; i < 3; i++) { dwCreationFlags = CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS; ZeroMemory(&startupInfo, sizeof startupInfo); startupInfo.cb = sizeof startupInfo; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = 0; ret = CreateProcessA(NULL, startup[i], NULL, NULL, 0, dwCreationFlags, NULL, NULL, &startupInfo, &processInformation); if (!ret) amiDebugLog("Close Process %s", startup[i]); CloseHandle(processInformation.hProcess); CloseHandle(processInformation.hThread); } } void mxMasterFirstFgProcessesStart(MX_MASTER* mxMaster) { appLauncherAppInfo_t appInfo; appInfo.m_mode = mxMaster->m_current; if (appInfo.m_mode == appLauncherLaunchSegabootR) { appInfo.m_mode = appLauncherLaunchSegaboot; } else if (appInfo.m_mode != appLauncherLaunchGame && appInfo.m_mode != appLauncherLaunchSegabootTR && appInfo.m_mode != appLauncherLaunchGameTest && appInfo.m_mode != appLauncherLaunchSegabootD) { amiDebugLog("Error : Not Process Mode"); mxMaster->m_current = 1; appInfo.m_mode = appLauncherLaunchSegaboot; } switch (appInfo.m_mode) { case appLauncherLaunchSegabootR: case appLauncherLaunchSegabootD: case appLauncherLaunchSegaboot: mxMaster->m_countSystemBoot = mxMaster->m_countSystemBoot + 1; break; case appLauncherLaunchGame: mxMaster->m_countGameBoot = mxMaster->m_countGameBoot + 1; break; case appLauncherLaunchSegabootTR: mxMaster->m_countSystemTest = mxMaster->m_countSystemTest + 1; break; case appLauncherLaunchGameTest: mxMaster->m_countGameTest = mxMaster->m_countGameTest + 1; break; } appLauncherCreateThread(&appInfo, mxMaster->m_appLauncher); } void mxMasterMainLoop(MX_MASTER* mxMaster) { mxMaster->m_loggingAvailable = false; mxMaster->m_backupMetadataChanged = false; mxMaster->m_backupCount = 1; mxMaster->m_clearCount = 100; mxMaster->m_interval = 60; if (!MxmEventLog.m_init) { MxmEventLog.m_backupCount = 1; MxmEventLog.m_clearCount = 100; MxmEventLog.m_interval = 60; MxmEventLog.m_logDriveFound = false; MxmEventLog.m_filenamesSet = false; ZeroMemory(MxmEventLog.m_desinations, sizeof MxmEventLog.m_desinations); MxmEventLog.m_init = true; } e_pcpa_t err; do { err = pcpaOpenServerWithBinary(&mxMaster->m_pcp, mxMaster->m_openMode, mxMaster->m_controlPort, mxMaster->m_dataPort, 60000); if (err != e_pcpa_ok) { if (mxMaster->m_pcpaHasInit) { pcpaClose(&mxMaster->m_pcp); mxMaster->m_pcpaHasInit = false; } mxMasterInitPcp(mxMaster); amiDebugLog("Error : Not Open Server. Code %d", err); } } while (err != e_pcpa_ok); mxMaster->m_serverOpen = true; appLauncherAppInfo_t appInfo[3]; while (1) { err = pcpaServer(&mxMaster->m_pcp, 16); if (err != e_pcpa_ok && err != e_pcpa_to && err != e_pcpa_closed) { if (mxMaster->m_pcpaHasInit) { pcpaClose(&mxMaster->m_pcp); mxMaster->m_pcpaHasInit = false; } mxMasterInitPcp(mxMaster); do { err = pcpaOpenServerWithBinary(&mxMaster->m_pcp, mxMaster->m_openMode, mxMaster->m_controlPort, mxMaster->m_dataPort, 60000); if (err != e_pcpa_ok) { if (mxMaster->m_pcpaHasInit) { pcpaClose(&mxMaster->m_pcp); mxMaster->m_pcpaHasInit = false; } mxMasterInitPcp(mxMaster); amiDebugLog("Error : Not Open Server. Code %d", err); } } while (err != e_pcpa_ok); } appLauncher_t* appLauncher; if (mxMaster->m_processStateChange) { appLauncher = mxMaster->m_appLauncher; if (appLauncher->m_createdThread) { if (WaitForSingleObject(appLauncher->m_hThread, 0) != WAIT_TIMEOUT) { CloseHandle(appLauncher->m_hThread); appLauncher->m_hThread = NULL; appLauncher->m_createdThread = false; } } if (!mxMaster->m_develop || mxMaster->m_changeIsSpawn) { appInfo[0].m_mode = mxMaster->m_current; mxMaster->m_changeIsSpawn = 0; if (appInfo[0].m_mode == appLauncherLaunchGame) { sprintf_s(appInfo[0].m_path, sizeof appInfo[0].m_path, "%s", mxMaster->m_nextPath); } switch (appInfo[0].m_mode) { case appLauncherLaunchSegabootR: case appLauncherLaunchSegabootD: case appLauncherLaunchSegaboot: mxMaster->m_countSystemBoot++; break; case appLauncherLaunchGame: mxMaster->m_countGameBoot++; break; case appLauncherLaunchSegabootTR: mxMaster->m_countSystemTest++; break; case appLauncherLaunchGameTest: mxMaster->m_countGameTest++; } appLauncherCreateThread(appInfo, mxMaster->m_appLauncher); } mxMaster->m_processStateChange = false; } if (mxMaster->m_backupMetadataChanged) { if (MxmEventLog.m_init) { MxmEventLog.m_backupCount = mxMaster->m_backupCount; MxmEventLog.m_clearCount = mxMaster->m_clearCount; MxmEventLog.m_interval = mxMaster->m_interval; } mxMaster->m_backupMetadataChanged = false; } if (MxmEventLog.m_init && MxmEventLog.m_filenamesSet) { for (int i = 0; i < NUM_LOGS; i++) { if (mxmBackupEventlog(i) != 0) break; } } } } int main() { load_micemaster_config(); // Enable colour HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); DWORD dwMode = 0; if (GetConsoleMode(hConsole, &dwMode)) SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); // Start WSA WSADATA wsaData; int err = WSAStartup(2, &wsaData); if (err) return -1; // Initialise mxm structures MX_MASTER* mxMaster = malloc(sizeof *mxMaster); if (mxMaster == NULL) { amiDebugLog("Unable to allocate MX_MASTER"); return -1; } ZeroMemory(mxMaster, sizeof *mxMaster); appLauncher_t appLauncher; ZeroMemory(&appLauncher, sizeof appLauncher); appLauncher.m_appInfo.m_appLauncher = &appLauncher; mxMaster->m_appLauncher = &appLauncher; // Startup if (!mxMasterInit(mxMaster)) { amiDebugLog("Error mxMasterInit"); return -1; } mxMaster->m_controlPort = 40100; mxMaster->m_dataPort = 40101; mxMaster->m_openMode = OPEN_MODE_LOCAL; mxMasterSysProcessesStart(mxMaster); mxMasterFdcProcessesStart(mxMaster); mxMasterFirstFgProcessesStart(mxMaster); mxMasterMainLoop(mxMaster); }