add compression.decode_rle_vram() to decompress RLE data directly to X16's VRAM.

Document the compression library.
This commit is contained in:
Irmen de Jong 2024-11-26 01:47:47 +01:00
parent 2eed75f602
commit bc9683cc54
5 changed files with 106 additions and 12 deletions

View File

@ -4,7 +4,7 @@
smallringbuffer {
; -- A ringbuffer (FIFO queue) that occupies a single page in memory, containing 255 bytes maximum.
; You can store and retrieve words too.
; You can store and retrieve bytes and words too.
; It's optimized for speed and depends on the byte-wrap-around feature when doing incs and decs.
ubyte fill
@ -70,8 +70,8 @@ smallringbuffer {
ringbuffer {
; -- A ringbuffer (FIFO queue) that occupies a single page in memory, containing 8 KB maximum.
; You can store and retrieve words too.
; -- A ringbuffer (FIFO queue) that uses a block of 8 KB of memory.
; You can store and retrieve bytes and words too.
uword fill
uword head
@ -148,5 +148,5 @@ ringbuffer {
}
; TODO ringbuffer (FIFO queue) should use banked ram on the X16, but still work on virtual
; TODO ringbuffer (FIFO queue) should use banked ram on the X16, but still work on virtual target
; TODO stack (LIFO queue) using more than 1 page of ram (maybe even banked ram on the x16)

View File

@ -7,7 +7,7 @@ compression {
sub encode_rle_outfunc(uword data, uword size, uword output_function, bool is_last_block) {
; -- Compress the given data block using ByteRun1 aka PackBits RLE encoding.
; output_function = address of a routine that gets a byte arg in A,
; this is the next RLE byte to write to the compressed output buffer or file.
; which is the next RLE byte to write to the compressed output buffer or file.
; is_last_block = usually true, but you can set it to false if you want to concatenate multiple
; compressed blocks (for instance if the source data is >64Kb)
; Worst case result storage size needed = (size + (size+126) / 127) + 1
@ -136,9 +136,9 @@ compression {
}
asmsub decode_rle_srcfunc(uword source_function @AY, uword target @R0, uword maxsize @R1) clobbers(X) -> uword @AY {
; -- decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
; instead of a source buffer, you provide a callback function that must return the next byte to compress in A.
; Stops decompressing when the maxsize has been reached.
; -- Decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
; Also stops decompressing when the maxsize has been reached. Returns the size of the decompressed data.
; Instead of a source buffer, you provide a callback function that must return the next byte to compress in A.
%asm {{
sta _cb_mod1+1
sty _cb_mod1+2
@ -234,8 +234,9 @@ _end
}
asmsub decode_rle(uword compressed @AY, uword target @R0, uword maxsize @R1) clobbers(X) -> uword @AY {
; -- decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
; Stops decompressing when the maxsize has been reached.
; -- Decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
; Also stops decompressing if the maxsize has been reached.
; Returns the size of the decompressed data.
%asm {{
sta P8ZP_SCRATCH_W1 ; compressed data ptr
sty P8ZP_SCRATCH_W1+1
@ -345,6 +346,65 @@ _end
}}
}
asmsub decode_rle_vram(uword compressed @R0, ubyte vbank @X, uword vaddr @AY) {
; -- Decodes "ByteRun1" (aka PackBits) RLE compressed data directly into Vera VRAM.
; Control byte value 128 ends the decoding. This routine is for the Commander X16 only.
%asm {{
stz cx16.VERA_CTRL
sta cx16.VERA_ADDR_L
sty cx16.VERA_ADDR_M
txa
ora #%00010000 ; autoincr by 1
sta cx16.VERA_ADDR_H
_loop
lda (cx16.r0)
bpl _copy_literals
cmp #128
bne +
rts ; DONE!
; replicate the next byte -n+1 times
+
inc cx16.r0L
bne +
inc cx16.r0H
+ eor #255
clc
adc #2
tay
lda (cx16.r0)
- sta cx16.VERA_DATA0
dey
bne -
inc cx16.r0L
bne _loop
inc cx16.r0H
bra _loop
_copy_literals
; copy the next n+1 bytes
inc cx16.r0L
bne +
inc cx16.r0H
+ pha
tax
inx
ldy #0
- lda (cx16.r0),y
sta cx16.VERA_DATA0
iny
dex
bne -
; increase pointer by n+1 bytes
pla
sec
adc cx16.r0L
sta cx16.r0L
bcc _loop
inc cx16.r0H
bra _loop
}}
}
/***
; prog8 source code for the asm routine above:

View File

@ -928,6 +928,37 @@ the `bmx source code <https://github.com/irmen/prog8/tree/master/compiler/res/pr
There's also the "showbmx" example to look at.
compression
-----------
Routines for data compression and decompression. Currently only the 'ByteRun1' aka 'PackBits' RLE encoding
is available. This is the compression that was also used in Amiga IFF images and in old MacPaint images.
``encode_rle (uword data, uword size, uword target, bool is_last_block) -> uword``
Compress the given data block using ByteRun1 aka PackBits RLE encoding.
Returns the size of the compressed RLE data. Worst case result storage size needed = (size + (size+126) / 127) + 1.
'is_last_block' = usually true, but you can set it to false if you want to concatenate multiple
compressed blocks (for instance if the source data is >64Kb)
``encode_rle_outfunc (uword data, uword size, uword output_function, bool is_last_block)``
Like ``encode_rle`` but not with an output buffer, but with an 'output_function' argument.
This is the address of a routine that gets a byte arg in A,
which is the next RLE byte to write to the compressed output buffer or file.
``decode_rle (uword compressed, uword target, uword maxsize) -> uword``
Decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
Also stops decompressing if the maxsize has been reached. Returns the size of the decompressed data.
``decode_rle_srcfunc (uword source_function, uword target, uword maxsize) -> uword``
Decodes "ByteRun1" (aka PackBits) RLE compressed data. Control byte value 128 ends the decoding.
Also stops decompressing when the maxsize has been reached. Returns the size of the decompressed data.
Instead of a source buffer, you provide a callback function that must return the next byte to compress in A.
``decode_rle_vram (uword compressed, ubyte vbank, uword vaddr)`` (cx16 only)
Decodes "ByteRun1" (aka PackBits) RLE compressed data directly into Vera VRAM.
Control byte value 128 ends the decoding.
emudbg (cx16 only)
-------------------
X16Emu Emulator debug routines, for Cx16 only.

View File

@ -1,6 +1,8 @@
TODO
====
work a bit more on the buffers library
document the @R0 - @R15 register support for normal subroutine parameters (footgun!)
make a compiler switch to disable footgun warnings

View File

@ -82,7 +82,8 @@ class BitmapImage:
def show(self) -> None:
"""Shows the image on the screen"""
if self.img.mode == "P":
self.img.convert("RGB").convert("P").show()
self.img.show()
# self.img.convert("RGB").convert("P").show()
else:
self.img.show()
@ -198,7 +199,7 @@ class BitmapImage:
elif bits_per_pixel == 4:
num_colors = 15 if fixed_color_zero else 16
if num_colors==16 and preserve_first_16_colors:
return self.quantize_to(default_colors[:16])
return self.quantize_to(default_colors[:16], 0)
elif bits_per_pixel == 2:
assert preserve_first_16_colors==False, "bpp is too small for 16 default colors"
num_colors = 3 if fixed_color_zero else 4