/*! * @file kboot.cpp * GOAL Boot. Contains the "main" function to launch GOAL runtime * DONE! */ #include #include #include #include #include #include "common/common_types.h" #include "common/util/Timer.h" #include "game/sce/libscf.h" #include "kboot.h" #include "kmachine.h" #include "kscheme.h" #include "ksocket.h" #include "klisten.h" #include "kprint.h" #ifdef _WIN32 #include "Windows.h" #include #elif __linux__ #include #endif using namespace ee; // Level to load on boot char DebugBootLevel[64]; // Pass to GOAL kernel on boot char DebugBootMessage[64]; // game configuration MasterConfig masterConfig; // Set to 1 to kill GOAL kernel u32 MasterExit; // Set to 1 to enable debug heap u32 MasterDebug; // Set to 1 to load debug code u32 DebugSegment; // Set to 1 to load game engine after boot automatically u32 DiskBoot; u32 MasterUseKernel; void kboot_init_globals() { strcpy(DebugBootLevel, "#f"); // no specified level strcpy(DebugBootMessage, "play"); // play mode, the default retail mode MasterExit = 0; MasterDebug = 1; MasterUseKernel = 1; DebugSegment = 1; DiskBoot = 0; memset(&masterConfig, 0, sizeof(MasterConfig)); } /*! * Launch the GOAL Kernel (EE). * DONE! * See InitParms for launch argument details. * @param argc : argument count * @param argv : argument list * @return 0 on success, otherwise failure. * * CHANGES: * Added InitParms call to handle command line arguments * Removed hard-coded debug mode disable * Renamed from `main` to `goal_main` * Add call to sceDeci2Reset when GOAL shuts down. */ s32 goal_main(int argc, const char* const* argv) { // Initialize global variables based on command line parameters // This call is not present in the retail version of the game // but the function is, and it likely goes here. InitParms(argc, argv); // Initialize CRC32 table for string hashing init_crc(); // NTSC V1, NTSC v2, PAL CD Demo, PAL Retail // Set up game configurations masterConfig.aspect = (u16)sceScfGetAspect(); masterConfig.language = (u16)sceScfGetLanguage(); masterConfig.inactive_timeout = 0; masterConfig.timeout = 0; masterConfig.volume = 100; // Set up language configuration if (masterConfig.language == SCE_SPANISH_LANGUAGE) { masterConfig.language = (u16)Language::Spanish; } else if (masterConfig.language == SCE_FRENCH_LANGUAGE) { masterConfig.language = (u16)Language::French; } else if (masterConfig.language == SCE_GERMAN_LANGUAGE) { masterConfig.language = (u16)Language::German; } else if (masterConfig.language == SCE_ITALIAN_LANGUAGE) { masterConfig.language = (u16)Language::Italian; } else { // pick english by default, if language is not supported. masterConfig.language = (u16)Language::English; } // Set up aspect ratio override in demo if (!strcmp(DebugBootMessage, "demo") || !strcmp(DebugBootMessage, "demo-shared")) { masterConfig.aspect = SCE_ASPECT_FULL; } // In retail game, disable debugging modes, and force on DiskBoot // MasterDebug = 0; // DiskBoot = 1; // DebugSegment = 0; // Launch GOAL! if (InitMachine() >= 0) { // init kernel KernelCheckAndDispatch(); // run kernel ShutdownMachine(); // kernel died, we should too. } else { fprintf(stderr, "InitMachine failed\n"); exit(1); } return 0; } /*! * Main loop to dispatch the GOAL kernel. */ void KernelCheckAndDispatch() { u64 goal_stack = u64(g_ee_main_mem) + EE_MAIN_MEM_SIZE - 8; while (!MasterExit) { // try to get a message from the listener, and process it if needed Ptr new_message = WaitForMessageAndAck(); if (new_message.offset) { ProcessListenerMessage(new_message); } // remember the old listener function auto old_listener = ListenerFunction->value; // dispatch the kernel //(**kernel_dispatcher)(); Timer kernel_dispatch_timer; if (MasterUseKernel) { // use the GOAL kernel. call_goal_on_stack(Ptr(kernel_dispatcher->value), goal_stack, s7.offset, g_ee_main_mem); } else { // use a hack to just run the listener function if there's no GOAL kernel. if (ListenerFunction->value != s7.offset) { auto result = call_goal_on_stack(Ptr(ListenerFunction->value), goal_stack, s7.offset, g_ee_main_mem); #ifdef __linux__ cprintf("%ld\n", result); #else cprintf("%lld\n", result); #endif ListenerFunction->value = s7.offset; } } auto time_ms = kernel_dispatch_timer.getMs(); if (time_ms > 3) { printf("Kernel dispatch time: %.3f ms\n", time_ms); } ClearPending(); // if the listener function changed, it means the kernel ran it, so we should notify compiler. if (MasterDebug && ListenerFunction->value != old_listener) { SendAck(); } std::this_thread::sleep_for(std::chrono::microseconds(1000)); } } /*! * Stop running the GOAL Kernel. * DONE, EXACT */ void KernelShutdown() { MasterExit = 2; // GOAL Kernel Dispatch loop will stop now. }