]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/Unpack/Unpack.java
Q2Tools source - didn't import this in initially
[xonotic/netradiant.git] / tools / quake2 / extra / Unpack / Unpack.java
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 ===========================================================================
21 */
22
23 /*
24  * Unpack -- a completely non-object oriented utility...
25  *
26  */
27
28 import java.io.*;
29
30 class Unpack {
31         static final int IDPAKHEADER    = (('K'<<24)+('C'<<16)+('A'<<8)+'P');
32
33         static int intSwap(int i) {
34                 int             a, b, c, d;
35
36                 a = i & 255;
37                 b = (i >> 8) & 255;
38                 c = (i >> 16) & 255;
39                 d = (i >> 24) & 255;
40
41                 return (a << 24) + (b << 16) + (c << 8) + d;
42         }
43
44         static boolean  patternMatch (String pattern, String s) {
45                 int             index;
46                 int             remaining;
47
48                 if (pattern.equals(s)) {
49                         return true;
50                 }
51
52                 // fairly lame single wildcard matching
53                 index = pattern.indexOf('*');
54                 if (index == -1) {
55                         return false;
56                 }
57                 if (!pattern.regionMatches(0, s, 0, index)) {
58                         return false;
59                 }
60
61                 index += 1;     // skip the *
62                 remaining = pattern.length() - index;
63                 if (s.length() < remaining) {
64                         return false;
65                 }
66
67                 if (!pattern.regionMatches(index, s, s.length()-remaining, remaining)) {
68                         return false;
69                 }
70
71                 return true;
72         }
73
74         static void usage() {
75                 System.out.println ("Usage: unpack <packfile> <match> <basedir>");
76                 System.out.println ("   or: unpack -list <packfile>");
77                 System.out.println ("<match> may contain a single * wildcard");
78                 System.exit (1);
79         }
80
81         public static void main (String[] args) {
82                 int                     ident;
83                 int                     dirofs;
84                 int                     dirlen;
85                 int                     i;
86                 int                     numLumps;
87                 byte[]          name = new byte[56];
88                 String          nameString;
89                 int                     filepos;
90                 int                     filelen;
91                 RandomAccessFile        readLump;
92                 DataInputStream         directory;
93                 String          pakName;
94                 String          pattern;
95
96                 if (args.length == 2) {
97                         if (!args[0].equals("-list")) {
98                                 usage();
99                         }
100                         pakName = args[1];
101                         pattern = null;
102                 } else if (args.length == 3) {
103                         pakName = args[0];
104                         pattern = args[1];
105                 } else {
106                         pakName = null;
107                         pattern = null;
108                         usage ();
109                 }
110
111                 try     {
112                         // one stream to read the directory
113                         directory = new DataInputStream(new FileInputStream(pakName));
114
115                         // another to read lumps
116                         readLump = new RandomAccessFile(pakName, "r");
117
118                         // read the header
119                         ident = intSwap(directory.readInt());
120                         dirofs = intSwap(directory.readInt());
121                         dirlen = intSwap(directory.readInt());
122
123                         if (ident != IDPAKHEADER) {
124                                 System.out.println ( pakName + " is not a pakfile.");
125                                 System.exit (1);
126                         }
127
128                         // read the directory
129                         directory.skipBytes (dirofs - 12);
130                         numLumps = dirlen / 64;
131
132                         System.out.println (numLumps + " lumps in " + pakName);
133
134                         for (i = 0 ; i < numLumps ; i++) {
135                                 directory.readFully(name);
136                                 filepos = intSwap(directory.readInt());
137                                 filelen = intSwap(directory.readInt());
138
139                                 nameString = new String (name, 0);
140                                 // chop to the first 0 byte
141                                 nameString = nameString.substring (0, nameString.indexOf(0));
142
143                                 if (pattern == null) {
144                                         // listing mode
145                                         System.out.println (nameString + " : " + filelen + "bytes");
146                                 } else if (patternMatch (pattern, nameString) ) {
147                                         File                            writeFile;
148                                         DataOutputStream        writeLump;
149                                         byte[]                          buffer = new byte[filelen];
150                                         StringBuffer            fixedString;
151                                         String                          finalName;
152                                         int                                     index;
153
154                                         System.out.println ("Unpaking " + nameString + " " + filelen
155                                                 + " bytes");
156
157                                         // load the lump
158                                         readLump.seek(filepos);
159                                         readLump.readFully(buffer);
160
161                                         // quake uses forward slashes, but java requires
162                                         // they only by the host's seperator, which
163                                         // varies from win to unix
164                                         fixedString = new StringBuffer (args[2] + File.separator + nameString);
165                                         for (index = 0 ; index < fixedString.length() ; index++) {
166                                                 if (fixedString.charAt(index) == '/') {
167                                                         fixedString.setCharAt(index, File.separatorChar);
168                                                 }
169                                         }
170                                         finalName = fixedString.toString ();
171
172                                         index = finalName.lastIndexOf(File.separatorChar);
173                                         if (index != -1) {
174                                                 String          finalPath;
175                                                 File            writePath;
176
177                                                 finalPath = finalName.substring(0, index);
178                                                 writePath = new File (finalPath);
179                                                 writePath.mkdirs();
180                                         }
181
182                                         writeFile = new File (finalName);
183                                         writeLump = new DataOutputStream ( new FileOutputStream(writeFile) );
184                                         writeLump.write(buffer);
185                                         writeLump.close();
186
187                                 }
188                         }
189
190                         readLump.close();
191                         directory.close();
192
193                 } catch (IOException e) {
194                         System.out.println ( e.toString() );
195                 }
196         }
197
198 }