Analysis model: gpt-5.5 xhigh

4K iNTRO by MLJ/Xenogenesis - Technical Dissection

Scope

4KR.EXE is the Xenogenesis/XNG 4 KB intro from The Gathering 1995. The TG95 results file lists the PC 4K third-place entry as Majakovskij/XNG, entry number 8. The TG95 in4k archive's Xenogenesis entry is 4kr.zip, and its DIZ identifies the intro as:

4K iNTRO by MLJ of Xenogenesis
    From The Gathering 1995

This analysis uses the public scene.org archive, PKLITE expansion with UNP, and static disassembly of the expanded real-mode executable. The program is a compact no-sound visual intro: it generates a Mandelbrot-like table, uses it as a texture source, then runs a tweaked-VGA heightfield/voxel-style renderer with an animated plasma height map.

Public references:

Offset notation:

This is not a source reconstruction. Names such as "height map", "texture map", and "horizon table" are inferred from memory use and renderer behavior.

Archive Identity

The archive contains the executable and DIZ:

334e5714cd509f65d85e90543c2fd583743408d06f119da93b34d9ac8b2851b7  4kr.zip
e1f8f22c96b26142ac0a4c0dc21e49f26b207f5628694a84ec6e3f28719b3792  4KR.EXE
3071fdcc0ee40773e924819714ea419cb2998133c24846043d43f3c031595cec  FILE_ID.DIZ

The packed executable is a 4089-byte MZ file, just under the 4096-byte 4K limit:

packed file size:      4,089 bytes
MZ header size:          128 bytes
packed load image:     3,961 bytes
PKLITE marker:       packed+0x001e
entry point:         CS:IP fff0:0100

UNP expands it to:

ac5165ecf6697e0f41f94cac6f4eaa05f8b0889fe0f5a50e07bc565ee3e7047e  UNP-expanded 4KR.EXE

expanded file size:    6,430 bytes
MZ header size:          512 bytes
load image size:       5,918 bytes
entry point:         CS:IP 0000:0000
entry file offset:   expanded+0x0200
relocations:               5

The expanded image still needs a large allocation. Its e_minalloc is 0x3001 paragraphs, because the intro uses several 64 KB work segments beyond the loaded code image.

The visible ending text in the expanded image is:

A contribution to the 4kB intro competition of The Gathering 1995
Coded by MLJ of Xenogenesis.

Runtime Segments

The executable stores four important segment constants at runtime+0x0f66:

runtime+0x0f66  A000h          VGA segment, not relocated
runtime+0x0f68  CS + 0172h     main work/backbuffer segment
runtime+0x0f6a  CS + 1172h     height-map segment
runtime+0x0f6c  CS + 2172h     texture/fractal segment
runtime+0x0f6e  CS + 2172h     same texture segment, later loaded into GS

The last four are MZ-relocated words. In the file they appear as 0172h, 1172h, and 2172h; DOS adds the program's load segment.

The work areas are used like this:

CS+0172h  row/column temporary data, horizon arrays, planar source buffer
CS+1172h  live height map sampled by the voxel renderer
CS+2172h  generated Mandelbrot/escape table, also used as color/texture map
A000h     VGA output

The main renderer clears CS+0172h each frame, renders into it, then copies it to VGA plane by plane.

Startup Flow

The expanded entry begins in text mode by printing the final/identity string:

expanded+0x0200 / runtime+0x0000:
  mov ax,cs
  mov ds,ax
  mov dx,16beh
  mov ah,09h
  int 21h

Then it initializes memory:

es = [cs:0f6a]       ; height map
eax = 80808080h
call clear64k

es = [cs:0f6c]       ; texture/fractal map
eax = 01010101h
call clear64k

ds = es = cs
call 0cf3h           ; build sine/cosine-like table
call 0d33h           ; build per-column offset table
call 0bb6h           ; generate Mandelbrot-like escape table

clear64k is:

runtime+0x02b9:
  xor di,di
  mov cx,4000h
  rep stosd

The program then copies every other row from the generated 256x256 fractal table into the work segment:

es = [cs:0f68]
ds = [cs:0f6c]
si = 0100h
di = 0
bp = 80h

