Skip to content

Boot / Loading Sequence

This page documents the boot-up sequence from process entry to the main menu. The sequence is derived from crimsonland_main analysis and the iterative asset loader load_textures_step.

1. System Initialization

(crimsonland_main start)

  1. DirectX / System Checks: Verifies DX8.1+, SSE support, etc.
  2. Path Setup: Sets current working directory (crt_getcwd).
  3. Console Init: Registers commands (console_register_command) and core cvars (register_core_cvars).
  4. Config Load: Loads crimson.cfg and executes autoexec.txt.
  5. Grim2D Init:
  6. grim_init_system
  7. grim_apply_config (Resolution/Window mode)
  8. Audio/Terrain Init: init_audio_and_terrain (0x0042a9f0).

2. Splash Assets Loading

(crimsonland_main continued)

The game pre-loads specific textures needed for the splash screen and loading screen before the main asset load.

Texture Resource Notes
backplasma load\backplasma.jaz 64×64 RGBA plasma tile (extracted as backplasma.png).
mockup load\mockup.jaz 512×256 RGBA overlay (extracted as mockup.png).
logo_esrb load\esrb_mature.jaz 256×128 RGBA ESRB logo (extracted as esrb_mature.png).
loading load\loading.jaz 128×32 RGBA "LOADING..." (extracted as loading.png).
cl_logo load\logo_crimsonland.tga 512×64 RGBA logo (extracted as logo_crimsonland.png).
splash10tons load\splash10tons.jaz 512×128 RGBA company logo (extracted as splash10tons.png).
splashReflexive load\splashReflexive.jpg 512×256 RGB company logo (extracted as splashReflexive.jpg).

Note: splash10tons and splashReflexive are loaded in game_startup_init after the main texture steps complete, not directly inside crimsonland_main.

3. Splash Screen Rendering (Runtime Evidence)

Runtime capture (artifacts/frida/share/splash_draw_calls.jsonl) shows the exact draw calls for the splash/loading screen at 800x600. Key facts:

  • Background: black clear. No backplasma or mockup draw calls appear in the captured splash frame.

  • Drawn textures: cl_logo, loading, logo_esrb.

  • Band frame: 1px rectangle around the logo band, rendered using cl_logo as a solid-tinted quad.

Geometry (800x600)

  • Logo: x=144, y=268, w=512, h=64 (centered).
  • Loading text: x=528, y=316, w=128, h=32 (right-aligned to logo).
  • ESRB: x=543, y=471, w=256, h=128 (bottom-right, 1px margin).
  • Band frame: a 808x128 rectangle centered on the logo:
  • Top: x=-4, y=232, w=808, h=1
  • Bottom: x=-4, y=360, w=809, h=1
  • Left: x=-4, y=232, w=1, h=128
  • Right: x=804, y=232, w=1, h=128

Colors / alpha

  • Logo/Loading/ESRB are drawn with a shared fade alpha (observed sequence: 0.03, 0.23, 0.42, 0.598, 0.772, 0.932, 1.0).

  • Band frame color ≈ #95AFC6 (r=0.5843, g=0.6863, b=0.7765).

  • Band frame alpha = logo_alpha * 0.7.

Note: The capture only logs splash draws in frame 0, so timing/duration cannot be inferred from this capture alone; the static timing model below supplies the fade schedule.

4. Splash Render Routine (Static + Runtime)

The draw calls above are inside game_startup_init (0x0042b290), with the loading-screen draw block around 0x0042be900x0042c1e2. The routine:

State / fade

  • startup_splash_timer (0x004aaf90) is incremented each tick by frame_dt (0x00480840).
  • alpha = clamp(2.0 * startup_splash_timer, 0.0, 1.0); clamped by comparing against constants 1.0 and 0.0.

  • The same alpha is used for logo_esrb, loading, and cl_logo.

  • The band frame uses alpha * 0.7 (validated in runtime capture).

Render setup (per frame)

From the assembly around 0x0042be90:

  • grim_clear_color(0, 0, 0, 1) (vtable +0x2c).
  • grim_set_config_var(0x15, 1) (vtable +0x20; D3D filter/texture state ID).
  • grim_set_color(1, 1, 1, alpha) (vtable +0x114).
  • grim_set_uv(0, 0, 1, 1) (vtable +0x100).
  • grim_set_rotation(0) (vtable +0xfc).

Draw order (per pass)

Each pass uses grim_get_texture_handle + grim_bind_texture, then grim_begin_batchgrim_draw_quadgrim_end_batch:

  1. ESRB (logo_esrb)
  2. x = screen_width - 257
  3. y = screen_height - 129
  4. w = 256, h = 128
  5. Loading (loading)
  6. x = (screen_width * 0.5) + 128
  7. y = (screen_height * 0.5) + 16
  8. w = 128, h = 32
  9. Logo (cl_logo)
  10. x = (screen_width * 0.5) - 256
  11. y = (screen_height * 0.5) - 32
  12. w = 512, h = 64
  13. Band frame (four 1px quads tinted)
  14. Top: x = -4, y = (screen_height * 0.5) - 68, w = screen_width + 8, h = 1
  15. Bottom: x = -4, y = (screen_height * 0.5) + 60, w = screen_width + 9, h = 1
  16. Left: x = -4, y = (screen_height * 0.5) - 68, w = 1, h = 128
  17. Right: x = screen_width + 4, y = (screen_height * 0.5) - 68, w = 1, h = 128

