I used a simple/basic RLE compression mechanism (for CHR data) in my FF2e intro, which I've been revamping as of late. I was going for size (due to limited ROM space) and not speed. It got a 1264 byte CHR file down to 610 bytes. One drawback is that it can only handle lengths between 0 and 127. Here's the code, since I figure it would benefit someone somewhere:
Code: Select all
; Copyright (C) 1998-2015 Jeremy Chadwick. All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions
; are met:
;
; 1. Redistributions of source code must retain the above copyright
; notice, this list of conditions and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright
; notice, this list of conditions and the following disclaimer in the
; documentation and/or other materials provided with the distribution.
;
; THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
; ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
; SUCH DAMAGE.
; This is an RLE decompression routine for CHR data. LOGO_ADDR (a
; 16-bit pointer) is used to reference the base address of the data in
; question. The format of the data is simple:
;
; Offset 0: Count: Number of times Value should be repeated.
; If the MSB is set, indicates this is the last entry to be
; handled. Number of times is therefore limited to $00-7F
; Offset 1: Value: Raw 8-bit value (i.e. tile number)
; ...repeat...
;
; An example set of compressed data would be:
;
; .byte $10, $32 ; Repeat sixteen ($10) times the value $32
; .byte $06, $FA ; Repeat six ($06) times the value $FA
; .byte $9F, $1D ; Repeat thirty-one ($1F) times the value $1D, then done
;
.proc Load_RLE_Data
L1: ldy #0
lda (LO_ADDR),y ; Get Count from data structure
pha ; ...and temporarily back it up for later use
and #$7f ; Strip off the MSB
tax ; ...and use the result as our loop counter
iny ; Move on to next byte in data structure
lda (LO_ADDR),y ; Get Value from data structure
: sta $2006 ; Write it $2006
dex ; Decrement the iteration count (for this value)
bne :- ; ...and repeat writing until 0
pla ; Restore the original Count value
bmi Done ; If MSB is set (negative flag set), we're done
lda LO_ADDR ; ...otherwise increment LO_ADDR (low byte) by 2
clc
adc #2
sta LO_ADDR ; ...if the ADC set the carry (indicating unsigned
bcc :+ ; ...overflow), then we know we wrapped ($FF->00)
inc LO_ADDR+1 ; ...and need to increment the high byte
: jmp L1 ; Move on to the next entry
Done:
rts ; ...and we're completely done
.endproc