Skip to content

Instantly share code, notes, and snippets.

@BlockoS
Created January 31, 2016 20:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BlockoS/fb927b3cf744a2c74660 to your computer and use it in GitHub Desktop.
Save BlockoS/fb927b3cf744a2c74660 to your computer and use it in GitHub Desktop.
LZSS pcengine unpacker
;;------------------------------------------------
;; Compressed image loading (lzss)
;; (c) 2005,2006 Vincent "MooZ" Cruz
;; cruz.vincent@gmail.com
;;------------------------------------------------
HUC = 1
;;------------------------------------------------
;; LZSS
BUFFER_SIZE .equ 4096
BUFFER_SIZE_MASK .equ 4095
MATCH_LENGTH .equ 18
THRESHOLD .equ 2
;;------------------------------------------------
;; Compressed data size (user defined)
DATA_SIZE .equ 17086
;;------------------------------------------------
;; mkit/huc includes
.include "startup.asm"
.data
.bank DATA_BANK
.code
;;------------------------------------------------
;; Compressed data/palette/bat
.data
.dw $0
_data:
.incbin "love.lzss"
.code
.data
.dw $0
_pal:
.incpal "love.pcx",0
.code
.data
.dw $0
_bat:
.incbat "love.pcx",4096,0,0,40,25
;;------------------------------------------------
.code
;;------------------------------------------------
;; variables
;;------------------------------------------------
.zp
;; lzss vars
c: .ds 1
j: .ds 1
k: .ds 1
i: .ds 2
size: .ds 2
r: .ds 2
flags: .ds 2
data_ptr: .ds 2
idx: .ds 1
word: .ds 2
;;------------------------------------------------
;; main [begin]
;;------------------------------------------------
.code
.proc _main
main:
__ldwi #4096
call _gfx_init
__ldwi #1
call _set_screen_size
; set horizontale resolution
__ldwi #320
__stw _ax
call _set_xres.1
; shutdown display
; load palette
set_bgpal #0, _pal, #16
; load bat
batcpy #$0, _bat, #40, #25
; load picture
lda #low(DATA_SIZE)
sta size
lda #high(DATA_SIZE)
sta size+1
call load_picture
jsr _disp_on
; main loop
.mainloop:
vsync
bra .mainloop
rts ; a bit useless ;)
.endp
;;------------------------------------------------
;; main [end]
;;------------------------------------------------
;;------------------------------------------------
;; load picture [begin]
;;------------------------------------------------
.proc _load_picture
load_picture:
stz <_di
lda #$10
sta <_di+1
jsr set_write
; LZSS
; clear text_buffer array
stz <i
stz <i+1
; initialize var
; flags = 0
stz <flags
stz <flags+1
; data_ptr = 0
stz <data_ptr
stz <data_ptr+1
; idx = 0
stz <idx
; r = BUFFER_SIZE - MATCH_LENGTH
lda #low(4078)
sta <r
lda #high(4078)
sta <r+1
; for(i=0; i<4078; ++i)
; text_buffer[i] = 0
tai i, text_buffer, r
lzss:
; flags >>= 1
lsr <flags+1
ror <flags
; if((flags & 256) == 0)
bbs0 <flags+1, lzss_1
lzss_0:
; if(data_ptr >= DATASIZE) break;
lzss_next .macro
lda <data_ptr+1
cmp <size+1
bcc lzss_b\@
bne lzss_a\@
lda <data_ptr
cmp <size
bcc lzss_b\@
lzss_a\@:
jmp lzss_end
lzss_b\@:
.endm
lzss_next
; c = g_Data[g_DataPtr++]
lzss_getbyte .macro
__ldw <data_ptr
__farptr_i _data
__fgetb
stx \1
incw <data_ptr
.endm
lzss_getbyte <c
; flags = 0xFF00 | c
lda <c
sta <flags
lda #$ff
sta <flags+1
lzss_1:
; if(flags & 1)
bbs0 <flags, lzss_2
jmp lzss_3
lzss_2:
; if(data_ptr => DATASIZE)
lzss_next
; c = g_Data[g_DataPtr++]
lzss_getbyte <c
; write word
; if(!(idx & 1)) {
; ++idx;
; word = c;
; }
; else {
; video_data_l = word;
; video_data_h = word;
; idx = 0;
; }
lzss_write_word .macro
bbs0 <idx,lzss_write_\@
inc <idx
lda <c
sta <word
jmp lzss_nowrite_\@
lzss_write_\@:
stz <idx
lda <word
sta video_data_l
lda <c
sta video_data_h
lzss_nowrite_\@:
.endm
lzss_write_word
; text_buffer[r] = c;
__ldwi text_buffer
__addw <r
__stw <__ptr
lda <c
sta [__ptr]
; ++r;
incw <r
; r &= BUFFER_SIZE_MASK
lda <r+1
and #HIGH(BUFFER_SIZE_MASK)
sta <r+1
jmp lzss_4
lzss_3:
; if(data_ptr => DATASIZE)
lzss_next
; i = g_Data[g_DataPtr++]
lzss_getbyte <i
; if(data_ptr => DATASIZE)
lzss_next
; j = g_Data[g_DataPtr++]
lzss_getbyte <j
; i |= (lzssj | 0xF0) << 4
lda <j
lsr A
lsr A
lsr A
lsr A
sta <i+1
; j = (j & 00F) + THRESHOLD
lda <j
and #15
inc A
inc A
sta <j
; for(k=0; k<=j; ++k)
stz <k
lzss_3e:
; c = g_TextBuffer[(i + k) & BUFFER_SIZE_MASK];
clx
lda <k
add <i
sax
adc <i+1
and #high(4095)
sax
add #low(text_buffer)
sta <__ptr
sax
adc #high(text_buffer)
sta <__ptr+1
lda [__ptr]
sta <c
; write word
lzss_write_word
; text_buffer[r] = c;
__ldwi text_buffer
__addw <r
__stw <__ptr
lda <c
sta [__ptr]
; ++r;
incw <r
; r &= BUFFER_SIZE_MASK
lda <r+1
and #HIGH(BUFFER_SIZE_MASK)
sta <r+1
inc <k
lda <j
cmp <k
bcc lzss_3g
jmp lzss_3e
lzss_3g:
lzss_4:
jmp lzss
lzss_end:
rts
.endp
;; load picture [end]
;;------------------------------------------------
;;------------------------------------------------
;; Ring buffer declaration
;;------------------------------------------------
.bss
text_buffer: .ds 4113 ; BUFFER_SIZE + MATCH_LENGTH - 1
__arg:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment