mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
0451a06d76
* set up the compiler to ptrace the runtime * clang format * move debugger state to a separate Debugger class * support registers and break and continue * documentation and fix windows * make listener part of compiler, not a separate library * implement memory read and write * fix for windows
192 lines
5.1 KiB
C++
192 lines
5.1 KiB
C++
/*!
|
|
* @file kboot.cpp
|
|
* GOAL Boot. Contains the "main" function to launch GOAL runtime
|
|
* DONE!
|
|
*/
|
|
|
|
#include <cstring>
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
#include "common/cross_os_debug/xdbg.h"
|
|
#include "common/common_types.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 <io.h>
|
|
#elif __linux__
|
|
#include <unistd.h>
|
|
#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) {
|
|
// Added for OpenGOAL's debugger
|
|
xdbg::allow_debugging();
|
|
|
|
// 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() {
|
|
while (!MasterExit) {
|
|
// try to get a message from the listener, and process it if needed
|
|
Ptr<char> 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)();
|
|
|
|
// todo remove. this is added while KERNEL.CGO is broken.
|
|
if (MasterUseKernel) {
|
|
call_goal(Ptr<Function>(kernel_dispatcher->value), 0, 0, 0, s7.offset, g_ee_main_mem);
|
|
} else {
|
|
if (ListenerFunction->value != s7.offset) {
|
|
// fprintf(stderr, "Running Listener Function:\n");
|
|
// auto cptr = Ptr<u8>(ListenerFunction->value).c();
|
|
// for (int i = 0; i < 40; i++) {
|
|
// fprintf(stderr, "%x ", cptr[i]);
|
|
// }
|
|
// fprintf(stderr, "\n");
|
|
auto result =
|
|
call_goal(Ptr<Function>(ListenerFunction->value), 0, 0, 0, s7.offset, g_ee_main_mem);
|
|
// fprintf(stderr, "result of listener function: %lld\n", result);
|
|
#ifdef __linux__
|
|
cprintf("%ld\n", result);
|
|
#else
|
|
cprintf("%lld\n", result);
|
|
#endif
|
|
ListenerFunction->value = s7.offset;
|
|
}
|
|
}
|
|
|
|
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 = 1; // GOAL Kernel Dispatch loop will stop now.
|
|
}
|