Skip to content

Latest commit

 

History

History
235 lines (188 loc) · 10.2 KB

File metadata and controls

235 lines (188 loc) · 10.2 KB

09 — The executable: a DOS program, and the field a Windows binary would need does not exist

Measure: SHI.EXE, 119,618 bytes, 0.0268 % of the disc. Real-mode MZ, Borland C++ 1991. The page arithmetic closes on the file length with residue 0; all 1,684 relocations land inside the load image. It detects VGA through the BIOS, sets mode 13h, writes segment A000h directly, and reads the mouse through INT 33h. There is no NE anywhere in it.


The header, and a correction

python tools/mz.py SHI.EXE
field
e_cblp 322 bytes used in the last page
e_cp 234 512-byte pages
e_crlc 1,684 relocation entries
e_cparhdr 480 paragraphs = 7,680 bytes of header
e_minalloc 251 = 4,016 bytes
e_maxalloc 0xFFFF take all available memory
e_ss:e_sp 1C47:0080
e_cs:e_ip 0000:0000 entry at file offset 7,680
e_lfarlc 0x3E where the relocation table starts

The check. (234 − 1) × 512 + 322 = 119,618, and the file is 119,618 bytes. Residue 0. The header says how long the image is; the file system says how long the file is; they agree. Nothing is appended — no overlay, no self-extracting tail, no packer's payload.

This was derived before the file was opened, from the sixteen bytes the pre-briefing quoted, and written into 00-predictions.md as clause C31.

And a correction to the pre-briefing. It reports "e_lfanew (u16 @0x3c) 0", and concludes from that there is no NE header. The conclusion is right; the reading is not. e_lfanew is a u32 at 0x3C, and here it reads 0x00010000. But that does not matter either, because:

e_lfarlc = 0x3E

The relocation table starts at 0x3E, which is the second half of the field a Windows-era binary would put e_lfanew in. The bytes at 0x3C..0x3F are 00 00 01 00: two bytes of DOS-era reserved space, and then the first relocation entry's offset word. The field is not zero. It does not exist. There is no room for it, because a linker that puts relocations at 0x3E is a linker that has never heard of an extended header.

That is a better statement than "e_lfanew is 0", and it is the one this disc supports:

occurrences of NE anywhere in the file 0
occurrences of LE 0
occurrences of LX 0
occurrences of PE\0\0 0

pe.py, written last session for PE32+, was run because the standing rule is that a refusal is a measurement:

ValueError: SHI.EXE: no PE signature at 0x10000
exit 1

Recorded, not skipped.

The relocations, which date the linker

1,684 entries at 0x3E, 6,736 bytes, ending at 0x1A8E. The header is 7,680 bytes, so 882 bytes of slack follow the table and every one of them is zero — paragraph alignment, written clean.

All 1,684 entries land inside the 111,938-byte load image. 1,684 of 1,684, none out of range, across 32 distinct segments. A 32-segment real-mode program with 1,684 fixups is a large-model C build, which is what Borland C++ 1991 produces and what the string at 0x1BA14 says it is.


What it says to the hardware

The pre-briefing's own list of what was not done opened with "no interrupt vector, port address or BIOS call was located in either binary, so nothing is known about how either talks to hardware", and _pre/question.txt called the display path "a real disassembly question and the strongest single test available, because the answer is a specific instruction and not an inference."

There are four INT 10h sites in the whole executable. All four, read by hand:

offset bytes what
+0x0CC43 b8 00 1a cd 10 3c 1a 75 07 80 fb 07 72 … AX=1A00hread display combination code; require AL=1Ah, then BL ≥ 7. This is the VGA test behind "Please make sure your graphics card is VGA compatible."
+0x0CC5E b4 00 b0 13 cd 10 AH=0, AL=13hVGA mode 13h, 320 × 200, 256 colours
+0x0CC66 b4 50 b0 01 b2 00 cd 10 AH=50h, AL=01, DL=00not a standard IBM VGA BIOS function
+0x0CCDF b4 00 b0 03 cd 10 AH=0, AL=3 — back to 80 × 25 text on exit

Then the frame buffer, three times:

+0x0CC6F   b8 00 a0        mov ax,0A000h
           2e a3 23 00     mov cs:[0x23],ax
           b8 40 01        mov ax,0140h        ; 320

A000h and 320, loaded together, stored together. That is a mode 13h program writing pixels itself, exactly as the platform notes describe their own DispDib path — except through DOS, with no Windows anywhere near it.

And the mouse, INT 33h, nine sites, one initialisation sequence:

33 c0                cd 33     AX=0000   reset the driver
b8 0c 00  b9 07 00   cd 33     AX=000C   install event handler, mask 7
b8 04 00  b9 3f 01  ba 63 00   cd 33     AX=0004   position cursor at 319, 99
b8 07 00  b9 00 00  ba 7f 02   cd 33     AX=0007   horizontal range 0 .. 639
b8 08 00  b9 00 00  ba c7 00   cd 33     AX=0008   vertical range 0 .. 199

