aboutsummaryrefslogtreecommitdiff
path: root/lib/cpcrslib/cpc_UnExoOpt.s
blob: 14197ccc3bbeeb7985440f2b4c4a4a4c4f47139c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
; ******************************************************
; **       Librer�a de rutinas SDCC para Amstrad CPC  **
; **       Ra�l Simarro (Artaburu)    -   2009, 2012  **
; ******************************************************


;*************************************
; UNEXO
;*************************************


; Exomizer 2 Z80 decoder
; by Metalbrain
;
; optimized by Antonio Villena
;
; compression algorithm by Magnus Lind

;input: 	hl=compressed data start
;		de=uncompressed destination start
;
;		you may change exo_mapbasebits to point to any free buffer


.globl _cpc_UnExo

_cpc_UnExo::

;	POP AF
;	POP HL	;DESTINATION ADDRESS
;	POP DE	;SPRITE DATA	
;	PUSH AF
	
	LD IX,#2
	ADD IX,SP
	LD e,2 (IX)
	LD d,3 (IX)	;DESTINO
   	LD l,0 (IX)
	LD h,1 (IX)	;TEXTO ORIGEN
		
	di
	call deexo
	ei
	ret

deexo:		
		ld	iy, #exo_mapbasebits
		ld	a,#128
		ld	b,#52
		push	de
exo_initbits:	
		ex	af,af'
		ld	a,b
		sub	#4
		and	#15
		jr	nz,exo_node1
		ld	de,#1		;DE=b2
exo_node1:	
			ld	c,#16
      		ex	af, af'
exo_get4bits:	
		call	exo_getbit
		rl	c
		jr	nc,exo_get4bits
		ld	(iy),c	;bits[i]=b1
		push	hl
		ld	hl,#1
		.db	#210		;3 bytes nop (JP NC)
exo_setbit:	
		add	hl,hl
		dec	c
		jr	nz,exo_setbit
		ld	52 (iy),e
		ld	104 (iy),d	;base[i]=b2
		add	hl,de
		ex	de,hl
		inc	iy
		pop	hl
		djnz	exo_initbits
		inc	c
exo_literalseq:	
		pop	de
exo_literalcopy:
		ldir			;copy literal(s)
exo_mainloop:	
		ld	c,#1
		call	exo_getbit	;literal?
		jr	c,exo_literalcopy
		ld	c,#255
exo_getindex:	
		inc	c
		call	exo_getbit
		jr	nc,exo_getindex
		bit	4,c
		jr	z,exo_continue
      	bit	0, c
		ret	z
		push	de
		ld	d,#16
		call	exo_getbits
		jr	exo_literalseq
exo_continue:	
		push	de
		call	exo_getpair
		push	bc
		pop	ix
		ld	de,#560  ;512+48	;1?
      		inc	b
      		djnz	exo_dontgo
      		dec	c
      		jr	z, exo_goforit
      		dec	c               ;2?
exo_dontgo:	
		ld	de,#1056 ;1024+32
		jr	z,exo_goforit
		ld	e,#16
exo_goforit:	
		call	exo_getbits
      		ex	af, af'
		ld	a,e
		add	a,c
		ld	c,a
      		ex	af, af'
		call	exo_getpair	;bc=offset
		pop	de		;de=destination
		push	hl		
		ld	h,d
		ld	l,e
		sbc	hl,bc		;hl=origin
		push	ix
		pop	bc		;bc=lenght
		ldir
		pop	hl		;Keep HL, DE is updated
		jr	exo_mainloop	;Next!

exo_getpair:	
		ld	iy,#exo_mapbasebits
		ld	b,#0
		add	iy,bc
		ld	d,(iy)
		call	exo_getbits
      		push	hl
      		ld	l, 52 (iy)
      		ld	h, 104 (iy)
      		add	hl, bc          ;Always clear C flag
      		ld	b, h
      		ld	c, l
      		pop	hl
		ret

exo_getbits:	
		ld	bc,#0		;get D bits in BC
exo_gettingbits:
		dec	d
		ret	m
		call	exo_getbit
		rl	c
		rl	b
		jr	exo_gettingbits

exo_getbit:	
			add	a, a		;get one bit
      		ret	nz
      		ld	a, (hl)
      		inc	hl
      		adc	a, a
      		ret

exo_mapbasebits:
			;defs	156	;tables for bits, baseL, baseH
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0
			.db #0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0,#0