Analysis model: gpt-5.5 xhigh
Big Deal by Acme - Technical Dissection
Big Deal is a 1995 MS-DOS/GUS demo by Acme, shown at X 1995 in Utrecht,
Holland. It won the X 1995 PC Demo competition.
Release year: 1995
Released: 22 April 1995 is the Demozoo release date. Pouet gives April 1995. The distributed executable and its internal player build date also point at the same spring 1995 release window.
Sources
- Scene.org X 1995 demo directory: https://files.scene.org/browse/parties/1995/x95/demo/
- Scene.org
acme_big.ziprelease archive: https://archive.scene.org/pub/parties/1995/x95/demo/acme_big.zip - Scene.org
bigdeal.zipmirror archive: https://archive.scene.org/pub/parties/1995/x95/demo/bigdeal.zip - Scene.org X 1995 results: https://archive.scene.org/pub/parties/1995/x95/info/x95res.txt
- Demozoo production: https://demozoo.org/productions/5199/
- Demozoo screenshot set: https://demozoo.org/productions/5199/screenshots/
- Pouet production: https://www.pouet.net/prod.php?which=1119
Old personal contact and distribution listings from the bundled text files are deliberately omitted.
Public Screenshot Reference
The direct DOSBox-X/ZMBV runtime attempt was kept private and did not produce usable effect frames: the emulator aborted at the first graphics-mode capture switch after the initial shell/text transition. The public images below are therefore Demozoo screenshot references, not local runtime captures. They are still useful because they line up with the static renderer analysis later in this page: car/object scenes, face/object rendering, true-motion-blur scenes, and the lamp/face object sequence.
No new H.264/MP4 media is published for this pass.






