bulgarian update by Hristo Kovachev
[Rockbox.git] / firmware / decompressor / decompressor.c
blobd368c79538cf2205b54d57df1bf6526ea675c732
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 by Jens Arnold
12 * Self-extracting firmware loader to work around the 200KB size limit
13 * for archos player and recorder v1
14 * Decompresses a built-in UCL-compressed image (method 2e) and executes it.
16 * All files in this archive are subject to the GNU General Public License.
17 * See the file COPYING in the source tree root for full license agreement.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include "uclimage.h"
26 #define ICODE_ATTR __attribute__ ((section (".icode")))
28 /* Symbols defined in the linker script */
29 extern char iramcopy[], iramstart[], iramend[];
30 extern char stackend[];
31 extern char loadaddress[], dramend[];
33 /* Prototypes */
34 extern void start(void);
36 void main(void) ICODE_ATTR;
37 int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst,
38 unsigned long *dst_len) ICODE_ATTR;
40 /* Vector table */
41 void (*vbr[]) (void) __attribute__ ((section (".vectors"))) =
43 start, (void *)stackend,
44 start, (void *)stackend,
45 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
46 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
49 /** All subsequent functions are executed from IRAM **/
51 /* Thinned out version of the UCL 2e decompression sourcecode
52 * Original (C) Markus F.X.J Oberhumer under GNU GPL license */
53 #define GETBIT(bb, src, ilen) \
54 (((bb = bb & 0x7f ? bb*2 : ((unsigned)src[ilen++]*2+1)) >> 8) & 1)
56 int ucl_nrv2e_decompress_8(const unsigned char *src, unsigned char *dst,
57 unsigned long *dst_len)
59 unsigned long bb = 0;
60 unsigned ilen = 0, olen = 0, last_m_off = 1;
62 for (;;)
64 unsigned m_off, m_len;
66 while (GETBIT(bb,src,ilen))
67 dst[olen++] = src[ilen++];
69 m_off = 1;
70 for (;;)
72 m_off = m_off*2 + GETBIT(bb,src,ilen);
73 if (GETBIT(bb,src,ilen))
74 break;
75 m_off = (m_off-1)*2 + GETBIT(bb,src,ilen);
77 if (m_off == 2)
79 m_off = last_m_off;
80 m_len = GETBIT(bb,src,ilen);
82 else
84 m_off = (m_off-3)*256 + src[ilen++];
85 if (m_off == 0xffffffff)
86 break;
87 m_len = (m_off ^ 0xffffffff) & 1;
88 m_off >>= 1;
89 last_m_off = ++m_off;
91 if (m_len)
92 m_len = 1 + GETBIT(bb,src,ilen);
93 else if (GETBIT(bb,src,ilen))
94 m_len = 3 + GETBIT(bb,src,ilen);
95 else
97 m_len++;
98 do {
99 m_len = m_len*2 + GETBIT(bb,src,ilen);
100 } while (!GETBIT(bb,src,ilen));
101 m_len += 3;
103 m_len += (m_off > 0x500);
105 const unsigned char *m_pos;
106 m_pos = dst + olen - m_off;
107 dst[olen++] = *m_pos++;
108 do dst[olen++] = *m_pos++; while (--m_len > 0);
111 *dst_len = olen;
113 return ilen;
116 #define ALIGNED_IMG_SIZE ((sizeof(image) + 3) & ~3)
117 /* This will never return */
118 void main(void)
120 unsigned long dst_len; /* dummy */
121 unsigned long *src = (unsigned long *)image;
122 unsigned long *dst = (unsigned long *)(dramend - ALIGNED_IMG_SIZE);
125 *dst++ = *src++;
126 while (dst < (unsigned long *)dramend);
128 ucl_nrv2e_decompress_8(dramend - ALIGNED_IMG_SIZE, loadaddress, &dst_len);
130 asm(
131 "mov.l @%0+,r0 \n"
132 "jmp @r0 \n"
133 "mov.l @%0+,r15 \n"
134 : : "r"(loadaddress) : "r0"