Ticket #5893: dumpsword.c

File dumpsword.c, 9.4 KB (added by eriktorbjorn, 12 years ago)

Program to extract sound effects data from DOS/Windows demo

Line 
1#include <stdio.h>
2#include <string.h>
3
4#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
5
6#define FX_START_DOS 556172
7#define FX_START_WIN 165352
8
9#define NUM_SOUNDS 280
10
11/* Using these resource names, I do get a reasonably close approximation of
12 * the FX list in staticresource.cpp for the sound effects that appear to be
13 * in the demo data files. Though the goal is to eventually create a mapping,
14 * rather than storing two copies of the entire structure.
15 */
16
17const char *resNamesDemo06[] = {
18 /* 00 */
19 "FX_CAMERA1", "FX_CAMERA2", "FX_CAMERA3", "FX_CANDO",
20 "FX_CANUP", "FX_CAW1", "FX_DUST", "FX_HORN1",
21 "FX_HORN2", "FX_HORN3", "FX_PAP1", "FX_PAP2",
22 "FX_PICK1", "FX_PICK2", "FX_PICK3", "FX_PICK4",
23 /* 10 */
24 "FX_PICK5", "FX_TRAFFIC2", "FX_TWEET1", "FX_TWEET2",
25 "FX_TWEET3", "FX_TWEET4", "FX_TWEET5", "FX_BIN1",
26 "FX_BIN2", "FX_BIN3", "FX_CAT", "FX_COVERON2",
27 "FX_CRATE", "FX_DRAIN", "FX_HOLE", "FX_BODY",
28 /* 20 */
29 "FX_BOTDN", "FX_BOTUP", "FX_GULP", "FX_LIGHT",
30 "FX_PIKUP", "FX_PAP3", "FX_PAP4", "FX_PAP5",
31 "FX_PISTOL", "FX_TBOX", "FX_KNOKKNOK", "FX_ALBCLO",
32 "FX_ALBOP", "FX_LADD1", "FX_LADD2", "FX_LADD3",
33 /* 30 */
34 "FX_RAT1", "FX_RAT2", "FX_SEWSTEP1", "FX_SEWSTEP2",
35 "FX_SWATER3", "FX_DRIP1", "FX_DRIP2", "FX_DRIP3",
36 "FX_SWATER1", "FX_SEWLADU7"
37};
38
39const char *resNamesDemo07[] = {
40 /* 00 */
41 "FX_BIRD", "FX_BIRD2", "FX_CARLTON", "FX_CARS",
42 "FX_DOORTRY", "FX_FIESTA", "FX_FLATDOOR", "FX_FONEUP",
43 "FX_FONEDN", "FX_GEOCCH", "FX_GEOCHAIR", "FX_GEOCHR9",
44 NULL, "FX_NICOPEN", "FX_NICLOSE", "FX_PHONIC01",
45 /* 10 */
46 "FX_GRAMOFON", "FX_SHOCK1", "FX_WINDUP11", "FX_FRISK",
47 "FX_TRAFFIC3", "FX_DESKBELL", "FX_PAPER6", "FX_PHONEDN2",
48 "FX_PHONEUP2", "FX_PIANO14", "FX_TRYDOR14", "FX_CABCLOSE",
49 "FX_CABOPEN", "FX_DORCLOSE", "FX_WINDOPEN", "FX_COO",
50 /* 20 */
51 "FX_COO2", "FX_LEDGE1", "FX_LEDGE2", "FX_BRIEFOFF",
52 "FX_BRIEFON", "FX_JUMPIN", "FX_WARDIN", "FX_WARDOUT",
53 "FX_CLIMBIN", "FX_CLIMBOUT"
54};
55
56const char *resNamesDemo08[] = {
57 /* 00 */
58 "FX_MUESEXT", "FX_AIRCON28", "FX_SARCO28A", "FX_SARCO28B",
59 "FX_SARCO28C", "FX_TOTEM28A", "FX_ALARM", "FX_CARABINE",
60 "FX_DOOR29", "FX_FISHFALL", "FX_GDROP29", "FX_GUI_HIT",
61 "FX_GUN1", "FX_ROPEDOWN", "FX_SARCO29", "FX_SMASHGLA",
62 /* 10 */
63 "FX_TOTEM29A", "FX_TOTEM29B", "FX_HOSPEXT", "FX_GRAVEL1",
64 "FX_GRAVEL2", "FX_HOSPNOISE", "FX_CUPBOPEN", "FX_CUPBCLOS",
65 "FX_SHINY", "FX_SHINYOFF", "FX_SHINYON", "FX_BLOODPRE",
66 "FX_GUN34", "FX_PULSE2", "FX_PULSE3"
67};
68
69const char *resNamesDemo09[] = {
70 /* 00 */
71 "FX_MANOP36", "FX_MONTAMB", "FX_OOH", "FX_PULLUP36",
72 "FX_REPLCE36", "FX_AMBIEN37", "FX_CHAIN37_AND37B","FX_DOOR37",
73 "FX_HOLE37", "FX_KNOCK37", "FX_KNOCK37B", "FX_WINCH37",
74 "FX_AIRCON41", "FX_FONEDN41", "FX_FONEUP41", "FX_PHONCALL",
75 /* 10 */
76 "FX_THERM01", "FX_DRIER1", "FX_CHURCHFX"
77};
78
79const char *resNamesDemo0A[] = {
80 /* 00 */
81 "FX_EIRBIRD3", "FX_SHOCK2", "FX_EIRBIRD1", "FX_EIRBIRD2",
82 "FX_SWITCH19", "FX_TRAPOPEN", "FX_VIOLIN19", "FX_WHISTLE",
83 "FX_BARFLAP", "FX_DORCLOSE20","FX_DRINK", "FX_FITZHIT",
84 "FX_FITZRUN", "FX_FITZUP", "FX_FUSE20", "FX_PULLPINT",
85 /* 10 */
86 "FX_WASHER", "FX_CELTAP", "FX_TAP", "FX_TAP2",
87 "FX_CLIMBHAY", "FX_FARMERGO", "FX_CASTLWAL", "FX_CLIMBFAL",
88 "FX_KEYSTEP", "FX_WIND", "FX_GEOGOAT", "FX_GOATBAA",
89 "FX_GOATCHEW", "FX_GOATDOH", "FX_PLOUGH", NULL,
90 /* 20 - FX_RAB3A, FX_RAT3B, FX_RAT3C, and RX_RAT3D all use same id */
91 NULL, "FX_SECDOR25", "FX_SLABFALL", "FX_SLABUP",
92 "FX_TRIGER25", "FX_WRING", "FX_LEVER", "FX_LEVER2",
93 "FX_RAT3ABCD",
94
95};
96
97const char *resNamesDemo0B[] = {
98 /* 00 */
99 "FX_SPNBIRD1", "FX_SPNBIRD2", "FX_AMBIEN56", "FX_DOGS56",
100 "FX_PENDULUM", "FX_CANFALL", "FX_HOSE57", "FX_HOSE57B",
101 "FX_SPAIN", "FX_CHESS", NULL, "FX_LIONFALL",
102 "FX_LIONFAL2", "FX_TOOTHPUL", "FX_SECDOR61", "FX_WELLDRIP"
103};
104
105const char *resNamesDemo0C[] = {
106 /* 00 */
107 "FX_SHOCK3", "FX_STALLBEL", "FX_AYUBDOOR", "FX_BALLPLAY",
108 "FX_CATHIT", "FX_MARIB", "FX_NEWTON", "FX_STALLCAT",
109 "FX_STATBREK", "FX_KEYS49", "FX_MANG1", "FX_MANG2",
110 "FX_MANG3", "FX_UNLOCK49", "FX_WCCHAIN", "FX_CUBDOR",
111 /* 10 */
112 "FX_BREKSTIK", "FX_CLIMBDWN", "FX_CRICKET", "FX_GEOFAL54",
113 "FX_KHANDOWN", "FX_RINGPULL", "FX_SECDOR54", "FX_SHOTKHAN",
114 "FX_SYRIWIND", "FX_THUMP1", "FX_SECDOR55"
115};
116
117const char *resNamesDemo0D[] = {
118 /* 00 */
119 "FX_SHOCK63", "FX_TRAINEXT", "FX_TRAININT", "FX_DOOR65",
120 "FX_WIND66", "FX_WINDOW66", "FX_BRAKES", "FX_DOOR69",
121 "FX_EKSHOOT", "FX_PNEUMO69", "FX_TICK69", "FX_TRNPASS"
122};
123
124const char *resNamesDemo0E[] = {
125 /* 00 */
126 "FX_WIND71", "FX_GUST71", "FX_OWL71A", "FX_OWL71B",
127 "FX_COG72A", "FX_PING", "FX_RUMMAGE1", "FX_RUMMAGE2",
128 "FX_SECDOR72", "FX_DAGGER1", "FX_GUNPOWDR", "FX_TORCH73",
129 "FX_ROSSODIE", "FX_CHOKE1", "FX_CHOKE2", "FX_FIGHT2",
130 /* 10 */
131 "FX_GUN79"
132};
133
134void dumpResNames(const char **resNames, long base, unsigned int numResources) {
135 int i;
136
137 for (i = 0; i < numResources; i++) {
138 if (resNames[i]) {
139 int len = strlen(resNames[i]);
140 printf("#define %s\t\t\t\t", resNames[i]);
141 if (strlen(resNames[i]) < 8)
142 printf("\t\t");
143 else if (strlen(resNames[i]) < 16)
144 printf("\t");
145 printf("0x%08X\n", base + i);
146 }
147 }
148
149 printf("\n");
150}
151
152const char *guessResName(unsigned long resId) {
153 unsigned long resFamily = (resId >> 24) & 0xFF;
154 unsigned long resIndex = resId & 0x00FFFFFF;
155 const char **resNames;
156 int numResources;
157
158 switch (resFamily) {
159 case 0x06:
160 resNames = resNamesDemo06;
161 numResources = ARRAYSIZE(resNamesDemo06);
162 break;
163 case 0x07:
164 resNames = resNamesDemo07;
165 numResources = ARRAYSIZE(resNamesDemo07);
166 break;
167 case 0x08:
168 resNames = resNamesDemo08;
169 numResources = ARRAYSIZE(resNamesDemo08);
170 break;
171 case 0x09:
172 resNames = resNamesDemo09;
173 numResources = ARRAYSIZE(resNamesDemo09);
174 break;
175 case 0x0A:
176 resNames = resNamesDemo0A;
177 numResources = ARRAYSIZE(resNamesDemo0A);
178 break;
179 case 0x0B:
180 resNames = resNamesDemo0B;
181 numResources = ARRAYSIZE(resNamesDemo0B);
182 break;
183 case 0x0C:
184 resNames = resNamesDemo0C;
185 numResources = ARRAYSIZE(resNamesDemo0C);
186 break;
187 case 0x0D:
188 resNames = resNamesDemo0D;
189 numResources = ARRAYSIZE(resNamesDemo0D);
190 break;
191 case 0x0E:
192 resNames = resNamesDemo0E;
193 numResources = ARRAYSIZE(resNamesDemo0E);
194 break;
195 default:
196 return "UNKNOWN";
197 }
198
199 if (resIndex < numResources && resNames[resIndex])
200 return resNames[resIndex];
201
202 return "UNKNOWN";
203}
204
205unsigned long readUint32(FILE *input) {
206 unsigned char buf[4];
207
208 fread(buf, 1, sizeof(buf), input);
209 return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
210}
211
212void dumpFx(FILE *input, int index) {
213 unsigned long resId = readUint32(input);
214 unsigned long fxType = readUint32(input);
215 unsigned long fxParam = readUint32(input);
216 const char *resName;
217 int silent, len, i;
218
219 printf("\t// %d\n", index);
220 printf("\t{\n");
221 resName = guessResName(resId);
222 len = strlen(resName);
223 printf("\t\t%s,", resName);
224 if (len < 7)
225 printf("\t\t\t");
226 else if (len < 15)
227 printf("\t\t");
228 else
229 printf("\t");
230 printf("// sampleId (0x%08X)\n", resId);
231 printf("\t\t");
232 switch (fxType) {
233 case 1:
234 printf("FX_SPOT");
235 break;
236 case 2:
237 printf("FX_LOOP");
238 break;
239 case 3:
240 printf("FX_RANDOM");
241 break;
242 default:
243 printf("UNKNOWN");
244 break;
245 }
246 printf(",\t\t// type (%d)\n", fxType);
247 printf("\t\t%d,\t\t\t// delay (or random chance)\n", fxParam);
248
249 printf("\t\t{\t\t\t// roomVolList\n");
250
251 silent = 0;
252
253 for (i = 0; i < 7; i++) {
254 unsigned long roomNo = readUint32(input);
255 unsigned long fxLeftVol = readUint32(input);
256 unsigned long fxRightVol = readUint32(input);
257
258 if (!silent) {
259 printf("\t\t\t{%d,%d,%d}", roomNo, fxLeftVol, fxRightVol);
260 if (i == 0)
261 printf(",\t// {roomNo,leftVol,rightVol}\n");
262 else if (i < 6)
263 printf(",\n");
264 else
265 printf("\n");
266 }
267
268 if (roomNo == 0 && fxLeftVol == 0 && fxRightVol == 0)
269 silent = 1;
270 }
271
272 printf("\t\t}\n");
273 printf("\t}");
274
275 if (index < NUM_SOUNDS - 1)
276 printf(",");
277
278 printf("\n");
279}
280
281int checkFile(FILE *input, long offset) {
282 unsigned char buf[92];
283 int i;
284
285 fseek(input, offset, SEEK_SET);
286
287 if (fread(buf, 1, sizeof(buf), input) != sizeof(buf)) {
288 return 0;
289 }
290
291 /* The first entry of the data structure is all zeroes */
292 for (i = 0; i < sizeof(buf); i++) {
293 if (buf[i]) {
294 return 0;
295 }
296 }
297
298 return 1;
299}
300
301int dumpAllFx(FILE *input) {
302 int i;
303
304 printf("const FxDef::_fxList[%d] = {\n", NUM_SOUNDS);
305
306 for (i = 0; i < NUM_SOUNDS; i++) {
307 dumpFx(input, i);
308 }
309
310 printf("};\n");
311
312}
313
314int main(int argc, char *argv[]) {
315 FILE *input;
316 long pos;
317
318 if (argc != 2) {
319 fprintf(stderr, "Usage: %s filename\n", argv[0]);
320 return 1;
321 }
322
323 input = fopen(argv[1], "rb");
324 if (!input) {
325 fprintf(stderr, "Could not open '%s' for reading!\n", argv[1]);
326 return 1;
327 }
328
329 if (checkFile(input, FX_START_WIN)) {
330 printf("// Data dumped from Windows EXE\n\n");
331 pos = FX_START_WIN;
332 } else if (checkFile(input, FX_START_DOS)) {
333 printf("// Data dumped from DOS EXE\n\n");
334 pos = FX_START_DOS;
335 } else {
336 fprintf(stderr, "Could not identify the EXE file!\n");
337 return 1;
338 }
339
340 fseek(input, pos, SEEK_SET);
341
342 dumpResNames(resNamesDemo06, 0x06000000, ARRAYSIZE(resNamesDemo06));
343 dumpResNames(resNamesDemo07, 0x07000000, ARRAYSIZE(resNamesDemo07));
344 dumpResNames(resNamesDemo08, 0x08000000, ARRAYSIZE(resNamesDemo08));
345 dumpResNames(resNamesDemo09, 0x09000000, ARRAYSIZE(resNamesDemo09));
346 dumpResNames(resNamesDemo0A, 0x0A000000, ARRAYSIZE(resNamesDemo0A));
347 dumpResNames(resNamesDemo0B, 0x0B000000, ARRAYSIZE(resNamesDemo0B));
348 dumpResNames(resNamesDemo0C, 0x0C000000, ARRAYSIZE(resNamesDemo0C));
349 dumpResNames(resNamesDemo0D, 0x0D000000, ARRAYSIZE(resNamesDemo0D));
350 dumpResNames(resNamesDemo0E, 0x0E000000, ARRAYSIZE(resNamesDemo0E));
351
352 dumpAllFx(input);
353
354 fclose(input);
355 return 0;
356}