Added support for cp932 (Shift-JIS) conversion
[deark.git] / modules / wad.c
blob4b9db265d23692253e89b94a65e53ec0b772c247
1 // This file is part of Deark.
2 // Copyright (C) 2017 Jason Summers
3 // See the file COPYING for terms of use.
5 // Doom WAD
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_wad);
11 typedef struct localctx_struct {
12 i64 nlumps;
13 i64 dir_pos;
14 } lctx;
16 static void do_lump_extract(deark *c, lctx *d, i64 dpos, i64 dlen, struct de_stringreaderdata *srd)
18 de_finfo *fi = NULL;
20 // 0-length lumps are assumed to be special "virtual" lumps.
21 if(dlen<=0) return;
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)
33 i64 lump_pos;
34 i64 lump_size;
35 struct de_stringreaderdata *srd = NULL;
37 de_dbg(c, "lump[%d] dir entry at %d", (int)lump_idx, (int)pos);
38 de_dbg_indent(c, 1);
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);
52 de_dbg_indent(c, -1);
53 de_destroy_stringreaderdata(c, srd);
56 static int do_directory(deark *c, lctx *d, i64 pos)
58 i64 k;
59 de_dbg(c, "directory at %d", (int)pos);
60 de_dbg_indent(c, 1);
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);
70 done:
71 de_dbg_indent(c, -1);
72 return 1;
75 static int do_header(deark *c, lctx *d, i64 pos)
77 de_dbg(c, "header at %d", (int)pos);
78 de_dbg_indent(c, 1);
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);
83 de_dbg_indent(c, -1);
84 return 1;
87 static void de_run_wad(deark *c, de_module_params *mparams)
89 lctx *d = NULL;
91 d = de_malloc(c, sizeof(lctx));
93 if(!do_header(c, d, 0)) goto done;
95 do_directory(c, d, d->dir_pos);
97 done:
98 de_free(c, d);
101 static int de_identify_wad(deark *c)
103 if(!dbuf_memcmp(c->infile, 1, "WAD", 3)) {
104 u8 b0;
105 b0 = de_getbyte(0);
106 if(b0=='I' || b0=='P') return 80;
108 return 0;
111 void de_module_wad(deark *c, struct deark_module_info *mi)
113 mi->id = "wad";
114 mi->desc = "Doom WAD";
115 mi->run_fn = de_run_wad;
116 mi->identify_fn = de_identify_wad;