repeat 128 times:
  cx = 40h
  rep movsd             ; 256 bytes copied
  si += 0100h           ; skip the next 256-byte row

So the first visual source is a vertically downsampled version of the generated fractal/escape map.

Generated Tables

Wave Table Builder

runtime+0x0cf3 builds a full signed wave table from a short embedded quarter wave at runtime+0x163e.

The high-level shape is:

si = 163eh
di = 0fa8h
cx = 40h
rep movsw              ; copy quarter-wave samples

store 7fffh
walk backwards and mirror
store negative mirrored samples
finish with copied tail

The table is later read at runtime+0x0fa8 and runtime+0x1028. The startup texture prelude uses it to produce changing sampling increments.

Offset Table

runtime+0x0d33 writes 128 words at runtime+0x1228:

di = 1228h
ax = 1450h
cx = 40h
repeat:
  [di++] = ax
  ax -= 50h

cx = 40h
repeat:
  [di++] = ax
  ax += 50h

This gives a down-and-up sequence of row/offset values. The prelude uses it as the BP parameter for 256 calls to the texture warp routine.

Span Jump Table

The file also contains a table of 200 runtime code addresses from roughly runtime+0x1434 through runtime+0x15c2:

062d, 0633, 0639, 063f, 0645, ...

Those point into the unrolled vertical span writer. The heightfield renderer indexes this table with a negative span height to jump directly into the correct number of store pixel; advance color instructions.

The table immediately after it, at runtime+0x15c4, begins:

0000, 0001, 0002, 0003, ...

That second table is read as distance/step data by the same renderer. The data region is intentionally overloaded.

Mandelbrot-Like Table Generator

runtime+0x0bb6 generates a 256x256 escape-style table in the segment at CS+2172h. It uses 32-bit fixed-point math in real mode.

Initial state:

es = [cs:0f6c]
[0f94] = 0
[0f8c] = fc000000h     ; y / imaginary coordinate
[0f96] = 000000ffh     ; row counter
[0f90] = 0             ; run start
[0f88] = fc000000h     ; x / real coordinate
[0f9a] = 0             ; column counter

For each pixel it performs up to 127 iterations:

esi = x
edi = y
bp  = 127

repeat:
  ebx = (esi * esi) >> 25
  ecx = (edi * edi) >> 25
  edi = ((esi * edi) >> 24) + y0
  esi = ebx - ecx + x0

  if ebx + ecx >= 08000000h:
    break
  bp--
  if bp != 0:
    repeat

value = 128 - bp

The stores are run-length compressed while generating:

if value changed:
  edi = row * 256 + run_start
  ecx = current_x - run_start
  al = old_value
  rep stosb
  old_value = value
  run_start = current_x

This is a good 4K trade: the escape algorithm produces a rich 64 KB texture from a few dozen instructions and writes long runs cheaply.

Twisted Texture Prelude

After mode 13h is set, the intro runs a 256-step prelude before the main heightfield.

Setup:

es = A000h
ds = CS+0172h          ; downsampled fractal source
[0fa6] = 0100h
cx = 0

repeat 256 times:
  di = cx
  bp = table_1228[(cx & 7fh) * 2]
  call 0d4eh
  cl++
  [0fa6]--

runtime+0x0d4e is a texture warp. It uses the wave table to derive two source-space increments and fills almost a full 320x200 mode-13h screen:

for y in 0..198:
  for group in 0..79:
    sample four bytes from DS using DH/high-byte address components
    pack them into EAX
    bswap eax
    es:[di] = eax
    di += 4

The inner loop uses only additions and byte fetches after setup. Four pixels are emitted per iteration with a 386 mov dword.

The source address pattern is intentionally odd:

bx = bp
bl = dh
bx &= 7fffh
al = [bx]
...

Only pieces of the evolving coordinate are used as the texture address. That keeps the code short and gives a rotating/twisting fractal texture rather than a strict affine mapper.

VGA Mode Setup

The intro starts from BIOS mode 13h, then turns it into a planar/tweaked 256-wide working mode:

mov ax,0013h
int 10h

; wait one retrace edge
in al,03dah ... 

; CRTC display start = 0
out 03d4h, 0c00h / 0d00h

; Sequencer memory mode: chain-4 off style setup
out 03c4h, 0604h

