aboutsummaryrefslogtreecommitdiff
path: root/lib/cpcrslib/cpc_Uncrunch.s
blob: 7eba8c3514f8da52ed8712ee47ca3e2b0f0544d4 (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
; ******************************************************
; **       Librer�a de rutinas SDCC para Amstrad CPC  **
; **       Ra�l Simarro (Artaburu)    -   2009, 2012  **
; ******************************************************


;*************************************
; UNCRUNCH
;*************************************


.globl _cpc_Uncrunch

_cpc_Uncrunch::
; datos necesarios que vienen en la pila:
; ORIGEN	HL
; DESTINO	DE

	;Ojo, para que el pucrunch funcione hay que coger y quitar el salto de las interrupciones.
	DI
	LD HL,(#0X0038)
	LD (#datos_int),HL

	LD HL,#0X00C9
	LD (#0x0038),HL
	EI

;POP AF
;POP HL
;POP DE
;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
		

pucrunch:
   PUSH   DE         ; destination pointer to 2nd register 
   EXX            ; set 
   POP   DE 

   
   PUSH   HL 
   PUSH   DE 
   PUSH   BC 
   PUSH   AF 

   EXX 

        ; read the header self-modifying the 
        ; parameters straight into the code 
        ; skip useless data 
 
   
   LD BC,#6
   ADD HL,BC

   LD   A, (HL)         ; starting escape 
   INC   HL 
   LD   (#esc+1), A 

   INC   HL         ; skip useless data 
   INC   HL 

   LD   A, (HL)         ; number of escape bits 
   INC   HL 
   LD   (#escb0+1), A 
   LD   (#escb1+1), A 

   LD   B, A         ; 8 - escape bits 
   LD   A, #8 
   SUB   B 
   LD   (#noesc+1), A 

   LD   A, (HL)         ; maxGamma + 1 
   INC   HL 
   LD   (#mg+1), A 

   LD   B, A         ; 8 - maxGamma 
   LD   A, #9 
   SUB   B 
   LD   (#longrle+1), A 

   LD   A, (HL)         ; (1 << maxGamma) 
   INC   HL 
   LD   (#mg1+1), A 

   ADD   A, A         ; (2 << maxGamma) - 1 
   DEC   A 
   LD   (#mg21+1), A 

   LD   A, (HL)         ; extra lz77_0 position bits 
   INC   HL 
   LD   (#elzpb+1), A 

   INC   HL         ; skip useless data 
   INC   HL 

   LD   E, (HL)         ; RLE table length 
   LD   (#rlet+1), HL      ; RLE table pointer 
   INC   HL 
   LD   D, #0 
   ADD   HL, DE 

   LD   C, #0X80         ; start decompression 
   JP   loop_u 

newesc:
   ld   a, (#esc+1)      ; save old escape code 
   ld   d, a 

escb0:
   LD   B, #2         ; ** parameter 
   XOR   A         ; get new escape code 
   CALL   get_bits 
   LD   (#esc+1), A 

   LD   A, D 

noesc:
	LD   B, #6         ; ** parameter 
	CALL   get_bits      ; get more bits to complete a byte 
	
	EXX            ; output the byte 
	LD   (DE), A 
	INC   DE 
	EXX 

loop_u: 
	XOR   A 
escb1:
	LD   B, #2         ; ** parameter 
    CALL   get_bits      ; get escape code 
esc:   
	CP   #0         ; ** PARAMETER 
	JP   NZ, noesc 
	
	CALL   get_gamma      ; get length 
	EXX 
	LD   B, #0 
	LD   C, A 
	EXX 
	
	CP   #1 
	JP   NZ, lz77_0      ; lz77_0 
	
	XOR   A 
	CALL   get_bit 
	JP   NC, lz77_0_2      ; 2-byte lz77_0 
	
	CALL   get_bit 
	JP   NC, newesc      ; escaped literal byte 
	
	CALL   get_gamma      ; get length 
	EXX 
	LD   B, #1 
	LD   C, A 
	EXX 

mg1:   
	CP   #64         ; ** parameter 
	JP   C, chrcode      ; short RLE, get bytecode 

longrle:   
	LD   B, #2         ; ** parameter 
	CALL   get_bits      ; complete length LSB 
	EX   AF, AF' 
	
	CALL   get_gamma      ; length MSB 
	EXX 
	LD   B, A 
	EX   AF, AF' 
	LD   C, A 
	EXX 

chrcode:   
	CALL   get_gamma      ; get byte to repeat 

	PUSH   HL 
rlet:   
	LD   HL, #0X0000      ; ** parameter 
	LD   D, #0 
	LD   E, A 
	ADD   HL, DE 
	
	CP   #32 
	LD   A, (HL) 
	POP   HL 
	JP   C, dorle 
	
	LD   A, E         ; get 3 more bits to complete the 
	LD   B, #3         ; byte 
	CALL   get_bits 

dorle:  
	EXX            ; output the byte n times 
	INC   C 
dorlei:
	LD   (DE), A 
	INC   DE 
	DEC   C 
	JP   NZ, dorlei 
	DEC   B 
	JP   NZ, dorlei 
	EXX 
	JP   loop_u 

lz77_0:
   CALL   get_gamma      ; offset MSB 
mg21:
   CP   #127         ; ** parameter 

   ; ret   z 

   JP   Z, fin         ; EOF, return 

   DEC   A         ; (1...126 -> 0...125) 
elzpb:
   LD   B, #0         ; ** parameter 
   CALL   get_bits      ; complete offset MSB 

lz77_0_2:
   EX   AF, AF' 
   LD   B, #8         ; offset LSB 
   CALL   get_bits 
   CPL            ; xor'ed by the compressor 

   EXX            ; combine them into offset 
   LD   L, A 
   EX   AF, AF' 
   LD   H, A 
   INC   HL 

   XOR   A         ; CF = 0 

   PUSH   DE         ; (current output position) - (offset) 
   EX   DE, HL 
   SBC   HL, DE 
   POP   DE 

   INC   BC 

   LDIR            ; copy 
   EXX 
   JP   loop_u 

;## Get a bit from the source stream. 
;## Return    CF = result 
get_bit:
   SLA   C         ; shift next bit into CF 
   RET   NZ 
   LD   C, (HL)         ; get next byte 
   INC   HL         ; increase source stream pointer 
   RL   C         ; shift next bit into CF, bit0 = 1 
   RET 

;## Get multiple bits from the source stream. 
;## In        B = number of bits to get 
;## Return    A = result 
get_bits:  
   DEC   B 
   RET   M 
   SLA   C         ; shift next bit into CF 
   JP   NZ, gb1 
   LD   C, (HL)         ; get next byte 
   INC   HL         ; increase source stream pointer 
   RL   C         ; shift next bit into CF, bit0 = 1 
gb1:
   RLA            ; rotate next bit into A 
   JP   get_bits 

;## Get an Elias Gamma coded value from the source stream. 
;## Return    A = result 
get_gamma:  
	LD   B, #1 
mg:  
	LD   A, #7         ; ** parameter 
gg1:
	CALL   get_bit         ; get bits until 0-bit or max 
	JR   NC, gg2 
	INC   B 
	CP   B 
	JP   NZ, gg1 
gg2:
   LD   A, #1         ; GET THE ACTUAL VALUE 
   DEC   B 
   JP   get_bits 

fin:
   ; Restauramos los registros dobles y vuelta limpia 
   EXX 
   POP   AF 
   POP   BC 
   POP   DE 
   POP   HL 
   EXX 
   
   ;RET   
	DI
	LD HL,(#datos_int)
	LD (#0X0038),HL	;RESTAURO LA INTERRUPCI�N ORIGINAL
	EI
	RET   
datos_int:
	.DW #0