@ apLib decruncher for ARM @ @ Based on the M68000 version by MML 2010 @ Size optimized (164 bytes) by Franck "hitchhikr" Charlet. @ @ Thumb version by Mic 2010 (178 bytes) .section .text .align .global aplib_decrunch .code 16 .thumb_func @ r0 = packed data, r1 = dest aplib_decrunch: push {r4-r7,lr} mov r6,#1 copy_byte: ldrb r4,[r0] strb r4,[r1] add r0,#1 add r1,#1 next_sequence_init: mov r7,#0 next_sequence: bl get_bit bcc copy_byte bl get_bit bcc code_pair bl get_bit mov r4,#0 bcc short_match mov r5,#4 get_offset: bl get_bit adc r4,r4 sub r5,#1 bne get_offset cmp r4,#0 beq write_byte neg r4,r4 ldrb r4,[r1,r4] write_byte: strb r4,[r1] add r1,#1 b next_sequence_init code_pair: bl decode_gamma mov r4,r2 sub r4,#2 bne normal_code_pair tst r7,r7 bne normal_code_pair mov r4,r8 bl decode_gamma b copy_code_pair normal_code_pair: add r4,r7 sub r4,#1 ldrb r5,[r0] add r0,#1 lsl r4,#8 orr r4,r5 bl decode_gamma mov r5,r4 cmp r5,#128 bcs cmp1 add r2,#2 b continue_short_match cmp1: lsr r5,#8 cmp r5,#0x7D bcc cmp2 add r2,#1 cmp2: cmp r5,#5 bcc continue_short_match add r2,#1 b continue_short_match get_bit: sub r6,#1 bne still_bits_left mov r6,#8 ldrb r3,[r0] add r0,#1 lsl r3,#24 still_bits_left: lsl r3,#1 bx lr decode_gamma: push {lr} mov r2,#1 get_more_gamma: bl get_bit adc r2,r2 bl get_bit bcs get_more_gamma pop {pc} short_match: mov r2,#1 ldrb r4,[r0] add r0,#1 lsr r4,#1 beq end_decrunch adc r2,r2 continue_short_match: mov r8,r4 copy_code_pair: neg r4,r4 loop_do_copy: ldrb r5,[r1,r4] strb r5,[r1] add r1,#1 sub r2,#1 bne loop_do_copy mov r7,#1 b next_sequence end_decrunch: @ In situations where it's known that this function will be called only by other Thumb functions @ it's possible to save 4 bytes by replacing the three below instructions with a single pop {r4-r7,pc} pop {r4-r7} pop {r0} bx r0