LZPACK is an executable compressor for CP/M‑80 binaries.
It shrinks 8080 and Z80 .COM programs, often to half their original size,
while leaving them directly executable: every compressed file is a
self‑extracting .COM that decompresses itself and runs without any
separate decompressor and requires no changes to how the program is invoked.
It works very much like Yoshihiko Mino's classic CP/M‑80 PopCom! utility, but compresses programs tighter by using a better compression engine and decompresses faster by using smaller hand‑optimized decompression stubs.
The LZPACK program itself as well as the compressed executables it produces can run on a wide range of CP/M‑80 machines, including systems with Z80, 8080, 8085, and V20 processors, and systems with less than 48K TPA.
Running the compressor on a system without CP/M‑80's memory constraints (such as on MS‑DOS, OS/2, Windows, Linux, BSD, or in most other UNIX‑like environments) gives even better compression results.
- Overview
- Details
- Usage
- Downloads
- Platform notes
- Building from source
- Security
- SAST and linters
- Code statistics
- License
LZPACK is a single, ultra‑portable ANSI C89 program.
The compressor runs on just about anything with an ANSI C89 compiler. You can compress CP/M‑80 programs on any modern UNIX (even ELKS), OS/2, Windows, or MS‑DOS system without emulation, as well as compress natively on the CP/M‑80 target.
The decompressor that is embedded into each compressed executable is hand‑written and highly optimized 8080 or Z80 assembly.
Precompiled binaries are provided for CP/M‑80 (8080 and Z80), CP/M‑86 (8086/8088), MS‑DOS (16‑bit 8086/8088 real‑mode and 32‑bit 386 DPMI), ELKS (8086/8088), OS/2 (32‑bit), Linux (32‑bit i386, 32‑bit ARMv5, 64‑bit x86‑64, and 64‑bit ARMv8), Atari ST (TOS/MINT), AmigaOS (68K), and Windows (both 32‑ and 64‑bit versions).
The CP/M‑80 builds also run on MSX‑DOS (as do the compressed executables LZPACK generates).
LZPACK's ‑R (restore) and ‑L (list) commands recognize both LZPACK
and PopCom!‑compressed files (as they use the same container and stream
format), making it simple to decompress (and recompress) already
compressed executables.
LZPACK (and LZPACK‑compressed binaries) can run on a plain 8080, not just the Z80. LZPACK analyzes the file to be compressed and automatically detects if the program might execute Z80 instructions, and picks a matching decompression stub.
Users can also specify ‑8 to explicitly use the 8080 stub, or ‑Z to force
the Z80 stub, in case the automatic detection gets it wrong (which can happen).
For example, the CP/M‑80 LZPACK program itself (when built for 8080) is
misdetected as a Z80 binary due to the Z80 opcode scanning routines embedded in
the executable.
While compressed 8080 programs using the 8080 stub will run on any 8080 (or 8085) system, they can sometimes be compressed smaller by using the Z80 stub, at the cost of 8080 compatibility. If you aren't compressing executables for public distribution, you might want to use the Z80 stub unconditionally if you have a Z80‑powered system.
LZPACK also includes a hand‑written and size‑optimized 8086/8088 assembly
decompressor used for the ‑R (restore) feature when built for 8086/8088
targets such as CP/M‑86, real‑mode MS‑DOS, and ELKS. This is not only faster
than the ANSI C89 version but also smaller, which leaves more memory available
for compression.
For extremely memory‑constrained systems, custom builds can be created that
completely exclude the ‑R decompression code, which might save a few
precious bytes.
LZPACK should build easily anywhere from source code, and needs only an ANSI C89‑conforming compiler, without requiring any external assemblers. The source repository does not include any binary blobs. Instead, the 8080 and Z80 stubs are assembled from their included sources during the build process using an included custom assembler, StubASM, also written in portable C89.
Tip
If you are looking for a stand‑alone 8080/Z80 assembler, it is suggested to use TPZASM rather than adapting StubASM for this purpose. StubASM is recommended if you are looking to add an 8080/Z80 assembly build stage to an existing software project.
LZPACK may not be the smallest executable compressor, nor the most technically impressive, but it is permissively licensed, portable (able to run on machines ranging from tiny CP/M‑80 systems to current workstations running any operating system), and extremely compatible (without depending on undefined behavior or undocumented functionality of any hardware or software).
The table below compares LZPACK against PopCom! 1.0 (the most popular CP/M‑80 executable compressor) on a few real‑world CP/M‑80 executables.
| Program | Original | PopCom! | LZPACK/N | LZPACK/N+ | LZPACK/C |
|---|---|---|---|---|---|
BLS |
19,210 |
12,160 (‑36.7%) |
11,890 (‑38.1%) |
11,884 (‑38.1%) |
11,945 (‑37.8%) |
FORTH80 |
8,136 |
6,272 (‑22.9%) |
6,094 (‑25.1%) |
6,093 (‑25.1%) |
6,106 (‑25.0%) |
M80 |
20,023 |
13,952 (‑30.3%) |
13,711 (‑31.5%) |
13,702 (‑31.6%) |
13,755 (‑31.3%) |
MBASIC |
24,313 |
19,456 (‑20.0%) |
19,182 (‑21.1%) |
19,178 (‑21.1%) |
19,239 (‑20.9%) |
PILOT |
30,902 |
13,184 (‑57.3%) |
12,798 (‑58.6%) |
12,792 (‑58.6%) |
12,876 (‑58.3%) |
SARGON |
14,592 |
8,704 (‑40.4%) |
8,598 (‑41.1%) |
8,593 (‑41.1%) |
8,619 (‑40.9%) |
VDT1398 |
17,443 |
13,056 (‑25.2%) |
12,876 (‑26.2%) |
12,874 (‑26.2%) |
12,914 (‑26.0%) |
VDT139Z |
16,485 |
12,544 (‑23.9%) |
12,333 (‑25.2%) |
12,325 (‑25.2%) |
12,371 (‑25.0%) |
VDT232Z |
24,304 |
18,688 (‑23.1%) |
18,437 (‑24.1%) |
18,430 (‑24.2%) |
18,500 (‑23.9%) |
WS30 |
15,872 |
11,648 (‑26.6%) |
11,427 (‑28.0%) |
11,425 (‑28.0%) |
11,455 (‑27.8%) |
ZORK1 |
8,426 |
5,376 (‑36.2%) |
5,280 (‑37.3%) |
5,276 (‑37.4%) |
5,297 (‑37.1%) |
-
The "/N" builds are native Linux x86_64; the "/C" builds are CP/M‑80.
-
LZPACK beats PopCom! on every file in every configuration.
-
The "/N+" column is the extra compression (
‑Emode). On a memory‑rich host, it parses the whole file at once and almost always beats the standard mode by at least a few bytes (/N+ vs. /N). -
The /C figures were measured under
tnylpo(with a ~63K TPA). On CP/M‑80 (or any other memory‑constrained system), the window sizes and compression ratio scale with the available memory: a small TPA means a small compression window and somewhat larger output. Currently any Z80 system with ~49K TPA and any 8080 system with ~52K TPA is able to run the "full strength" (8K window) compressor. See the following table for compression window size vs. available TPA:System 1K‑window 2K‑window 4K‑window 8K‑window Z80 28,315(27.6K)31,387(30.6K)37,531(36.6K)49,819(48.6K)8080 31,292(30.5K)34,364(33.5K)40,508(39.5K)52,796(51.5K) -
The test files were "trimmed" to their "near‑exact" length on the Linux host system used for testing (determined by discarding up to, but not including, the final
0x00or0x1Abytes in the last 128‑byte "record"). -
On CP/M 2.2 systems, files do not have exact lengths but instead occupy fixed‑size records of 1024 bits (128 bytes). When LZPACK is operating on CP/M‑Plus (CP/M‑80 or CP/M‑86 3+) or DOS‑Plus (CP/M‑86 4+), the LRBC (Last Record Byte Count) metadata is used to determine how many bytes of the final record should be compressed. On CP/M 2.2 systems, all bytes in the final record are compressed. PopCom! does not support sizing according to the LRBC and always compresses all bytes of the final record.
-
Because the
tnylpoandcpmemulators used for testing do not emulate CP/M‑Plus (and thus do not provide LRBC metadata), any file not ending at an exact record boundary would be automatically padded to the size of the next full record. Theiz‑cpmemulator (using‑‑cpm3) does support the LRBC if testing is needed.
Because every compressed program must include a copy of the decompression stub, it is vital that the code be as small (and fast) as possible. The table below compares the sizes of the LZPACK decompression stubs against those from PopCom!.
| CPU | PopCom! | LZPACK |
|---|---|---|
| Z80 | 230 bytes |
180 bytes |
| 8080 | (Unsupported) | 238 bytes |
- LZPACK's Z80 code is just 180 bytes (including setup code) versus PopCom!'s 230 bytes, over 21% smaller.
- PopCom! has no 8080 support at all, while LZPACK's pure 8080 decompressor weighs in at only ~3% larger than the PopCom! Z80 code.
When a compressed program is invoked, the CP/M loader places it at 0x100 and
a JP at the entry redirects control to the decompression stub, which then:
- Restores the 16 original header bytes the decompressor has saved,
- Relocates the compressed payload and the decompression stub into the high end of the TPA, so the stub can run without overwriting itself,
- Decompresses in‑place into the TPA, writing output from
0x110upward, and - Jumps back to
0x100to run the decompressed executable image.
Important
This scheme does not currently support CP/M‑Plus / CP/M‑3+
GENCOM‑processed executables which use pre‑initialization code or have
attached RSXs. These programs have a header (the first byte is C9h which
is RET, to prevent them from running on CP/M 2.2). LZPACK detects
the GENCOM header and refuses to compress (giving a GENCOM unsupported
error). You should use the GENCOM utility to convert these executables to
standard CP/M executables if possible (i.e., no pre‑init code, or RSXs)
before compressing with LZPACK. Support for some GENCOM‑processed
CP/M‑Plus executables may be added in a future LZPACK release.
LZPACK compresses using a cost‑optimal shortest‑path parser and includes two implementations:
-
The in‑memory implementation loads the entire file into RAM and finds matches with a hash‑chain over the entire file. It is used by native, 32‑bit and 64‑bit Windows, 32‑bit OS/2, and 386 DPMI MS‑DOS builds.
-
The streaming implementation reads the input through a sliding window and writes the output to a temporary file, so its working memory is independent of the file size. This lets memory‑constrained systems (e.g., CP/M‑80, CP/M‑86, real‑mode MS‑DOS, and ELKS) compress arbitrarily large executables.
Each implementation has two modes, which trade memory for size:
-
The standard compression mode uses a small parse block, keeping its working set tiny and leaving the most room for a large match window.
-
The extra compression mode (
‑E) enlarges the block for the tightest possible parse.
On a memory‑rich host, using ‑E trims down files by at least a few more
bytes. On CP/M‑80 systems, due to memory constraints, the ‑E option is
not available.
LZPACK includes four independent (but equivalent) decompression engines, differing in execution speed, code size, and memory usage:
-
The standard portable decompression engine is written in pure ANSI C89.
-
The 8080 assembly‑language decompression engine (built by StubASM).
-
The Z80 assembly‑language decompression engine (also built by StubASM).
-
The 8086 assembly‑language decompression engine, used for the
‑Rrestore option on 8086/8088 systems (i.e., CP/M‑86, MS‑DOS, and ELKS).
The 8086 decompression engine source code is automatically generated by the
build system, which works by transforming a shared assembly routine into the
proper dialect for the target (currently GNU as,
Watcom wasm, or Aztec #asm), so no additional assemblers or
tools are required when cross‑compiling.
-
While LZPACK‑generated executables are often smaller, more compatible, and always decompress faster than those produced by PopCom!, the LZPACK compressor is much slower than PopCom!'s, especially on vintage hardware: PopCom! uses hand‑written Z80 assembly language, whereas LZPACK uses portable ANSI C89 to implement a cost‑optimal parser that does far more work per byte.
-
LZPACK prioritizes the smallest output with the fastest possible decompression, because decompression happens every time the compressed program is run, while compression (usually) happens rarely, especially now that the compression need not be performed on vintage systems, but on modern hardware (which almost everyone has now, in the year 2026).
LZPACK v1.08 - CP/M-80 (8080 and Z80) executable compressor
Copyright (c) 2026 Jeffrey H. Johnson <johnsonjh.dev@gmail.com>
Usage:
lzpack [-E] [-8|-Z] <file> compress (-E: extra, -8/-Z: force 8080/Z80 stub)
lzpack -R <file> restore (decompress)
lzpack -L <file> list stored sizes
lzpack -O <name> set output name
lzpack -M <top> set memory top (default 48K)
lzpack -C stub verifies memory at run time
lzpack -F <floor> require memory top >= floor (implies -C)
lzpack -V show LZPACK information
The CP/M‑80 version of LZPACK is split into two utilities:
LZPACK.COMfor compression only, andLZUNPACK.COMfor decompression and listing.
On all other platforms, a single lzpack tool is provided, as shown above.
As a compressed program decompresses in place on the target machine, the image
expands to its full original size at 0x100 with the relocated decompressor
sitting above it. At compression time, LZPACK verifies that everything
fits below a memory ceiling (MEMTOP), and will refuse to produce an output
file otherwise. The default is at 0xBDFF, so all compressed programs are
guaranteed to run on any 48K TPA system. The ‑M option can be used
to override this:
- Use
‑M 64to compress programs too large for 48K TPA, but the result requires a correspondingly larger TPA at run time. - Use
‑M 32(or less) to guarantee the output runs on smaller systems, or to keep the decompressor away from any resident driver (that might have stolen the top of the TPA), or to enforce a maximum image size while developing new software.
The ‑M option accepts an argument in three formats:
| Format | Example | Description |
|---|---|---|
| KB size (≤64) | ‑M 32 (or ‑M 32K) |
kilobytes (48 is default) |
| hex address | ‑M 0x7DFF |
literal MEMTOP address |
| decimal address | ‑M 65023 |
literal MEMTOP address (>64) |
Values below 0x1190 (4K) or above 0xFFFF (64K) are rejected.
LZPACK may suggest a "worst case" estimated value to try if ‑M is
required but was not supplied.
The compression‑time checks cannot know the details of the machine the
compressed program will eventually run on; for example, it might have a much
smaller TPA than the one running the compressor, or it might have a resident
driver that lowers the BDOS pointer at 0x0006 (which could be silently
overwritten during decompression). The ‑C option enhances the stub with
a small (48‑byte) runtime check. It verifies that the highest address the
decompressor will write to lies below the BDOS base and that at least 24 bytes
are clear of the live inherited stack. If the program does not fit, it
prints No room and aborts.
Because this check adds an extra 48 bytes to every compressed executable, it is
disabled by default. Enabling it does not consume any high memory, and it
is never relocated, so it will not change what fits with any given
‑M setting.
The ‑F option is mostly useful to developers of CP/M‑80 software and
not end‑users.
Expand this section for further details.
The ‑C option adds a check that refuses a TPA that the decompressor would
overrun, but a compressed program almost always needs more memory to actually
run than it does to simply decompress. With a TPA that sits between those
two bounds, the program decompresses successfully but then crashes (or silently
corrupts memory) during its own startup (which would still happen even in
the absence of any executable compression).
When the decompressor is informed of the actual program runtime memory
requirements via the ‑F option, the check stub (normally emitted with ‑C)
can cleanly refuse to run on a machine whose memory top lies below the
specified floor. The argument accepts the same formats as ‑M (and
implies ‑C).
Most CP/M users wishing to save space on their disks will be compressing
existing programs and will never need to use ‑F. Developers who are
creating CP/M software (who ship compressed executables), especially when
working with compiled languages, can greatly benefit. For most CP/M‑80
programs, the size of the executable on the disk is not representative of the
actual runtime footprint, and the language runtimes for most high‑level
languages setup stack and heap before any user code (e.g., main()) runs.
Potential trouble can happen at this early stage in tight memory situations,
there is no in‑program check a developer can easily add to their programs
without using completely custom startup code. A program might start but not
work correctly, or just crash without any useful error messages displayed
at all.
Finding the floor value to use is an extra step at release: read the end of static storage from the linker's map and add the runtime's stack reserve, or if you are cross‑developing, simply measure the value empirically by using an emulator that can dynamically shrink the TPA.
It is hoped that the LZPACK build can serve as an example of this process,
since the shipped CP/M‑80 binaries (LZPACK.COM and LZUNPACK.COM) are
compressed with a floor derived from each tool's own map plus the stack
reserve, so on any system with a TPA large enough for them to decompress
successfully but too small for them to fully initialize and run user code,
they simply print No room and exit cleanly, which would be impossible to
achieve using C code alone.
The ‑L (list) command reads the check code out of a compressed executable.
It reports no ‑C check for files compressed without ‑C, and the enforced
floor for checked files (‑C check; floor 0xBDFF).
It also reports the self‑extractor's architecture (Z80 or 8080), recognized by the stub bytes themselves, not by full program analysis. Files with an unrecognized stub (foreign tools, uncompressed executables, or possibly newer versions of LZPACK) will not display the architecture.
On CP/M‑80 systems the list option is in the LZUNPACK.COM executable, so
the embedded floor of any compressed program can be inspected on a
CP/M‑80 system.
| File | Size | Platform |
|---|---|---|
| LZPCKI80.ARC | 24 KiB | CP/M‑80 (8080) |
| LZPCKZ80.ARC | 24 KiB | CP/M‑80 (Z80) |
| LZPCK86C.ARC | 20 KiB | CP/M‑86 (8086/8088) |
| LZPCKELK.Z | 16 KiB | ELKS (8086/8088) |
| LZPCK86R.ZIP | 20 KiB | MS‑DOS (8086/8088) |
| LZPCK86P.ZIP | 76 KiB | MS‑DOS (80386 DPMI) |
| LZPACKST.LZH | 132 KiB | Atari ST (TOS/MINT) |
| LZPACKAM.LHA | 40 KiB | AmigaOS (68K) |
| LZPCKOS2.ZIP | 20 KiB | OS/2 (32‑bit i386) |
| LZPCKW32.ZIP | 40 KiB | Windows (32‑bit MSVCRT) |
| LZPCKW64.ZIP | 24 KiB | Windows (64‑bit UCRT) |
| LZPCKA32.gz | 32 KiB | Linux (32‑bit ARMv5) |
| LZPCKA64.gz | 40 KiB | Linux (64‑bit ARMv8) |
| LZPCKL32.gz | 16 KiB | Linux (32‑bit i386) |
| LZPCKL64.gz | 40 KiB | Linux (64‑bit x86‑64) |
Tip
If you need a CP/M ARC utility, UNARC is available for
8080
and
Z80
CP/M‑80, and ARC86 for
CP/M‑86.
If you need an Atari ST LHA/LZH utility, LHarc is available for
TOS/MINT.
The CP/M‑86 version of LZPACK supports wildcard expansion, checking against the current drive's directory. Any drive letter specified in the pattern is ignored and the current drive is always searched.
To keep CP/M‑80 versions as small as possible, wildcard expansion is disabled
by default, but can be enabled in custom builds using ‑DLZPACK_WILDCARD=1.
The 386 DPMI MS‑DOS and Windows versions fully support wildcard expansion.
The real‑mode MS‑DOS version does not expand wildcards.
LZPACK needs only an ANSI C89 compiler to build on any UNIX‑like system.
-
To build a native binary, just run
make(orgmake), which builds StubASM, assembles the stubs, and then compileslzpack:make
-
You can also explicitly set
CC,CFLAGS,LDFLAGS, etc. For example, to build an optimized 64‑bit binary on IBM AIX using the IBM XL C/C++ compiler and AIXmake:make CC=xlc CFLAGS="-O3 -q64" LDFLAGS="-Wl,-b64"
-
To build a native binary on Windows using the Microsoft Visual Studio C/C++ compiler, from a Developer Command Prompt for Visual Studio window, run:
msvcbuild.bat
The GNU GCC, LLVM Clang, PCC, NVIDIA HPC SDK C/C++, Oracle Studio C/C++, DMD ImportC, CompCert C, Open64, PathScale EKOPath, IBM XL C/C++, DJGPP, Vbcc, Ack, IBM Open XL C/C++, МЦСТ LCC, and Microsoft Visual C/C++ compilers are regularly tested.
The following targets build various lzpack binaries.
Most users will only be interested in the native binary build.
| Make Target | Description | Toolchain |
|---|---|---|
all |
Native binary | ANSI C89 compiler (e.g., c89, gcc, clang) |
cpm |
CP/M‑80 8080 + Z80 | z88dk (2026‑07‑10+) and patched tnylpo |
cpm86 |
CP/M‑86 8086/8088 | cross‑Aztec C86 v4.2 (tsupplis) |
os2 |
OS/2 i386 | Open Watcom V2.0 |
msdos |
MS‑DOS 8086/8088 | Open Watcom V2.0 |
djgpp |
MS‑DOS 80386 | DJGPP and CWSDPMI |
elks |
ELKS 8086/8088 | IA16‑GCC |
atari |
Atari ST TOS/MINT | Crossmint |
amiga |
AmigaOS 68K | Vbcc |
windows |
Windows 32/64‑bit | MinGW‑w64 GCC |
The following targets will likely only be of interest to developers:
| Make Target | Description |
|---|---|
stubs |
Builds only StubASM and the 8080 + Z80 stubs |
test |
Runs a comprehensive end‑to‑end multiplatform test suite |
lint |
Source‑code quality checks (linting and static analysis) |
tags |
Builds source code tags (etags, ctags, gtags, cscope) |
The CP/M‑80 build targets support running z88dk in the usual way or via
Docker. Setting the environment variable CPM_BACKEND=local forces a
standard build and setting CPM_BACKEND=docker forces the Docker‑ized build.
If the CPM_BACKEND environment variable is unset, a proper z88dk
invocation will be automatically determined by the build system.
Other build targets are available; review the Makefile for
complete details.
Important
The complete CP/M‑80 build (which automatically sets and verifies the
‑M and ‑F values) requires a patched version of
Georg Brein's tnylpo emulator
available in your PATH.
-
make lintneeds only a POSIX shell to run (plus whichever linters and static analysis tools it invokes). You'll be informed of any missing prerequisites as well as any optional tools when you invokemake lint. -
make testrequirespython3, several emulators, and many cross‑toolchains installed if you want to run all the tests (of which there are several hundred). At a minimum, you need both a patched version of Georg Brein'stnylpoemulator and Joe Hallen'scpmemulator installed. You should build these with full optimizations enabled, as the test suite is extensive with a lengthy runtime. -
If you would like to contribute to LZPACK development, it is extremely important that you have all of the optional linters, static analysis tools, emulators, and cross‑toolchains installed, and that both
make lintandmake testpass completely clean, as this is a prerequisite for any change. Every linter has, at some point, caught real bugs in the code. -
Usage of AI (artificial intelligence) tools by contributors is currently permitted, subject to the same terms and conditions as the LLVM AI Tool Use Policy, but this permission may be withdrawn at any time and without notice.
- The canonical home of this software is
https://github.com/johnsonjh/lzpack, with a mirror athttps://gitlab.com/johnsonjh/lzpack. - This software is intended to be secure 🛡️.
- If you find any security‑related problems, please don't hesitate to open a GitHub Issue.
The following static analysis and dynamic verification tools are used as part
of the comprehensive LZPACK testing process (with many invoked
automatically via the make lint target):
| Tool | Usage |
|---|---|
| PVS‑Studio | Static analysis tool for C, C++, C#, and Java code |
| Clang Analyzer, Sanitizers | Static and dynamic analysis tools for C, C++, and Objective‑C code |
| Cppcheck | Static analysis tool for C and C++ code |
| Dr. Memory | Memory debugging tool for Windows, Linux, macOS, and Android |
| DUMA | Detect Unintended Memory Access, a memory debugger |
| Flawfinder | Scans C and C++ source code for potential security weaknesses |
| Funcheck | A tool for checking function call return protections |
| GCC Static Analyzer | Coverage‑guided symbolic execution static analyzer for C code |
| GNU Global | Source code indexing and tagging system |
| GNU Cppi | C preprocessor directive linting, indenting, and regularization |
| IBM AIX lint | Checks C and C++ language programs for potential problems |
| NetBSD lint(1) | A C (C90/C99/C11/C17/C23) program verifier |
| Oracle Developer Studio | Performance, security, and analysis tools for C, C++, and FORTRAN |
| PurifyPlus | Run‑time analysis tools for application reliability and performance |
| REUSE | Verifies compliance with the REUSE software licensing guidelines |
| Semgrep | A fast, open‑source, static analysis engine for many languages |
| ShellCheck | A static analysis tool for Unix shell scripts |
| Smatch | Smatch (Source Matcher) is a static analysis tool for C code |
| SoftIntegration Ch | C/C++ interpreter and interactive platform for scientific computing |
| Valgrind | Tools for memory debugging, memory leak detection, and profiling |
| Visual Studio Code Analyzer | Tools to analyze and improve C/C++ source code quality |
Code statistics 📈 generated by scc:
| Language | Files | Lines | Blank | Comment | Code | Complexity | Bytes | Uloc |
|---|---|---|---|---|---|---|---|---|
| C | 5 | 8999 | 1897 | 739 | 6363 | 1366 | 204831 | 3570 |
| Shell | 8 | 4017 | 581 | 594 | 2842 | 497 | 116446 | 1414 |
| Python | 2 | 1307 | 110 | 232 | 965 | 342 | 51970 | 920 |
| Makefile | 3 | 1143 | 187 | 234 | 722 | 214 | 40929 | 647 |
| Assembly | 8 | 1052 | 87 | 280 | 685 | 0 | 42866 | 608 |
| Patch | 1 | 212 | 8 | 0 | 204 | 0 | 6070 | 174 |
| C Header | 1 | 72 | 15 | 27 | 30 | 1 | 1869 | 39 |
| Messages | 1 | 67 | 0 | 0 | 67 | 0 | 6229 | 67 |
| Batch | 1 | 33 | 7 | 17 | 9 | 0 | 994 | 27 |
| Total | 30 | 16902 | 2892 | 2123 | 11887 | 2420 | 472204 | 7412 |
This software is distributed under the terms of the permissive MIT No Attribution (MIT‑0) License.
While not legally required, giving me credit if you benefit from this code is highly appreciated.