The band frame draw is implemented inside grim.dll (callsites in the DLL), but the geometry and color are confirmed via Frida capture.

5. Company Logo Sequence (Static)

The company logo sequence runs inside game_startup_init after load_textures_step completes and the splash fade-out finishes.

Activation / gating

  • When textures finish, the game loads splashReflexive and splash10Tons, runs game_startup_init_prelude, starts the sound thread, and clamps startup_splash_timer to 0.5 if it is larger. [static]

  • This handoff is gated by startup latches: startup_bootstrap_pending (0x004aaf86) -> startup_logo_sequence_active (0x004aaf9c), with startup_skip_requested (0x004aaf94) controlling fast-forward behavior. [static]

  • A 5-tick delay (Sleep(5) per tick) runs before the logos display, tracked by startup_post_load_settle_ticks (0x004aaf98). [static]

Timing model

  • The internal timer (startup_splash_timer) advances by frame_dt * 1.1. [static]
  • For logo rendering, it uses t = startup_splash_timer - 2.0. [static]
  • If the user skips (key/mouse), time jumps to t = 16.0 when not inside a fade window; otherwise it accelerates by frame_dt * 4.0. [static]

10tons logo (512×128)

  • Fade in: t in [1.0, 2.0) → alpha = t - 1.0 (0→1). [static]
  • Hold: t in [2.0, 4.0) → alpha = 1.0. [static]
  • Fade out: t in [4.0, 5.0) → alpha = 1.0 - (t - 4.0) (1→0). [static]

Reflexive logo (512×256)

  • Fade in: t in [7.0, 8.0) → alpha = t - 7.0. [static]
  • Hold: t in [8.0, 10.0) → alpha = 1.0. [static]
  • Fade out: t in [10.0, 11.0) → alpha = 1.0 - (t - 10.0). [static]

Handoff to theme

  • When startup_splash_timer > 14.0, the intro is muted and crimson_theme (or crimsonquest in demo mode) begins, ending the logo sequence. [static+runtime]

6. Main Asset Loading Loop (load_textures_step)

The game enters a loop where it calls load_textures_step (0x0042abd0) repeatedly. While this loop runs, the loading texture (load\loading.jaz) is displayed on screen.

load_textures_step returns 0 while busy and 1 when finished. It uses startup_texture_load_stage (0x004aaf88) to track progress (0..9).

Loading Steps

Step Assets Loaded
0 Creatures: trooper, zombie, spider (sp1/sp2), alien, lizard, smallWhite font.
1 Projectiles/Bodies: arrow, bullet16, bulletTrail, bodyset, projs (projectiles).
2 UI Basics: ui_iconAim, ui_button (Sm/Md), ui_check (On/Off), ui_rect (On/Off), bonuses.
3 Indicators & Particles: ui_indBullet, ui_indRocket, ui_indElectric, ui_indFire, particles.
4 UI Cursor & Panels: ui_indLife, ui_indPanel, ui_arrow, ui_cursor, ui_aim.
5 Terrain Textures: ter_q1..q4 (base/tex1) OR ter_fb (fallback) if high-res failed.
6 UI Text & Numbers: ui_textLevComp, ui_textQuest, ui_num1..num5.
7 HUD / Weapon Icons: ui_wicons, ui_gameTop, ui_lifeHeart, ui_clockTable, ui_clockPointer.
8 Muzzle Flash & Dropdowns: muzzleFlash, ui_dropDown (On/Off).
9 Finalization: Creates bullet_i and aim64 sprites. Sets game_state_id = 0.

7. Startup Finalization

(game_startup_init @ 0x0042b290)

Once loading is complete (step > 9):

  1. Effect/UV Tables: effect_uv_tables_init.
  2. Databases: perks_init_database, weapon_table_init.
  3. Game Core: game_core_init.
  4. Easter Eggs: Checks system date (e.g. Sep 12, Nov 8, Dec 18) for special behavior (s_balloon).
  5. Gameplay Reset: gameplay_reset_state, terrain_generate_random.
  6. Registry: Updates "Time Played" counter.

Boot music handoff (runtime evidence)

Frida trace (artifacts/frida/share/music_intro_trace.jsonl) shows the intro track is played inside game_startup_init, then muted and replaced by crimson_theme:

  • sfx_play_exclusive(music_track_intro_id) at 0x0042b69a
  • sfx_mute_all(music_track_intro_id) at 0x0042b556
  • sfx_play_exclusive(music_track_crimson_theme_id) at 0x0042b584

Measured timing from the same trace:

  • Intro starts ~20.4s after process start and plays for ~12.7s.
  • Theme starts immediately after intro mute (same frame).

Additional sfx_mute_all calls with return addresses in ui_menu_click_back_contextual (0x00447420) occur later during UI transitions (menu flow), not the boot sequence.

8. Main Loop

The game enters the main loop with game_state_id = 0 (Main Menu). The per-frame input/hotkey pass here is game_frame_update (0x0040c1c0).

Post-logo render setup

The early grim_clear_color calls clear the target; config ID 0x36 invokes IDirect3DDevice8::Present. The subsequent loading and logo draw loop is game_startup_init, described above. See the Grim config API and tools/native/recovered/grim/config/set_var.cpp for state-ID semantics.

For visual verification, compare logo/loading/ESRB geometry, layering and fades at the target resolution. load\loading.jaz is the 128×32 loading label shown above, not a fullscreen background.