force services into guest process and singlecore option

This commit is contained in:
lizzie 2026-06-10 01:29:34 +00:00
parent 27ab01fd1d
commit bcfab23498
5 changed files with 32 additions and 19 deletions

View file

@ -28,4 +28,5 @@ There are two main applications, an SDL-based app (`eden-cli`) and a Qt based ap
- `--version/-v`: Display version and quit. - `--version/-v`: Display version and quit.
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only). - `--input-profile/-i`: Specifies input profile name to use (for player #0 only).
- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings. - `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings.
- `--filter/-F`: Sets the debug log filter irrespective of settings. - `--filter/-x`: Sets the debug log filter irrespective of settings.
- `--singlecore/-s`: Forces single-core regardless of settings.

View file

@ -86,7 +86,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
// BEGONE cold clones of lambdas, for I have merged you all into a SINGLE lambda instead of // BEGONE cold clones of lambdas, for I have merged you all into a SINGLE lambda instead of
// spamming lambdas like it's some kind of lambda calculus class // spamming lambdas like it's some kind of lambda calculus class
for (auto const& e : std::vector<std::pair<std::string_view, void (*)(Core::System&)>>{ std::vector<std::pair<std::string_view, void (*)(Core::System&)>> rt_services{
{"audio", &Audio::LoopProcess}, {"audio", &Audio::LoopProcess},
{"FS", &FileSystem::LoopProcess}, {"FS", &FileSystem::LoopProcess},
// Must match with src/core/CMakeLists.txt for target_source of jit.cpp // Must match with src/core/CMakeLists.txt for target_source of jit.cpp
@ -97,9 +97,16 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
{"Loader", &LDR::LoopProcess}, {"Loader", &LDR::LoopProcess},
{"nvservices", &Nvidia::LoopProcess}, {"nvservices", &Nvidia::LoopProcess},
{"bsdsocket", &Sockets::LoopProcess}, {"bsdsocket", &Sockets::LoopProcess},
}) };
#if defined(__EMSCRIPTEN__) || defined(__wasi__) || defined(__OPENORBIS__)
for (auto const& e : rt_services)
kernel.RunOnGuestCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); });
kernel.RunOnGuestCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); });
#else
for (auto const& e : rt_services)
kernel.RunOnHostCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); }).detach(); kernel.RunOnHostCoreProcess(std::string(e.first), [&system, f = e.second] { f(system); }).detach();
kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach(); kernel.RunOnHostCoreProcess("vi", [&, token] { VI::LoopProcess(system, token); }).detach();
#endif
// Avoid cold clones of lambdas -- succintly // Avoid cold clones of lambdas -- succintly
for (auto const& e : std::vector<std::pair<std::string_view, void (*)(Core::System&)>>{ for (auto const& e : std::vector<std::pair<std::string_view, void (*)(Core::System&)>>{
{"sm", &SM::LoopProcess}, {"sm", &SM::LoopProcess},

View file

@ -199,7 +199,7 @@ void EmuWindow_SDL3::OnEvent(SDL_Event& event) {
case SDL_EVENT_MOUSE_BUTTON_UP: case SDL_EVENT_MOUSE_BUTTON_UP:
// ignore if it came from touch // ignore if it came from touch
if (event.button.which != SDL_TOUCH_MOUSEID) { if (event.button.which != SDL_TOUCH_MOUSEID) {
OnMouseButton(event.button.button, event.button.down ? 1 : 0, s32(event.button.x), s3>(event.button.y)); OnMouseButton(event.button.button, event.button.down ? 1 : 0, s32(event.button.x), s32(event.button.y));
} }
return; return;
case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_DOWN:

View file

@ -216,6 +216,7 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
bool use_multiplayer = false; bool use_multiplayer = false;
bool fullscreen = false; bool fullscreen = false;
bool force_null_render = false; bool force_null_render = false;
bool force_single_core = false;
std::string nickname{}; std::string nickname{};
std::string password{}; std::string password{};
std::string address{}; std::string address{};
@ -236,7 +237,8 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
{"version", no_argument, 0, 'v'}, {"version", no_argument, 0, 'v'},
{"input-profile", no_argument, 0, 'i'}, {"input-profile", no_argument, 0, 'i'},
{"null-render", no_argument, 0, 'n'}, {"null-render", no_argument, 0, 'n'},
{"filter", no_argument, 0, 'F'}, {"singlecore", no_argument, 0, 's'},
{"filter", no_argument, 0, 'x'},
{0, 0, 0, 0}, {0, 0, 0, 0},
// clang-format on // clang-format on
}; };
@ -310,7 +312,10 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
case 'n': case 'n':
force_null_render = true; force_null_render = true;
break; break;
case 'F': case 's':
force_single_core = true;
break;
case 'x':
log_filter = argv[optind]; log_filter = argv[optind];
++optind; ++optind;
break; break;
@ -351,6 +356,10 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
Settings::values.gdbstub_port = *override_gdb_port; Settings::values.gdbstub_port = *override_gdb_port;
} }
if (force_single_core) {
Settings::values.use_multi_core = false;
}
if (force_null_render) { if (force_null_render) {
Settings::values.renderer_backend = Settings::RendererBackend::Null; Settings::values.renderer_backend = Settings::RendererBackend::Null;
} }

View file

@ -5,8 +5,7 @@
import { createServer } from 'http'; import { createServer } from 'http';
import { readFile } from 'fs'; import { readFile } from 'fs';
import { join } from 'path'; import { join } from 'path';
console.log(`dont forget to run: "npm --global install @jdmichaud/dwarf-2-sourcemap" for better debugging!`);
// DO NOT RUN THIS IN ANY PRODUCTION ENVIRONMENT EVER
const server = createServer((req, res) => { const server = createServer((req, res) => {
console.log(`get ${req.url}`); console.log(`get ${req.url}`);
if (req.url === '/') { if (req.url === '/') {
@ -22,15 +21,15 @@ const server = createServer((req, res) => {
<head> <head>
<title>eden-cli</title> <title>eden-cli</title>
</head> </head>
<body style="margin:0;padding:0;background-color:black;font-family:Monospace,Tahoma,Arial;width:100%;height:100%;"> <body style="margin:0;padding:0;background-color:black;color:white;font-family:Monospace,Tahoma,Arial;">
<div style="display:grid;grid-template-columns:1fr 1fr;gap:2px;width:100%;height:100%;"> <div style="display:grid;grid-template-columns:1fr 1fr;gap:2px;width:100%;height:100vh;">
<canvas id="canvas" oncontextmenu="event.preventDefault()" style="width:100%;height:100%;background-color:gray;"></canvas> <canvas id="canvas" oncontextmenu="event.preventDefault()" style="width:100%;height:100%;background-color:gray;"></canvas>
<div id="tty-stdout"></div> <div id="tty-stdout"></div>
</div> </div>
<script> <script>
var Module = { //do not prepend var var Module = { //do not prepend var
mainScriptUrlOrBlob: 'eden-cli.js', mainScriptUrlOrBlob: 'eden-cli.js',
arguments: ['--null-render', '-F', '*:Trace', 'game.nro'], arguments: ['--null-render', '--singlecore', '--filter', '*:Trace', 'game.nro'],
canvas: document.getElementById('canvas'), canvas: document.getElementById('canvas'),
print: (e) => { print: (e) => {
e = e.replace('[1;31m', '<span style="color:red;font-weight:bold;">'); e = e.replace('[1;31m', '<span style="color:red;font-weight:bold;">');
@ -52,9 +51,7 @@ var Module = { //do not prepend var
monitorRunDependencies: (e) => { Module.printInternal("monitor deps: " + e); }, monitorRunDependencies: (e) => { Module.printInternal("monitor deps: " + e); },
__wasm_call_ctors: () => { Module.printInternal("ctors beep"); }, __wasm_call_ctors: () => { Module.printInternal("ctors beep"); },
}; };
var gameNroFileBuffer = {}; var gameNroFileBuffer = {};
Module.printInternal(\`Atomics: \${window.Atomics}, SharedArrayBuffer: \${window.SharedArrayBuffer}\`); Module.printInternal(\`Atomics: \${window.Atomics}, SharedArrayBuffer: \${window.SharedArrayBuffer}\`);
Module.printInternal("trying to load script (if it hangs here check console)"); Module.printInternal("trying to load script (if it hangs here check console)");
fetch('game.nro').then((resp) => { fetch('game.nro').then((resp) => {
@ -63,8 +60,7 @@ fetch('game.nro').then((resp) => {
return resp.arrayBuffer(); return resp.arrayBuffer();
}).then((buffer) => { }).then((buffer) => {
gameNroFileBuffer = buffer; gameNroFileBuffer = buffer;
Module.printInternal("buffer: " + gameNroFileBuffer); Module.printInternal(\`buffer: \${gameNroFileBuffer}\`);
// load the thingy AFTER loading the nro // load the thingy AFTER loading the nro
Module.printInternal(\`loading from ${build_dir}/\${Module.mainScriptUrlOrBlob}\`); Module.printInternal(\`loading from ${build_dir}/\${Module.mainScriptUrlOrBlob}\`);
var script = document.createElement('script'); var script = document.createElement('script');
@ -95,16 +91,16 @@ fetch('game.nro').then((resp) => {
'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp' 'Cross-Origin-Embedder-Policy': 'require-corp'
}); });
res.end(content, 'utf-8'); res.end(content);
}); });
} else if (req.url === '/game.nro') { } else if (req.url === '/game.nro') {
readFile(nro_file, (err, content) => { readFile(nro_file, (err, content) => {
res.writeHead(200, { res.writeHead(200, {
'Content-Type': 'application/wasm', 'Content-Type': 'application/octet-stream',
'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp' 'Cross-Origin-Embedder-Policy': 'require-corp'
}); });
res.end(content, 'utf-8'); res.end(content);
}); });
} else { } else {
res.writeHead(404, {}); res.writeHead(404, {});