/
seg009.cpp
144 lines (119 loc) · 4.41 KB
/
seg009.cpp
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
/**
* Rewrite of DSA1 v3.02_de functions of seg009 (PP20 decompressor)
* Functions rewritten: 1/1
*
* Borlandified and identical
* Take a look in seg009.asm
*/
/* Code from Heikki Orsila's amigadepack 0.02 to replace previous
* PowerPack depacker with license issues.
*
* You'll probably want to use ppcrack stand-alone to crack encrypted
* powerpack files once instead of using brute force at each replay.
*
* Modified for xmp by Claudio Matsuoka, 08/2007
* - merged mld's checks from the old depack sources. Original credits:
* - corrupt file and data detection
* (thanks to Don Adan and Dirk Stoecker for help and infos)
* - implemeted "efficiency" checks
* - further detection based on code by Georg Hoermann
*/
#include "v302de.h"
#if !defined(__BORLANDC__)
namespace M302de {
#endif
static inline unsigned int val(const unsigned char *p) {
return (p[0]<<16 | p[1] << 8 | p[2]);
}
static unsigned long depackedlen(const unsigned char *p, unsigned long plen) {
/* DSA1/ROA1 doesn't use the first bytes as a signature "PP20".
* It's used instead for the lenght of the packed data. */
if (p[0] == 'P' && p[1] == 'P' && p[2] == '2' && p[3] == '0')
return val(p+plen-4);
if (host_readd((Bit8u*)p) == plen)
return val(p+plen-4);
if (host_readd((Bit8u*)p) + 8 == plen)
return val(p+plen-4);
return 0; /* not a powerpacker file */
}
typedef unsigned char uint8;
typedef unsigned int uint32;
#define PP_READ_BITS(nbits, var) do { \
bit_cnt = (nbits); \
while (bits_left < bit_cnt) { \
if (buf_src < src) return 0; /* out of source bits */ \
bit_buffer |= (*--buf_src << bits_left); \
bits_left += 8; \
} \
(var) = 0; \
bits_left -= bit_cnt; \
while (bit_cnt--) { \
(var) = ((var) << 1) | (bit_buffer & 1); \
bit_buffer >>= 1; \
} \
} while(0)
#define PP_BYTE_OUT(byte) do { \
if (out <= dest) return 0; /* output overflow */ \
*--out = (byte); \
written++; \
} while (0)
int ppDecrunch(uint8 *src, uint8 *dest, uint8 *offset_lens,
uint32 src_len, uint32 dest_len, uint8 skip_bits)
{
uint8 *buf_src, *out, *dest_end, bits_left = 0, bit_cnt;
uint32 bit_buffer = 0, x, todo, offbits, offset, written=0;
if (!NOT_NULL(src) || !NOT_NULL(dest) || offset_lens == NULL) return 0;
/* set up input and output pointers */
buf_src = src + src_len;
out = dest_end = dest + dest_len;
/* skip the first few bits */
PP_READ_BITS(skip_bits, x);
/* while there are input bits left */
while (written < dest_len) {
PP_READ_BITS(1, x);
if (x == 0) {
/* 1bit==0: literal, then match. 1bit==1: just match */
todo = 1; do { PP_READ_BITS(2, x); todo += x; } while (x == 3);
while (todo--) { PP_READ_BITS(8, x); PP_BYTE_OUT(x); }
/* should we end decoding on a literal, break out of the main loop */
if (written == dest_len) break;
}
/* match: read 2 bits for initial offset bitlength / match length */
PP_READ_BITS(2, x);
offbits = offset_lens[x];
todo = x+2;
if (x == 3) {
PP_READ_BITS(1, x);
if (x==0) offbits = 7;
PP_READ_BITS(offbits, offset);
do { PP_READ_BITS(3, x); todo += x; } while (x == 7);
}
else {
PP_READ_BITS(offbits, offset);
}
if ((out + offset) >= dest_end) return 0; /* match overflow */
while (todo--) { x = out[offset]; PP_BYTE_OUT(x); }
}
/* all output bytes written without error */
return 1;
/* return (src == buf_src) ? 1 : 0; */
}
void decomp_pp20(Bit8u *src, Bit8u *dst, Bit8u *p3, Bit32u plen)
{
size_t unplen;
#if !defined(__BORLANDC__)
if (plen < 4)
D1_ERR("PP20: Length argument is below 4\n");
#endif
unplen = depackedlen(src, plen);
#if !defined(__BORLANDC__)
if (unplen == 0) {
D1_ERR("PP20: No PP20 file\n");
}
#endif
ppDecrunch(&src[8], dst, &src[4], plen - 12, unplen, src[plen -1]);
return;
}
#if !defined(__BORLANDC__)
}
#endif