Analysis model: gpt-5.5 xhigh
Disorder by Halcyon - Technical Dissection
Disorder is Halcyon's four-minute MS-DOS demo from Juhla 1995. The archive
looks modest: one 56,812-byte executable, one Scream Tracker module and two
short text files. Restoring the COMPACK carrier exposes a much larger program:
119,232 bytes of load image, 1,111 relocations, an early sequence of segmented
16-bit renderers, and a second scene controller reached through a far call for
the final hundred seconds.
That late controller is important. Stopping at the first code segment makes the demo appear to finish at its 500-point effect while the actual show continues through bars, grids, rings and closing graphics. The analysis below follows both controllers, the tracker order and row fields, and the inner loops that produce the pictures.
Release year: 1995
Identity And Original Evidence
| Item | Recovered fact |
|---|---|
| Production | Disorder by Halcyon |
| Release | 14 January 1995; third in the Juhla 1995 PC demo competition |
| Code | Blitz |
| Music | Croaker |
| Graphics | Placidity |
| Party archive | h_disord.zip, 265,594 bytes |
| Party archive SHA-256 | 42d0b798bcfa5723fcbef9087c7d90dcb62ce15dc0dba96c2b7e966a43d1a0fa |
DISORDER.EXE |
56,812 bytes; SHA-256 932fcf26e92b8a8629aab706fbe14a8e31dcf4ca4daf67dac5ca4620f6070e0d |
_HALCYON.JOO |
277,042 bytes; SHA-256 e884f51bf54e25bf9ca3e1ecdd958d679924289bc2794d0f0aabd53161da41d4 |
The date, platform, credits and placing agree across the
Demozoo production record, the
Pouet record and the
original Scene.org party archive.
The archive's DIZ says gus & nosound. HALCYON!.NFO identifies Blitz as the
coder, Croaker as a musician and Placidity as the graphician, and dates
H!DISORD.ZIP to 14 January 1995.
A later copy in Halcyon's Scene.org group directory has a different ZIP hash
because it adds TRIP1601.COM and a Scene.org marker. Its four production
files are byte-identical to the party archive. The smaller party ZIP is used as
the primary object here.
COMPACK Restoration And The Real Program Boundary
The distributed entry contains W. Collis's COMPACK signature. UNP 4.12,
running inside DOS, identifies COMPACK V4.5 and restores the executable from
56,812 to 123,712 bytes. The restored SHA-256 is:
4531efbbb49ca31d116f4a7a0e6e619a1dbef48a5f02279f9e628ceb5e4f71cd
Its MZ header is unusually relocation-heavy:
| Header field | Value |
|---|---|
| Header size | 4,480 bytes (0118h paragraphs) |
| Load image | 119,232 bytes |
| Relocations | 1,111 (0457h) |
Initial SS:SP |
2A64:4000 |
Initial CS:IP |
0000:A429 |
| Physical file entry | B5A9h |
| Load-image SHA-256 | 09bc41a077c3ab9941d29f19eca330754f9799a0e45ea8349e423a3efad6f80b |
The relocation targets range from load-image offset 0015h to 1CDF8h.
That spread matters: the executable is not one tiny routine followed by opaque
data. It is a segmented Borland-era program with demo code and several runtime
libraries distributed throughout the full image. The code is predominantly
16-bit real mode, with selected 386 instructions and 32-bit arithmetic where
the compiler or renderer benefits from them.
The program contains both No Sound Sound Device v1.10 and the literal module
name _halcyon.joo. A complete DOSBox-X run of the original four-file party
archive, with the no-sound path selected and host audio disabled, reaches the
ending and returns normally after about 4:17. No audio was played or captured.
The S3M Is The Show Clock
_HALCYON.JOO is a Scream Tracker III module titled Se vilkuilee mua....
Its header declares 36 order slots, 28 instruments and 99 pattern slots, with
initial speed 6 and tempo 128. Only patterns 0 through 21 are used:
15 00 01 02 03 04 04 05 05 05 06 07 08 09 09 0A 0B 0A
0B 0C 0D 0E 0E 0E 0E 0F 0F 10 11 11 11 12 13 14 FF FF
The field read at player-object offset +08h is the current order-list
position, not the pattern number. The proof is in the ending: the controller
waits for 21h, or order position 33, while the highest used pattern number is
21 decimal. Offset +0Ch is the row. Confusing those two identities breaks the
timeline wherever patterns 4, 5, 9, 11, 14, 15 and 17 repeat.
The module contains almost no timing tricks. Every normal order lasts 7.5 seconds. In order 32, rows 45 through 63 step tempo from 124 down to 106; a structural S3M simulation gives 256.814 seconds, while libopenmpt reports 256.681 seconds. The preservation run is 257.040 seconds. Agreement within a fraction of a second ties the code comparisons to the visible cuts.
Two Controllers, One Complete Schedule
Addresses through A429h below are offsets in the restored load image's first
code segment. The later physical offsets are shown separately because they are
reached through a relocated far pointer.
| Order boundary | Approx. song time | Code path and established job |
|---|---|---|
| 2 | 15.000 s | 0E96h opening 3D/line scene returns |
| 3 | 22.500 s | 296Eh five-panel preparation, then common renderer with target 3 |
| 3 to 5 | 22.500-37.500 s | 3204h two-phase woven line field |
| 5 to 7 | 37.500-52.500 s | 395Eh nested line tunnel |
| 7 to 8, row 52 | 52.500-66.094 s | 4EA8h projected object/scanline scene |
| 8, row 52 to 9, row 44 | 66.094-72.656 s | 5DF6h short cube construction |
| 9 to 11 | 67.500-82.500 s | 6D8Ah multi-object raster scene; its opening condition is already true when entered |
| 11 to 13 | 82.500-97.500 s | 7C7Fh larger mesh scene |
| 13, row 56 | 104.063 s | 8683h returns after its row-timed mesh pass |
| 15 | 112.500 s | 915Dh fifteen-record object engine returns |
| 16, row 32 onward | 123.750 s onward | 99DBh 1,024-phase procedural field changes state |
| 18, row 52 to 19 | 141.094-142.500 s | 9E27h stops spawning and drains its 500-point system |
| 19 through 21 | 142.500-157.500 s | late-controller setup, two additional renderers and palette transitions |
| 21 to 23 | 157.500-172.500 s | physical 13E25h renderer |
| 23 to 25 | 172.500-187.500 s | physical 165BCh scanline field |
| 25 to 28 | 187.500-210.000 s | physical 15368h plus 15CCBh object/grid pair |
| 28 to 33 | 210.000-247.757 s | physical 16FBCh radial/ring engine |
| 33, row 52 | about 255.1 s | final wait, shutdown and normal DOS return |
The first controller calls the late one at far address 13C1:4713, physical
load-image offset 18323h, passing the player and framebuffer objects. That
routine allocates 768 local bytes, creates another 4,097-byte random table,
loads palettes into the work pages, and dispatches the renderers at physical
offsets 13E25h, 165BCh, 15368h, 15CCBh and 16FBCh. It returns only
after the long order-28-to-33 effect. This far call is the missing half of any
analysis that sees the early AFA7h file-offset routine and declares the show
finished.
Five 106x66 Tiles Feed The Twister
At load offset 296Eh, the program allocates five blocks of 2100h bytes --
8,448 bytes each -- and clears every byte. It then copies five 106x66 windows
from a 320-wide source into 128-byte-stride destinations. The source windows
form a cross around the central region: left, middle, right, above and below.
The unused destination padding is deliberate; the renderer wants power-of-two
row addressing, not tightly packed pictures.
Those five pages are passed to the routine at 1DECh. Its first loop doubles
all three components of sixteen stored vertices. It then builds transformed
coordinate arrays, projects edges and feeds scanline workers before freeing all
five allocations. The code therefore makes one articulated textured object
from five small panels. It does not store several frames of a prerecorded
twist.

