1 // This file is part of Deark.
2 // Copyright (C) 2017 Jason Summers
3 // See the file COPYING for terms of use.
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_wad
);
11 typedef struct localctx_struct
{
16 static void do_lump_extract(deark
*c
, lctx
*d
, i64 dpos
, i64 dlen
, struct de_stringreaderdata
*srd
)
20 // 0-length lumps are assumed to be special "virtual" lumps.
22 if(dpos
<0 || dpos
>=c
->infile
->len
|| dpos
+dlen
>c
->infile
->len
) return;
24 fi
= de_finfo_create(c
);
25 de_finfo_set_name_from_ucstring(c
, fi
, srd
->str
, 0);
26 fi
->original_filename_flag
= 1;
27 dbuf_create_file_from_slice(c
->infile
, dpos
, dlen
, NULL
, fi
, 0);
28 de_finfo_destroy(c
, fi
);
31 static void do_lump_entry(deark
*c
, lctx
*d
, i64 lump_idx
, i64 pos
)
35 struct de_stringreaderdata
*srd
= NULL
;
37 de_dbg(c
, "lump[%d] dir entry at %d", (int)lump_idx
, (int)pos
);
39 lump_pos
= de_getu32le(pos
);
40 de_dbg(c
, "data pos: %d", (int)lump_pos
);
41 lump_size
= de_getu32le(pos
+4);
42 de_dbg(c
, "data size: %d", (int)lump_size
);
44 // dbuf_read_string is used (instead of dbuf_read_to_ucstring) because
45 // the names have special meanings, so someday we might want to run
46 // comparisons against them. But currently we don't do that.
47 srd
= dbuf_read_string(c
->infile
, pos
+8, 8, 8, DE_CONVFLAG_STOP_AT_NUL
, DE_ENCODING_ASCII
);
48 de_dbg(c
, "name: \"%s\"", ucstring_getpsz_d(srd
->str
));
50 do_lump_extract(c
, d
, lump_pos
, lump_size
, srd
);
53 de_destroy_stringreaderdata(c
, srd
);
56 static int do_directory(deark
*c
, lctx
*d
, i64 pos
)
59 de_dbg(c
, "directory at %d", (int)pos
);
62 if(pos
<0 || pos
>=c
->infile
->len
) goto done
;
63 if(d
->nlumps
<1 || d
->nlumps
>10000) goto done
;
65 for(k
=0; k
<d
->nlumps
; k
++) {
66 if(pos
+16*k
> c
->infile
->len
-16) break;
67 do_lump_entry(c
, d
, k
, pos
+16*k
);
75 static int do_header(deark
*c
, lctx
*d
, i64 pos
)
77 de_dbg(c
, "header at %d", (int)pos
);
79 d
->nlumps
= de_getu32le(pos
+4);
80 de_dbg(c
, "#lumps: %d", (int)d
->nlumps
);
81 d
->dir_pos
= de_getu32le(pos
+8);
82 de_dbg(c
, "dir pos: %d", (int)d
->dir_pos
);
87 static void de_run_wad(deark
*c
, de_module_params
*mparams
)
91 d
= de_malloc(c
, sizeof(lctx
));
93 if(!do_header(c
, d
, 0)) goto done
;
95 do_directory(c
, d
, d
->dir_pos
);
101 static int de_identify_wad(deark
*c
)
103 if(!dbuf_memcmp(c
->infile
, 1, "WAD", 3)) {
106 if(b0
=='I' || b0
=='P') return 80;
111 void de_module_wad(deark
*c
, struct deark_module_info
*mi
)
114 mi
->desc
= "Doom WAD";
115 mi
->run_fn
= de_run_wad
;
116 mi
->identify_fn
= de_identify_wad
;