Analysis model: GPT-5 (Codex), reasoning level not exposed

Last edited: 2026-08-30

BBS-A-Holic BBS (2) by The Humble Guys - Technical Dissection

BBS-A-Holic BBS (2) is a real 1991 MS-DOS BBStro, but it is a much smaller kind of production than a realtime cracktro. The only surviving file is a 3,762-byte executable made with GRABBER 3.60. It expands one signed 80x25 colour-text page, copies the resulting 4,000 bytes to B800h, waits for a key and restores the previous display state.

The distinction matters. The large left-hand lettering and bordered board ad are original CP437/attribute artwork; the decompressor, video setup, optional timer and key handling belong to G.A. Monroe's generic GRABBER viewer. There are no vector balls, custom bitmap graphics, music or hidden second screen.

Release year: 1991.

The previous research queue associated this file with a THG Lemmings release. The examined archive does not support that claim: it contains only THGSITE!.EXE, with no game, release note or companion metadata. This page therefore treats it as a genuine standalone board advert attributed to The Humble Guys by the surviving catalogues, not as a proven software-bundled cracktro.

Sources

Demozoo identifies the production as a 1991 MS-DOS BBStro by The Humble Guys and an advert for BBS-A-Holic. Pouet independently gives the same year, group, platform and board-ad identity. Neither catalogue supplies an artwork credit. The visible footer in the executable signs the ANSI as D·ToX <ACiD> / Little T; that literal signature is reported without trying to map it to catalogue person records that are not present.

Examined Artifact

The archive has one member:

79394f3638b2a09ada655e90310cbd017da0accd7994891d52bc9a279358dce2  bbs-a-holic_bbs2.zip
b7abdb261d044c774520d7b586740679e6d48a0b8293f8bb38c5d50a1a2494e6  THGSITE!.EXE  3,762 bytes

Its ZIP timestamp is 22 November 2016, the day the production was added to Pouet, so it is a preservation timestamp rather than release-date evidence. The year on this page comes from the catalogues.

The executable identifies its generator internally:

Created by GRABBER (tm) Version 3.60
Copyright (c) G.A. Monroe 1987, 1988, 1989, 1990

That tool identity is consistent with the code: a general-purpose viewer parses /F, /N, /K and /T command-tail switches, detects the active adapter, allocates a screen buffer, expands a stored image and optionally times the display. The examined default route uses none of those switches.

Complete Silent DOSBox-X Run

The exact executable was run directly under DOSBox-X 2026.01.02 on 30 August 2026 with machine=svga_s3 and 3,000 fixed cycles. SDL video and audio used dummy host drivers; the mixer had nosound=true, and Sound Blaster, MIDI, PC speaker and Tandy audio were disabled. The file neither requires nor attempts sound output.

One scripted Enter key traversed the complete route. The program displayed its single page, accepted the key, restored the prior mode and returned normally to DOS. The capture lasts 8.043 seconds. Its private MPEG-TS diagnostic contains an empty AAC stream created by the capture container and is not published.

DOSBox-X produced 720x400 video samples with sample aspect ratio 20:27. The still below is the complete frame at 00:02, converted with nearest-neighbour scaling to 720x540 square pixels without cropping or padding:

BBS-A-Holic BBS 2 complete text-mode screen at 00:02

The page includes only an area-code placeholder and explicitly tells the reader to obtain the number elsewhere. No telephone number is present in the executable, so the complete authored frame can be shown without reproducing historical contact data.

The emulator log records one benign INT 16h extension-probe call before the screen. That is the viewer's AX=4752h, DL=FFh capability query, not a failed runtime gate; the page appears, the later Enter is accepted and the process exits normally.

MZ Shape And A 48-Byte Length Quirk

The executable is not packed by PKLITE, LZEXE or a self-modifying wrapper. It is an ordinary zero-relocation MZ with the GRABBER player and packed page stored together:

physical file size                 3,762 bytes
MZ-declared file size              3,714 bytes
header                                48 bytes
physical bytes after header        3,714 bytes
MZ-declared load image             3,666 bytes
physical tail beyond declaration      48 bytes
relocations                            0
entry CS:IP                    0008:0000
entry file offset                   00B0h
stack SS:SP                    0000:0080

