.QVM in IGI 2 -- Advanced Script Bytecode

1. Architectural Role & Engine Purpose

The QVM (Covert Strike Virtual Machine Bytecode) format powers the advanced tactical simulation, multi-tiered stealth awareness systems, security alarm matrices, surveillance camera panning networks, and mission objective progressions in I.G.I. 2: Covert Strike (2003).

For the sequel, Innerloop kept the same LOOP bytecode container (VM v8.5, 49 opcodes) while shipping a much richer script catalog: AI routines, physics hooks, per-level objects.qvm, config and menu scripts. QVM content is more complex even though the bytecode format is shared with IGI 1.

2. Binary File Layout & Memory Map Diagram

The IGI 2 QVM format keeps the shared 60-byte LOOP header (VM v8.5) with table indexing for larger scripts:

IGI 2 QVM SCRIPT BYTECODE — BINARY FILE LAYOUT (VM v8.5, SHARED) 0x00: Header (60 Bytes) 60 BYTES FourCC "LOOP" | Major: 8 | Minor: 5 (VM v8.5) | Table Offsets & Sizes | Runtime Flags signature[4], ver_major (8), ver_minor (5), of_itable, of_ivalue, sz_itable, of_stable, sz_ctable... OFFSET: of_itable — Identifier Table POINTERS Array of 32-bit descriptors pointing into Identifier String Pool sz_itable bytes • Function & Object Schema Symbol Indexing OFFSET: of_ivalue — Identifier String Pool SYMBOLS Contiguous null-terminated ASCII symbol names "DefineMagicObj", "Task_InvestigateNoise", "m_nAlertLevel" OFFSET: of_stable — String Table (STable) POINTERS Array of 32-bit pointers into String Value Pool sz_stable bytes • Multi-language dialogue & subtitle text OFFSET: of_svalue — String Value Pool STRINGS Contiguous null-terminated dialogue & OSD string literals "Anya: Alarm in Sector B!", "Thermal Mode Active" OFFSET: of_ctable — Extended Bytecode Stream (55 Opcodes) 55 OPCODES VM v8.5 Instruction Stream: 49 shared opcodes (0x00-0x30), Native Bridges [PUSH: 0x02] [CALL: 0x18] [0x00000001] [0x00000045] [RET: 0x13]

3. Engine Pipeline & Multi-Threaded Task Scheduler Diagram

IGI 2 executes scripts across cooperative priority queues, dynamically handling guard AI combat tactics:

IGI 2 SCRIPT ENGINE — MULTI-THREADED TASK SCHEDULER 1. DISK INGESTION • Read from .RES2 Archive • Verify "LOOP" & v8.5 • Allocate Memory Heap 2. TASK PRIORITIZER • High: Combat AI (Every Tick) • Med: Patrols (Every 2 Ticks) • Low: Ambient (Every 5 Ticks) 3. SENSORY QUEUE • FIFO Interrupt Buffer • Sight / Sound Signals • Dispatch Events to AI 4. 55 OPCODES • Fetch Bytecode • Object Dereference • Math & Flow Control 5. NATIVE IGI2.EXE ENGINE METHOD DISPATCH • Over 180 registered native engine routines via push-pair registrars • Tactical Squad Coordination, Cover Evaluation, Thermal Radar Hooks • Safe execution without corrupting shared global memory state

4. Architectural Mechanics & Engine Implementation Details

The shared VM v8.5 runtime executes IGI 2's larger script catalog (AI, physics, per-level objects.qvm, config, menus) without changing the bytecode format:

  • Shared Opcode Space: The same 49 opcodes (0x00–0x30) as IGI 1 — stack pushes, arithmetic, comparisons, branches (BRA/BF/BT), JSR/RET, and CALL (0x18) for script subroutines and native engine methods.
  • Richer Script Content: Larger identifier/string pools and per-level scripts drive squad behaviors, alarm matrices, camera networks, and mission objectives.
  • Native Symbol Registration: Engine APIs are bound via native registrar push-pairs in IGI2.EXE, providing fine-grained control over guard vision cones, weapon dispersion, and dialogue playback.

5. Binary Header Specification (60 Bytes)

OffsetSizeTypeFieldDescription
0x004char[4]signatureMagic FourCC: "LOOP" (0x4C4F4F50 in little-endian)
0x044uint32_tver_majorMajor version: strictly 8
0x084uint32_tver_minorMinor version: strictly 5 (VM v8.5, shared with IGI 1)
0x0C4uint32_tof_itableByte offset to Identifier Table (ITable)
0x104uint32_tof_ivalueByte offset to Identifier String Pool
0x144uint32_tsz_itableSize of Identifier Table in bytes
0x184uint32_tsz_ivalueSize of Identifier String Pool in bytes
0x1C4uint32_tof_stableByte offset to String Table (STable)
0x204uint32_tof_svalueByte offset to String Value Pool
0x244uint32_tsz_stableSize of String Table in bytes
0x284uint32_tsz_svalueSize of String Value Pool in bytes
0x2C4uint32_tof_ctableByte offset to Bytecode Section (CTable)
0x304uint32_tsz_ctableSize of Bytecode Section in bytes
0x344uint32_tflagsScheduler configuration flags
0x384uint32_treservedAlignment padding

6. C++ Struct Definitions

#pragma pack(push, 1)
struct QvmHeaderIgi2 {
    char     signature[4];  // "LOOP"
    uint32_t ver_major;     // 8 (shared VM v8.5)
    uint32_t ver_minor;     // 5
    uint32_t of_itable;     // Offset to Identifier Table
    uint32_t of_ivalue;     // Offset to Identifier Strings
    uint32_t sz_itable;     // Size of Identifier Table
    uint32_t sz_ivalue;     // Size of Identifier String Pool
    uint32_t of_stable;     // Offset to String Table
    uint32_t of_svalue;     // Offset to String Values
    uint32_t sz_stable;     // Size of String Table
    uint32_t sz_svalue;     // Size of String Value Pool
    uint32_t of_ctable;     // Offset to Bytecode Section
    uint32_t sz_ctable;     // Size of Bytecode Section
    uint32_t flags;         // Execution flags
    uint32_t reserved;      // Alignment
};
static_assert(sizeof(QvmHeaderIgi2) == 60, "QvmHeaderIgi2 must be 60 bytes");
#pragma pack(pop)