1 /*
2 * compression/DecompressorUMX.cpp
3 *
4 * Copyright 2009 Peter Barth
5 *
6 * This file is part of Milkytracker.
7 *
8 * Milkytracker is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Milkytracker is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Milkytracker. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23 /*
24 * DecompressorUMX.cpp
25 * milkytracker_universal
26 *
27 * Created by Peter Barth on 22.06.08.
28 *
29 */
30
31 #include "DecompressorUMX.h"
32 #include "XMFile.h"
33 #include "LittleEndian.h"
34
35 // -- UMX --------------------------------------------------------------------
DecompressorUMX(const PPSystemString & fileName)36 DecompressorUMX::DecompressorUMX(const PPSystemString& fileName) :
37 DecompressorBase(fileName)
38 {
39 }
40
identify(XMFile & f)41 bool DecompressorUMX::identify(XMFile& f)
42 {
43 f.seek(0);
44 mp_dword id = f.readDword();
45
46 // UMX ID
47 return (id == 0x9E2A83C1);
48 }
49
getDescriptors(Hints hint) const50 const PPSimpleVector<Descriptor>& DecompressorUMX::getDescriptors(Hints hint) const
51 {
52 descriptors.clear();
53 descriptors.add(new Descriptor("umx", "Unreal Data File"));
54 return descriptors;
55 }
56
57 #define TEST_SIZE 1500
58
59 #define MAGIC4(a,b,c,d) \
60 (((pp_uint32)(a)<<24)|((pp_uint32)(b)<<16)|((pp_uint32)(c)<<8)|(d))
61
62 #define MAGIC_IMPM MAGIC4('I','M','P','M')
63 #define MAGIC_SCRM MAGIC4('S','C','R','M')
64 #define MAGIC_M_K_ MAGIC4('M','.','K','.')
65
decompress(const PPSystemString & outFileName,Hints hint)66 bool DecompressorUMX::decompress(const PPSystemString& outFileName, Hints hint)
67 {
68 // If client requests something else than a module we can't deal we that
69 if (hint != HintAll &&
70 hint != HintModules)
71 return false;
72
73 XMFile f(fileName);
74
75 int i;
76 pp_uint8 *buf, *b;
77 int len, offset = -1;
78
79 if ((b = buf = new pp_uint8[0x10000]) == NULL)
80 return false;
81
82 f.read(buf, 1, TEST_SIZE);
83 for (i = 0; i < TEST_SIZE; i++, b++) {
84 pp_uint32 id;
85
86 id = BigEndian::GET_DWORD(b);
87
88 if (!memcmp(b, "Extended Module:", 16)) {
89 offset = i;
90 break;
91 }
92 if (id == MAGIC_IMPM) {
93 offset = i;
94 break;
95 }
96 if (i > 44 && id == MAGIC_SCRM) {
97 offset = i - 44;
98 break;
99 }
100 if (i > 1080 && id == MAGIC_M_K_) {
101 offset = i - 1080;
102 break;
103 }
104 }
105
106 if (offset < 0) {
107 delete[] buf;
108 return false;
109 }
110
111 f.seek(offset);
112
113 XMFile fOut(outFileName, true);
114
115 do {
116 len = f.read(buf, 1, 0x10000);
117 fOut.write(buf, 1, len);
118 } while (len == 0x10000);
119
120 delete[] buf;
121
122 return true;
123 }
124
clone()125 DecompressorBase* DecompressorUMX::clone()
126 {
127 return new DecompressorUMX(fileName);
128 }
129
130 static Decompressor::RegisterDecompressor<DecompressorUMX> registerDecompressor;
131