主函数入口分析
主要是检查配置文件,初始化项目及开始工作循
int main(int argc, char **argv) {
initFileIO();//设置软件名为ONScripter-RU
#ifdef DROID
// Attempt to launch an already running ons (by tapping on the icon) right after the installation
// will cause the library not to be loaded and reused without state initialisation.
// We must prevent this somehow and at any cost.
pid_t currentPid = getpid();
static pid_t previousPid;
FileIO::setLogMode(FileIO::LogMode::Unspecified);
sendToLog(LogLevel::Info, "Launched with pid %d, previous pid %d\n", currentPid, previousPid);
if (currentPid == previousPid) {
sendToLog(LogLevel::Error, "Detected same pids, aborting!\n");
// We cannot call the normal exit function here since we already have broken state for many reasons.
// Additionally a new library instance is already being loaded and we are merely awaiting a kill.
// For this reason we just quit silently and return a successful error code.
// We should be calling standard std::quick_exit or _Exit functions but neither is exported :/.
// Yet according to AOSP _exit appears to be _Exit alias and it actually works.
_exit(0);
}
previousPid = currentPid;
#endif
std::atexit([]() {//当程序正常终止时,调用指定的函数 func。
ctrl.deinit();//进行控制器的析构
});
requestHighMemoryUsage();//如果是ios平台,则需申请更多内存权限
bool hasArchivePath = false;//档案路径,脚本等文件所在目录
bool works = false;//工作指示
#ifndef PUBLIC_RELEASE//非正式版,则打开控制台调试
FileIO::setLogMode(FileIO::LogMode::Console); // Enable console logging in development mode
#endif
ons.script_is_set = false;//脚本关
if (!FileIO::setArguments(ons.argc, ons.argv, argc, argv))//将获取的命令行参数转为unicode编码
performTerminate("Failed to obtain program arguments!");
//Firstly, read command line options 解析命令行参数,设置游戏属性,如窗口分辨率,查看帮助等
parseOptions(ons.argc, ons.argv, hasArchivePath);
// --root has zero priority
if (initWithPath(nullptr, hasArchivePath)) {//解析配置文件ons.cfg
works = true;
} else {
// Try app launch dir根目录没找到配置文件,则在APP启动目录下找
works = initWithPath(FileIO::getLaunchDir(), hasArchivePath);
// Try app working dir
if (!works)
works = initWithPath(FileIO::getWorkingDir(), hasArchivePath);
// If there is anything to try, do it
if (!works && FileIO::getPlatformSpecificDir())
works = initWithPath(FileIO::getPlatformSpecificDir(), hasArchivePath);
}
if (!works) {//找不到配置文件,则提示启动目录有误
#ifdef MACOSX
performTerminate("Invalid launch directory!\nTry executing xattr -cr /path/to/onscripter-ru-osx.app");
#else
performTerminate("Invalid launch directory!");
#endif
}
auto &opts = ons.ons_cfg_options;
if (!FileIO::setStorageDir(opts.find("current-user-appdata") != opts.end()) ||
!FileIO::makeDir(FileIO::getStorageDir(opts.find("disable-icloud") == opts.end()), nullptr, true))
performTerminate("Failed to access storage directory!");
if (FileIO::getLogMode() == FileIO::LogMode::File) {
std::string log_path(FileIO::getStorageDir());
FileIO::fileHandleReopen(log_path + "out.txt", stdout);
FileIO::fileHandleReopen(log_path + "err.txt", stderr);
} else if (FileIO::getLogMode() == FileIO::LogMode::Console) {
FileIO::prepareConsole(150, 30);
}
sendToLog(LogLevel::Info, "Available crash reporter features error code %d\n", crashReporterError);
if (ons.init())//进行整个项目的初始化
ctrl.quit(-1);
ons.executeLabel();//开启循环,等待用户指令
ctrl.quit(0);//程序退出
}