TSCrunch V1.3

by Antonio Savona

April 2022


About
=====

TSCrunch is an optimal, byte-aligned, LZ+RLE hybrid encoder, designed to maximize decoding speed on NMOS 6502 and derived CPUs, while keeping decent compression performance (for a bytecruncher, that is).
TSCrunch was designed as the default asset cruncher for the upcoming game A Pig Quest, and, as such, it's optimized for in-memory level compression, but at as of version 1.0 it can also create SFX executables for off-line prg crunching.

Requirements
============

TSCrunch requires python 3.x with scipy library installed, or a windows x64 machine(A pre-compiled windows x64 command line executable is also provided). A GO version is also supplied to facilitate building on your OS of choice. 
The memory decrunchers requires Kick Assembler, but it should be quite easy to port it to your assembler of choice.

Usage
=====

tscrunch [option] infile outfile

Crunching examples:

	tscrunch -x $0820 game.prg crunched.prg
	
Crunches the file game.prg and generates a self executable crunched.prg, using $0820 as post-decrunch jmp address

	tscrunch -p game.prg crunched.bin

Mem-crunches the file game.prg, stripping the 2-byte header and generates a binary file crunched.bin

	tscrunch data.bin crunched.bin
Mem-crunches the file data.bin and generates a binary file crunched.bin

	tscrunch -i data.prg crunched.prg
Mem-crunches the file data.prg for in-place use, and generates a prg file crunched.prg with the appropriate load address


Please refer to the inline help (tscrunch -h) for a detailed description of the different crunching options.
Note that with the exception of self executables and in-place, all the files generated by TSCrunch are headless binaries, that is they don't come with a 2 byte loader offset.

Decrunching files from code
===========================

For memory decrunching, please #include decrunch.asm and include the crunched binaries in your code, then use the macro TS_DECRUNCH, as explained by the following code fragment 

		.pc = $1000 "test"
		//decrunches data to $4000
		:TS_DECRUNCH(compressed_data,$4000) 
		jmp *

		.align $100
		#include "decrunch.asm"
		
		compressed_data:
		.import binary "data.bin"
		

For inplace decrunching, please #define INPLACE before including the decruncher code, as explained by the following code fragment

		#define INPLACE

		.pc = $1000 "test"
		//decrunches data inplace
		:TS_DECRUNCH(compressed_data) 
		jmp *

		.align $100
		#include "decrunch.asm"
		
		.pc = LoadAddress //as provided by the cruncher
		compressed_data:
		.import c64 "data.bin"


decruncher.asm is the recommended decruncher for the general case, but other than it two alternative decrunchers are supplied: a small version, which saves some bytes at the cost of speed, and an extreme version which is generally marginally faster, but comes with a larger footprint. 


Performance
===========

TSCrunch is designed for ultra-fast decrunching while keeping a decent compression ratio. Being a byte-cruncher, it falls short of popular bit-crunchers, such as exomizer or B2, when comparing compression efficiency, but it is usually much faster at decoding. Furthermore, you can expect a 20% to 40% speed bump compared to popular byte-crunchers with similar compression efficiency.
The following benchmark compares TSCrunch performance with those of a fast byte-cruncher, TinyCrunch, and a fast bit-cruncher, B2, on a real-case compression scenario: Chopper Command, from the same author.


Chopper Command - Raw encoding	 - game prg
			
				Tscrunch 1.3	TinyCrunch 1.2	B2
Size			46913			46913			46913
Crunched size	12506			15419			11181
% of original	26.66%			32.87%			23.83%
Decrunch cycles	754733			1133039			1694585
Cycles per byte	16.08792872		24.15191951		36.12186388


Changelog
=========

1.3
-Improved compression adding near-optimal zero-runs and refactoring literals and lz2 tokens
-Improved decrunching speed 
-Added extreme and small decruncher versions, for maximum speed and minimal footprint respectively

1.2
-Added long matches to improve compression with no effect on decrunching speed
-Fixed bug in LZ2 search that would prevent some short matches from being identified 
-Code is available also in Go to improve crunching speed and increase portability

1.1
-Added Inplace compression
-Minor speed improvement 

1.0
-Initial release