#include "kboot.h" #include #include #include #include "common/goal_constants.h" #include "common/util/Timer.h" #include "game/common/game_common_types.h" #include "game/kernel/common/Ptr.h" #include "game/kernel/common/Symbol4.h" #include "game/kernel/common/klisten.h" #include "game/kernel/common/kprint.h" #include "game/kernel/common/kscheme.h" #include "game/kernel/common/ksocket.h" #include "game/kernel/jak2/klisten.h" #include "game/kernel/jak2/kmachine.h" #include "game/sce/libscf.h" namespace jak2 { char DebugBootUser[64]; char DebugBootArtGroup[64]; void kboot_init_globals() { memset(DebugBootUser, 0, sizeof(DebugBootUser)); memset(DebugBootArtGroup, 0, sizeof(DebugBootArtGroup)); strcpy(DebugBootUser, "unknown"); } void KernelCheckAndDispatch(); s32 goal_main(int argc, const char* const* argv) { // only in PC port InitParms(argc, argv); init_crc(); masterConfig.aspect = ee::sceScfGetAspect(); auto sony_language = ee::sceScfGetLanguage(); masterConfig.inactive_timeout = 0; masterConfig.volume = 100; masterConfig.timeout = 0; switch (sony_language) { case SCE_JAPANESE_LANGUAGE: masterConfig.language = (u16)Language::Japanese; break; case SCE_FRENCH_LANGUAGE: masterConfig.language = (u16)Language::French; break; case SCE_SPANISH_LANGUAGE: masterConfig.language = (u16)Language::Spanish; break; case SCE_GERMAN_LANGUAGE: masterConfig.language = (u16)Language::German; break; case SCE_ITALIAN_LANGUAGE: masterConfig.language = (u16)Language::Italian; default: masterConfig.language = (u16)Language::English; break; } // Set up aspect ratio override in demo if (!strcmp(DebugBootMessage, "demo") || !strcmp(DebugBootMessage, "demo-shared")) { masterConfig.aspect = SCE_ASPECT_FULL; } // removed in PC port // DiskBoot = 1; // MasterDebug = 0; // DebugSegment = 0; // Launch GOAL! if (InitMachine() >= 0) { // init kernel KernelCheckAndDispatch(); // run kernel ShutdownMachine(); // kernel died, we should too. // movie playback stuff removed. } else { fprintf(stderr, "InitMachine failed\n"); exit(1); } return 0; } void KernelDispatch(u32 dispatcher_func) { // place our stack at the end of EE memory u64 goal_stack = u64(g_ee_main_mem) + EE_MAIN_MEM_SIZE - 8; // 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 auto old_listener_function = ListenerFunction->value(); // run the kernel! Timer dispatch_timer; if (MasterUseKernel) { call_goal_on_stack(Ptr(dispatcher_func), goal_stack, s7.offset, g_ee_main_mem); } else { // added, just calls the listener function 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; } } float time_ms = dispatch_timer.getMs(); if (time_ms > 50) { printf("Kernel dispatch time: %.3f ms\n", time_ms); } // flush stdout ClearPending(); // now run the extra "kernel function" auto bonus_function = KernelFunction->value(); if (bonus_function != s7.offset) { // clear the pending kernel function KernelFunction->value() = s7.offset; // and run call_goal_on_stack(Ptr(bonus_function), goal_stack, s7.offset, g_ee_main_mem); } // send ack to indicate that the listener function has been processed and the result printed if (MasterDebug && ListenerFunction->value() != old_listener_function) { SendAck(); } // prevent crazy spinning if we're not vsyncing (added) if (time_ms < 4) { std::this_thread::sleep_for(std::chrono::microseconds(1000)); } } void KernelShutdown(u32 reason) { MasterExit = (RuntimeExitStatus)reason; } void KernelCheckAndDispatch() { while (MasterExit == RuntimeExitStatus::RUNNING) { KernelDispatch(kernel_dispatcher->value()); } } } // namespace jak2