; CRTC offset / byte-panning-related setup
out 03d4h, 0014h
out 03d4h, e317h
out 03d4h, 0009h

; enable all planes for clears
out 03c4h, 0f02h

The later copy to A000h writes each VGA plane separately with sequencer map masks 1, 2, 4, and 8.

Main Timeline

The main loop uses runtime+0x0fa6 as a frame counter:

[0fa6] = 0
[132c] = 0             ; scene flag

frame:
  [0fa6]++

  if [132c] == 0:
    call 04b6h         ; update camera/heightfield path

  if [0fa6] == 00a0h:
    call 0e44h         ; convert Mandelbrot texture into height map

  if [0fa6] == 019ah:
    fill height map with 80808080h
    [0f70] = 0020h     ; change camera delta

  if [0fa6] == 0226h:
    [132c] = 1         ; switch to animated plasma height source

  if [132c] == 1:
    call 0e6bh         ; update animated height map

  if [0fa6] == 02b7h:
    exit_scroll

  call clear_work
  call render_heightfield
  call copy_planes_to_vga
  goto frame

So there are three broad visual states:

  1. Flat/initial height map with moving camera.
  2. A height map derived from the Mandelbrot table.
  3. A height map regenerated every frame by the plasma routine.

Camera Update

runtime+0x04b6 updates the main view parameters:

ax = 0
bx = [0f70]
[0f72] -= bx          ; horizontal/position term
[0f74] += 10h         ; vertical/depth phase
cx = [0f72]
dx = [0f74]
[0f82] = cx
[0f84] = dx
call 0b55h            ; derives another view scalar
ah += 19h
if carry:
  ax = ffffh
[0f86] = ax

[0f70] starts as zero and is later changed to 0x20, which makes the camera begin drifting. [0f82], [0f84], and [0f86] are read by the heightfield renderer as camera/phase/projection values.

Heightfield Renderer

runtime+0x04f8 is the main renderer. It renders into the CS+0172h work segment, not directly to VGA.

It first initializes two 256-entry arrays in the work segment:

fs = [cs:0f6a]        ; height map
gs = [cs:0f6e]        ; color/texture map

word horizon[256] = 7d00h
word color_cache[256] = 0000h

The horizon array lives at work offset 03aa, and the color cache at 05aa. The exaggerated initial horizon value ensures the first visible projected terrain samples produce spans.

The distance loop starts at runtime+0x0778 / table offset 0x78 and steps backwards by two:

[0f78] = 0078h
while [0f78] != 0:
  distance = word [15c4 + [0f78]]
  ...
  [0f78] -= 2

For each distance layer, it renders 256 columns. The column loop starts with:

si = 01feh            ; horizon/color-cache index, counts down by 2
[0f9e] = 07aah        ; base offset into work framebuffer

For each column, it computes a texture coordinate from the camera, distance, and fractional phase, then samples the height map with linear interpolation:

al = fs:[bx+1] - fs:[bx]
ax = al * fractional_x
ax = (ax,dx) >> 7
ah += fs:[bx]

projected_y = [0f7a] - ((height * [0f7c]) >> 16)
clamp projected_y to 0..199

The projected y is compared to the current horizon:

old_y = horizon[x]
horizon[x] = projected_y
span = old_y - projected_y

if span >= 0:
  only update color cache
else:
  draw vertical span

This is classic voxel/Comanche-style hidden-surface rendering: nearer distance layers overwrite only the parts that rise above the previous horizon for that screen column.

Color Interpolation

When a span is visible, the renderer samples GS similarly to the height map:

al = gs:[bx+1] - gs:[bx]
imul ch
shl ax,1
ah += gs:[bx]
dx = ax               ; new color endpoint

Then it exchanges the new color endpoint with the cached one:

xchg word [si+05aa],ax
ax = old_color - new_color
idiv span

The division gives a per-pixel color delta. The span writer then walks color in DX, storing DH as the byte color for each vertical pixel.

Unrolled Vertical Span Writer

The hot path does not loop once per pixel. It jumps into a block of unrolled stores:

bp = span_height
bp <<= 1
jmp word cs:[bp + 15c4h]

For visible spans, span_height is negative before the shift, so this indexes backward from runtime+0x15c4 into the table at runtime+0x1434. That table contains addresses into the unrolled writer starting around runtime+0x062d.

