bmp: Rewrote the RLE decompressor
[deark.git] / modules / abk.c
blob9b60d5945a18be1095f8b38aeed37f667ac9ffa5
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // AMOS sprite/icon bank
7 #include <deark-private.h>
8 #include <deark-fmtutil.h>
9 DE_DECLARE_MODULE(de_module_abk);
10 DE_DECLARE_MODULE(de_module_amos_source);
12 #define CODE_AmBk 0x416d426bU
13 #define CODE_AmBs 0x416d4273U
14 #define CODE_AmIc 0x416d4963U
15 #define CODE_AmSp 0x416d5370U
17 // Data related to the whole file.
18 typedef struct localctx_struct {
19 u32 fmt;
20 } lctx;
22 // Data related to a "bank". Most files consist of one bank, but some have
23 // multiple banks.
24 struct amosbank {
25 struct de_fourcc banktype4cc;
26 i64 bank_len;
27 i64 bank_data_len;
28 dbuf *f;
29 const char *file_ext;
31 i64 num_objects;
32 i64 pal_pos;
33 u32 pal[256];
35 // per-image settings
36 i64 xsize; // 16-bit words per row per plane
37 i64 ysize;
38 i64 nplanes;
39 i64 max_planes;
41 // Picture Bank settings
42 i64 pic_rledata_offset;
43 i64 pic_points_offset;
44 i64 pic_picdata_offset;
45 i64 picdata_expected_unc_bytes;
46 u32 amiga_mode;
49 static void do_read_sprite_image(deark *c, lctx *d, struct amosbank *bk, i64 pos)
51 i64 width, height;
52 i64 rowspan, planespan;
53 de_bitmap *img = NULL;
55 width = bk->xsize * 16;
56 height = bk->ysize;
58 de_dbg_dimensions(c, width, height);
59 de_dbg(c, "planes: %d", (int)bk->nplanes);
60 if(!de_good_image_dimensions(c, width, height)) goto done;
61 if(bk->nplanes<1 || bk->nplanes>6) {
62 de_err(c, "Unsupported number of planes: %d", (int)bk->nplanes);
63 goto done;
66 img = de_bitmap_create(c, width, height, 4);
68 rowspan = bk->xsize*2;
69 planespan = rowspan*bk->ysize;
70 de_convert_image_paletted_planar(bk->f, pos, bk->nplanes,
71 rowspan, planespan, bk->pal, img, 0x2);
73 de_bitmap_write_to_file(img, NULL, 0);
75 done:
76 de_bitmap_destroy(img);
79 static int do_sprite_object(deark *c, lctx *d, struct amosbank *bk, i64 obj_idx,
80 i64 pos, int pass, i64 *bytes_consumed)
83 if(pass==2) {
84 de_dbg(c, "object #%d at %d", (int)obj_idx, (int)pos);
86 de_dbg_indent(c, 1);
88 bk->xsize = dbuf_getu16be(bk->f, pos);
89 bk->ysize = dbuf_getu16be(bk->f, pos+2);
90 bk->nplanes = dbuf_getu16be(bk->f, pos+4);
92 if(pass==1) {
93 if(bk->nplanes > bk->max_planes) {
94 bk->max_planes = bk->nplanes;
98 if(pass==2) {
99 do_read_sprite_image(c, d, bk, pos+10);
102 *bytes_consumed = 10 + (bk->xsize*bk->ysize*bk->nplanes*2);
104 de_dbg_indent(c, -1);
105 return 1;
108 // pass 1 is just to find the location of the palette/
109 // pass 2 decodes the images.
110 static void do_read_sprite_objects(deark *c, lctx *d, struct amosbank *bk, i64 pos, int pass)
112 int ret;
113 i64 bytes_consumed;
114 i64 obj_idx;
116 de_dbg(c, "pass %d", pass);
118 obj_idx = 0;
119 while(1) {
120 if(pos >= bk->f->len) break;
121 if(obj_idx >= bk->num_objects) break;
122 bytes_consumed = 0;
123 ret = do_sprite_object(c, d, bk, obj_idx, pos, pass, &bytes_consumed);
124 if(!ret || bytes_consumed<1) break;
125 pos += bytes_consumed;
126 obj_idx++;
129 if(pass==1) {
130 bk->pal_pos = pos;
131 bk->bank_len = bk->pal_pos + 64;
132 de_dbg(c, "palette offset: %d", (int)bk->pal_pos);
133 de_dbg(c, "bank len: %d", (int)bk->bank_len);
137 static void do_read_sprite_palette(deark *c, lctx *d, struct amosbank *bk)
139 i64 k;
140 unsigned int n;
141 u8 cr, cg, cb;
142 u8 cr1, cg1, cb1;
143 i64 pos;
144 i64 colors_used;
145 char tmps[64];
147 pos = bk->pal_pos;
148 de_dbg(c, "palette at %d", (int)pos);
149 de_dbg_indent(c, 1);
151 colors_used = de_pow2(bk->max_planes);
153 for(k=0; k<32; k++) {
154 n = (unsigned int)dbuf_getu16be(bk->f, pos+k*2);
155 cr1 = (u8)((n>>8)&0xf);
156 cg1 = (u8)((n>>4)&0xf);
157 cb1 = (u8)(n&0xf);
158 cr = cr1*17;
159 cg = cg1*17;
160 cb = cb1*17;
161 bk->pal[k] = DE_MAKE_RGB(cr, cg, cb);
162 de_snprintf(tmps, sizeof(tmps), "0x%04x (%2d,%2d,%2d) "DE_CHAR_RIGHTARROW" ",
163 n, (int)cr1, (int)cg1, (int)cb1);
164 de_dbg_pal_entry2(c, k, bk->pal[k], tmps, NULL,
165 (k>=colors_used)?" [unused]":"");
167 // Set up colors #32-63 for 6-plane "Extra Half-Brite" mode.
168 // For normal images (<=5 planes), these colors won't be used.
169 bk->pal[k+32] = DE_MAKE_RGB(cr/2, cg/2, cb/2);
172 bk->pal[0] = DE_SET_ALPHA(bk->pal[0], 0); // First color is transparent.
173 // (Don't know if pal[32] should be transparent also.)
175 de_dbg_indent(c, -1);
178 // AmSp or AmIc
179 static int do_read_sprite(deark *c, lctx *d, struct amosbank *bk)
181 bk->num_objects = dbuf_getu16be(bk->f, 4);
182 de_dbg(c, "number of objects: %d", (int)bk->num_objects);
184 do_read_sprite_objects(c, d, bk, 6, 1);
186 if(d->fmt==CODE_AmBs) {
187 dbuf_create_file_from_slice(bk->f, 0, bk->bank_len, bk->file_ext, NULL, 0);
189 else {
190 do_read_sprite_palette(c, d, bk);
192 do_read_sprite_objects(c, d, bk, 6, 2);
195 return 1;
198 #define MEMBANKTYPE_DATAS 1
199 #define MEMBANKTYPE_MUSIC 2
200 #define MEMBANKTYPE_PICTURE 3
201 #define MEMBANKTYPE_ASM 4
202 #define MEMBANKTYPE_AMAL 5
203 #define MEMBANKTYPE_SAMPLES 6
205 struct membankinfo {
206 int type;
207 const u8 name[8];
208 const char *file_ext;
210 static const struct membankinfo membankinfo_arr[] = {
211 { MEMBANKTYPE_DATAS, {'D','a','t','a','s',' ',' ',' '}, "data.abk" },
212 { MEMBANKTYPE_MUSIC, {'M','u','s','i','c',' ',' ',' '}, "music.abk" },
213 { MEMBANKTYPE_PICTURE, {'P','a','c','.','P','i','c','.'}, "pic.abk" },
214 { MEMBANKTYPE_ASM, {'A','s','m',' ',' ',' ',' ',' '}, "asm.abk" },
215 { MEMBANKTYPE_AMAL, {'A','m','a','l',' ',' ',' ',' '}, "amal.abk" },
216 { MEMBANKTYPE_SAMPLES, {'S','a','m','p','l','e','s',' '}, "samples.abk" },
217 { 0, {0,0,0,0,0,0,0,0}, NULL }
220 // 90-byte "Screen header"
221 // Has information about the intended display device. Not much of this
222 // is useful, other than the palette.
223 static void picture_bank_screen_header(deark *c, lctx *d, struct amosbank *bk, i64 pos)
225 i64 screen_width, screen_height;
226 i64 ncolors;
227 i64 nplanes;
229 de_dbg(c, "screen header at %d", (int)pos);
230 de_dbg_indent(c, 1);
232 screen_width = dbuf_getu16be(bk->f, pos+4);
233 screen_height = dbuf_getu16be(bk->f, pos+6);
234 de_dbg(c, "screen dimensions: %d"DE_CHAR_TIMES"%d", (int)screen_width, (int)screen_height);
236 bk->amiga_mode = (u32)dbuf_getu16be(bk->f, pos+20);
237 ncolors = dbuf_getu16be(bk->f, pos+22);
238 nplanes = dbuf_getu16be(bk->f, pos+24);
240 de_dbg(c, "screen mode: 0x%04x, colors: %d, planes: %d",
241 (unsigned int)bk->amiga_mode, (int)ncolors, (int)nplanes);
243 bk->pal_pos = pos + 26;
245 // Set bk->max_planes, so that do_read_sprite_palette doesn't print
246 // "[unused]".
247 // TODO: We could look ahead at the picture header to figure out how many
248 // palette entries are used. Or we could just guess that it's the same as
249 // 'nplanes' in the screen header.
250 bk->max_planes = 5;
251 do_read_sprite_palette(c, d, bk);
252 bk->max_planes = 0;
254 de_dbg_indent(c, -1);
257 struct pictbank_params {
258 u8 ok;
259 UI num_planes;
260 UI bits_per_pixel;
261 i64 width_in_bytes;
262 i64 height_in_lumps;
263 i64 lines_per_lump;
264 i64 pseudoheight;
265 dbuf *unc_pixels;
266 de_bitmap *img;
267 de_color *pal;
270 // TODO: Consolidate this with the similar function in mbk.c.
271 // (Deferred for now. Should probably at least investigate HAM picture banks,
272 // first.)
273 static void render_stos_pictbank(deark *c, struct pictbank_params *pb)
275 i64 planesize;
276 i64 lump;
277 u8 xbuf[8];
279 if((size_t)pb->num_planes > sizeof(xbuf)) goto done;
280 if(pb->bits_per_pixel != pb->num_planes) goto done;
281 de_zeromem(xbuf, sizeof(xbuf));
282 planesize = pb->width_in_bytes * pb->pseudoheight;
284 for(lump=0; lump<pb->height_in_lumps; lump++) {
285 i64 col_idx;
286 i64 lump_start_srcpos_in_plane;
287 i64 lump_start_ypos;
289 lump_start_srcpos_in_plane = pb->width_in_bytes * pb->lines_per_lump * lump;
290 lump_start_ypos = pb->lines_per_lump * lump;
292 for(col_idx=0; col_idx<pb->width_in_bytes; col_idx++) {
293 i64 col_start_srcpos_in_plane;
294 i64 ypos_in_lump;
296 col_start_srcpos_in_plane = lump_start_srcpos_in_plane +
297 pb->lines_per_lump*col_idx;
299 for(ypos_in_lump=0; ypos_in_lump<pb->lines_per_lump; ypos_in_lump++) {
300 UI i;
301 UI pn;
302 i64 xpos, ypos;
304 ypos = lump_start_ypos + ypos_in_lump;
306 for(pn=0; pn<pb->num_planes; pn++) {
307 xbuf[pn] = dbuf_getbyte(pb->unc_pixels, planesize*pn +
308 col_start_srcpos_in_plane + ypos_in_lump);
311 for(i=0; i<8; i++) {
312 UI palent;
314 palent = 0;
315 for(pn=0; pn<pb->bits_per_pixel; pn++) {
316 if(xbuf[pn] & (1<<(7-i))) {
317 palent |= (1<<pn);
321 xpos = col_idx*8 + i;
322 de_bitmap_setpixel_rgb(pb->img, xpos, ypos, pb->pal[palent]);
328 pb->ok = 1;
330 done:
334 static void picture_bank_read_picture(deark *c, lctx *d, struct amosbank *bk, i64 pos)
336 i64 bytes_per_row_per_plane;
337 i64 height_in_lumps;
338 i64 lines_per_lump;
339 i64 width, height;
340 de_bitmap *img = NULL;
341 dbuf *unc_pixels = NULL;
342 struct pictbank_params *pb = NULL;
343 int saved_indent_level;
345 de_dbg_indent_save(c, &saved_indent_level);
346 de_dbg(c, "picture header at %d", (int)pos);
347 de_dbg_indent(c, 1);
349 // 24-byte "Picture header"
351 bytes_per_row_per_plane = dbuf_getu16be(bk->f, pos+8);
352 de_dbg(c, "bytes per row per plane: %d", (int)bytes_per_row_per_plane);
353 width = bytes_per_row_per_plane * 8;
355 height_in_lumps = dbuf_getu16be(bk->f, pos+10);
356 de_dbg(c, "height in lumps: %d", (int)height_in_lumps);
357 lines_per_lump = dbuf_getu16be(bk->f, pos+12);
358 de_dbg(c, "lines per lump: %d", (int)lines_per_lump);
359 height = height_in_lumps * lines_per_lump;
361 de_dbg(c, "calculated dimensions: %d"DE_CHAR_TIMES"%d", (int)width, (int)height);
363 bk->nplanes = dbuf_getu16be(bk->f, pos+14);
364 de_dbg(c, "number of bitplanes: %d", (int)bk->nplanes);
366 bk->pic_rledata_offset = dbuf_getu32be(bk->f, pos+16);
367 de_dbg(c, "rledata offset: %d (file offset: %d)", (int)bk->pic_rledata_offset,
368 (int)(pos+bk->pic_rledata_offset));
369 bk->pic_rledata_offset += pos; // Convert to absolute offset
371 bk->pic_points_offset = dbuf_getu32be(bk->f, pos+20);
372 de_dbg(c, "points offset: %d (file offset: %d)", (int)bk->pic_points_offset,
373 (int)(pos+bk->pic_points_offset));
374 bk->pic_points_offset += pos; // Convert to absolute offset
376 if(!de_good_image_dimensions(c, width, height)) goto done;
377 if(bk->nplanes<1 || bk->nplanes>6) {
378 de_err(c, "Unsupported number of planes: %d", (int)bk->nplanes);
379 goto done;
382 de_dbg_indent(c, -1);
384 bk->pic_picdata_offset = pos + 24;
385 de_dbg(c, "picdata at %d", (int)bk->pic_picdata_offset);
387 bk->picdata_expected_unc_bytes = bytes_per_row_per_plane * bk->nplanes * height;
388 unc_pixels = dbuf_create_membuf(c, bk->picdata_expected_unc_bytes, 0);
389 fmtutil_decompress_stos_pictbank(c, c->infile, bk->pic_picdata_offset,
390 bk->pic_rledata_offset, bk->pic_points_offset,
391 unc_pixels, bk->picdata_expected_unc_bytes);
392 img = de_bitmap_create(c, width, height, 3);
394 pb = de_malloc(c, sizeof(struct pictbank_params));
395 pb->num_planes = (UI)bk->nplanes;
396 pb->bits_per_pixel = pb->num_planes;
397 pb->width_in_bytes = bytes_per_row_per_plane;
398 pb->height_in_lumps = height_in_lumps;
399 pb->lines_per_lump = lines_per_lump;
400 pb->pseudoheight = height;
401 pb->unc_pixels = unc_pixels;
402 pb->img = img;
403 pb->pal = bk->pal;
405 render_stos_pictbank(c, pb);
407 de_bitmap_write_to_file(img, NULL, 0);
408 done:
409 dbuf_close(unc_pixels);
410 de_bitmap_destroy(img);
411 de_free(c, pb);
412 de_dbg_indent_restore(c, saved_indent_level);
415 static void picture_bank_make_palette(deark *c, lctx *d, struct amosbank *bk)
417 i64 k;
418 u8 v;
420 de_warn(c, "No palette found. Using grayscale palette.");
421 for(k=0; k<32; k++) {
422 v = (u8)(0.5+ ((double)k)*(255.0/31.0));
423 bk->pal[k] = DE_MAKE_GRAY(v);
424 bk->pal[k+32] = DE_MAKE_GRAY(v/2);
428 static void do_picture_bank(deark *c, lctx *d, struct amosbank *bk)
430 i64 pos = 0;
431 u32 segtype;
432 int found_screen_header = 0;
434 de_dbg(c, "picture bank");
436 pos += 20; // Advance past AmBk header
438 segtype = (u32)de_getu32be(pos);
439 if(segtype==0x12031990) {
440 found_screen_header = 1;
441 picture_bank_screen_header(c, d, bk, pos);
442 pos += 90;
444 if(bk->amiga_mode & 0x0800) {
445 de_err(c, "HAM Picture Bank images are not supported.");
446 goto done;
449 segtype = (u32)de_getu32be(pos);
452 if(segtype!=0x06071963) {
453 de_err(c, "Missing Picture Header");
454 goto done;
457 if(!found_screen_header) {
458 picture_bank_make_palette(c, d, bk);
461 picture_bank_read_picture(c, d, bk, pos);
463 done:
467 static int do_read_AmBk(deark *c, lctx *d, struct amosbank *bk)
469 i64 banknum;
470 i64 bank_len_code;
471 i64 bank_len_raw;
472 int membanktype = 0;
473 const struct membankinfo *mbi = NULL;
474 struct de_stringreaderdata *srd = NULL;
475 i64 i;
476 int retval = 0;
478 if(bk->f->len < 20) goto done;
480 banknum = dbuf_getu16be(bk->f, 4);
481 de_dbg(c, "bank number (1-15): %d", (int)banknum);
483 bank_len_code = dbuf_getu32be(bk->f, 8);
484 bank_len_raw = bank_len_code & 0x0fffffff;
485 bk->bank_len = bank_len_raw+12;
486 bk->bank_data_len = bank_len_raw-8;
487 de_dbg(c, "bank length: %d (dlen=%d, tlen=%d)", (int)bank_len_raw,
488 (int)bk->bank_data_len, (int)bk->bank_len);
490 srd = dbuf_read_string(bk->f, 12, 8, 8, 0, DE_ENCODING_ASCII);
491 de_dbg(c, "bank name: \"%s\"", ucstring_getpsz(srd->str));
493 if(bk->bank_data_len<0) goto done;
495 for(i=0; membankinfo_arr[i].type!=0; i++) {
496 if(!de_memcmp(srd->sz, membankinfo_arr[i].name, 8)) {
497 mbi = &membankinfo_arr[i];
498 break;
502 if(mbi) {
503 membanktype = mbi->type;
504 bk->file_ext = mbi->file_ext;
507 if(d->fmt==CODE_AmBs) {
508 // If original file is in AmBs format, just extract the AmBk file.
509 dbuf_create_file_from_slice(bk->f, 0, bk->bank_len, bk->file_ext, NULL, 0);
510 retval = 1;
511 goto done;
514 switch(membanktype) {
515 case MEMBANKTYPE_PICTURE:
516 do_picture_bank(c, d, bk);
517 retval = 1;
518 goto done;
521 if(c->extract_level>=2) {
522 // Extracting the raw memory-bank data can be useful sometimes.
523 dbuf_create_file_from_slice(bk->f, 20, bk->bank_data_len, "bin", NULL, 0);
526 retval = 1;
527 done:
528 de_destroy_stringreaderdata(c, srd);
529 return retval;
532 static int do_read_bank(deark *c, lctx *d, i64 pos, i64 *bytesused)
534 struct amosbank *bk = NULL;
535 int ret;
536 int retval = 0;
538 bk = de_malloc(c, sizeof(struct amosbank));
539 bk->f = dbuf_open_input_subfile(c->infile, pos, c->infile->len - pos);
541 dbuf_read_fourcc(bk->f, 0, &bk->banktype4cc, 4, 0x0);
542 de_dbg(c, "bank type '%s'", bk->banktype4cc.id_dbgstr);
544 switch(bk->banktype4cc.id) {
545 case CODE_AmIc: bk->file_ext = "icon.abk"; break;
546 case CODE_AmSp: bk->file_ext = "sprite.abk"; break;
547 case CODE_AmBk: bk->file_ext = "AmBk.abk"; break;
548 default: bk->file_ext = "abk";
551 if(bk->banktype4cc.id==CODE_AmIc || bk->banktype4cc.id==CODE_AmSp) {
552 ret = do_read_sprite(c, d, bk);
553 retval = ret;
554 *bytesused = bk->bank_len;
556 else if(bk->banktype4cc.id==CODE_AmBk) {
557 ret = do_read_AmBk(c, d, bk);
558 retval = ret;
559 *bytesused = bk->bank_len;
561 else {
562 de_err(c, "Unsupported bank type: '%s'", bk->banktype4cc.id_sanitized_sz);
565 if(bk) {
566 dbuf_close(bk->f);
567 de_free(c, bk);
569 return retval;
572 static void do_read_AmBs(deark *c, lctx *d)
574 i64 bytesused;
575 i64 nbanks;
576 i64 i;
577 i64 pos;
578 int ret;
580 nbanks = de_getu16be(4);
581 de_dbg(c, "number of banks: %d", (int)nbanks);
583 pos = 6;
584 for(i=0; i<nbanks; i++) {
585 if(pos >= c->infile->len) break;
586 de_dbg(c, "bank #%d at %d", (int)i, (int)pos);
587 bytesused = 0;
588 de_dbg_indent(c, 1);
589 ret = do_read_bank(c, d, pos, &bytesused);
590 de_dbg_indent(c, -1);
591 if(!ret || bytesused<1) break;
592 pos += bytesused;
596 static void de_run_abk(deark *c, de_module_params *mparams)
598 lctx *d = NULL;
599 i64 bytesused = 0;
601 d = de_malloc(c, sizeof(lctx));
603 d->fmt = (u32)de_getu32be(0);
605 if(d->fmt==CODE_AmBk) {
606 de_declare_fmt(c, "AMOS Memory Bank");
608 else if(d->fmt==CODE_AmSp) {
609 de_declare_fmt(c, "AMOS Sprite Bank");
611 else if(d->fmt==CODE_AmIc) {
612 de_declare_fmt(c, "AMOS Icon Bank");
614 else if(d->fmt==CODE_AmBs) {
615 de_declare_fmt(c, "AMOS AmBs format");
617 else {
618 de_err(c, "Unsupported format");
619 goto done;
622 if(d->fmt==CODE_AmBk ||d->fmt==CODE_AmSp || d->fmt==CODE_AmIc) {
623 do_read_bank(c, d, 0, &bytesused);
625 else if(d->fmt==CODE_AmBs) {
626 do_read_AmBs(c, d);
629 done:
630 de_free(c, d);
633 static int de_identify_abk(deark *c)
635 u8 b[4];
636 int ext_bonus = 0;
638 if(de_input_file_has_ext(c, "abk")) ext_bonus=40;
640 de_read(b, 0, 4);
641 if(!de_memcmp(b, "AmBk", 4))
642 return 60+ext_bonus;
643 if(!de_memcmp(b, "AmSp", 4))
644 return 60+ext_bonus;
645 if(!de_memcmp(b, "AmIc", 4))
646 return 60+ext_bonus;
647 if(!de_memcmp(b, "AmBs", 4))
648 return 60+ext_bonus;
649 return 0;
652 void de_module_abk(deark *c, struct deark_module_info *mi)
654 mi->id = "abk";
655 mi->desc = "AMOS resource (AmBk, sprite, icon, AmBs)";
656 mi->run_fn = de_run_abk;
657 mi->identify_fn = de_identify_abk;
660 static void de_run_amos_source(deark *c, de_module_params *mparams)
662 lctx *d = NULL;
663 i64 basic_len;
664 i64 pos;
665 i64 nbanks;
667 d = de_malloc(c, sizeof(lctx));
669 pos = 16;
670 basic_len = de_getu32be(pos);
671 pos += 4;
672 de_dbg(c, "BASIC code at %d, len=%d", (int)pos, (int)basic_len);
673 pos += basic_len;
674 if(pos >= c->infile->len) goto done;
675 if(dbuf_memcmp(c->infile, pos, "AmBs", 4)) {
676 de_err(c, "AmBs segment not found, expected at offset %d", (int)pos);
677 goto done;
680 de_dbg(c, "AmBs segment at %d", (int)pos);
681 nbanks = de_getu16be(pos+4);
682 de_dbg_indent(c, 1);
683 de_dbg(c, "number of banks: %d", (int)nbanks);
684 if(nbanks>0 || c->extract_level>=2) {
685 dbuf_create_file_from_slice(c->infile, pos, c->infile->len-pos, "AmBs.abk", NULL, 0);
687 else {
688 de_dbg(c, "not extracting empty AmBs segment");
690 de_dbg_indent(c, -1);
693 done:
694 de_free(c, d);
697 static int de_identify_amos_source(deark *c)
699 u8 b[10];
700 int ext_bonus = 0;
702 if(de_input_file_has_ext(c, "amos")) ext_bonus=20;
704 de_read(b, 0, 10);
705 if(!de_memcmp(b, "AMOS Basic", 10))
706 return 80+ext_bonus;
707 if(!de_memcmp(b, "AMOS Pro", 8))
708 return 80+ext_bonus;
709 return 0;
712 void de_module_amos_source(deark *c, struct deark_module_info *mi)
714 mi->id = "amos_source";
715 mi->desc = "AMOS source code";
716 mi->run_fn = de_run_amos_source;
717 mi->identify_fn = de_identify_amos_source;