Galactic Empire (GE) is a MajorBBS module, not a standalone server. MajorBBS loads the game, routes users' input to it, supplies channel and account information, runs its scheduled callbacks, formats and sends its output, and provides database services. Understanding that boundary is useful when reading GE's source or porting it to another host.

Loading and registration

The 16-bit source supports two MajorBBS integration paths:

  • MajorBBS 5.x: GE is linked into the BBS and enters its common startup routine, iniwara(), through iniwar().
  • MajorBBS 6.x (Phar Lap): The BBS loads GE as a DLL and calls its exported init__galemp() initializer. That initializer reads the module description from the game's MDF file, calls iniwara(), then passes GE's struct module to register_module(). The returned module state code is stored in gestt.

The MDF supplies the name used by the BBS Menu Tree. GE uses gmdnam() to copy that name into the module registration block; the developer's guide warns that a mismatch between the registered description and the MDF name makes the module inaccessible through the menu. Registration by itself does not put the game in a user's menu: the sysop must also link the module into the Menu Tree. Classic names its module block mbmge. ge-next uses mpoge, while ge-arena uses mpoga; those builds also have separate MDF and resource files so they can run alongside classic and one another.

Common startup in iniwara() opens the compiled message bank, reads configuration options, opens Btrieve files, loads ship classes and other game data, allocates in-memory tables, and starts recurring work with rtkick(). The 5.x and 6.x routes differ in how the host reaches GE, not in the main game initialization they perform.

The module interface

MajorBBS's struct module contains a description and nine callback slots. GE fills them as follows in its 6.x registration block (the 5.x build uses corresponding host entry points):

Host event GE routine Purpose
Supplemental logon gelogon() Optional GE message while a user logs on to the BBS.
Module input galemp() Handles menu selections, prompts, and gameplay commands while the user is in GE.
Status input stshdlr() Handles host status input while GE is selected.
Injected-other input NULL GE does not install a special injoth handler.
Supplemental logoff pwarlof() Receives the BBS logoff event. In ge-next, it also clears the session's DATA state.
Carrier loss / hangup pwarhup() Handles an abrupt disconnect, including any needed ship cleanup.
Midnight cleanup pgemidnight() Runs GE's daily maintenance work.
Account deletion pgedelete() Removes that user's GE records when the BBS deletes the account.
System shutdown pclswar() Closes GE resources as the BBS shuts down.

The logon, logoff, hangup, midnight, deletion, and shutdown hooks are host lifecycle events, not commands the player types. The main input callback is different: MajorBBS calls it when a user selects GE and after subsequent input lines. Returning zero leaves the module and returns the user to the parent menu.

Channels and input state

For user-facing callbacks, MajorBBS supplies globals including usrnum (the current channel), usrptr (its live user state), and usaptr (account information). usrptr->state identifies the selected module; usrptr->substt identifies the current prompt or input substate within that module. GE's galemp() uses substt to dispatch to the appropriate menu or gameplay handler. It also establishes pointers to the current channel's GE ship and user entries through warshpoff(usrnum) and warusroff(usrnum).

A channel number is a live connection slot, not a permanent player identity. Slots can be reused after a user disconnects; persistent GE records are keyed separately. GE also uses globals as working storage for the current callback. That is ordinary in the single-threaded MajorBBS execution model, but a port cannot treat those globals as independent per-user state or assume a pointer remains valid for a different callback.

Timed and lifecycle work

During startup, GE schedules recurring callbacks with rtkick(). Those callbacks process ship movement, automatic systems, Cybertrons and other NPC activity, and planetary updates at different intervals. The 5.x and 6.x builds use different callback wrappers where their required function signatures differ. A callback schedules its next run; the host is not executing a separate GE thread. See Game timing and Game execution flow for the full sequence.

The BBS calls GE's registered midnight routine for daily game maintenance. Separately, when the BBS disconnects users for its own cleanup, it calls GE's hangup routine. Classic GE treats that hangup like an ordinary disconnect, so a ship still engaged in combat can be lost. MajorBBS provides rsmodes to indicate that a channel is being reset. ge-next checks it on the hangup path and, when the BBS is disconnecting a combat-locked user for cleanup, saves the ship instead of destroying it.

Output and message resources

GE's MSG source is compiled into MCV resource files. opnmsg() opens a bank, setmbk() selects it, and prfmsg() formats a named message into the host's prfbuf. outprf() sends the formatted text to a channel; clrprf() discards it. The buffer and its write pointer are shared formatting state, not one independent PRF buffer per channel. GE must select the right bank and explicitly send, reuse, or clear the buffer as it delivers messages to different users. A careless clear or send can hide a message or deliver it to the wrong audience. See Configuring Galactic Empire.

Persistent data

GE stores users, ships, sectors and planets, and other game records through the host's Btrieve API. Startup opens the files with the expected record sizes; later operations select a file and use its position block, data buffer, key, operation, and key number. The in-memory channel tables are separate from those persistent records. A port or emulator must preserve the relevant Btrieve key and update behavior, not merely the visible data fields. See Data structures and MBBSEmu.

See also

Source