Analysis model: gpt-5.5 xhigh

Knights Of Legend Cracktro by The Humble Guys - Technical Dissection

Knights Of Legend Cracktro is a 23 January 1990 MS-DOS cracktro / loader by The Humble Guys. Demozoo lists it as a The Humble Guys MS-DOS cracktro released on 23 January 1990, with the release-date source noted as artscene.fix.no. The Scene.org archive is demos/compilations/lost_found_and_more/cracktro/knights_of_legend_cracktro.zip.

Release year: 1990.

Sources:

This is the same visual family as the later THG Bubble Bobble Cracktro: a static text-mode colour-bar card, not an animated demo. Technically, though, it is different. Bubble Bobble is a flat COM with an XOR stub and a rough DOS EXEC handoff. Knights Of Legend is a real MZ executable with a 512-byte header, one relocation, plain unencrypted code, a data segment placed before the entry code, and a post-key far return to PSP:0000.

The preserved file contains an unused Start.exe string, but it contains no reachable DOS EXEC path. The visible program draws the card, waits for a key, then exits.

Visual References

Time Image Notes
00:00.000 Knights Of Legend Cracktro public Demozoo frame Public Demozoo still of the rendered text-mode colour-bar screen. The program reaches this static state immediately, then waits for a key.

Generated execution map:

Knights Of Legend Cracktro MZ pipeline map

No local DOSBox timing capture was needed for this pass. The display has one visible state, so the 00:00.000 marker means "after the BIOS text draw stream has completed", not a measured animated timestamp.

Archive Shape

The examined Scene.org ZIP is 943 bytes:

thg-kol.exe  3463 bytes  1989-12-21 21:19

SHA-256:

bf7639ad6820b18fe32c39ef136c80440b7fe170c5e3a462339965168ee88222  knights_of_legend_cracktro.zip
a53291024cc1dc397d73ebe9780301f2a782f7bb74965f08ab53c5e8b3daf168  thg-kol.exe

There are no sidecar files in this package. The internal file timestamp is 21 December 1989, while Demozoo records a 23 January 1990 release date. I keep the release year as 1990 because that is the public production metadata, but the binary was likely built earlier.

MZ Header

The first 32 bytes:

4D 5A 87 01 07 00 01 00 20 00 00 00 FF FF 00 00
8C 00 81 B3 00 00 17 00 1E 00 00 00 01 00 05 00

Important fields:

last page bytes       0187h
page count            0007h
computed file size    0D87h
relocation records    0001h
header paragraphs     0020h = 512 bytes
minalloc              0000h
maxalloc              FFFFh
initial SS:SP         0000h:008Ch
initial CS:IP         0017h:0000h
relocation table      001Eh
overlay number        0000h

The computed MZ size exactly matches the physical file:

(pages - 1) * 512 + last_page = 6 * 512 + 0187h = 0D87h
load image size = 0D87h - 0200h = 0B87h
entry load offset = CS * 16 + IP = 0170h
entry file offset = 0200h + 0170h = 0370h

The single relocation record is:

offset 0005h, segment 0017h

That points at the immediate word in the entry instruction mov ax,0009h. After DOS relocation, it becomes mov ax,load_segment+0009h, which is then loaded into DS.

Load-Image Layout

Offsets below are load-image offsets, where 0000h is the first byte after the 512-byte MZ header:

0000-008B  repeated "HUMBLE!" filler
0090-0169  strings and dead filename/final-message data
0170-0B86  entry and generated text-mode renderer

The interesting detail is that the strings are before the entry code, not after it. DOS relocates the entry's mov ax,0009h, and the code sets:

DS = load_segment + 0009h

That makes DS:0000h point at load offset 0090h, the start of the string pool.

The string pool:

DS:0000  "The Humble Guys!", "$"
DS:0011  "Present", "$"
DS:0019  "Knights of Legend!", "$"
DS:002C  "Seems to be Unprotected!", "$"
DS:0045  members line, "$"
DS:0093  "Press any Key to Load!", "$"
DS:00AA  "Start.exe", 00
DS:00B4  final thank-you string, "$"

Start.exe and the final string are never reached by the preserved code path.

Entry And Relocated DS Setup

The entry starts at load offset 0170h:

0170  1e              push ds
0171  2b c0           sub ax,ax
0173  50              push ax
0174  b8 09 00        mov ax,0009h      ; relocated by DOS
0177  8e d8           mov ds,ax

There are two jobs here.

First, push ds and push 0000h build a far-return frame. At DOS EXE entry, DS normally points at the PSP. The final LRET pops IP=0000h and CS=original DS, so it returns to PSP:0000h. The PSP starts with INT 20h, so this is an old DOS exit idiom.

Second, the relocated mov ax,0009h sets up the data segment. With DS equal to load_segment+0009h, all later DOS string offsets are short offsets into the string pool.

No stack frame, heap, interrupt hook, or display probe is initialized.

Mode Setup

The mode setup is inline:

0179  b4 00           mov ah,00h
017b  b0 03           mov al,03h
017d  cd 10           int 10h

Mode 3 gives an 80x25 colour text page. The public frame is a 635x397 JPEG capture of a screen that is logically 80 columns by 25 rows.

Cursor And Block-Write Template

Unlike Bubble Bobble, this MZ version does not factor cursor positioning into a subroutine. Every draw command inlines both BIOS calls.

A typical span:

017f  b6 00           mov dh,00h        ; row
0181  b2 00           mov dl,00h        ; column
0183  b4 02           mov ah,02h
0185  b7 00           mov bh,00h
0187  cd 10           int 10h          ; set cursor

0189  b0 dc           mov al,0dch       ; CP437 lower half block
018b  b3 0a           mov bl,0ah        ; bright green foreground
018d  b9 50 00        mov cx,0050h      ; 80 cells
0190  b4 09           mov ah,09h
0192  b7 00           mov bh,00h
0194  cd 10           int 10h          ; write repeated char/attribute

The renderer emits 107 BIOS AH=09h repeated-cell writes before the key wait. The repeated-cell contract is the same as in Bubble Bobble:

current cursor = row/column selected by AH=02h
AL = CP437 character
BL = text attribute
BH = display page, always zero
CX = repeat count
INT 10h AH=09h writes CX cells at that cursor position

The important glyphs:

0DCh  lower half block
0DAh  top-left box corner
0BFh  top-right box corner
0C0h  bottom-left box corner
0D9h  bottom-right box corner
0C4h  horizontal line
0B3h  vertical line

0DCh is why the image looks like scanline colour bars. In text mode the glyph fills only the lower half of the character cell, while the attribute supplies the foreground colour. The black background remains visible in the upper half.

Recovered Draw Counts

A small emulator for INT 10h/AH=00h, AH=02h, AH=09h, INT 21h/AH=09h, and INT 16h/AH=00h gives:

mode set calls             1
cursor-position calls    108
BIOS block writes        107
DOS string writes          6
keyboard waits             1
far returns                1

The six DOS string writes:

063A  row 04 col 32  DS:0000  The Humble Guys!
064B  row 06 col 36  DS:0011  Present
065C  row 08 col 31  DS:0019  Knights of Legend!
0850  row 14 col 28  DS:002C  Seems to be Unprotected!
09A3  row 18 col 01  DS:0045  members line
0B80  row 22 col 29  DS:0093  Press any Key to Load!

The members line is the same long THG member string used in the later Bubble Bobble card. It fills the wide box interior from column 1 through column 77.

Screen Geometry

The authored screen layout:

row 00  full-width DCh colour bar
row 01  full-width DCh colour bar
row 02  bars plus top of title box, columns 20..59
row 03  bars plus title-box side walls
row 04  title string inside title box
row 05  blank row inside title box
row 06  "Present" string inside title box
row 07  blank row inside title box
row 08  game title string inside title box
row 09  blank row inside title box
row 10  bottom of title box
row 11  middle colour bar with a 40-cell brown middle span
row 12  full-width DCh bar
row 13  top of credit box, columns 24..56
row 14  credit string inside credit box
row 15  bottom of credit box
row 16  full-width DCh bar
row 17  top of members box
row 18  members string inside members box
row 19  bottom of members box
row 20  full-width DCh bar with a wide blue middle span
row 21  top of key-prompt box, columns 27..52
row 22  key prompt inside key-prompt box
row 23  bottom of key-prompt box
row 24  final colour bar

The geometry is almost the same as Bubble Bobble. The main differences are the title string column (Knights of Legend! starts at column 31) and the credit-box text (Seems to be Unprotected! starts at column 28).

Key Wait And Exit

The final visible command writes the key prompt, then the program waits:

0b7b  b4 09           mov ah,09h
0b7d  ba 93 00        mov dx,0093h
0b80  cd 21           int 21h
0b82  b4 00           mov ah,00h
0b84  cd 16           int 16h
0b86  cb              retf

There is no timer loop during the wait. After the key, RETF consumes the far-return frame from startup:

IP <- 0000h
CS <- original DOS entry DS, normally the PSP segment

The result is a return to PSP:0000h, where DOS placed the INT 20h exit instruction. This is the only actual post-key behaviour in the preserved file.

Dead Handoff Data

The data segment contains:

DS:00AA  "Start.exe",00
DS:00B4  final thank-you string

But the loaded image has no reachable code after the RETF. It also contains no INT 21h/AH=4Bh DOS EXEC call, no file open/read path, and no branch that targets these strings.

That means Start.exe is either a leftover from a fuller template or a hint at an expected external batch/executable chain not present in this preserved archive. It is not executed by thg-kol.exe as archived.

Comparison With Bubble Bobble

The visible template is shared:

80x25 mode-3 text page
CP437 DCh colour-bar rows
CP437 box drawing
six DOS AH=09h strings
one BIOS key wait
same THG member line

The implementation differs:

Knights Of Legend:
  MZ executable
  512-byte header
  one relocation
  strings before code
  inline cursor calls
  no XOR decode
  final RETF to PSP:0000
  no live EXEC handoff

Bubble Bobble:
  flat COM executable
  15-byte XOR 45h decoder
  strings after code
  cursor helper subroutine
  post-key memory resize/allocation
  attempted EXEC of Bubble.mcf

This makes Knights Of Legend the cleaner display-card specimen. It is almost all generated BIOS text output wrapped in a minimal MZ shell.

What The Code Does, Condensed

  1. DOS loads the MZ image after a 512-byte header.
  2. DOS applies one relocation to the entry's mov ax,0009h.
  3. The entry builds a far-return exit frame to PSP:0000h.
  4. The entry sets DS to the string segment at load offset 0090h.
  5. It sets BIOS video mode 3.
  6. It emits 107 BIOS repeated-cell writes for the colour bars and boxes.
  7. It emits six DOS $-string writes for the title, credit, member line, and key prompt.
  8. It waits for one key via INT 16h/AH=00h.
  9. It exits by RETF to PSP:0000h.

The important negative result: despite the embedded Start.exe string, this publicly preserved executable does not load the game. The cracktro is a static THG text-mode announcement card and exit stub.