0..639 horizontal, 0..199 vertical is the mouse coordinate space of a mode 13h screen, where X counts in half-pixels. The cursor is parked at (319, 99) — the exact centre. This is a textbook Microsoft-mouse initialisation for a 320 × 200 VGA application, and it is why the disc ships MOUSE.COM.

And what it never mentions

python tools/vistokens.py over the two executables only:

in SHI.EXE
Tandy, VIS, Video Information System 0
tlaunch, MODULAR, Modular Windows 0
HC.DLL, DISPDIB, MMSYSTEM, WIN87EM 0
WIN.INI, SYSTEM.INI, KERNEL, USER.EXE 0
EnterDVA, StretchDIBits, waveOut, timeGetTime 0
OPL3 ports 0x388 / 0x389 as immediates 0
DAC / Sound Blaster base 0x220 as an immediate 0

Nothing in this binary knows what machine it is on, and nothing in it touches either audio port the VIS platform notes document. How it plays 8.5 MB of SOUND.DAT and 143 MB of interleaved PCM without naming a port is 17-not-done.md's third entry — the likely answer is a computed port from a configuration this disc does not carry, and that is a hypothesis and not a finding.

And the scan that fires is the scan to read by hand

Run over all 193 files instead of the two executables, the same search returns 230 hits on 0xA000, 7 on 0x388, 4 on 0x389, 300 on the string VIS, 773 on DVA and 1,387 on GDI — every one of them inside .IMV compressed video, where 429,867,008 bytes of high-entropy data contain every three-byte sequence hundreds of times by arithmetic.

The previous session's lesson was that its own dumper's hexadecimal offset column produced eight false hits on a project name. This session's version is larger and the same shape: the loudest scanner in the room was mine. The tool now refuses to print a bare count and prints file names and offsets instead, and the code-pattern search is documented as belonging on executables.

The strings, all of them

Only 39 printable runs of 8 or more bytes in 119,618 bytes, and these are nearly all of them:

0x01BA14  Borland C++ - Copyright 1991 Borland Intl.
0x01BBC2  Could not initialize heap manager.
0x01BC67  There is not enough free memory to play Sherlock.
0x01BCD7  Could not initialize mouse.
0x01BCF3  Please make sure your mouse is connected and the mouse drivers are installed.
0x01BD42  Could not initialize graphics card.
0x01BD66  Please make sure your graphics card is VGA compatible.
0x01BD9E  Could not initialize sound manager.
0x01BDC3  L O A D I N G . . .
0x01BDD7  RESOURCE.DAT
0x01BDF8  There has been a read error on the CD. Please make sure it is inserted.
0x01BE49  QUIT GAME
0x01BE53  Please insert the disk. Click to continue.
0x01CDDE  Could not find Sherlock Holmes data files.

RESOURCE.DAT is the only filename in the executable. Not CDPLAYER.DIB, not NEXTPAGE.DIB, not SOUND.DAT, not GAMESCEN, not HOLMES, not SCENES, and — on a disc that is 96 % of them — not IMV, not once. Every path the program opens comes out of a data file at run time, in the container format of 07-the-container.md, written as .\MC\SCENES\MC1.IMV.

paths.py over all 193 files, coverage 100 %: 36 drive-lettered raw hits, 0 real. All 36 are in .IMVX:\9\9, L:/.7G\u, C:\g\7CC. Zero absolute build paths, zero source-tree paths, and none of the 36 in either executable or any text file. The previous session's row was one path on 28.59 % coverage for a structural reason; this one is zero on 100 %, because a 1992 disc has nothing to hide behind.


MOUSE.COM, and the two Windows bitmaps

MOUSE.COM, 56,448 bytes, is the Microsoft DOS mouse driver*** This is Copyright 1983-1992 Microsoft ***, 636 printable runs of 10+ bytes, HorizontalSensitivity, DoubleThreshold, ActiveAccelerationProfile, CursorDisplayDelay, and a list of language names. It is named first in CONTROL.TAT's program list, with A: in front of it (10-the-vendor-block.md).

CDPLAYER.DIB and NEXTPAGE.DIB, 8,454 bytes each, are the only Windows artefacts on this disc — 16,908 bytes, 0.0038 %. Both parse exactly: BM, declared size == actual, pixel data at 174, 40-byte BITMAPINFOHEADER, 90 × 90, 1 plane, 8 bpp, BI_RGB, stride 92, biSizeImage 8,280 == computed, 174 + 8,280 = 8,454, residue 0, 2 of 2.

And they carry 30 palette entries while their pixels use indices 1 and 231–255. A DIB whose pixels index past its own colour table is a DIB drawn against the Windows system palette — the idiom of a palette-managed Windows 3.1 display, where the top and bottom of the 256 entries are the static system colours. That palette is in the console's ROM, not on this disc, so the true colours of these two files are not recoverable from the disc alone.

Rendered with the file's own thirty colours laid over the range its pixels use, CDPLAYER.DIB is a 90 × 90 circular icon with radial detail — a CD. Neither filename appears in SHI.EXE. They are consumed by something that is not on this pressing, and that makes them the second piece of evidence in 11-the-question.md after the vendor block.