The animation is visual concordance for the order-2-to-3 routine. The byte dimensions, allocations and stride come from the restored executable.
The Woven-Line Inner Loop
The scene at 3204h reserves 1716h stack bytes. Before drawing, it generates
400 random words and two 1,025-word phase tables, plus a 200-byte scanline
selector. Each frame advances two angles by 10 and 5 modulo 1,024. For every
one of the 200 rows it combines those lookup values with the selector and calls
the span worker at 319Ch twice.
The worker is a one-dimensional 8.8 fixed-point texture mapper. In compact form its hot loop is:
mov bl,dh ; integer part of the 8.8 source phase
mov ah,[bx+si] ; sample one byte from the line texture
add ah,color_bias ; bias is 64 - span_length
cmp ah,63
jb store
mov ah,63 ; saturate to the VGA ramp
store: mov es:[di],ah
add dx,phase_step
inc di
dec cx
jnz loop
Span length controls brightness as well as geometry: shorter spans receive a
larger bias. DX advances independently of the framebuffer address, so each
horizontal stroke samples a moving one-dimensional color waveform. Two spans
per row, 200 rows, and independently moving phase tables create the woven
bundle without a stored bitmap.

A 36-Layer Integer Line Tunnel
The following routine at 395Eh reserves 0402h local bytes and initializes
four phase indices in the range 0..4095. It builds two banks of 36 records, each
record 280 bytes. Paired lookup tables at 1BBEh and 3BC0h supply rotation
components; radii 85 and 60 define the rectangular cross-section. Sixteen
projected points per active layer are divided by depth and sent to the line
clipper at 38BFh.
The layer state advances while the tracker moves from order 5 to order 7.
Every frame is synchronized by polling VGA status port 3DAh; palettes go
through the DAC path, and the line geometry is regenerated rather than copied.

The Repeated 3D Core Is A Family, Not One Mystery Call
The middle of the demo contains several visibly different solids, but the code
shows deliberate reuse. Routines beginning at 4EA8h, 5DF6h, 6D8Ah,
7C7Fh, 8683h and 915Dh repeat the same structural pieces:
- three angle accumulators wrapping at 360 (
0168h); - paired lookup-table rotation components;
- signed perspective division;
- edge walkers clipped to x 0..319 and y 0..199;
- per-scanline left and right limits;
- horizontal fills into a selected 64 KiB work segment;
- page copies or swaps only after retrace synchronization.
They are not byte-identical. 4EA8h keeps 32 projected records and switches at
order 8 row 52. 5DF6h is a compact four-face construction with dedicated
edge routines at 682Dh and 6A97h. 6D8Ah can maintain two separately
transformed objects and six independent angles. 7C7Fh reserves 06A2h local
bytes and draws a larger record set. 8683h reserves 0638h, includes direct
DAC programming and stops on row 56. 915Dh triples the XYZ components of
fifteen stored vertices before entering its matrix and projection loop.
This is the useful code-level reading of the succession of cubes and awkward solids: Blitz kept replacing the object data and scene state around a small set of integer polygon techniques instead of shipping a general-purpose 3D engine.
The 1,024-Phase Procedural Field
At 99DBh, two 1,025-word tables are populated from different numeric ranges.
The frame loop advances their indices by 6 and 3 modulo 1,024 and combines one
sample from each:
y = base_y - table_b[phase_b] + table_a[phase_a]
It does this for all 320 x positions. Around a moving center it looks up a
20x20 binary mask at load offset 10AEh. Set mask cells invoke the small
additive kernel at 9D93h: four corner neighbours receive color, four axial
neighbours receive color+3, and the center receives color+6. The result is
a procedural height trace with a pulsing, nine-tap additive object embedded in
it. Retrace polling brackets each full 320-column pass.

Five Hundred Points With Individual State
The scene at 9E27h reserves 17A8h bytes. It clears 501 triples of signed
coordinates and parallel state arrays, then admits points until the active
count reaches 500 (01F4h). New movement deltas come from a five-value random
range, shifted to -2..+2, while three global drift terms are kept inside
-40..40. Each live point is transformed, projected and drawn; its lifetime and
velocity state survive to the next frame.
At order 18 row 52 the code increases the drain term. At order 19 it stops the loop, restores the work page and returns. That explicit lifetime machinery is why the particle cloud can coalesce and disappear without a frame sequence.
The Late Ring Engine And Its Inner Geometry
The final long renderer at physical offset 16FBCh reserves 215Eh bytes --
8,542 bytes of local state. Its first nested loop constructs a radial lookup
field for radii 0 through 60. For every signed x from -r through +r, it
evaluates the integer form of:
y = sqrt(r*r - x*x)
radial[x][r] = y
The compiler emits the square, subtraction, square-root runtime call and byte
store explicitly; signed-x rows have a 61-byte stride (3Dh). The routine then builds
two 256-word phase tables, copies a 256x200 window from a 320-stride page into a
256-stride work page, and initializes a tracker-row-driven state machine.
Every eighth tracker row begins a new color transition. Two RGB triples move one component per update toward their targets, DAC entries are rewritten, and the active work page changes after nine and then five completed transitions. The radial table supplies the ring boundaries while the phase tables distort their centers and thickness. Order 32 row 48 begins the closing state; order 33 ends the renderer.

VGA Timing And Why The Demo Is Stable
The renderers repeatedly poll bit 3 of VGA input status port 3DAh, first
waiting for retrace to begin or end and then doing the complementary wait. DAC
updates use color components in the 0..63 VGA range. Work segments are copied
or selected outside the hottest pixel loops, so the inner loops mostly perform
integer address arithmetic and writes.
The opening main routine also builds two 4,097-word numeric lookup tables and a 4,097-byte random table once. Later scenes reuse them with modulo-1,024 or modulo-4,096 phase arithmetic. The memory cost is small, but it removes trigonometric and random-number work from most frames.
This is conventional 1995 VGA engineering done thoroughly: precompute the expensive curves, clip before writing, draw to another segment, wait for the display boundary, then reveal or copy the completed page.
What The Preserved Images Do And Do Not Prove
The GIFs are short excerpts generated without audio from the preservation video linked by the Pouet record. They are used to correlate recovered routines with visible intervals. No video or H.264 asset is embedded in this page.
DOSBox-X's built-in AVI capture path crashed on this executable's early mode switch in the test environment, so those broken captures were discarded. The separate no-capture run of the original archive completed normally. File dimensions, order/row thresholds, allocation sizes, lookup-table lengths and inner-loop behavior above come from the original module and restored program, not from reverse-engineering a compressed video.
Assessment
Disorder is not one spectacular algorithm surrounded by filler. Its strength
is the amount of authored machinery behind a 56 KiB packed carrier: five-panel
texture preparation, a fixed-point line mapper, a 36-layer tunnel, several
specialized polygon variants, a 1,024-phase procedural field, 500 independently
tracked points, and a separate late controller with a radial renderer that runs
almost to the last order.
The rough cubes and handwritten disclaimers are honest presentation. Underneath them is a carefully scheduled real-mode program that keeps changing methods for more than four minutes and still returns cleanly to DOS.