1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Portfolio graphics formats:
8 // * PGX (Portfolio animation)
10 #include <deark-config.h>
11 #include <deark-private.h>
12 DE_DECLARE_MODULE(de_module_pgx
);
13 DE_DECLARE_MODULE(de_module_pf_pgf
);
14 DE_DECLARE_MODULE(de_module_pgc
);
16 typedef struct localctx_struct
{
20 static void do_pgc_in_pgx(deark
*c
, lctx
*d
, i64 pos
, i64 len
)
24 f
= dbuf_create_output_file(c
, "pgc", NULL
, 0);
26 // Embedded PGC files don't include the 3-byte PGC header, so we have to add that.
27 dbuf_write(f
, (const unsigned char*)"PG\x01", 3);
29 // Copy the rest of the PGC file.
30 dbuf_copy(c
->infile
, pos
, len
, f
);
35 static int do_process_frame(deark
*c
, lctx
*d
, i64 pos1
, i64
*bytes_consumed
)
39 i64 frame_payload_size
;
45 de_dbg(c
, "frame at %d", (int)pos1
);
48 // 8-byte frame header
49 frame_type
= de_getbyte(pos
);
50 de_dbg(c
, "type: %d", (int)frame_type
);
52 frame_payload_size
= de_getu16le(pos
+1);
53 de_dbg(c
, "reported payload size: %d", (int)frame_payload_size
);
57 if(pos
+ frame_payload_size
> c
->infile
->len
) {
58 de_err(c
, "Frame goes beyond end of file");
65 do_pgc_in_pgx(c
, d
, pos
, frame_payload_size
);
66 *bytes_consumed
+= frame_payload_size
;
70 de_warn(c
, "PGT frames (text screen dumps) are not supported");
72 // The spec contradicts itself about how to figure out the frame
73 // payload size of PGT frames. First it says the size field is not
74 // used. The it says it *is* used, and is expected to always be 320.
75 // In the only example file I have, it is 317, though the actual size
76 // of the frame in that file is 320.
77 *bytes_consumed
+= 320;
82 *bytes_consumed
+= frame_payload_size
;
90 de_err(c
, "Unknown frame type (%d)", (int)frame_type
);
100 static void de_run_pgx(deark
*c
, de_module_params
*mparams
)
108 if(dbuf_memcmp(c
->infile
, 0, "PGX", 3)) {
109 // Some "PGX" files are actually .COM files with an embedded PGX file.
110 // The ones I've seen always have the PGX file at offset 1248, so look
112 if(dbuf_memcmp(c
->infile
, 0, "PGX", 1248)) {
118 de_declare_fmt(c
, "PGX (Portfolio Animation, executable)");
122 de_declare_fmt(c
, "PGX (Portfolio Animation)");
126 d
= de_malloc(c
, sizeof(lctx
));
128 d
->version
= de_getbyte(pos
+3);
129 de_dbg(c
, "Version: %d", (int)d
->version
);
133 if(pos
>= c
->infile
->len
) break;
134 ret
= do_process_frame(c
, d
, pos
, &frame_size
);
135 if(!ret
|| !frame_size
) break;
142 static int de_identify_pgx(deark
*c
)
144 if(!dbuf_memcmp(c
->infile
, 0, "PGX", 3))
149 void de_module_pgx(deark
*c
, struct deark_module_info
*mi
)
152 mi
->desc
= "Atari Portfolio animation";
153 mi
->run_fn
= de_run_pgx
;
154 mi
->identify_fn
= de_identify_pgx
;
157 // **************************************************************************
159 // **************************************************************************
161 static void de_run_pf_pgf(deark
*c
, de_module_params
*mparams
)
163 de_declare_fmt(c
, "PGF (Portfolio graphics)");
164 de_convert_and_write_image_bilevel(c
->infile
, 0, 240, 64, 240/8,
165 DE_CVTF_WHITEISZERO
, NULL
, 0);
168 static int de_identify_pf_pgf(deark
*c
)
170 if(c
->infile
->len
!= 1920) return 0;
171 if(!de_input_file_has_ext(c
, "pgf")) return 0;
175 void de_module_pf_pgf(deark
*c
, struct deark_module_info
*mi
)
178 mi
->desc
= "Atari Portfolio Graphics - uncompressed";
179 mi
->run_fn
= de_run_pf_pgf
;
180 mi
->identify_fn
= de_identify_pf_pgf
;
183 // **************************************************************************
184 // PGC - Portfolio graphics compressed
185 // **************************************************************************
187 static void de_run_pgc(deark
*c
, de_module_params
*mparams
)
189 dbuf
*unc_pixels
= NULL
;
194 de_declare_fmt(c
, "PGC (Portfolio graphics compressed)");
195 unc_pixels
= dbuf_create_membuf(c
, 1920, 1);
198 while(pos
<c
->infile
->len
) {
201 count
= (i64
)(b
& 0x7f);
204 b2
= de_getbyte(pos
);
206 dbuf_write_run(unc_pixels
, b2
, count
);
210 dbuf_copy(c
->infile
, pos
, count
, unc_pixels
);
215 de_convert_and_write_image_bilevel(unc_pixels
, 0, 240, 64, 240/8,
216 DE_CVTF_WHITEISZERO
, NULL
, 0);
217 dbuf_close(unc_pixels
);
220 static int de_identify_pgc(deark
*c
)
222 if(!dbuf_memcmp(c
->infile
, 0, "PG\x01", 3)) {
228 void de_module_pgc(deark
*c
, struct deark_module_info
*mi
)
231 mi
->desc
= "Atari Portfolio Graphics - compressed";
232 mi
->run_fn
= de_run_pgc
;
233 mi
->identify_fn
= de_identify_pgc
;