Miniconsole: the front end + LocalConsole marshal -- self-launched missions (step 3)
NEW gated dir game/glass/: btl4fe (green-on-black GDI catalog menu -- map/ time/weather/length/mech/color/pilot/mode/port/peers; egg writer emitting the FULL console egg shape, golden-tested vs MP.EGG: identical section sequence at identical line offsets, the 4 static ordinal pages verbatim, GDI-rendered 128x32/64x16 pilot-name plasma bitmaps in MP.EGG framing) and btl4console (the marshal: a worker-thread console CLIENT speaking the btconsole.py wire protocol verbatim -- 1040-byte chunked egg, 20s settle, RunMission x2, STAY CONNECTED, own the clock, StopMission at expiry; logs marshal.log). The engine sees a real connected console and runs the 100% stock ladder -- NO engine hooks (less invasive than planned: the L4APP.H setters proved unnecessary; launches go through real argv on relaunch). WinMain (one gated block): zero-mission-arg glass launch -> menu -> relaunch self with the mission argv (per-mission process relaunch; BT_FE_* env arms the marshal); post-RunMissions BT_FE_LOOP tail returns to the menu. Menu relaunches CLEAR the BT_FE_* handoff (found live: the inherited env re-armed a marshal instead of showing the menu). Verified end-to-end (synthetic menu drive): menu -> frontend.egg -> relaunch -> marshal feeds self over loopback -> stock console ladder -> mission RUNS (58+ ticks) -> 60s clock -> StopMission -> clean menu return, no env leak. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -110,6 +110,11 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
#ifdef BT_GLASS
|
||||
#include "btl4fe.hpp"
|
||||
#include "btl4console.hpp"
|
||||
#endif
|
||||
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
// Heap-corruption hunt (env BT_HEAPCHECK=1; default OFF -- ~100x slower): validate
|
||||
@@ -328,6 +333,67 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
: "DEV (single window + keyboard)")
|
||||
<< std::endl << std::flush;
|
||||
|
||||
#ifdef BT_GLASS
|
||||
//
|
||||
// MINICONSOLE FRONT END (glass step 3): a zero-mission-arg launch (no
|
||||
// -egg, no -net) runs the menu INSTEAD of the game, then RELAUNCHES
|
||||
// this exe with the chosen mission's real arguments -- the per-mission
|
||||
// process-relaunch pattern (reconstructed gBT* globals do not survive
|
||||
// in-process re-init). BT_FE_* env vars arm the mission process's
|
||||
// LocalConsole marshal; BT_FE_LOOP returns post-mission exits to the
|
||||
// menu. The console-wire ladder itself is 100% stock -- the engine
|
||||
// sees a real connected console (btl4console.cpp).
|
||||
//
|
||||
{
|
||||
int fe_has_egg = lpCmdLine && strstr(lpCmdLine, "-egg") != NULL;
|
||||
int fe_has_net = lpCmdLine && strstr(lpCmdLine, "-net") != NULL;
|
||||
if (!fe_has_egg && !fe_has_net && getenv("BT_FE_EGG") == NULL)
|
||||
{
|
||||
BTFeLaunchSpec fe_spec;
|
||||
if (BTFrontEnd_Run(&fe_spec) != 0 || fe_spec.mode == BTFeLaunchNone)
|
||||
{
|
||||
return 0; // quit from the menu
|
||||
}
|
||||
char fe_arguments[192];
|
||||
char fe_value[64];
|
||||
SetEnvironmentVariableA("BT_FE_LOOP", "1");
|
||||
SetEnvironmentVariableA("BT_PLATFORM", "glass");
|
||||
switch (fe_spec.mode)
|
||||
{
|
||||
case BTFeLaunchRawSolo:
|
||||
SetEnvironmentVariableA("BT_FE_EGG", NULL);
|
||||
sprintf(fe_arguments, "-egg %s -platform glass", fe_spec.eggPath);
|
||||
break;
|
||||
case BTFeLaunchJoinLan:
|
||||
SetEnvironmentVariableA("BT_FE_EGG", NULL);
|
||||
sprintf(fe_arguments, "-net %d -platform glass", fe_spec.consolePort);
|
||||
break;
|
||||
default: // Solo / HostLan: the marshal armed via env handoff
|
||||
SetEnvironmentVariableA("BT_FE_EGG", fe_spec.eggPath);
|
||||
SetEnvironmentVariableA("BT_FE_PODS", fe_spec.podList);
|
||||
sprintf(fe_value, "%d", fe_spec.missionSeconds);
|
||||
SetEnvironmentVariableA("BT_FE_SECS", fe_value);
|
||||
sprintf(fe_arguments, "-net %d -platform glass", fe_spec.consolePort);
|
||||
break;
|
||||
}
|
||||
BTFE_RelaunchSelfAndExit(fe_arguments); // never returns
|
||||
}
|
||||
//
|
||||
// A marshal-armed mission process: start the LocalConsole worker
|
||||
// (it retries until our own console listener is up).
|
||||
//
|
||||
const char *fe_egg = getenv("BT_FE_EGG");
|
||||
if (fe_egg != NULL && fe_egg[0])
|
||||
{
|
||||
const char *fe_pods = getenv("BT_FE_PODS");
|
||||
const char *fe_secs = getenv("BT_FE_SECS");
|
||||
BTLocalConsole_Start(fe_egg,
|
||||
fe_pods ? fe_pods : "",
|
||||
fe_secs ? atoi(fe_secs) : 600);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// DEBUG (bring-up, default OFF): force the player mech to walk full-ahead with
|
||||
// no keypress so locomotion + camera-follow can be verified in a headless run.
|
||||
// BT_FORCE_THROTTLE may carry a VALUE: +1 full run, ~0.3 walk, -1 reverse (default 1.0).
|
||||
@@ -508,6 +574,21 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||
app_manager->RunMissions();
|
||||
std::cout << "[boot] RunMissions returned (mission loop exited)." << std::endl << std::flush;
|
||||
|
||||
#ifdef BT_GLASS
|
||||
//
|
||||
// Front-end loop (glass step 3): a menu-launched mission returns
|
||||
// to the menu on exit. (Marshal missions normally relaunch from
|
||||
// the marshal thread at clock expiry; this tail covers raw-solo
|
||||
// and early exits.)
|
||||
//
|
||||
if (getenv("BT_FE_LOOP") != NULL)
|
||||
{
|
||||
std::cout << "[fe] mission over -- relaunching the menu"
|
||||
<< std::endl << std::flush;
|
||||
BTFE_RelaunchSelfAndExit("");
|
||||
}
|
||||
#endif
|
||||
|
||||
btl4App = NULL;
|
||||
Unregister_Object(app_manager);
|
||||
delete app_manager;
|
||||
|
||||
Reference in New Issue
Block a user