Skip to content

Zero Hour can still launch with no base Generals content when no Generals root is declared #333

Description

@bobtista

Problem

A Zero Hour launch with no reachable base Generals content starts and runs broken, and neither GenHub nor the engine reports it.

Verified in the engine source — StdBIGFileSystem::init() on bobtista/GeneralsGameCode at bobtista/topic/trunk:

// load original Generals assets
AsciiString installPath;
GetStringFromGeneralsRegistry("", "InstallPath", installPath );
//@todo this will need to be ramped up to a crash for release
DEBUG_ASSERTCRASH(!installPath.isEmpty(), ("Be 1337! Go install Generals!"));
if (!installPath.isEmpty())
  loadBigFilesFromDirectory(installPath, "*.big");

With an empty Generals install path the base load is skipped silently in release buildsDEBUG_ASSERTCRASH is debug-only, and the in-tree @todo records that it ought to be a release crash but is not. The block is RTS_ZEROHOUR-guarded, confirming Zero Hour is the case that needs base content.

This is distinct from the failures the engine does report. Those were reproduced end-to-end on the trunk macOS build: an empty root aborts during initialisation with exit 1 and a ReleaseCrashInfo.txt, and an unmountable archive additionally writes [ggc] ARCHIVE MOUNT FAILED to stderr. Neither reaches the main loop. The missing-base-content case is the one expected to get through: the silent skip is verified in source, but whether Zero Hour then actually boots past initialisation silently broken has not been reproduced. Establishing that, both ways — no base content anywhere must fail; base archives present in the working directory must still be accepted — is the acceptance gate for any fix here.

Why GenHub's validation cannot close it

#315 rejects a retail root that is absent, unreadable, or holds no *.big, and #332 extended that so a Zero Hour launch also checks a declared Generals root. What remains is the case where no Generals root is declared at all.

That cannot simply be made an error. The engine mounts archives from the working directory as well, so base content may legitimately sit in the profile workspace rather than a retail root — the arrangement the install-path environment replaces, still valid.

Distinguishing the two needs to know whether base content is actually reachable, which is not testable from filenames. A real install holds arbitrary archives beside the retail ones:

!!!HotkeyIDMarkersZHEnglish_v2.big
310_ExpandedLANLobbyMenu.big
340_ControlBarPro720ZH.big

A workspace *.big check was considered and rejected: a Zero Hour workspace always contains archives, so it would always pass — worse than no check, because it reads as a guard while guaranteeing nothing.

What would close it

Either side works:

  • Engine: promote the empty-installPath case for Zero Hour from a debug assert to an observable failure, as the @todo already anticipates.
  • GenHub: act on a mount-count or mount-failure signal once the engine exposes one.

The engine route is cheaper and the @todo suggests it was always intended.

Acceptance criteria

  • A Zero Hour launch with no reachable base content fails with an actionable error naming the cause.
  • A Zero Hour profile whose base content comes from the workspace still launches.
  • No filename-based heuristic for identifying base archives.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions