Analysis model: gpt-5.5 xhigh, sol high
Last edited: 2026-08-26
TU Player V1.0 by The Untouchables - Technical Dissection
Release date: 25 December 1991
TU Player V1.0 is a small MS-DOS VGA intro by The Untouchables. Its one
screen is economical rather than static: a 33-row Gothic text strip enters one
four-pixel column per frame, a three-page planar ring lets the CRTC scroll that
strip without moving the whole screen, and four 17-colour ramps animate the
skull, eyes, bars, logo, and lettering. A custom packed-image decoder supplies
both the font atlas and the skull/TU base picture. The final TU.DAT region
is a complete four-channel ProTracker module, with direct-DAC Sound Blaster and
Covox playback code in the restored executable.

This is a direct, continuous, silent DOSBox-X excerpt from graphics-stream
00:04.000..00:10.000, reduced from the emulator's exact 2x output to the
logical 320x200 frame. It shows the top strip moving independently of the
lower skull picture, the next Gothic columns entering at the right edge, the
horizontal bars crossing the split, and the four offset palette pulses. It is
not a slideshow or a public-screen reconstruction.
Identity and source chain
Demozoo records the release as an MS-DOS intro by The Untouchables on 25
December 1991. The archive's two payload timestamps are also Christmas Day
1991. This is not a shortened copy of the group's earlier Anti-svd: the
executables, TU.DAT sizes, decoded pictures, scroll text, and module formats
all differ.
tu_player_v1_0_intro.zip 131,975 bytes
INTRO.EXE 11,513 bytes 1991-12-25 15:37:34
TU.DAT 174,035 bytes 1991-12-25 15:37:24
9226a10f98eeae8f989dd5452aec0a80298e79790a626ad25c3971e9ec07b11f archive
e303a84308dc15344653486808e0f6816e2d2b741130775564f52563e30d1957 INTRO.EXE
5518426aa66e81dfcbadb4c2ab0738c1cd1006d18b35452b869d2b0456bc6b6a TU.DAT

The unmodified 320x200 Pouet still catches the scroll phrase The Untouchables above the same skull and logo. The direct run reproduces that
composition and shows what the still cannot: the words and bars belong to a
moving CRTC strip, while the skull and emblem below it come from one decoded
raster resource.
Runtime capture and normal exit
The release was run through its explicit fastest/no-sound command-line route:
emulator DOSBox-X 2024.03.01, commit 02f36ba
machine / CPU svga_s3, normal core, fixed 12,000 cycles
guest command INTRO.EXE /speed:7 /sound:4
host audio SDL dummy; guest no-sound branch
capture DOSBox-X dx-capture /v /-a /-m
graphics stream ZMBV 640x400, 70.0863 fps, 16.879189 seconds
exit input one X11 Space event at host-run +15 seconds
timing zero first frame of the 640x400 graphics stream
The first 13 seconds cover the running strip and palette phases. The injected
Space request becomes visible as the final palette fade by about stream
00:14; the image is almost black at 00:16, BIOS mode 3 follows, and the
capture closes normally. The host mixer was dummy and sound option 4 skips the
module loader and all sample output. No soundtrack was monitored or auditioned.
DOSBox-X startup, SDL, XKB, and code-page diagnostics were redirected to an
ignored log. The installed build has -silent, but that option also selects
dummy video, so it is unsuitable for a visual capture; ordinary launch plus
stdout/stderr redirection is the quiet capture path used here.
Two unpacking boundaries
The distributed 11,513-byte MZ contains a PKLITE Copr. 1990-91 signature.
One UNP pass expands it to a 23,109-byte MZ that still contains the inner
backward expander. A second pass restores the actual application:
first UNP result 23,109 bytes
SHA-256 b5203fa1524e9fde227480d90486fc610b9ea6cd02617a5ee6a3c9fe911f2bec
final restored MZ 252,672 bytes
SHA-256 09715545035d8a18c7b0a9c9ef96850e824e9ede274feab5a53c8a300a3cfc73
MZ header 272 bytes (0011h paragraphs)
load image 252,400 bytes
relocations 60
entry 144A:0010
entry file offset 145C0h
stack 3D9F:46B0
Addresses below are written as linked segment:offset values from this final
image. Its principal file bases are 0589 -> 059A0h, 144A -> 145B0h, and
1581 -> 15920h; DOS adds the process load segment through the relocation
table at runtime.
The MZ entry at 144A:0010 gets the PSP with INT 21h/AH=62h, saves it,
checks four marker words (3412h,7856h,BC9Ah,F0DEh) at the load-image start,
calls the application body at 144A:10AF, and exits through
INT 21h/AX=4C00h. This explains why the application can use raw segment zero
as shorthand for the relocated load segment: several zero immediates are
relocation words, not references to physical low memory.
Startup dispatcher
144A:10AF first checks F000:FFFE; machine-model byte FCh enables
REP OUTSB for DAC transfers, while other machines use an explicit
LODSB/OUT loop. It then uppercases the PSP command tail and accepts:
/SPEED:1..7
/SOUND:1..4
The speed words are:
2000 26D7 2E9C 3E25 4295 4DAE 5D37
The selected word is reduced by 0500h. Sound values become zero-based:
Sound Blaster, Covox LPT1, Covox LPT2, and no sound. Missing switches lead to
the corresponding BIOS-keyboard menus.
The graphics path is then:
144A:00D9 install private INT 9 handler
144A:11B6 BIOS mode 13h
144A:0870 clear all 768 DAC components
144A:0954 unchain mode 13h
144A:0939 clear all four 64 KiB VGA planes
144A:0BD7 program CRTC split/start state
0589:014C decode font atlas to segment 2DA1h
0589:014C decode base image directly to planar A000h
144A:08EC copy 768-byte release palette
144A:07D4 64-level palette fade-in
144A:12AC enter the frame loop
The INT 9 handler at 144A:00B2 reads port 60h, recognizes only Space scan
code 39h, writes exit state 1 unless shutdown has already reached state 6,
pulses port 61h bit 7, acknowledges the master PIC, and returns without
chaining the previous keyboard handler. Escape therefore does not end this
intro.
Exact TU.DAT directory
The resource-loader segment starts with three little-endian dword offsets:
0589:0000 00000000h
0589:0004 00002BDDh
0589:0008 000054F1h
They divide TU.DAT exactly:
| File range | Bytes | Proven role |
|---|---|---|
00000h..02BDCh |
11,229 | packed 320x200 Gothic font atlas |
02BDDh..054F0h |
10,516 | packed 320x200 skull/TU base picture |
054F1h..2A7D2h |
152,290 | complete four-channel M.K. module |
The first word of each picture is its compressed payload length:
block 0: 2BDBh + 2-byte length = 2BDDh bytes
block 1: 2912h + 2-byte length = 2914h bytes
The graphics loader at 0589:014C opens tu.DAT, seeks to the selected dword,
requests EA60h (60,000) bytes into 0589:01AC, closes the handle, and calls
one of two decoders. Those deliberately oversized reads overlap later regions,
but each bitstream terminates through its exact final payload byte. The loader
checks open failure, not a short read; open failure exits immediately with DOS
status 1 instead of unwinding video and interrupt state.
The packed-image inner loop
Linear decoder 0589:0050 and planar decoder 0589:009F share the same token
loop. Both start at packed offset 2 and stop when logical destination index
DI reaches FA00h, exactly 64,000 pixels. Every token uses two overlapping
big-endian byte windows even though the stream-length header is little-endian:
window = (source[si] << 8) | source[si+1]
window = RCL16(window, bit_position)
window = RCL16(window, 9)
carry clear: emit low_byte(window) once
carry set: retain that byte as colour,
extract another window with RCL16(...,10),
emit colour (low_byte(second_window)+1) times
bit_position++
at bit_position 8: reset it and advance source one extra byte
The first stream consists of 557 literals and 4,988 repeated-value tokens; the second has 3,879 literals and 2,894 runs. A run can emit 1..256 pixels. Decoded indexed hashes are:
bb851194d3e850f22e214ae3da19c7440ff6ca95499488d6378b514d37a759de font
aa310556183ca439d8305a94181e1a7cfe7c7f967a0ae3337cf8a336d32888af base picture
The linear path writes ordinary bytes with STOSB. The planar store at
0589:002B turns logical pixel index p into:
SEQ map mask = 1 << (p & 3)
VGA byte address = (p >> 2) + plane_base
It then increments the original logical index. Recombining the four planes therefore recreates the normal 320x200 chunky order exactly.

This is the first TU.DAT stream decoded by that loop and coloured with the
exact 768-byte, 6-bit DAC palette at restored load offsets 0071h..0370h.
It is not a font approximation: the renderer reads its columns directly from
the 64,000-byte result in segment 2DA1h.

This is the second stream under the same release palette. It owns the skull, eyes, logo, and tiny lower credits in both runtime images. The bars and top message are absent because those are the live strip inserted after this image has been decoded into planar VGA memory.
Scroll-message codec and glyph records
The restored load image contains 661 encoded message bytes at
0375h..0609h, followed by count 0295h. The frame code decodes one source
byte at a time with feedback from the previous encoded byte:
x = encoded[i] XOR encoded[i-1] // encoded[-1] = 0
plain = ROL8(x,4) XOR 3Eh
glyph_code = plain - 20h
plain is ordinary text. It begins:
Well Dudes.... You're watching at a new masterpiece from The Untouchables
Released On Christmas-Day 1991 (25 December 1991) ...
and closes with Christmas/New Year greetings and thanks to the composers of the included MOD material. The old board-name interval was inspected to close the stream but is not reproduced here.
For glyph code g, the supporting tables are:
width byte load[0616h + g]
source offset word load[06D8h + 2*g]
source x/y offset % 320, offset / 320
glyph height 33 source rows
Only codes 0..89 occur. The width table is stored in pixels and the renderer
uses width >> 2 as the number of four-pixel columns. Each source pointer
lands directly in the decoded atlas shown above.
One complete scroller frame
The steady-state renderer begins at 144A:0A62 (restored file 15012h). Its
active constants are:
logical source pitch 320 bytes
VGA pitch per plane 80 bytes
strip height 33 rows
one strip page 33*80 = 0A50h bytes
three-page ring 3*0A50h = 1EF0h bytes
ring base 7D00h
new-column x byte 79
The visible top region is 32 logical rows; row 33 is the guard/source row used by the ring. Mode 13h scan doubling turns the split into about 64 physical scanlines. CRTC line compare is exactly 63.
Before drawing, the renderer advances the current glyph only after source
phase reaches width[g] >> 2. It then feedback-decodes the next scroll byte,
looks up that glyph's atlas pointer, and computes:
source = glyph_pointer[g] + 4*source_phase
dest = 7D00h + scroll_offset + 79
The first nested loop writes the entering four-pixel column into a selected display page:
for plane = 0..3:
SEQ.map_mask = 1 << plane
SI = source + plane
DI = dest + page_select
repeat 33 rows:
MOVSB // one source pixel into this VGA plane
SI += 013Fh // net source stride: 1+319 = 320
DI += 004Fh // net VGA stride: 1+79 = 80
This is 4 planes x 33 rows = 132 byte writes. 144A:0A10 then writes CRTC
start address 7D00h + scroll_offset + page_select; page_select toggles
between 0 and 0A50h.
After the retrace/palette handoff, the same four-plane, 33-row column is copied
again at a two-page displacement. Each row compares DI with
7D00h + 3*0A50h; crossing it subtracts 0A50h three times. That second 132
writes keeps all aliases of the circular backing strip coherent. Finally:
scroll_offset++
if scroll_offset == 0A50h: scroll_offset = 0
source_phase++
One frame therefore performs only 264 planar video-byte writes. It does not copy or clear 64,000 pixels. The CRTC advances one plane byte—four logical pixels—through the ring, while the fixed lower picture restarts at line compare 63. This is the exact ownership split visible in the GIF.
VGA setup and presentation
144A:0954 derives unchained byte-addressed mode from BIOS mode 13h:
Sequencer 04h: clear bit 3, set bit 2 disable chain-4 / odd-even
Graphics 05h: clear bit 4
Graphics 06h: clear bit 1
CRTC 14h: clear bit 6
CRTC 17h: set bit 6
The initial presentation setup writes:
CRTC 18h = 3Fh line compare 63
CRTC 09h = 80h scan doubling retained
CRTC 07h = 01h
CRTC start = 7D00h
There is no mode probe or fallback. The all-plane clear selects sequencer map
mask 0Fh and writes 32,768 words to A000:0000, covering every 64 KiB plane.
Palette baseline, dirty range, and four pulses
The direct picture is animated chiefly through palette memory. At
144A:0D38, each frame restores 01A4h (420) baseline bytes into the working
palette and preserves the previous dirty endpoints. Four calls to
144A:0F87 then overlay 51 bytes—17 RGB entries—at staggered phase starts:
frame >= 0000h ramp at load 0DEDh, phase byte 0F86h
frame >= 00C8h ramp at load 0E20h, phase byte 0F85h
frame >= 01A4h ramp at load 0E53h, phase byte 0F84h
frame >= 0280h ramp at load 0E86h, phase byte 0F83h
Each phase advances through 0..198 and indexes the 200-byte triangular table
at 144A:0F81. The destination is:
palette[010Bh + 3*phase_table_value : +51]
The routine records the affected palette-index interval. 144A:0D7C writes
only the merged current/previous dirty span through DAC ports 03C8h/03C9h;
when the computed upper endpoint is below the lower one, it emits nothing.
Every fourth frame, 144A:0FE8 also oscillates another palette interval by
one component step. This is why the skull eyes, logo, bars, and letters pulse
without any corresponding pixel rewrite.
The main phase counter starts at zero, increments once per loop, and at
2000h subtracts 1000h. It therefore traverses 1..8191 once and subsequently
cycles through 4096..8191. The delayed ramp starts at frames 200, 420, and 640
occur only during that first traversal.
Retrace and IRQ pacing
The paced wait at 144A:011E first waits until 03DAh bit 3 is clear. It
compares player IRQ count 1581:75AC with floor(selected_rate/60). If the
count is not already above that budget, it waits for the next retrace start;
if the renderer is late, it skips the extra wait. It then clears the count.
No-sound option 4 skips module loading, PIT reprogramming, and sample mixing.
Its IRQ0 handler at 1581:6A19 performs only the stop handshake and PIC EOI,
so the sample counter remains zero and normal VGA retrace controls the frame
rate. The measured graphics stream is 70.0863 fps, matching the mode-13h-class
refresh rather than a fixed 60 fps.
Static module and mixer audit
The soundtrack was not played, but the binary and module path are fully
addressable. TU.DAT offset 54F1h begins a complete 152,290-byte ProTracker
module and ends exactly at EOF:
title SHAKIN
signature M.K. at module +0438h / file 05929h
song length 17 orders
orders 1,1,0,2,3,4,5,5,6,6,6,7,8,8,3,0,0
patterns 9 x 1024 bytes
nonempty samples 13 of 31
sample bytes 141,990
Music loader 1581:79C5 opens the same tu.DAT, seeks to 54F1h, probes both
the !Scream! and M.K. positions, and selects its 31-sample MOD loader. It
reads 31 headers, the 128-position order table, 9 patterns, and 31 sample
slots. Inactive branches support Scream Tracker and 15-sample MOD material;
neither owns this release data.
For sound options 1..3, the selected speed word minus 0500h is a requested
sample IRQ rate. At speed 7 that is 22,583 Hz; the player chooses PIT divisor
floor(1193180/22583)=52, yielding about 22,945.8 IRQ/s. Tracker setup uses six
ticks per row and a countdown near rate/49.
The mixer has four channel records with 16.16 nearest-neighbour sample
stepping, sample end/loop pointers, volume, and a 65x256 signed-sample/volume
lookup table at 1581:1D45. The IRQ alternates channel pairs (0,1) and
(2,3), pipelines adjacent sums, adds 80h, and performs no separate clipping
pass.
Sound Blaster output is deliberately primitive:
base ports fixed 220h; BLASTER is not parsed
setup reset through 226h, then send D1h speaker-on
each IRQ poll 22Ch, send direct-DAC command 10h,
mix one byte, poll 22Ch, send sample
DMA none
SB IRQ none; timing is PIT IRQ0
Covox output uses the LPT1/LPT2 data-port words at BIOS data addresses
0040:0008 and 0040:000A, with one OUT DX,AL and no control-port strobe.
All playback modes replace INT 8 and acknowledge the master PIC without
chaining the BIOS clock handler.
Space handshake and cleanup
When the keyboard ISR changes state to 1, main changes it to 2 and waits. The
active IRQ0 handler notices state 2, calls the common stop helper at
1581:69DE, changes state to 6, and sends PIC EOI. Main then:
144A:0750 read the palette and perform 64 decrement passes
port 21h force PIC mask 00h
port 40h write FFh,FFh as PIT channel-0 divisor
1581:7566 restore saved INT 8 vector
144A:00FA restore saved INT 9 vector
INT 10h BIOS mode 3
RET return to MZ exit
The fade reads all 768 DAC components in four 192-byte chunks and performs
64*4 paced writes, 261 paced waits including setup. Cleanup is functional but
not a byte-for-byte hardware restore: the previous PIC mask and PIT mode/count
are not saved, lost BIOS ticks are not compensated, the Sound Blaster never
receives speaker-off D3h, and a Covox latch is not centred.
The common IRQ stop helper also runs a backwards XOR transform over part of the loaded image using the physical INT 2 vector offset as both starting/count material. Its instructions are verified; whether the original intent was anti-ripping, self-scrubbing, or another cleanup convention remains uncertain.
What the screen actually is
This production contains no vector-object, polygon, or generated-circle
renderer. Its skull and TU emblem are packed indexed pixels. Its text is a
packed raster font whose four-pixel columns are injected into a 33-row planar
ring. Its apparent moving light is four palette overlays, not redrawn shading.
The CRTC split and start-address updates make that narrow strip move while the
lower raster remains fixed. The public still, exact resource decodes, direct
runtime GIF, and restored inner loops all describe the same screen.