Skip to content

Commit

Permalink
improved format and ASM decompressor
Browse files Browse the repository at this point in the history
(image width stored in data file, ASM decompressor is now IRQ and VRAM
*safe*
- also: official name is now "ShrunkTileMap")
  • Loading branch information
sverx committed Dec 28, 2017
1 parent a1c72c9 commit e4bedc1
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 79 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
STMcomp
=====================

Sverx's TileMap compressed format Bmp2Tile plugin and Z80 decompression routine
ShrunkTileMap compressed format Bmp2Tile plugin and Z80 decompression routine
Binary file modified compressor plugin/gfxcomp_stm.dll
Binary file not shown.
8 changes: 7 additions & 1 deletion compressor plugin/src/gfxcomp_stm.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ bool checkHI (int i) {
}

__declspec(dllexport) const char* getName() {
return "Sverx`s TileMap";
return "ShrunkTileMap (compressed)";
}

__declspec(dllexport) const char* getExt() {
Expand All @@ -104,6 +104,12 @@ __declspec(dllexport) int compressTilemap(uint8_t* source, uint32_t width, uint3
cur_HH=0;
writepos=0;

// write header (it's just 1 byte and it stores the width -in tiles- of the map
if (writepos<outsize)
outbuf[writepos++]=width; // write map width in tiles
else
return (0); // please give me more space for output

while (current<in_size) {

// check if the HH part of the next tile is the same as what we have
Expand Down
240 changes: 167 additions & 73 deletions decompressor/src/STM_tilemap_decomp.inc
Original file line number Diff line number Diff line change
@@ -1,80 +1,174 @@
; ***** Sverx's TileMap decompressor *****
; ***** ShrunkTileMap (previously known as "Sverx's TileMap") decompressor *****
; ***** by sverx - https://github.com/sverx/STMcomp/tree/master/decompressor/src *****
; ***** (now VRAM / Interrupt *SAFE* !!!) *****
; ***** (note: code backported from devkitSMS) *****

; to use it, you have to do this:
; ld hl,compressed_tilemap ; - set source address
; ld de,VRAMAddress|$4000 ; - set destination VRAM address, ORed with $4000
; ************************************************************************************
; to use this function, you have to do this:
; ld hl,STMcompr_tilemap ; load address of STM data into HL
; ld de,VRAMAddress ; set destination VRAM address into DE
; call STM_tilemap_decompr
; the function needs 9 bytes of RAM to work, see ramsection at the end of this file
; ************************************************************************************

.section "Sverx's TileMap decompressor" free
; HL = compressed tilemap binary (source)
; DE = VRAM address (destination) - ORed with $4000
; destroys AF,BC,DE,HL,IX
.section "ShortTileMap decompressor" free
; HL = compressed tilemap (source)
; DE = VRAM address (destination)
; destroys AF,BC,DE,HL
STM_tilemap_decompr:
ld c,$bf ; set VRAM address
out (c),e
out (c),d
ld c,$be ; set C to VDP data port
ld d,$00 ; sets HH to $00
ld ix,$0000 ; sets oldHH/flags to $0000
_MainLoop:
ld a,ixl ; do we need to restore HH?
or a
jr z,+ ; if flag is 0 then no restore
ld d,ixh ; restore HH
ld ixl,$0 ; reset restore flag
_MainLoop_nocheck:
+:ld a,(hl)
inc hl
rra ; is it a RLE run?
jr c,_RLE
rra ; is a RAW run?
jr nc,_RAW

; set new HH
rra ; is it a temporary set?
jr nc,_noTemp
ld ixh,d ; save old HH
ld ixl,$1 ; raise restore flag
_noTemp:
and $1F ; keep only last 5 bits
ld d,a ; set new HH
jp _MainLoop_nocheck

_RLE:
rra ; is it a RLE run of same value bytes?
jr c,_incrementalRLE
and $3F ; keep only last 6 bits (counter)
add a,2 ; counter +=2
ld b,a
ld e,(hl) ; load value
inc hl
-:out (c),e ; push (same) values to VRAM
out (c),d
djnz -
jp _MainLoop

_RAW:
and $3F ; keep only last 6 bits (counter)
ret z ; if counter==0 then data is over, leave!
ld b,a
-:ld e,(hl) ; load value
inc hl
out (c),e ; push value to VRAM
out (c),d
djnz -
jp _MainLoop
ld a,$40
or d
ld d,a
ld (STM_dest),de
xor a
ld (STM_HH),a
ld (STM_oldHH),a
ld (STM_needRestore),a
ld a,(hl)
ld (STM_width),a
ld (STM_ttw),a
inc hl
ld (STM_src),hl
ld hl,(STM_dest)
ld c, $BF ; set VDP Control Port
di ; make it interrupt SAFE
out (c),l
out (c),h
ei
_STM_loop:
ld hl,(STM_src)
ld a,(hl)
inc hl
ld (STM_src),hl
rra
jr nc,_STM_noRLE
rra
jr nc,_STM_RLE
; ***************** RLE of successive words
and $3F ; keep only last 6 bits (counter)
add a,$02
ld b,a ; b = cnt
ld a,(STM_HH)
ld d,a ; d = high part of tile
ld e,(hl) ; e = low part of tile
inc hl
ld (STM_src),hl ; src++
ld hl,STM_ttw
ld c,(hl) ; c = ttw
_STM_inc_RLE_loop:
ld a,e ; write tile to VRAM respecting access time costraints
out ($BE),a ; 11
ld a,d ; 4
sub $00 ; *delay* 7
dec c ; ttw-- 4 = 26 (VRAM SAFE)
out ($BE),a
call z,_STM_setAddr ; ttw==0?
dec b
jr z,_STM_inc_RLE_done ; cnt==0?
inc de ; tile++
jr _STM_inc_RLE_loop
_STM_inc_RLE_done:
ld hl,STM_HH ; save high part of tile
ld (hl),d
ld hl,STM_ttw ; save ttw
ld (hl),c
_STM_check_restore:
ld a,(STM_needRestore)
or a
jr z,_STM_loop
xor a
ld (STM_needRestore),a
ld a,(STM_oldHH)
ld (STM_HH),a
jr _STM_loop
_STM_noRLE:
rra
jr nc,_STM_RAW
; ***************** special
rra
jr nc,_STM_no_temp_HH
ld b,a
ld a,(STM_HH)
ld (STM_oldHH),a
ld a,$01
ld (STM_needRestore),a
ld a,b
_STM_no_temp_HH:
and $1F ; keep only last 5 bits
ld (STM_HH),a
jr _STM_loop
_STM_RLE:
; ***************** RLE
and $3F ; keep only last 6 bits (counter)
add a,$02
ld b,a ; b = cnt
ld a,(STM_HH)
ld d,a ; d = high part of tile
ld e,(hl) ; e = low part of tile
inc hl
ld (STM_src),hl ; src++
ld hl,STM_ttw
ld c,(hl) ; c = ttw
_STM_RLE_loop:
ld a,e ; write tile to VRAM respecting access time costraints
out ($BE),a ; 11
ld a,d ; 4
sub $00 ; *delay* 7
dec c ; ttw-- 4 = 26 (VRAM SAFE)
out ($BE),a
call z,_STM_setAddr ; ttw==0?
dec b
jr nz,_STM_RLE_loop ; cnt==0?
ld hl,STM_ttw ; save ttw
ld (hl),c
jr _STM_check_restore
_STM_RAW:
; ***************** RAW
and $3F ; keep only last 6 bits (counter)
or a
ret z ; if cnt is 0 - end of STM
ld b,a ; b = cnt
ld hl,STM_ttw
ld c,(hl) ; c = ttw
_STM_RAW_loop:
ld hl,(STM_src)
ld a,(hl)
out ($BE),a ; 11 low part of tile
inc hl ; 6
ld (STM_src),hl ; 16 src++
ld a,(STM_HH) ; 13 high part of tile
out ($BE),a ; xx = VRAM safe
dec c
call z,_STM_setAddr
dec b
jr nz,_STM_RAW_loop
ld hl,STM_ttw
ld (hl),c
jr _STM_check_restore
_STM_setAddr:
ld hl,(STM_dest)
ld a,b ; preserve b
ld bc,64
add hl,bc
ld b,a ; restore b
ld (STM_dest),hl
ld c,$BF ; set VDP Control Port
di ; make it interrupt SAFE
out (c),l
out (c),h
ei
ld a,(STM_width)
ld (STM_ttw),a
ld c,a
ret
.ends

_incrementalRLE:
and $3F ; keep only last 6 bits (counter)
add a,2 ; counter +=2
ld b,a
ld e,(hl) ; load start value
inc hl
-:out (c),e ; push incremental values to VRAM
out (c),d
inc de
djnz -
dec de ; this is to keep HH consistent with last value
jp _MainLoop
.ramsection "STM variables" slot 3
STM_src dw
STM_dest dw
STM_HH db
STM_oldHH db
STM_needRestore db
STM_ttw db
STM_width db
.ends
12 changes: 8 additions & 4 deletions file format.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
Format details (everything is stored as run of bytes)
Format details:

first byte -- other bytes that may be following
%nnnnnn01 -- dd : run of n+2 (2 to 65) same word value HHdd (a.k.a. "normal" RLE)
%nnnnnn11 -- dd : run of n+2 (2 to 65) successive word values (HHdd, HHdd+1, HHdd+2 ...)
first byte -- header. image width (in tiles)

next bytes -- runs. type of run described by the two least significant bits of the first byte of each run
according to the folowing:

%nnnnnn01 -- dd : run of n+2 (2 to 65) *same word* value HHdd (a.k.a. "normal" RLE)
%nnnnnn11 -- dd : run of n+2 (2 to 65) *successive word* values (HHdd, HHdd+1, HHdd+2 ...)
: will eventually change HH too!
%nnnnnn00 -- dd kk pp [...] : run of n (1 to 63) words using each of the following bytes (HHdd, HHkk, HHpp...)
: n=0 means end of compressed data
Expand Down

0 comments on commit e4bedc1

Please sign in to comment.