The header fields are e_cp=8, e_cblp=0082h and e_cparhdr=3. Curiously, the declared total is exactly the physical post-header length, as if GRABBER computed the module size and forgot to add its 48-byte header. The last 48 physical bytes are not disposable padding: they finish the compressed attribute plane. The DOSBox-X run proves that its loader made those bytes available on this route. Exact historical DOS-loader compatibility was not separately tested, so the malformed size is preserved as an observed artifact rather than normalized away.

At the MZ entry point, runtime CS begins 128 bytes into the load image. The first instruction jumps over strings and state to the player at runtime offset 00F7h:

0000  jmp  00F7h

00F7  mov  bx,ds
00F9  mov  ax,cs
00FB  mov  ds,ax
00FD  mov  es,ax
00FF  mov  [0043h],bx      ; retain original PSP/data segment
0103  cld
0104  call 0759h           ; shrink/allocate and switch private stack
0107  call 07E7h           ; uppercase command tail in the PSP

No relocation fixups are needed because the player keeps code and state relative to CS, stores allocated segment values at runtime, and uses BIOS/DOS services for the machine-facing operations.

The Embedded Page Header

The packed-image header starts at runtime offset 0809h, immediately after the viewer code:

0809  19          rows = 25
080A  50          columns = 80
080B  03          BIOS mode = 3, colour text
080C  30          border/palette state
080D  A0 0F       expanded byte count = 4,000
080F..081B        viewer state / reserved bytes = zero
081C              first compressed plane

The dimensions and byte count agree exactly:

25 rows * 80 columns = 2,000 cells
2,000 cells * (one character + one attribute) = 4,000 bytes

The image is stored as two compressed 2,000-byte planes rather than as interleaved screen words. The character plane occupies 969 bytes from runtime 081Ch through 0BE4h. A six-byte delimiter follows:

0BE5  00 00 52 47 00 00    NUL, "RG", NUL marker
0BEB                       attribute plane begins

The attribute plane takes the final 535 bytes and ends at physical EOF.

Exact GRABBER RLE Decoder

The common decoder begins at runtime 0629h. DL is a rotating one-bit token selector; every eighth token fetches a new flag byte into DH. A clear flag bit means one literal byte. A set bit means a two-byte (count,value) run:

0629  mov  dx,0080h        ; rotating selector, DH initially zero
062C  mov  bx,[080Dh]      ; 0FA0h expanded interleaved size
0630  add  bx,di           ; terminal destination offset
0632  mov  es,[003Ch]      ; allocated 4,000-byte page buffer

0636  rol  dl,1
0638  lodsb                ; first token byte
0639  cmp  dl,1
063C  jne  0641h
063E  mov  dh,al           ; one flag byte for the next eight tokens
0640  lodsb                ; first data byte
0641  mov  cx,1
0644  test dh,dl
0646  je   064Bh           ; clear bit: AL is a literal
0648  mov  cl,al           ; set bit: AL is repeat count
064A  lodsb                ; repeated value

064B  stosb
064C  or   bp,bp
064E  je   0651h
0650  inc  di              ; text mode: stride two, one plane at a time
0651  loop 064Bh
0653  cmp  di,bx
0655  jb   0636h
0657  mov  ax,cs
0659  mov  es,ax
065B  ret

For text modes the caller sets BP=FFFFh, so every output byte advances DI twice. The first invocation begins at DI=0 and fills the even character positions. The marker scanner then locates 00 00 52 47 00 00; the second invocation begins at DI=1 and fills the odd attribute positions.

The recovered expansion ledger is:

character plane   969 packed bytes   729 tokens   148 runs -> 2,000 bytes
attribute plane   535 packed bytes   293 tokens   205 runs -> 2,000 bytes
separator           6 bytes
combined payload 1,510 bytes                         -> 4,000 bytes

Hashes of the independently reconstructed data are:

6c3bd2c143ec647b2fe46d728d9ba40eeaeb9b2876246aaf912117384c115c86  character plane
ea3a8ba12d0ed838dd5f7011b48928526fa4948ee3690afcdbb0b876d6b769bb  attribute plane
c9d27671fec1e758cc913a61bd0e326ee679bc23e7537ee33e0bf14cc27488ce  interleaved B800 page

