DOS 时代的「安装程序生成器」,1999 年用 C(Turbo / Borland C)写成。
它不是某一个软件的安装程序,而是一套打包 + 安装 + 压缩的小工具链:先把若干 文件压进一个归档,再让一个通用安装器把它们解到用户指定的目录。归档头里写死了 机器卷序列号,换个盘就装不了,算是最朴素的防盗版。
BUILD v1.0 / INSTALL v1.0 / COMPRESS v1.0
Copyright (c) Zhang Weidong, 1999-2000, All Rights Reserved.
这是 Fun 语言作者(张卫东,笔名一了,Wisdom ZHANG)学生时代的早期作品。
| 程序 | 源文件 | 作用 |
|---|---|---|
| BUILD | Build.c |
把多个文件压成一个归档(Archive),写头、写文件名与长度、Huffman 压缩正文 |
| INSTALL | Install.c |
通用安装器:校验归档头,询问安装路径,逐个 Huffman 解压并建目录 |
| COMPRESS | Compress.c |
通用压缩/解压:COMPRESS <A|E> <输入> <输出>,A 压缩、E 解压 |
Build.c 里的 main 已经写好了用法:
BUILD <Archive> <File1> <File2> ...
INSTALL <Archive> [/DEMO]
COMPRESS <A|E> <InputFile> <OutputFile>BUILD MYAPP.EXE A.DAT B.DAT→ 生成归档MYAPP.EXE(注意归档名由你定,后缀随意);INSTALL MYAPP.EXE→ 校验、选目录、逐文件安装;带/DEMO时固定装到 A: 盘,方便演示;- 归档头包含两段 32 位数据:魔术串
"Zwd\x20"(作者缩写 + 空格)与当前机器卷序列号。
目录里有三套并列的静态 Huffman 编码实现,看得出反复改过:
| 头文件 | 角色 |
|---|---|
Huffman1.h |
早期版本:ArraysToList → ListToTree → Coding / TreeToBits |
Huffman2.h |
打包侧:BuildTree → SaveTree → ByteToBits → C_Huffman(BUILD / COMPRESS 用) |
Huffman3.h |
解包侧:LoadTree → TreeToByte → E_Huffman(INSTALL / COMPRESS 用) |
压缩用的是统计 Huffman:先数一遍字节频率建树,把树写进归档,再逐位输出编码。
码流放在一张 Tree(Tree.h)里,位运算在 Bit.h / Bits.h。
File.h:带缓冲的类型化读写(ReadByte/ReadLong/WriteByte/WriteLong), 32KB(0x8000)一块;要求以 COMPACT 内存模式编译(#ifndef __COMPACT__ #error), 因为要一次性malloc两个 32KB 缓冲,large 模式指针太大、small 模式堆不够。Arrays.h/List.h:频率表和链表,用来建树。Line.h:行程编码(RLE)的一个旁支,C_Line/E_Line。Tree.h:Huffman 树的节点与遍历。
Borland / Turbo C(DOS 下或 DOSBox 里),按 COMPACT 模式分别编译三个程序:
bcc -mc Build.c → Build.exe
bcc -mc Install.c → Install.exe
bcc -mc Compress.c → Compress.exe(-mc 即 compact 模式。)注意归档头绑定机器卷序列号,BUILD 与 INSTALL 必须在
同一台机器(或同一个 DOSBox 实例)上配合使用。
GetSerial() 用 INT 21h, AX=6900h 取当前卷的序列号,Build 建归档时写进去,
Install 安装时再取一次比对。对不上就打印 Invalid Copy Software. 并退出——
意思很直白:这个安装包只认打包时那台机器。
Copyright (c) Zhang Weidong, 1999-2000, All Rights Reserved. 源码作为历史存档公开,请自行斟酌用途。
A DOS-era "installer generator", written in C (Turbo / Borland C) in 1999.
It is not one program's installer but a small pack + install + compress toolchain: pack several files into one archive, then let a generic installer unpack them into a user-chosen directory. The archive header pins itself to the machine's volume serial number, so it only installs on the machine it was built on, a plain anti-copy trick.
BUILD v1.0 / INSTALL v1.0 / COMPRESS v1.0
Copyright (c) Zhang Weidong, 1999-2000, All Rights Reserved.
An early work by the author of the Fun programming language (张卫东 / Wisdom ZHANG, pen name 一了).
| Program | Source | Role |
|---|---|---|
| BUILD | Build.c |
Packs several files into one archive: header, per-file name and length, Huffman-coded body |
| INSTALL | Install.c |
Generic installer: verifies the header, asks for a path, Huffman-decodes each file and makes directories |
| COMPRESS | Compress.c |
General compress/extract: COMPRESS <A|E> <input> <output> |
Usage:
BUILD <Archive> <File1> <File2> ...
INSTALL <Archive> [/DEMO]
COMPRESS <A|E> <InputFile> <OutputFile>BUILD MYAPP.EXE A.DAT B.DATproduces the archiveMYAPP.EXE(the name is yours; any extension works).INSTALL MYAPP.EXEverifies, picks a directory and installs file by file;/DEMOpins installation to drive A: for demos.- The archive header carries two 32-bit words: the magic string
"Zwd\x20"(the author's initials plus a space) and the current machine's volume serial number.
Three parallel static-Huffman implementations sit side by side, clearly iterated on:
| Header | Role |
|---|---|
Huffman1.h |
Early: ArraysToList → ListToTree → Coding / TreeToBits |
Huffman2.h |
Packing: BuildTree → SaveTree → ByteToBits → C_Huffman (used by BUILD / COMPRESS) |
Huffman3.h |
Unpacking: LoadTree → TreeToByte → E_Huffman (used by INSTALL / COMPRESS) |
It is statistical Huffman: count byte frequencies, build the tree, write the tree
into the archive, then emit the codes bit by bit. The codes live in a Tree
(Tree.h); bit I/O is in Bit.h / Bits.h.
File.h: buffered typed I/O (ReadByte/ReadLong/WriteByte/WriteLong), 32KB (0x8000) at a time; it requires the COMPACT memory model (#ifndef __COMPACT__ #error), because itmallocs two 32KB buffers at once: large-model pointers are too big, small-model heap is too small.Arrays.h/List.h: frequency tables and a linked list for building the tree.Line.h: a side branch doing run-length coding (C_Line/E_Line).Tree.h: Huffman tree nodes and traversal.
Borland / Turbo C (under DOS or DOSBox), compact model, once per program:
bcc -mc Build.c -> Build.exe
bcc -mc Install.c -> Install.exe
bcc -mc Compress.c -> Compress.exe(-mc is compact model.) The archive header is bound to the volume serial
number, so BUILD and INSTALL must run on the same machine (or the same DOSBox
instance).
GetSerial() reads the volume serial number via INT 21h, AX=6900h. Build
writes it into the archive, and Install reads it again on install and compares.
On mismatch it prints Invalid Copy Software. and exits: the package only
recognises the machine it was built on.
Copyright (c) Zhang Weidong, 1999-2000, All Rights Reserved. Published as a historical archive; use at your own discretion.