Each unrolled pixel step is six bytes:

mov [di + y*256], dh
add dx, ax

The disassembly appears as:

runtime+0x062d:
  mov [di+3900h],dh
  add dx,ax
  mov [di+3a00h],dh
  add dx,ax
  mov [di+3b00h],dh
  add dx,ax
  ...

Because the working screen is 256 bytes wide, adding 0x0100 to the address moves exactly one scanline down. Starting at the correct jump-table entry makes the code draw the exact span height without a branch inside the pixel writer.

After the unrolled block falls through, it advances to the next column:

inc word [0f9e]       ; next screen x base
si -= 2               ; previous horizon/color entry
if si >= 0:
  continue column loop
else:
  next distance layer

This is the most important inner loop in the intro.

Height-Map Conversion

At frame 0x00a0, runtime+0x0e44 converts the generated Mandelbrot table into the live height map:

es = [cs:0f6a]        ; destination height map
ds = [cs:0f6c]        ; source fractal map
si = 0
ecx = 10000h

for each byte:
  al = [si]
  if al == 80h:
    al = 40h
  else:
    al &= 1fh
  es:[si] = al
  si++

That compresses the rich escape table into low terrain heights, with the special 0x80 value mapped to a higher plateau.

Animated Plasma Height Map

At frame 0x0226, scene flag [132c] becomes 1 and runtime+0x0e6b starts regenerating the height map every frame.

The routine writes 1024 groups of 256 bytes into the height-map segment:

es = [cs:0f6a]
si = 142eh
di = 0
outer = 0400h

for outer rows:
  bp = 0100h
  dl,dh,cl,ch = moving phase bytes
  bx = [1432]

  for 256 bytes:
    ax = bx + bp
    al += cs:[si + dl]
    al += cs:[si + dh]
    al += cs:[si + cl]
    al += cs:[si + ch]
    ax >>= 1
    es:[di++] = al
    dl += 1
    dh += 3

The table at runtime+0x142e is another overloaded data area. It includes bytes from the jump-address table, which are perfectly usable as a compact quasi-random waveform source.

After filling the map, it updates the phase velocities at 1328..132b and the phase bytes at 142e..1431:

[1432]--
bl ^= bh
bl ^= last_output_byte
bl ^= cl
bl ^= dl

derive two small velocity pairs
sometimes increment/decrement one component

[142e] += [1329]
[142f] -= [1328]
[1430] += [132a]
[1431] -= [132b]

This gives a moving synthetic height map without storing any frame data.

Planar Copy To VGA

The renderer's work buffer is 256 bytes wide, but VGA output is planar. The copy routine writes one plane at a time by changing the Sequencer map mask:

source si = 07aah
dest di   = 1f48h
rows      = 200

for each row:
  plane 0: map mask 01h, copy bytes [si+0] and [si+4] pairs
  plane 1: map mask 02h, copy bytes [si+1] and [si+5] pairs
  plane 2: map mask 04h, copy bytes [si+2] and [si+6] pairs
  plane 3: map mask 08h, copy bytes [si+3] and [si+7] pairs

  di += 50h
  si += 0100h

Each plane copy emits 32 words per row:

cx = 20h
repeat:
  al = [si + plane]
  ah = [si + plane + 4]
  es:[di] = ax
  di += 2
  si += 8

That deinterleaves the 256-byte chunky work row into four VGA planes. The visual output is 256 pixels wide in the tweaked mode, centered/positioned by the chosen CRTC setup.

Exit Scroll

At frame 0x02b7, the program leaves the main loop and scrolls the display start through video memory:

bx = 0
repeat:
  write CRTC start address high/low from BX
  wait retrace
  bx += 50h
until bx == 7d00h

mode 3
int 21h AH=4Ch

The repeated CRTC start-address writes produce a hardware scroll/fade-out style ending before returning to text mode.

What Each Part Does

The intro's strength is that its assets are mostly algorithms: one escape-time table, one overloaded waveform/jump-table area, a heightfield renderer, and a few timeline switches. That is enough to create several distinct visual states inside a 4089-byte packed executable.

Confidence Notes

High-confidence findings:

Lower-confidence or caveated findings: