summaryrefslogtreecommitdiff
path: root/src/export/extract_version_2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/export/extract_version_2.c')
-rw-r--r--src/export/extract_version_2.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/export/extract_version_2.c b/src/export/extract_version_2.c
new file mode 100644
index 0000000..fe85252
--- /dev/null
+++ b/src/export/extract_version_2.c
@@ -0,0 +1,131 @@
1#include <fcntl.h>
2#include "mystdlib.h"
3#include <stdlib.h>
4#include <string.h>
5#include <stdint.h>
6#include <unistd.h>
7
8/* lha header:
9
1000 Header length
1101 Header checksum [02-length]
1202 0x2d ('-')
1303 0x6c ('l')
1404 0x68 ('h')
1505 0x?? ('0' or '5') unsure
1606 0x2d ('-')
1707 0x?? LSB of compressed size
1808 0x?? ..
1909 0x00 ..
2010 0x00 MSB of compressed size, i.e. 0
21..
2221 Length of path name
23
24
25*/
26
27static uint8_t mantra_in[] = { 0x68, 0x35, 0x2d, 0x6c };
28
29int main( int args, char **argv )
30{
31 int filenum = 0, run = 1;
32 size_t offset = 0, oldoffset = -1, reported = 0, enc_len = 32;
33 uint8_t mantra[4], id0, id5, *mappedfile;
34 MAP map;
35
36 /* For streets we do have a enc_len of 34 */
37 while( run ) {
38 switch( getopt( args, argv, ":e:" ) ) {
39 case -1 : run = 0; break;
40 case 'e':
41 enc_len = atol( optarg );
42 break;
43 default:
44 fputs( "Syntax: %s [-e encrypted_length (default: 32, for streets 34 or 0)] path-to-teiln.dat", stderr ); exit( 1 );
45 break;
46 }
47 }
48 run = 1;
49
50 if( optind == args )
51 { fputs( "Missing filename.", stderr ); exit( 1 ); }
52
53 map = map_file( argv[optind], 1 );
54 mappedfile = map->addr;
55
56 mantra[0] = mantra_in[0] ^ mappedfile[4];
57 mantra[1] = mantra_in[1] ^ mappedfile[5];
58 mantra[2] = mantra_in[2] ^ mappedfile[2];
59 mantra[3] = mantra_in[3] ^ mappedfile[3];
60
61 id0 = mappedfile[0];
62 id5 = mappedfile[5];
63
64 while( run )
65 {
66 while( ( offset < map->size ) && (
67 ( mappedfile[ offset + 0 ] != id0 ) ||
68 ( mappedfile[ offset + 2 ] != ( '-' ^ mantra[2] )) ||
69 ( mappedfile[ offset + 3 ] != ( 'l' ^ mantra[3] )) ||
70 ( mappedfile[ offset + 4 ] != ( 'h' ^ mantra[0] )) ||
71 ( mappedfile[ offset + 5 ] != id5 ) ||
72 ( mappedfile[ offset + 6 ] != ( '-' ^ mantra[2] ))
73 ) ) offset++;
74
75 // printf( "Found an appropriate offset at: %zd\n", offset );
76
77 if( reported < ( offset * 10 ) / map->size )
78 {
79 reported++;
80 printf( "%zd%% ", 10 * reported );
81 fflush( stdout );
82 }
83
84 if( offset == map->size )
85 run = 0;
86
87 if( oldoffset != -1 )
88 {
89 uint8_t *mf = mappedfile + oldoffset, df[128];
90 size_t filename_len, header_len;
91 char filename_template[32], filename[32];
92 int i;
93
94 /* De-"crypt" obfuscation to our header copy */
95 for( i=0; i<enc_len; ++i)
96 df[i] = mf[i] ^ mantra[i%4];
97
98 /* Get values from LHA header */
99 header_len = df[0] + 2;
100 filename_len = df[21];
101
102 /* Copy rest of header, so we can checksum */
103 for( i=enc_len; i<header_len; ++i)
104 df[i] = mf[i];
105
106 /* Make up new sequental file name */
107 snprintf( filename_template, sizeof(filename_template), "%%0%dd.lha", (int)filename_len );
108 snprintf( filename, sizeof( filename ), filename_template, filenum++ );
109 memcpy( ((uint8_t*)df) + 22, filename, filename_len);
110
111 /* Recalculate checksum with new file name */
112 df[1] = 0; for( i=2; i<header_len; ++i) df[1] += df[i];
113
114 /* Open file and dump our de-"crypted" header and then rest of file */
115 i = open( filename, O_CREAT | O_TRUNC | O_WRONLY, 0644 );
116 if( enc_len > header_len ) {
117 write( i, df, enc_len );
118 write( i, mf + enc_len, offset - oldoffset - enc_len );
119 } else {
120 write( i, df, header_len );
121 write( i, mf + header_len, offset - oldoffset - header_len );
122 }
123 close( i );
124 }
125 oldoffset = offset;
126 offset++;
127 }
128
129 unmap_file( &map );
130 return 0;
131}