Grand Theft Auto 2 Wild Demo

Exact artifacts

The installed program tree has 73 payload files. InstallShield also writes uninst.isu, making 74 files beneath C:\Program Files\GTA2 DEMO after a complete run.

Authentic installer chain

gta2demo.exe is a PackageForTheWeb self-extractor. Its LZ32 calls unpack 92 split data*.cab volumes and the rest of Disk1 under C:\WINDOWS\TEMP\pftw3~tmp\Disk1. It then calls:

CreateProcessA(NULL, "\"C:\WINDOWS\TEMP\pftw3~tmp\Disk1\Setup.exe\" /SMS", ...)

The emitted 73,728-byte Setup.exe has SHA-256 5656e87da0641c9dcfcd0ee8949ce72b3fa6a7d0e8b1fd985a16f6bd6c34ce52. It expands the InstallShield engine and invokes C:\WINDOWS\TEMP\_ISTMP1.DIR\_INS5576._MP with WinExec. That engine has SHA-256 a8657371f03e2e66db951c3dcd3aeb42c576894908ca2eb1b3806aa0404cb083.

Wine Assembly currently emulates one Win32 process and does not execute either child-process request. test/test-gta2-demo-installer.js therefore resumes the two files emitted by the preceding authentic stage as separate emulator runs. It does not use Unshield. The engine receives the command line generated by Setup's _INS0432.INI, its actual wizard pages are clicked, its cabinet copy runs, and acceptance requires this final text:

The GTA2 Installer has finished installing GTA2 on your computer.
The GTA2 Installer can now launch GTA2.

Unshield was used once while diagnosing a split-volume boundary issue and to compare file layouts. That extraction is neither the prepared collection path nor installer acceptance.

Compatibility findings

Gameplay reproduction

node test/run.js --app=gta2_demo --no-build \
  --max-batches=4500 --batch-size=1000 \
  '--input=3000:di-keydown:13,3100:di-keyup:13' \
  --quiet-api --quiet-blocks --dx-slot=7 --png=/tmp/gta2.png

Slot 7 is the primary gameplay surface. The generic screenshot heuristic can otherwise select a cached front-end surface because this title creates many DirectDraw surfaces. The captured 640x480 frame contains the player in the Wild Demo playfield, the health-heart HUD, and the opening tutorial message.

Shared lazy synchronization A/B (2026-09-29)

The hardware browser benchmark reached gameplay with two live guest workers throughout measurement. Lazy OFF / ON measured 29.86 / 29.79 FPS and about one readback per frame in both modes. ON leaves one armed Lock untouched per frame, but presentation still needs its readback and GPU backend fence calls increase from one to two. A later call-stack trace confirmed only one guest fence request per frame: the other backend call is inside queued-flip replay. Publication adds its own wait, measured separately. The helper recorded no lazy surface touches, so this is coexistence coverage, not a real-game test of foreign-thread pixel access. This initially remained opt-in; the subsequent shared-WebGL default rollout provides ?no-lazy-sync and the live Lazy sync debug checkbox as opt-outs. The retained-GDI-pointer limitation still applies.