├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── benchmark ├── Makefile ├── benchmark_bitfire.ods ├── checksum.asm └── files │ ├── a │ ├── a.lz │ ├── b │ ├── b.lz │ ├── c │ ├── c.lz │ ├── d │ ├── d.lz │ ├── e │ ├── e.lz │ ├── f │ ├── f.lz │ ├── g │ ├── g.lz │ ├── h │ ├── h.lz │ ├── i │ ├── i.lz │ ├── j │ ├── j.lz │ ├── k │ ├── k.lz │ ├── l │ ├── l.lz │ ├── m │ ├── m.lz │ ├── n │ ├── n.lz │ ├── o │ ├── o.lz │ ├── p │ ├── p.lz │ ├── q │ ├── q.lz │ ├── r │ └── r.lz ├── changelog ├── config.inc ├── crtwrite ├── Makefile ├── bootstrap.asm ├── crtwrite.c ├── debug.h └── loop.asm ├── d64write ├── Makefile ├── d64.h ├── d64write.c ├── debug.h ├── romchar.h └── stb_image.h ├── example ├── depack_only │ ├── Makefile │ └── example.asm ├── dirart │ ├── exampledir.bin │ └── exampledir.png ├── example_project │ ├── bitfire │ │ └── place_bitfire_as_a_submodule_here │ ├── bootstrap │ │ ├── Makefile │ │ └── boot.asm │ ├── config.inc │ ├── installer │ │ ├── Makefile │ │ └── installer.asm │ ├── link │ │ └── Makefile.example.for.demo.build │ └── music.inc └── loadertest │ ├── Makefile │ ├── example.asm │ └── files │ ├── pic1.bin │ └── pic2.bin ├── loader ├── Makefile ├── constants.inc ├── detect.asm ├── drivecode.asm ├── frag.c ├── gcr_tables.c ├── gcrstream.c ├── installer.asm ├── resident.asm ├── tables1 └── tables2 ├── macros ├── Makefile ├── convert.sh ├── link_macros_64tass.inc ├── link_macros_acme.inc ├── link_macros_ca65.inc ├── link_macros_dasm.inc ├── link_macros_dreamass.inc └── link_macros_kickass.inc ├── music.inc ├── packer ├── dali │ ├── Makefile │ ├── dali.c │ ├── dzx0_dali.asm │ ├── dzx0_orig_zx0_v1.asm │ ├── dzx0_orig_zx0_v2.asm │ ├── example.asm │ └── sfx.asm └── zx0 │ ├── 6502 │ ├── Makefile │ ├── depack.asm │ ├── dzx0_v1.asm │ ├── dzx0_v2.asm │ ├── testfile │ └── testfile.zx0 │ ├── LICENSE │ ├── Makefile │ ├── compress.c │ ├── compress.h │ ├── dzx0.c │ ├── optimize.c │ ├── optimize.h │ ├── sfx.asm │ ├── zx0.c │ └── zx0.h ├── readme.txt └── syncpoints.inc /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packer/dali/salvador"] 2 | path = packer/dali/salvador 3 | url = https://github.com/emmanuel-marty/salvador.git 4 | branch = origin/main 5 | update = merge 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Tobias Bindhammer 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKE_OPTS ?= --no-print-directory --quiet 2 | ACME ?= acme 3 | 4 | LDLIBS = 5 | CC ?= cc 6 | 7 | V ?= 0 8 | ifeq ($(V),1) 9 | VR:= 10 | else 11 | VR:=@ 12 | endif 13 | 14 | all: loader dali d64write crtwrite 15 | 16 | bitnax: FORCE 17 | @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C packer/$@ 18 | 19 | dali: FORCE 20 | @git submodule update --init --recursive 21 | @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C packer/$@ 22 | 23 | d64write: FORCE 24 | @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C $@ 25 | 26 | crtwrite: FORCE 27 | @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C $@ 28 | 29 | loader: FORCE 30 | @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C $@ 31 | 32 | #macros: FORCE 33 | # @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C $@ 34 | # 35 | #benchmark-lz: FORCE 36 | # @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C benchmark/ $@ 37 | # 38 | #benchmark-dali: FORCE 39 | # @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C benchmark/ $@ 40 | # 41 | #benchmark: FORCE dali d64write loader 42 | # @$(MAKE) $(MAKE_OPTS) ACME=$(ACME) -C benchmark/ $@ 43 | 44 | clean: 45 | # @$(MAKE) $(MAKE_OPTS) -C packer/zx0/ clean 46 | @$(MAKE) $(MAKE_OPTS) -C packer/dali/ clean 47 | @$(MAKE) $(MAKE_OPTS) -C d64write/ clean 48 | @$(MAKE) $(MAKE_OPTS) -C crtwrite/ clean 49 | @$(MAKE) $(MAKE_OPTS) -C loader/ clean 50 | # @$(MAKE) $(MAKE_OPTS) -C benchmark/ clean 51 | # @$(MAKE) $(MAKE_OPTS) -C example/loadertest/ clean 52 | 53 | FORCE: 54 | @true 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitfire 2 | 3 | Bitfire is a fixed-interleave loader system for C64 with a depacker, a basic framework and an image-writing tool. 4 | 5 | # the techniques behind it 6 | 7 | ## disk layout 8 | 9 | The sectors on a floppy disk have 256 bytes of payload. Files consist of a chain of sectors on disk that are linked together. The first two bytes of a sector's payload are used to either point to the next track/sector or give the size of the last sector being used. 10 | This means, that the de-facto payload per sector is 254 bytes, an awful number to calculate with easily. Also, the last sector of a file leaves quite a few bytes unused, as files always start on a new sector at position 0 within the sector. 11 | 12 | When assuming a fixed interleave for the blocks the file is located on, and by knowing the filsizes beforehand, in fact each single byte on a disk can be used for files, and files can be loaded in chunks of 256 bytes, which simplifies a few things in a loader. 13 | So this means, with an interleave of 4, the sectors 0, 4, 8, 12, 16, 20 are used, on wrap around, 1, 5, 9, ... and so on. When the filesize is known beforehand, the size of the last sector is also known. 14 | Now it is possible to glue each file after another without any gaps in between. This means, however, that a new dir-layout is needed, as the native layout can not compensate for such design changes. For that purpose, 2 sectors on track 18 are spent with 63 entries each, while the native directory still exists for dir-layout, standard files and the bootloader. 15 | 16 | The bitfire dir entries only contain the load-address and the filesize and are accessed by number, which is more than sufficient for a demo. Most of the time these will load sequentially from disk. Random file-access is nevertheless still possible. 17 | By walking through the file list and adding up filesizes, the right track/sector and offset within a sector can be determined. Each dir-sector has a track, sector and block index it starts at. That is why only 63 entries are located on it, as that information is also stored in the dir-sector. The final remaining byte is used to indicate the disk-side. 18 | 19 | The layout of a dir-sector: 20 | 21 | pos | content 22 | --- | ------- 23 | $00 | track where first file starts 24 | $01 | index to sector first file starts 25 | $02 | position in sector first file starts 26 | $03 | disk-side info 27 | $04 | load-address lowbyte 28 | $44 | load-address hibyte 29 | $84 | filesize lowbyte 30 | $c4 | filesize hibyte 31 | ... | ... repeated 63 times ... 32 | 33 | ## GCR-loop 34 | 35 | The data on disk is GCR-enocded, so every nibble of a byte is represented by a quintuple on disk. To make the decoding fast enough, tables are used to look up data-portions for low- and high-nibbles that are finally merged together to form the original bytes. This happens so fast that the checksumming of a sector is also done on the fly. The tables also have further advantages, as bits can be swapped, so they are better suited to a specific method of serial transfer later on. However, debugging or sending variable values over the serial bus are more complicated then, as they need to be scrambled/descrambled beforehand to the needed bit order. 36 | 37 | So 8 nibbles are represented like this on disc and stored in 8 quintuples on disc: 38 | 39 | ``` 40 | 11111222 22333334 44445555 56666677 77788888 41 | ``` 42 | 43 | Things are shifted and masked together, so that the read values represent the following orders: 44 | 45 | ``` 46 | 11111000 47 | 02200222 48 | 00333330 49 | 44444000 50 | 00005555 51 | 05666660 note: the last bit of 5 is added with the 6th nibble 52 | 0070dd77 note: bit 0, 2 can be formed to one partition, this are the remaining bits 1, 3, 4 53 | 7d788888 note: the resulting table is big, but this saves masking and decodes 7 bits at once! 54 | ``` 55 | 56 | As one can see, the quintuples can be partitioned in some way, but in the gcr encoding choosen this is very restricted. Bit 2 even reflects the same bit in the gcr and raw data, bit 0 can also be clipped of and added again with ora, adc or eor. So a quintuple can be partitoned like this: 57 | ``` 58 | 43210 -> 4321. + ....0 59 | 43210 -> 43.10 + ..2.. 60 | 43210 -> 43.1. + ..2.0 61 | ``` 62 | 63 | Sadly, no partitioning is possible in those ways (only if you change the mapping for the gcr-codes): 64 | ``` 65 | 43210 -> 432.. + ...10 66 | 43210 -> 43... + ..210 67 | 43210 -> 4.... + .3210 68 | ``` 69 | 70 | The tables can be arranged in a way (with offsets) that many of them overlay nicely and merge into a small area to save space. One table is located in the first half of the zeropage, the gaps are used for variables and lists for the loader. Another table is located @ $0200 where the gaps are filled with code. The 0070dd77-table is located @ $0300, as it is very small, it can be easily interleaved into the code. If using a more strict mask on the seventh table or also other tables, the size could be reduced even more, but all this costs cycles in the gcr-loop, resulting in a less tolerant behaviour. 71 | Read bytes are directly stored on the stack via PHA, as this only needs 3 cycles for a written byte. This however makes it impossible to use the stack for most of the code, so most of all JSR calls need to be avoided as they would destroy data on the stack. 72 | 73 | ## salvador / zx0 74 | 75 | The original [zx0 packer](https://github.com/einar-saukas/ZX0) is done by Einar Saukas (thanks for the many mails and discussions and exchange of ideas!) and yields a really good pack-ratio and depacking speed! 76 | Meanwhile also [salvador](https://github.com/emmanuel-marty/salvador) emerged that features very fast compression speeds compared to zx0 and yields results that are nearly as good, while being compatible with zx0, regarding the output format. I added a recoder named dali under packer/dali that wraps salvador and outputs compressed files in a bitfire compatible format, as i changed a few things on the encoding to optimise the format for little endian, speed up things and shrink the depacker-code. This wrapper also does all the c64-specific things you are used to from bitfire, like handling load-addresses, relocation, cutting and a featuring a self extractor. It substitutes the modified zx0 that also comes along with bitfire so far. The new depacker is not compatible with the modified zx0 anymore, so dali is the new way to go. 77 | 78 | The most notable changes in the encoding are the drop of the xor 0xff on the LSB of the offset, so offsets are now subtracted and not added. I also changed the order of MSB and LSB bits, sent via the interlaced elias gamma encoding. Lengths greater than 8 bit happen very rarely, and thus an extra 8 bit loop is done first and only extended to 16 bit if necessary. This speeds up bitfetching in 6502 quite a bit. To save upon the setup of .lz_bits i changed direction of the bitbuffer, it is now shifted right. 79 | 80 | In-place depacking was also added, so that files can be directly loaded and depacked within the memory range the unpacked data would land in anyway. So no more safety-margins, deltas, overlap or however you name it, needs to be taken care of, except, if you depack out of another location. To achieve that, the end-marker is clamped off, and encoding is interupted as soon as a match or literal would overwrite the still packed data. From there on the data is output as plain unencoded literal. It is there in memory, where it belongs anyway. 81 | 82 | Besides the adopted version there's also a compatible version for the original zx0 format used by the original zx0 and salvador. It can be found [here](https://github.com/bboxy/bitfire/tree/master/packer/zx0/6502) for either versions, v1 and v2. 83 | 84 | ## future work 85 | 86 | The tables needed for decoding could be shrunk in several ways. One way to do so is more precise masking and not adding any bits we don't care about. By swapping nibbles (3 and 4), the 44444000_lo table could be replaced by the 11111000_hi table. The eor-checksum for the native d64-format would then fail, however. The tables 05666660_lo and 7d788888_lo could be used in the same way if an additional bit would be added or the 7d788888 table is shifted one to the left. So far this means extra code to achieve smaller tables, and this has not been implemented but there's quite some potential left. 87 | -------------------------------------------------------------------------------- /benchmark/Makefile: -------------------------------------------------------------------------------- 1 | D64WRITE = ../d64write/d64write 2 | D64WRITE_OPTS = -v 3 | TIMESTAMP = $(shell date +%Y%m%d-%H%M%S) 4 | 5 | ACME = acme 6 | ACME_OPTS = -f cbm 7 | 8 | ZX0 = ../packer/zx0/zx0 9 | ZX0_OPTS = -f 10 | 11 | PACKER = ../packer/dali/dali 12 | 13 | all: benchmark 14 | 15 | benchmark-zx0: 16 | rm files/*.lz; for i in files/*; do $(ZX0) $(ZX0_OPTS) -o $$i.lz $$i; done 17 | benchmark-dali: 18 | rm files/*.lz; for i in files/*; do $(PACKER) $(PACKER_OPTS) -o $$i.lz $$i; done 19 | 20 | benchmark: checksum.asm Makefile ../loader/installer 21 | -rm side*.d64 22 | -rm installer*.prg 23 | $(MAKE) -C ../ 24 | $(ACME) $(ACME_OPTS) -o $@ $< 25 | #exomizer sfx 0x0900 -o $@.prg $@ 26 | $(PACKER) $(PACKER_OPTS) --sfx 0x0900 -o $@.prg $@ 27 | #$(ZX0) $(ZX0_OPTS) --sfx 0x0900 -o $@.prg $@ 28 | cp benchmark.prg installer$(TIMESTAMP).prg 29 | $(D64WRITE) $(D64WRITE_OPTS) -c side$(TIMESTAMP).d64 -h oxyron -i \<3 \ 30 | --boot $@.prg \ 31 | -b files/a.lz \ 32 | -b files/b.lz \ 33 | -b files/c.lz \ 34 | -b files/d.lz \ 35 | -b files/e.lz \ 36 | -b files/f.lz \ 37 | -b files/g.lz \ 38 | -b files/h.lz \ 39 | -b files/i.lz \ 40 | -b files/j.lz \ 41 | -b files/k.lz \ 42 | -b files/l.lz \ 43 | -b files/m.lz \ 44 | -b files/n.lz \ 45 | -b files/o.lz \ 46 | -b files/p.lz \ 47 | -b files/q.lz \ 48 | -b files/r.lz \ 49 | -b files/b.lz \ 50 | -b files/b.lz \ 51 | -b files/b.lz \ 52 | -b files/e.lz 53 | 54 | x64sc side$(TIMESTAMP).d64 55 | 56 | clean: 57 | -rm side*.d64 insstaller*.prg benchmark benchmark.prg 58 | -------------------------------------------------------------------------------- /benchmark/benchmark_bitfire.ods: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/benchmark_bitfire.ods -------------------------------------------------------------------------------- /benchmark/files/a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/a -------------------------------------------------------------------------------- /benchmark/files/a.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/a.lz -------------------------------------------------------------------------------- /benchmark/files/b: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/b -------------------------------------------------------------------------------- /benchmark/files/b.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/b.lz -------------------------------------------------------------------------------- /benchmark/files/c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/c -------------------------------------------------------------------------------- /benchmark/files/c.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/c.lz -------------------------------------------------------------------------------- /benchmark/files/d: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/d -------------------------------------------------------------------------------- /benchmark/files/d.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/d.lz -------------------------------------------------------------------------------- /benchmark/files/e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/e -------------------------------------------------------------------------------- /benchmark/files/e.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/e.lz -------------------------------------------------------------------------------- /benchmark/files/f: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/f -------------------------------------------------------------------------------- /benchmark/files/f.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/f.lz -------------------------------------------------------------------------------- /benchmark/files/g: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/g -------------------------------------------------------------------------------- /benchmark/files/g.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/g.lz -------------------------------------------------------------------------------- /benchmark/files/h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/h -------------------------------------------------------------------------------- /benchmark/files/h.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/h.lz -------------------------------------------------------------------------------- /benchmark/files/i: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/i -------------------------------------------------------------------------------- /benchmark/files/i.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/i.lz -------------------------------------------------------------------------------- /benchmark/files/j: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/j -------------------------------------------------------------------------------- /benchmark/files/j.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/j.lz -------------------------------------------------------------------------------- /benchmark/files/k: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/k -------------------------------------------------------------------------------- /benchmark/files/k.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/k.lz -------------------------------------------------------------------------------- /benchmark/files/l: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/l -------------------------------------------------------------------------------- /benchmark/files/l.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/l.lz -------------------------------------------------------------------------------- /benchmark/files/m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/m -------------------------------------------------------------------------------- /benchmark/files/m.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/m.lz -------------------------------------------------------------------------------- /benchmark/files/n: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/n -------------------------------------------------------------------------------- /benchmark/files/n.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/n.lz -------------------------------------------------------------------------------- /benchmark/files/o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/o -------------------------------------------------------------------------------- /benchmark/files/o.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/o.lz -------------------------------------------------------------------------------- /benchmark/files/p: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/p -------------------------------------------------------------------------------- /benchmark/files/p.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/p.lz -------------------------------------------------------------------------------- /benchmark/files/q: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/q -------------------------------------------------------------------------------- /benchmark/files/q.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/q.lz -------------------------------------------------------------------------------- /benchmark/files/r: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/r -------------------------------------------------------------------------------- /benchmark/files/r.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/benchmark/files/r.lz -------------------------------------------------------------------------------- /changelog: -------------------------------------------------------------------------------- 1 | v0.2: 2 | - shrunk drivecode size 3 | - serial transfer back at 74 cycles / byte 4 | - fixed sporadic data corruption while loading 5 | - to allow more variance in rotation speed of disc 6 | 7 | v0.3: 8 | - further shrunk drive- and resident code 9 | - added 40 track support 10 | - removed intermittent stepping for now as it caused some problems 11 | - NTSC support via config (no autodetect yet) 12 | - removed depack offset feature, too bloated 13 | 14 | v0.4: 15 | - waste more cycles when uploading code, here it's a good thing :-) 16 | - added load_next functionality 17 | - added all config params to config.inc, also addresses and so on 18 | - added signalling for first block to be transferred, so less painfull and 19 | smaller code 20 | - added ntsc autodetection and modify code in case 21 | - resident part is now copied by installer, no further manual copy action 22 | needed. Calling bitfire_install_ is now sufficient. 23 | - added a basic framework with load/load_next hooks that can be called safely 24 | without being overwritten, including macros for linking 25 | - initial detection code for sid/cia type with globally available flags 26 | - offloaded blockmap handling and barriers to diskdrive (saves a fair amount 27 | of space on the resident part!) 28 | - further drivecode cleanup and thus saving bytes 29 | - track now checked via header checksum, no explicit checks needed anymore 30 | - bitnax allows now to reference preceeding data that is split/cut off with 31 | --cut-load-addr. This makes files smaller, but preceeding data must be loaded 32 | and depacked beforehand. --full-dict is introduced as switch for that. 33 | 34 | v0.5: 35 | - overlap is calculated on a new basis and thus lower 36 | - depack can be done completely in place with zero overlap. This is the new 37 | default. Switch back to old behaviour, but tighter margins with --overlap when using bitnax 38 | - d64write spits out blocks free 39 | - fix assert bug (bailed out with false alarm) on files with huge literals 40 | - fix compilation error with resident.asm when NMI_GAPS are used without 41 | framework 42 | - clean up errors and added warnings on lz.c, and added possibility to exit on 43 | warnings (good if build output is too messy to spot the warnings) 44 | - more documentation 45 | 46 | v0.6: 47 | - fix broken NTSC ;_; the indexed opcodes changed from ,x to ,y and an extra nop cured 48 | many things 49 | - shrink resident code size, after we have bloated it with in place depacking 50 | - standalone loader size now $7b bytes \o/ 51 | - faster init 52 | - get rid of inversion during sending of data (filename/init) 53 | - allow for an even wider rpm variance when reading a sector/header 54 | - fixed packer. With a given --load-addr and zero overlap option, the last 55 | literal was not copied. It is now included into the stream in that case, and 56 | it is taken care that the file ends with a 257 byte match to signal EOF. Also 57 | needed a fix in the depacker that slows it down :-( 58 | - motor spin up time: relying on checksums is not enough there, in very rare 59 | cases we happen to load junk despite all the checksumming. What a bother! Now 60 | loading arbitrary blocks on spin up until there's success. 61 | - shrink drivecode size after those additions 62 | - testsuite now included 63 | - fixed code upload/reset_drive 64 | - even faster init 65 | - fixed decomp under IO issues and issues with loading of remaining literal 66 | blobs > 255 bytes 67 | - improved depacker speed a bit after other fixes slowed it down and bloat 68 | resident size again up to the max by that, dammit! :-D 69 | - fixed different $01 values depending on hw-detection 70 | - added resident_minimal_zp.asm a minimal version residing in zeropage. Could 71 | be squeezed down to $6a bytes. Useful? 72 | - added --relocate-to addr switch to pack files as if loaded with an 73 | alternative load-address (also helps with --binfile) 74 | - give notice if more then 1 drive is on bus to avoid injuries and pebcak 75 | - switch to 2MHz mode where possible on 1571 especially during transfer to 76 | be on the safe side 77 | 78 | v0.7 79 | - add also sln and vcproj files for bitnax 80 | - possibility to choose between NMI and raster IRQ for baseirq 81 | - add possibility for buslock to allow arbitary $dd00 writes when loader is 82 | idle, and add macros for that (bus_lock, bus_unlock $bank) 83 | - fix spin up handling of read dummy sectors (might have been skipped under 84 | some circumstances) 85 | 86 | v1.0-alpha 87 | - rewrite of many parts 88 | - reduced dir-entries to 4 byte, only two dir-sectors are needed max 89 | - add on the fly gcr-decoding and checksumming 90 | - 72 cycles transfer loop 91 | - use each sector to 100%, no zeropadded last blcoks of file \o/ 92 | - standard files can be linked to certain lines of dir-art 93 | - dir-art now also sets blocksize, filetype and locked status of files 94 | - more sanity checks during disk read 95 | - loading of file number $ff now resets drive, $f0-$fe for requesting disc-sides 96 | - 63 dir-entries per dir-sector 97 | - sfx.asm can now be adopted and is integrated into bitnax/zx0 at compile time 98 | - bus_lock feature improved 99 | - an ATN-responder is uploaded to all remaining drives, so they can stay turned on 100 | - loader is started from current drive ($ba) 101 | - added and adopted zx0 by Einar Saukas as new standard packer/depacker, tiny files, fast depack \o/ 102 | 103 | v1.0 104 | - new dir structure 105 | - wait 4s until motor spin down 106 | - NTSC works again 107 | - amount of free blocks in d64 can be manipulated with d64write --free, play at your own risk, as it corrupts the BAM somewhat 108 | - fixed barrier bug 109 | - minor speedup 110 | - slow down stepping to make it work with some ALPS and Sankyo-mechanics 111 | - tested on 1541U-II, UK1541, 1541-II (Sankyo, JPN, Mitsumi), 1541 & 1541C (Mitsumi, ALPS) 112 | - works okay on 287-312 rpm on all speedzones 113 | - error logging 114 | - saved space on gcr-tables by combining bit 0 and 2 in one partition 115 | - shrink drivecode 116 | - dali (salvador) as the new packer in the place to be 117 | - speedup of depacker 118 | - smaller depacker code 119 | - reduced code in the resident part 120 | - reworking sfx code 121 | - more sfx options 122 | 123 | v1.1 124 | - faster decompressor 125 | - reworked preamble-xfer 126 | - loadraw: ~22% faster than with v0.7 127 | - loadcomp: ~14% faster than with v0.7 128 | - decomp: ~20% faster than with v0.7 129 | - pack ratio: ~5,5% smaller than bitnax 130 | - add --prefix-from to dali 131 | - add --prefix-file to dali 132 | 133 | v1.2 134 | - dali compiles on more targets now (ARM64), also Windows-executables are possible 135 | - dali now supports --exit_on_warn 136 | - added proper depack-example to dali 137 | - dali sfx can be relocated to any address (upon feature request by comos) 138 | - fixed bug in fast dali sfx 139 | - 3.5% faster decompressor 140 | - fixed bug, inplace decompression would miss loading sectors if final literal is > than 1 sector/crosses 2 sectors or more 141 | - turn disk is a simple loadraw with file# $fx now that returns when done 142 | - fixed nasty bitrate bug in drivecode that would sometimes choose wrong bitrate on slowest speed zone and bring timing to its edge 143 | - finally fixed and changed buslock-technique so that it also works with THCM's SX64 - broken since introduced in 0.7 /o\ 144 | - saved huge amount of bytes 145 | - changed layout of dir-sector 146 | - use free memory for proper caching of first/last sector, thanks to $0262 bytes free for cache and dir 147 | - improve loadraw performance by more than 5% 148 | - sending data between halfsteps seemed to cause problems on my longboard 1541, moved it to the end of stepping when settle time for the stepper is due 149 | - fixed bug with uninitialized d64 in d64write 150 | - added .c (petscii editor by marq) and .png support for dirart (save without border!) 151 | - bootfile can be linked to a single line of dirart (had bugs, fixed now) 152 | - variable interleave per speedzone 153 | - dirart can be loaded raw, use at your own risk 154 | - files can be skipped when using load_next mechanism with a skip_file macro 155 | - filenumbers are shown for bitfire files in the summary 156 | - avoid linking standard or bootfile to other filetypes than prg 157 | - fixed optimal load address on dali when using --no-inplace option 158 | 159 | v1.3 160 | shorter resident part 161 | move from libpng to stb_image.h for less dependecies like on cygwin 162 | -------------------------------------------------------------------------------- /config.inc: -------------------------------------------------------------------------------- 1 | !ifndef CONFIG_LOADED { 2 | 3 | ;options for resident part 4 | CONFIG_RESIDENT_ADDR = $f000 5 | CONFIG_ZP_ADDR = $02 ;maximum 11 bytes needed, 5 for loader, 6 for depacker 6 | CONFIG_LAX_ADDR = $00 ;Usually save to have the value $37 here, but can be also set elsewhere, but must stay persistent during loading 7 | 8 | ;options for installer 9 | CONFIG_INSTALLER_ADDR = $1000 10 | 11 | ;only compile with loader, no depacker 12 | CONFIG_LOADER_ONLY = 0 ;Only compile loader standalone 13 | 14 | CONFIG_NEXT_DOUBLE = 0 ;If enabled the old load_next_double code stays in resident area (Hi Bob/Censor!) 15 | 16 | ;options for drivecode 17 | CONFIG_MOTOR_ALWAYS_ON = 0 ;If you want to be annoying, let the motor spin during the whole demo :-D 18 | 19 | ;enable crt loader only 20 | CONFIG_CRT = 0 21 | 22 | CONFIG_DEBUG = 0 23 | 24 | CONFIG_DEPACK_ONLY = 0 ;Only compile the bare depacker 25 | } 26 | -------------------------------------------------------------------------------- /crtwrite/Makefile: -------------------------------------------------------------------------------- 1 | CRTWRITE_CFLAGS = $(CFLAGS) -Ofast -Wall 2 | CRTWRITE_LIBS = $(CLIBS) -lpng 3 | ACME ?= acme 4 | ACME_OPTS ?= -f cbm 5 | 6 | ifdef win 7 | CC = x86_64-w64-mingw32-gcc 8 | STRIP = x86_64-w64-mingw32-strip 9 | else ifdef win32 10 | CC = x86_64-w64-mingw32-gcc-win32 11 | STRIP = x86_64-w64-mingw32-strip 12 | else 13 | CC ?= gcc 14 | STRIP ?= strip 15 | endif 16 | 17 | V ?= 0 18 | ifeq ($(V),1) 19 | VR:= 20 | else 21 | VR:=@ 22 | endif 23 | 24 | SOURCE:= crtwrite.c 25 | HEADER:= *.h 26 | 27 | all: crtwrite 28 | 29 | crtwrite: $(SOURCE) $(HEADER) bootstrap.h 30 | @echo "Building crtwrite..." 31 | $(VR)$(CC) $(CRTWRITE_CFLAGS) -o $@ $(SOURCE) $(CRTWRITE_LIBS) 32 | ifdef win 33 | $(VR)$(STRIP) $@.exe 34 | else ifdef win32 35 | $(VR)$(STRIP) $@.exe 36 | else 37 | $(VR)$(STRIP) $@ 38 | endif 39 | bootstrap.h: bootstrap.asm 40 | $(VR)$(ACME) $(ACME_OPTS) --labeldump $(basename $@).lst -o $(basename $@) $< 41 | $(VR)echo 'static const char bootstrap[] = {' > $@ 42 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 43 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 44 | $(VR)echo '};' >> $@ 45 | $(VR)rm $(basename $@).lst $(basename $@) 46 | 47 | clean: 48 | $(VR)-rm crtwrite bootstrap.h 49 | -------------------------------------------------------------------------------- /crtwrite/bootstrap.asm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/crtwrite/bootstrap.asm -------------------------------------------------------------------------------- /crtwrite/crtwrite.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * The name of its author may not be used to endorse or promote products 12 | * derived from this software without specific prior written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef _MSC_VER 35 | #else 36 | #include 37 | #endif 38 | 39 | #include "debug.h" 40 | #include "bootstrap.h" 41 | 42 | int crt_write_file(FILE* crt, char* file, int header) { 43 | FILE* fp; 44 | int c; 45 | int addr; 46 | int size = 0; 47 | 48 | fp = fopen(file, "rb"); 49 | if (!fp) { 50 | fatal_message("can't open file '%s'\n", file); 51 | } 52 | fseek(fp, 0L, SEEK_END); 53 | size = ftell(fp) - 2; 54 | rewind(fp); 55 | 56 | addr = fgetc(fp); 57 | addr |= (fgetc(fp) << 8); 58 | 59 | if (header) { 60 | fputc((addr & 255), crt); 61 | fputc((addr >> 8), crt); 62 | 63 | fputc((size & 255), crt); 64 | fputc((size >> 8), crt); 65 | } 66 | 67 | while ((c = fgetc(fp)) != EOF) { 68 | fputc(c, crt); 69 | } 70 | fclose(fp); 71 | return size + (header * 4); 72 | } 73 | 74 | int main(int argc, char *argv[]) { 75 | int c; 76 | FILE* crt; 77 | int crt_pos = 0; 78 | char* crt_path = NULL; 79 | int done = 0; 80 | 81 | if (argc <= 1) { 82 | printf("Usage: crtwrite -o image.bin [-b file]\n"); 83 | exit (0); 84 | } 85 | 86 | c = 0; 87 | while(++c < argc) { 88 | if(!strcmp(argv[c], "-o")) { 89 | if (crt_path) { 90 | fatal_message("image name already given ('%s')\n", crt_path); 91 | } 92 | if (argc -c > 1) { 93 | crt_path = argv[++c]; 94 | } else { 95 | fatal_message("missing path for option '%s'\n", argv[c]); 96 | } 97 | } 98 | else if(!strcmp(argv[c], "-b")) { 99 | c++; 100 | } 101 | else { 102 | fatal_message("unknown option '%s'\n", argv[c]); 103 | } 104 | } 105 | 106 | crt = fopen(crt_path, "wb"); 107 | 108 | for (c = 2; c < sizeof(bootstrap); c++) { 109 | fputc(bootstrap[c],crt); 110 | crt_pos++; 111 | } 112 | 113 | c = 0; 114 | while(++c < argc) { 115 | if(argc -c > 1 && (!strcmp(argv[c], "-b") || !strcmp(argv[c], "--boot"))) { 116 | printf("$%04x: %s\n",crt_pos,argv[c + 1]); 117 | crt_pos += crt_write_file(crt, argv[++c], 1); 118 | if (!done) { 119 | while ((crt_pos & 255) != 0) { 120 | fputc(0xff,crt); 121 | crt_pos++; 122 | } 123 | done = 1; 124 | } 125 | } 126 | } 127 | 128 | while (crt_pos < 0x100000) { 129 | fputc(0xff, crt); 130 | crt_pos++; 131 | } 132 | fclose(crt); 133 | exit(0); 134 | } 135 | 136 | -------------------------------------------------------------------------------- /crtwrite/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * The name of its author may not be used to endorse or promote products 12 | * derived from this software without specific prior written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | int debug_level; 27 | 28 | //log levels 29 | #define ENABLE_DEBUG 0 30 | #define ENABLE_BENCHMARK 1 31 | #define ENABLE_INFO 1 32 | #define ENABLE_FAIL 1 33 | #define ENABLE_FATAL 1 34 | 35 | #ifdef _MSC_VER 36 | #define debug_message(format,...); { if(ENABLE_DEBUG) { fprintf(stdout,"DEBUG: %s: %s(): ",__FILE__,__FUNCTION__); fprintf(stdout,format,__VA_ARGS__); } } 37 | #define info_message(format,...); { if(ENABLE_INFO) { fprintf(stdout,"INFO: "); fprintf(stdout,format,__VA_ARGS__); } } 38 | #define fail_message(format,...); { if(ENABLE_FAIL) { fprintf(stdout,"FAIL: %s: ",__FILE__); fprintf(stdout,format,__VA_ARGS__); } } 39 | #define fatal_message(format,...); { if(ENABLE_FATAL) { fprintf(stderr,"ERROR: "); fprintf(stderr,format,__VA_ARGS__); exit(2); } } 40 | #else 41 | #define debug_message(format,args...); { if(ENABLE_DEBUG) { fprintf(stdout,"DEBUG: %s: %s(): ",__FILE__,__FUNCTION__); fprintf(stdout,format,##args); } } 42 | #define info_message(format,args...); { if(ENABLE_INFO) { fprintf(stdout,"INFO: "); fprintf(stdout,format,##args); } } 43 | #define fail_message(format,args...); { if(ENABLE_FAIL) { fprintf(stdout,"FAIL: %s: ",__FILE__); fprintf(stdout,format,##args); } } 44 | #define fatal_message(format,args...); { if(ENABLE_FATAL) { fprintf(stderr,"ERROR: "); fprintf(stderr,format,##args); exit(2); } } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /crtwrite/loop.asm: -------------------------------------------------------------------------------- 1 | crt_loop 2 | lda $de00 3 | ldx #$04 4 | - 5 | lda $df04,x 6 | cmp signature,x 7 | bne + 8 | dex 9 | bpl - 10 | + 11 | inx 12 | bne crt_loop 13 | sei 14 | lda #$7f 15 | sta $dd0d 16 | sta $dc0d 17 | lda $dd0d 18 | lda $dc0d 19 | lda #$37 20 | sta $01 21 | jmp ($fffc) 22 | signature 23 | !byte $c3 ;c 24 | !byte $c2 ;b 25 | !byte $cd ;m 26 | !byte $38 ;8 27 | !byte $30 ;0 28 | -------------------------------------------------------------------------------- /d64write/Makefile: -------------------------------------------------------------------------------- 1 | D64WRITE_CFLAGS = $(CFLAGS) -Ofast -Wall 2 | D64WRITE_LIBS = $(CLIBS) -lm 3 | ifdef win 4 | CC = x86_64-w64-mingw32-gcc 5 | STRIP = x86_64-w64-mingw32-strip 6 | else ifdef win32 7 | CC = x86_64-w64-mingw32-gcc-win32 8 | STRIP = x86_64-w64-mingw32-strip 9 | else 10 | CC ?= gcc 11 | STRIP ?= strip 12 | endif 13 | 14 | V ?= 0 15 | ifeq ($(V),1) 16 | VR:= 17 | else 18 | VR:=@ 19 | endif 20 | 21 | SOURCE:= d64write.c 22 | HEADER:= *.h 23 | 24 | all: d64write 25 | 26 | d64write: $(SOURCE) $(HEADER) 27 | @echo "Building d64write..." 28 | $(VR)$(CC) $(D64WRITE_CFLAGS) -o $@ $(SOURCE) $(D64WRITE_LIBS) 29 | ifdef win 30 | $(VR)$(STRIP) $@.exe 31 | else ifdef win32 32 | $(VR)$(STRIP) $@.exe 33 | else 34 | $(VR)$(STRIP) $@ 35 | endif 36 | 37 | clean: 38 | $(VR)-rm d64write 39 | -------------------------------------------------------------------------------- /d64write/d64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * The name of its author may not be used to endorse or promote products 12 | * derived from this software without specific prior written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | #define TYPE_PRG 0 27 | #define TYPE_PNG 1 28 | #define TYPE_C 2 29 | 30 | #define FILETYPE_DEL 0x00 31 | #define FILETYPE_SEQ 0x01 32 | #define FILETYPE_PRG 0x02 33 | #define FILETYPE_USR 0x03 34 | #define FILETYPE_REL 0x04 35 | #define FILETYPE_DIR 0x05 36 | 37 | #define FILETYPE_STANDARD 0x00 38 | #define FILETYPE_BITFIRE 0x01 39 | #define FILETYPE_BOOT 0x02 40 | 41 | #define MAX_C64_NAME 16 42 | 43 | static const char filetype[][4] = { 44 | "DEL", /* 0x00 */ 45 | "SEQ", /* 0x01 */ 46 | "PRG", /* 0x02 */ 47 | "USR", /* 0x03 */ 48 | "REL", /* 0x04 */ 49 | "DIR", /* 0x05 */ 50 | }; 51 | 52 | #define DIR_INTERLEAVE 1 53 | #define FILE_INTERLEAVE 4 54 | 55 | #define D64_BAM_TRACK 18 56 | #define D64_BAM_SECTOR 0 57 | 58 | #define D64_DIR_TRACK 18 59 | #define D64_DIR_SECTOR 1 60 | 61 | #define D64_DRIVE_CODE_SECT 15 62 | 63 | #define BAM_FREE 1 64 | #define BAM_USED 0 65 | 66 | #define D64_MIN_TRACK 1 67 | #define D64_MAX_TRACK 35 68 | 69 | #define SECTOR_SIZE 256 70 | #define BITFIRE_DIRSECT 18 71 | 72 | #define D64_DTRACK 0x03 73 | #define D64_DSECTOR 0x04 74 | #define D64_DTYPE 0x02 75 | #define D64_DNAME 0x05 76 | #define D64_DBLOCKS 0x1e 77 | 78 | #define D64_BAM_HEADER 0x90 79 | #define D64_BAM_ID 0xa2 80 | 81 | static const int sectors[] = { 82 | 0, 83 | 21, /* track 1 */ 84 | 21, /* track 2 */ 85 | 21, /* track 3 */ 86 | 21, /* track 4 */ 87 | 21, /* track 5 */ 88 | 21, /* track 6 */ 89 | 21, /* track 7 */ 90 | 21, /* track 8 */ 91 | 21, /* track 9 */ 92 | 21, /* track 10 */ 93 | 21, /* track 11 */ 94 | 21, /* track 12 */ 95 | 21, /* track 13 */ 96 | 21, /* track 14 */ 97 | 21, /* track 15 */ 98 | 21, /* track 16 */ 99 | 21, /* track 17 */ 100 | 19, /* track 18 */ 101 | 19, /* track 19 */ 102 | 19, /* track 20 */ 103 | 19, /* track 21 */ 104 | 19, /* track 22 */ 105 | 19, /* track 23 */ 106 | 19, /* track 24 */ 107 | 18, /* track 25 */ 108 | 18, /* track 26 */ 109 | 18, /* track 27 */ 110 | 18, /* track 28 */ 111 | 18, /* track 29 */ 112 | 18, /* track 30 */ 113 | 17, /* track 31 */ 114 | 17, /* track 32 */ 115 | 17, /* track 33 */ 116 | 17, /* track 34 */ 117 | 17, /* track 35 */ 118 | 17, /* track 36 */ 119 | 17, /* track 37 */ 120 | 17, /* track 38 */ 121 | 17, /* track 39 */ 122 | 17 /* track 40 */ 123 | }; 124 | 125 | static const unsigned int track_offsets[] = { 126 | 0x00000, 127 | 0x00000, /* track 1 */ 128 | 0x01500, /* track 2 */ 129 | 0x02a00, /* track 3 */ 130 | 0x03f00, /* track 4 */ 131 | 0x05400, /* track 5 */ 132 | 0x06900, /* track 6 */ 133 | 0x07e00, /* track 7 */ 134 | 0x09300, /* track 8 */ 135 | 0x0a800, /* track 9 */ 136 | 0x0bd00, /* track 10 */ 137 | 0x0d200, /* track 11 */ 138 | 0x0e700, /* track 12 */ 139 | 0x0fc00, /* track 13 */ 140 | 0x11100, /* track 14 */ 141 | 0x12600, /* track 15 */ 142 | 0x13b00, /* track 16 */ 143 | 0x15000, /* track 17 */ 144 | 0x16500, /* track 18 */ 145 | 0x17800, /* track 19 */ 146 | 0x18b00, /* track 20 */ 147 | 0x19e00, /* track 21 */ 148 | 0x1b100, /* track 22 */ 149 | 0x1c400, /* track 23 */ 150 | 0x1d700, /* track 24 */ 151 | 0x1ea00, /* track 25 */ 152 | 0x1fc00, /* track 26 */ 153 | 0x20e00, /* track 27 */ 154 | 0x22000, /* track 28 */ 155 | 0x23200, /* track 29 */ 156 | 0x24400, /* track 30 */ 157 | 0x25600, /* track 31 */ 158 | 0x26700, /* track 32 */ 159 | 0x27800, /* track 33 */ 160 | 0x28900, /* track 34 */ 161 | 0x29a00, /* track 35 */ 162 | 0x2ab00, /* track 36 */ 163 | 0x2bc00, /* track 37 */ 164 | 0x2cd00, /* track 38 */ 165 | 0x2de00, /* track 39 */ 166 | 0x2ef00, /* track 40 */ 167 | }; 168 | 169 | /* description of a direntry including d64 specific values*/ 170 | typedef struct dirent64 { 171 | /* start position of file */ 172 | unsigned char d_track; 173 | unsigned char d_sector; 174 | /* track/sector and offset of where the dirent is stored */ 175 | unsigned char d_detrack; 176 | unsigned char d_desector; 177 | unsigned char d_desectpos; 178 | /* size information */ 179 | unsigned d_blocks; 180 | unsigned d_size; 181 | 182 | unsigned char d_type; /* DEL, SEQ, PRG, USR, REL, DIR */ 183 | unsigned char d_locked; //Bit 6 184 | unsigned char d_closed; //Bit 7 produces * if not set 185 | unsigned char d_ctype; 186 | char d_petscii_name[MAX_C64_NAME + 1]; 187 | } dirent64; 188 | 189 | /* dsecription of the surrounding filesys our file is in */ 190 | typedef struct d64 { 191 | FILE* file; 192 | 193 | char header[32]; 194 | char id[6]; 195 | 196 | /* d64 specific things */ 197 | unsigned char track; 198 | unsigned char sector; 199 | unsigned char track_link; 200 | unsigned char sector_link; 201 | unsigned char detrack; 202 | unsigned char desector; 203 | unsigned char desectpos; 204 | unsigned free; 205 | unsigned sectpos; 206 | unsigned sectsize; 207 | unsigned char sectbuf[256]; 208 | unsigned char bam[256]; 209 | 210 | /* dirlist things */ 211 | dirent64** dirlist; 212 | int dirsize; 213 | int dirpos; 214 | unsigned char checksum; 215 | unsigned char supported_tracks; 216 | } d64; 217 | -------------------------------------------------------------------------------- /d64write/debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * The name of its author may not be used to endorse or promote products 12 | * derived from this software without specific prior written permission. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | */ 25 | 26 | int debug_level; 27 | 28 | //log levels 29 | #define ENABLE_DEBUG 0 30 | #define ENABLE_BENCHMARK 1 31 | #define ENABLE_INFO 1 32 | #define ENABLE_FAIL 1 33 | #define ENABLE_FATAL 1 34 | 35 | #ifdef _MSC_VER 36 | #define debug_message(format,...); { if(ENABLE_DEBUG) { fprintf(stdout,"DEBUG: %s: %s(): ",__FILE__,__FUNCTION__); fprintf(stdout,format,__VA_ARGS__); } } 37 | #define info_message(format,...); { if(ENABLE_INFO) { fprintf(stdout,"INFO: "); fprintf(stdout,format,__VA_ARGS__); } } 38 | #define fail_message(format,...); { if(ENABLE_FAIL) { fprintf(stdout,"FAIL: %s: ",__FILE__); fprintf(stdout,format,__VA_ARGS__); } } 39 | #define fatal_message(format,...); { if(ENABLE_FATAL) { fprintf(stderr,"ERROR: "); fprintf(stderr,format,__VA_ARGS__); exit(2); } } 40 | #else 41 | #define debug_message(format,args...); { if(ENABLE_DEBUG) { fprintf(stdout,"DEBUG: %s: %s(): ",__FILE__,__FUNCTION__); fprintf(stdout,format,##args); } } 42 | #define info_message(format,args...); { if(ENABLE_INFO) { fprintf(stdout,"INFO: "); fprintf(stdout,format,##args); } } 43 | #define fail_message(format,args...); { if(ENABLE_FAIL) { fprintf(stdout,"FAIL: %s: ",__FILE__); fprintf(stdout,format,##args); } } 44 | #define fatal_message(format,args...); { if(ENABLE_FATAL) { fprintf(stderr,"ERROR: "); fprintf(stderr,format,##args); exit(2); } } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /example/depack_only/Makefile: -------------------------------------------------------------------------------- 1 | BITNAX_OPTS = -v --bitfire 2 | D64WRITE_OPTS = -v 3 | PACKER = ../../packer/dali/dali 4 | PACKER_OPTS = 5 | D64WRITE = ../../d64write/d64write 6 | 7 | all: example 8 | 9 | testfile.lz: ../../benchmark/files/b 10 | $(PACKER) -o $@ $< 11 | 12 | example: example.asm Makefile ../../loader/installer testfile.lz 13 | acme -f cbm -o $@ $< 14 | $(PACKER) $(PACKER_OPTS) --sfx 0x0800 -o $@.prg $@ 15 | 16 | clean: 17 | -rm testfile.lz example example.prg 18 | -------------------------------------------------------------------------------- /example/depack_only/example.asm: -------------------------------------------------------------------------------- 1 | !cpu 6510 2 | 3 | 4 | !src "../../loader/loader_acme.inc" 5 | !src "../../macros/link_macros_acme.inc" 6 | 7 | * = $1000 8 | !bin "../../loader/installer",,2 9 | * = $0800 10 | lda #$08 11 | sta $b8 12 | lda #$37 13 | sta $01 14 | jsr bitfire_install_ 15 | sei 16 | lda #$35 17 | sta $01 18 | lda $d011 19 | bpl *-3 20 | lda #$0b 21 | sta $d011 22 | 23 | ldx #$00 24 | lda #$20 25 | - 26 | sta $0400,x 27 | sta $0500,x 28 | sta $0600,x 29 | sta $0700,x 30 | dex 31 | bne - 32 | 33 | jsr .timer_start 34 | 35 | lda #<(data_start) 36 | sta bitfire_load_addr_lo 37 | lda #>(data_start) 38 | sta bitfire_load_addr_hi 39 | 40 | jsr bitfire_decomp_ 41 | 42 | jsr .timer_stop 43 | 44 | lda #$1b 45 | sta $d011 46 | jmp * 47 | 48 | .timer_start 49 | lda #$00 50 | sta $dc0e 51 | lda #$40 52 | sta $dc0f 53 | lda #$ff 54 | sta $dc04 55 | sta $dc05 56 | sta $dc06 57 | sta $dc07 58 | lda #$41 59 | sta $dc0f 60 | lda #$01 61 | sta $dc0e 62 | rts 63 | .timer_stop 64 | lda #$00 65 | sta $dc0e 66 | lda #$40 67 | sta $dc0f 68 | 69 | ldy #$00 70 | - 71 | lda .cycles,y 72 | sta $0400,y 73 | iny 74 | cpy #$08 75 | bne - 76 | lda $dc04 77 | pha 78 | lda $dc05 79 | pha 80 | lda $dc06 81 | pha 82 | lda $dc07 83 | jsr .print_hex 84 | pla 85 | jsr .print_hex 86 | pla 87 | jsr .print_hex 88 | pla 89 | .print_hex 90 | eor #$ff 91 | pha 92 | lsr 93 | lsr 94 | lsr 95 | lsr 96 | tax 97 | lda .hextab,x 98 | sta $0400,y 99 | iny 100 | pla 101 | ldx #$0f 102 | sbx #$00 103 | lda .hextab,x 104 | sta $0400,y 105 | iny 106 | rts 107 | .cycles 108 | !scr "cycles: " 109 | .hextab 110 | !scr "0123456789abcdef" 111 | 112 | ; * = $6b00 113 | * = $6a62 114 | data_start 115 | !bin "testfile.lz",,2 116 | -------------------------------------------------------------------------------- /example/dirart/exampledir.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/example/dirart/exampledir.bin -------------------------------------------------------------------------------- /example/dirart/exampledir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/example/dirart/exampledir.png -------------------------------------------------------------------------------- /example/example_project/bitfire/place_bitfire_as_a_submodule_here: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/example/example_project/bitfire/place_bitfire_as_a_submodule_here -------------------------------------------------------------------------------- /example/example_project/bootstrap/Makefile: -------------------------------------------------------------------------------- 1 | link_exit ?= 0 2 | release ?= 0 3 | ACME ?= acme 4 | ACME_OPTS ?= -v1 -f cbm -Drelease=$(release) -Dlink_exit=$(link_exit) 5 | 6 | .PHONY: all 7 | 8 | all: bootstrap1 bootstrap2 9 | 10 | bootstrap1: boot.asm ../*.inc 11 | $(ACME) $(ACME_OPTS) -DSIDE=1 -o $@ $< 12 | 13 | bootstrap2: boot.asm ../*.inc 14 | $(ACME) $(ACME_OPTS) -DSIDE=2 -o $@ $< 15 | 16 | clean: 17 | -rm bootstrap* 18 | -------------------------------------------------------------------------------- /example/example_project/bootstrap/boot.asm: -------------------------------------------------------------------------------- 1 | !src "../loader/loader_acme.inc" 2 | !src "../macros/link_macros_acme.inc" 3 | !src "../config.inc" 4 | 5 | * = $0100 6 | 7 | !if SIDE = 1 { 8 | ;load music 9 | jsr link_load_next_comp 10 | lda #$00 11 | ;reset frame counter 12 | sta link_frame_count + 0 13 | sta link_frame_count + 1 14 | ;load tune1 15 | jsr link_load_next_comp 16 | lda #$00 17 | ldy #$12 18 | ldx #$0a 19 | jsr link_music_init_side1 20 | ;add if music entry changes on current side 21 | lda #>link_music_play_side1 22 | sta link_music_addr + 1 23 | } else { 24 | ;load music 25 | lda #$02 ;file 1 is turndisk, file 0 is bootstrap 26 | jsr link_load_comp 27 | lda #$00 28 | ;reset frame counter 29 | sta link_frame_count + 0 30 | sta link_frame_count + 1 31 | tax 32 | tay 33 | jsr link_music_init_side2 34 | ;add if music entry changes on current side 35 | lda #>link_music_play_side2 36 | sta link_music_addr + 1 37 | } 38 | 39 | sei 40 | lda #$35 41 | sta $01 42 | 43 | !if CONFIG_FRAMEWORK_MUSIC_NMI = 1 { 44 | +start_music_nmi 45 | 46 | ;better cease all other IRQs 47 | lda #$7f 48 | sta $dc0d 49 | lda $dc0d 50 | 51 | lda #$00 52 | sta $d019 53 | sta $d01a 54 | 55 | dec $d019 56 | } else { 57 | ldx #link_player 59 | stx $fffe 60 | sta $ffff 61 | lda #$7f 62 | sta $dc0d 63 | lda $dc0d 64 | lda #$01 65 | sta $d019 66 | sta $d01a 67 | lda #$ff 68 | sta $d012 69 | lda $d011 70 | and #$7f 71 | sta $d011 72 | } 73 | cli 74 | 75 | !if SIDE = 1 { 76 | jsr link_load_next_comp 77 | } else { 78 | lda #$10 79 | bit $d011 80 | beq + 81 | lda #$01 82 | sta $d020 83 | sta $d021 84 | lda #$0b 85 | sta $d011 86 | + 87 | ;load first part 88 | jsr link_load_next_comp 89 | } 90 | 91 | ;start part at the same point in time 92 | jmp link_exit 93 | -------------------------------------------------------------------------------- /example/example_project/config.inc: -------------------------------------------------------------------------------- 1 | !ifndef CONFIG_LOADED { 2 | 3 | ;options for resident part 4 | CONFIG_RESIDENT_ADDR = $0200 5 | CONFIG_ZP_ADDR = $02 ;maximum 7 bytes needed 6 | CONFIG_LAX_ADDR = $00 ;Usually save to have the value $37 here, but can be also set elsewhere, but must stay persistent during loading 7 | 8 | ;options for installer 9 | CONFIG_INSTALLER_ADDR = $1000 10 | CONFIG_RESIDENT_AUTOINST = 1 ;Set this to zero if you want to do the install of the resident part on your own, but why would you want to do so anyway? :-D 11 | 12 | ;Framework options, certain features can be switched on/off separatedly 13 | CONFIG_FRAMEWORK = 1 ;Enable/Disable whole framework 14 | CONFIG_FRAMEWORK_BASEIRQ = 1 ;Include a base irq handler into the framework 15 | CONFIG_FRAMEWORK_FRAMECOUNTER = 1 ;Include framecounter handling 16 | CONFIG_FRAMEWORK_MUSIC_NMI = 1 ;should base irq run in NMI or raster IRQ? 17 | 18 | ;Include a decompressor and by that on the fly decrunching? 19 | CONFIG_DECOMP = 1 ;Include decompressor and on the fly decompression 20 | 21 | ;Include the loader 22 | CONFIG_LOADER = 1 ;Include the loader or maybe decide for a standalone depacker + framework for onefilers 23 | 24 | CONFIG_NMI_GAPS = 0 ;Leaves gaps @ $0200 and $0300 (if resident part is at default location) for NMI handlers, needed for stable NMIs with THCM's digistuff. 25 | 26 | CONFIG_AUTODETECT = 1 ;Autodetect CIA + SID and store the results in the resident part for later use, so upcoming parts do not need an own detection anymore but can read out that values again 27 | 28 | ;options for drivecode 29 | CONFIG_MOTOR_ALWAYS_ON = 0 ;If you want to be annoying, let the motor spin during the whole demo :-D 30 | 31 | CONFIG_LOADED = 1 32 | 33 | } 34 | -------------------------------------------------------------------------------- /example/example_project/installer/Makefile: -------------------------------------------------------------------------------- 1 | release ?= 0 2 | link_exit ?= 256 3 | ACME ?= acme 4 | ACME_OPTS ?= -f cbm -Drelease=$(release) 5 | 6 | .PHONY: all 7 | 8 | all: installer 9 | 10 | installer: installer.asm ../loader/installer ../loader/loader_*.inc 11 | $(ACME) $(ACME_OPTS) -Dlink_exit=$(link_exit) -o $@ $< 12 | 13 | clean: 14 | -rm installer 15 | -------------------------------------------------------------------------------- /example/example_project/installer/installer.asm: -------------------------------------------------------------------------------- 1 | ;linking helper macros 2 | !src "../macros/link_macros_acme.inc" 3 | 4 | ;loader labels 5 | !src "../loader/loader_acme.inc" 6 | 7 | !ifndef link_exit { 8 | link_exit = $0100 9 | } 10 | 11 | * = bitfire_install_ 12 | !bin "../loader/installer",,2 13 | 14 | * = $0900 15 | .init 16 | ;install loader 17 | jsr bitfire_install_ 18 | 19 | ;reset stack shits 20 | sei 21 | lda #$35 22 | sta $01 23 | ldx #$ff 24 | txs 25 | 26 | ;load stage 2, either loaded by bootloader or after turn disk 27 | jsr link_load_next_raw 28 | 29 | ;XXX TODO here it would also be possible to laod a custom link_resident part per side, but would require includes per side and resident part 30 | jmp link_exit 31 | -------------------------------------------------------------------------------- /example/example_project/link/Makefile.example.for.demo.build: -------------------------------------------------------------------------------- 1 | SHELL = /bin/bash 2 | PACKER = ../packer/dali/dali 3 | D64WRITE = ../d64write/d64write 4 | X64 = x64 5 | MAKE_FLAGS = RELEASE=1 6 | PACKER_OPTS = 7 | 8 | .PHONY: all vice vice 9 | 10 | #Build all 11 | all: bitfire image1.d64 image2.d64 12 | 13 | #Build bitfire and tools 14 | #Build all and launch side 1 15 | vice: all 16 | $(X64) -pal -autostart "image1.d64:*" -truedrive -model c64c 17 | 18 | #Build and launch side 1 only 19 | vice1: image1.d64 20 | $(X64) -pal -autostart "image1.d64:*" -truedrive -model c64c 21 | 22 | #Build and launch side 2 only 23 | vice2: image2.d64 24 | $(X64) -pal -autostart "image2.d64:*" -truedrive -model c64c 25 | 26 | image1.d64: mydemo bootstrap1.prg music1.prg scroller.prg vector.prg note.prg 27 | $(D64WRITE) -c $@ -h oxyron -i rules --side 1 \ 28 | --boot mydemo \ 29 | -b bootstrap1.prg \ 30 | -b music1.prg \ 31 | -b scroller.prg \ 32 | -b vector1.prg \ 33 | -b vector2.prg \ 34 | -s note.prg 35 | 36 | image2.d64: mydemo bootstrap2.prg 37 | $(D64WRITE) -c $@ -h oxyron -i rules --side 2 \ 38 | --boot mydemo \ 39 | -b bootstrap2.prg 40 | 41 | ##################### BOOTLOADER - GENERIC STUFF ############## 42 | 43 | #The bootloader with installer 44 | ../installer/installer: FORCE 45 | $(MAKE) -C $(dir $@) $(MAKE_FLAGS) 46 | mydemo: ../installer/installer 47 | $(PACKER) --sfx 0x0900 -o $@ $< 48 | 49 | #A note file written as standard file 50 | ../parts/note/note: FORCE 51 | $(MAKE) -C $(dir $@) $(MAKE_FLAGS) 52 | note.prg: ./parts/note/note 53 | $(PACKER) --sfx 0x4000 -o $@ $< 54 | 55 | ##################### SIDE 1 ################################## 56 | 57 | #The bootstrap for each side, see the SIDE param 58 | ../bootstrap/bootstrap1: FORCE 59 | $(MAKE) -C $(dir $@) $(MAKE_FLAGS) $(notdir $@) link_exit=8192 SIDE=1 60 | bootstrap1.prg: ../bootstrap/bootstrap1 61 | $(PACKER) $(PACKER_OPTS) -o $@ $< 62 | 63 | #Music to be loaded. Just packing is sufficient here 64 | music1.prg: ../music/funkyshit.prg 65 | $(PACKER) $(PACKER_OPTS) -o $@ $< 66 | 67 | #Build first part 68 | ../parts/scroller/scroller: FORCE 69 | #build part in its own dir with an own Makefile 70 | $(MAKE) -C $(dir $@) $(MAKE_FLAGS) link_exit=8192 71 | #And pack it. This is separated from building to only pack again if the part really changed 72 | scroller.prg: ../parts/scroller/scroller 73 | #part in a single file, as it can be laoded in one go 74 | $(PACKER) $(PACKER_OPTS) -o $@ $< 75 | 76 | #A second part that we split upon packing. 77 | ../parts/vector/vector: FORCE 78 | #build part in its own dir with an own Makefile 79 | make -C ($dir $@) $(MAKE_FLAGS) link_exit=8192 80 | #Generates two files, as it is splitted to be loaded under IO, but also if mem is still occupied and things need to be loaded bit by bit 81 | vector.prg: ../parts/vector/vector 82 | $(PACKER) $(PACKER_OPTS) -o $(basename $@)1.prg --from 0x2000 --to 0xcff0 $< 83 | $(PACKER) $(PACKER_OPTS) -o $(basename $@)2.prg --use-prefix --from 0xcff0 --to 0xfff8 $< 84 | 85 | ##################### SIDE 2 ################################## 86 | 87 | #The bootstrap for each side, see the SIDE param 88 | ../bootstrap/bootstrap2: FORCE 89 | $(MAKE) -C $(dir $@) $(MAKE_FLAGS) $(notdir $@) link_exit=8192 SIDE=1 90 | bootstrap2.prg: ./bootstrap/bootstrap2 91 | $(PACKER) $(PACKER_OPTS) -o $@ $< 92 | 93 | ##################### CLEANUP ################################# 94 | 95 | clean: clean_framework 96 | -rm *.prg *.d64 97 | -rm mydemo 98 | 99 | ############################################################### 100 | 101 | #Always returns true so that Make always has a peek into each subdir to take notice of changes so tha twe recompile parts in case 102 | FORCE: 103 | -------------------------------------------------------------------------------- /example/example_project/music.inc: -------------------------------------------------------------------------------- 1 | link_music_init_side1 = $0800 2 | link_music_play_side1 = link_music_init_side1 + 3 3 | link_music_fade_side1 = link_music_init_side1 + 9 4 | 5 | link_music_init_side2 = $0800 6 | link_music_play_side2 = link_music_init_side2 + 3 7 | link_music_fade_side2 = link_music_init_side2 + 6 8 | -------------------------------------------------------------------------------- /example/loadertest/Makefile: -------------------------------------------------------------------------------- 1 | BITNAX_OPTS = -v --bitfire 2 | D64WRITE_OPTS = -v 3 | PACKER = ../../packer/dali/dali 4 | PACKER_OPTS = 5 | D64WRITE = ../../d64write/d64write 6 | 7 | all: example 8 | 9 | example: example.asm Makefile ../../loader/installer files/pic1.bin.lz files/pic2.bin.lz 10 | acme -f cbm -o $@ $< 11 | $(PACKER) $(PACKER_OPTS) --sfx 0x0800 -o $@.prg $@ 12 | $(D64WRITE) $(D64WRITE_OPTS) -c side1.d64 -h performers -i \<3 --side 1 \ 13 | --boot $@.prg \ 14 | -b files/pic1.bin.lz \ 15 | -b files/pic2.bin.lz \ 16 | -b files/pic1.bin \ 17 | -b files/pic2.bin 18 | 19 | rm $@ $@.prg 20 | x64 side1.d64 21 | 22 | files/pic1.bin.lz: files/pic1.bin 23 | $(PACKER) $(PACKER_OPTS) -o $@ $< 24 | 25 | files/pic2.bin.lz: files/pic2.bin 26 | $(PACKER) $(PACKER_OPTS) -o $@ $< 27 | 28 | clean: 29 | -rm side1.d64 example example.prg 30 | -rm files/*.lz 31 | -------------------------------------------------------------------------------- /example/loadertest/example.asm: -------------------------------------------------------------------------------- 1 | !src "../../loader/loader_acme.inc" 2 | !src "../../macros/link_macros_acme.inc" 3 | 4 | * = $1000 5 | !bin "../../loader/installer",,2 6 | * = $0800 7 | lda #$0b 8 | sta $d020 9 | sta $d021 10 | ldx #$00 11 | - 12 | lda #$7b 13 | sta $0400,x 14 | sta $0500,x 15 | sta $0600,x 16 | sta $0700,x 17 | dex 18 | bne - 19 | 20 | lda #$3b 21 | sta $d011 22 | lda #$18 23 | sta $d018 24 | lda #$08 25 | sta $d016 26 | 27 | jsr bitfire_install_ 28 | 29 | sei 30 | 31 | lda #$35 32 | sta $01 33 | .loop 34 | jsr .start_timer 35 | lda #$00 36 | jsr bitfire_loadcomp_ 37 | ldx #$00 38 | jsr .stop_timer 39 | jsr .start_timer 40 | lda #$01 41 | jsr bitfire_loadcomp_ 42 | ldx #$04 43 | jsr .stop_timer 44 | jsr .start_timer 45 | lda #$02 46 | jsr bitfire_loadraw_ 47 | ldx #$08 48 | jsr .stop_timer 49 | jsr .start_timer 50 | lda #$03 51 | jsr bitfire_loadraw_ 52 | ldx #$0c 53 | jsr .stop_timer 54 | jmp .loop 55 | .start_timer 56 | lda #$00 57 | sta $dc0e 58 | lda #$40 59 | sta $dc0f 60 | lda #$ff 61 | sta $dc04 62 | sta $dc05 63 | sta $dc06 64 | sta $dc07 65 | lda #$41 66 | sta $dc0f 67 | lda #$01 68 | sta $dc0e 69 | rts 70 | .stop_timer 71 | lda #$00 72 | sta $dc0e 73 | lda #$40 74 | sta $dc0f 75 | 76 | lda $dc04 77 | eor #$ff 78 | sta $0f03,x 79 | lda $dc05 80 | eor #$ff 81 | sta $0f02,x 82 | lda $dc06 83 | eor #$ff 84 | sta $0f01,x 85 | lda $dc07 86 | eor #$ff 87 | sta $0f00,x 88 | rts 89 | -------------------------------------------------------------------------------- /example/loadertest/files/pic1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/example/loadertest/files/pic1.bin -------------------------------------------------------------------------------- /example/loadertest/files/pic2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/example/loadertest/files/pic2.bin -------------------------------------------------------------------------------- /loader/Makefile: -------------------------------------------------------------------------------- 1 | ACME ?= acme 2 | ACME_OPTS ?= -f cbm 3 | loader_CFLAGS ?= $(CFLAGS) -Os -Wall 4 | CC ?= cc 5 | LOADER_CONFIG ?= '../config.inc' 6 | 7 | V ?= 0 8 | ifeq ($(V),1) 9 | VR:= 10 | else 11 | VR:=@ 12 | endif 13 | 14 | all: bitfire gcr_tables frag 15 | 16 | frag: frag.c 17 | @echo "Building frag tool..." 18 | $(VR)$(CC) $< -o $@ $(loader_CFLAGS) 19 | 20 | gcr_tables: gcr_tables.c 21 | @echo "Building gcr table tool..." 22 | $(VR)$(CC) $< -o $@ $(loader_CFLAGS) 23 | 24 | resident: resident.asm ../config.inc constants.inc Makefile 25 | @echo "Building resident part..." 26 | $(VR)$(ACME) $(ACME_OPTS) -I ../../ -I ../ -o resident --labeldump resident_labels.txt resident.asm 27 | @printf "Resident size: $$%04x\n" $$((`wc -c < resident` - 2)) 28 | @echo "Creating loader_acme.inc..." 29 | @#fetch all global labels for resident part 30 | $(VR)grep "bitfire_*" resident_labels.txt | sed "s/[[:space:]]*;[[:space:]]*.*//g" | tr -d "\t" | sed -e 's/\$$\([0-9a-f]\{3\}$$\)/\$$0\1/' -e "s/\= / \= /" > loader_acme.inc 31 | $(VR)grep "link_*" resident_labels.txt | sed "s/[[:space:]]*;[[:space:]]*.*//g" | tr -d "\t" | sed -e 's/\$$\([0-9a-f]\{3\}$$\)/\$$0\1/' -e "s/\= / \= /" >> loader_acme.inc 32 | @#fetch all config labels 33 | $(VR)grep "BITFIRE_*" resident_labels.txt | sed "s/[[:space:]]*;[[:space:]]*.*//g" | tr -d "\t" | sed -e 's/\$$\([0-9a-f]\{3\}$$\)/\$$0\1/' -e "s/\= / \= /" >> loader_acme.inc 34 | @echo "Creating loader_c6510.inc..." 35 | @#convert to c6510 format (add const, wipe out underscores and add prefix with .) 36 | $(VR)echo "if def BITFIRE.ISINCLUDED == 0" > loader_c6510.inc 37 | $(VR)cat loader_acme.inc | sed "s/\(.*\)/const \\1/" >> loader_c6510.inc 38 | $(VR)echo "endif" >> loader_c6510.inc 39 | $(VR)echo ".importonce" > loader_kickass.inc 40 | @#cat loader_acme.inc | grep "bitfire" | sed "s/bitfire/\.var bitfire/" >> loader_kickass.inc 41 | @#cat loader_acme.inc | grep "BITFIRE" | sed "s/BITFIRE/\.var BITFIRE/" >> loader_kickass.inc 42 | @echo "Creating loader_kickass.inc..." 43 | $(VR)cat loader_acme.inc | sed "s/\(.*\)/\.var \\1/" >> loader_kickass.inc 44 | @#echo "}" >> loader_kickass.inc 45 | $(VR)rm resident_labels.txt 46 | 47 | installer: resident drivecode.asm installer.asm constants.inc ../config.inc detect.asm Makefile 48 | @echo "Building installer..." 49 | @$(ACME) $(ACME_OPTS) -I ../../ -I ../ -o installer installer.asm 50 | 51 | bitfire: installer 52 | 53 | clean: 54 | $(VR)-rm installer loader_acme.inc loader_c6510.inc loader_kickass.inc resident gcr_tables frag 55 | -------------------------------------------------------------------------------- /loader/constants.inc: -------------------------------------------------------------------------------- 1 | ;constants, better don't touch 2 | BITFIRE_RESET = $ff 3 | BITFIRE_EXEC = $ed 4 | BITFIRE_EXEC_SECT = 15 5 | BITFIRE_LOAD_NEXT = $ef 6 | BITFIRE_SKIP_FILE = $ee 7 | BITFIRE_REQ_DISC = $f0 8 | 9 | BITFIRE_SID_NEW = 1 10 | BITFIRE_CIA_NEW = 2 11 | BITFIRE_CIA1_NEW = 4 12 | BITFIRE_CIA2_NEW = 2 13 | -------------------------------------------------------------------------------- /loader/detect.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions are met: 6 | ; * Redistributions of source code must retain the above copyright 7 | ; notice, this list of conditions and the following disclaimer. 8 | ; * Redistributions in binary form must reproduce the above copyright 9 | ; notice, this list of conditions and the following disclaimer in the 10 | ; documentation and/or other materials provided with the distribution. 11 | ; * The name of its author may not be used to endorse or promote products 12 | ; derived from this software without specific prior written permission. 13 | ; 14 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ; 25 | 26 | .detect_sid 27 | sei 28 | lda #$35 29 | sta $01 30 | lda #$00 31 | sta $d015 32 | lda #$ff 33 | cmp $d012 34 | bne *-3 35 | 36 | lda #$ff 37 | sta $d412 38 | sta $d40e 39 | sta $d40f 40 | lda #$20 41 | sta $d412 42 | lda $d41b 43 | eor #$01 44 | and #$01 45 | ora link_chip_types ;0 = old, 1 = new sid 46 | sta link_chip_types 47 | 48 | .detect_cia 49 | lda #$7f 50 | sta $dd0d 51 | sta $dc0d 52 | lda $dd0d 53 | lda $dc0d 54 | 55 | lda #$00 56 | sta $d01a 57 | sta $dd0e 58 | sta $dd0f 59 | sta $dc0e 60 | sta $dc0f 61 | sta $dd0e 62 | sta $dd0f 63 | sta $dd05 64 | sta $dd07 65 | sta $dc05 66 | sta $dc07 67 | 68 | inc $d019 69 | 70 | lda #<.detect_2 71 | sta $fffa 72 | lda #>.detect_2 73 | sta $fffb 74 | 75 | lda #$02 76 | sta $dd04 77 | sta $dc04 78 | lda #%10000001 79 | sta $dd0d 80 | lda #%00011001 81 | sta $dd0e 82 | tsx 83 | 84 | nop 85 | lda #BITFIRE_CIA2_NEW 86 | lda #$00 87 | .detect_2 88 | ora link_chip_types 89 | sta link_chip_types 90 | 91 | lda #$7f 92 | sta $dd0d 93 | bit $dd0d 94 | 95 | lda #<.detect_1 96 | sta $fffe 97 | lda #>.detect_1 98 | sta $ffff 99 | 100 | lda #%10000001 101 | sta $dc0d 102 | lda #%00011001 103 | sta $dc0e 104 | cli 105 | 106 | nop 107 | lda #BITFIRE_CIA1_NEW 108 | lda #$00 109 | .detect_1 110 | ora link_chip_types 111 | sta link_chip_types 112 | 113 | lda #$7f 114 | sta $dc0d 115 | bit $dc0d 116 | 117 | txs 118 | 119 | lda #$37 120 | sta $01 121 | -------------------------------------------------------------------------------- /loader/gcrstream.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | //XXX TODO include tables here and check against tables if reads that are off table could also lead to resulting values in case of differences? -> 256 possibilities? only possibilities within normal range, but with gaps (5 bits!) 5 | 6 | unsigned char tables1[256] = { 0 }; 7 | unsigned char tables2[512] = { 0 }; 8 | 9 | int data_sane[] = { 10 | 0x3d, 0xc0, 0x1a, 0xb8, 0xc0, 11 | 0x06, 0xfc, 0x85, 0x05, 0x29, 0x03, 0xfc, 0x61, 0x00, 0x2e, 0x0e, 0x6f, 0x36, 0x02, 0x58, 0xbd, 12 | 0xa2, 0xb4, 0x3d, 0xac, 0x87, 0xfd, 0xec, 0x03, 0xfc, 0x34, 0x0a, 0xfd, 0xec, 0x2c, 0x9c, 0x28, 13 | 0xcd, 0x34, 0x8e, 0x5c, 0x0c, 0x0b, 0xeb, 0x0d, 0x49, 0x05, 0xff, 0x70, 0x04, 0x24, 0x02, 0xbe, 14 | 0x11, 0x84, 0x28, 0x0f, 0x9c, 0x8a, 0x08, 0xfa, 0x4e, 0x8a, 0x10, 0xa2, 0x5a, 0x79, 0x92, 0x01, 15 | 0x9e, 0x94, 0x02, 0x7f, 0x47, 0x05, 0xff, 0x9c, 0x07, 0x7f, 0xb6, 0x0f, 0xff, 0xc2, 0x1f, 0xff, 16 | 0xc4, 0x17, 0x67, 0xf9, 0x17, 0xfe, 0x18, 0x09, 0xfc, 0xd3, 0x33, 0xb2, 0xd1, 0xa0, 0x02, 0x06, 17 | 0xba, 0x02, 0xff, 0x98, 0x38, 0x91, 0xa3, 0x0d, 0xa4, 0xc3, 0x6c, 0xa8, 0xf9, 0x2c, 0xfa, 0xf0, 18 | 0x40, 0x05, 0x44, 0x28, 0xd0, 0x04, 0xda, 0x74, 0x10, 0xef, 0x3c, 0x4a, 0xd0, 0x2e, 0xd4, 0x0a, 19 | 0xdc, 0xfe, 0x7e, 0x9b, 0x95, 0x3a, 0x04, 0xfc, 0xff, 0x4a, 0x8a, 0x18, 0xa7, 0x88, 0xf1, 0x8a, 20 | 0x3e, 0x92, 0xd4, 0x8a, 0xdf, 0xbc, 0x22, 0xff, 0x30, 0x28, 0x48, 0x17, 0xad, 0x84, 0x2f, 0xd4, 21 | 0x24, 0x05, 0xe8, 0x58, 0x27, 0xf8, 0x30, 0x1e, 0xcc, 0x6f, 0x94, 0xa2, 0x8c, 0x9f, 0x70, 0xfe, 22 | 0x0c, 0x8a, 0xa7, 0x0a, 0xb0, 0x32, 0x3f, 0x9e, 0xff, 0x8a, 0x9c, 0xa4, 0x8a, 0x3c, 0xe4, 0x22, 23 | 0xcc, 0x3c, 0xbb, 0xb0, 0xb5, 0x0f, 0x29, 0x05, 0x0c, 0x82, 0x3c, 0x10, 0x34, 0x34, 0xb4, 0x35, 24 | 0xa3, 0x13, 0x3c, 0x0c, 0xfe, 0x31, 0xdc, 0x7a, 0x8a, 0xb3, 0x14, 0x5e, 0x28, 0x29, 0x65, 0xea, 25 | 0xfc, 0x97, 0xff, 0x96, 0x28, 0xff, 0x92, 0x88, 0xfb, 0xe4, 0x68, 0x98, 0x07, 0xfe, 0x70, 0x0b, 26 | 0xa0, 0x88, 0x3f, 0x68, 0x84, 0x4f, 0xf4, 0xd8, 0x47, 0xe2, 0x70 27 | }; 28 | 29 | int data_broken[] = { 30 | 0x3d, 0xc0, 0x1a, 0xb8, 0xc0, 31 | 0x06, 0xfc, 0x85, 0x05, 0x29, 0x03, 0xfc, 0x61, 0x00, 0x2e, 0x0e, 0x6f, 0x36, 0x02, 0x58, 0xbd, 32 | 0xa2, 0xb4, 0x3d, 0xac, 0x87, 0xfd, 0xec, 0x03, 0xfc, 0x34, 0x0a, 0xfd, 0xec, 0x2c, 0x9c, 0x28, 33 | 0xcd, 0x34, 0x8e, 0x5c, 0x0c, 0x0b, 0xeb, 0x0d, 0x49, 0x05, 0xff, 0x70, 0x04, 0x24, 0x02, 0xbe, 34 | 0x11, 0x84, 0x28, 0x0f, 0x9c, 0x8a, 0x08, 0xfa, 0x4e, 0x8a, 0x10, 0xa2, 0x5a, 0x79, 0x92, 0x01, 35 | 0x9e, 0x94, 0x02, 0x7f, 0x47, 0x05, 0xff, 0x9c, 0x07, 0x7f, 0xb6, 0x0f, 0xff, 0xc2, 0x1f, 0xff, 36 | 0xc4, 0x17, 0x67, 0xf9, 0x17, 0xfe, 0x18, 0x09, 0xfc, 0xd3, 0x33, 0xb2, 0xd1, 0xa0, 0x02, 0x06, 37 | 0xba, 0x02, 0xff, 0x98, 0x38, 0x91, 0xa3, 0x43, 0x35, 0x90, 0x42, 0xc4, 0xb3, 0xc4, 0x3e, 0x22, 38 | 0x80, 0x3e, 0x3a, 0x22, 0xdb, 0xf4, 0x0e, 0x09, 0x67, 0xc4, 0xf8, 0x54, 0x80, 0xc4, 0x6a, 0x84, 39 | 0x7d, 0xfe, 0x58, 0x8a, 0xf6, 0x6f, 0xb0, 0x18, 0xa7, 0x88, 0xf0, 0x53, 0xff, 0x8b, 0x25, 0x16, 40 | 0xc0, 0xf1, 0x68, 0x6b, 0x21, 0xbd, 0x46, 0x07, 0xfa, 0x89, 0x8d, 0x58, 0x27, 0xf8, 0x31, 0x31, 41 | 0xcf, 0x41, 0x66, 0xb3, 0x14, 0xf1, 0xa2, 0xdc, 0x1f, 0xcc, 0xf0, 0x47, 0x74, 0x6f, 0xee, 0xa4, 42 | 0x8a, 0x3c, 0x6b, 0x31, 0xbb, 0x4e, 0xea, 0xef, 0x20, 0x50, 0x4b, 0x98, 0x6f, 0xf8, 0x71, 0xca, 43 | 0xec, 0x0c, 0xed, 0xb0, 0x3d, 0x3e, 0x88, 0xfd, 0x3f, 0x7c, 0xcb, 0x22, 0x2b, 0x4b, 0x5e, 0xaf, 44 | 0xcd, 0x5f, 0xf9, 0x66, 0xad, 0xfa, 0x31, 0x7d, 0xa9, 0xf2, 0x98, 0xe7, 0xa0, 0xba, 0x08, 0x87, 45 | 0x15, 0xd8, 0x07, 0x74, 0xe7, 0xde, 0x80, 0x38, 0xf8, 0x8a, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0x53, 46 | 0x1c, 0x3f, 0x08, 0x62, 0x80, 0xe4, 0x80, 0x0f, 0x0f, 0x0f, 0x0f 47 | }; 48 | 49 | int gcr[16] = { 50 | 0b00001010, //0f 0 51 | 0b00001011, //07 1 52 | 0b00010010, //0d 2 53 | 0b00010011, //05 3 54 | 0b00001110, //0b 4 55 | 0b00001111, //03 5 56 | 0b00010110, //09 6 57 | 0b00010111, //01 7 58 | 0b00001001, //0e 8 59 | 0b00011001, //06 9 60 | 0b00011010, //0c a 61 | 0b00011011, //04 b 62 | 0b00001101, //0a c 63 | 0b00011101, //02 d 64 | 0b00011110, //08 e 65 | 0b00010101 //00 f 66 | }; 67 | 68 | void print_bit(int p, int bit1, int bit2) { 69 | if (bit1 == bit2) printf("%d", bit1); 70 | else printf("."); 71 | //if ((p % 40) == 0) printf ("\n"); 72 | //else if ((p % 8) == 0) printf(" "); 73 | } 74 | 75 | int is_gcr(int num) { 76 | int g; 77 | for (g = 0; g < 16; g++) { 78 | if (gcr[g] == num) return 1; 79 | } 80 | return 0; 81 | } 82 | 83 | void check_tables(int pair, int byte1, int byte2) { 84 | int i,j; 85 | int g; 86 | switch(pair) { 87 | case 0: 88 | for (i = 0; i < 64; i += 2) { 89 | //printf("m%02x ", tables1[i]); 90 | for (j = 0; j < 256; j += 8) { 91 | if (byte1 == (tables1[i] ^ tables2[j + 4])) { 92 | //if(is_gcr(i >> 1) && is_gcr(j >> 3)) printf("m%02x %02x ", i, j); 93 | } 94 | } 95 | } 96 | break; 97 | case 1: 98 | break; 99 | case 2: 100 | break; 101 | case 3: 102 | break; 103 | } 104 | } 105 | 106 | void decode(int* data1, int* data2) { 107 | int b, i, p; 108 | p = 0; 109 | printf ("sane:\n"); 110 | for (i = 0; i < 256; i++) { 111 | for (b = 4; b >= 0; b--) { 112 | p++; 113 | print_bit(p, (gcr[data1[i] >> 4] >> b) & 1, (gcr[data1[i] >> 4] >> b) & 1); 114 | } 115 | for (b = 4; b >= 0; b--) { 116 | p++; 117 | print_bit(p, (gcr[data1[i] & 0xf] >> b) & 1, (gcr[data1[i] & 0xf] >> b) & 1); 118 | } 119 | } 120 | printf ("\nbroken:\n"); 121 | for (i = 0; i < 256; i++) { 122 | if (i < 254) check_tables(i % 4, data2[i], data2[i + 1]); 123 | for (b = 4; b >= 0; b--) { 124 | p++; 125 | print_bit(p, (gcr[data2[i] >> 4] >> b) & 1, (gcr[data2[i] >> 4] >> b) & 1); 126 | } 127 | for (b = 4; b >= 0; b--) { 128 | p++; 129 | print_bit(p, (gcr[data2[i] & 0xf] >> b) & 1, (gcr[data2[i] & 0xf] >> b) & 1); 130 | } 131 | } 132 | printf ("\ndiff:\n"); 133 | for (i = 0; i < 256; i++) { 134 | for (b = 4; b >= 0; b--) { 135 | p++; 136 | print_bit(p, (gcr[data1[i] >> 4] >> b) & 1, (gcr[data2[i] >> 4] >> b) & 1); 137 | } 138 | for (b = 4; b >= 0; b--) { 139 | p++; 140 | print_bit(p, (gcr[data1[i] & 0xf] >> b) & 1, (gcr[data2[i] & 0xf] >> b) & 1); 141 | } 142 | } 143 | } 144 | 145 | int main () { 146 | FILE* fd; 147 | fd = fopen("tables1","rb"); 148 | fread(tables1, 1, 256, fd); 149 | fclose(fd); 150 | fd = fopen("tables2","rb"); 151 | fread(tables2, 1, 512, fd); 152 | fclose(fd); 153 | decode(data_sane, data_broken); 154 | } 155 | -------------------------------------------------------------------------------- /loader/installer.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions are met: 6 | ; * Redistributions of source code must retain the above copyright 7 | ; notice, this list of conditions and the following disclaimer. 8 | ; * Redistributions in binary form must reproduce the above copyright 9 | ; notice, this list of conditions and the following disclaimer in the 10 | ; documentation and/or other materials provided with the distribution. 11 | ; * The name of its author may not be used to endorse or promote products 12 | ; derived from this software without specific prior written permission. 13 | ; 14 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ; 25 | 26 | !src "config.inc" 27 | 28 | !convtab pet 29 | !cpu 6510 30 | 31 | .dc_src = $fc 32 | .dc_dst = $fe 33 | .mydrive = $fb 34 | 35 | .listen = $ffb1 36 | .listen_sa = $ff93 37 | .iecout = $ffa8 38 | .unlisten = $ffae 39 | 40 | !src "loader_acme.inc" 41 | * = CONFIG_INSTALLER_ADDR 42 | .init_inst 43 | lda #$7f 44 | sta $dc0d 45 | lda $dc0d 46 | !if CONFIG_DEPACK_ONLY = 0 { 47 | lda #$37 48 | !if CONFIG_CRT = 0 { 49 | sta .drivecode_size) + 1 95 | 96 | bit $dd00 ;wait until drive bootloader is active 97 | bmi *-3 98 | 99 | lda #$37 100 | sta $dd02 101 | 102 | ldy #$00 103 | ldx #$00 104 | .dc_loop 105 | .dc_data lda .drivecode_start, y 106 | sec 107 | ror 108 | sta .dc_src 109 | ;transfer like this? 110 | lda #$2f 111 | .s_loop 112 | and #$2f ;clear bit 4 and 0..2 and waste some cycles here 113 | adc #$00 ;on carry set, clear bit 4, else keep 114 | eor #$30 115 | ora #$0f 116 | 117 | sta $dd02 118 | pha ;make NTSC machines happy 119 | pla 120 | lsr .dc_src 121 | bne .s_loop 122 | 123 | iny 124 | bne + 125 | inx 126 | inc .dc_data + 2 127 | + 128 | cpy #<(.drivecode_size) 129 | bne .dc_loop 130 | cpx #>(.drivecode_size) 131 | bne .dc_loop 132 | 133 | lda #$37 ;raise atn to signal end of transfer 134 | sta $dd02 135 | } 136 | } 137 | 138 | ;!if (CONFIG_RESIDENT_AUTOINST != 0) { 139 | !if (bitfire_resident_size) < 256 { 140 | ;better force to 8 bit, label might be defined as 16 bit 141 | ldx #<(bitfire_resident_size) 142 | - 143 | lda .res_start,x 144 | sta CONFIG_RESIDENT_ADDR,x 145 | dex 146 | !if bitfire_resident_size >= $80 { 147 | cpx #$ff 148 | bne - 149 | } else { 150 | bpl - 151 | } 152 | } else { 153 | ;copy resident part 154 | ldx #$00 155 | - 156 | lda .res_start,x 157 | sta CONFIG_RESIDENT_ADDR,x 158 | lda .res_start + ((bitfire_resident_size) - $100),x 159 | sta CONFIG_RESIDENT_ADDR + ((bitfire_resident_size) - $100),x 160 | dex 161 | bne - 162 | } 163 | ;} 164 | 165 | !if CONFIG_LOADER_ONLY = 0 { 166 | !if CONFIG_DEPACK_ONLY = 0 { 167 | !src "detect.asm" 168 | } 169 | } 170 | 171 | !if CONFIG_DEPACK_ONLY = 0 { 172 | !if CONFIG_CRT = 0 { 173 | ;!if CONFIG_LOADER = 1 { 174 | .l1 lda $d012 175 | .l2 cmp $d012 176 | beq .l2 177 | bmi .l1 178 | cmp #$20 179 | bcs .nontsc 180 | 181 | lda #$1d ;ora $xxxx,x 182 | sta bitfire_ntsc0 183 | sta bitfire_ntsc1 184 | lda #$3d ;and $xxxx,x 185 | sta bitfire_ntsc2 186 | lda #$7d ;adc $xxxx,x 187 | sta bitfire_ntsc3_op + 1 188 | 189 | lda #-$3f 190 | sta bitfire_ntsc1 + 1 191 | sta bitfire_ntsc2 + 1 192 | lda #-$37 193 | sta bitfire_ntsc0 + 1 194 | sta bitfire_ntsc3 + 1 195 | 196 | lda #$dc 197 | sta bitfire_ntsc0 + 2 198 | sta bitfire_ntsc1 + 2 199 | sta bitfire_ntsc2 + 2 200 | sta bitfire_ntsc3 + 2 201 | 202 | .nontsc 203 | } 204 | ;} 205 | lda #$3f ;drop atn to signal end of transfer 206 | sta $dd02 207 | 208 | ;wait until floppy is ready 209 | ;wait for drive to initialize XXX TODO maybe wait for special signal on $dd00? 210 | 211 | ; sei 212 | ; ldx #$10 213 | ;wait 214 | ;- 215 | ; bit $d011 216 | ; bpl *-3 217 | ; bit $d011 218 | ; bmi *-3 219 | ; dex 220 | ; bpl - 221 | - 222 | lda $dd00 223 | bpl - 224 | } 225 | rts 226 | 227 | !if CONFIG_DEPACK_ONLY = 0 { 228 | !if CONFIG_CRT = 0 { 229 | .open_w_15 230 | lda $ba 231 | jsr .listen 232 | lda #$00 233 | sta $90 234 | lda #$6f 235 | jmp .listen_sa 236 | 237 | .install_bootstrap 238 | jsr .open_w_15 239 | lda #'i' 240 | jsr .iecout 241 | jsr .unlisten 242 | ;ldx #$10 243 | ;jsr wait 244 | ;install first routines via m-w 245 | 246 | ldx #$00 247 | .bs_loop 248 | 249 | stx .mw_code + 3 250 | 251 | jsr .open_w_15 252 | ldy #$00 253 | - 254 | lda .mw_code,y 255 | jsr .iecout 256 | iny 257 | cpy #$06 258 | bne - 259 | - 260 | lda .bootstrap_start,x 261 | jsr .iecout 262 | inx 263 | txa 264 | and #$1f 265 | bne - 266 | 267 | jsr .unlisten 268 | 269 | cpx #.bootstrap_size 270 | bcc .bs_loop 271 | 272 | ;now execute bootstrap 273 | jsr .open_w_15 274 | ldy #$00 275 | - 276 | lda .me_code,y 277 | jsr .iecout 278 | iny 279 | cpy #$05 280 | bne - 281 | jmp .unlisten 282 | 283 | .install_responder 284 | jsr .open_w_15 285 | ldy #$00 286 | .datalo lda .atnlo,y 287 | jsr .iecout 288 | iny 289 | cpy #.atnlo_end - .atnlo 290 | bne .datalo 291 | jsr .unlisten 292 | 293 | jsr .open_w_15 294 | ldy #$00 295 | .datahi lda .atnhi,y 296 | jsr .iecout 297 | iny 298 | cpy #.atnhi_end - .atnhi 299 | bne .datahi 300 | jsr .unlisten 301 | 302 | jsr .open_w_15 303 | ldy #$00 304 | .fallb lda .fallback,y 305 | jsr .iecout 306 | iny 307 | cpy #.fallback_end - .fallback 308 | bne .fallb 309 | jsr .unlisten 310 | 311 | jsr .open_w_15 312 | ldy #$00 313 | .exec lda .responder,y 314 | jsr .iecout 315 | iny 316 | cpy #.responder_end - .responder 317 | bne .exec 318 | jmp .unlisten 319 | 320 | ;XXX TODO keep current drive in $ba? kill all other drives beforehand, then upload code to #8 321 | .responder_code = $0205 322 | .fallback_code = $0440 323 | .atnlo_code = $0400 324 | .atnhi_code = .atnlo_code + $80 325 | 326 | .mw_code 327 | !text "m-w" 328 | !word .bootstrap_run 329 | !byte $20 330 | .me_code 331 | !text "m-e" 332 | !word .bootstrap_run 333 | 334 | .responder 335 | !text "m-e" 336 | !word .responder_code 337 | !pseudopc .responder_code { 338 | sei 339 | ldx #$10 340 | ldy #$ff 341 | sty $1803 342 | iny 343 | lda #$7f 344 | sta $1802 345 | lda #$04 346 | sta $1801 347 | sty $1800 348 | cmp $1801 349 | beq *+5 350 | jmp .fallback_code 351 | jmp ($1800) 352 | } 353 | .responder_end 354 | 355 | .fallback 356 | !text "m-w" 357 | !word .fallback_code 358 | !byte .fallback_end - .fallback_start 359 | .fallback_start 360 | !pseudopc .fallback_code { 361 | sty $1803 362 | .fb1 363 | bit $1800 364 | bpl .fb1 365 | stx $1800 366 | .fb2 367 | bit $1800 368 | bmi .fb2 369 | sty $1800 370 | jmp .fb1 371 | } 372 | .fallback_end 373 | 374 | .atnlo !text "m-w" 375 | !word .atnlo_code 376 | !byte .atnlo_end - .atnlo_start 377 | .atnlo_start 378 | !pseudopc .atnlo_code { 379 | ;00 380 | jmp ($1800) 381 | * = .atnlo_code + $10 382 | ;10 383 | sty $1800 384 | jmp ($1800) 385 | } 386 | .atnlo_end 387 | 388 | .atnhi !text "m-w" 389 | !word .atnhi_code 390 | !byte .atnhi_end - .atnhi_start 391 | .atnhi_start 392 | !pseudopc .atnhi_code { 393 | ;80 394 | ;stx $1800 395 | ;top 396 | ;84 397 | ;bne .reset_check ;BRA 398 | ;jmp ($1800) 399 | stx $1800 400 | jmp ($1800) ;get $84 free, set $1801 to $7a and check if really $84? 401 | * = .atnhi_code + $10 402 | ;90 403 | jmp ($1800) 404 | } 405 | .atnhi_end 406 | } 407 | } 408 | ;!if (CONFIG_RESIDENT_AUTOINST != 0) { 409 | .res_start 410 | !bin "resident",,2 411 | ;} 412 | 413 | !if CONFIG_CRT = 0 { 414 | !src "drivecode.asm" 415 | } 416 | -------------------------------------------------------------------------------- /loader/tables1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/loader/tables1 -------------------------------------------------------------------------------- /loader/tables2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/loader/tables2 -------------------------------------------------------------------------------- /macros/Makefile: -------------------------------------------------------------------------------- 1 | V ?= 0 2 | ifeq ($(V),1) 3 | VR:= 4 | else 5 | VR:=@ 6 | endif 7 | 8 | all: macros 9 | 10 | macros: link_macros_acme.inc 11 | @echo "Generating macros for other assemblers..." 12 | $(VR)./convert.sh 13 | 14 | clean: 15 | $(VR)-rm link_macros_64tass.inc link_macros_kickass.inc link_macros_dreamass.inc link_macros_ca65.inc link_macros_dasm.inc 16 | -------------------------------------------------------------------------------- /macros/convert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ################### DASM ################### 3 | cat ./link_macros_acme.inc | \ 4 | #comments \ 5 | #sed 's/;/;/g' | \ 6 | sed 's/\r//g' | \ 7 | #remove arg 8 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*\(\.arg\)[[:space:]]*{/\1mac \2/g' | \ 9 | #!macro name { \ 10 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*.*{/\1mac \2/g' | \ 11 | #add end \ 12 | sed 's/^\([[:space:]]*\)*}/\1endm/g' | \ 13 | #replace arg within block \ 14 | sed 's/\(.*[[:graph:]]\)\.arg/\1\{1\}/g' | \ 15 | #remove trailing + from macros \ 16 | sed 's/\(^[[:space:]]*\)+\(.*\)/\1\2/g' \ 17 | > ./link_macros_dasm.inc 18 | ################### 64TASS ################### 19 | cat ./link_macros_acme.inc | \ 20 | #comments \ 21 | #sed 's/;/;/g' | \ 22 | sed 's/\r//g' | \ 23 | #remove arg \ 24 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*\(\.arg\)[[:space:]]*{/\1\2 .macro/g' | \ 25 | #!macro name { \ 26 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*.*{/\1\2 .macro/g' | \ 27 | #add end \ 28 | sed 's/^\([[:space:]]*\)*}/\1.endm/g' | \ 29 | #replace arg within block \ 30 | sed 's/\(.*[[:graph:]]\)\.arg/\1\\1/g' | \ 31 | #replace .l \ 32 | sed 's/\.l/l/g' | \ 33 | #remove trailing + from macros \ 34 | sed 's/\(^[[:space:]]*\)+\(.*\)/\1\2/g' \ 35 | > ./link_macros_64tass.inc 36 | ################### CA65 ################### 37 | cat ./link_macros_acme.inc | \ 38 | #comments \ 39 | #sed 's/;/;/g' | \ 40 | #replace .l \ 41 | sed 's/\r//g' | \ 42 | sed 's/\.l/l/g' | \ 43 | #remove arg \ 44 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*\(\.arg\)[[:space:]]*{/\1.macro \2 arg\n\t\t.local l/g' | \ 45 | #!macro name { \ 46 | #sed 's/\(.*\)\(!macro\)[[:space:]]*\(.*\)[[:space:]]*{/\1\t\t.macro \3\n\t\t.local l/g' | \ 47 | sed 's/^\([[:space:]]*\)!macro[[:space:]]*\([[:graph:]]*\)[[:space:]]*.*{/\1.macro \2\n\t\t.local l/g' | \ 48 | #add end \ 49 | sed 's/^\([[:space:]]*\)}/\1.endmacro/g' | \ 50 | #replace arg within block \ 51 | sed 's/\.arg/arg/g' \ 52 | > ./link_macros_ca65.inc 53 | ################### KICKASS ################### 54 | cat ./link_macros_acme.inc | \ 55 | sed 's/\r//g' | \ 56 | sed 's/(/[/g' | \ 57 | sed 's/)/]/g' | \ 58 | #remove arg \ 59 | sed 's/^\([[:space:]]*\)\(!macro\)[[:space:]]*\(.*\)[[:space:]]*\(\.arg\)[[:space:]]*{/\1.macro \3(arg) {/g' | \ 60 | #!macro name { \ 61 | sed 's/^\([[:space:]]*\)\(!macro\)[[:space:]]*\(.*\)[[:space:]]*{/\1.macro \3() {/g' | \ 62 | #replace arg within block \ 63 | sed 's/\.arg/arg/g' | \ 64 | #replace local labels \ 65 | sed 's/^\.\([[:graph:]]\)$/\1:/g' | \ 66 | sed 's/^;\.\([[:graph:]]\)$/;\1:/g' | \ 67 | sed 's/\.\([[:graph:]]\)\([[:space:]][[:space:]]*\)\(.*\)$/\1\2\3/g' | \ 68 | sed 's/\.\([[:graph:]]\)$/\1/g' | \ 69 | #comments \ 70 | sed 's/;/\/\//g' | \ 71 | #expand macros \ 72 | sed 's/^\([[:space:]]*\)+\([[:graph:]]*\)[[:space:]]*\([[:graph:]]*\)/\1:\2(\3)/' \ 73 | > ./link_macros_kickass.inc 74 | ################### DREAMASS ################### 75 | cat ./link_macros_acme.inc | \ 76 | #comments \ 77 | sed 's/\r//g' | \ 78 | #replace .l \ 79 | sed 's/^\.l/l:/g' | \ 80 | sed 's/^;\.l/;l:/g' | \ 81 | sed 's/\.l/l/g' | \ 82 | #remove arg \ 83 | sed 's/^\([[:space:]]*\)\(!macro\)[[:space:]]*\(.*\)[[:space:]]*\(\.arg\)[[:space:]]*{/\1\t\t#macro \3(arg) {\n.(/g' | \ 84 | #!macro name { \ 85 | sed 's/^\([[:space:]]*\)\(!macro\)[[:space:]]*\(.*\)[[:space:]]*{/\1\t\t#macro \3\n\t\t{\n.(/g' | \ 86 | #endmacro \ 87 | sed 's/^[[:space:]]*}/).\n\t\t}/g' | \ 88 | #replace arg within block \ 89 | sed 's/\.arg/arg/g' \ 90 | > ./link_macros_dreamass.inc 91 | -------------------------------------------------------------------------------- /macros/link_macros_64tass.inc: -------------------------------------------------------------------------------- 1 | link_decomp_under_io .macro 2 | dec $01 ;bank out IO 3 | jsr link_decomp ;depack 4 | inc $01 5 | .endm 6 | 7 | link_load_next_raw_decomp .macro 8 | jsr link_load_next_raw 9 | dec $01 ;bank out IO 10 | jsr link_decomp ;depack 11 | inc $01 12 | .endm 13 | 14 | ;load next file as a raw file (do not decomp on the fly) and jump to .addr 15 | link_load_next_raw_jmp .macro 16 | lda #>(\1-1) 17 | pha 18 | lda #<(\1-1) 19 | pha 20 | jmp link_load_next_raw 21 | .endm 22 | 23 | ;load next file and decomp on the fly, then jump to .arg 24 | link_load_next_comp_jmp .macro 25 | lda #>(\1-1) 26 | pha 27 | lda #<(\1-1) 28 | pha 29 | jmp link_load_next_comp 30 | .endm 31 | 32 | ;decomp previously loaded file and jump to .arg 33 | link_decomp_jmp .macro 34 | lda #>(\1-1) 35 | pha 36 | lda #<(\1-1) 37 | pha 38 | jmp link_decomp 39 | .endm 40 | 41 | link_load_next_double .macro 42 | jsr link_load_next_comp 43 | jsr link_load_next_raw 44 | dec $01 45 | jsr link_decomp 46 | inc $01 47 | .endm 48 | 49 | ;link irq hook back to base irq 50 | link_player_irq .macro 51 | sei 52 | lda #link_player 55 | sta $ffff 56 | lda #$ff 57 | sta $d012 58 | cli 59 | .endm 60 | 61 | reset_drive .macro 62 | lda #BITFIRE_RESET 63 | jsr bitfire_send_byte_ 64 | .endm 65 | 66 | ;request next disk side and reset filenum_counter 67 | request_disk .macro 68 | lda #\1 + $ef 69 | ;simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-) 70 | jsr bitfire_loadraw_ 71 | .endm 72 | 73 | ;wait for given frame counter value 74 | link_wait_syncpoint .macro 75 | l 76 | lda link_syncpoint 77 | cmp #\1 78 | bcc l 79 | .endm 80 | 81 | setup_sync .macro 82 | lda #$00 83 | sta link_frame_count + 0 ;avoid that the counter wraps worstcase, as we can't write atomic 84 | lda #>($8000-\1) 85 | sta link_frame_count + 1 86 | lda #<($8000-\1) 87 | sta link_frame_count + 0 ;now setup counter 88 | .endm 89 | 90 | sync .macro 91 | l 92 | lda link_frame_count + 1 ;Counter expired when $8000 is reached 93 | bpl l 94 | .endm 95 | 96 | bus_lock .macro 97 | lda #$37 ;set ATN 98 | sta $dd02 99 | .endm 100 | 101 | bus_unlock .macro 102 | lda $dd00 103 | and #$03 104 | sta $dd00 105 | lda #$3f 106 | sta $dd02 107 | .endm 108 | 109 | set_depack_pointers .macro 110 | lda #<\1 111 | sta bitfire_load_addr_lo 112 | lda #>\1 113 | sta bitfire_load_addr_hi 114 | .endm 115 | 116 | link_music_update .macro 117 | inc link_frame_count + 0 118 | bne l 119 | inc link_frame_count + 1 120 | l 121 | jmp (link_music_addr) 122 | .endm 123 | 124 | to_nmi .macro 125 | lda #$ad 126 | sta link_player + 7 127 | lda #$0d 128 | sta link_player + 8 129 | lda #$dd 130 | sta link_player + 9 131 | .endm 132 | 133 | to_irq .macro 134 | lda #$ce 135 | sta link_player + 7 136 | lda #$19 137 | sta link_player + 8 138 | lda #$d0 139 | sta link_player + 9 140 | .endm 141 | 142 | switch_to_nmi .macro 143 | lda #$fe 144 | l 145 | cmp $d012 146 | bne l 147 | sei 148 | to_nmi 149 | start_music_nmi 150 | jsr link_music_play 151 | .endm 152 | 153 | switch_to_irq .macro 154 | lda #$fe 155 | l 156 | cmp $d012 157 | bne l 158 | stop_music_nmi 159 | to_irq 160 | ldx #link_player 162 | 163 | stx $fffe 164 | sta $ffff 165 | lda #$ff 166 | sta $d012 167 | jsr link_music_play 168 | .endm 169 | 170 | start_music_nmi .macro 171 | ;lda #$20 172 | ;sta link_music_play_jmp 173 | ldx #link_player 175 | 176 | stx $fffa 177 | sta $fffb 178 | lda #$00 179 | sta $dd0e 180 | lda $dd0d 181 | lda #$c7 182 | sta $dd04 183 | lda #$4c 184 | sta $dd05 185 | lda #$81 186 | sta $dd0d 187 | 188 | lda #$ff 189 | l 190 | cmp $d012 191 | bne l 192 | 193 | lda #$11 194 | sta $dd0e 195 | .endm 196 | 197 | stop_music_nmi .macro 198 | lda #$7f 199 | sta $dd0d 200 | lda $dd0d 201 | .endm 202 | 203 | restart_music_nmi .macro 204 | lda $dd0d 205 | lda #$81 206 | sta $dd0d 207 | .endm 208 | 209 | set_music_addr .macro 210 | lda #<\1 211 | sta link_music_addr + 0 212 | lda #>\1 213 | sta link_music_addr + 1 214 | .endm 215 | 216 | wait_space .macro 217 | lda #$7f 218 | sta $dc00 219 | lda #$10 220 | l 221 | 222 | bit $dc01 223 | bne l 224 | .endm 225 | 226 | wait_shift_lock .macro 227 | lda #$fd 228 | sta $dc00 229 | l 230 | lda $dc01 231 | bpl l 232 | .endm 233 | 234 | crt_request_disk .macro 235 | setup_sync .arg 236 | l 237 | lda #$7f ;space pressed? 238 | sta $dc00 239 | lda $dc01 240 | and #$10 241 | beq .e ;yes, exit 242 | lda link_frame_count + 1 ;check counter 243 | bpl .g 244 | sta .f + 1 245 | .g 246 | lda #$fd ;shift lock pressed? 247 | sta $dc00 248 | lda $dc01 249 | .f 250 | and #$00 251 | bpl l ;shift lock pressed or not expired 252 | .e 253 | .endm 254 | 255 | skip_file .macro 256 | lda #BITFIRE_SKIP_FILE 257 | jsr bitfire_loadraw_ 258 | .endm 259 | 260 | ; !macro gaps_setup { 261 | ; ldx #$09 262 | ;l 263 | ; lda CONFIG_RESIDENT_ADDR + $000,x 264 | ; pha 265 | ; lda CONFIG_RESIDENT_ADDR + $100,x 266 | ; pha 267 | ; dex 268 | ; bpl l 269 | ; } 270 | ; 271 | ; !macro gaps_restore { 272 | ; ldx #$00 273 | ;l 274 | ; pla 275 | ; sta CONFIG_RESIDENT_ADDR + $000,x 276 | ; pla 277 | ; sta CONFIG_RESIDENT_ADDR + $100,x 278 | ; inx 279 | ; cpx #$0a 280 | ; bne l 281 | ; } 282 | -------------------------------------------------------------------------------- /macros/link_macros_acme.inc: -------------------------------------------------------------------------------- 1 | !macro link_decomp_under_io { 2 | dec $01 ;bank out IO 3 | jsr link_decomp ;depack 4 | inc $01 5 | } 6 | 7 | !macro link_load_next_raw_decomp { 8 | jsr link_load_next_raw 9 | dec $01 ;bank out IO 10 | jsr link_decomp ;depack 11 | inc $01 12 | } 13 | 14 | ;load next file as a raw file (do not decomp on the fly) and jump to .addr 15 | !macro link_load_next_raw_jmp .arg { 16 | lda #>(.arg-1) 17 | pha 18 | lda #<(.arg-1) 19 | pha 20 | jmp link_load_next_raw 21 | } 22 | 23 | ;load next file and decomp on the fly, then jump to .arg 24 | !macro link_load_next_comp_jmp .arg { 25 | lda #>(.arg-1) 26 | pha 27 | lda #<(.arg-1) 28 | pha 29 | jmp link_load_next_comp 30 | } 31 | 32 | ;decomp previously loaded file and jump to .arg 33 | !macro link_decomp_jmp .arg { 34 | lda #>(.arg-1) 35 | pha 36 | lda #<(.arg-1) 37 | pha 38 | jmp link_decomp 39 | } 40 | 41 | !macro link_load_next_double { 42 | jsr link_load_next_comp 43 | jsr link_load_next_raw 44 | dec $01 45 | jsr link_decomp 46 | inc $01 47 | } 48 | 49 | ;link irq hook back to base irq 50 | !macro link_player_irq { 51 | sei 52 | lda #link_player 55 | sta $ffff 56 | lda #$ff 57 | sta $d012 58 | cli 59 | } 60 | 61 | !macro reset_drive { 62 | lda #BITFIRE_RESET 63 | jsr bitfire_send_byte_ 64 | } 65 | 66 | ;request next disk side and reset filenum_counter 67 | !macro request_disk .arg { 68 | lda #.arg + $ef 69 | ;simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-) 70 | jsr bitfire_loadraw_ 71 | } 72 | 73 | ;wait for given frame counter value 74 | !macro link_wait_syncpoint .arg { 75 | .l 76 | lda link_syncpoint 77 | cmp #.arg 78 | bcc .l 79 | } 80 | 81 | !macro setup_sync .arg { 82 | lda #$00 83 | sta link_frame_count + 0 ;avoid that the counter wraps worstcase, as we can't write atomic 84 | lda #>($8000-.arg) 85 | sta link_frame_count + 1 86 | lda #<($8000-.arg) 87 | sta link_frame_count + 0 ;now setup counter 88 | } 89 | 90 | !macro sync { 91 | .l 92 | lda link_frame_count + 1 ;Counter expired when $8000 is reached 93 | bpl .l 94 | } 95 | 96 | !macro bus_lock { 97 | lda #$37 ;set ATN 98 | sta $dd02 99 | } 100 | 101 | !macro bus_unlock { 102 | lda $dd00 103 | and #$03 104 | sta $dd00 105 | lda #$3f 106 | sta $dd02 107 | } 108 | 109 | !macro set_depack_pointers .arg { 110 | lda #<.arg 111 | sta bitfire_load_addr_lo 112 | lda #>.arg 113 | sta bitfire_load_addr_hi 114 | } 115 | 116 | !macro link_music_update { 117 | inc link_frame_count + 0 118 | bne .l 119 | inc link_frame_count + 1 120 | .l 121 | jmp (link_music_addr) 122 | } 123 | 124 | !macro to_nmi { 125 | lda #$ad 126 | sta link_player + 7 127 | lda #$0d 128 | sta link_player + 8 129 | lda #$dd 130 | sta link_player + 9 131 | } 132 | 133 | !macro to_irq { 134 | lda #$ce 135 | sta link_player + 7 136 | lda #$19 137 | sta link_player + 8 138 | lda #$d0 139 | sta link_player + 9 140 | } 141 | 142 | !macro switch_to_nmi { 143 | lda #$fe 144 | .l 145 | cmp $d012 146 | bne .l 147 | sei 148 | +to_nmi 149 | +start_music_nmi 150 | jsr link_music_play 151 | } 152 | 153 | !macro switch_to_irq { 154 | lda #$fe 155 | .l 156 | cmp $d012 157 | bne .l 158 | +stop_music_nmi 159 | +to_irq 160 | ldx #link_player 162 | 163 | stx $fffe 164 | sta $ffff 165 | lda #$ff 166 | sta $d012 167 | jsr link_music_play 168 | } 169 | 170 | !macro start_music_nmi { 171 | ;lda #$20 172 | ;sta link_music_play_jmp 173 | ldx #link_player 175 | 176 | stx $fffa 177 | sta $fffb 178 | lda #$00 179 | sta $dd0e 180 | lda $dd0d 181 | lda #$c7 182 | sta $dd04 183 | lda #$4c 184 | sta $dd05 185 | lda #$81 186 | sta $dd0d 187 | 188 | lda #$ff 189 | .l 190 | cmp $d012 191 | bne .l 192 | 193 | lda #$11 194 | sta $dd0e 195 | } 196 | 197 | !macro stop_music_nmi { 198 | lda #$7f 199 | sta $dd0d 200 | lda $dd0d 201 | } 202 | 203 | !macro restart_music_nmi { 204 | lda $dd0d 205 | lda #$81 206 | sta $dd0d 207 | } 208 | 209 | !macro set_music_addr .arg { 210 | lda #<.arg 211 | sta link_music_addr + 0 212 | lda #>.arg 213 | sta link_music_addr + 1 214 | } 215 | 216 | !macro wait_space { 217 | lda #$7f 218 | sta $dc00 219 | lda #$10 220 | .l 221 | 222 | bit $dc01 223 | bne .l 224 | } 225 | 226 | !macro wait_shift_lock { 227 | lda #$fd 228 | sta $dc00 229 | .l 230 | lda $dc01 231 | bpl .l 232 | } 233 | 234 | !macro crt_request_disk .arg { 235 | +setup_sync .arg 236 | .l 237 | lda #$7f ;space pressed? 238 | sta $dc00 239 | lda $dc01 240 | and #$10 241 | beq .e ;yes, exit 242 | lda link_frame_count + 1 ;check counter 243 | bpl .g 244 | sta .f + 1 245 | .g 246 | lda #$fd ;shift lock pressed? 247 | sta $dc00 248 | lda $dc01 249 | .f 250 | and #$00 251 | bpl .l ;shift lock pressed or not expired 252 | .e 253 | } 254 | 255 | !macro skip_file { 256 | lda #BITFIRE_SKIP_FILE 257 | jsr bitfire_loadraw_ 258 | } 259 | 260 | ; !macro gaps_setup { 261 | ; ldx #$09 262 | ;.l 263 | ; lda CONFIG_RESIDENT_ADDR + $000,x 264 | ; pha 265 | ; lda CONFIG_RESIDENT_ADDR + $100,x 266 | ; pha 267 | ; dex 268 | ; bpl .l 269 | ; } 270 | ; 271 | ; !macro gaps_restore { 272 | ; ldx #$00 273 | ;.l 274 | ; pla 275 | ; sta CONFIG_RESIDENT_ADDR + $000,x 276 | ; pla 277 | ; sta CONFIG_RESIDENT_ADDR + $100,x 278 | ; inx 279 | ; cpx #$0a 280 | ; bne .l 281 | ; } 282 | -------------------------------------------------------------------------------- /macros/link_macros_ca65.inc: -------------------------------------------------------------------------------- 1 | .macro link_decomp_under_io 2 | .local l 3 | dec $01 ;bank out IO 4 | jsr link_decomp ;depack 5 | inc $01 6 | .endmacro 7 | 8 | .macro link_load_next_raw_decomp 9 | .local l 10 | jsr link_load_next_raw 11 | dec $01 ;bank out IO 12 | jsr link_decomp ;depack 13 | inc $01 14 | .endmacro 15 | 16 | ;load next file as a raw file (do not decomp on the fly) and jump to .addr 17 | .macro link_load_next_raw_jmp arg 18 | .local l 19 | lda #>(arg-1) 20 | pha 21 | lda #<(arg-1) 22 | pha 23 | jmp link_load_next_raw 24 | .endmacro 25 | 26 | ;load next file and decomp on the fly, then jump to arg 27 | .macro link_load_next_comp_jmp arg 28 | .local l 29 | lda #>(arg-1) 30 | pha 31 | lda #<(arg-1) 32 | pha 33 | jmp link_load_next_comp 34 | .endmacro 35 | 36 | ;decomp previously loaded file and jump to arg 37 | .macro link_decomp_jmp arg 38 | .local l 39 | lda #>(arg-1) 40 | pha 41 | lda #<(arg-1) 42 | pha 43 | jmp link_decomp 44 | .endmacro 45 | 46 | .macro link_load_next_double 47 | .local l 48 | jsr link_load_next_comp 49 | jsr link_load_next_raw 50 | dec $01 51 | jsr link_decomp 52 | inc $01 53 | .endmacro 54 | 55 | ;link irq hook back to base irq 56 | .macro link_player_irq 57 | .local l 58 | sei 59 | lda #link_player 62 | sta $ffff 63 | lda #$ff 64 | sta $d012 65 | cli 66 | .endmacro 67 | 68 | .macro reset_drive 69 | .local l 70 | lda #BITFIRE_RESET 71 | jsr bitfire_send_byte_ 72 | .endmacro 73 | 74 | ;request next disk side and reset filenum_counter 75 | .macro request_disk arg 76 | .local l 77 | lda #arg + $ef 78 | ;simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-) 79 | jsr bitfire_loadraw_ 80 | .endmacro 81 | 82 | ;wait for given frame counter value 83 | .macro link_wait_syncpoint arg 84 | .local l 85 | l 86 | lda link_syncpoint 87 | cmp #arg 88 | bcc l 89 | .endmacro 90 | 91 | .macro setup_sync arg 92 | .local l 93 | lda #$00 94 | sta link_frame_count + 0 ;avoid that the counter wraps worstcase, as we can't write atomic 95 | lda #>($8000-arg) 96 | sta link_frame_count + 1 97 | lda #<($8000-arg) 98 | sta link_frame_count + 0 ;now setup counter 99 | .endmacro 100 | 101 | .macro sync 102 | .local l 103 | l 104 | lda link_frame_count + 1 ;Counter expired when $8000 is reached 105 | bpl l 106 | .endmacro 107 | 108 | .macro bus_lock 109 | .local l 110 | lda #$37 ;set ATN 111 | sta $dd02 112 | .endmacro 113 | 114 | .macro bus_unlock 115 | .local l 116 | lda $dd00 117 | and #$03 118 | sta $dd00 119 | lda #$3f 120 | sta $dd02 121 | .endmacro 122 | 123 | .macro set_depack_pointers arg 124 | .local l 125 | lda #arg 128 | sta bitfire_load_addr_hi 129 | .endmacro 130 | 131 | .macro link_music_update 132 | .local l 133 | inc link_frame_count + 0 134 | bne l 135 | inc link_frame_count + 1 136 | l 137 | jmp (link_music_addr) 138 | .endmacro 139 | 140 | .macro to_nmi 141 | .local l 142 | lda #$ad 143 | sta link_player + 7 144 | lda #$0d 145 | sta link_player + 8 146 | lda #$dd 147 | sta link_player + 9 148 | .endmacro 149 | 150 | .macro to_irq 151 | .local l 152 | lda #$ce 153 | sta link_player + 7 154 | lda #$19 155 | sta link_player + 8 156 | lda #$d0 157 | sta link_player + 9 158 | .endmacro 159 | 160 | .macro switch_to_nmi 161 | .local l 162 | lda #$fe 163 | l 164 | cmp $d012 165 | bne l 166 | sei 167 | +to_nmi 168 | +start_music_nmi 169 | jsr link_music_play 170 | .endmacro 171 | 172 | .macro switch_to_irq 173 | .local l 174 | lda #$fe 175 | l 176 | cmp $d012 177 | bne l 178 | +stop_music_nmi 179 | +to_irq 180 | ldx #link_player 182 | 183 | stx $fffe 184 | sta $ffff 185 | lda #$ff 186 | sta $d012 187 | jsr link_music_play 188 | .endmacro 189 | 190 | .macro start_music_nmi 191 | .local l 192 | ;lda #$20 193 | ;sta link_music_play_jmp 194 | ldx #link_player 196 | 197 | stx $fffa 198 | sta $fffb 199 | lda #$00 200 | sta $dd0e 201 | lda $dd0d 202 | lda #$c7 203 | sta $dd04 204 | lda #$4c 205 | sta $dd05 206 | lda #$81 207 | sta $dd0d 208 | 209 | lda #$ff 210 | l 211 | cmp $d012 212 | bne l 213 | 214 | lda #$11 215 | sta $dd0e 216 | .endmacro 217 | 218 | .macro stop_music_nmi 219 | .local l 220 | lda #$7f 221 | sta $dd0d 222 | lda $dd0d 223 | .endmacro 224 | 225 | .macro restart_music_nmi 226 | .local l 227 | lda $dd0d 228 | lda #$81 229 | sta $dd0d 230 | .endmacro 231 | 232 | .macro set_music_addr arg 233 | .local l 234 | lda #arg 237 | sta link_music_addr + 1 238 | .endmacro 239 | 240 | .macro wait_space 241 | .local l 242 | lda #$7f 243 | sta $dc00 244 | lda #$10 245 | l 246 | 247 | bit $dc01 248 | bne l 249 | .endmacro 250 | 251 | .macro wait_shift_lock 252 | .local l 253 | lda #$fd 254 | sta $dc00 255 | l 256 | lda $dc01 257 | bpl l 258 | .endmacro 259 | 260 | .macro crt_request_disk arg 261 | .local l 262 | +setup_sync arg 263 | l 264 | lda #$7f ;space pressed? 265 | sta $dc00 266 | lda $dc01 267 | and #$10 268 | beq .e ;yes, exit 269 | lda link_frame_count + 1 ;check counter 270 | bpl .g 271 | sta .f + 1 272 | .g 273 | lda #$fd ;shift lock pressed? 274 | sta $dc00 275 | lda $dc01 276 | .f 277 | and #$00 278 | bpl l ;shift lock pressed or not expired 279 | .e 280 | .endmacro 281 | 282 | .macro skip_file 283 | .local l 284 | lda #BITFIRE_SKIP_FILE 285 | jsr bitfire_loadraw_ 286 | .endmacro 287 | 288 | ; !macro gaps_setup { 289 | ; ldx #$09 290 | ;l 291 | ; lda CONFIG_RESIDENT_ADDR + $000,x 292 | ; pha 293 | ; lda CONFIG_RESIDENT_ADDR + $100,x 294 | ; pha 295 | ; dex 296 | ; bpl l 297 | ; } 298 | ; 299 | ; !macro gaps_restore { 300 | ; ldx #$00 301 | ;l 302 | ; pla 303 | ; sta CONFIG_RESIDENT_ADDR + $000,x 304 | ; pla 305 | ; sta CONFIG_RESIDENT_ADDR + $100,x 306 | ; inx 307 | ; cpx #$0a 308 | ; bne l 309 | ; } 310 | -------------------------------------------------------------------------------- /macros/link_macros_dasm.inc: -------------------------------------------------------------------------------- 1 | mac link_decomp_under_io 2 | dec $01 ;bank out IO 3 | jsr link_decomp ;depack 4 | inc $01 5 | endm 6 | 7 | mac link_load_next_raw_decomp 8 | jsr link_load_next_raw 9 | dec $01 ;bank out IO 10 | jsr link_decomp ;depack 11 | inc $01 12 | endm 13 | 14 | ;load next file as a raw file (do not decomp on the fly) and jump to .addr 15 | mac link_load_next_raw_jmp 16 | lda #>({1}-1) 17 | pha 18 | lda #<({1}-1) 19 | pha 20 | jmp link_load_next_raw 21 | endm 22 | 23 | ;load next file and decomp on the fly, then jump to .arg 24 | mac link_load_next_comp_jmp 25 | lda #>({1}-1) 26 | pha 27 | lda #<({1}-1) 28 | pha 29 | jmp link_load_next_comp 30 | endm 31 | 32 | ;decomp previously loaded file and jump to .arg 33 | mac link_decomp_jmp 34 | lda #>({1}-1) 35 | pha 36 | lda #<({1}-1) 37 | pha 38 | jmp link_decomp 39 | endm 40 | 41 | mac link_load_next_double 42 | jsr link_load_next_comp 43 | jsr link_load_next_raw 44 | dec $01 45 | jsr link_decomp 46 | inc $01 47 | endm 48 | 49 | ;link irq hook back to base irq 50 | mac link_player_irq 51 | sei 52 | lda #link_player 55 | sta $ffff 56 | lda #$ff 57 | sta $d012 58 | cli 59 | endm 60 | 61 | mac reset_drive 62 | lda #BITFIRE_RESET 63 | jsr bitfire_send_byte_ 64 | endm 65 | 66 | ;request next disk side and reset filenum_counter 67 | mac request_disk 68 | lda #{1} + $ef 69 | ;simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-) 70 | jsr bitfire_loadraw_ 71 | endm 72 | 73 | ;wait for given frame counter value 74 | mac link_wait_syncpoint 75 | .l 76 | lda link_syncpoint 77 | cmp #{1} 78 | bcc .l 79 | endm 80 | 81 | mac setup_sync 82 | lda #$00 83 | sta link_frame_count + 0 ;avoid that the counter wraps worstcase, as we can't write atomic 84 | lda #>($8000-{1}) 85 | sta link_frame_count + 1 86 | lda #<($8000-{1}) 87 | sta link_frame_count + 0 ;now setup counter 88 | endm 89 | 90 | mac sync 91 | .l 92 | lda link_frame_count + 1 ;Counter expired when $8000 is reached 93 | bpl .l 94 | endm 95 | 96 | mac bus_lock 97 | lda #$37 ;set ATN 98 | sta $dd02 99 | endm 100 | 101 | mac bus_unlock 102 | lda $dd00 103 | and #$03 104 | sta $dd00 105 | lda #$3f 106 | sta $dd02 107 | endm 108 | 109 | mac set_depack_pointers 110 | lda #<{1} 111 | sta bitfire_load_addr_lo 112 | lda #>{1} 113 | sta bitfire_load_addr_hi 114 | endm 115 | 116 | mac link_music_update 117 | inc link_frame_count + 0 118 | bne .l 119 | inc link_frame_count + 1 120 | .l 121 | jmp (link_music_addr) 122 | endm 123 | 124 | mac to_nmi 125 | lda #$ad 126 | sta link_player + 7 127 | lda #$0d 128 | sta link_player + 8 129 | lda #$dd 130 | sta link_player + 9 131 | endm 132 | 133 | mac to_irq 134 | lda #$ce 135 | sta link_player + 7 136 | lda #$19 137 | sta link_player + 8 138 | lda #$d0 139 | sta link_player + 9 140 | endm 141 | 142 | mac switch_to_nmi 143 | lda #$fe 144 | .l 145 | cmp $d012 146 | bne .l 147 | sei 148 | to_nmi 149 | start_music_nmi 150 | jsr link_music_play 151 | endm 152 | 153 | mac switch_to_irq 154 | lda #$fe 155 | .l 156 | cmp $d012 157 | bne .l 158 | stop_music_nmi 159 | to_irq 160 | ldx #link_player 162 | 163 | stx $fffe 164 | sta $ffff 165 | lda #$ff 166 | sta $d012 167 | jsr link_music_play 168 | endm 169 | 170 | mac start_music_nmi 171 | ;lda #$20 172 | ;sta link_music_play_jmp 173 | ldx #link_player 175 | 176 | stx $fffa 177 | sta $fffb 178 | lda #$00 179 | sta $dd0e 180 | lda $dd0d 181 | lda #$c7 182 | sta $dd04 183 | lda #$4c 184 | sta $dd05 185 | lda #$81 186 | sta $dd0d 187 | 188 | lda #$ff 189 | .l 190 | cmp $d012 191 | bne .l 192 | 193 | lda #$11 194 | sta $dd0e 195 | endm 196 | 197 | mac stop_music_nmi 198 | lda #$7f 199 | sta $dd0d 200 | lda $dd0d 201 | endm 202 | 203 | mac restart_music_nmi 204 | lda $dd0d 205 | lda #$81 206 | sta $dd0d 207 | endm 208 | 209 | mac set_music_addr 210 | lda #<{1} 211 | sta link_music_addr + 0 212 | lda #>{1} 213 | sta link_music_addr + 1 214 | endm 215 | 216 | mac wait_space 217 | lda #$7f 218 | sta $dc00 219 | lda #$10 220 | .l 221 | 222 | bit $dc01 223 | bne .l 224 | endm 225 | 226 | mac wait_shift_lock 227 | lda #$fd 228 | sta $dc00 229 | .l 230 | lda $dc01 231 | bpl .l 232 | endm 233 | 234 | mac crt_request_disk 235 | setup_sync .arg 236 | .l 237 | lda #$7f ;space pressed? 238 | sta $dc00 239 | lda $dc01 240 | and #$10 241 | beq .e ;yes, exit 242 | lda link_frame_count + 1 ;check counter 243 | bpl .g 244 | sta .f + 1 245 | .g 246 | lda #$fd ;shift lock pressed? 247 | sta $dc00 248 | lda $dc01 249 | .f 250 | and #$00 251 | bpl .l ;shift lock pressed or not expired 252 | .e 253 | endm 254 | 255 | mac skip_file 256 | lda #BITFIRE_SKIP_FILE 257 | jsr bitfire_loadraw_ 258 | endm 259 | 260 | ; !macro gaps_setup { 261 | ; ldx #$09 262 | ;.l 263 | ; lda CONFIG_RESIDENT_ADDR + $000,x 264 | ; pha 265 | ; lda CONFIG_RESIDENT_ADDR + $100,x 266 | ; pha 267 | ; dex 268 | ; bpl .l 269 | ; } 270 | ; 271 | ; !macro gaps_restore { 272 | ; ldx #$00 273 | ;.l 274 | ; pla 275 | ; sta CONFIG_RESIDENT_ADDR + $000,x 276 | ; pla 277 | ; sta CONFIG_RESIDENT_ADDR + $100,x 278 | ; inx 279 | ; cpx #$0a 280 | ; bne .l 281 | ; } 282 | -------------------------------------------------------------------------------- /macros/link_macros_dreamass.inc: -------------------------------------------------------------------------------- 1 | #macro link_decomp_under_io 2 | { 3 | .( 4 | dec $01 ;bank out IO 5 | jsr link_decomp ;depack 6 | inc $01 7 | ). 8 | } 9 | 10 | #macro link_load_next_raw_decomp 11 | { 12 | .( 13 | jsr link_load_next_raw 14 | dec $01 ;bank out IO 15 | jsr link_decomp ;depack 16 | inc $01 17 | ). 18 | } 19 | 20 | ;load next file as a raw file (do not decomp on the fly) and jump to .addr 21 | #macro link_load_next_raw_jmp (arg) { 22 | .( 23 | lda #>(arg-1) 24 | pha 25 | lda #<(arg-1) 26 | pha 27 | jmp link_load_next_raw 28 | ). 29 | } 30 | 31 | ;load next file and decomp on the fly, then jump to arg 32 | #macro link_load_next_comp_jmp (arg) { 33 | .( 34 | lda #>(arg-1) 35 | pha 36 | lda #<(arg-1) 37 | pha 38 | jmp link_load_next_comp 39 | ). 40 | } 41 | 42 | ;decomp previously loaded file and jump to arg 43 | #macro link_decomp_jmp (arg) { 44 | .( 45 | lda #>(arg-1) 46 | pha 47 | lda #<(arg-1) 48 | pha 49 | jmp link_decomp 50 | ). 51 | } 52 | 53 | #macro link_load_next_double 54 | { 55 | .( 56 | jsr link_load_next_comp 57 | jsr link_load_next_raw 58 | dec $01 59 | jsr link_decomp 60 | inc $01 61 | ). 62 | } 63 | 64 | ;link irq hook back to base irq 65 | #macro link_player_irq 66 | { 67 | .( 68 | sei 69 | lda #link_player 72 | sta $ffff 73 | lda #$ff 74 | sta $d012 75 | cli 76 | ). 77 | } 78 | 79 | #macro reset_drive 80 | { 81 | .( 82 | lda #BITFIRE_RESET 83 | jsr bitfire_send_byte_ 84 | ). 85 | } 86 | 87 | ;request next disk side and reset filenum_counter 88 | #macro request_disk (arg) { 89 | .( 90 | lda #arg + $ef 91 | ;simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-) 92 | jsr bitfire_loadraw_ 93 | ). 94 | } 95 | 96 | ;wait for given frame counter value 97 | #macro link_wait_syncpoint (arg) { 98 | .( 99 | l: 100 | lda link_syncpoint 101 | cmp #arg 102 | bcc l 103 | ). 104 | } 105 | 106 | #macro setup_sync (arg) { 107 | .( 108 | lda #$00 109 | sta link_frame_count + 0 ;avoid that the counter wraps worstcase, as we can't write atomic 110 | lda #>($8000-arg) 111 | sta link_frame_count + 1 112 | lda #<($8000-arg) 113 | sta link_frame_count + 0 ;now setup counter 114 | ). 115 | } 116 | 117 | #macro sync 118 | { 119 | .( 120 | l: 121 | lda link_frame_count + 1 ;Counter expired when $8000 is reached 122 | bpl l 123 | ). 124 | } 125 | 126 | #macro bus_lock 127 | { 128 | .( 129 | lda #$37 ;set ATN 130 | sta $dd02 131 | ). 132 | } 133 | 134 | #macro bus_unlock 135 | { 136 | .( 137 | lda $dd00 138 | and #$03 139 | sta $dd00 140 | lda #$3f 141 | sta $dd02 142 | ). 143 | } 144 | 145 | #macro set_depack_pointers (arg) { 146 | .( 147 | lda #arg 150 | sta bitfire_load_addr_hi 151 | ). 152 | } 153 | 154 | #macro link_music_update 155 | { 156 | .( 157 | inc link_frame_count + 0 158 | bne l 159 | inc link_frame_count + 1 160 | l: 161 | jmp (link_music_addr) 162 | ). 163 | } 164 | 165 | #macro to_nmi 166 | { 167 | .( 168 | lda #$ad 169 | sta link_player + 7 170 | lda #$0d 171 | sta link_player + 8 172 | lda #$dd 173 | sta link_player + 9 174 | ). 175 | } 176 | 177 | #macro to_irq 178 | { 179 | .( 180 | lda #$ce 181 | sta link_player + 7 182 | lda #$19 183 | sta link_player + 8 184 | lda #$d0 185 | sta link_player + 9 186 | ). 187 | } 188 | 189 | #macro switch_to_nmi 190 | { 191 | .( 192 | lda #$fe 193 | l: 194 | cmp $d012 195 | bne l 196 | sei 197 | +to_nmi 198 | +start_music_nmi 199 | jsr link_music_play 200 | ). 201 | } 202 | 203 | #macro switch_to_irq 204 | { 205 | .( 206 | lda #$fe 207 | l: 208 | cmp $d012 209 | bne l 210 | +stop_music_nmi 211 | +to_irq 212 | ldx #link_player 214 | 215 | stx $fffe 216 | sta $ffff 217 | lda #$ff 218 | sta $d012 219 | jsr link_music_play 220 | ). 221 | } 222 | 223 | #macro start_music_nmi 224 | { 225 | .( 226 | ;lda #$20 227 | ;sta link_music_play_jmp 228 | ldx #link_player 230 | 231 | stx $fffa 232 | sta $fffb 233 | lda #$00 234 | sta $dd0e 235 | lda $dd0d 236 | lda #$c7 237 | sta $dd04 238 | lda #$4c 239 | sta $dd05 240 | lda #$81 241 | sta $dd0d 242 | 243 | lda #$ff 244 | l: 245 | cmp $d012 246 | bne l 247 | 248 | lda #$11 249 | sta $dd0e 250 | ). 251 | } 252 | 253 | #macro stop_music_nmi 254 | { 255 | .( 256 | lda #$7f 257 | sta $dd0d 258 | lda $dd0d 259 | ). 260 | } 261 | 262 | #macro restart_music_nmi 263 | { 264 | .( 265 | lda $dd0d 266 | lda #$81 267 | sta $dd0d 268 | ). 269 | } 270 | 271 | #macro set_music_addr (arg) { 272 | .( 273 | lda #arg 276 | sta link_music_addr + 1 277 | ). 278 | } 279 | 280 | #macro wait_space 281 | { 282 | .( 283 | lda #$7f 284 | sta $dc00 285 | lda #$10 286 | l: 287 | 288 | bit $dc01 289 | bne l 290 | ). 291 | } 292 | 293 | #macro wait_shift_lock 294 | { 295 | .( 296 | lda #$fd 297 | sta $dc00 298 | l: 299 | lda $dc01 300 | bpl l 301 | ). 302 | } 303 | 304 | #macro crt_request_disk (arg) { 305 | .( 306 | +setup_sync arg 307 | l: 308 | lda #$7f ;space pressed? 309 | sta $dc00 310 | lda $dc01 311 | and #$10 312 | beq .e ;yes, exit 313 | lda link_frame_count + 1 ;check counter 314 | bpl .g 315 | sta .f + 1 316 | .g 317 | lda #$fd ;shift lock pressed? 318 | sta $dc00 319 | lda $dc01 320 | .f 321 | and #$00 322 | bpl l ;shift lock pressed or not expired 323 | .e 324 | ). 325 | } 326 | 327 | #macro skip_file 328 | { 329 | .( 330 | lda #BITFIRE_SKIP_FILE 331 | jsr bitfire_loadraw_ 332 | ). 333 | } 334 | 335 | ; !macro gaps_setup { 336 | ; ldx #$09 337 | ;l: 338 | ; lda CONFIG_RESIDENT_ADDR + $000,x 339 | ; pha 340 | ; lda CONFIG_RESIDENT_ADDR + $100,x 341 | ; pha 342 | ; dex 343 | ; bpl l 344 | ; } 345 | ; 346 | ; !macro gaps_restore { 347 | ; ldx #$00 348 | ;l: 349 | ; pla 350 | ; sta CONFIG_RESIDENT_ADDR + $000,x 351 | ; pla 352 | ; sta CONFIG_RESIDENT_ADDR + $100,x 353 | ; inx 354 | ; cpx #$0a 355 | ; bne l 356 | ; } 357 | -------------------------------------------------------------------------------- /macros/link_macros_kickass.inc: -------------------------------------------------------------------------------- 1 | .macro link_decomp_under_io () { 2 | dec $01 //bank out IO 3 | jsr link_decomp //depack 4 | inc $01 5 | } 6 | 7 | .macro link_load_next_raw_decomp () { 8 | jsr link_load_next_raw 9 | dec $01 //bank out IO 10 | jsr link_decomp //depack 11 | inc $01 12 | } 13 | 14 | //load next file as a raw file [do not decomp on the fly] and jump to .addr 15 | .macro link_load_next_raw_jmp (arg) { 16 | lda #>[arg-1] 17 | pha 18 | lda #<[arg-1] 19 | pha 20 | jmp link_load_next_raw 21 | } 22 | 23 | //load next file and decomp on the fly, then jump to arg 24 | .macro link_load_next_comp_jmp (arg) { 25 | lda #>[arg-1] 26 | pha 27 | lda #<[arg-1] 28 | pha 29 | jmp link_load_next_comp 30 | } 31 | 32 | //decomp previously loaded file and jump to arg 33 | .macro link_decomp_jmp (arg) { 34 | lda #>[arg-1] 35 | pha 36 | lda #<[arg-1] 37 | pha 38 | jmp link_decomp 39 | } 40 | 41 | .macro link_load_next_double () { 42 | jsr link_load_next_comp 43 | jsr link_load_next_raw 44 | dec $01 45 | jsr link_decomp 46 | inc $01 47 | } 48 | 49 | //link irq hook back to base irq 50 | .macro link_player_irq () { 51 | sei 52 | lda #link_player 55 | sta $ffff 56 | lda #$ff 57 | sta $d012 58 | cli 59 | } 60 | 61 | .macro reset_drive () { 62 | lda #BITFIRE_RESET 63 | jsr bitfire_send_byte_ 64 | } 65 | 66 | //request next disk side and reset filenum_counter 67 | .macro request_disk (arg) { 68 | lda #arg + $ef 69 | //simply do a bogus loadraw, this will call ld_pblock until eof is raised, nothing is loaded as block_ready never happens :-] 70 | jsr bitfire_loadraw_ 71 | } 72 | 73 | //wait for given frame counter value 74 | .macro link_wait_syncpoint (arg) { 75 | l: 76 | lda link_syncpoint 77 | cmp #arg 78 | bcc l 79 | } 80 | 81 | .macro setup_sync (arg) { 82 | lda #$00 83 | sta link_frame_count + 0 //avoid that the counter wraps worstcase, as we can't write atomic 84 | lda #>[$8000-arg] 85 | sta link_frame_count + 1 86 | lda #<[$8000-arg] 87 | sta link_frame_count + 0 //now setup counter 88 | } 89 | 90 | .macro sync () { 91 | l: 92 | lda link_frame_count + 1 //Counter expired when $8000 is reached 93 | bpl l 94 | } 95 | 96 | .macro bus_lock () { 97 | lda #$37 //set ATN 98 | sta $dd02 99 | } 100 | 101 | .macro bus_unlock () { 102 | lda $dd00 103 | and #$03 104 | sta $dd00 105 | lda #$3f 106 | sta $dd02 107 | } 108 | 109 | .macro set_depack_pointers (arg) { 110 | lda #arg 113 | sta bitfire_load_addr_hi 114 | } 115 | 116 | .macro link_music_update () { 117 | inc link_frame_count + 0 118 | bne l 119 | inc link_frame_count + 1 120 | l: 121 | jmp [link_music_addr] 122 | } 123 | 124 | .macro to_nmi () { 125 | lda #$ad 126 | sta link_player + 7 127 | lda #$0d 128 | sta link_player + 8 129 | lda #$dd 130 | sta link_player + 9 131 | } 132 | 133 | .macro to_irq () { 134 | lda #$ce 135 | sta link_player + 7 136 | lda #$19 137 | sta link_player + 8 138 | lda #$d0 139 | sta link_player + 9 140 | } 141 | 142 | .macro switch_to_nmi () { 143 | lda #$fe 144 | l: 145 | cmp $d012 146 | bne l 147 | sei 148 | :to_nmi() 149 | :start_music_nmi() 150 | jsr link_music_play 151 | } 152 | 153 | .macro switch_to_irq () { 154 | lda #$fe 155 | l: 156 | cmp $d012 157 | bne l 158 | :stop_music_nmi() 159 | :to_irq() 160 | ldx #link_player 162 | 163 | stx $fffe 164 | sta $ffff 165 | lda #$ff 166 | sta $d012 167 | jsr link_music_play 168 | } 169 | 170 | .macro start_music_nmi () { 171 | //lda #$20 172 | //sta link_music_play_jmp 173 | ldx #link_player 175 | 176 | stx $fffa 177 | sta $fffb 178 | lda #$00 179 | sta $dd0e 180 | lda $dd0d 181 | lda #$c7 182 | sta $dd04 183 | lda #$4c 184 | sta $dd05 185 | lda #$81 186 | sta $dd0d 187 | 188 | lda #$ff 189 | l: 190 | cmp $d012 191 | bne l 192 | 193 | lda #$11 194 | sta $dd0e 195 | } 196 | 197 | .macro stop_music_nmi () { 198 | lda #$7f 199 | sta $dd0d 200 | lda $dd0d 201 | } 202 | 203 | .macro restart_music_nmi () { 204 | lda $dd0d 205 | lda #$81 206 | sta $dd0d 207 | } 208 | 209 | .macro set_music_addr (arg) { 210 | lda #arg 213 | sta link_music_addr + 1 214 | } 215 | 216 | .macro wait_space () { 217 | lda #$7f 218 | sta $dc00 219 | lda #$10 220 | l: 221 | 222 | bit $dc01 223 | bne l 224 | } 225 | 226 | .macro wait_shift_lock () { 227 | lda #$fd 228 | sta $dc00 229 | l: 230 | lda $dc01 231 | bpl l 232 | } 233 | 234 | .macro crt_request_disk (arg) { 235 | :setup_sync(arg) 236 | l: 237 | lda #$7f //space pressed? 238 | sta $dc00 239 | lda $dc01 240 | and #$10 241 | beq e //yes, exit 242 | lda link_frame_count + 1 //check counter 243 | bpl g 244 | sta f + 1 245 | g: 246 | lda #$fd //shift lock pressed? 247 | sta $dc00 248 | lda $dc01 249 | f: 250 | and #$00 251 | bpl l //shift lock pressed or not expired 252 | e: 253 | } 254 | 255 | .macro skip_file () { 256 | lda #BITFIRE_SKIP_FILE 257 | jsr bitfire_loadraw_ 258 | } 259 | 260 | // !macro gaps_setup { 261 | // ldx #$09 262 | //l: 263 | // lda CONFIG_RESIDENT_ADDR + $000,x 264 | // pha 265 | // lda CONFIG_RESIDENT_ADDR + $100,x 266 | // pha 267 | // dex 268 | // bpl l 269 | // } 270 | // 271 | // !macro gaps_restore { 272 | // ldx #$00 273 | //l: 274 | // pla 275 | // sta CONFIG_RESIDENT_ADDR + $000,x 276 | // pla 277 | // sta CONFIG_RESIDENT_ADDR + $100,x 278 | // inx 279 | // cpx #$0a 280 | // bne l 281 | // } 282 | -------------------------------------------------------------------------------- /music.inc: -------------------------------------------------------------------------------- 1 | link_music_init_side1 = $0800 2 | link_music_play_side1 = link_music_init_side1 + 3 3 | link_music_fade_side1 = link_music_init_side1 + 9 4 | 5 | link_music_init_side2 = $0800 6 | link_music_play_side2 = link_music_init_side2 + 3 7 | link_music_fade_side2 = link_music_init_side2 + 6 8 | -------------------------------------------------------------------------------- /packer/dali/Makefile: -------------------------------------------------------------------------------- 1 | ACME ?= acme 2 | ACME_OPTS ?= -f cbm 3 | SALVADOR_PATH = salvador/src 4 | SALVADOR_LIB_PATH = $(SALVADOR_PATH)/libdivsufsort/lib 5 | DALI_INCLUDES = $(SALVADOR_PATH)/libdivsufsort/include 6 | DALI_CFLAGS = $(CFLAGS) -O3 -g -Wall -fomit-frame-pointer -I$(DALI_INCLUDES) 7 | ifdef win 8 | CC = x86_64-w64-mingw32-gcc 9 | STRIP = x86_64-w64-mingw32-strip 10 | else ifdef win32 11 | CC = i686-w64-mingw32-gcc 12 | STRIP = i686-w64-mingw32-strip 13 | else 14 | CC ?= gcc 15 | STRIP ?= strip 16 | endif 17 | #DALI_OBJS += $(SALVADOR_PATH)/expand.o 18 | #DALI_OBJS += $(SALVADOR_PATH)/matchfinder.o 19 | #DALI_OBJS += $(SALVADOR_PATH)/shrink.o 20 | #DALI_OBJS += $(SALVADOR_LIB_PATH)/divsufsort.o 21 | #DALI_OBJS += $(SALVADOR_LIB_PATH)/divsufsort_utils.o 22 | #DALI_OBJS += $(SALVADOR_LIB_PATH)/sssort.o 23 | #DALI_OBJS += $(SALVADOR_LIB_PATH)/trsort.o 24 | 25 | SALVADOR_SRC += $(SALVADOR_PATH)/expand.c 26 | SALVADOR_SRC += $(SALVADOR_PATH)/matchfinder.c 27 | SALVADOR_SRC += $(SALVADOR_PATH)/shrink.c 28 | SALVADOR_SRC += $(SALVADOR_LIB_PATH)/divsufsort.c 29 | SALVADOR_SRC += $(SALVADOR_LIB_PATH)/divsufsort_utils.c 30 | SALVADOR_SRC += $(SALVADOR_LIB_PATH)/sssort.c 31 | SALVADOR_SRC += $(SALVADOR_LIB_PATH)/trsort.c 32 | 33 | V ?= 0 34 | ifeq ($(V),1) 35 | VR:= 36 | else 37 | VR:=@ 38 | endif 39 | 40 | all: dali 41 | 42 | #%.o: %.c 43 | # $(VR)$(CC) $(DALI_CFLAGS) -c $< -o $@ 44 | # 45 | #dali.o: dali.c sfx_small.h sfx_fast.h 46 | # @echo "Building dali..." 47 | # $(VR)$(CC) $(DALI_CFLAGS) -c $< -o $@ 48 | # 49 | #dali: dali.o $(DALI_OBJS) 50 | 51 | dali: dali.c $(SALVADOR_SRC) sfx.h 52 | @echo "Building dali..." 53 | $(VR)$(CC) dali.c $(SALVADOR_SRC) $(DALI_CFLAGS) -o $@ 54 | ifdef win 55 | $(VR)$(STRIP) $@.exe 56 | else ifdef win32 57 | $(VR)$(STRIP) $@.exe 58 | else 59 | $(VR)$(STRIP) $@ 60 | endif 61 | 62 | testfile.lz: ../../benchmark/files/b dali 63 | ./dali -o $@ $< 64 | 65 | example.prg: example.asm dali dzx0_dali.asm testfile.lz 66 | $(VR)$(ACME) $(ACME_OPTS) -o $@ $< 67 | 68 | sfx.h: sfx.asm 69 | @echo "Creating sfx.h..." 70 | $(VR)$(ACME) $(ACME_OPTS) -DSFX_EFFECT=1 -DSFX_SMALL=1 -o $(basename $@) $< 71 | 72 | $(VR)echo 'static const char decruncher_small_effect[] = {' > $@ 73 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 74 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 75 | $(VR)echo '};' >> $@ 76 | 77 | $(VR)$(ACME) $(ACME_OPTS) -DSFX_EFFECT=1 -DSFX_FAST=1 -o $(basename $@) $< 78 | $(VR)echo 'static const char decruncher_effect[] = {' >> $@ 79 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 80 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 81 | $(VR)echo '};' >> $@ 82 | 83 | $(VR)$(ACME) $(ACME_OPTS) -DSFX_SMALL=1 -o $(basename $@) $< 84 | $(VR)echo 'static const char decruncher_small[] = {' >> $@ 85 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 86 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 87 | $(VR)echo '};' >> $@ 88 | 89 | $(VR)$(ACME) $(ACME_OPTS) -DSFX_FAST=1 -o $(basename $@) $< 90 | $(VR)echo 'static const char decruncher[] = {' >> $@ 91 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 92 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 93 | $(VR)echo '};' >> $@ 94 | @rm $(basename $@) 95 | 96 | clean: 97 | $(VR)-rm dali dali.exe sfx.h example.prg testfile.lz 98 | # $(VR)-rm $(SALVADOR_PATH)/*.o 99 | # $(VR)-rm $(SALVADOR_LIB_PATH)/*.o 100 | $(VR)-make -C salvador clean 101 | -------------------------------------------------------------------------------- /packer/dali/dzx0_dali.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions are met: 6 | ; * Redistributions of source code must retain the above copyright 7 | ; notice, this list of conditions and the following disclaimer. 8 | ; * Redistributions in binary form must reproduce the above copyright 9 | ; notice, this list of conditions and the following disclaimer in the 10 | ; documentation and/or other materials provided with the distribution. 11 | ; * The name of its author may not be used to endorse or promote products 12 | ; derived from this software without specific prior written permission. 13 | ; 14 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ; 25 | 26 | !cpu 6510 27 | 28 | LZ_BITS_LEFT = 1 29 | INPLACE = 1 30 | CONFIG_ZP_ADDR = $f0 31 | 32 | lz_bits = CONFIG_ZP_ADDR + 0 ;1 byte 33 | lz_dst = CONFIG_ZP_ADDR + 1 ;2 byte 34 | lz_src = CONFIG_ZP_ADDR + 3 ;2 byte 35 | lz_len_hi = CONFIG_ZP_ADDR + 5 ;1 byte 36 | 37 | !macro get_lz_bit { 38 | !if LZ_BITS_LEFT = 1 { 39 | asl lz_dst_hi + 1, so never zero. 81 | txa 82 | .lz_cp_page_ ;a is already 0 if entered here 83 | dec lz_dst + 1, except if we would depack to zp on a wrap around? 90 | beq .lz_m_page ;as Y = 0 and A = 0 now, we can skip the part that does Y = A xor $ff 91 | 92 | ;------------------ 93 | ;LITERAL 94 | ;------------------ 95 | - 96 | +get_lz_bit ;fetch payload bit 97 | rol ;can also moved to front and executed once on start 98 | .lz_literal 99 | +get_lz_bit ;fetch payload bit 100 | bcc - 101 | + 102 | bne + 103 | .lz_start_depack 104 | jsr .lz_refill_bits 105 | beq .lz_cp_page_ ;handle special case of length being $xx00 106 | + 107 | tax 108 | .lz_l_page 109 | .lz_cp_lit ;XXX TODO copy with Y += 1 but have lz_src + 0 eor #$ff in x and countdown x, so that lz_src + 1 can be incremented in time? 110 | lda (lz_src),y ;/!\ Need to copy this way, or we run into danger to copy from an area that is yet blocked by barrier, this totally sucks, loading in order reveals that 111 | sta (lz_dst),y 112 | 113 | inc A = 1 with rol, but not if we copy literal this way 131 | +get_lz_bit 132 | bcs .lz_match ;either match with new offset or old offset 133 | 134 | ;------------------ 135 | ;REPEAT LAST OFFSET 136 | ;------------------ 137 | .lz_repeat 138 | +get_lz_bit 139 | bcs + 140 | - 141 | +get_lz_bit ;fetch payload bit 142 | rol ;can also moved to front and executed once on start 143 | +get_lz_bit ;cheaper with 2 branches, as initial branch to .lz_literal therefore is removed 144 | bcc - 145 | + 146 | bne + 147 | jsr .lz_refill_bits ;fetch more bits 148 | beq .lz_cp_page ;handle special case of length being $xx00 149 | + 150 | sbc #$01 ;subtract 1, will be added again on adc as C = 1 151 | .lz_match_big ;we enter with length - 1 here from normal match 152 | eor #$ff 153 | tay 154 | .lz_m_page 155 | eor #$ff ;restore A 156 | .lz_match_len2 157 | adc can be changed to .lz_poll, depending on decomp/loadcomp 180 | } 181 | ;------------------ 182 | ;ENTRY POINT DEPACKER 183 | ;------------------ 184 | .lz_start_over 185 | ;lda #$01 ;we fall through this check on entry and start with literal 186 | +get_lz_bit 187 | bcc .lz_literal 188 | 189 | ;------------------ 190 | ;MATCH 191 | ;------------------ 192 | .lz_match 193 | +get_lz_bit 194 | bcs + 195 | - 196 | +get_lz_bit ;fetch payload bit 197 | rol ;add bit to number 198 | +get_lz_bit ;fetch control bit 199 | bcc - ;not yet done, fetch more bits 200 | + 201 | bne + ;last bit or bitbuffer empty? fetched 1 to 4 bits now 202 | jsr .lz_refill_bits ;refill bitbuffer 203 | beq .lz_eof ;so offset was $100 as lowbyte is $00, only here 4-8 bits are fetched 204 | + 205 | sbc #$01 ;subtract 1, elias numbers range from 1..256, we need 0..255 206 | lsr ;set bit 15 to 0 while shifting hibyte 207 | sta .lz_offset_hi + 1 ;hibyte of offset 208 | 209 | lda (lz_src),y ;fetch another byte directly, same as refill_bits... 210 | ror ;and shift -> first bit for lenth is in carry, and we have %0xxxxxxx xxxxxxxx as offset 211 | sta .lz_offset_lo + 1 ;lobyte of offset 212 | 213 | inc move away to prefer Z = 0 case 81 | 82 | ;------------------ 83 | ;NEW OR OLD OFFSET 84 | ;------------------ 85 | 86 | lda #$01 87 | asl <.lz_bits 88 | bcs .lz_new_offset ;either match with new offset or old offset 89 | !if ZX0_INLINE_GET_LEN == 1 { 90 | bcc .lz_match_repeat 91 | 92 | ;------------------ 93 | ;DO MATCH 94 | ;------------------ 95 | - ;lz_get_len as inline 96 | asl <.lz_bits ;fetch payload bit 97 | rol 98 | .lz_match_repeat 99 | asl <.lz_bits 100 | bcc - 101 | + 102 | bne + 103 | jsr .lz_refill_bits 104 | + 105 | } else { 106 | .lz_match_repeat 107 | jsr .lz_get_len 108 | } 109 | sbc #$01 ;saves the iny later on 110 | bcs + 111 | dcp .lz_len_hi ;dec highbyte of length by one, a = $ff, so cmp will always set carry for free on top 112 | + 113 | .lz_match_ 114 | eor #$ff 115 | ;beq .lz_calc_msrc ;just fall through on zero? $ff + sec -> addition is neutralized and carry is set, so no harm 116 | tay 117 | eor #$ff ;restore A 118 | .lz_match__ ;entry from new_offset handling 119 | adc <.lz_dst + 0 120 | sta <.lz_dst + 0 121 | bcs .lz_clc ;/!\ branch happens very seldom 122 | dec <.lz_dst + 1 123 | .lz_clc 124 | clc 125 | .lz_offset_lo adc #$00 ;carry is cleared, subtract (offset + 1) 126 | sta .lz_msrcr + 0 127 | lda <.lz_dst + 1 128 | .lz_offset_hi adc #$ff 129 | sta .lz_msrcr + 1 130 | .lz_cp_match 131 | .lz_msrcr = * + 1 132 | lda $beef,y 133 | sta (.lz_dst),y 134 | iny 135 | bne .lz_cp_match 136 | inc <.lz_dst + 1 137 | 138 | lda <.lz_len_hi ;check for more loop runs 139 | !if ZX0_INPLACE == 1 { 140 | bne .lz_m_page ;do more page runs 141 | 142 | cpx <.lz_dst + 0 ;check for end condition when depacking inplace 143 | bne .lz_start_over 144 | lda <.lz_dst + 1 145 | sbc <.lz_src1 146 | bne .lz_start_over 147 | rts 148 | } else { 149 | beq .lz_start_over ;do more page runs 150 | } 151 | ;------------------ 152 | ;SELDOM STUFF 153 | ;------------------ 154 | .lz_m_page 155 | dec <.lz_len_hi 156 | inc .lz_msrcr + 1 157 | jmp .lz_cp_match 158 | .lz_l_page 159 | dec <.lz_len_hi 160 | sec ;only needs to be set for consecutive rounds of literals, happens very seldom 161 | ldy #$00 162 | beq .lz_cp_literal 163 | 164 | ;------------------ 165 | ;FETCH A NEW OFFSET 166 | ;------------------ 167 | 168 | !if ZX0_INLINE_GET_LEN == 1 { 169 | - ;lz_get_len as inline 170 | asl <.lz_bits ;fetch payload bit 171 | rol 172 | .lz_new_offset 173 | asl <.lz_bits 174 | bcc - 175 | + 176 | bne + 177 | jsr .lz_refill_bits 178 | + 179 | } else { 180 | .lz_new_offset 181 | jsr .lz_get_len 182 | } 183 | sbc #$01 184 | bcc .lz_eof ;underflow. must have been 0 185 | eor #$ff 186 | 187 | ror 188 | sta .lz_offset_hi + 1 ;hibyte of offset 189 | 190 | .lz_src2 = * + 2 191 | lda $1000,x ;looks expensive, but is cheaper than loop 192 | inx 193 | bne + 194 | jsr .lz_inc_src_hi 195 | + 196 | ror 197 | sta .lz_offset_lo + 1 198 | 199 | lda #$01 200 | ldy #$fe 201 | bcs .lz_match__ ;length = 2 ^ $ff, do it the very short way :-) 202 | ldy #$00 203 | !if ZX0_INLINE_GET_LEN == 1 { 204 | - 205 | asl <.lz_bits ;fetch first payload bit 206 | rol 207 | asl <.lz_bits 208 | bcc - 209 | bne .lz_match_ 210 | jsr .lz_refill_bits ;fetch remaining bits 211 | } else { 212 | jsr .lz_get_len_ 213 | } 214 | bcs .lz_match_ 215 | 216 | .lz_inc_src_hi 217 | inc .lz_src1 218 | inc .lz_src2 219 | inc .lz_src3 220 | rts 221 | 222 | !if ZX0_INLINE_GET_LEN == 0 { 223 | .lz_get_len_ 224 | - ;lz_get_len as inline 225 | asl <.lz_bits ;fetch payload bit 226 | rol 227 | .lz_get_len 228 | asl <.lz_bits 229 | bcc - 230 | bne .lz_get_end 231 | } 232 | .lz_refill_bits ;refill bits, this happens after 4 payload-bits bestcase 233 | .lz_src3 = * + 2 234 | ldy $1000,x 235 | inx 236 | bne + 237 | jsr .lz_inc_src_hi 238 | + 239 | sty <.lz_bits 240 | ldy #$00 241 | rol <.lz_bits 242 | bcs .lz_get_end 243 | - ;continue with 16 bit shifting 244 | asl <.lz_bits ;fetch payload bit 245 | rol ;can also moved to front and executed once on start 246 | .lz_get_len_16 247 | rol <.lz_len_hi 248 | asl <.lz_bits 249 | bcc - 250 | beq .lz_refill_bits 251 | .lz_get_end 252 | .lz_eof 253 | rts 254 | .depacker_end 255 | -------------------------------------------------------------------------------- /packer/dali/dzx0_orig_zx0_v2.asm: -------------------------------------------------------------------------------- 1 | ;/!\ Attention, this depacker only works with the original zx0 version contained within this folder as well, it does not work with the modified version coming with bitfire, as some things on the encoding got changed due to speed optimizations 2 | 3 | !cpu 6510 4 | 5 | ;ZX0_INPLACE = 0 6 | 7 | .ZP_ADDR = $f8 8 | .lz_dst = .ZP_ADDR + 0 9 | .lz_bits = .ZP_ADDR + 2 10 | .lz_len_hi = .ZP_ADDR + 4 11 | 12 | .depacker_start 13 | ;------------------ 14 | ;INIT 15 | ;------------------ 16 | 17 | ;lowbyte of data start must be in X, highbyte in A 18 | sta .lz_src1 19 | sta .lz_src2 20 | sta .lz_src3 21 | 22 | lda #$00 23 | sta <.lz_dst + 0 24 | lda #$a0 25 | sta <.lz_dst + 1 26 | 27 | ldy #$ff 28 | sty .lz_offset_lo + 1 29 | sty .lz_offset_hi + 1 30 | 31 | iny 32 | sty <.lz_len_hi 33 | lda #$40 34 | sta <.lz_bits ;will make us fall through on next test and force us to load a new byte into bit-buffer upon next .lz_get_len 35 | 36 | ;------------------ 37 | ;LITERAL 38 | ;------------------ 39 | .lz_start_over 40 | lda #$01 41 | asl <.lz_bits 42 | bcs .lz_new_offset 43 | .lz_literal 44 | jsr .lz_get_len 45 | sta .lz_y + 1 46 | and #$ff ;annoying, but flags are not set corresponding to A 47 | beq .lz_l_page_ 48 | .lz_cp_literal 49 | .lz_src1 = * + 2 50 | lda $1000,x 51 | inx 52 | bne + 53 | jsr .lz_inc_src_hi 54 | + 55 | sta (.lz_dst),y 56 | iny 57 | .lz_y cpy #$00 58 | bne .lz_cp_literal 59 | 60 | dey ;this way we force increment of lz_dst + 1 if y = 0 61 | tya ;carry is still set on first round 62 | adc <.lz_dst + 0 ;correct dst after copy loop 63 | sta <.lz_dst + 0 64 | bcc + 65 | inc <.lz_dst + 1 66 | + 67 | ldy <.lz_len_hi 68 | bne .lz_l_page ;happens very seldom -> move away to prefer Z = 0 case 69 | 70 | ;------------------ 71 | ;NEW OR OLD OFFSET 72 | ;------------------ 73 | 74 | lda #$01 75 | asl <.lz_bits 76 | bcs .lz_new_offset ;either match with new offset or old offset 77 | .lz_match_repeat 78 | jsr .lz_get_len 79 | ;!if ZX0_INPLACE == 0 { 80 | ;} 81 | sbc #$01 ;saves the iny later on 82 | bcc .lz_dcp ;dec highbyte of length by one, a = $ff, so cmp will always set carry for free on top 83 | .lz_match_ 84 | eor #$ff 85 | ;beq .lz_calc_msrc ;just fall through on zero? $ff + sec -> addition is neutralized and carry is set, so no harm 86 | tay 87 | eor #$ff ;restore A 88 | .lz_match__ ;entry from new_offset handling 89 | adc <.lz_dst + 0 90 | sta <.lz_dst + 0 91 | bcs .lz_clc ;/!\ branch happens very seldom 92 | dec <.lz_dst + 1 93 | .lz_clc_back 94 | clc 95 | .lz_offset_lo adc #$ff ;carry is cleared, subtract (offset + 1) 96 | sta .lz_msrcr + 0 97 | lda <.lz_dst + 1 98 | .lz_offset_hi adc #$ff 99 | sta .lz_msrcr + 1 100 | .lz_cp_match 101 | .lz_msrcr = * + 1 102 | lda $beef,y 103 | sta (.lz_dst),y 104 | iny 105 | bne .lz_cp_match 106 | inc <.lz_dst + 1 107 | 108 | lda <.lz_len_hi ;check for more loop runs 109 | ;!if ZX0_INPLACE == 1 { 110 | ; bne .lz_m_page ;do more page runs 111 | ; 112 | ; cpx <.lz_dst + 0 ;check for end condition when depacking inplace 113 | ; bne .lz_start_over 114 | ; lda <.lz_dst + 1 115 | ; sbc <.lz_src1 116 | ; bne .lz_start_over 117 | ; rts 118 | ;.lz_m_page 119 | ; lda #$ff 120 | ;} else { 121 | beq .lz_start_over ;do more page runs 122 | lda #$ff 123 | ;} 124 | ;------------------ 125 | ;SELDOM STUFF 126 | ;------------------ 127 | .lz_dcp 128 | dcp .lz_len_hi 129 | bcs .lz_match_ 130 | .lz_clc 131 | clc 132 | bcc .lz_clc_back 133 | .lz_l_page 134 | sec ;only needs to be set for consecutive rounds of literals, happens very seldom 135 | ldy #$00 136 | .lz_l_page_ 137 | dec <.lz_len_hi 138 | bcs .lz_cp_literal 139 | 140 | ;------------------ 141 | ;FETCH A NEW OFFSET 142 | ;------------------ 143 | 144 | .lz_new_offset 145 | lda #$fe 146 | jsr .lz_get_len 147 | sty .lz_len_hi 148 | adc #$00 149 | beq .lz_eof ;underflow. must have been 0 150 | 151 | sec 152 | ror 153 | sta .lz_offset_hi + 1 ;hibyte of offset 154 | 155 | .lz_src2 = * + 2 156 | lda $1000,x ;looks expensive, but is cheaper than loop 157 | inx 158 | bne + 159 | jsr .lz_inc_src_hi 160 | + 161 | ror 162 | sta .lz_offset_lo + 1 163 | 164 | lda #$01 165 | ldy #$fe 166 | bcs .lz_match__ ;length = 2 ^ $ff, do it the very short way :-) 167 | ldy #$00 168 | jsr .lz_get_len_ 169 | bcs .lz_match_ 170 | 171 | .lz_inc_src_hi 172 | inc .lz_src1 173 | inc .lz_src2 174 | inc .lz_src3 175 | rts 176 | 177 | .lz_get_len_ 178 | - ;lz_get_len as inline 179 | asl <.lz_bits ;fetch payload bit 180 | rol 181 | .lz_get_len 182 | asl <.lz_bits 183 | bcc - 184 | bne .lz_get_end 185 | .lz_refill_bits ;refill bits, this happens after 4 payload-bits bestcase 186 | .lz_src3 = * + 2 187 | ldy $1000,x 188 | inx 189 | bne + 190 | jsr .lz_inc_src_hi 191 | + 192 | sty <.lz_bits 193 | ldy #$00 194 | rol <.lz_bits 195 | bcs .lz_get_end 196 | - ;continue with 16 bit shifting 197 | asl <.lz_bits ;fetch payload bit 198 | rol ;can also moved to front and executed once on start 199 | .lz_get_len_16 200 | rol <.lz_len_hi 201 | asl <.lz_bits 202 | bcc - 203 | beq .lz_refill_bits 204 | .lz_get_end 205 | .lz_eof 206 | rts 207 | .depacker_end 208 | -------------------------------------------------------------------------------- /packer/dali/example.asm: -------------------------------------------------------------------------------- 1 | !cpu 6510 2 | * = $0801 3 | !byte $0b,$08 4 | !word 1602 5 | !byte $9e 6 | !text "2061" 7 | !byte $00,$00,$00 8 | 9 | sei 10 | lda #$35 11 | sta $01 12 | lda $d011 13 | bpl *-3 14 | lda #$0b 15 | sta $d011 16 | 17 | ldx #$00 18 | lda #$20 19 | - 20 | sta $0400,x 21 | sta $0500,x 22 | sta $0600,x 23 | sta $0700,x 24 | dex 25 | bne - 26 | 27 | jsr .timer_start 28 | 29 | lda data_start 30 | sta (data_start + 2) 36 | 37 | jsr depack 38 | 39 | jsr .timer_stop 40 | 41 | lda #$1b 42 | sta $d011 43 | jmp * 44 | 45 | .timer_start 46 | lda #$00 47 | sta $dc0e 48 | lda #$40 49 | sta $dc0f 50 | lda #$ff 51 | sta $dc04 52 | sta $dc05 53 | sta $dc06 54 | sta $dc07 55 | lda #$41 56 | sta $dc0f 57 | lda #$01 58 | sta $dc0e 59 | rts 60 | .timer_stop 61 | lda #$00 62 | sta $dc0e 63 | lda #$40 64 | sta $dc0f 65 | 66 | ldy #$00 67 | - 68 | lda .cycles,y 69 | sta $0400,y 70 | iny 71 | cpy #$08 72 | bne - 73 | lda $dc04 74 | pha 75 | lda $dc05 76 | pha 77 | lda $dc06 78 | pha 79 | lda $dc07 80 | jsr .print_hex 81 | pla 82 | jsr .print_hex 83 | pla 84 | jsr .print_hex 85 | pla 86 | .print_hex 87 | eor #$ff 88 | pha 89 | lsr 90 | lsr 91 | lsr 92 | lsr 93 | tax 94 | lda .hextab,x 95 | sta $0400,y 96 | iny 97 | pla 98 | ldx #$0f 99 | sbx #$00 100 | lda .hextab,x 101 | sta $0400,y 102 | iny 103 | rts 104 | .cycles 105 | !scr "cycles: " 106 | .hextab 107 | !scr "0123456789abcdef" 108 | 109 | !align 255,0 110 | depack_ 111 | !src "dzx0_dali.asm" 112 | !warn "depacker size: ", * - depack_ 113 | 114 | ; * = $6b00 115 | * = $6a62 116 | data_start 117 | !bin "testfile.lz",,2 118 | !warn * 119 | -------------------------------------------------------------------------------- /packer/dali/sfx.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions are met: 6 | ; * Redistributions of source code must retain the above copyright 7 | ; notice, this list of conditions and the following disclaimer. 8 | ; * Redistributions in binary form must reproduce the above copyright 9 | ; notice, this list of conditions and the following disclaimer in the 10 | ; documentation and/or other materials provided with the distribution. 11 | ; * The name of its author may not be used to endorse or promote products 12 | ; derived from this software without specific prior written permission. 13 | ; 14 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ; 25 | 26 | !cpu 6510 27 | 28 | BITS_LEFT = 1 29 | 30 | .depacker_dst = $01 31 | 32 | !macro get_lz_bit { 33 | !if BITS_LEFT = 1 { 34 | asl anc $08 would not hurt, but $9e hurts 52 | !word 1602 53 | !byte $9e 54 | !text "2061" 55 | !byte $00,$00,$00 56 | 57 | ;/!\ ATTENTION, the depacker just fits into ZP this way, if it gets larger, the copy routine will overwrite $00, as it is a 8-bit address sta 58 | sei 59 | 60 | !ifdef SFX_FAST { 61 | ;full zp code will be copied, but later less bytes will be copied back 62 | ldx #<($100 + (.depacker_end - .restore_end)) 63 | txs 64 | 65 | } 66 | ldy #.depacker_end - .depacker_start 67 | - 68 | !ifdef SFX_FAST { 69 | pha ;saved zp to stack down to $02 70 | lax <.depacker_dst - 1,y ;saves a byte, 2 byte compared to lda $0000,y 71 | } 72 | sfx_src = * + 1 73 | ldx .depacker_code - 1,y 74 | stx <.depacker_dst - 1,y 75 | dey 76 | bne - 77 | jmp .depack 78 | 79 | ;------------------ 80 | ;depacker starts here 81 | ;------------------ 82 | .dali_code_end 83 | .depacker_code 84 | !pseudopc .depacker_dst { 85 | .depacker_start 86 | !byte $34 87 | lz_bits 88 | !if BITS_LEFT = 1 { 89 | !byte $40 90 | } else { 91 | !byte $02 92 | } 93 | 94 | .depack 95 | !ifdef SFX_FAST { 96 | lz_01 = * + 1 97 | lda #$37 ;replace value for $01 in saved ZP on stack 98 | pha 99 | } 100 | - ;copy data to end of ram ($ffff) 101 | dey 102 | lz_data_end = * + 1 103 | .src lda $beef,y 104 | .dst sta $ff00,y 105 | tya ;annoying, but need to copy from $ff ... $00 106 | bne - 107 | 108 | dec <.src + 2 109 | lz_data_size_hi = * + 1 110 | lda #$00 ;check for last page to copy 111 | dcp <.dst + 2 112 | bne - 113 | 114 | ;ldy #$00 ;is already 0 115 | 116 | ;------------------ 117 | ;LITERAL 118 | ;------------------ 119 | .lz_start_over 120 | lda #$01 ;we fall through this check on entry and start with literal 121 | +get_lz_bit 122 | !ifdef SFX_FAST { 123 | bcc .literal 124 | bcs .lz_new_offset ;after each match check for another match or literal? 125 | - ;lz_length as inline 126 | +get_lz_bit ;fetch payload bit 127 | rol ;can also moved to front and executed once on start 128 | .literal 129 | +get_lz_bit 130 | bcc - 131 | 132 | bne + 133 | jsr lz_refill_bits 134 | + 135 | tax 136 | .lz_l_page_ 137 | } else { 138 | bcs .lz_new_offset ;after each match check for another match or literal? 139 | .literal 140 | jsr get_length 141 | tax 142 | beq .lz_l_page 143 | .lz_l_page_ 144 | } 145 | cp_literal 146 | lz_src = * + 1 147 | lda $beef,y ;looks expensive, but is cheaper than loop 148 | sta (lz_dst),y 149 | inc same as lda #$01 167 | +get_lz_bit 168 | bcs .lz_new_offset ;either match with new offset or old offset 169 | 170 | ;------------------ 171 | ;DO MATCH 172 | ;------------------ 173 | .lz_match 174 | !ifdef SFX_EFFECT { 175 | lz_effect 176 | inc $01 177 | dec $d020 178 | dec $01 179 | } 180 | jsr get_length 181 | !ifdef SFX_FAST { 182 | sbc #$01 ;saves the sec and iny later on, if it results in a = $ff, no problem, we branch with the beq later on 183 | sec 184 | } else { 185 | .lz_m_page_ 186 | sbc #$01 ;saves the sec and iny later on, if it results in a = $ff, no problem, we branch with the beq later on 187 | bcs .lz_match_ 188 | dcp data_start 37 | 38 | jsr depack 39 | 40 | jsr .timer_stop 41 | 42 | lda #$1b 43 | sta $d011 44 | jmp * 45 | 46 | .timer_start 47 | lda #$00 48 | sta $dc0e 49 | lda #$40 50 | sta $dc0f 51 | lda #$ff 52 | sta $dc04 53 | sta $dc05 54 | sta $dc06 55 | sta $dc07 56 | lda #$41 57 | sta $dc0f 58 | lda #$01 59 | sta $dc0e 60 | rts 61 | .timer_stop 62 | lda #$00 63 | sta $dc0e 64 | lda #$40 65 | sta $dc0f 66 | 67 | ldy #$00 68 | - 69 | lda .cycles,y 70 | sta $0400,y 71 | iny 72 | cpy #$08 73 | bne - 74 | lda $dc04 75 | pha 76 | lda $dc05 77 | pha 78 | lda $dc06 79 | pha 80 | lda $dc07 81 | jsr .print_hex 82 | pla 83 | jsr .print_hex 84 | pla 85 | jsr .print_hex 86 | pla 87 | .print_hex 88 | eor #$ff 89 | pha 90 | lsr 91 | lsr 92 | lsr 93 | lsr 94 | tax 95 | lda .hextab,x 96 | sta $0400,y 97 | iny 98 | pla 99 | ldx #$0f 100 | sbx #$00 101 | lda .hextab,x 102 | sta $0400,y 103 | iny 104 | rts 105 | .cycles 106 | !scr "cycles: " 107 | .hextab 108 | !scr "0123456789abcdef" 109 | 110 | !align 255,0 111 | depack 112 | ;!src "zx0_6502.asm" 113 | !src "dzx0_v2.asm" 114 | !warn "depacker size: ", * - depack 115 | 116 | data_start 117 | !bin "testfile.zx0" 118 | -------------------------------------------------------------------------------- /packer/zx0/6502/dzx0_v1.asm: -------------------------------------------------------------------------------- 1 | ;/!\ Attention, this depacker only works with the original zx0 version contained within this folder as well, it does not work with the modified version coming with bitfire, as some things on the encoding got changed due to speed optimizations 2 | 3 | !cpu 6510 4 | 5 | ZX0_INPLACE = 0 6 | ZX0_INLINE_GET_LEN = 0 7 | 8 | .ZP_ADDR = $f8 9 | .lz_dst = .ZP_ADDR + 0 10 | .lz_bits = .ZP_ADDR + 2 11 | .lz_len_hi = .ZP_ADDR + 4 12 | 13 | .depacker_start 14 | ;------------------ 15 | ;INIT 16 | ;------------------ 17 | 18 | ;lowbyte of data start must be in X, highbyte in A 19 | sta .lz_src1 20 | sta .lz_src2 21 | sta .lz_src3 22 | 23 | ldy #$ff 24 | sty .lz_offset_lo + 1 25 | sty .lz_offset_hi + 1 26 | 27 | iny 28 | sty <.lz_len_hi 29 | lda #$40 30 | sta <.lz_bits ;will make us fall through on next test and force us to load a new byte into bit-buffer upon next .lz_get_len 31 | 32 | ;------------------ 33 | ;LITERAL 34 | ;------------------ 35 | .lz_start_over 36 | lda #$01 37 | asl <.lz_bits 38 | !if ZX0_INLINE_GET_LEN == 1 { 39 | bcc .lz_literal 40 | jmp .lz_new_offset ;after each match check for another match or literal 41 | - ;lz_get_len as inline 42 | asl <.lz_bits ;fetch payload bit 43 | rol 44 | .lz_literal 45 | asl <.lz_bits 46 | bcc - 47 | + 48 | bne + 49 | jsr .lz_refill_bits 50 | + 51 | } else { 52 | bcs .lz_new_offset 53 | .lz_literal 54 | jsr .lz_get_len 55 | } 56 | sta .lz_y + 1 57 | and #$ff ;annoying, but flags are not set corresponding to A 58 | beq .lz_l_page 59 | ; dec <.lz_len_hi ;happens very seldom, so let's do that with lz_l_page that also decrements lz_len_hi 60 | .lz_cp_literal 61 | .lz_src1 = * + 2 62 | lda $1000,x 63 | inx 64 | bne + 65 | jsr .lz_inc_src_hi 66 | + 67 | sta (.lz_dst),y 68 | iny 69 | .lz_y cpy #$00 70 | bne .lz_cp_literal 71 | 72 | dey ;this way we force increment of lz_dst + 1 if y = 0 73 | tya ;carry is still set on first round 74 | adc <.lz_dst + 0 ;correct dst after copy loop 75 | sta <.lz_dst + 0 76 | bcc + 77 | inc <.lz_dst + 1 78 | + 79 | ldy <.lz_len_hi 80 | bne .lz_l_page ;happens very seldom -> move away to prefer Z = 0 case 81 | 82 | ;------------------ 83 | ;NEW OR OLD OFFSET 84 | ;------------------ 85 | 86 | lda #$01 87 | asl <.lz_bits 88 | bcs .lz_new_offset ;either match with new offset or old offset 89 | !if ZX0_INLINE_GET_LEN == 1 { 90 | bcc .lz_match_repeat 91 | 92 | ;------------------ 93 | ;DO MATCH 94 | ;------------------ 95 | - ;lz_get_len as inline 96 | asl <.lz_bits ;fetch payload bit 97 | rol 98 | .lz_match_repeat 99 | asl <.lz_bits 100 | bcc - 101 | + 102 | bne + 103 | jsr .lz_refill_bits 104 | + 105 | } else { 106 | .lz_match_repeat 107 | jsr .lz_get_len 108 | } 109 | sbc #$01 ;saves the iny later on 110 | bcs + 111 | dcp .lz_len_hi ;dec highbyte of length by one, a = $ff, so cmp will always set carry for free on top 112 | + 113 | .lz_match_ 114 | eor #$ff 115 | ;beq .lz_calc_msrc ;just fall through on zero? $ff + sec -> addition is neutralized and carry is set, so no harm 116 | tay 117 | eor #$ff ;restore A 118 | .lz_match__ ;entry from new_offset handling 119 | adc <.lz_dst + 0 120 | sta <.lz_dst + 0 121 | bcs .lz_clc ;/!\ branch happens very seldom 122 | dec <.lz_dst + 1 123 | .lz_clc 124 | clc 125 | .lz_offset_lo adc #$00 ;carry is cleared, subtract (offset + 1) 126 | sta .lz_msrcr + 0 127 | lda <.lz_dst + 1 128 | .lz_offset_hi adc #$ff 129 | sta .lz_msrcr + 1 130 | .lz_cp_match 131 | .lz_msrcr = * + 1 132 | lda $beef,y 133 | sta (.lz_dst),y 134 | iny 135 | bne .lz_cp_match 136 | inc <.lz_dst + 1 137 | 138 | lda <.lz_len_hi ;check for more loop runs 139 | !if ZX0_INPLACE == 1 { 140 | bne .lz_m_page ;do more page runs 141 | 142 | cpx <.lz_dst + 0 ;check for end condition when depacking inplace 143 | bne .lz_start_over 144 | lda <.lz_dst + 1 145 | sbc <.lz_src1 146 | bne .lz_start_over 147 | rts 148 | } else { 149 | beq .lz_start_over ;do more page runs 150 | } 151 | ;------------------ 152 | ;SELDOM STUFF 153 | ;------------------ 154 | .lz_m_page 155 | dec <.lz_len_hi 156 | inc .lz_msrcr + 1 157 | jmp .lz_cp_match 158 | .lz_l_page 159 | dec <.lz_len_hi 160 | sec ;only needs to be set for consecutive rounds of literals, happens very seldom 161 | ldy #$00 162 | beq .lz_cp_literal 163 | 164 | ;------------------ 165 | ;FETCH A NEW OFFSET 166 | ;------------------ 167 | 168 | !if ZX0_INLINE_GET_LEN == 1 { 169 | - ;lz_get_len as inline 170 | asl <.lz_bits ;fetch payload bit 171 | rol 172 | .lz_new_offset 173 | asl <.lz_bits 174 | bcc - 175 | + 176 | bne + 177 | jsr .lz_refill_bits 178 | + 179 | } else { 180 | .lz_new_offset 181 | jsr .lz_get_len 182 | } 183 | sbc #$01 184 | bcc .lz_eof ;underflow. must have been 0 185 | eor #$ff 186 | 187 | ror 188 | sta .lz_offset_hi + 1 ;hibyte of offset 189 | 190 | .lz_src2 = * + 2 191 | lda $1000,x ;looks expensive, but is cheaper than loop 192 | inx 193 | bne + 194 | jsr .lz_inc_src_hi 195 | + 196 | ror 197 | sta .lz_offset_lo + 1 198 | 199 | lda #$01 200 | ldy #$fe 201 | bcs .lz_match__ ;length = 2 ^ $ff, do it the very short way :-) 202 | ldy #$00 203 | !if ZX0_INLINE_GET_LEN == 1 { 204 | - 205 | asl <.lz_bits ;fetch first payload bit 206 | rol 207 | asl <.lz_bits 208 | bcc - 209 | bne .lz_match_ 210 | jsr .lz_refill_bits ;fetch remaining bits 211 | } else { 212 | jsr .lz_get_len_ 213 | } 214 | bcs .lz_match_ 215 | 216 | .lz_inc_src_hi 217 | inc .lz_src1 218 | inc .lz_src2 219 | inc .lz_src3 220 | rts 221 | 222 | !if ZX0_INLINE_GET_LEN == 0 { 223 | .lz_get_len_ 224 | - ;lz_get_len as inline 225 | asl <.lz_bits ;fetch payload bit 226 | rol 227 | .lz_get_len 228 | asl <.lz_bits 229 | bcc - 230 | bne .lz_get_end 231 | } 232 | .lz_refill_bits ;refill bits, this happens after 4 payload-bits bestcase 233 | .lz_src3 = * + 2 234 | ldy $1000,x 235 | inx 236 | bne + 237 | jsr .lz_inc_src_hi 238 | + 239 | sty <.lz_bits 240 | ldy #$00 241 | rol <.lz_bits 242 | bcs .lz_get_end 243 | - ;continue with 16 bit shifting 244 | asl <.lz_bits ;fetch payload bit 245 | rol ;can also moved to front and executed once on start 246 | .lz_get_len_16 247 | rol <.lz_len_hi 248 | asl <.lz_bits 249 | bcc - 250 | beq .lz_refill_bits 251 | .lz_get_end 252 | .lz_eof 253 | rts 254 | .depacker_end 255 | -------------------------------------------------------------------------------- /packer/zx0/6502/dzx0_v2.asm: -------------------------------------------------------------------------------- 1 | ;/!\ Attention, this depacker only works with the original zx0 version contained within this folder as well, it does not work with the modified version coming with bitfire, as some things on the encoding got changed due to speed optimizations 2 | 3 | !cpu 6510 4 | 5 | ;ZX0_INPLACE = 0 6 | 7 | .ZP_ADDR = $f8 8 | .lz_dst = .ZP_ADDR + 0 9 | .lz_bits = .ZP_ADDR + 2 10 | .lz_len_hi = .ZP_ADDR + 4 11 | 12 | .depacker_start 13 | ;------------------ 14 | ;INIT 15 | ;------------------ 16 | 17 | ;lowbyte of data start must be in X, highbyte in A 18 | sta .lz_src1 19 | sta .lz_src2 20 | sta .lz_src3 21 | 22 | lda #$00 23 | sta <.lz_dst + 0 24 | lda #$a0 25 | sta <.lz_dst + 1 26 | 27 | ldy #$ff 28 | sty .lz_offset_lo + 1 29 | sty .lz_offset_hi + 1 30 | 31 | iny 32 | sty <.lz_len_hi 33 | lda #$40 34 | sta <.lz_bits ;will make us fall through on next test and force us to load a new byte into bit-buffer upon next .lz_get_len 35 | 36 | ;------------------ 37 | ;LITERAL 38 | ;------------------ 39 | .lz_start_over 40 | asl <.lz_bits 41 | bcs .lz_new_offset 42 | .lz_literal 43 | lda #$01 44 | jsr .lz_get_len 45 | sta .lz_y + 1 46 | cmp #$00 ;annoying, but flags are not set corresponding to A 47 | beq .lz_l_page_ 48 | .lz_cp_literal 49 | .lz_src1 = * + 2 50 | lda $1000,x 51 | inx 52 | bne + 53 | jsr .lz_inc_src_hi 54 | + 55 | sta (.lz_dst),y 56 | iny 57 | .lz_y cpy #$00 58 | bne .lz_cp_literal 59 | 60 | dey ;this way we force increment of lz_dst + 1 if y = 0 61 | tya ;carry is still set on first round 62 | adc <.lz_dst + 0 ;correct dst after copy loop 63 | sta <.lz_dst + 0 64 | bcc + 65 | inc <.lz_dst + 1 66 | + 67 | ldy <.lz_len_hi 68 | bne .lz_l_page ;happens very seldom -> move away to prefer Z = 0 case 69 | 70 | ;------------------ 71 | ;NEW OR OLD OFFSET 72 | ;------------------ 73 | 74 | asl <.lz_bits 75 | bcs .lz_new_offset ;either match with new offset or old offset 76 | .lz_match_repeat 77 | lda #$01 78 | jsr .lz_get_len 79 | ;!if ZX0_INPLACE == 0 { 80 | ;} 81 | sbc #$01 ;saves the iny later on 82 | bcc .lz_dcp ;dec highbyte of length by one, a = $ff, so cmp will always set carry for free on top 83 | .lz_match_ 84 | eor #$ff 85 | ;beq .lz_calc_msrc ;just fall through on zero? $ff + sec -> addition is neutralized and carry is set, so no harm 86 | tay 87 | eor #$ff ;restore A 88 | .lz_match__ ;entry from new_offset handling 89 | adc <.lz_dst + 0 90 | sta <.lz_dst + 0 91 | bcs .lz_clc ;/!\ branch happens very seldom 92 | dec <.lz_dst + 1 93 | .lz_clc 94 | clc 95 | .lz_offset_lo adc #$ff ;carry is cleared, subtract (offset + 1) 96 | sta .lz_msrcr + 0 97 | lda <.lz_dst + 1 98 | .lz_offset_hi adc #$ff 99 | sta .lz_msrcr + 1 100 | .lz_cp_match 101 | .lz_msrcr = * + 1 102 | lda $beef,y 103 | sta (.lz_dst),y 104 | iny 105 | bne .lz_cp_match 106 | inc <.lz_dst + 1 107 | 108 | lda <.lz_len_hi ;check for more loop runs 109 | ;!if ZX0_INPLACE == 1 { 110 | ; bne .lz_m_page ;do more page runs 111 | ; 112 | ; cpx <.lz_dst + 0 ;check for end condition when depacking inplace 113 | ; bne .lz_start_over 114 | ; lda <.lz_dst + 1 115 | ; sbc <.lz_src1 116 | ; bne .lz_start_over 117 | ; rts 118 | ;.lz_m_page 119 | ; lda #$ff 120 | ;} else { 121 | beq .lz_start_over ;do more page runs 122 | lda #$ff 123 | ;} 124 | ;------------------ 125 | ;SELDOM STUFF 126 | ;------------------ 127 | .lz_dcp 128 | dcp .lz_len_hi 129 | bcs .lz_match_ 130 | .lz_l_page 131 | sec ;only needs to be set for consecutive rounds of literals, happens very seldom 132 | ldy #$00 133 | .lz_l_page_ 134 | dec <.lz_len_hi 135 | bcs .lz_cp_literal 136 | 137 | ;------------------ 138 | ;FETCH A NEW OFFSET 139 | ;------------------ 140 | 141 | .lz_new_offset 142 | lda #$fe 143 | jsr .lz_get_len 144 | sty .lz_len_hi 145 | adc #$00 146 | beq .lz_eof ;underflow. must have been 0 147 | 148 | sec 149 | ror 150 | sta .lz_offset_hi + 1 ;hibyte of offset 151 | 152 | .lz_src2 = * + 2 153 | lda $1000,x ;looks expensive, but is cheaper than loop 154 | inx 155 | bne + 156 | jsr .lz_inc_src_hi 157 | + 158 | ror 159 | sta .lz_offset_lo + 1 160 | 161 | lda #$01 162 | ldy #$fe 163 | bcs .lz_match__ ;length = 2 ^ $ff, do it the very short way :-) 164 | ldy #$00 165 | jsr .lz_get_len_ 166 | bcs .lz_match_ 167 | 168 | .lz_inc_src_hi 169 | inc .lz_src1 170 | inc .lz_src2 171 | inc .lz_src3 172 | rts 173 | 174 | .lz_get_len_ 175 | - ;lz_get_len as inline 176 | asl <.lz_bits ;fetch payload bit 177 | rol 178 | .lz_get_len 179 | asl <.lz_bits 180 | bcc - 181 | bne .lz_get_end 182 | .lz_refill_bits ;refill bits, this happens after 4 payload-bits bestcase 183 | .lz_src3 = * + 2 184 | ldy $1000,x 185 | inx 186 | bne + 187 | jsr .lz_inc_src_hi 188 | + 189 | sty <.lz_bits 190 | ldy #$00 191 | rol <.lz_bits 192 | bcs .lz_get_end 193 | - ;continue with 16 bit shifting 194 | asl <.lz_bits ;fetch payload bit 195 | rol ;can also moved to front and executed once on start 196 | .lz_get_len_16 197 | rol <.lz_len_hi 198 | asl <.lz_bits 199 | bcc - 200 | beq .lz_refill_bits 201 | .lz_get_end 202 | .lz_eof 203 | rts 204 | .depacker_end 205 | -------------------------------------------------------------------------------- /packer/zx0/6502/testfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/packer/zx0/6502/testfile -------------------------------------------------------------------------------- /packer/zx0/6502/testfile.zx0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bboxy/bitfire/eb7714dc0163f3a9d3883309489471361139d0dd/packer/zx0/6502/testfile.zx0 -------------------------------------------------------------------------------- /packer/zx0/LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Modified version (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 4 | 5 | Based on original (c) Copyright 2021 by Einar Saukas. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | 3. Neither the name of the copyright holder nor the names of its 18 | contributors may be used to endorse or promote products derived from 19 | this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 25 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /packer/zx0/Makefile: -------------------------------------------------------------------------------- 1 | ACME ?= acme 2 | ACME_OPTS ?= -f cbm 3 | zx0_CFLAGS ?= $(CFLAGS) -Ofast -Wall 4 | CC ?= cc 5 | 6 | V ?= 0 7 | ifeq ($(V),1) 8 | VR:= 9 | else 10 | VR:=@ 11 | endif 12 | 13 | SOURCE:= zx0.c compress.c optimize.c 14 | HEADER:= zx0.h sfx.h 15 | 16 | all: zx0 dzx0 17 | 18 | zx0: $(SOURCE) $(HEADER) 19 | @echo "Building zx0..." 20 | $(VR)$(CC) $(zx0_CFLAGS) -o $@ $(SOURCE) 21 | 22 | dzx0: dzx0.c 23 | $(VR)$(CC) $(zx0_CFLAGS) -o $@ $^ 24 | 25 | sfx.h: sfx.asm 26 | @#$(VR)$(ACME) $(ACME_OPTS) --labeldump sau.lst --vicelabels $(basename $@).lst -o $(basename $@) $< 27 | @#$(VR)grep 'ZX0' $(basename $@).lst | sed -E 's/al C:([0-9a-f]+)[[:space:]]\.(.*)/#define \2 0x\1/' >> $@ 28 | $(VR)$(ACME) $(ACME_OPTS) --labeldump $(basename $@).lst -o $(basename $@) $< 29 | $(VR)grep 'ZX0' $(basename $@).lst | sed -e 's/[[:space:]]*;[[:space:]]*.*//g' -e 's/[[:space:]]*//g' -e 's/\=\$$/ 0x/g' -e 's/^/#define /' > $@ 30 | $(VR)echo 'static const char decruncher[] = {' >> $@ 31 | @#create a hexdump, add a marker (+) where lines are truncated (each 50 chars = 8 bytes per line), substitute marker (+) with newline (use tr here, as bsd-sed fails on \n), add identation to each line 32 | $(VR)hexdump -ve '1/1 "0x%.2x,"' $(basename $@) | sed -e 's/,$$/+/g' -e 's/.\{50\}/&+/g' | tr -s '+' '\n' | sed 's/^/& /g' >> $@ 33 | $(VR)echo '};' >> $@ 34 | $(VR)rm $(basename $@).lst sfx 35 | 36 | clean: 37 | $(VR)-rm zx0 dzx0 sfx.h 38 | -------------------------------------------------------------------------------- /packer/zx0/compress.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified version (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Based on original (c) Copyright 2021 by Einar Saukas. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * The name of its author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "compress.h" 29 | #include 30 | #include 31 | #include 32 | 33 | #include "zx0.h" 34 | 35 | static unsigned char* output_data; 36 | static int output_index; 37 | static int input_index; 38 | static int bit_index; 39 | static int bit_mask; 40 | static int diff; 41 | //static int backtrack; 42 | 43 | static void read_bytes(int n, int *delta) { 44 | input_index += n; 45 | diff += n; 46 | if (diff > *delta) 47 | *delta = diff; 48 | } 49 | 50 | static void write_byte(int value) { 51 | output_data[output_index++] = value; 52 | diff--; 53 | } 54 | 55 | static void write_bit(int value) { 56 | // if (backtrack) { 57 | // if (value) 58 | // output_data[output_index-1] |= 1; 59 | // backtrack = FALSE; 60 | // } else { 61 | if (!bit_mask) { 62 | bit_mask = 128; 63 | bit_index = output_index; 64 | write_byte(0); 65 | } 66 | if (value) 67 | output_data[bit_index] |= bit_mask; 68 | bit_mask >>= 1; 69 | // } 70 | } 71 | 72 | static void write_interlaced_elias_gamma(int value, int backwards_mode, int skip, int invert) { 73 | int bits = bit_size(value); 74 | int i; 75 | int count = 0; 76 | 77 | for (i = 2; i <= value; i <<= 1) 78 | ; 79 | i >>= 1; 80 | 81 | if (bits >= 8) { 82 | /* change bit-order, send LSB first */ 83 | /* remove preceeding 1 first */ 84 | value = value & ((0xffff ^ i)); 85 | /* move LSB bits to the beginning */ 86 | value = (value >> 8) | ((value & 0xff) << (bits - 8)); 87 | } 88 | 89 | while ((i >>= 1) > 0) { 90 | if (count >= 8) invert = 0; 91 | count++; 92 | if (!skip) write_bit(0); 93 | //if (!skip) write_bit(backwards_mode); 94 | skip = 0; 95 | if (!skip) write_bit(((value & i) > 0) ^ invert); 96 | } 97 | if (!skip) write_bit(1); 98 | //if (!skip) write_bit(!backwards_mode); 99 | } 100 | 101 | static void encode_literal(int length, const unsigned char *input_data, int *delta, int backwards_mode, int first) { 102 | int i; 103 | if (!first) write_bit(0); 104 | 105 | /* copy literals length */ 106 | write_interlaced_elias_gamma(length, backwards_mode, 0, 0); 107 | /* copy literals values */ 108 | for (i = 0; i < length; i++) { 109 | write_byte(input_data[input_index]); 110 | read_bytes(1, delta); 111 | } 112 | return; 113 | } 114 | 115 | static void encode_rep(int length, int *delta, int backwards_mode) { 116 | write_bit(0); 117 | /* copy from last offset length */ 118 | write_interlaced_elias_gamma(length, backwards_mode, 0, 0); 119 | read_bytes(length, delta); 120 | return; 121 | } 122 | 123 | static void encode_match(int length, int offset, int *delta, int backwards_mode) { 124 | write_bit(1); 125 | /* copy from new offset MSB, -1 to make use of full offset range + 1 as 0 is not allowed in elias gamma */ 126 | write_interlaced_elias_gamma((offset - 1) / 128 + 1, backwards_mode, 0, 0); 127 | write_byte((((offset - 1) % 128) << 1) | (length == 2)); 128 | 129 | /* copy from new offset length */ 130 | write_interlaced_elias_gamma(length-1, backwards_mode, 1, 0); 131 | read_bytes(length, delta); 132 | return; 133 | } 134 | 135 | unsigned char *compress(BLOCK *optimal, const unsigned char *input_data, int input_size, int skip, int backwards_mode, int *output_size, int *delta, int inplace, int *inplace_end_pos) { 136 | BLOCK *next; 137 | BLOCK *prev; 138 | int last_offset = INITIAL_OFFSET; 139 | int first = TRUE; 140 | int i; 141 | int remaining; 142 | int inplace_output_index = 0; 143 | int inplace_input_index = 0; 144 | int overwrite; 145 | //int expected = 0; 146 | int actual = 0; 147 | 148 | /* calculate and allocate output buffer */ 149 | if (!inplace) { 150 | /* add end-marker */ 151 | *output_size = (optimal->bits + 18 + 7); 152 | } else { 153 | *output_size = (optimal->bits + 7); 154 | } 155 | //expected = *output_size; 156 | *output_size >>= 3; 157 | output_data = (unsigned char *)malloc(*output_size); 158 | if (!output_data) { 159 | fprintf(stderr, "Error: Insufficient memory\n"); 160 | exit(1); 161 | } 162 | 163 | /* initialize delta */ 164 | diff = *output_size - input_size + skip; 165 | *delta = 0; 166 | 167 | /* un-reverse optimal sequence */ 168 | next = NULL; 169 | while (optimal) { 170 | prev = optimal->chain; 171 | optimal->chain = next; 172 | next = optimal; 173 | optimal = prev; 174 | } 175 | 176 | input_index = skip; 177 | output_index = 0; 178 | bit_mask = 0; 179 | 180 | inplace_output_index = output_index; 181 | inplace_input_index = input_index; 182 | 183 | //printf("expected: %d\n", expected / 8); 184 | 185 | for (optimal = next->chain; optimal; optimal = optimal->chain) { 186 | if (!optimal->offset) { 187 | //printf("literal: len $%04x\n", optimal->length); 188 | encode_literal(optimal->length, input_data, delta, backwards_mode, first); 189 | actual += costof_literal(optimal->length); 190 | /* copy literals indicator */ 191 | if (first) first = FALSE; 192 | } else if (optimal->offset == last_offset) { 193 | //printf("copy last offset: $%04x len $%04x\n", optimal->offset, optimal->length); 194 | /* copy from last offset indicator */ 195 | encode_rep(optimal->length, delta, backwards_mode); 196 | actual += costof_rep(optimal->length); 197 | } else { 198 | /* copy from new offset indicator */ 199 | //printf("copy new offset: $%04x len $%04x\n", optimal->offset, optimal->length); 200 | encode_match(optimal->length, optimal->offset, delta, backwards_mode); 201 | last_offset = optimal->offset; 202 | actual += costof_match(optimal->offset, optimal->length); 203 | } 204 | 205 | if (inplace) { 206 | /* added +1, was off by one, thanks to Krill! */ 207 | overwrite = (input_index) - (input_size - *output_size + output_index) + 1; 208 | /* we would overwrite our packed data with a match, or have a literal that directly is followed by plain literal, so they can be aggregated */ 209 | /* it is a literal that woudl overwrite, so exit already here */ 210 | if (overwrite >= 0 && !optimal->offset) break; 211 | /* accept match and update end_position, literals are skipped then, as they fall back to last position */ 212 | *inplace_end_pos = input_index - skip; 213 | inplace_output_index = output_index; 214 | inplace_input_index = input_index; 215 | /* it is a match that overwrites, let it still happen, but then end with plain literal */ 216 | if (overwrite >= 0 && optimal->offset) break; 217 | } 218 | } 219 | 220 | //printf("actual: %d\n", expected); 221 | 222 | /* no endmarker in case of inplace depacking */ 223 | if (!inplace) { 224 | *inplace_end_pos = input_index - skip; 225 | /* end marker */ 226 | write_bit(1); 227 | write_interlaced_elias_gamma(256, backwards_mode, 0, 0); 228 | } else { 229 | /* copy remaining data as is */ 230 | input_index = inplace_input_index; 231 | output_index = inplace_output_index; 232 | remaining = input_size - inplace_input_index; 233 | *output_size = inplace_output_index + remaining; 234 | for (i = 0; i < remaining; i++) { 235 | write_byte(input_data[input_index]); 236 | read_bytes(1, delta); 237 | } 238 | } 239 | 240 | return output_data; 241 | } 242 | -------------------------------------------------------------------------------- /packer/zx0/compress.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified version (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Based on original (c) Copyright 2021 by Einar Saukas. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * The name of its author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | struct block_t; 29 | 30 | extern unsigned char *compress(struct block_t *optimal, const unsigned char *input_data, int input_size, int skip, int backwards_mode, int *output_size, int *delta, int inplace, int *inplace_end_pos); 31 | 32 | -------------------------------------------------------------------------------- /packer/zx0/dzx0.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ZX0 decompressor - by Einar Saukas 3 | * https://github.com/einar-saukas/ZX0 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #define BUFFER_SIZE 65536 /* must be > MAX_OFFSET */ 11 | #define INITIAL_OFFSET 1 12 | 13 | #define FALSE 0 14 | #define TRUE 1 15 | 16 | static FILE *ifp; 17 | static FILE *ofp; 18 | static char *input_name; 19 | static char *output_name; 20 | static unsigned char *input_data; 21 | static unsigned char *output_data; 22 | static size_t input_index; 23 | static size_t output_index; 24 | static size_t input_size; 25 | static size_t output_size; 26 | static size_t partial_counter; 27 | static int bit_mask; 28 | static int bit_value; 29 | static int backtrack; 30 | static int last_byte; 31 | static int last_offset; 32 | 33 | static int read_byte() { 34 | if (input_index == partial_counter) { 35 | input_index = 0; 36 | partial_counter = fread(input_data, sizeof(char), BUFFER_SIZE, ifp); 37 | input_size += partial_counter; 38 | if (partial_counter == 0) { 39 | fprintf(stderr, (input_size ? "Error: Truncated input file %s\n" : "Error: Empty input file %s\n"), input_name); 40 | exit(1); 41 | } 42 | } 43 | last_byte = input_data[input_index++]; 44 | return last_byte; 45 | } 46 | 47 | static int read_bit() { 48 | if (backtrack) { 49 | backtrack = FALSE; 50 | return last_byte & 1; 51 | } 52 | bit_mask >>= 1; 53 | if (bit_mask == 0) { 54 | bit_mask = 128; 55 | bit_value = read_byte(); 56 | } 57 | return bit_value & bit_mask ? 1 : 0; 58 | } 59 | 60 | static int read_interlaced_elias_gamma() { 61 | int bit_size = 0; 62 | int value = 0; 63 | int value1 = 1; 64 | int value2 = 0; 65 | 66 | /* also encode like this XXX TODO, easier to understand */ 67 | while (!read_bit()) { 68 | if (bit_size >= 8) { 69 | value2 = value2 << 1 | read_bit(); 70 | } else { 71 | value1 = value1 << 1 | read_bit(); 72 | } 73 | bit_size++; 74 | if (bit_size == 8) value2 = 1; 75 | } 76 | value = (value2 << 8) | (value1 & 0xff); 77 | return value; 78 | } 79 | 80 | static void save_output() { 81 | if (output_index != 0) { 82 | if (fwrite(output_data, sizeof(char), output_index, ofp) != output_index) { 83 | fprintf(stderr, "Error: Cannot write output file %s\n", output_name); 84 | exit(1); 85 | } 86 | output_size += output_index; 87 | output_index = 0; 88 | } 89 | } 90 | 91 | static void write_byte(int value) { 92 | output_data[output_index++] = value; 93 | if (output_index == BUFFER_SIZE) { 94 | save_output(); 95 | } 96 | } 97 | 98 | static void write_bytes(int offset, int length) { 99 | int i; 100 | 101 | if (offset > output_size+output_index) { 102 | fprintf(stderr, "Error: Invalid data in input file %s\n", input_name); 103 | exit(1); 104 | } 105 | while (length-- > 0) { 106 | i = output_index-offset; 107 | write_byte(output_data[i >= 0 ? i : BUFFER_SIZE+i]); 108 | } 109 | } 110 | 111 | static void decompress() { 112 | int length; 113 | int i; 114 | 115 | /* XXX TODO support inplace and cbm style files */ 116 | input_data = (unsigned char *)malloc(BUFFER_SIZE); 117 | output_data = (unsigned char *)malloc(BUFFER_SIZE); 118 | if (!input_data || !output_data) { 119 | fprintf(stderr, "Error: Insufficient memory\n"); 120 | exit(1); 121 | } 122 | 123 | input_size = 0; 124 | input_index = 0; 125 | partial_counter = 0; 126 | output_index = 0; 127 | output_size = 0; 128 | bit_mask = 0; 129 | backtrack = FALSE; 130 | last_offset = INITIAL_OFFSET; 131 | 132 | COPY_LITERALS: 133 | length = read_interlaced_elias_gamma(); 134 | for (i = 0; i < length; i++) { 135 | write_byte(read_byte()); 136 | } 137 | if (read_bit()) { 138 | goto COPY_FROM_NEW_OFFSET; 139 | } 140 | 141 | /*COPY_FROM_LAST_OFFSET:*/ 142 | length = read_interlaced_elias_gamma(); 143 | write_bytes(last_offset, length); 144 | if (!read_bit()) { 145 | goto COPY_LITERALS; 146 | } 147 | 148 | COPY_FROM_NEW_OFFSET: 149 | last_offset = read_interlaced_elias_gamma(); 150 | if (last_offset == 256) { 151 | save_output(); 152 | if (input_index != partial_counter) { 153 | fprintf(stderr, "Error: Input file %s too long\n", input_name); 154 | exit(1); 155 | } 156 | return; 157 | } 158 | last_offset = ((last_offset-1)<<7)+128-(read_byte()>>1); 159 | backtrack = TRUE; 160 | length = read_interlaced_elias_gamma()+1; 161 | write_bytes(last_offset, length); 162 | if (read_bit()) { 163 | goto COPY_FROM_NEW_OFFSET; 164 | } else { 165 | goto COPY_LITERALS; 166 | } 167 | } 168 | 169 | int main(int argc, char *argv[]) { 170 | int forced_mode = FALSE; 171 | int i; 172 | 173 | printf("DZX0 v1.5: Data decompressor by Einar Saukas\n"); 174 | 175 | /* process hidden optional parameters */ 176 | for (i = 1; i < argc && *argv[i] == '-'; i++) { 177 | if (!strcmp(argv[i], "-f")) { 178 | forced_mode = TRUE; 179 | } else { 180 | fprintf(stderr, "Error: Invalid parameter %s\n", argv[i]); 181 | exit(1); 182 | } 183 | } 184 | 185 | /* determine output filename */ 186 | if (argc == i+1) { 187 | input_name = argv[i]; 188 | input_size = strlen(input_name); 189 | if (input_size > 4 && !strcmp(input_name+input_size-4, ".zx0")) { 190 | input_size = strlen(input_name); 191 | output_name = (char *)malloc(input_size); 192 | strcpy(output_name, input_name); 193 | output_name[input_size-4] = '\0'; 194 | } else { 195 | fprintf(stderr, "Error: Cannot infer output filename\n"); 196 | exit(1); 197 | } 198 | } else if (argc == i+2) { 199 | input_name = argv[i]; 200 | output_name = argv[i+1]; 201 | } else { 202 | fprintf(stderr, "Usage: %s [-f] input.zx0 [output]\n" 203 | " -f Force overwrite of output file\n", argv[0]); 204 | exit(1); 205 | } 206 | 207 | /* open input file */ 208 | ifp = fopen(input_name, "rb"); 209 | if (!ifp) { 210 | fprintf(stderr, "Error: Cannot access input file %s\n", input_name); 211 | exit(1); 212 | } 213 | 214 | /* check output file */ 215 | if (!forced_mode && fopen(output_name, "rb") != NULL) { 216 | fprintf(stderr, "Error: Already existing output file %s\n", output_name); 217 | exit(1); 218 | } 219 | 220 | /* create output file */ 221 | ofp = fopen(output_name, "wb"); 222 | if (!ofp) { 223 | fprintf(stderr, "Error: Cannot create output file %s\n", output_name); 224 | exit(1); 225 | } 226 | 227 | /* generate output file */ 228 | decompress(); 229 | 230 | /* close input file */ 231 | fclose(ifp); 232 | 233 | /* close output file */ 234 | fclose(ofp); 235 | 236 | /* done! */ 237 | printf("File decompressed from %lu to %lu bytes!\n", (unsigned long)input_size, (unsigned long)output_size); 238 | 239 | return 0; 240 | } 241 | -------------------------------------------------------------------------------- /packer/zx0/optimize.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified version (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Based on original (c) Copyright 2021 by Einar Saukas. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * The name of its author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | struct block_t; 29 | 30 | extern struct block_t *optimize(const unsigned char *input_data, int input_size, int skip, int offset_limit); 31 | 32 | -------------------------------------------------------------------------------- /packer/zx0/sfx.asm: -------------------------------------------------------------------------------- 1 | ; 2 | ; (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | ; 4 | ; Redistribution and use in source and binary forms, with or without 5 | ; modification, are permitted provided that the following conditions are met: 6 | ; * Redistributions of source code must retain the above copyright 7 | ; notice, this list of conditions and the following disclaimer. 8 | ; * Redistributions in binary form must reproduce the above copyright 9 | ; notice, this list of conditions and the following disclaimer in the 10 | ; documentation and/or other materials provided with the distribution. 11 | ; * The name of its author may not be used to endorse or promote products 12 | ; derived from this software without specific prior written permission. 13 | ; 14 | ; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | ; DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 18 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | ; 25 | 26 | !cpu 6510 27 | 28 | .depacker = $01 29 | .smc_offsetd = .depacker - (.depacker_start - .zx0_code_start) 30 | ;ZX0_SRC_HI1 = .lz_src1 - .smc_offsetd + 2 31 | ;ZX0_SRC_HI2 = .lz_src2 - .smc_offsetd + 2 32 | ;ZX0_SRC_HI3 = .lz_src3 - .smc_offsetd + 2 33 | ;ZX0_SRC_LO = .lz_src_lo - .smc_offsetd + 2 34 | ZX0_SRC = .lz_src - .smc_offsetd + 2 35 | ZX0_DST = .lz_dst - .smc_offsetd + 2 36 | ZX0_SFX_ADDR = .lz_sfx_addr - .smc_offsetd + 2 37 | ZX0_DATA_END = .lz_data_end - .zx0_code_start + 2 38 | ZX0_DATA_SIZE_HI = .lz_data_size_hi - .zx0_code_start + 2 39 | 40 | * = $0801 41 | .zx0_code_start 42 | !byte $0b,$08 43 | !word 1602 44 | !byte $9e 45 | !text "2061" 46 | !byte $00,$00,$00 47 | 48 | ;/!\ ATTENTION, the depacker just fits into ZP this way, if it gets larger, the copy routine will overwrite $00, as it is a 8-bit address sta 49 | sei 50 | lda $ba 51 | pha 52 | ldx #.depacker_end - .depacker_start 53 | - 54 | lda .depacker_start - 1,x 55 | sta .depacker - 1,x 56 | dex 57 | bne - 58 | 59 | .lz_data_size_hi = * + 1 60 | ldy #>(.data_end - .data) + 1 61 | - 62 | dex 63 | .lz_data_end = * + 1 64 | .src lda .data_end - $100,x 65 | .dst sta $ff00,x 66 | txa 67 | bne - 68 | 69 | dec .src + 2 70 | dec .dst + 2 71 | dey 72 | bne - 73 | jmp .depack 74 | 75 | ;------------------ 76 | ;depacker starts here 77 | ;------------------ 78 | .depacker_start 79 | !pseudopc .depacker { 80 | !byte $38 81 | .depack 82 | ;ldy #$00 ;is already 0 83 | ;------------------ 84 | ;LITERAL 85 | ;------------------ 86 | .lz_start_over 87 | lda #$01 ;we fall through this check on entry and start with literal 88 | asl <.lz_bits 89 | bcs .lz_new_offset ;after each match check for another match or literal? 90 | .literal 91 | jsr .get_length 92 | tax 93 | beq .lz_l_page_ 94 | ; dec <.lz_len_hi ;happens very seldom, so let's do that with lz_l_page that also decrements lz_len_hi, it sets carry and resets Y, what is unnecessary, but happens so seldom it doesn't hurt 95 | .cp_literal 96 | .lz_src = * + 1 97 | lda .data,y ;looks expensive, but is cheaper than loop 98 | sta (.lz_dst),y 99 | iny 100 | dex 101 | bne .cp_literal 102 | 103 | dey ;this way we force increment of lz_dst + 1 if y = 0 104 | tya 105 | adc <.lz_dst + 0 106 | sta <.lz_dst + 0 ;XXX TODO final add of y, coudl be combined with next add? -> postpone until match that will happen necessarily later on? 107 | bcc + 108 | inc <.lz_dst + 1 109 | + 110 | tya 111 | sec 112 | adc <.lz_src + 0 113 | sta <.lz_src + 0 114 | bcc + 115 | inc <.lz_src + 1 116 | + 117 | ldy <.lz_len_hi 118 | bne .lz_l_page ;happens very seldom 119 | 120 | ;------------------ 121 | ;NEW OR OLD OFFSET 122 | ;------------------ 123 | 124 | .cp_literal_done 125 | lda #$01 126 | asl <.lz_bits 127 | bcs .lz_new_offset ;either match with new offset or old offset 128 | 129 | ;------------------ 130 | ;DO MATCH 131 | ;------------------ 132 | .lz_match_repeat 133 | jsr .get_length 134 | ;XXX TODO encode length - 1 for rep match? but 0 can't be detected then? 135 | sbc #$01 ;saves the sec and iny later on, if it results in a = $ff, no problem, we branch with the beq later on 136 | ;sec ;need sec here if we want to forgo in the beq .lz_calc_msrc 137 | bcs + 138 | dcp <.lz_len_hi 139 | + 140 | .lz_match_ 141 | eor #$ff 142 | ;beq .lz_calc_msrc ;just fall through on zero? $ff + sec -> addition is neutralized and carry is set, so no harm 143 | tay 144 | eor #$ff ;restore A 145 | .lz_match__ ;entry from new_offset handling 146 | adc <.lz_dst + 0 147 | sta <.lz_dst + 0 148 | bcs + ;/!\ branch happens less than fall through, only in case of branch carry needs to be cleared :-( 149 | dec <.lz_dst + 1 150 | + 151 | clc ;can this be avoided by receiving offset - 1 from stream? 152 | .lz_offset_lo = * + 1 153 | sbc #$00 154 | sta <.lz_msrcr + 0 155 | lda <.lz_dst + 1 156 | .lz_offset_hi = * + 1 157 | sbc #$00 158 | sta <.lz_msrcr + 1 159 | .cp_match 160 | .lz_msrcr = * + 1 161 | lda $beef,y 162 | .lz_dst = * + 1 163 | sta $4000,y 164 | iny 165 | bne .cp_match 166 | inc <.lz_dst + 1 167 | 168 | .lz_len_hi = * + 1 169 | lda #$00 ;check for more loop runs 170 | beq .lz_start_over 171 | dec <.lz_len_hi 172 | inc <.lz_msrcr + 1 ;XXX TODO only needed if more pages follow 173 | bne .cp_match 174 | .lz_l_page 175 | sec ;only needs to be set for consecutive rounds of literals, happens very seldom 176 | ldy #$00 177 | .lz_l_page_ 178 | dec <.lz_len_hi 179 | bcs .cp_literal 180 | 181 | ;------------------ 182 | ;FETCH A NEW OFFSET 183 | ;------------------ 184 | - ;get_length as inline 185 | asl <.lz_bits ;fetch payload bit 186 | rol ;can also moved to front and executed once on start 187 | .lz_new_offset 188 | asl <.lz_bits 189 | bcc - 190 | + 191 | bne + 192 | jsr .lz_refill_bits 193 | + 194 | sbc #$01 195 | 196 | bcc .lz_eof ;underflow. must have been 0 197 | lsr 198 | sta <.lz_offset_hi ;hibyte of offset 199 | 200 | lda (.lz_src),y ;fetch another byte directly 201 | ror 202 | sta <.lz_offset_lo 203 | 204 | inc <.lz_src + 0 205 | bne + 206 | inc <.lz_src + 1 207 | + 208 | ;XXX TODO would be nice to have inverted data sent, but would mean MSB also receives inverted bits? sucks. As soon as we refill bits we fall into loop that checks overflow on LSB, should check for bcc however :-( then things would work 209 | ;would work on offset MSB, but need to clear lz_len_hi after that 210 | lda #$01 211 | ldy #$fe 212 | bcs .lz_match__ ;length = 2 ^ $ff, do it the very short way :-) 213 | - 214 | asl <.lz_bits ;fetch first payload bit 215 | 216 | rol ;can also moved to front and executed once on start 217 | asl <.lz_bits 218 | bcc - 219 | bne .lz_match_ 220 | ldy #$00 221 | jsr .lz_refill_bits ;fetch remaining bits 222 | bcs .lz_match_ 223 | .lz_bits !byte $40 224 | .lz_refill_bits 225 | tax 226 | lda (.lz_src),y 227 | rol 228 | sta <.lz_bits 229 | inc <.lz_src + 0 230 | bne + 231 | inc <.lz_src + 1 232 | + 233 | txa 234 | bcs .end_bit_16 235 | 236 | ;fetch up to 8 bits first, if first byte overflows, stash away byte and fetch more bits as MSB 237 | .lz_get_loop 238 | asl <.lz_bits ;fetch payload bit 239 | .get_length_ 240 | rol ;can also moved to front and executed once on start 241 | bcs .get_length_16 ;first 1 drops out from lowbyte, need to extend to 16 bit, unfortunatedly this does not work with inverted numbers 242 | .get_length 243 | asl <.lz_bits 244 | bcc .lz_get_loop 245 | beq .lz_refill_bits 246 | rts 247 | 248 | .get_length_16 249 | pha ;save LSB 250 | tya ;start with MSB = 1 251 | jsr .get_length_ ;get up to 7 more bits 252 | sta <.lz_len_hi ;save MSB 253 | pla ;restore LSB 254 | .end_bit_16 255 | rts 256 | .lz_eof 257 | ;------------------ 258 | ;exit code for sfx only 259 | ;------------------ 260 | 261 | dec $01 262 | ;cli 263 | sty $98 264 | pla 265 | sta $ba 266 | .lz_sfx_addr = * + 1 267 | jmp $0000 268 | } 269 | .depacker_end 270 | ;!warn "sfx size: ", .depacker_end - .depacker_start 271 | .data 272 | ;!bin "test.lz" 273 | .data_end 274 | -------------------------------------------------------------------------------- /packer/zx0/zx0.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Modified version (c) Copyright 2021 by Tobias Bindhammer. All rights reserved. 3 | * 4 | * Based on original (c) Copyright 2021 by Einar Saukas. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * * Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * * The name of its author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #define INITIAL_OFFSET 1 29 | 30 | #define FALSE 0 31 | #define TRUE 1 32 | 33 | typedef struct block_t { 34 | struct block_t *chain; 35 | int bits; 36 | int index; 37 | int offset; 38 | int length; 39 | int references; 40 | } BLOCK; 41 | 42 | static inline unsigned bit_size(unsigned value) { 43 | # ifdef __GNUC__ 44 | // enum { WORD_BITS = sizeof(unsigned) * CHAR_BIT }; 45 | 46 | return ((sizeof(unsigned) * 8 - 1) ^ __builtin_clz(value)); 47 | # else 48 | signed bits = -1; 49 | 50 | do 51 | ++bits; 52 | while(value >>= 1); 53 | 54 | return bits; 55 | # endif 56 | } 57 | 58 | static inline int costof_run(int length) { 59 | return bit_size(length) * 2 + 1; 60 | } 61 | 62 | static inline int costof_literal(int length) { 63 | return 1 + costof_run(length) + length * 8; 64 | } 65 | 66 | static inline int costof_rep(int length) { 67 | return 1 + costof_run(length); 68 | } 69 | 70 | static inline int costof_match(int offset, int length) { 71 | return 1 + costof_run(length - 1) + 7 + costof_run(((offset - 1) / 128) + 1); 72 | } 73 | -------------------------------------------------------------------------------- /syncpoints.inc: -------------------------------------------------------------------------------- 1 | ;mem location of sid player that utters syncpoints 2 | link_syncpoint = $0e81 3 | 4 | ;values for the various selfdefined syncpoints 5 | sync_part_xxx_fadein = $00 6 | sync_part_xxx_fadeout = $01 7 | 8 | ;central defines for parts that sync around loading operations. So all counters are maintained in a single file and not spread over many many parts 9 | ;use like: 10 | 11 | ;!include "framework/syncpoints.inc" 12 | ;+setup_sync SYNC_FRAMES_PARTX 13 | ;jsr bitfire_loadnext_compd_ 14 | ;+sync 15 | 16 | SYNC_FRAMES_PARTX = $0300 17 | SYNC_FRAMES_PARTY = $0380 18 | --------------------------------------------------------------------------------