diff --git a/Content/Batty/b48v.bin b/Content/Batty/b48v.bin deleted file mode 100644 index 1cd2fb8..0000000 Binary files a/Content/Batty/b48v.bin and /dev/null differ diff --git a/Content/Batty/batty.tap b/Content/Batty/batty.tap deleted file mode 100644 index 67318ab..0000000 Binary files a/Content/Batty/batty.tap and /dev/null differ diff --git a/Content/Batty/debuild.sh b/Content/Batty/debuild.sh deleted file mode 100644 index a6840be..0000000 --- a/Content/Batty/debuild.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# скрипт извлечения ресурсов из TAP файла с помощью tzxlist - -TAP_FILE="batty.tap" - -echo "Извлекаем блоки из $TAP_FILE..." - -tzxlist -d 2 "$TAP_FILE" -tzxlist -d 3 "$TAP_FILE" - -# Переименовываем в понятные имена -mv 00000002.dat screen.scr # картинка -mv 00000003.dat main.bin # код игры -rm *.dsc -rm *.hdr - -rm *.zx0 -./../tools/zx0/build/zx0 screen.scr -./../tools/zx0/build/zx0 main.bin - -# main.bin -> 0x6800 (26624) точка входа в main - -ls -la \ No newline at end of file diff --git a/Content/Makefile b/Content/Makefile deleted file mode 100644 index 9de403f..0000000 --- a/Content/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -SJASMPLUS=sjasmplus - -build: clean - mkdir -p build - @${SJASMPLUS} ./ram_part.asm --syntax=F - @${SJASMPLUS} ./main.asm --syntax=F -# @${SJASMPLUS} ./test.asm --syntax=F - -clean: -# @rm -f -r ./assets/*.zx0 - @rm -f -r build - - -# ./tools/zx0/build/zx0 ./assets/Spec.scr -# ./tools/zx0/build/zx0 ./assets/Arsen.scr -# ./tools/zx0/build/zx0 ./assets/Jura.scr -# tape2wav ./build/GBX2601.tap ./build/GBX2601.wav -# run: -# fuse --machine 128 -g 3x --tape ./build/GBX2601.tap -# assets: diff --git a/Content/main.asm b/Content/main.asm deleted file mode 100644 index c7d447c..0000000 --- a/Content/main.asm +++ /dev/null @@ -1,91 +0,0 @@ -; 19 Feb 2026 -; Михаил Каа - - DEVICE ZXSPECTRUM48 - ORG 0 - -start: - di - ld sp, 0xffff - jp main - - ORG 100 -main: - ld bc, 0x7ffd - ld a, 0b00010000 - ld (0x5B5C), a - out (c), a - - ld bc, 0xdf7f - ld a, 0b00000001 - out (c), a - - ld hl, 16384 - ld de, 16385 - ld bc, 49151 - ld (hl), 0 - ldir - - ld hl, batty_scr - ld de, 0x4000 - call dzx0_standard - - ld hl, batty_bin - ld de, 0x6800 - call dzx0_standard - - ld hl, bvars - ld de, 0x5c00 - ld bc, bvars_end - bvars - ldir - - ld hl, ram_part - ld de, 0x6700 - ld bc, ram_part_end - ram_part - ldir - - ; ld bc, 65535 - ; call delay - ; ld bc, 65535 - ; call delay - ; ld bc, 65535 - ; call delay - ; ld bc, 65535 - ; call delay - - jp 0x6700 - - jp main - -; Процедура задержки -; bc - время -; delay: -; dec bc -; ld a, b -; or c -; jr nz, delay -; ret - - INCLUDE "./tools/zx0/z80/dzx0_standard.asm" - -batty_scr: - INCBIN "./Batty/screen.scr.zx0" - -batty_bin: - INCBIN "./Batty/main.bin.zx0" - -ram_part: - INCBIN "./build/ram_part_6700.bin" -ram_part_end - -bvars: - INCBIN "./Batty/b48v.bin" -bvars_end - -end: - ; Выводим размер бинарника. - display "Cartridge BIOS code size: ", /d, end - start - display "Cartridge BIOS code start: ", /d, start - display "Cartridge BIOS code end: ", /d, end - - SAVEBIN "build/bios_0000.bin", start, 16384 diff --git a/Content/ram_part.asm b/Content/ram_part.asm deleted file mode 100644 index 0dbe12c..0000000 --- a/Content/ram_part.asm +++ /dev/null @@ -1,31 +0,0 @@ -; 19 Feb 2026 -; Михаил Каа - - DEVICE ZXSPECTRUM48 - ORG 0x6700 - -start: - ld bc, 0xbf7f - ld a, 0b10000000 - out (c), a - - ld sp, 0x6000 - - ld iy, 23610 - -wait_any_key: - ld bc, 0x00fe - in a, (c) - and 0x1f - cp 0x1f - jr z, wait_any_key - - jp 0x6800 - -end: - ; Выводим размер бинарника. - display "ram_part code size: ", /d, end - start - display "ram_part code start: ", /d, start - display "ram_part code end: ", /d, end - - SAVEBIN "./build/ram_part_6700.bin", start, end - start diff --git a/Content/test.asm b/Content/test.asm deleted file mode 100644 index 0cb3b0e..0000000 --- a/Content/test.asm +++ /dev/null @@ -1,48 +0,0 @@ -; Простейший тест переключения банков для карика -; Банк 0 всегда в 0000-1FFF, переключаемый в 2000-3FFF -; Цикл: переключить банк, прочитать байт из 2000h, повторить - - DEVICE ZXSPECTRUM48 - - ORG 0 -start: - di - jp main - - ; векторы RST (просто возврат) - ORG 0x08 - ret - ORG 0x10 - ret - ORG 0x18 - ret - ORG 0x20 - ret - ORG 0x28 - ret - ORG 0x30 - ret - ORG 0x38 - ret - - ORG 0x100 -main: - ld bc, 0xdf7f ; порт выбора банка - ld d, 0 ; начальный банк -loop: - ld a, d - out (c), a ; переключить банк - nop ; небольшая пауза - nop - ld hl, 0x2000 - ld a, (hl) ; прочитать первый байт банка - inc d ; следующий банк - jr loop - -end: - ; Выводим размер бинарника. - display "test code size: ", /d, end - start - display "test code start: ", /d, start - display "test code end: ", /d, end - - SAVEBIN "build/test_0000.bin", start, 16384 \ No newline at end of file diff --git a/Content/tools/zx0/LICENSE b/Content/tools/zx0/LICENSE deleted file mode 100644 index a0b5162..0000000 --- a/Content/tools/zx0/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2021, Einar Saukas -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Content/tools/zx0/Makefile b/Content/tools/zx0/Makefile deleted file mode 100644 index bb4bb65..0000000 --- a/Content/tools/zx0/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -# We only allow compilation on linux! -ifneq ($(shell uname), Linux) -$(error OS must be WSL or Linux!) -endif - -CC = gcc -#CFLAGS = -ox -ob -ol+ -onatx -oh -zp8 -g0 -Ofast -oe -ot -Wall -xc -s -finline-functions -floop-optimize -fno-stack-check -march=i386 -mtune=i686 -CFLAGS = -Wall -RM = rm - -all: build_dir zx0 dzx0 - -build_dir: - mkdir -p build - -zx0: - $(CC) $(CFLAGS) -o build/zx0 src/zx0.c src/optimize.c src/compress.c src/memory.c - -dzx0: - $(CC) $(CFLAGS) -o build/dzx0 src/dzx0.c - -clean: - # Remove everything except source files - rm -r -f build diff --git a/Content/tools/zx0/README.md b/Content/tools/zx0/README.md deleted file mode 100644 index 6f36c0e..0000000 --- a/Content/tools/zx0/README.md +++ /dev/null @@ -1,476 +0,0 @@ -# ZX0 - -**ZX0** is an optimal data compressor for a custom -[LZ77/LZSS](https://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Storer%E2%80%93Szymanski) -based compression format, that provides a tradeoff between high compression -ratio, and extremely simple fast decompression. Therefore it's especially -appropriate for low-end platforms, including 8-bit computers like the ZX -Spectrum. - -A comparison with other compressors (courtesy of **introspec/spke**) can be seen -[here](https://www.cpcwiki.eu/forum/programming/new-cruncher-zx0/msg197727/#msg197727). - - -_**WARNING**: The ZX0 file format was changed in version 2. This new format allows -decompressors to be slightly smaller and run slightly faster. If you need to compress -a file to the old "classic" file format from version 1, then execute ZX0 compressor -using parameter "-c"._ - - -## Usage - -To compress a file, use the command-line compressor as follows: - -``` -zx0 Cobra.scr -``` - -This will generate a compressed file called "Cobra.scr.zx0". - -Afterwards you can choose a decompressor routine in assembly Z80, according to -your requirements for speed and size: - -* "Standard" routine: 68 bytes only -* "Turbo" routine: 126 bytes, about 21% faster -* "Fast" routine: 187 bytes, about 25% faster -* "Mega" routine: 673 bytes, about 28% faster - -Finally compile the chosen decompressor routine and load the compressed file -somewhere in memory. To decompress data, just call the routine specifying the -source address of compressed data in HL and the target address in DE. - -For instance, if you compile the decompressor routine to address 65000, load -"Cobra.scr.zx0" at address 51200, and you want to decompress it directly to the -screen, then execute the following code: - -``` - LD HL, 51200 ; source address (put "Cobra.scr.zx0" there) - LD DE, 16384 ; target address (screen memory in this case) - CALL 65000 ; decompress routine compiled at this address -``` - -It's also possible to decompress data into a memory area that partially overlaps -the compressed data itself (only if you won't need to decompress it again later, -obviously). In this case, the last address of compressed data must be at least -"delta" bytes higher than the last address of decompressed data. The exact value -of "delta" for each case is reported by **ZX0** during compression. See image -below: - -``` - |------------------| compressed data - |---------------------------------| decompressed data - start >> <---> - delta -``` - -For convenience, there's also a command-line decompressor that works as follows: - -``` -dzx0 Cobra.scr.zx0 -``` - - -## Performance - -The **ZX0** optimal compressor algorithm is fairly complex, thus compressing -typical files can take a few seconds. During development, you can speed up this -process simply using **ZX0** in "quick" mode. This will produce a non-optimal -larger compressed file but execute almost instantly: - -``` -zx0 -q Cobra.scr -``` - -This way, you can repeatedly modify your files, then quickly compress and test -them. Later, when you finish changing these files, you can compress them again -without "quick" mode for maximum compression. Notice that using "quick" mode -will only affect the size of the compressed file, not its format. Therefore -all decompressor routines will continue to work exactly the same way. - -Fortunately all complexity lies on the compression process only. The **ZX0** -compression format itself is very simple and efficient, providing a high -compression ratio that can be decompressed quickly and easily. The provided -**ZX0** decompressor routines in assembly Z80 are small and fast, they only use -main registers (BC, DE, HL, AF), consume very little stack space, and do not -require additional decompression buffer. - -The provided **ZX0** decompressor in C writes the output file while reading the -compressed file, without keeping it in memory. Therefore it always use the same -amount of memory, regardless of file size. Thus even large compressed files can -be decompressed in very small computers with limited memory, even if it took -considerable time and memory to compress it originally. It means decompressing -within asymptotically optimal space and time O(n) only, using storage space O(n) -for input and output files, and only memory space O(w) for processing. - - -## File Format - -The **ZX0** compressed format is very simple. There are only 3 types of blocks: - -* Literal (copy next N bytes from compressed file) -``` - 0 Elias(length) byte[1] byte[2] ... byte[N] -``` - -* Copy from last offset (repeat N bytes from last offset) -``` - 0 Elias(length) -``` - -* Copy from new offset (repeat N bytes from new offset) -``` - 1 Elias(MSB(offset)+1) LSB(offset) Elias(length-1) -``` - -**ZX0** needs only 1 bit to distinguish between these blocks, because literal -blocks cannot be consecutive, and reusing last offset can only happen after a -literal block. The first block is always a literal, so the first bit is omitted. - -The offset MSB and all lengths are stored using interlaced -[Elias Gamma Coding](https://en.wikipedia.org/wiki/Elias_gamma_coding). When -offset MSB equals 256 it means EOF. The offset LSB is stored using 7 bits -instead of 8, because it produces better results in most practical cases. - - -## Advanced Features - -The **ZX0** compressor contains a few extra "hidden" features, that are slightly -harder to use properly, and not supported by the **ZX0** decompressor in C. Please -read carefully these instructions before attempting to use any of them! - - -#### _COMPRESSING BACKWARDS_ - -When using **ZX0** for "in-place" decompression (decompressing data to overlap the -same memory area storing the compressed data), you must always leave a small -margin of "delta" bytes of compressed data at the end. However it won't work to -decompress some large data that will occupy all the upper memory until the last -memory address, since there won't be even a couple bytes left at the end. - -A possible workaround is to compress and decompress data backwards, starting at -the last memory address. Therefore you will only need to leave a small margin of -"delta" bytes of compressed data at the beginning instead. Technically, it will -require that lowest address of compressed data should be at least "delta" bytes -lower than lowest address of decompressed data. See image below: - - compressed data |------------------| - decompressed data |---------------------------------| - <---> << start - delta - -To compress a file backwards, use the command-line compressor as follows: - -``` -zx0 -b Cobra.scr -``` - -To decompress it later, you must call one of the supplied "backwards" variants -of the Assembly decompressor, specifying last source address of compressed data -in HL and last target address in DE. - -For instance, if you compile a "backwards" Assembly decompressor routine to -address 64000, load backwards compressed file "Cobra.scr.zx0" (with size 2202 -bytes) to address 51200, and want to decompress it directly to the ZX Spectrum -screen (with 6912 bytes), then execute the following code: - -``` - LD HL, 51200+2202-1 ; source (last address of "Cobra.scr.zx0") - LD DE, 16384+6912-1 ; target (last address of screen memory) - CALL 64000 ; backwards decompress routine -``` - -Notice that compressing backwards may sometimes produce slightly smaller -compressed files in certain cases, slightly larger compressed files in others. -Overall it shouldn't make much difference either way. - - -#### _COMPRESSING WITH PREFIX_ - -The LZ77/LZSS compression is achieved by "abbreviating repetitions", such that -certain sequences of bytes are replaced with much shorter references to previous -occurrences of these same sequences. For this reason, it's harder to get very -good compression ratio on very short files, or in the initial parts of larger -files, due to lack of choices for previous sequences that could be referenced. - -A possible improvement is to compress data while also taking into account what -else will be already stored in memory during decompression later. Thus the -compressed data may even contain shorter references to repetitions stored in -some previous "prefix" memory area, instead of just repetitions within the -decompressed area itself. - -An input file may contain both some prefix data to be referenced only, and the -actual data to be compressed. An optional parameter can specify how many bytes -must be skipped before compression. See below: - -``` - compressed data - |-------------------| - prefix decompressed data - |--------------|---------------------------------| - start >> - <--------------> <---> - skip delta -``` - -As usual, if you want to decompress data into a memory area that partially -overlaps the compressed data itself, the last address of compressed data must be -at least "delta" bytes higher than the last address of decompressed data. - -For instance, if you want the first 6144 bytes of a certain file to be skipped -(not compressed but possibly referenced), then use the command-line compressor -as follows: - -``` -zx0 +6144 Cobra.cbr -``` - -In practice, suppose an action game uses a few generic sprites that are common -for all levels (such as player graphics), and other sprites are specific for -each level (such as enemies). All generic sprites must stay always accessible at -a certain memory area, but any level specific data can be only decompressed as -needed, to the memory area immediately following it. In this case, the generic -sprites area could be used as prefix when compressing and decompressing each -level, in an attempt to improve compression. For instance, suppose generic -graphics are loaded from file "generic.gfx" to address 56000, occupying 2500 -bytes, and level specific graphics will be decompressed immediately afterwards, -to address 58500. To compress each level using "generic.gfx" as a 2500 bytes -prefix, use the command-line compressor as follows: - -``` -copy /b generic.gfx+level_1.gfx prefixed_level_1.gfx -zx0 +2500 prefixed_level_1.gfx - -copy /b generic.gfx+level_2.gfx prefixed_level_2.gfx -zx0 +2500 prefixed_level_2.gfx - -copy /b generic.gfx+level_3.gfx prefixed_level_3.gfx -zx0 +2500 prefixed_level_3.gfx -``` - -To decompress it later, you simply need to use one of the normal variants of the -Assembly decompressor, as usual. In this case, if you loaded compressed file -"prefixed_level_1.gfx.zx0" to address 48000 for instance, decompressing it will -require the following code: - -``` - LD HL, 48000 ; source address (put "prefixed_level_1.gfx.zx0" there) - LD DE, 58500 ; target address (level specific memory area in this case) - CALL 65000 ; decompress routine compiled at this address -``` - -However decompression will only work properly if exactly the same prefix data is -present in the memory area immediately preceding the decompression address. -Therefore you must be extremely careful to ensure the prefix area does not store -variables, self-modifying code, or anything else that may change prefix content -between compression and decompression. Also don't forget to recompress your -files whenever you modify a prefix! - -In certain cases, compressing with a prefix may considerably help compression. -In others, it may not even make any difference. It mostly depends on how much -similarity exists between data to be compressed and its provided prefix. - - -#### _COMPRESSING BACKWARDS WITH SUFFIX_ - -Both features above can be used together. A file can be compressed backwards, -with an optional parameter to specify how many bytes should be skipped (not -compressed but possibly referenced) from the end of the input file instead. See -below: - -``` - compressed data - |-------------------| - decompressed data suffix - |---------------------------------|--------------| - << start - <---> <--------------> - delta skip -``` - -As usual, if you want to decompress data into a memory area that partially -overlaps the compressed data itself, lowest address of compressed data must be -at least "delta" bytes lower than lowest address of decompressed data. - -For instance, if you want to skip the last 768 bytes of a certain input file and -compress everything else (possibly referencing this "suffix" of 768 bytes), then -use the command-line compressor as follows: - -``` -zx0 -b +768 Cobra.cbr -``` - -In previous example, suppose the action game now stores level-specific sprites -in the memory area from address 33000 to 33511 (512 bytes), just before generic -sprites that are stored from address 33512 to 34535 (1024 bytes). In this case, -these generic sprites could be used as suffix when compressing and decompressing -level-specific data as needed, in an attempt to improve compression. To compress -each level using "generic.gfx" as a 1024 bytes suffix, use the command-line -compressor as follows: - -``` -copy /b level_1.gfx+generic.gfx level_1_suffixed.gfx -zx0 -b +1024 level_1_suffixed.gfx - -copy /b level_2.gfx+generic.gfx level_2_suffixed.gfx -zx0 -b +1024 level_2_suffixed.gfx - -copy /b level_3.gfx+generic.gfx level_3_suffixed.gfx -zx0 -b +1024 level_3_suffixed.gfx -``` - -To decompress it later, use the backwards variant of the Assembly decompressor. -In this case, if you compile a "backwards" decompressor routine to address -64000, and load compressed file "level_1_suffixed.gfx.zx0" (with 217 bytes) to -address 39000 for instance, decompressing it will require the following code: - -``` - LD HL, 39000+217-1 ; source (last address of "level_1_suffixed.gfx.zx0") - LD DE, 33000+512-1 ; target (last address of level-specific data) - CALL 64000 ; backwards decompress routine -``` - -Analogously, decompression will only work properly if exactly the same suffix -data is present in the memory area immediately following the decompression area. -Therefore you must be extremely careful to ensure the suffix area does not store -variables, self-modifying code, or anything else that may change suffix content -between compression and decompression. Also don't forget to recompress your -files whenever you modify a suffix! - -Also if you are using "in-place" decompression, you must leave a small margin of -"delta" bytes of compressed data just before the decompression area. - - -## License - -The **ZX0** data compression format and algorithm was designed and implemented -by **Einar Saukas**. Special thanks to **introspec/spke** for several -suggestions and improvements, and together with **uniabis** for providing the -"Fast" decompressor. Also special thanks to **Urusergi** for additional ideas -and improvements. - -The optimal C compressor is available under the "BSD-3" license. In practice, -this is relevant only if you want to modify its source code and/or incorporate -the compressor within your own products. Otherwise, if you just execute it to -compress files, you can simply ignore these conditions. - -The decompressors can be used freely within your own programs (either for the -ZX Spectrum or any other platform), even for commercial releases. The only -condition is that you must indicate somehow in your documentation that you have -used **ZX0**. - - -## Links - -**ZX0** implemented in other programming languages: - -* [ZX0-Java](https://github.com/einar-saukas/ZX0-Java) - Faster -multi-thread data compressor for **ZX0** in [Java](https://www.java.com/). - -* [ZX0-Kotlin](https://github.com/einar-saukas/ZX0-Kotlin) - Faster -multi-thread data compressor for **ZX0** in [Kotlin](https://kotlinlang.org/). - -* [Salvador](https://github.com/emmanuel-marty/salvador) - A non-optimal but -much faster data compressor for **ZX0** in C. - -**ZX0** ported to other platforms: - -* [DEC PDP11](https://github.com/ivagorRetrocomp/DeZX) _("classic" file format v1)_ - -* [Hitachi 6309](https://github.com/dougmasten/zx0-6x09) _("classic" file format v1)_ - -* [Intel 8080](https://github.com/ivagorRetrocomp/DeZX) _("classic" file format v1)_ - -* [Intel 8088/x86](https://github.com/emmanuel-marty/unzx0_x86) _(all formats)_ - -* [MOS 6502](https://github.com/bboxy/bitfire/tree/master/packer/zx0/6502) _(all formats)_ - -* [MOS 6502](https://xxl.atari.pl/zx0-decompressor/) (stream) - _(all formats)_ - -* [Motorola 6809](https://github.com/dougmasten/zx0-6x09) _("classic" file format v1)_ - -* [Motorola 68000](https://github.com/emmanuel-marty/unzx0_68000) _(all formats)_ - -Tools supporting **ZX0**: - -* [z88dk](http://www.z88dk.org/) - The main C compiler for Z80 machines, that -provides built-in support for **ZX0**, **ZX1**, **ZX2**, and **ZX7**. - -* [ZX Basic](https://zxbasic.readthedocs.io/) - The main BASIC compiler for -Z80 machines, that provides built-in support for **ZX0**. - -* [Mad-Pascal](https://github.com/tebe6502/Mad-Pascal) - The 32-bit Turbo -Pascal compiler for Atari XE/XL, that provides built-in support for **ZX0**. - -* [RASM Assembler](https://github.com/EdouardBERGE/rasm/) - A very fast Z80 -assembler, that provides built-in support for **ZX0** and **ZX7**. - -* [MSXlib](https://github.com/theNestruo/msx-msxlib) - A set of libraries to -create MSX videogame cartridges, that provides built-in support -for **ZX0**, **ZX1**, and **ZX7**. - -* [coco-dev](https://github.com/jamieleecho/coco-dev) - A Docker development -environment to create Tandy Color Computer applications, that provides -built-in support for **ZX0**. - -* [Gfx2Next](https://github.com/headkaze/Gfx2Next) - A graphics conversion -utility for ZX Spectrum Next development, that provides built-in support -for **ZX0**. - -* [ConvImgCpc](https://github.com/DemoniakLudo/ConvImgCpc) - An image -conversion utility for Amstrad CPC development, that provides built-in support -for **ZX0** and **ZX1**. - -* [Vortex2_Player_SJASM](https://github.com/andydansby/Vortex2_Player_SJASM_ver2_compress) - -A packaging utility to compile Vortex 2 music for a ZX Spectrum, that compresses -songs using **ZX0**. - -Projects using **ZX0**: - -* [Bitfire](https://github.com/bboxy/bitfire) - A disk image loader/generator -for Commodore 64, that stores all compressed data using a modified version -of **ZX0**. - -* [Defender CoCo 3](http://www.lcurtisboyle.com/nitros9/defender.html) - A -conversion of the official Williams Defender game from the arcades for the -Tandy Color Computer 3 that stores all compressed data using **ZX0** to fit -on two 160K floppy disks. - -* [NSID_Emu](https://spectrumcomputing.co.uk/forums/viewtopic.php?f=8&t=2786) - -A SID Player for ZX Spectrum that stores all compressed data using **ZX0**. - -* [ZX Interface 2 Cartridges](http://www.fruitcake.plus.com/Sinclair/Interface2/Cartridges/Interface2_RC_New_3rdParty_GameConversions.htm) - -Several ZX Interface 2 conversions were created using either **ZX0** or **ZX7** -so a full game could fit into a small 16K cartridge. - -* [Joust CoCo 3](http://www.lcurtisboyle.com/nitros9/joust.html) - A port of -arcade game Joust for the Tandy Color Computer 3, that stores all compressed -data using **ZX0** to fit on a single 160K floppy disk. - -* [Sonic GX](http://norecess.cpcscene.net/) - A remake of video game Sonic the -Hedgehog for the GX-4000, that stores all compressed data using **ZX0**. - -* [Rit and Tam](http://www.indieretronews.com/2021/02/rit-and-tam-arcade-classic-rodland-is.html) - -A remake of platform game Rodland for the Amstrad, that stores all compressed -data using **ZX0**. - -* [others](https://spectrumcomputing.co.uk/entry/36245/ZX-Spectrum/ZX0) - -A list of Sinclair-related programs using **ZX0** is available at **Spectrum Computing**. - -Related projects (by the same author): - -* [RCS](https://github.com/einar-saukas/RCS) - Use **ZX0** and **RCS** together -to improve compression of ZX Spectrum screens. - -* [ZX0](https://github.com/einar-saukas/ZX0) - The official **ZX0** repository. - -* [ZX1](https://github.com/einar-saukas/ZX1) - A simpler but faster version -of **ZX0**, that sacrifices about 1.5% compression to run about 15% faster. - -* [ZX2](https://github.com/einar-saukas/ZX2) - A minimalist version of **ZX1**, -intended for compressing very small files. - -* [ZX5](https://github.com/einar-saukas/ZX5) - An experimental, more complex -compressor based on **ZX0**. - -* [ZX7](https://spectrumcomputing.co.uk/entry/27996/ZX-Spectrum/ZX7) - A widely -popular predecessor compressor (now superseded by **ZX0**). diff --git a/Content/tools/zx0/src/compress.c b/Content/tools/zx0/src/compress.c deleted file mode 100644 index ca966a3..0000000 --- a/Content/tools/zx0/src/compress.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * (c) Copyright 2021 by Einar Saukas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of its author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "zx0.h" - -unsigned char* output_data; -int output_index; -int input_index; -int bit_index; -int bit_mask; -int diff; -int backtrack; - -void read_bytes(int n, int *delta) { - input_index += n; - diff += n; - if (*delta < diff) - *delta = diff; -} - -void write_byte(int value) { - output_data[output_index++] = value; - diff--; -} - -void write_bit(int value) { - if (backtrack) { - if (value) - output_data[output_index-1] |= 1; - backtrack = FALSE; - } else { - if (!bit_mask) { - bit_mask = 128; - bit_index = output_index; - write_byte(0); - } - if (value) - output_data[bit_index] |= bit_mask; - bit_mask >>= 1; - } -} - -void write_interlaced_elias_gamma(int value, int backwards_mode, int invert_mode) { - int i; - - for (i = 2; i <= value; i <<= 1) - ; - i >>= 1; - while (i >>= 1) { - write_bit(backwards_mode); - write_bit(invert_mode ? !(value & i) : (value & i)); - } - write_bit(!backwards_mode); -} - -unsigned char *compress(BLOCK *optimal, unsigned char *input_data, int input_size, int skip, int backwards_mode, int invert_mode, int *output_size, int *delta) { - BLOCK *prev; - BLOCK *next; - int last_offset = INITIAL_OFFSET; - int length; - int i; - - /* calculate and allocate output buffer */ - *output_size = (optimal->bits+25)/8; - output_data = (unsigned char *)malloc(*output_size); - if (!output_data) { - fprintf(stderr, "Error: Insufficient memory\n"); - exit(1); - } - - /* un-reverse optimal sequence */ - prev = NULL; - while (optimal) { - next = optimal->chain; - optimal->chain = prev; - prev = optimal; - optimal = next; - } - - /* initialize data */ - diff = *output_size-input_size+skip; - *delta = 0; - input_index = skip; - output_index = 0; - bit_mask = 0; - backtrack = TRUE; - - /* generate output */ - for (optimal = prev->chain; optimal; prev=optimal, optimal = optimal->chain) { - length = optimal->index-prev->index; - - if (!optimal->offset) { - /* copy literals indicator */ - write_bit(0); - - /* copy literals length */ - write_interlaced_elias_gamma(length, backwards_mode, FALSE); - - /* copy literals values */ - for (i = 0; i < length; i++) { - write_byte(input_data[input_index]); - read_bytes(1, delta); - } - } else if (optimal->offset == last_offset) { - /* copy from last offset indicator */ - write_bit(0); - - /* copy from last offset length */ - write_interlaced_elias_gamma(length, backwards_mode, FALSE); - read_bytes(length, delta); - } else { - /* copy from new offset indicator */ - write_bit(1); - - /* copy from new offset MSB */ - write_interlaced_elias_gamma((optimal->offset-1)/128+1, backwards_mode, invert_mode); - - /* copy from new offset LSB */ - if (backwards_mode) - write_byte(((optimal->offset-1)%128)<<1); - else - write_byte((127-(optimal->offset-1)%128)<<1); - - /* copy from new offset length */ - backtrack = TRUE; - write_interlaced_elias_gamma(length-1, backwards_mode, FALSE); - read_bytes(length, delta); - - last_offset = optimal->offset; - } - } - - /* end marker */ - write_bit(1); - write_interlaced_elias_gamma(256, backwards_mode, invert_mode); - - /* done! */ - return output_data; -} diff --git a/Content/tools/zx0/src/dzx0.c b/Content/tools/zx0/src/dzx0.c deleted file mode 100644 index 502f96d..0000000 --- a/Content/tools/zx0/src/dzx0.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * ZX0 decompressor - by Einar Saukas - * https://github.com/einar-saukas/ZX0 - */ - -#include -#include -#include - -#define BUFFER_SIZE 65536 /* must be > MAX_OFFSET */ -#define INITIAL_OFFSET 1 - -#define FALSE 0 -#define TRUE 1 - -FILE *ifp; -FILE *ofp; -char *input_name; -char *output_name; -unsigned char *input_data; -unsigned char *output_data; -size_t input_index; -size_t output_index; -size_t input_size; -size_t output_size; -size_t partial_counter; -int bit_mask; -int bit_value; -int backtrack; -int last_byte; - -int read_byte() { - if (input_index == partial_counter) { - input_index = 0; - partial_counter = fread(input_data, sizeof(char), BUFFER_SIZE, ifp); - input_size += partial_counter; - if (partial_counter == 0) { - fprintf(stderr, (input_size ? "Error: Truncated input file %s\n" : "Error: Empty input file %s\n"), input_name); - exit(1); - } - } - last_byte = input_data[input_index++]; - return last_byte; -} - -int read_bit() { - if (backtrack) { - backtrack = FALSE; - return last_byte & 1; - } - bit_mask >>= 1; - if (bit_mask == 0) { - bit_mask = 128; - bit_value = read_byte(); - } - return bit_value & bit_mask ? 1 : 0; -} - -int read_interlaced_elias_gamma(int inverted) { - int value = 1; - while (!read_bit()) { - value = value << 1 | read_bit() ^ inverted; - } - return value; -} - -void save_output() { - if (output_index != 0) { - if (fwrite(output_data, sizeof(char), output_index, ofp) != output_index) { - fprintf(stderr, "Error: Cannot write output file %s\n", output_name); - exit(1); - } - output_size += output_index; - output_index = 0; - } -} - -void write_byte(int value) { - output_data[output_index++] = value; - if (output_index == BUFFER_SIZE) { - save_output(); - } -} - -void write_bytes(int offset, int length) { - int i; - - if (offset > output_size+output_index) { - fprintf(stderr, "Error: Invalid data in input file %s\n", input_name); - exit(1); - } - while (length-- > 0) { - i = output_index-offset; - write_byte(output_data[i >= 0 ? i : BUFFER_SIZE+i]); - } -} - -void decompress(int classic_mode) { - int last_offset = INITIAL_OFFSET; - int length; - int i; - - input_data = (unsigned char *)malloc(BUFFER_SIZE); - output_data = (unsigned char *)malloc(BUFFER_SIZE); - if (!input_data || !output_data) { - fprintf(stderr, "Error: Insufficient memory\n"); - exit(1); - } - - input_size = 0; - input_index = 0; - partial_counter = 0; - output_index = 0; - output_size = 0; - bit_mask = 0; - backtrack = FALSE; - -COPY_LITERALS: - length = read_interlaced_elias_gamma(FALSE); - for (i = 0; i < length; i++) - write_byte(read_byte()); - if (read_bit()) - goto COPY_FROM_NEW_OFFSET; - -/*COPY_FROM_LAST_OFFSET:*/ - length = read_interlaced_elias_gamma(FALSE); - write_bytes(last_offset, length); - if (!read_bit()) - goto COPY_LITERALS; - -COPY_FROM_NEW_OFFSET: - last_offset = read_interlaced_elias_gamma(!classic_mode); - if (last_offset == 256) { - save_output(); - if (input_index != partial_counter) { - fprintf(stderr, "Error: Input file %s too long\n", input_name); - exit(1); - } - return; - } - last_offset = last_offset*128-(read_byte()>>1); - backtrack = TRUE; - length = read_interlaced_elias_gamma(FALSE)+1; - write_bytes(last_offset, length); - if (read_bit()) - goto COPY_FROM_NEW_OFFSET; - else - goto COPY_LITERALS; -} - -int main(int argc, char *argv[]) { - int forced_mode = FALSE; - int classic_mode = FALSE; - int i; - - printf("DZX0 v2.2: Data decompressor by Einar Saukas\n"); - - /* process hidden optional parameters */ - for (i = 1; i < argc && *argv[i] == '-'; i++) { - if (!strcmp(argv[i], "-f")) { - forced_mode = TRUE; - } else if (!strcmp(argv[i], "-c")) { - classic_mode = TRUE; - } else { - fprintf(stderr, "Error: Invalid parameter %s\n", argv[i]); - exit(1); - } - } - - /* determine output filename */ - if (argc == i+1) { - input_name = argv[i]; - input_size = strlen(input_name); - if (input_size > 4 && !strcmp(input_name+input_size-4, ".zx0")) { - input_size = strlen(input_name); - output_name = (char *)malloc(input_size); - strcpy(output_name, input_name); - output_name[input_size-4] = '\0'; - } else { - fprintf(stderr, "Error: Cannot infer output filename\n"); - exit(1); - } - } else if (argc == i+2) { - input_name = argv[i]; - output_name = argv[i+1]; - } else { - fprintf(stderr, "Usage: %s [-f] [-c] input.zx0 [output]\n" - " -f Force overwrite of output file\n" - " -c Classic file format (v1.*)\n", argv[0]); - exit(1); - } - - /* open input file */ - ifp = fopen(input_name, "rb"); - if (!ifp) { - fprintf(stderr, "Error: Cannot access input file %s\n", input_name); - exit(1); - } - - /* check output file */ - if (!forced_mode && fopen(output_name, "rb") != NULL) { - fprintf(stderr, "Error: Already existing output file %s\n", output_name); - exit(1); - } - - /* create output file */ - ofp = fopen(output_name, "wb"); - if (!ofp) { - fprintf(stderr, "Error: Cannot create output file %s\n", output_name); - exit(1); - } - - /* generate output file */ - decompress(classic_mode); - - /* close input file */ - fclose(ifp); - - /* close output file */ - fclose(ofp); - - /* done! */ - printf("File decompressed from %lu to %lu bytes!\n", (unsigned long)input_size, (unsigned long)output_size); - - return 0; -} diff --git a/Content/tools/zx0/src/memory.c b/Content/tools/zx0/src/memory.c deleted file mode 100644 index be52c3a..0000000 --- a/Content/tools/zx0/src/memory.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * (c) Copyright 2021 by Einar Saukas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of its author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "zx0.h" - -#define QTY_BLOCKS 10000 - -BLOCK *ghost_root = NULL; -BLOCK *dead_array = NULL; -int dead_array_size = 0; - -BLOCK *allocate(int bits, int index, int offset, BLOCK *chain) { - BLOCK *ptr; - - if (ghost_root) { - ptr = ghost_root; - ghost_root = ptr->ghost_chain; - if (ptr->chain && !--ptr->chain->references) { - ptr->chain->ghost_chain = ghost_root; - ghost_root = ptr->chain; - } - } else { - if (!dead_array_size) { - dead_array = (BLOCK *)malloc(QTY_BLOCKS*sizeof(BLOCK)); - if (!dead_array) { - fprintf(stderr, "Error: Insufficient memory\n"); - exit(1); - } - dead_array_size = QTY_BLOCKS; - } - ptr = &dead_array[--dead_array_size]; - } - ptr->bits = bits; - ptr->index = index; - ptr->offset = offset; - if (chain) - chain->references++; - ptr->chain = chain; - ptr->references = 0; - return ptr; -} - -void assign(BLOCK **ptr, BLOCK *chain) { - chain->references++; - if (*ptr && !--(*ptr)->references) { - (*ptr)->ghost_chain = ghost_root; - ghost_root = *ptr; - } - *ptr = chain; -} diff --git a/Content/tools/zx0/src/optimize.c b/Content/tools/zx0/src/optimize.c deleted file mode 100644 index 99ca540..0000000 --- a/Content/tools/zx0/src/optimize.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * (c) Copyright 2021 by Einar Saukas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of its author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include "zx0.h" - -#define MAX_SCALE 50 - -int offset_ceiling(int index, int offset_limit) { - return index > offset_limit ? offset_limit : index < INITIAL_OFFSET ? INITIAL_OFFSET : index; -} - -int elias_gamma_bits(int value) { - int bits = 1; - while (value >>= 1) - bits += 2; - return bits; -} - -BLOCK* optimize(unsigned char *input_data, int input_size, int skip, int offset_limit) { - BLOCK **last_literal; - BLOCK **last_match; - BLOCK **optimal; - int* match_length; - int* best_length; - int best_length_size; - int bits; - int index; - int offset; - int length; - int bits2; - int dots = 2; - int max_offset = offset_ceiling(input_size-1, offset_limit); - - /* allocate all main data structures at once */ - last_literal = (BLOCK **)calloc(max_offset+1, sizeof(BLOCK *)); - last_match = (BLOCK **)calloc(max_offset+1, sizeof(BLOCK *)); - optimal = (BLOCK **)calloc(input_size, sizeof(BLOCK *)); - match_length = (int *)calloc(max_offset+1, sizeof(int)); - best_length = (int *)malloc(input_size*sizeof(int)); - if (!last_literal || !last_match || !optimal || !match_length || !best_length) { - fprintf(stderr, "Error: Insufficient memory\n"); - exit(1); - } - if (input_size > 2) - best_length[2] = 2; - - /* start with fake block */ - assign(&last_match[INITIAL_OFFSET], allocate(-1, skip-1, INITIAL_OFFSET, NULL)); - - printf("["); - - /* process remaining bytes */ - for (index = skip; index < input_size; index++) { - best_length_size = 2; - max_offset = offset_ceiling(index, offset_limit); - for (offset = 1; offset <= max_offset; offset++) { - if (index != skip && index >= offset && input_data[index] == input_data[index-offset]) { - /* copy from last offset */ - if (last_literal[offset]) { - length = index-last_literal[offset]->index; - bits = last_literal[offset]->bits + 1 + elias_gamma_bits(length); - assign(&last_match[offset], allocate(bits, index, offset, last_literal[offset])); - if (!optimal[index] || optimal[index]->bits > bits) - assign(&optimal[index], last_match[offset]); - } - /* copy from new offset */ - if (++match_length[offset] > 1) { - if (best_length_size < match_length[offset]) { - bits = optimal[index-best_length[best_length_size]]->bits + elias_gamma_bits(best_length[best_length_size]-1); - do { - best_length_size++; - bits2 = optimal[index-best_length_size]->bits + elias_gamma_bits(best_length_size-1); - if (bits2 <= bits) { - best_length[best_length_size] = best_length_size; - bits = bits2; - } else { - best_length[best_length_size] = best_length[best_length_size-1]; - } - } while(best_length_size < match_length[offset]); - } - length = best_length[match_length[offset]]; - bits = optimal[index-length]->bits + 8 + elias_gamma_bits((offset-1)/128+1) + elias_gamma_bits(length-1); - if (!last_match[offset] || last_match[offset]->index != index || last_match[offset]->bits > bits) { - assign(&last_match[offset], allocate(bits, index, offset, optimal[index-length])); - if (!optimal[index] || optimal[index]->bits > bits) - assign(&optimal[index], last_match[offset]); - } - } - } else { - /* copy literals */ - match_length[offset] = 0; - if (last_match[offset]) { - length = index-last_match[offset]->index; - bits = last_match[offset]->bits + 1 + elias_gamma_bits(length) + length*8; - assign(&last_literal[offset], allocate(bits, index, 0, last_match[offset])); - if (!optimal[index] || optimal[index]->bits > bits) - assign(&optimal[index], last_literal[offset]); - } - } - } - - /* indicate progress */ - if (index*MAX_SCALE/input_size > dots) { - printf("."); - fflush(stdout); - dots++; - } - } - - printf("]\n"); - - return optimal[input_size-1]; -} diff --git a/Content/tools/zx0/src/zx0.c b/Content/tools/zx0/src/zx0.c deleted file mode 100644 index 45b2efd..0000000 --- a/Content/tools/zx0/src/zx0.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * (c) Copyright 2021 by Einar Saukas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of its author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -#include "zx0.h" - -#define MAX_OFFSET_ZX0 32640 -#define MAX_OFFSET_ZX7 2176 - -void reverse(unsigned char *first, unsigned char *last) { - unsigned char c; - - while (first < last) { - c = *first; - *first++ = *last; - *last-- = c; - } -} - -int main(int argc, char *argv[]) { - int skip = 0; - int forced_mode = FALSE; - int quick_mode = FALSE; - int backwards_mode = FALSE; - int classic_mode = FALSE; - char *output_name; - unsigned char *input_data; - unsigned char *output_data; - FILE *ifp; - FILE *ofp; - int input_size; - int output_size; - int partial_counter; - int total_counter; - int delta; - int i; - - printf("ZX0 v2.2: Optimal data compressor by Einar Saukas\n"); - - /* process optional parameters */ - for (i = 1; i < argc && (*argv[i] == '-' || *argv[i] == '+'); i++) { - if (!strcmp(argv[i], "-f")) { - forced_mode = TRUE; - } else if (!strcmp(argv[i], "-c")) { - classic_mode = TRUE; - } else if (!strcmp(argv[i], "-b")) { - backwards_mode = TRUE; - } else if (!strcmp(argv[i], "-q")) { - quick_mode = TRUE; - } else if ((skip = atoi(argv[i])) <= 0) { - fprintf(stderr, "Error: Invalid parameter %s\n", argv[i]); - exit(1); - } - } - - /* determine output filename */ - if (argc == i+1) { - output_name = (char *)malloc(strlen(argv[i])+5); - strcpy(output_name, argv[i]); - strcat(output_name, ".zx0"); - } else if (argc == i+2) { - output_name = argv[i+1]; - } else { - fprintf(stderr, "Usage: %s [-f] [-c] [-b] [-q] input [output.zx0]\n" - " -f Force overwrite of output file\n" - " -c Classic file format (v1.*)\n" - " -b Compress backwards\n" - " -q Quick non-optimal compression\n", argv[0]); - exit(1); - } - - /* open input file */ - ifp = fopen(argv[i], "rb"); - if (!ifp) { - fprintf(stderr, "Error: Cannot access input file %s\n", argv[i]); - exit(1); - } - /* determine input size */ - fseek(ifp, 0L, SEEK_END); - input_size = ftell(ifp); - fseek(ifp, 0L, SEEK_SET); - if (!input_size) { - fprintf(stderr, "Error: Empty input file %s\n", argv[i]); - exit(1); - } - - /* validate skip against input size */ - if (skip >= input_size) { - fprintf(stderr, "Error: Skipping entire input file %s\n", argv[i]); - exit(1); - } - - /* allocate input buffer */ - input_data = (unsigned char *)malloc(input_size); - if (!input_data) { - fprintf(stderr, "Error: Insufficient memory\n"); - exit(1); - } - - /* read input file */ - total_counter = 0; - do { - partial_counter = fread(input_data+total_counter, sizeof(char), input_size-total_counter, ifp); - total_counter += partial_counter; - } while (partial_counter > 0); - - if (total_counter != input_size) { - fprintf(stderr, "Error: Cannot read input file %s\n", argv[i]); - exit(1); - } - - /* close input file */ - fclose(ifp); - - /* check output file */ - if (!forced_mode && fopen(output_name, "rb") != NULL) { - fprintf(stderr, "Error: Already existing output file %s\n", output_name); - exit(1); - } - - /* create output file */ - ofp = fopen(output_name, "wb"); - if (!ofp) { - fprintf(stderr, "Error: Cannot create output file %s\n", output_name); - exit(1); - } - - /* conditionally reverse input file */ - if (backwards_mode) - reverse(input_data, input_data+input_size-1); - - /* generate output file */ - output_data = compress(optimize(input_data, input_size, skip, quick_mode ? MAX_OFFSET_ZX7 : MAX_OFFSET_ZX0), input_data, input_size, skip, backwards_mode, !classic_mode && !backwards_mode, &output_size, &delta); - - /* conditionally reverse output file */ - if (backwards_mode) - reverse(output_data, output_data+output_size-1); - - /* write output file */ - if (fwrite(output_data, sizeof(char), output_size, ofp) != output_size) { - fprintf(stderr, "Error: Cannot write output file %s\n", output_name); - exit(1); - } - - /* close output file */ - fclose(ofp); - - /* done! */ - printf("File%s compressed%s from %d to %d bytes! (delta %d)\n", (skip ? " partially" : ""), (backwards_mode ? " backwards" : ""), input_size-skip, output_size, delta); - - return 0; -} diff --git a/Content/tools/zx0/src/zx0.h b/Content/tools/zx0/src/zx0.h deleted file mode 100644 index cb298cf..0000000 --- a/Content/tools/zx0/src/zx0.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * (c) Copyright 2021 by Einar Saukas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * The name of its author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define INITIAL_OFFSET 1 - -#define FALSE 0 -#define TRUE 1 - -typedef struct block_t { - struct block_t *chain; - struct block_t *ghost_chain; - int bits; - int index; - int offset; - int references; -} BLOCK; - -BLOCK *allocate(int bits, int index, int offset, BLOCK *chain); - -void assign(BLOCK **ptr, BLOCK *chain); - -BLOCK *optimize(unsigned char *input_data, int input_size, int skip, int offset_limit); - -unsigned char *compress(BLOCK *optimal, unsigned char *input_data, int input_size, int skip, int backwards_mode, int invert_mode, int *output_size, int *delta); diff --git a/Content/tools/zx0/z80/OLD_V1/dzx0_fast_CLASSIC.asm b/Content/tools/zx0/z80/OLD_V1/dzx0_fast_CLASSIC.asm deleted file mode 100644 index 657a589..0000000 --- a/Content/tools/zx0/z80/OLD_V1/dzx0_fast_CLASSIC.asm +++ /dev/null @@ -1,250 +0,0 @@ -; -; Speed-optimized ZX0 decompressor by spke (191 bytes) - OLD FILE FORMAT v1 -; -; ver.00 by spke (27/01-23/03/2021, 191 bytes) -; ver.01 by spke (24/03/2021, 193(+2) bytes - fixed a bug in the initialization) -; ver.01patch2 by uniabis (25/03/2021, 191(-2) bytes - fixed a bug with elias over 8bits) -; ver.01patch5 by uniabis (29/03/2021, 191 bytes - a bit faster) -; -; Original ZX0 decompressors were written by Einar Saukas -; -; This decompressor was written on the basis of "Standard" decompressor by -; Einar Saukas and optimized for speed by spke. This decompressor is -; about 5% faster than the "Turbo" decompressor, which is 128 bytes long. -; It has about the same speed as the 412 bytes version of the "Mega" decompressor. -; -; The decompressor uses AF, AF', BC, DE, HL and IX and relies upon self-modified code. -; -; The decompression is done in the standard way: -; -; ld hl,FirstByteOfCompressedData -; ld de,FirstByteOfMemoryForDecompressedData -; call DecompressZX0 -; -; Of course, ZX0 compression algorithms are (c) 2021 Einar Saukas, -; see https://github.com/einar-saukas/ZX0 for more information -; -; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software. -; 3. This notice may not be removed or altered from any source distribution. - -DecompressZX0: - scf - ex af, af' - ld ix, CopyMatch1 - ld bc, $ffff - ld (PrevOffset+1), bc ; default offset is -1 - inc bc - ld a, $80 - jr RunOfLiterals ; BC is assumed to contains 0 most of the time - - ; 7-bit offsets allow additional optimizations, based on the facts that C==0 and AF' has C ON! -ShorterOffsets: - ex af, af' - sbc a, a - ld (PrevOffset+2), a ; the top byte of the offset is always $FF - ld a, (hl) - inc hl - rra - ld (PrevOffset+1), a ; note that AF' always has flag C ON - jr nc, LongerMatch - -CopyMatch2: ; the case of matches with len=2 - ex af, af' - ld c, 2 - - ; the faster match copying code -CopyMatch1: - push hl ; preserve source - -PrevOffset: - ld hl, $ffff ; restore offset (default offset is -1) - add hl, de ; HL = dest - offset - ldir - pop hl ; restore source - - ; after a match you can have either - ; 0 + = run of literals, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match -AfterMatch1: - add a, a - jr nc, RunOfLiterals - -UsualMatch: ; this is the case of usual match+offset - add a, a - jr nc, LongerOffets - jr nz, ShorterOffsets ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, ShorterOffsets - -LongerOffets: - inc c - - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - call z, ReloadReadGamma - -ProcessOffset: - ex af, af' - xor a - sub c - ret z ; end-of-data marker (only checked for longer offsets) - rra - ld (PrevOffset+2),a - ld a, (hl) - inc hl - rra - ld (PrevOffset+1), a - - ; lowest bit is the first bit of the gamma code for length - jr c, CopyMatch2 - - ; this wastes 1 t-state for longer matches far away, - ; but saves 4 t-states for longer nearby (seems to pay off in testing) - ld c, b -LongerMatch: - inc c - ; doing SCF here ensures that AF' has flag C ON and costs - ; cheaper than doing SCF in the ShortestOffsets branch - scf - ex af, af' - - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - call z,ReloadReadGamma - -CopyMatch3: - push hl ; preserve source - ld hl, (PrevOffset+1) ; restore offset - add hl, de ; HL = dest - offset - - ; because BC>=3-1, we can do 2 x LDI safely - ldi - ldir - inc c - ldi - pop hl ; restore source - - ; after a match you can have either - ; 0 + = run of literals, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match -AfterMatch3: - add a, a - jr c, UsualMatch - -RunOfLiterals: - inc c - add a, a - jr nc, LongerRun - jr nz, CopyLiteral ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, CopyLiteral - -LongerRun: - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - jr nz, CopyLiterals - - ld a, (hl) ; reload bits - inc hl - rla - - call nc, ReadGammaAligned - -CopyLiterals: - ldi - -CopyLiteral: - ldir - - ; after a literal run you can have either - ; 0 + = match using a repeated offset, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match - add a, a - jr c, UsualMatch - -RepMatch: - inc c - add a, a - jr nc, LongerRepMatch - jr nz, CopyMatch1 ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, CopyMatch1 - -LongerRepMatch: - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - jp nz, CopyMatch1 - - ; this is a crafty equivalent of CALL ReloadReadGamma : JP CopyMatch1 - push ix - - ; the subroutine for reading the remainder of the partly read Elias gamma code. - ; it has two entry points: ReloadReadGamma first refills the bit reservoir in A, - ; while ReadGammaAligned assumes that the bit reservoir has just been refilled. -ReloadReadGamma: - ld a, (hl) ; reload bits - inc hl - rla - - ret c -ReadGammaAligned: - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a - -ReadingLongGamma: ; this loop does not need unrolling, as it does not get much use anyway - ret c - add a, a - rl c - rl b - add a, a - jr nz, ReadingLongGamma - - ld a, (hl) ; reload bits - inc hl - rla - - jr ReadingLongGamma diff --git a/Content/tools/zx0/z80/OLD_V1/dzx0_mega_CLASSIC.asm b/Content/tools/zx0/z80/OLD_V1/dzx0_mega_CLASSIC.asm deleted file mode 100644 index e703093..0000000 --- a/Content/tools/zx0/z80/OLD_V1/dzx0_mega_CLASSIC.asm +++ /dev/null @@ -1,464 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas -; "Mega" version (681 bytes, 28% faster) - OLD FILE FORMAT v1 -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_mega: - ld bc, $ffff ; preserve default offset 1 - ld (dzx0m_last_offset+1), bc - inc bc - jr dzx0m_literals0 - -dzx0m_new_offset6: - inc c - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset5 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset3 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset1 -dzx0m_elias_offset1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_offset7 -dzx0m_new_offset7: - ex af, af' ; adjust for negative offset - xor a - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length7 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length5 - add a, a - rl c - add a, a - jp c, dzx0m_length3 -dzx0m_elias_length3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length1 -dzx0m_length1: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset0 -dzx0m_literals0: - inc c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain length - jp c, dzx0m_literals7 - add a, a - rl c - add a, a - jp c, dzx0m_literals5 - add a, a - rl c - add a, a - jp c, dzx0m_literals3 -dzx0m_elias_literals3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals1 -dzx0m_literals1: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset0 - inc c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain length - jp c, dzx0m_reuse7 - add a, a - rl c - add a, a - jp c, dzx0m_reuse5 - add a, a - rl c - add a, a - jp c, dzx0m_reuse3 -dzx0m_elias_reuse3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse1 -dzx0m_reuse1: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals0 - -dzx0m_new_offset0: - inc c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset7 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset5 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset3 -dzx0m_elias_offset3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset1 -dzx0m_new_offset1: - ex af, af' ; adjust for negative offset - xor a - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length1 ; obtain length - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_length7 - add a, a - rl c - add a, a - jp c, dzx0m_length5 -dzx0m_elias_length5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length3 -dzx0m_length3: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset2 -dzx0m_literals2: - inc c - add a, a ; obtain length - jp c, dzx0m_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_literals7 - add a, a - rl c - add a, a - jp c, dzx0m_literals5 -dzx0m_elias_literals5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals3 -dzx0m_literals3: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset2 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_reuse7 - add a, a - rl c - add a, a - jp c, dzx0m_reuse5 -dzx0m_elias_reuse5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse3 -dzx0m_reuse3: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals2 - -dzx0m_new_offset2: - inc c - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_new_offset7 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset5 -dzx0m_elias_offset5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset3 -dzx0m_new_offset3: - ex af, af' ; adjust for negative offset - xor a - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length3 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_length7 -dzx0m_elias_length7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length5 -dzx0m_length5: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset4 -dzx0m_literals4: - inc c - add a, a ; obtain length - jp c, dzx0m_literals3 - add a, a - rl c - add a, a - jp c, dzx0m_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_literals7 -dzx0m_elias_literals7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals5 -dzx0m_literals5: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset4 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse3 - add a, a - rl c - add a, a - jp c, dzx0m_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_reuse7 -dzx0m_elias_reuse7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse5 -dzx0m_reuse5: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals4 - -dzx0m_new_offset4: - inc c - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset3 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_new_offset7 -dzx0m_elias_offset7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset5 -dzx0m_new_offset5: - ex af, af' ; adjust for negative offset - xor a - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length5 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length3 - add a, a - rl c - add a, a - jp c, dzx0m_length1 -dzx0m_elias_length1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_length7 -dzx0m_length7: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jp c, dzx0m_new_offset6 -dzx0m_literals6: - inc c - add a, a ; obtain length - jp c, dzx0m_literals5 - add a, a - rl c - add a, a - jp c, dzx0m_literals3 - add a, a - rl c - add a, a - jp c, dzx0m_literals1 -dzx0m_elias_literals1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_literals7 -dzx0m_literals7: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jp c, dzx0m_new_offset6 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse5 - add a, a - rl c - add a, a - jp c, dzx0m_reuse3 - add a, a - rl c - add a, a - jp c, dzx0m_reuse1 -dzx0m_elias_reuse1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_reuse7 -dzx0m_reuse7: - push hl ; preserve source -dzx0m_last_offset: - ld hl, 0 - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals6 - - jp dzx0m_new_offset6 -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/OLD_V1/dzx0_standard_CLASSIC.asm b/Content/tools/zx0/z80/OLD_V1/dzx0_standard_CLASSIC.asm deleted file mode 100644 index 9b7d8ff..0000000 --- a/Content/tools/zx0/z80/OLD_V1/dzx0_standard_CLASSIC.asm +++ /dev/null @@ -1,63 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas -; "Standard" version (69 bytes only) - OLD FILE FORMAT v1 -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_standard: - ld bc, $ffff ; preserve default offset 1 - push bc - inc bc - ld a, $80 -dzx0s_literals: - call dzx0s_elias ; obtain length - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0s_new_offset - call dzx0s_elias ; obtain length -dzx0s_copy: - ex (sp), hl ; preserve source, restore offset - push hl ; preserve offset - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore offset - ex (sp), hl ; preserve offset, restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0s_literals -dzx0s_new_offset: - call dzx0s_elias ; obtain offset MSB - ex af, af' - pop af ; discard last offset - xor a ; adjust for negative offset - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - push bc ; preserve new offset - ld bc, 1 ; obtain length - call nc, dzx0s_elias_backtrack - inc bc - jr dzx0s_copy -dzx0s_elias: - inc c ; interlaced Elias gamma coding -dzx0s_elias_loop: - add a, a - jr nz, dzx0s_elias_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0s_elias_skip: - ret c -dzx0s_elias_backtrack: - add a, a - rl c - rl b - jr dzx0s_elias_loop -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/OLD_V1/dzx0_turbo_CLASSIC.asm b/Content/tools/zx0/z80/OLD_V1/dzx0_turbo_CLASSIC.asm deleted file mode 100644 index fa94bc0..0000000 --- a/Content/tools/zx0/z80/OLD_V1/dzx0_turbo_CLASSIC.asm +++ /dev/null @@ -1,103 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas & introspec -; "Turbo" version (128 bytes, 21% faster) - OLD FILE FORMAT v1 -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_turbo: - ld bc, $ffff ; preserve default offset 1 - ld (dzx0t_last_offset+1), bc - inc bc - ld a, $80 - jr dzx0t_literals -dzx0t_new_offset: - inc c ; obtain offset MSB - add a, a - jp nz, dzx0t_new_offset_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_new_offset_skip: - call nc, dzx0t_elias - ex af, af' ; adjust for negative offset - xor a - sub c - ret z ; check end marker - ld b, a - ex af, af' - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0t_last_offset+1), bc ; preserve new offset - ld bc, 1 ; obtain length - call nc, dzx0t_elias - inc bc -dzx0t_copy: - push hl ; preserve source -dzx0t_last_offset: - ld hl, 0 ; restore offset - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0t_new_offset -dzx0t_literals: - inc c ; obtain length - add a, a - jp nz, dzx0t_literals_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_literals_skip: - call nc, dzx0t_elias - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0t_new_offset - inc c ; obtain length - add a, a - jp nz, dzx0t_last_offset_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_last_offset_skip: - call nc, dzx0t_elias - jp dzx0t_copy -dzx0t_elias: - add a, a ; interlaced Elias gamma coding - rl c - add a, a - jr nc, dzx0t_elias - ret nz - ld a, (hl) ; load another group of 8 bits - inc hl - rla - ret c - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a - ret c -dzx0t_elias_loop: - add a, a - rl c - rl b - add a, a - jr nc, dzx0t_elias_loop - ret nz - ld a, (hl) ; load another group of 8 bits - inc hl - rla - jr nc, dzx0t_elias_loop - ret -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_fast.asm b/Content/tools/zx0/z80/dzx0_fast.asm deleted file mode 100644 index b908145..0000000 --- a/Content/tools/zx0/z80/dzx0_fast.asm +++ /dev/null @@ -1,235 +0,0 @@ -; -; Speed-optimized ZX0 decompressor by spke (187 bytes) -; -; ver.00 by spke (27/01-23/03/2021, 191 bytes) -; ver.01 by spke (24/03/2021, 193(+2) bytes - fixed a bug in the initialization) -; ver.01patch2 by uniabis (25/03/2021, 191(-2) bytes - fixed a bug with elias over 8bits) -; ver.01patch9 by uniabis (10/09/2021, 187(-4) bytes - support for new v2 format) -; -; Original ZX0 decompressors were written by Einar Saukas -; -; This decompressor was written on the basis of "Standard" decompressor by -; Einar Saukas and optimized for speed by spke. This decompressor is -; about 5% faster than the "Turbo" decompressor, which is 128 bytes long. -; It has about the same speed as the 412 bytes version of the "Mega" decompressor. -; -; The decompressor uses AF, BC, DE, HL and IX and relies upon self-modified code. -; -; The decompression is done in the standard way: -; -; ld hl,FirstByteOfCompressedData -; ld de,FirstByteOfMemoryForDecompressedData -; call DecompressZX0 -; -; Of course, ZX0 compression algorithms are (c) 2021 Einar Saukas, -; see https://github.com/einar-saukas/ZX0 for more information -; -; Drop me an email if you have any comments/ideas/suggestions: zxintrospec@gmail.com -; -; This software is provided 'as-is', without any express or implied -; warranty. In no event will the authors be held liable for any damages -; arising from the use of this software. -; -; Permission is granted to anyone to use this software for any purpose, -; including commercial applications, and to alter it and redistribute it -; freely, subject to the following restrictions: -; -; 1. The origin of this software must not be misrepresented; you must not -; claim that you wrote the original software. If you use this software -; in a product, an acknowledgment in the product documentation would be -; appreciated but is not required. -; 2. Altered source versions must be plainly marked as such, and must not be -; misrepresented as being the original software. -; 3. This notice may not be removed or altered from any source distribution. - -DecompressZX0: - - ld ix, CopyMatch1 - ld bc, $ffff - ld (PrevOffset+1), bc ; default offset is -1 - inc bc - ld a, $80 - jr RunOfLiterals ; BC is assumed to contains 0 most of the time - -ShorterOffsets: - ld b, $ff ; the top byte of the offset is always $FF - ld c, (hl) - inc hl - rr c - ld (PrevOffset+1), bc - jr nc, LongerMatch - -CopyMatch2: ; the case of matches with len=2 - ld bc, 2 - - ; the faster match copying code -CopyMatch1: - push hl ; preserve source - -PrevOffset: - ld hl, $ffff ; restore offset (default offset is -1) - add hl, de ; HL = dest - offset - ldir - pop hl ; restore source - - ; after a match you can have either - ; 0 + = run of literals, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match -AfterMatch1: - add a, a - jr nc, RunOfLiterals - -UsualMatch: ; this is the case of usual match+offset - add a, a - jr nc, LongerOffets - jr nz, ShorterOffsets ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, ShorterOffsets - -LongerOffets: - ld c, $fe - - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - call z, ReloadReadGamma - -ProcessOffset: - - inc c - ret z ; end-of-data marker (only checked for longer offsets) - rr c - ld b, c - ld c, (hl) - inc hl - rr c - ld (PrevOffset+1), bc - - ; lowest bit is the first bit of the gamma code for length - jr c, CopyMatch2 - -LongerMatch: - ld bc, 1 - - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - call z,ReloadReadGamma - -CopyMatch3: - push hl ; preserve source - ld hl, (PrevOffset+1) ; restore offset - add hl, de ; HL = dest - offset - - ; because BC>=3-1, we can do 2 x LDI safely - ldi - ldir - inc c - ldi - pop hl ; restore source - - ; after a match you can have either - ; 0 + = run of literals, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match -AfterMatch3: - add a, a - jr c, UsualMatch - -RunOfLiterals: - inc c - add a, a - jr nc, LongerRun - jr nz, CopyLiteral ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, CopyLiteral - -LongerRun: - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - jr nz, CopyLiterals - - ld a, (hl) ; reload bits - inc hl - rla - - call nc, ReadGammaAligned - -CopyLiterals: - ldi - -CopyLiteral: - ldir - - ; after a literal run you can have either - ; 0 + = match using a repeated offset, or - ; 1 + + [7-bits of offset lsb + 1-bit of length] + = another match - add a, a - jr c, UsualMatch - -RepMatch: - inc c - add a, a - jr nc, LongerRepMatch - jr nz, CopyMatch1 ; NZ after NC == "confirmed C" - - ld a, (hl) ; reload bits - inc hl - rla - - jr c, CopyMatch1 - -LongerRepMatch: - add a, a ; inline read gamma - rl c - add a, a - jr nc, $-4 - - jp nz, CopyMatch1 - - ; this is a crafty equivalent of CALL ReloadReadGamma : JP CopyMatch1 - push ix - - ; the subroutine for reading the remainder of the partly read Elias gamma code. - ; it has two entry points: ReloadReadGamma first refills the bit reservoir in A, - ; while ReadGammaAligned assumes that the bit reservoir has just been refilled. -ReloadReadGamma: - ld a, (hl) ; reload bits - inc hl - rla - - ret c -ReadGammaAligned: - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a -ReadingLongGamma: ; this loop does not need unrolling, as it does not get much use anyway - ret c - add a, a - rl c - rl b - add a, a - jr nz, ReadingLongGamma - - ld a, (hl) ; reload bits - inc hl - rla - jr ReadingLongGamma diff --git a/Content/tools/zx0/z80/dzx0_mega.asm b/Content/tools/zx0/z80/dzx0_mega.asm deleted file mode 100644 index c3713d4..0000000 --- a/Content/tools/zx0/z80/dzx0_mega.asm +++ /dev/null @@ -1,452 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas -; "Mega" version (673 bytes, 28% faster) -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_mega: - ld bc, $ffff ; preserve default offset 1 - ld (dzx0m_last_offset+1), bc - inc bc - jr dzx0m_literals0 - -dzx0m_new_offset6: - ld c, $fe ; prepare negative offset - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset5 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset3 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset1 -dzx0m_elias_offset1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_offset7 -dzx0m_new_offset7: - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length7 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length5 - add a, a - rl c - add a, a - jp c, dzx0m_length3 -dzx0m_elias_length3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length1 -dzx0m_length1: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset0 -dzx0m_literals0: - inc c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain length - jp c, dzx0m_literals7 - add a, a - rl c - add a, a - jp c, dzx0m_literals5 - add a, a - rl c - add a, a - jp c, dzx0m_literals3 -dzx0m_elias_literals3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals1 -dzx0m_literals1: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset0 - inc c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain length - jp c, dzx0m_reuse7 - add a, a - rl c - add a, a - jp c, dzx0m_reuse5 - add a, a - rl c - add a, a - jp c, dzx0m_reuse3 -dzx0m_elias_reuse3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse1 -dzx0m_reuse1: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals0 - -dzx0m_new_offset0: - ld c, $fe ; prepare negative offset - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset7 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset5 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset3 -dzx0m_elias_offset3: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset1 -dzx0m_new_offset1: - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length1 ; obtain length - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_length7 - add a, a - rl c - add a, a - jp c, dzx0m_length5 -dzx0m_elias_length5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length3 -dzx0m_length3: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset2 -dzx0m_literals2: - inc c - add a, a ; obtain length - jp c, dzx0m_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_literals7 - add a, a - rl c - add a, a - jp c, dzx0m_literals5 -dzx0m_elias_literals5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals3 -dzx0m_literals3: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset2 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_reuse7 - add a, a - rl c - add a, a - jp c, dzx0m_reuse5 -dzx0m_elias_reuse5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse3 -dzx0m_reuse3: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals2 - -dzx0m_new_offset2: - ld c, $fe ; prepare negative offset - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_new_offset7 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset5 -dzx0m_elias_offset5: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset3 -dzx0m_new_offset3: - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length3 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_length7 -dzx0m_elias_length7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_length5 -dzx0m_length5: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0m_new_offset4 -dzx0m_literals4: - inc c - add a, a ; obtain length - jp c, dzx0m_literals3 - add a, a - rl c - add a, a - jp c, dzx0m_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_literals7 -dzx0m_elias_literals7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_literals5 -dzx0m_literals5: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0m_new_offset4 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse3 - add a, a - rl c - add a, a - jp c, dzx0m_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_reuse7 -dzx0m_elias_reuse7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_reuse5 -dzx0m_reuse5: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals4 - -dzx0m_new_offset4: - ld c, $fe ; prepare negative offset - add a, a ; obtain offset MSB - jp c, dzx0m_new_offset3 - add a, a - rl c - add a, a - jp c, dzx0m_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp c, dzx0m_new_offset7 -dzx0m_elias_offset7: - add a, a - rl c - rl b - add a, a - jp nc, dzx0m_elias_offset5 -dzx0m_new_offset5: - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0m_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp c, dzx0m_length5 ; obtain length - add a, a - rl c - add a, a - jp c, dzx0m_length3 - add a, a - rl c - add a, a - jp c, dzx0m_length1 -dzx0m_elias_length1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_length7 -dzx0m_length7: - push hl ; preserve source - ld hl, (dzx0m_last_offset+1) - add hl, de ; calculate destination - offset - ldir ; copy from offset - inc c - ldi ; copy one more from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jp c, dzx0m_new_offset6 -dzx0m_literals6: - inc c - add a, a ; obtain length - jp c, dzx0m_literals5 - add a, a - rl c - add a, a - jp c, dzx0m_literals3 - add a, a - rl c - add a, a - jp c, dzx0m_literals1 -dzx0m_elias_literals1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_literals7 -dzx0m_literals7: - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jp c, dzx0m_new_offset6 - inc c - add a, a ; obtain length - jp c, dzx0m_reuse5 - add a, a - rl c - add a, a - jp c, dzx0m_reuse3 - add a, a - rl c - add a, a - jp c, dzx0m_reuse1 -dzx0m_elias_reuse1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - inc hl - add a, a - jp nc, dzx0m_elias_reuse7 -dzx0m_reuse7: - push hl ; preserve source -dzx0m_last_offset: - ld hl, 0 - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0m_literals6 - - jp dzx0m_new_offset6 -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_mega_back.asm b/Content/tools/zx0/z80/dzx0_mega_back.asm deleted file mode 100644 index bdbc4b7..0000000 --- a/Content/tools/zx0/z80/dzx0_mega_back.asm +++ /dev/null @@ -1,459 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas & introspec -; "Mega" version (676 bytes, 28% faster) - BACKWARDS VARIANT -; ----------------------------------------------------------------------------- -; Parameters: -; HL: last source address (compressed data) -; DE: last destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_mega_back: - ld bc, 1 ; preserve default offset 1 - ld (dzx0mb_last_offset+1), bc - jr dzx0mb_literals0 - -dzx0mb_new_offset6: - add a, a ; obtain offset MSB - jp nc, dzx0mb_new_offset5 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset3 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset1 -dzx0mb_elias_offset1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp c, dzx0mb_elias_offset7 -dzx0mb_new_offset7: - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - ld (dzx0mb_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp nc, dzx0mb_length7 ; obtain length - add a, a - rl c - add a, a - jp nc, dzx0mb_length5 - add a, a - rl c - add a, a - jp nc, dzx0mb_length3 -dzx0mb_elias_length3: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_length1 -dzx0mb_length1: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - ldd ; copy one more from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0mb_new_offset0 -dzx0mb_literals0: - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a ; obtain length - jp nc, dzx0mb_literals7 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals5 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals3 -dzx0mb_elias_literals3: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_literals1 -dzx0mb_literals1: - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jr c, dzx0mb_new_offset0 - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a ; obtain length - jp nc, dzx0mb_reuse7 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse5 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse3 -dzx0mb_elias_reuse3: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_reuse1 -dzx0mb_reuse1: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0mb_literals0 - -dzx0mb_new_offset0: - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a ; obtain offset MSB - jp nc, dzx0mb_new_offset7 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset5 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset3 -dzx0mb_elias_offset3: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_offset1 -dzx0mb_new_offset1: - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - ld (dzx0mb_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp nc, dzx0mb_length1 ; obtain length - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_length7 - add a, a - rl c - add a, a - jp nc, dzx0mb_length5 -dzx0mb_elias_length5: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_length3 -dzx0mb_length3: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - ldd ; copy one more from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0mb_new_offset2 -dzx0mb_literals2: - add a, a ; obtain length - jp nc, dzx0mb_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_literals7 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals5 -dzx0mb_elias_literals5: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_literals3 -dzx0mb_literals3: - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jr c, dzx0mb_new_offset2 - add a, a ; obtain length - jp nc, dzx0mb_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_reuse7 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse5 -dzx0mb_elias_reuse5: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_reuse3 -dzx0mb_reuse3: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0mb_literals2 - -dzx0mb_new_offset2: - add a, a ; obtain offset MSB - jp nc, dzx0mb_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_new_offset7 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset5 -dzx0mb_elias_offset5: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_offset3 -dzx0mb_new_offset3: - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - ld (dzx0mb_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp nc, dzx0mb_length3 ; obtain length - add a, a - rl c - add a, a - jp nc, dzx0mb_length1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_length7 -dzx0mb_elias_length7: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_length5 -dzx0mb_length5: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - ldd ; copy one more from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0mb_new_offset4 -dzx0mb_literals4: - add a, a ; obtain length - jp nc, dzx0mb_literals3 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_literals7 -dzx0mb_elias_literals7: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_literals5 -dzx0mb_literals5: - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jr c, dzx0mb_new_offset4 - add a, a ; obtain length - jp nc, dzx0mb_reuse3 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_reuse7 -dzx0mb_elias_reuse7: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_reuse5 -dzx0mb_reuse5: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0mb_literals4 - -dzx0mb_new_offset4: - add a, a ; obtain offset MSB - jp nc, dzx0mb_new_offset3 - add a, a - rl c - add a, a - jp nc, dzx0mb_new_offset1 - add a, a - rl c - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp nc, dzx0mb_new_offset7 -dzx0mb_elias_offset7: - add a, a - rl c - rl b - add a, a - jp c, dzx0mb_elias_offset5 -dzx0mb_new_offset5: - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - ld (dzx0mb_last_offset+1), bc ; preserve new offset - ld bc, 1 - jp nc, dzx0mb_length5 ; obtain length - add a, a - rl c - add a, a - jp nc, dzx0mb_length3 - add a, a - rl c - add a, a - jp nc, dzx0mb_length1 -dzx0mb_elias_length1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp c, dzx0mb_elias_length7 -dzx0mb_length7: - push hl ; preserve source - ld hl, (dzx0mb_last_offset+1) - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - ldd ; copy one more from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jp c, dzx0mb_new_offset6 -dzx0mb_literals6: - add a, a ; obtain length - jp nc, dzx0mb_literals5 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals3 - add a, a - rl c - add a, a - jp nc, dzx0mb_literals1 -dzx0mb_elias_literals1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp c, dzx0mb_elias_literals7 -dzx0mb_literals7: - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jp c, dzx0mb_new_offset6 - add a, a ; obtain length - jp nc, dzx0mb_reuse5 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse3 - add a, a - rl c - add a, a - jp nc, dzx0mb_reuse1 -dzx0mb_elias_reuse1: - add a, a - rl c - rl b - ld a, (hl) ; load another group of 8 bits - dec hl - add a, a - jp c, dzx0mb_elias_reuse7 -dzx0mb_reuse7: - push hl ; preserve source -dzx0mb_last_offset: - ld hl, 0 - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0mb_literals6 - - jp dzx0mb_new_offset6 -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_standard.asm b/Content/tools/zx0/z80/dzx0_standard.asm deleted file mode 100644 index ec8d3dc..0000000 --- a/Content/tools/zx0/z80/dzx0_standard.asm +++ /dev/null @@ -1,61 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas & Urusergi -; "Standard" version (68 bytes only) -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_standard: - ld bc, $ffff ; preserve default offset 1 - push bc - inc bc - ld a, $80 -dzx0s_literals: - call dzx0s_elias ; obtain length - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0s_new_offset - call dzx0s_elias ; obtain length -dzx0s_copy: - ex (sp), hl ; preserve source, restore offset - push hl ; preserve offset - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore offset - ex (sp), hl ; preserve offset, restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0s_literals -dzx0s_new_offset: - pop bc ; discard last offset - ld c, $fe ; prepare negative offset - call dzx0s_elias_loop ; obtain offset MSB - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - push bc ; preserve new offset - ld bc, 1 ; obtain length - call nc, dzx0s_elias_backtrack - inc bc - jr dzx0s_copy -dzx0s_elias: - inc c ; interlaced Elias gamma coding -dzx0s_elias_loop: - add a, a - jr nz, dzx0s_elias_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0s_elias_skip: - ret c -dzx0s_elias_backtrack: - add a, a - rl c - rl b - jr dzx0s_elias_loop -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_standard_back.asm b/Content/tools/zx0/z80/dzx0_standard_back.asm deleted file mode 100644 index 2a52af8..0000000 --- a/Content/tools/zx0/z80/dzx0_standard_back.asm +++ /dev/null @@ -1,62 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas -; "Standard" version (69 bytes only) - BACKWARDS VARIANT -; ----------------------------------------------------------------------------- -; Parameters: -; HL: last source address (compressed data) -; DE: last destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_standard_back: - ld bc, 1 ; preserve default offset 1 - push bc - ld a, $80 -dzx0sb_literals: - call dzx0sb_elias ; obtain length - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jr c, dzx0sb_new_offset - call dzx0sb_elias ; obtain length -dzx0sb_copy: - ex (sp), hl ; preserve source, restore offset - push hl ; preserve offset - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore offset - ex (sp), hl ; preserve offset, restore source - add a, a ; copy from literals or new offset? - jr nc, dzx0sb_literals -dzx0sb_new_offset: - inc sp ; discard last offset - inc sp - call dzx0sb_elias ; obtain offset MSB - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - push bc ; preserve new offset - ld bc, 1 ; obtain length - call c, dzx0sb_elias_backtrack - inc bc - jr dzx0sb_copy -dzx0sb_elias_backtrack: - add a, a - rl c - rl b -dzx0sb_elias: - add a, a ; inverted interlaced Elias gamma coding - jr nz, dzx0sb_elias_skip - ld a, (hl) ; load another group of 8 bits - dec hl - rla -dzx0sb_elias_skip: - jr c, dzx0sb_elias_backtrack - ret -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_turbo.asm b/Content/tools/zx0/z80/dzx0_turbo.asm deleted file mode 100644 index eb0ce28..0000000 --- a/Content/tools/zx0/z80/dzx0_turbo.asm +++ /dev/null @@ -1,100 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas & introspec -; "Turbo" version (126 bytes, 21% faster) -; ----------------------------------------------------------------------------- -; Parameters: -; HL: source address (compressed data) -; DE: destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_turbo: - ld bc, $ffff ; preserve default offset 1 - ld (dzx0t_last_offset+1), bc - inc bc - ld a, $80 - jr dzx0t_literals -dzx0t_new_offset: - ld c, $fe ; prepare negative offset - add a, a - jp nz, dzx0t_new_offset_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_new_offset_skip: - call nc, dzx0t_elias ; obtain offset MSB - inc c - ret z ; check end marker - ld b, c - ld c, (hl) ; obtain offset LSB - inc hl - rr b ; last offset bit becomes first length bit - rr c - ld (dzx0t_last_offset+1), bc ; preserve new offset - ld bc, 1 ; obtain length - call nc, dzx0t_elias - inc bc -dzx0t_copy: - push hl ; preserve source -dzx0t_last_offset: - ld hl, 0 ; restore offset - add hl, de ; calculate destination - offset - ldir ; copy from offset - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0t_new_offset -dzx0t_literals: - inc c ; obtain length - add a, a - jp nz, dzx0t_literals_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_literals_skip: - call nc, dzx0t_elias - ldir ; copy literals - add a, a ; copy from last offset or new offset? - jr c, dzx0t_new_offset - inc c ; obtain length - add a, a - jp nz, dzx0t_last_offset_skip - ld a, (hl) ; load another group of 8 bits - inc hl - rla -dzx0t_last_offset_skip: - call nc, dzx0t_elias - jp dzx0t_copy -dzx0t_elias: - add a, a ; interlaced Elias gamma coding - rl c - add a, a - jr nc, dzx0t_elias - ret nz - ld a, (hl) ; load another group of 8 bits - inc hl - rla - ret c - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a - ret c - add a, a - rl c - add a, a - ret c -dzx0t_elias_loop: - add a, a - rl c - rl b - add a, a - jr nc, dzx0t_elias_loop - ret nz - ld a, (hl) ; load another group of 8 bits - inc hl - rla - jr nc, dzx0t_elias_loop - ret -; ----------------------------------------------------------------------------- diff --git a/Content/tools/zx0/z80/dzx0_turbo_back.asm b/Content/tools/zx0/z80/dzx0_turbo_back.asm deleted file mode 100644 index d8cfaa6..0000000 --- a/Content/tools/zx0/z80/dzx0_turbo_back.asm +++ /dev/null @@ -1,99 +0,0 @@ -; ----------------------------------------------------------------------------- -; ZX0 decoder by Einar Saukas & introspec -; "Turbo" version (126 bytes, 21% faster) - BACKWARDS VARIANT -; ----------------------------------------------------------------------------- -; Parameters: -; HL: last source address (compressed data) -; DE: last destination address (decompressing) -; ----------------------------------------------------------------------------- - -dzx0_turbo_back: - ld bc, 1 ; preserve default offset 1 - ld (dzx0tb_last_offset+1), bc - ld a, $80 - jr dzx0tb_literals -dzx0tb_new_offset: - add a, a ; obtain offset MSB - call c, dzx0tb_elias - dec b - ret z ; check end marker - dec c ; adjust for positive offset - ld b, c - ld c, (hl) ; obtain offset LSB - dec hl - srl b ; last offset bit becomes first length bit - rr c - inc bc - ld (dzx0tb_last_offset+1), bc ; preserve new offset - ld bc, 1 ; obtain length - call c, dzx0tb_elias_loop - inc bc -dzx0tb_copy: - push hl ; preserve source -dzx0tb_last_offset: - ld hl, 0 ; restore offset - add hl, de ; calculate destination - offset - lddr ; copy from offset - inc c - pop hl ; restore source - add a, a ; copy from literals or new offset? - jr c, dzx0tb_new_offset -dzx0tb_literals: - add a, a ; obtain length - call c, dzx0tb_elias - lddr ; copy literals - inc c - add a, a ; copy from last offset or new offset? - jr c, dzx0tb_new_offset - add a, a ; obtain length - call c, dzx0tb_elias - jp dzx0tb_copy -dzx0tb_elias_loop: - add a, a - rl c - add a, a - ret nc -dzx0tb_elias: - jp nz, dzx0tb_elias_loop ; inverted interlaced Elias gamma coding - ld a, (hl) ; load another group of 8 bits - dec hl - rla - ret nc - add a, a - rl c - add a, a - ret nc - add a, a - rl c - add a, a - ret nc - add a, a - rl c - add a, a - ret nc -dzx0tb_elias_reload: - add a, a - rl c - rl b - add a, a - ld a, (hl) ; load another group of 8 bits - dec hl - rla - ret nc - add a, a - rl c - rl b - add a, a - ret nc - add a, a - rl c - rl b - add a, a - ret nc - add a, a - rl c - rl b - add a, a - jr c, dzx0tb_elias_reload - ret -; -----------------------------------------------------------------------------