lzhuf: Refactored to avoid direct array access
[deark.git] / modules / psionapp.c
blobca4b332b72c8382bdb1b304f5a4d1dbb11ec9ca5
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Psion APP/IMG
7 #include <deark-config.h>
8 #include <deark-private.h>
9 DE_DECLARE_MODULE(de_module_psionapp);
11 typedef struct localctx_struct {
12 int convert_images; // 0=extract PIC, 1=convert PIC
13 } lctx;
15 static void handle_embedded_file(deark *c, lctx *d, i64 offset, i64 len)
17 u8 buf[16];
18 const char *ext;
19 int extract_this_file;
20 int is_pic;
22 de_dbg(c, "embedded file at %d, len=%d", (int)offset, (int)len);
23 is_pic = 0;
24 ext = "bin";
25 extract_this_file = 0;
27 if(len>0 && c->extract_level>=2)
28 extract_this_file = 1;
30 // As far as I can tell, there's no way to tell the type of an
31 // embedded file, except by sniffing it.
32 de_read(buf, offset, 16);
33 if(len>=8) {
34 if(!de_memcmp(buf, "PIC\xdc\x30\x30", 6)) {
35 // Looks like a PIC file
36 is_pic = 1;
37 ext = "pic";
38 extract_this_file = 1;
42 if(extract_this_file) {
43 if(is_pic && d->convert_images) {
44 // Convert PIC to PNG.
45 // For consistency, this option shouldn't exist. But I'm not sure that
46 // PIC files embedded in APP files are really the same as PIC files on
47 // their own. They might need special handling. Until I'm sure they don't,
48 // I'll leave this option here.
49 de_run_module_by_id_on_slice(c, "psionpic", NULL, c->infile, offset, len);
51 else {
52 // Just extract the file
53 dbuf_create_file_from_slice(c->infile, offset, len, ext, NULL, is_pic?0:DE_CREATEFLAG_IS_AUX);
56 else {
57 de_dbg(c, "(not extracting this file)");
61 static void do_opo_opa(deark *c, lctx *d)
63 i64 offset_2ndheader;
64 i64 pos;
65 i64 n;
66 i64 len;
68 de_declare_fmt(c, "Psion OPO/OPA");
70 // The second header marks the end of the embedded files section, I guess.
71 offset_2ndheader = de_getu16le(18);
72 de_dbg(c, "offset of second header: %d", (int)offset_2ndheader);
73 pos = 20;
75 // Read length of source filename
76 n = (i64)de_getbyte(pos);
77 pos++;
78 pos+=n;
79 while(pos<offset_2ndheader) {
80 // Read length of this embedded file
81 len = de_getu16le(pos);
82 pos+=2;
83 handle_embedded_file(c, d, pos, len);
84 pos+=len;
88 static void do_img_app(deark *c, lctx *d)
90 i64 i;
91 i64 offset;
92 i64 len;
94 de_declare_fmt(c, "Psion IMG/APP");
96 for(i=0; i<4; i++) {
97 offset = de_getu16le(40 + 4*i);
98 len = de_getu16le(40 + 4*i + 2);
99 if(offset==0) break;
100 handle_embedded_file(c, d, offset, len);
104 static void de_run_psionapp(deark *c, de_module_params *mparams)
106 u8 b;
107 const char *s;
108 lctx *d = NULL;
110 d = de_malloc(c, sizeof(lctx));
112 s = de_get_ext_option(c, "psionapp:convertpic");
113 if(s) {
114 d->convert_images = 1;
117 b = de_getbyte(0);
118 if(b=='O') {
119 do_opo_opa(c, d);
121 else {
122 do_img_app(c, d);
125 de_free(c, d);
128 static int de_identify_psionapp(deark *c)
130 u8 b[16];
131 de_read(b, 0, 16);
132 if(!de_memcmp(b, "ImageFileType**\0", 16))
133 return 100;
134 if(!de_memcmp(b, "OPLObjectFile**\0", 16))
135 return 100;
136 return 0;
139 void de_module_psionapp(deark *c, struct deark_module_info *mi)
141 mi->id = "psionapp";
142 mi->desc = "Psion .APP/.IMG and .OPA/.OPO";
143 mi->desc2 = "extract images";
144 mi->run_fn = de_run_psionapp;
145 mi->identify_fn = de_identify_psionapp;