1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MI
3 File: mi_uncomp_stream.c
4
5 Copyright 2003-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/mi/stream.h>
19 #include <nitro/mi/uncompress.h>
20 #include <nitro/mi/uncomp_stream.h>
21
22 // #define MI_USE_STRB
23
24 /*---------------------------------------------------------------------------*
25 Name: MI_InitUncompContextRL
26
27 Description: Initializes the streaming decompression context for run-length compressed data.
28
29
30 Arguments: context Pointer to the run-length uncompressed context
31 dest Destination address for uncompressed data
32 header Pointer to the start data for the compressed data
33
34 Returns: Can get the data size after decompression.
35
36 *---------------------------------------------------------------------------*/
MI_InitUncompContextRL(MIUncompContextRL * context,u8 * dest,const MICompressionHeader * header)37 void MI_InitUncompContextRL(MIUncompContextRL *context, u8 *dest, const MICompressionHeader *header)
38 {
39 context->destp = dest;
40 context->destCount = (s32)header->destSize;
41 context->flags = 0;
42 context->length = 0;
43 context->destTmp = 0;
44 context->destTmpCnt = 0;
45 }
46
47
48 /*---------------------------------------------------------------------------*
49 Name: MI_InitUncompContextLZ
50
51 Description: Initializes the streaming decompression context for LZ-compressed data.
52
53 Arguments: context Pointer to the LZ uncompressed context
54 dest Destination address for uncompressed data
55 header Pointer to the start data for the compressed data
56
57 *---------------------------------------------------------------------------*/
MI_InitUncompContextLZ(MIUncompContextLZ * context,u8 * dest,const MICompressionHeader * header)58 void MI_InitUncompContextLZ(MIUncompContextLZ *context, u8 *dest, const MICompressionHeader *header)
59 {
60 context->destp = dest;
61 context->destCount = (s32)header->destSize;
62 context->flags = 0;
63 context->flagIndex = 0;
64 context->length = 0;
65 context->lengthFlg = 3;
66 context->destTmp = 0;
67 context->destTmpCnt = 0;
68 context->exFormat = (u8)( (header->compParam == 0)? 0U : 1U );
69 }
70
71
72 /*---------------------------------------------------------------------------*
73 Name: MI_InitUncompContextHuffman
74
75 Description: Initializes the streaming decompression context for Huffman-compressed data.
76
77 Arguments: context Pointer to the Huffman uncompressed context
78 dest Destination address for uncompressed data
79 header Pointer to the start data for the compressed data
80
81 *---------------------------------------------------------------------------*/
MI_InitUncompContextHuffman(MIUncompContextHuffman * context,u8 * dest,const MICompressionHeader * header)82 void MI_InitUncompContextHuffman(MIUncompContextHuffman *context, u8 *dest,
83 const MICompressionHeader *header)
84 {
85 context->destp = dest;
86 context->destCount = (s32)header->destSize;
87 context->bitSize = (u8)header->compParam;
88 context->treeSize = -1;
89 context->treep = &context->tree[0];
90 context->destTmp = 0;
91 context->destTmpCnt = 0;
92 context->srcTmp = 0;
93 context->srcTmpCnt = 0;
94 }
95
96
97 //---- This code will be compiled in ARM-Mode
98 #include <nitro/code32.h>
99 /*---------------------------------------------------------------------------*
100 Name: MI_ReadUncompRL8
101
102 Description: Performs streaming decompression of run-length compressed data.
103 Data is written in units of 8 bits. Data cannot be directly uncompressed to VRAM.
104
105 Arguments: context Pointer to the run-length uncompressed context
106 data Pointer to the next data
107 len Data size
108
109 Returns: Size of remaining uncompressed data.
110
111 *---------------------------------------------------------------------------*/
MI_ReadUncompRL8(register MIUncompContextRL * context,register const u8 * data,register u32 len)112 asm s32 MI_ReadUncompRL8( register MIUncompContextRL *context, register const u8* data, register u32 len )
113 {
114 stmfd sp!, {r4-r8}
115 // r0: context, r1: data, r2: len
116 ldr r3, [r0, #MIUncompContextRL.destp] // r3: destp = context->destp;
117 ldr r4, [r0, #MIUncompContextRL.destCount] // r4: destCount = context->destCount;
118 ldrb r5, [r0, #MIUncompContextRL.flags] // r5: flags = context->flags;
119 ldrh r6, [r0, #MIUncompContextRL.length] // r6: length = context->length
120
121 @41:
122 cmp r4, #0 // while ( destCount > 0 )
123 ble @49
124
125 tst r5, #0x80 // if ( ! flags & 0x80 ) {
126 bne @43
127
128 @42:
129 cmp r6, #0 // while ( length > 0 ) {
130 ble @45
131
132 sub r6, r6, #1 // length--;
133 ldrb r7, [r1], #1 // *destp++ = *data++;
134 sub r4, r4, #1 // destCount--; // <- avoid pipe stall
135 #ifdef MI_USE_STRB
136 strb r7, [r3], #1
137 #else
138 swpb r8, r7,[r3]
139 add r3, r3, #1
140 #endif
141 subs r2, r2, #1 // len--;
142 beq @49 // if ( len == 0 ) { return destCount }
143 b @42 // }
144
145 @43: // } else if ( length > 0 ) {
146 cmp r6, #0
147 ble @45
148
149 ldrb r7, [r1], #1 // r7: srcTmp = *data++;
150 @44: // do {
151 sub r4, r4, #1 // destCount--; // <- avoid pipe stall
152 #ifdef MI_USE_STRB
153 strb r7, [r3], #1 // *destp++ = srcTmp;
154 #else
155 swpb r8, r7, [r3]
156 add r3, r3, #1
157 #endif
158 subs r6, r6, #1 // } while ( --length > 0 )
159 bgt @44
160
161 subs r2, r2, #1 // len--;
162 beq @49 // if ( len == 0 ) { return destCount }
163 // }
164 @45:
165 ldrb r5, [r1], #1 // flags = *data++;
166 and r6, r5, #0x7F // length = flags & 0x7F
167 tst r5, #0x80 // if ( flags & 0x80 ) { length += 3 }
168 addne r6, r6, #2 //
169 add r6, r6, #1 // else { length += 1 }
170
171 subs r2, r2, #1 // len--;
172 bne @41 // if ( len == 0 ) { return destCount }
173 // }
174 @49:
175 str r3, [r0, #MIUncompContextRL.destp] // context->destp = destp;
176 str r4, [r0, #MIUncompContextRL.destCount] // context->destCount = destCount;
177 strb r5, [r0, #MIUncompContextRL.flags] // context->flags = flags;
178 strh r6, [r0, #MIUncompContextRL.length] // context->length = length;
179 mov r0, r4
180
181 ldmfd sp!, {r4-r8}
182 bx lr
183 }
184
185
186 /*---------------------------------------------------------------------------*
187 Name: MI_ReadUncompRL16
188
189 Description: Performs streaming decompression of run-length compressed data.
190 Data is written in 16-bit units. Data can be directly uncompressed to VRAM, but this is slower than MI_ReadUncompRL8.
191
192
193 Arguments: context Pointer to the run-length uncompressed context
194 data Pointer to the next data
195 len Data size
196
197 Returns: Size of remaining uncompressed data.
198
199 *---------------------------------------------------------------------------*/
MI_ReadUncompRL16(register MIUncompContextRL * context,register const u8 * data,register u32 len)200 asm s32 MI_ReadUncompRL16( register MIUncompContextRL *context, register const u8* data, register u32 len )
201 {
202 stmfd sp!, {r4-r9}
203 // r0: context, r1: data, r2: len
204 ldr r3, [r0, #MIUncompContextRL.destp] // r3: destp = context->destp;
205 ldr r4, [r0, #MIUncompContextRL.destCount] // r4: destCount = context->destCount;
206 ldrb r5, [r0, #MIUncompContextRL.flags] // r5: flags = context->flags;
207 ldrh r6, [r0, #MIUncompContextRL.length] // r6: length = context->length;
208 ldrh r7, [r0, #MIUncompContextRL.destTmp] // r7: destTmp = context->destTmp;
209 ldrb r8, [r0, #MIUncompContextRL.destTmpCnt] // r8: destTmpCnt = context->destTmpCnt;
210
211 @41:
212 cmp r4, #0 // while ( destCount > 0 )
213 ble @49
214
215 tst r5, #0x80 // if ( ! flags & 0x80 ) {
216 bne @44
217
218 @42:
219 cmp r6, #0 // while ( length > 0 ) {
220 ble @47
221
222 ldrb r9, [r1], #1 // destTmp |= (*data++) << destTmpCnt;
223 sub r6, r6, #1 // length--; // <- avoid pipe stall
224 orr r7, r7, r9, lsl r8
225 add r8, r8, #8 // destTmpCnt += 8;
226 cmp r8, #16 // if ( destTmpCnt == 16 ) {
227 bne @43
228 strh r7, [r3], #2 // *(u16*)destp = destTmp; destp += 2;
229 mov r7, #0 // destTmp = 0;
230 mov r8, #0 // destTmpCnt = 0;
231 sub r4, r4, #2 // destCount -= 2;
232 @43: // }
233 subs r2, r2, #1 // len--;
234 beq @49 // if ( len == 0 ) { return destCount; }
235 b @42 // }
236
237 @44: // } else if ( length > 0 ) {
238 cmp r6, #0
239 ble @47
240
241 ldrb r9, [r1], #1 // r9: srcTmp = *data++;
242 @45: // do {
243 orr r7, r7, r9, lsl r8 // destTmp |= srcTmp << destTmpCnt;
244 add r8, r8, #8 // destTmpCnt += 8;
245 cmp r8, #16 // if ( destTmpCnt == 16 ) {
246 bne @46
247 strh r7, [r3], #2 // *(u16*)destp = destTmp; destp += 2;
248 mov r7, #0 // destTmp = 0;
249 mov r8, #0 // destTmpCnt = 0;
250 sub r4, r4, #2 // destCount -= 2;
251 // }
252 @46:
253 subs r6, r6, #1 // } while (--length > 0);
254 bgt @45
255
256 subs r2, r2, #1 // len--;
257 beq @49 // if ( len == 0 ) { return destCount; }
258 // }
259 @47:
260 ldrb r5, [r1], #1 // flags = *data++;
261 and r6, r5, #0x7F // length = flags & 0x7F
262 tst r5, #0x80 // if ( flags & 0x80 ) { length += 3 }
263 addne r6, r6, #2 //
264 add r6, r6, #1 // else { length += 1 }
265
266 subs r2, r2, #1 // len--;
267 bne @41 // if ( len == 0 ) { return destCount }
268 // }
269 @49:
270 str r3, [r0, #MIUncompContextRL.destp] // context->destp = destp;
271 str r4, [r0, #MIUncompContextRL.destCount] // context->destCount = destCount;
272 strb r5, [r0, #MIUncompContextRL.flags] // context->flags = flags;
273 strh r6, [r0, #MIUncompContextRL.length] // context->length = length;
274 strh r7, [r0, #MIUncompContextRL.destTmp] // context->destTmp = destTmp;
275 strb r8, [r0, #MIUncompContextRL.destTmpCnt] // context->destTmpCnt = destTmpCnt;
276 mov r0, r4
277
278 ldmfd sp!, {r4-r9}
279 bx lr
280 }
281
282 /*---------------------------------------------------------------------------*
283 Name: MI_ReadUncompLZ8
284
285 Description: Performs streaming decompression of LZ-compressed data.
286 Data is written in units of 8 bits. Data cannot be directly uncompressed to VRAM.
287
288 Arguments: context Pointer to the LZ uncompressed context
289 data Pointer to the next data
290 len Data size
291
292 Returns: Size of remaining uncompressed data.
293
294 *---------------------------------------------------------------------------*/
MI_ReadUncompLZ8(register MIUncompContextLZ * context,register const u8 * data,register u32 len)295 asm s32 MI_ReadUncompLZ8( register MIUncompContextLZ *context, register const u8* data, register u32 len )
296 {
297 stmfd sp!, {r4-r11}
298 // r0: context, r1: data, r2: len
299 ldr r3, [r0, #MIUncompContextLZ.destp] // r3: destp = context->destp;
300 ldr r4, [r0, #MIUncompContextLZ.destCount] // r4: destCount = context->destCount;
301 ldrb r5, [r0, #MIUncompContextLZ.flags] // r5: flags = context->flags;
302 ldrb r6, [r0, #MIUncompContextLZ.flagIndex] // r6: flagIndex = context->flagIndex;
303 ldr r7, [r0, #MIUncompContextLZ.length] // r7: length = context->length
304 ldrb r8, [r0, #MIUncompContextLZ.lengthFlg] // r8: lengthFlg = context->lengthFlg;
305 ldrb r11, [r0, #MIUncompContextLZ.exFormat] // r11: exFormat = context->exFormat;
306 @21:
307 cmp r4, #0 // while (destCount > 0) {
308 ble @29
309
310 cmp r6, #0 // wihle ( flagIndex > 0 ) {
311 beq @28
312 @22
313 cmp r2, #0 // if ( len == 0 ) { return destCount }
314 beq @29
315
316 tst r5, #0x80 // if ( ! flags & 0x80 ) {
317 bne @23
318 ldrb r9, [r1], #1 // *destp++ = *srcp++;
319 sub r4, r4, #1 // destCount--; // <- avoid pipe stall
320 sub r2, r2, #1 // len--;
321 #ifdef MI_USE_STRB
322 strb r9, [r3], #1
323 #else
324 swpb r9, r9, [r3]
325 add r3, r3, #1
326 #endif
327 b @26
328 @23: // } else {
329 cmp r8, #0 // while ( lengthFlg > 0 ) {
330 beq @24 // if ( exFormat ) {
331 cmp r11, #1
332 bne @23_9
333
334 subs r8, r8, #1 // --lengthFlg;
335 beq @23_7 // switch ( lengthFlg ) {
336 cmp r8, #1
337 beq @23_6
338 // case 2:
339 ldrb r7, [r1], #1 // length = *data++;
340 tst r7, #0xE0
341 beq @23_4
342 // if ( (length >> 4) > 1 ) {
343 add r7, r7, #0x10 // length += (1 << 4);
344 mov r8, #0 // lengthFlg = 0;
345 b @23_10 // }
346 @23_4: // else {
347 mov r10, #0x110 // length += (0xF + 2) << 4;
348 tst r7, #0x10 //
349 beq @23_5 // if ( (length >> 4) == 1 ) {
350
351 and r7, r7, #0xF // length = (length & 0x0F) << 16;
352 add r10, r10, #0x1000 // length += (0xFF + 1) << 4;
353 add r7, r10, r7, lsl #16
354 b @23_8 // }
355 @23_5: // else {
356 and r7, r7, #0xF // length = (length & 0xF) << 8;
357 add r7, r10, r7, lsl #8 // lengthFlg = 1;
358 mov r8, #1 // }
359 b @23_8 // } break;
360 @23_6: // case 1:
361 ldrb r10, [r1], #1 // length += (*data++) << 8;
362 add r7, r7, r10, lsl #8 // break;
363 b @23_8 //
364 @23_7: // case 0:
365 ldrb r10, [r1], #1 // length += *data++;
366 add r7, r7, r10 // break;
367 b @23_10
368 @23_8: // }
369 subs r2, r2, #1 // if ( --len == 0 ) { return destCount; }
370 beq @29 // }
371 b @23
372
373 @23_9: // else {
374 ldrb r7, [r1], #1 // length = *data++;
375 add r7, r7, #0x30 // length += (3 << 4);
376 mov r8, #0 // lengthFlg = 0;
377 @23_10:
378 subs r2, r2, #1 // if ( --len == 0 ) { return destCount }
379 beq @29 // }
380 // }
381 @24:
382 and r9, r7, #0xF // r9: offset = ( length & 0xF ) << 8;
383 mov r10, r9, lsl #8
384 ldrb r9, [r1], #1 // offset = ( offset | *data++ ) + 1;
385 mov r8, #3 // lengthFlg = 3; // <- avoid pipe stall
386 sub r2, r2, #1 // len--;
387 orr r9, r9, r10
388 add r9, r9, #1
389 movs r7, r7, asr #4 // length = length >> 4;
390 beq @26 // while ( length > 0 ) {
391 @25:
392 ldrb r10, [r3, -r9] // *destp++ = *(destp - offset);
393 sub r4, r4, #1 // destCount--; // <- avoid pipe stall
394 #ifdef MI_USE_STRB
395 strb r10, [r3], #1
396 #else
397 swpb r10, r10, [r3]
398 add r3, r3, #1
399 #endif
400 subs r7, r7, #1 // length--;
401 bgt @25 // }
402 @26: // }
403 cmp r4, #0 // if ( destCount == 0 ) { return destCount }
404 beq @29
405 mov r5, r5, lsl #1 // flags <<= 1;
406 subs r6, r6, #1 // flagIndex--;
407 bne @22 // }
408
409 @28:
410 cmp r2, #0 // if ( len == 0 ) { return destCount }
411 beq @29
412 ldrb r5, [r1], #1 // flags = *data++;
413 mov r6, #8 // flagIndex = 8;
414 sub r2, r2, #1 // len--
415 b @21 // }
416
417 @29:
418 str r3, [r0, #MIUncompContextLZ.destp] // context->destp = destp;
419 str r4, [r0, #MIUncompContextLZ.destCount] // context->destCount = destCount;
420 strb r5, [r0, #MIUncompContextLZ.flags] // context->flags = flags;
421 strb r6, [r0, #MIUncompContextLZ.flagIndex] // context->flagIndex = flagIndex;
422 str r7, [r0, #MIUncompContextLZ.length] // context->length = length;
423 strb r8, [r0, #MIUncompContextLZ.lengthFlg] // context->lengthFlg = lengthFlg;
424 strb r11, [r0, #MIUncompContextLZ.exFormat] // context->exFormat = exFormat
425 mov r0, r4 // return destCount
426
427 ldmfd sp!, {r4-r11}
428 bx lr
429 }
430
431
432 /*---------------------------------------------------------------------------*
433 Name: MI_ReadUncompLZ16
434
435 Description: Performs streaming uncompression of LZ compressed data.
436 Data is written in 16-bit units. Data can be directly uncompressed to VRAM, as well, but this is slower than MI_ReadUncompLZ8.
437
438
439 Arguments: context Pointer to the LZ uncompressed context
440 data Pointer to the next data
441 len Data size
442
443 Returns: Size of remaining uncompressed data.
444
445 *---------------------------------------------------------------------------*/
MI_ReadUncompLZ16(register MIUncompContextLZ * context,register const u8 * data,register u32 len)446 asm s32 MI_ReadUncompLZ16( register MIUncompContextLZ *context, register const u8* data, register u32 len )
447 {
448 stmfd sp!, {r4-r12,lr}
449 // r0: context, r1: data, r2: len
450 ldr r3, [r0, #MIUncompContextLZ.destp] // r3: destp = context->destp;
451 ldr r4, [r0, #MIUncompContextLZ.destCount] // r4: destCount = context->destCount;
452 ldrb r5, [r0, #MIUncompContextLZ.flags] // r5: flags = context->flags;
453 ldrb r6, [r0, #MIUncompContextLZ.flagIndex] // r6: flagIndex = context->flagIndex;
454 ldr r7, [r0, #MIUncompContextLZ.length] // r7: length = context->length
455 ldrb r8, [r0, #MIUncompContextLZ.lengthFlg] // r8: lengthFlg = context->lengthFlg;
456 ldrh r9, [r0, #MIUncompContextLZ.destTmp] // r9: destTmp = context->destTmp;
457 ldrb r10, [r0, #MIUncompContextLZ.destTmpCnt] // r10: destTmpCnt = context->destTmpCnt;
458 ldrb r14, [r0, #MIUncompContextLZ.exFormat] // r14: exFormat = context->exFormat;
459
460 stmfd sp!, {r0}
461
462 @21:
463 cmp r4, #0 // while (destCount > 0) {
464 ble @29
465
466 cmp r6, #0 // wihle ( flagIndex > 0 ) {
467 beq @28
468 @22
469 cmp r2, #0 // if ( len == 0 ) { return destCount }
470 beq @29
471
472 tst r5, #0x80 // if ( ! flags & 0x80 ) {
473 bne @23
474 ldrb r11, [r1], #1 // destTmp |= (*data++) << destTmpCnt;
475 sub r2, r2, #1 // len--; // <- avoid pipe stall
476 orr r9, r9, r11, lsl r10
477 add r10, r10, #8 // destTmpCnt += 8;
478 cmp r10, #16 // if ( destTmpCnt == 16 ) {
479 bne @26
480 strh r9, [r3], #2 // *(u16*)destp = destTmp; destp += 2;
481 sub r4, r4, #2 // destCount -= 2;
482 mov r9, #0 // destTmp = 0;
483 mov r10, #0 // destTmpCount = 0;
484 // }
485 b @26
486 @23: // } else {
487 cmp r8, #0 // while ( lengthFlg > 0 ) {
488 beq @24 // if ( exFormat ) {
489 cmp r14, #1
490 bne @23_9
491
492 subs r8, r8, #1 // --lengthFlg;
493 beq @23_7 // switch ( lengthFlg ) {
494 cmp r8, #1
495 beq @23_6
496 // case 2:
497 ldrb r7, [r1], #1 // length = *data++;
498 tst r7, #0xE0
499 beq @23_4
500 // if ( (length >> 4) > 1 ) {
501 add r7, r7, #0x10 // length += (1 << 4);
502 mov r8, #0 // lengthFlg = 0;
503 b @23_10 // }
504 @23_4: // else {
505 mov r11, #0x110 // length += (0xF + 2) << 4;
506 tst r7, #0x10 //
507 beq @23_5 // if ( (length >> 4) == 1 ) {
508
509 and r7, r7, #0xF // length = (length & 0x0F) << 16;
510 add r11, r11, #0x1000 // length += (0xFF + 1) << 4;
511 add r7, r11, r7, lsl #16
512 b @23_8 // }
513 @23_5: // else {
514 and r7, r7, #0xF // length = (length & 0xF) << 8;
515 add r7, r11, r7, lsl #8 // lengthFlg = 1;
516 mov r8, #1 // }
517 b @23_8 // } break;
518 @23_6: // case 1:
519 ldrb r11, [r1], #1 // length += (*data++) << 8;
520 add r7, r7, r11, lsl #8 // break;
521 b @23_8 //
522 @23_7: // case 0:
523 ldrb r11, [r1], #1 // length += *data++;
524 add r7, r7, r11 // break;
525 b @23_10
526 @23_8: // }
527 subs r2, r2, #1 // if ( --len == 0 ) { return destCount; }
528 beq @29 // }
529 b @23
530
531 @23_9: // else {
532 ldrb r7, [r1], #1 // length = *data++;
533 add r7, r7, #0x30 // length += (3 << 4);
534 mov r8, #0 // lengthFlg = 0;
535 @23_10:
536 subs r2, r2, #1 // if ( --len == 0 ) { return destCount }
537 beq @29 // }
538 // }
539 @24:
540 and r11, r7, #0xF // r11: offset = ( length & 0xF ) << 8;
541 mov r12, r11, lsl #8
542 ldrb r11, [r1], #1 // offset = ( offset | *data++ ) + 1;
543 mov r8, #3 // lengthFlg = 3; // <- avoid pipe stall
544 sub r2, r2, #1 // len--
545 orr r11, r11, r12
546 add r11, r11, #1
547 movs r7, r7, asr #4 // length = length >> 4;
548 beq @26 // while ( length > 0 ) {
549 @25:
550 subs r12, r11, r10, lsr #3 // r12: offsetTmp = offset - ( destTmpCnt / 8 );
551 bne @25_1 // if ( offsetTmp == 0 ) {
552 and r0, r9, #0xF // destTmp |= ( destTmp & 0xF ) << 8;
553 orr r9, r9, r0, lsl #8
554 b @25_2
555 @25_1: // } else {
556 add r0, r12, #1 // r0: tmpData = *(u16*)( destp - ( (offsetTmp + 1) & ~0x1 ) )
557 mov r0, r0, lsr #1
558 sub r0, r3, r0, lsl #1
559 ldrh r0, [r0, #0]
560 tst r12, #1 // if ( offsetTmp & 1 ) {
561 movne r0, r0, lsr #8 // tmpData >>= 8;
562 // } else {
563 andeq r0, r0, #0xFF // tmpData &= 0xFF;
564 // }
565 orr r9, r9, r0, lsl r10 // destTmp |= tmpData << destTmpCnt;
566 @25_2: // }
567 add r10, r10, #8 // destTmpCnt += 8;
568 cmp r10, #16 // if ( destTmpCnt == 16 ) {
569 bne @25_3
570 strh r9, [r3], #2 // *(u16*)destp = destTmp; destp += 2;
571 sub r4, r4, #2 // destCount -= 2;
572 mov r9, #0 // destTmp = 0;
573 mov r10, #0 // destTmpCnt = 0;
574 // }
575 @25_3:
576 subs r7, r7, #1 // length--;
577 bgt @25 // }
578 @26: // }
579 cmp r4, #0 // if ( destCount == 0 ) { return destCount }
580 beq @29
581 mov r5, r5, lsl #1 // flags <<= 1;
582 subs r6, r6, #1 // flagIndex--;
583 bne @22 // }
584
585 @28:
586 cmp r2, #0 // if ( len == 0 ) { return destCount }
587 beq @29
588 ldrb r5, [r1], #1 // flags = *data++;
589 mov r6, #8 // flagIndex = 8;
590 sub r2, r2, #1 // len--
591 b @21 // }
592
593 @29:
594 ldmfd sp!, {r0}
595 str r3, [r0, #MIUncompContextLZ.destp] // context->destp = destp;
596 str r4, [r0, #MIUncompContextLZ.destCount] // context->destCount = destCount;
597 strb r5, [r0, #MIUncompContextLZ.flags] // context->flags = flags;
598 strb r6, [r0, #MIUncompContextLZ.flagIndex] // context->flagIndex = flagIndex;
599 str r7, [r0, #MIUncompContextLZ.length] // context->length = length;
600 strb r8, [r0, #MIUncompContextLZ.lengthFlg] // context->lengthFlg = lengthFlg;
601 strh r9, [r0, #MIUncompContextLZ.destTmp] // context->destTmp = destTmp;
602 strb r10, [r0, #MIUncompContextLZ.destTmpCnt] // context->destTmpCnt = destTmpCnt;
603 strb r14, [r0, #MIUncompContextLZ.exFormat] // context->exFormat = exFormat;
604 mov r0, r4 // return destCount
605
606 ldmfd sp!, {r4-r12,lr}
607 bx lr
608 }
609
610
611 /*---------------------------------------------------------------------------*
612 Name: MI_ReadUncompHuffman
613
614 Description: Performs streaming decompression of Huffman-compressed data.
615
616 Arguments: context Pointer to the Huffman uncompressed context
617 data Pointer to the next data
618 len Data size
619
620 Returns: Size of remaining uncompressed data.
621
622 *---------------------------------------------------------------------------*/
623 #define TREE_END_MASK 0x80
624
MI_ReadUncompHuffman(register MIUncompContextHuffman * context,register const u8 * data,register u32 len)625 asm s32 MI_ReadUncompHuffman( register MIUncompContextHuffman *context, register const u8* data, register u32 len )
626 {
627 stmfd sp!, {r4-r12, lr}
628 // r0: context, r1: data, r2: len
629 ldr r3, [r0, #MIUncompContextHuffman.destp] // r3: destp = context->destp;
630 ldr r4, [r0, #MIUncompContextHuffman.destCount] // r4: destCount = context->destCount;
631 ldr r5, [r0, #MIUncompContextHuffman.treep] // r5: treep = context->treep;
632 ldr r6, [r0, #MIUncompContextHuffman.srcTmp] // r6: srcTmp = context->srcTmp;
633 ldr r7, [r0, #MIUncompContextHuffman.destTmp] // r7: destTmp = context->destTmp;
634 ldrsh r8, [r0, #MIUncompContextHuffman.treeSize] // r8: treeSize = context->treeSize;
635 ldrb r9, [r0, #MIUncompContextHuffman.srcTmpCnt] // r9: srcTmpCnt = context->srcTmpCnt;
636 ldrb r10, [r0, #MIUncompContextHuffman.destTmpCnt] // r10: destTmpCnt = context->destTmpCnt;
637 ldrb r11, [r0, #MIUncompContextHuffman.bitSize] // r11: bitSize = context->bitSize;
638
639 cmp r8, #0 // if ( treeSize < 0 ) {
640 beq @12
641 bgt @11
642 ldrb r8, [r1], #1 // treeSize = ( *data + 1 ) * 2 - 1;
643 sub r2, r2, #1 // len--; // <- avoid pipe stall
644 strb r8, [r5], #1 // *treep++ = *data++;
645 add r8, r8, #1
646 mov r8, r8, lsl #1
647 sub r8, r8, #1
648 @11: // }
649 // while ( treeSize > 0 ) {
650 cmp r2, #0 // if ( len == 0 ) { return destCount; }
651 beq @19
652 ldrb r12, [r1], #1 // *treep++ = *data++;
653 sub r2, r2, #1 // len--; // <- avoid pipe stall
654 strb r12, [r5], #1
655 subs r8, r8, #1 // treeSize--;
656 addeq r5, r0, #MIUncompContextHuffman.tree[1] // if ( treeSize == 0 ) { treep = &context->tree[ 1 ]; }
657 bgt @11 // }
658 @12:
659 cmp r4, #0 // while (destCount > 0) {
660 ble @19
661 @13:
662 cmp r9, #32 // while ( srcTmpCnt < 32 ) {
663 bge @15
664 @14:
665 cmp r2, #0 // if ( len == 0 ) { return destCount; }
666 beq @19
667 ldr r12, [r1], #1 // srcTmp |= (*data++) << srcTmpCnt;
668 sub r2, r2, #1 // len--; // <- avoid pipe stall
669 orr r6, r6, r12, lsl r9
670 add r9, r9, #8 // srcTmpCnt += 8;
671 cmp r9, #32 // }
672 blt @14
673 @15: // do {
674 mov r12, r6, lsr #31 // r12: select = srcTmp >> 31;
675 ldrb r14, [r5, #0] // r14: endFlag = ( *treep << select ) & TREE_END_MASK;
676 mov r5, r5, lsr #1 // treep = ( treep & ~0x1 ) + ( ( (*treep & 0x3F) + 1 ) * 2 ) + select;
677 mov r5, r5, lsl #1
678 and r8, r14, #0x3F
679 add r8, r8, #1
680 add r5, r5, r8, lsl #1
681 add r5, r5, r12
682 mov r8, #0
683 mov r14, r14, lsl r12
684 ands r14, r14, #TREE_END_MASK
685 mov r6, r6, lsl #1 // srcTmp <<= 1;
686 sub r9, r9, #1 // srcTmpCnt--;
687 beq @17 // if ( ! endFlag ) { continue; }
688
689 mov r7, r7, lsr r11 // destTmp >>= bitSize;
690 ldrb r12, [r5, #0] // destTmp |= *treep << ( 32 - bitSize );
691 rsb r14, r11, #32
692 orr r7, r7, r12, lsl r14
693 add r5, r0, #MIUncompContextHuffman.tree[1] // treep = &context->tree[ 1 ];
694 add r10, r10, r11 // destTmpCnt += bitSize;
695
696 cmp r4, r10, asr #3 // if ( destCount <= destTmpCnt / 8 ) {
697 bgt @16
698 rsb r12, r10, #32 // destTmp >>= 32 - destTmpCnt;
699 mov r7, r7, asr r12
700 mov r10, #32 // destTmpCnt = 32;
701 @16: // }
702 cmp r10, #32 // if ( destTmpCnt == 32 ) {
703 bne @17
704 str r7, [r3], #4 // *(u32*)destp = destTmp; destp += 4;
705 mov r10, #0 // destTmpCnt = 0;
706 subs r4, r4, #4 // destCount -= 4;
707 movle r4, #0 // if ( destCount <= 0 ) { return 0 };
708 ble @19
709 // }
710 @17:
711 cmp r9, #0 // } while ( srcTmpCnt > 0 );
712 bgt @15
713 cmp r4, #0 // }
714 bgt @13
715
716 @19:
717 str r3, [r0, #MIUncompContextHuffman.destp] // r3: context->destp = destp;
718 str r4, [r0, #MIUncompContextHuffman.destCount] // r4: context->destCount = destCount;
719 str r5, [r0, #MIUncompContextHuffman.treep] // r5: context->treep = treep;
720 str r6, [r0, #MIUncompContextHuffman.srcTmp] // r6: context->srcTmp = srcTmp;
721 str r7, [r0, #MIUncompContextHuffman.destTmp] // r7: context->destTmp = destTmp;
722 strh r8, [r0, #MIUncompContextHuffman.treeSize] // r8: context->treeSize = treeSize;
723 strb r9, [r0, #MIUncompContextHuffman.srcTmpCnt] // r9: context->srcTmpCnt = srcTmpCnt;
724 strb r10, [r0, #MIUncompContextHuffman.destTmpCnt] // r10: context->destTmpCnt = destTmpCnt;
725 strb r11, [r0, #MIUncompContextHuffman.bitSize] // r11: context->bitSize = bitSize;
726 mov r0, r4 // return destCount
727
728 ldmfd sp!, {r4-r12, lr}
729 bx lr
730
731 }
732
733 //---- End limitation of processor mode
734 #include <nitro/codereset.h>
735