The page has 1,213 non-space character cells. Its 2,000 attributes use 14 values from 01h through 7Fh; none has bit 7 set, so the artwork does not request hardware blink. Large coloured fields are ordinary text-cell backgrounds, while the title edges use CP437 half blocks and full blocks.

Allocation, Mode Setup And Full-Page Copy

The setup at runtime 0759h disables DOS Ctrl-Break checking temporarily, shrinks the original allocation, reserves a private stack, then allocates an even-paragraph buffer large enough for the 4,000-byte expanded page. The resulting screen-buffer segment is stored at [003Ch] and used as ES by the decoder.

The display path queries the current video mode through BIOS INT 10h/AH=0Fh and saves the mode, active page and column count. It also reads BIOS data-area geometry and adapter state. Because the embedded header requests mode 3, the active colour-text destination is B800:0000; monochrome mode 7 would select B000:0000 instead.

After both planes have been expanded into their interleaved buffer, one copy publishes the entire authored screen:

03C3  mov  ax,B800h
03C6  cmp  word [005Eh],03B4h  ; monochrome CRT controller?
03CC  jne  03D1h
03CE  mov  ax,B000h
03D1  push es
03D2  mov  es,ax
03D4  mov  cx,[080Dh]          ; 0FA0h bytes
03D8  shr  cx,1                ; 07D0h words = 2,000 cells
03DA  mov  di,[0058h]          ; saved display-page offset
03DE  xor  si,si
03E0  push ds
03E4  mov  ds,[003Ch]          ; expanded screen buffer
03E8  rep  movsw
03EA  pop  ds
03EB  pop  es

There is no drawing loop after this copy. What looks like a large graphic is already fully authored in the decompressed cell page.

Timer Hook, Key Gate And Cleanup

GRABBER supports timed and unattended presentation, so the generic player saves interrupt vector 8 and installs a tiny tick handler. The handler only increments a counter and chains to the previous vector:

06FE  inc  word cs:[0047h]
0703  jmp  far cs:[004Bh]

The default route polls with DOS INT 21h/AH=06h, DL=FFh while the timer window is active. When it reaches the normal blocking gate, the player uses INT 21h function 0Ch with subfunction 07h: flush standard input, then read one character without echo. The scripted Enter therefore changes no screen state; it simply releases the single page.

The exit path restores the prior video mode when necessary, resets palette and cursor state, restores the saved interrupt-8 vector, restores the original DOS Ctrl-Break flag and terminates through INT 21h/AH=4Ch. The observed DOSBox-X return confirms that this cleanup path completed; no timeout or forced kill was used.

Runtime-To-Code Concordance

Runtime evidence Recovered mechanism Conclusion
One static 80x25 page appears and remains unchanged until Enter Header bytes specify 25 rows, 80 columns, mode 3 and a 4,000-byte expansion This is one colour-text page, not a multi-part graphics intro.
The left title and right panel use blocks, half-blocks, line characters and many cell colours Two RLE streams reconstruct 2,000 CP437 bytes and 2,000 attribute bytes The apparent graphic is ANSI-style cell art, not a bitmap or custom font.
The complete page appears at once rep movsw copies exactly 2,000 words from the expanded buffer to B800h There is no incremental renderer, wipe or animation pass.
The frame stays silent and static No sound path exists; the only interrupt hook increments a timer counter The hook supports viewer timing, not music or motion.
One Enter returns cleanly to DOS Function 0Ch/07h supplies the blocking key gate; mode, palette, cursor, timer vector and Ctrl-Break state are restored The direct run covers the complete authored route and normal exit.
The page identifies THG and ACiD distribution roles and bears an ANSI footer signature Those strings are reconstructed from the executable's character plane, while the viewer identifies itself separately as GRABBER 3.60 The board advert and art are genuine; the playback code is a generic tool, and no parent game is proven.

The preservation result is thus narrower but firmer than the earlier catalogue lead: THGSITE!.EXE is a real period BBStro, not an invented vector/ball demo, and its entire visual can be recovered byte-for-byte. Its technical interest is the compact split-plane RLE representation and the surprisingly complete generic DOS display wrapper around one signed colour-text page.