Competition Identity
The X 1995 result file lists the PC Demo top three as:
1. Big Deal Acme 748
2. Expression Abstract Concepts 722
3. Uitgeroeid Ground Zero 610
Demozoo credits:
Code: Lone Ranger, SimStim
Graphics: Aap, Ricochet
Music: Vic
That split matches the binary. The wrapper and player identify Lone Ranger's code, while most visual child programs carry SimStim strings and protected-mode object-scene code.
Archive Identity
Two Scene.org archives carry the same executable:
d36b764e551e3dba11c9919d82cbdeca51dfcd6066777e584897d74c748c4bc1 acme_big.zip
39c3fda4dd79b7d8c325761b56925f70d8a5b60f279adb0bb45aed96b8556882 bigdeal.zip
acme_big.zip contains:
DISCLAIM.ER 816 bytes
ACME-BIG.EXE 927085 bytes
WORLDTOU.R95 613 bytes
ACME-BIG.NFO 2419 bytes
FILE_ID.DIZ 598 bytes
bigdeal.zip contains the same production files except for DISCLAIM.ER.
The main executable hash is:
90c0710707adcfd0566b85b6858f38021616c5b4f167aa49824217df00e6886b ACME-BIG.EXE
The executable is not one single flat demo body. It is a small DOS MZ loader with an appended virtual file system. That virtual file system contains a launcher, six packed effect executables, and the sample bank.
Outer MZ And VFS Layout
The outer ACME-BIG.EXE starts as a tiny MZ image:
MZ image size: 0x7f7 bytes
header bytes: 0x020 bytes
load bytes: 0x7d7 bytes
entry body: small real-mode VFS loader
overlay start: file offset 0x7f7
The loader strings identify the container code:
VFS - Virtual File System v1.0
Copyright (c) 1994 by Lone Ranger/AcmE
The VFS header begins at file offset 0x7f7:
95 24 0e 00 d8 00 08 00 00 00 56 46 53
Interpreted by the loader:
directory offset: 0x000e2495
directory size: 0x00d8 bytes
record count: 8
autostart index: 0
signature: VFS
The directory has eight records of 27 bytes. The records are lightly obscured:
for each 27-byte record:
for i = 0..13:
record[i] ^= 0x56;
for i = 14..26:
record[i] ^= 0x9d;
After decoding, the fields line up as:
byte 0 flags
bytes 1..3 24-bit payload offset
byte 5 DOS-like attribute byte, usually 0x20
bytes 6..9 payload length
bytes 14..26 internal filename
The decoded virtual files are:
0 DEMO.EXE offset 0x000804 size 0x0042fb
1 VETTE.EXE offset 0x004aff size 0x00b33a
2 GOUTEX.EXE offset 0x00fe39 size 0x00af6a
3 PHONG.EXE offset 0x01ada3 size 0x00e43d
4 BETHOOF.EXE offset 0x0291e0 size 0x00a948
5 MOTION.EXE offset 0x033b28 size 0x003e04
6 LUXO.EXE offset 0x03792c size 0x0229b8
7 GHERKIN2.SMP offset 0x05a2e4 size 0x0881b1
The loader installs an INT 21h filter so those virtual files behave like normal
DOS files. That is why DEMO.EXE can open GHERKIN2.SMP and execute the child
programs by name even though none of them exist as separate files on disk.
The VFS handle trick is simple:
open(name):
if name matches a VFS directory entry:
slot = allocate_vfs_handle();
slot.file = matching_record;
slot.cursor = 0;
return 0x8000 | slot_index;
else:
pass to old INT 21h;
read(handle, count, buffer):
if handle has bit 15 set:
slot = handle & 0x7fff;
physical = slot.file.payload_offset + slot.cursor;
seek host executable to physical;
bytes = min(count, slot.file.size - slot.cursor);
read bytes into buffer;
slot.cursor += bytes;
return bytes;
else:
pass to old INT 21h;
lseek(handle, origin, delta):
if handle has bit 15 set:
origin 0: cursor = delta;
origin 1: cursor += delta;
origin 2: cursor = file.size + delta;
clamp or return DOS-style error on invalid range;
else:
pass to old INT 21h;
close(handle):
if handle has bit 15 set:
free slot;
else:
pass to old INT 21h;
So the wrapper is not merely a compressor. It is a self-contained file server for a multi-program show.
Carved Virtual Files
The carved payload hashes:
949f71097b842bf1babaa8a4dedd797f254029e7dc687ade8e6f64966ea9bfbe DEMO.EXE
fb44069cb6e3c2b01a64fe23462284f13f3af70158c32daf0ff5b6c57fca01eb VETTE.EXE
35e0e30e41a93668825a8eef9cec7d29be739b80e9bb4bedd604b72b8ff6ede9 GOUTEX.EXE
7f539856ca3a635d09872727852f9e11848e01ad8befbf5d7b253078b551716f PHONG.EXE
734e74734ce038d1410c8df485094c9eae63f2ffd2a78be048215e0105dbdd90 BETHOOF.EXE
a9633fd406e0fbeb8643334458ac67c953e28a2def25541fedc78e64cbd01c9a MOTION.EXE
41f1279d8b92a274ca7f63bafe9cd699eb0a7daffc9f19cd526d74161d832511 LUXO.EXE
f67a42c7ad2617977f92c24caf3b31d5001f316839f2767e91593168774cabe6 GHERKIN2.SMP
The seven EXE payloads are PKLITE packed. After UNP expansion:
DEMO.EXE 53072 bytes
VETTE.EXE 339951 bytes
GOUTEX.EXE 364037 bytes
PHONG.EXE 355573 bytes
BETHOOF.EXE 343295 bytes
MOTION.EXE 156854 bytes
LUXO.EXE 459668 bytes
The expanded child programs are much larger than their VFS form. Big Deal
therefore combines two layers of packing:
outer ACME-BIG.EXE
VFS wrapper
PKLITE child EXE
real-mode or protected-mode demo code
Launcher: DEMO.EXE
DEMO.EXE is the show conductor. Its data block begins with the VFS filenames:
GHERKIN2.SMP
VETTE.EXE
GOUTEX.EXE
MOTION.EXE
PHONG.EXE
LUXO.EXE
BETHOOF.EXE
The visible player strings are:
PolyPlayer v2.0
(c) Copyright 1993, 1994 by Lone Ranger/AcmE
Compiled on 23/04/95 at 10:16:36 using TASM 3.2
Gravis Ultrasound driver (c) Copyright 1993-95 by Lone Ranger/AcmE
ULTRASND=
EMMXXXX0
Gherkin demo versie
The entry at load offset 0x80 does this:
; shrink DOS memory block
mov ah,4ah
int 21h
; hardware gate
call 0x13a ; VGA check and 386 check
; open sample bank through the VFS INT 21h hook
mov dx,GHERKIN2_SMP
mov ax,3d00h
int 21h
; player/sample setup calls
mov bx,1
call 0x3542
mov bx,2
call 0x3542
mov bx,0dh
call 0x3542
mov bx,4
call 0x3542
mov bx,0ah
call 0x3542
; keep keyboard IRQ masked while child parts own the machine
in al,21h
or al,02h
out 21h,al
; run the visual parts
mov ax,4b00h
mov dx,VETTE_EXE
int 21h
mov ax,4b00h
mov dx,GOUTEX_EXE
int 21h
mov ax,4b00h
mov dx,MOTION_EXE
int 21h
mov ax,4b00h
mov dx,PHONG_EXE
int 21h
mov ax,4b00h
mov dx,LUXO_EXE
int 21h
mov ax,4b00h
mov dx,BETHOOF_EXE
int 21h
; stop player, close sample bank, return to DOS
Offset 0x13a uses int 10h AX=1A00h for the VGA display-combination check.
The 386 test uses the classic FLAGS-bit method: attempt to toggle a CPU flag
that exists only on 386-class machines, then compare the result.
The show timing API used by the child parts is coupled to the player. Visual
parts call int 33h with AL=0xAC, then compare the word cached around
ds:0xdc. In the effect binaries this behaves as a music/tick query rather
than as ordinary mouse logic.
Sample Bank
GHERKIN2.SMP is the shared sound payload. Strings in the bank include:
TUBSAX.PTS TUBSAX.RAW
TBGUIT1.PTS TBGUIT1.RAW
TBGUIT2.PTS TBGUIT2.RAW
CYMCRSH1.PTS CYMCRSH1.RAW
ISBEAT2.PTS ISBEAT2.PCM
ISBEAT3.PTS ISBEAT3.PCM
ISBEAT4.PTS ISBEAT4.PCM
LIZBASS.PTS
Lead Guitar
Heavy Guitar
FCPIANO1.PTS FCPIANO1.SMP
LIZLEAD3.PTS LizLead 3
SYNSTR.PTS SynthString Minor
The important implementation point is that the music is not bundled into each visual EXE. The launcher opens one sample bank and keeps the player alive while the VFS-loaded child EXEs take over video.
Shared Protected-Mode Runtime
VETTE.EXE, GOUTEX.EXE, PHONG.EXE, BETHOOF.EXE, MOTION.EXE, and
LUXO.EXE share a real-mode startup and a protected-mode bridge. Strings in
the parts include:
386 or better not detected!!!
Not enough low memory!!!
System is already in V86 mode, and no VCPI or DPMI found!!!
Not enough extended memory!!!
Couldn't enable A20 gate!!!
DPMI host is not 32bit!!!
Incompatible VCPI PIC mappings!!!
The VCPI path contains the expected switch sequence:
int 67h AX=DE0Ch ; VCPI service
lgdt [gdt_ptr]
lidt [idt_ptr]
mov eax,cr0
or al,1
mov cr0,eax
jmp 20h:0000021e ; enter 32-bit code selector
After the shared runtime, each expanded binary reaches a part-specific 32-bit
entry through the dispatcher around load offset 0x1100:
LUXO.EXE part entry 0x01c46
GOUTEX.EXE part entry 0x03dfc
MOTION.EXE part entry 0x06113
BETHOOF.EXE part entry 0x0daa4
VETTE.EXE part entry 0x10964
PHONG.EXE part entry 0x150f4
The shared exit target is 0x1266.
Shared VGA Idioms
The parts draw mostly through 64,000-byte chunky pages:
mov esi,source_page
mov edi,destination_page
mov ecx,3e80h ; 16000 dwords = 64000 bytes
rep movsd
That is a complete 320x200 8-bit page. Some destinations are work pages such as
0x21830, 0x3f1a0, or allocation-returned pointers; some are the linearized
VGA page:
mov edi,0a0000h
sub edi,[runtime_linear_bias]
mov ecx,3e80h
rep movsd
The repeated full-page clear uses the same scale:
mov eax,0fefefefeh
mov ecx,3e80h
rep stosd
That fill value is not black. It is a bright sentinel or background level used by later object/pixel stages.
Shared Palette Fade Kernel
Several child parts have near-identical palette interpolation code. One full
copy appears in LUXO.EXE at 0x391c and 0x3952.
Fade setup:
; ESI = old palette bytes
; EDI = target palette bytes
; ECX = byte count
; EBX = delta table
loop:
mov al,[edi]
sub al,[esi]
cbw
shl ax,2
mov [ebx],ax ; signed per-step delta
inc edi
inc esi
add ebx,2
loop loop
; copy old palette into 8.8 fixed-point accumulators
loop:
lodsb
shl ax,8
stosw
loop loop
Per-frame update and DAC write:
push ecx
mov esi,delta_table
mov edi,accumulator_table
mov ecx,palette_byte_count
step_loop:
lodsw
add ax,[edi]
stosw
loop step_loop
mov dx,03c8h
mov al,start_index
out dx,al
inc dx
mov esi,accumulator_table
mov ecx,palette_byte_count
dac_loop:
lodsw
mov al,ah ; high byte of 8.8 accumulator
out dx,al
loop dac_loop
pop ecx
ret
Most parts wrap that per-frame call in a 64-step vertical blank loop:
mov ecx,40h
mov dx,03dah
frame:
wait_not_vblank:
in al,dx
test al,8
jne wait_not_vblank
wait_vblank:
in al,dx
test al,8
je wait_vblank
call palette_step
loop frame
This is why fades look smooth but are still deterministic: 64 retrace-synced steps, with byte palettes expanded through 8.8 fixed accumulators.
MOTION.EXE has a small ordering variation at 0x2640c: it writes the current
accumulators to the DAC first, then applies the next delta. The other sampled
copies add first and write after.
MOTION.EXE: Still Page, PIT Rate, Fades
MOTION.EXE is the smallest visual part and the cleanest inner-loop specimen.
The part entry at 0x6113 begins:
sti
in al,21h
or al,02h
out 21h,al
; runtime allocation / setup callbacks
call dword [0x24]
mov [0x528f],edx
call dword [0x28]
Then it reprograms PIT channel 0:
cli
mov al,36h
out 43h,al
mov al,95h
out 40h,al
mov al,42h
out 40h,al
sti
The divisor is 0x4295 or 17045 decimal. With the normal PIT base of about
1.19318 MHz, that is roughly 70 Hz. This is a good fit for a short part that
needs finer cues than a 50 Hz PAL-style frame clock.
The first visible operation is a raw DAC upload from 0x900:
mov dx,03c8h
xor al,al
out dx,al
inc dx
mov cx,0300h
mov esi,0900h
rep outs dx,byte ptr [esi]
Then it copies one full screen:
mov esi,53b0h
mov edi,0a0000h
sub edi,[0x18]
mov cx,3e80h
rep movsd
The part waits for music time:
wait:
mov al,0ach
int 33h
mov ax,[0dch]
cmp ah,08h
jb wait
ja after
cmp al,00h
jb wait
after:
After that, the part uses the shared fade kernel:
mov esi,0900h
mov edi,0f00h
call 263d6h ; build delta and accumulator tables
mov ecx,40h
vblank_64:
wait vertical blank on port 03dah
call 2640ch ; write DAC, then add one step
loop vblank_64
The rest of MOTION.EXE alternates palette helper calls and music-time waits:
0x25630 called twice after the first fade
0x256cc called with ESI=0x0f00, EDI=0x0c00
0x2571f called after tick 08:20
0x25630 called after a retrace wait
0x25772 called after tick 09:30
Finally it restores PIT channel 0 to divisor zero and jumps to the shared exit:
cli
mov al,36h
out 43h,al
xor al,al
out 40h,al
out 40h,al
sti
jmp 1266h
So this part is not a geometry section. It is a timing-sensitive still or motion-card section built from direct palette writes, one full-page blit, and player-cued fades.
GOUTEX.EXE: Object Setup, Page Clears, Render Calls
GOUTEX.EXE enters its part body at 0x3dfc. The name suggests a
Gouraud/texture object part, but the safer statement from the code is that it
is an object-render section with full-page buffers and several camera-state
calls.
The initial path sets up FS from a runtime-returned segment, prepares assets,
and uploads a palette from 0x900:
mov dx,03c8h
xor al,al
out dx,al
inc dx
mov cx,0300h
mov esi,0900h
rep outs dx,byte ptr [esi]
The first screen copy is another 64,000-byte page:
mov edi,[0x52a60]
mov esi,4ae9h
mov ecx,3e80h
rep movsd
The fade setup and step helpers are at 0x58f9 and 0x592f. They are the same
signed-delta / 8.8-accumulator kernel described above, using these tables:
delta table: 0x3274
accumulator table: 0x3e74
byte count: [0x4a75]
start DAC index: [0x4a74]
The part then clears two full pages to 0xfefefefe:
mov edi,[0x52a60]
mov eax,0fefefefeh
mov ecx,3e80h
rep stosd
mov edi,43050h
mov eax,0fefefefeh
mov ecx,3e80h
rep stosd
The render dispatches use fixed-point-looking camera values. Examples:
call 0x15fe8 with EAX=0x00000000 EBX=0x00000000 ECX=0xfffcf2c0 EDX=0x78
call 0x16060 with EAX=0x00000000 EBX=0x00000000 ECX=0xffff3cb0 EDX=0x78
call 0x16060 with EAX=0xffedb080 ... EDX=0x78
call 0x16060 with EAX=0x000493e0 ECX=0x002c4020 ... EDX=0x78
The page-clears and camera calls make the structure look like:
upload_palette();
copy_intro_page();
fade_between_palettes();
clear_page(work_a, 0xfe);
clear_page(work_b, 0xfe);
render_object_state(camera_0);
render_object_state(camera_1);
render_object_state(camera_2);
render_object_state(camera_3);
fade_out_or_bridge();
The heavy object raster code sits below those dispatches. This pass identifies the orchestration and the reusable loops rather than naming every generated surface span inside the renderer.
LUXO.EXE: Lamp/Object Scene
LUXO.EXE is the largest expanded visual part. The name and visible reputation
point to the lamp/object section. The part entry is 0x1c46.
It allocates and fills full pages:
; request 0xfa00 bytes through shared allocator
call 1134h
mov [0x199d0],eax
mov edi,eax
mov esi,9fd0h
mov ecx,3e80h
rep movsd
mov edi,[0x199dc]
mov esi,9fd0h
mov ecx,3e80h
rep movsd
It initializes several object-state bytes:
[0x3720] = 0
[0x0ac0] = 0
[0x0ac1] = 0
[0x375e] = 1
The high-level frame loop around 0x1ce2 repeatedly calls:
0x1e4b object setup or per-frame object state update
0x1e05 render / page stage
0x1d895 timing or input helper
A more detailed object update path at 0x1d15 walks tables and object pointers
such as:
0x59a84
0x6c700
0x6f274
0x2f46c
0x545e8
0x4eafc
It also uses small state variables around:
0x0f7f scroll or phase value
0x0f7b direction or signed step
Camera/object setup at 0x1e69 writes fixed-point-looking constants into
scene structures:
0x0006ddd0
0x00002710
0xfffb6c20
Those are too large and too signed to be byte graphics constants; they are position/angle/scale state for the object engine.
The part uses the same palette fade pair at 0x391c and 0x3952. The code is
important because it proves the visual polish is not just page flipping: the
part computes per-byte palette deltas and performs 64 retrace-synced DAC
updates during scene bridges.
VETTE.EXE: Beethoven Section
VETTE.EXE has a visible internal string:
SimStim / A(c)Me presented mr. TA DA DA DAAAAA (aka Beethoven)
The part entry is 0x10964. It starts by blanking the full DAC:
mov dx,03c8h
xor al,al
out dx,al
inc dx
mov ecx,0300h
clear:
out dx,al
loop clear
Then it performs full-page copies:
mov esi,2f7a0h
mov edi,3f1a0h
mov ecx,3e80h
rep movsd
mov esi,3f1a0h
mov edi,[0x4eba8]
mov ecx,3e80h
rep movsd
It patches repeated palette triples to a dark blue-grey target:
R = 0x0c
G = 0x17
B = 0x1c
The local 64-step fade wrapper is at 0x10d95. It calls:
0x125ba build fade deltas and accumulators
0x125f0 add one step and write DAC
The sequence body around 0x10ae7 mixes render calls and page copies. A typical
render call passes camera-like state to 0x1f2e1:
EAX = 0xfffea070
ECX = 0x00015f90
Then it waits for a frame count such as 0x168, copies image chunks from
0x120ad, 0x16075, and 0x1a03c, and writes those chunks to three
destinations:
live page: [0x4eba8]
work page: 0x2f7a0
work page: 0x3f1a0
copy size: 0x0ff0 dwords, about 0x3fc0 bytes
The object orientation is flipped by negating a word inside two object records:
; paraphrased from the object-list walk
obj = [some_object_pointer]
neg word [obj + 0x18 + 8]
...
neg word [other_obj + 0x18 + 8]
So the part is not only a still-image display. It performs page staging, paletted bridge fades, render calls, and object mirroring inside a themed Beethoven sequence.
PHONG.EXE: Phong Motor Section
PHONG.EXE identifies itself directly:
3D Phucking Phong (YEAH!) Motor (PM Versie) 1.0
(c) 1994/1995, SimStim / A(c)Me
Kan dit object in de demo ?
PhongPic
The part entry is 0x150f4. It starts by copying two full pages:
mov eax,[0x50c40]
sub eax,[0x18]
mov esi,eax
mov edi,21830h
mov ecx,3e80h
rep movsd
mov esi,21830h
mov edi,41230h
mov ecx,3e80h
rep movsd
Then it installs a scene callback:
[0x55c5a] = 0x1565f
The setup path calls:
0x56ae2
0x22530
0x1648d
At 0x1521d, the part waits for the player clock, loads object or picture
data, and uploads 0x249 palette bytes from 0x148b7. The palette helper pair
at 0x15084 and 0x150ba is another copy of the shared fade kernel:
delta table: 0x129ff
accumulator table: 0x135ff
byte count: [0x14200]
start DAC index: [0x141ff]
The render path uses page pointer 0x3f7a0 and camera state including
0xfff92230. It calls 0x16840, then waits through frame counts such as
0x258 and 0x0f0. Later it loads more data from 0x122d2 and 0x0a9d8,
waits for an object condition, subtracts 0x96 from an object field, restores
the DAC from palette 0x145b5, and waits for 0x618 frames before exit.
The useful low-level read is:
copy_saved_page_to_work();
copy_work_to_second_page();
install_scene_callback(0x1565f);
prepare_object_data();
wait_for_music_tick();
upload_partial_palette(0x148b7, 0x249);
render_phong_scene(page=0x3f7a0, camera=0xfff92230);
run_timed_scene_blocks(0x258, 0x0f0, ...);
restore_palette(0x145b5);
wait(0x618);
The big renderer behind 0x16840 is the expensive part, but the surrounding
code makes the section identity clear: it is a protected-mode object renderer
with palette-timed bridges and a specific Phong engine string.
BETHOOF.EXE: Final Beethoven/Object Card
BETHOOF.EXE enters at 0x0daa4. The name is another Beethoven pun and it
shares visual infrastructure with VETTE.EXE.
Its first full-page copy:
mov edi,3feb0h
mov esi,304b0h
mov ecx,3e80h
rep movsd
It calls major render/setup helpers:
0x5387e
0x311b4
0x1fef1
Then it touches the PIT:
mov al,34h
out 43h,al
xor al,al
out 40h,al
out 40h,al
The path at 0xdb98 initializes camera/scene data and uploads a palette from
0xe704. A render/timing call follows:
call 0x1ffe1 with EAX=0x11170 EBX=0 ECX=0 EDX=0x1a4
frame loop at 0xdb2e for 0x1a4 frames
The fade routine at 0xdc68 is the same 64-retrace wrapper:
call 0xf514 ; build fade deltas and accumulators
mov ecx,40h
wait retrace on 03dah
call 0xf54a ; one palette step
loop
At 0xdc88, the part builds a 255-entry palette target with the repeated
triple (0x0c, 0x17, 0x1c), fades into it, copies a complete page from
0xf309 to [0x4f8b8], waits until player tick 0x16:0x38, and fades back.
That makes BETHOOF.EXE a final staged object/card section:
copy_page();
prepare_scene();
upload_palette();
render_for_0x1a4_frames();
build_dark_target_palette();
fade_64_steps();
copy_final_page();
wait_for_music_tick(0x16, 0x38);
fade_64_steps();
Part Order As Seen By The Viewer
The true order is the launcher order, not the physical order in the VFS:
1. DEMO.EXE setup, VFS-visible player, GUS sample bank
2. VETTE.EXE Beethoven themed object/page section
3. GOUTEX.EXE object render section with full-page clears
4. MOTION.EXE still/page section with PIT timing and palette bridges
5. PHONG.EXE identified Phong object engine section
6. LUXO.EXE lamp/object scene
7. BETHOOF.EXE final Beethoven/object card section
GHERKIN2.SMP is kept open as the sound payload for that chain.
Why The Demo Is Structured This Way
The VFS wrapper solves three practical 1995 problems at once:
- the release is one executable for the user;
- the developers can still build independent child EXEs;
- the player and sample bank can remain common while each visual part owns the machine for its own protected-mode scene.
The children do not share one universal effect engine. They share the runtime, timing calls, page conventions, and palette kernels, then run their own large object/render blocks.
That explains the fancy feel. It is not a tiny demo chaining five variations of the same loop. It is closer to a mini show system:
VFS loader
-> player/sample bank
-> protected-mode object part
-> protected-mode object part
-> timed still/palette part
-> protected-mode Phong part
-> protected-mode lamp part
-> final protected-mode object/card part
The common low-level language is still very DOS-demo-like: PIT writes, PIC mask
writes, direct DAC ports, 3DAh retrace waits, 64,000-byte page moves, and
fixed-point palette fades. The unusual part is the packaging and sequencing.
Acme used normal DOS file semantics inside a one-file VFS shell, then let each
effect section be a separate executable with its own packed data and protected
mode body.
Limits Of This Pass
This is a static binary pass over the distributed executable, the carved VFS
payloads, and UNP-expanded child EXEs. It identifies the loader, part order,
shared loops, and major scene scaffolding. It does not claim a full line-by-line
reconstruction of every object renderer under GOUTEX, LUXO, PHONG,
VETTE, or BETHOOF.
Where labels such as "lamp section" or "Gouraud/texture object part" are used, they are based on internal filenames, strings, visible production identity, and surrounding render setup. The exact pixel algorithm inside each large renderer would need a separate renderer-specific pass.