New "ea_data" module
[deark.git] / modules / abk.c
blob03ef37a0f15dbbcf8ba685eb5a4326bb1d4a318b
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-config.h>
8 #include <deark-private.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 i, j;
53 i64 plane;
54 unsigned int palent;
55 u8 b;
56 i64 rowspan, planespan;
57 u32 clr;
58 de_bitmap *img = NULL;
60 width = bk->xsize * 16;
61 height = bk->ysize;
63 de_dbg_dimensions(c, width, height);
64 de_dbg(c, "planes: %d", (int)bk->nplanes);
65 if(!de_good_image_dimensions(c, width, height)) goto done;
66 if(bk->nplanes<1 || bk->nplanes>6) {
67 de_err(c, "Unsupported number of planes: %d", (int)bk->nplanes);
68 goto done;
71 img = de_bitmap_create(c, width, height, 4);
73 rowspan = bk->xsize*2;
74 planespan = rowspan*bk->ysize;
76 for(j=0; j<height; j++) {
77 for(i=0; i<width; i++) {
78 palent = 0;
79 for(plane=0; plane<bk->nplanes; plane++) {
80 b = de_get_bits_symbol(bk->f, 1, pos + plane*planespan + j*rowspan, i);
81 if(b) palent |= (1<<plane);
83 if(palent<=255) clr = bk->pal[palent];
84 else clr=0;
86 de_bitmap_setpixel_rgb(img, i, j, clr);
90 de_bitmap_write_to_file(img, NULL, 0);
92 done:
93 de_bitmap_destroy(img);
96 static int do_sprite_object(deark *c, lctx *d, struct amosbank *bk, i64 obj_idx,
97 i64 pos, int pass, i64 *bytes_consumed)
100 if(pass==2) {
101 de_dbg(c, "object #%d at %d", (int)obj_idx, (int)pos);
103 de_dbg_indent(c, 1);
105 bk->xsize = dbuf_getu16be(bk->f, pos);
106 bk->ysize = dbuf_getu16be(bk->f, pos+2);
107 bk->nplanes = dbuf_getu16be(bk->f, pos+4);
109 if(pass==1) {
110 if(bk->nplanes > bk->max_planes) {
111 bk->max_planes = bk->nplanes;
115 if(pass==2) {
116 do_read_sprite_image(c, d, bk, pos+10);
119 *bytes_consumed = 10 + (bk->xsize*bk->ysize*bk->nplanes*2);
121 de_dbg_indent(c, -1);
122 return 1;
125 // pass 1 is just to find the location of the palette/
126 // pass 2 decodes the images.
127 static void do_read_sprite_objects(deark *c, lctx *d, struct amosbank *bk, i64 pos, int pass)
129 int ret;
130 i64 bytes_consumed;
131 i64 obj_idx;
133 de_dbg(c, "pass %d", pass);
135 obj_idx = 0;
136 while(1) {
137 if(pos >= bk->f->len) break;
138 if(obj_idx >= bk->num_objects) break;
139 bytes_consumed = 0;
140 ret = do_sprite_object(c, d, bk, obj_idx, pos, pass, &bytes_consumed);
141 if(!ret || bytes_consumed<1) break;
142 pos += bytes_consumed;
143 obj_idx++;
146 if(pass==1) {
147 bk->pal_pos = pos;
148 bk->bank_len = bk->pal_pos + 64;
149 de_dbg(c, "palette offset: %d", (int)bk->pal_pos);
150 de_dbg(c, "bank len: %d", (int)bk->bank_len);
154 static void do_read_sprite_palette(deark *c, lctx *d, struct amosbank *bk)
156 i64 k;
157 unsigned int n;
158 u8 cr, cg, cb;
159 u8 cr1, cg1, cb1;
160 i64 pos;
161 i64 colors_used;
162 char tmps[64];
164 pos = bk->pal_pos;
165 de_dbg(c, "palette at %d", (int)pos);
166 de_dbg_indent(c, 1);
168 colors_used = de_pow2(bk->max_planes);
170 for(k=0; k<32; k++) {
171 n = (unsigned int)dbuf_getu16be(bk->f, pos+k*2);
172 cr1 = (u8)((n>>8)&0xf);
173 cg1 = (u8)((n>>4)&0xf);
174 cb1 = (u8)(n&0xf);
175 cr = cr1*17;
176 cg = cg1*17;
177 cb = cb1*17;
178 bk->pal[k] = DE_MAKE_RGB(cr, cg, cb);
179 de_snprintf(tmps, sizeof(tmps), "0x%04x (%2d,%2d,%2d) "DE_CHAR_RIGHTARROW" ",
180 n, (int)cr1, (int)cg1, (int)cb1);
181 de_dbg_pal_entry2(c, k, bk->pal[k], tmps, NULL,
182 (k>=colors_used)?" [unused]":"");
184 // Set up colors #32-63 for 6-plane "Extra Half-Brite" mode.
185 // For normal images (<=5 planes), these colors won't be used.
186 bk->pal[k+32] = DE_MAKE_RGB(cr/2, cg/2, cb/2);
189 bk->pal[0] = DE_SET_ALPHA(bk->pal[0], 0); // First color is transparent.
190 // (Don't know if pal[32] should be transparent also.)
192 de_dbg_indent(c, -1);
195 // AmSp or AmIc
196 static int do_read_sprite(deark *c, lctx *d, struct amosbank *bk)
198 bk->num_objects = dbuf_getu16be(bk->f, 4);
199 de_dbg(c, "number of objects: %d", (int)bk->num_objects);
201 do_read_sprite_objects(c, d, bk, 6, 1);
203 if(d->fmt==CODE_AmBs) {
204 dbuf_create_file_from_slice(bk->f, 0, bk->bank_len, bk->file_ext, NULL, 0);
206 else {
207 do_read_sprite_palette(c, d, bk);
209 do_read_sprite_objects(c, d, bk, 6, 2);
212 return 1;
215 #define MEMBANKTYPE_DATAS 1
216 #define MEMBANKTYPE_MUSIC 2
217 #define MEMBANKTYPE_PICTURE 3
218 #define MEMBANKTYPE_ASM 4
219 #define MEMBANKTYPE_AMAL 5
220 #define MEMBANKTYPE_SAMPLES 6
222 struct membankinfo {
223 int type;
224 const u8 name[8];
225 const char *file_ext;
227 static const struct membankinfo membankinfo_arr[] = {
228 { MEMBANKTYPE_DATAS, {'D','a','t','a','s',' ',' ',' '}, "data.abk" },
229 { MEMBANKTYPE_MUSIC, {'M','u','s','i','c',' ',' ',' '}, "music.abk" },
230 { MEMBANKTYPE_PICTURE, {'P','a','c','.','P','i','c','.'}, "pic.abk" },
231 { MEMBANKTYPE_ASM, {'A','s','m',' ',' ',' ',' ',' '}, "asm.abk" },
232 { MEMBANKTYPE_AMAL, {'A','m','a','l',' ',' ',' ',' '}, "amal.abk" },
233 { MEMBANKTYPE_SAMPLES, {'S','a','m','p','l','e','s',' '}, "samples.abk" },
234 { 0, {0,0,0,0,0,0,0,0}, NULL }
237 // 90-byte "Screen header"
238 // Has information about the intended display device. Not much of this
239 // is useful, other than the palette.
240 static void picture_bank_screen_header(deark *c, lctx *d, struct amosbank *bk, i64 pos)
242 i64 screen_width, screen_height;
243 i64 ncolors;
244 i64 nplanes;
246 de_dbg(c, "screen header at %d", (int)pos);
247 de_dbg_indent(c, 1);
249 screen_width = dbuf_getu16be(bk->f, pos+4);
250 screen_height = dbuf_getu16be(bk->f, pos+6);
251 de_dbg(c, "screen dimensions: %d"DE_CHAR_TIMES"%d", (int)screen_width, (int)screen_height);
253 bk->amiga_mode = (u32)dbuf_getu16be(bk->f, pos+20);
254 ncolors = dbuf_getu16be(bk->f, pos+22);
255 nplanes = dbuf_getu16be(bk->f, pos+24);
257 de_dbg(c, "screen mode: 0x%04x, colors: %d, planes: %d",
258 (unsigned int)bk->amiga_mode, (int)ncolors, (int)nplanes);
260 bk->pal_pos = pos + 26;
262 // Set bk->max_planes, so that do_read_sprite_palette doesn't print
263 // "[unused]".
264 // TODO: We could look ahead at the picture header to figure out how many
265 // palette entries are used. Or we could just guess that it's the same as
266 // 'nplanes' in the screen header.
267 bk->max_planes = 5;
268 do_read_sprite_palette(c, d, bk);
269 bk->max_planes = 0;
271 de_dbg_indent(c, -1);
274 static void picture_bank_uncompress(deark *c, lctx *d, struct amosbank *bk,
275 dbuf *unc_pixels)
277 i64 picdatapos; // file offset of next unread byte
278 i64 rledatapos;
279 i64 pointspos;
280 u8 picbyte;
281 u8 rlebyte;
282 u8 pointsbyte;
283 int rbitnum, pbitnum;
285 de_dbg(c, "uncompressing picture");
286 de_dbg_indent(c, 1);
288 picdatapos = bk->pic_picdata_offset;
289 rledatapos = bk->pic_rledata_offset;
290 pointspos = bk->pic_points_offset;
292 picbyte = dbuf_getbyte(bk->f, picdatapos++);
293 rlebyte = dbuf_getbyte(bk->f, rledatapos++);
294 rbitnum = 7;
295 pointsbyte = dbuf_getbyte(bk->f, pointspos++);
296 pbitnum = 7;
298 if(pointsbyte & (1 << pbitnum--)) {
299 rlebyte = dbuf_getbyte(bk->f, rledatapos++);
302 while(1) {
303 if(unc_pixels->len >= bk->picdata_expected_unc_bytes) break;
304 if(rlebyte & (1 << rbitnum--)) {
305 picbyte = dbuf_getbyte(bk->f, picdatapos++);
308 dbuf_writebyte(unc_pixels, picbyte);
310 if(rbitnum < 0) {
311 if(pointsbyte & (1 << pbitnum--)) {
312 rlebyte = dbuf_getbyte(bk->f, rledatapos++);
314 rbitnum = 7;
316 if(pbitnum < 0) {
317 pointsbyte = dbuf_getbyte(bk->f, pointspos++);
318 pbitnum = 7;
324 i64 cmpr_pic_bytes, cmpr_rle_bytes, points_bytes;
326 cmpr_pic_bytes = picdatapos - bk->pic_picdata_offset;
327 cmpr_rle_bytes = rledatapos - bk->pic_rledata_offset;
328 points_bytes = pointspos - bk->pic_points_offset;
329 de_dbg(c, "compressed pic bytes: %d", (int)cmpr_pic_bytes);
330 de_dbg(c, "compressed rle bytes: %d", (int)cmpr_rle_bytes);
331 de_dbg(c, "points bytes: %d", (int)points_bytes);
332 de_dbg(c, "uncompressed %d bytes to %d bytes",
333 (int)(cmpr_pic_bytes + cmpr_rle_bytes + points_bytes),
334 (int)unc_pixels->len);
337 de_dbg_indent(c, -1);
340 static void picture_bank_read_picture(deark *c, lctx *d, struct amosbank *bk, i64 pos)
342 i64 bytes_per_row_per_plane;
343 i64 height_in_lumps;
344 i64 lines_per_lump;
345 i64 width, height;
346 de_bitmap *img = NULL;
347 dbuf *unc_pixels = NULL;
348 i64 k;
349 i64 xpos, ypos;
350 i64 lump;
351 i64 line_in_lump;
352 i64 strip;
353 i64 plane;
354 unsigned int palent;
355 u8 x;
356 i64 planespan;
357 i64 lumpspan;
358 i64 pos_in_picdata;
359 int saved_indent_level;
361 de_dbg_indent_save(c, &saved_indent_level);
362 de_dbg(c, "picture header at %d", (int)pos);
363 de_dbg_indent(c, 1);
365 // 24-byte "Picture header"
367 bytes_per_row_per_plane = dbuf_getu16be(bk->f, pos+8);
368 de_dbg(c, "bytes per row per plane: %d", (int)bytes_per_row_per_plane);
369 width = bytes_per_row_per_plane * 8;
371 height_in_lumps = dbuf_getu16be(bk->f, pos+10);
372 de_dbg(c, "height in lumps: %d", (int)height_in_lumps);
373 lines_per_lump = dbuf_getu16be(bk->f, pos+12);
374 de_dbg(c, "lines per lump: %d", (int)lines_per_lump);
375 height = height_in_lumps * lines_per_lump;
377 de_dbg(c, "calculated dimensions: %d"DE_CHAR_TIMES"%d", (int)width, (int)height);
379 bk->nplanes = dbuf_getu16be(bk->f, pos+14);
380 de_dbg(c, "number of bitplanes: %d", (int)bk->nplanes);
382 bk->pic_rledata_offset = dbuf_getu32be(bk->f, pos+16);
383 de_dbg(c, "rledata offset: %d (file offset: %d)", (int)bk->pic_rledata_offset,
384 (int)(pos+bk->pic_rledata_offset));
385 bk->pic_rledata_offset += pos; // Convert to absolute offset
387 bk->pic_points_offset = dbuf_getu32be(bk->f, pos+20);
388 de_dbg(c, "points offset: %d (file offset: %d)", (int)bk->pic_points_offset,
389 (int)(pos+bk->pic_points_offset));
390 bk->pic_points_offset += pos; // Convert to absolute offset
392 if(!de_good_image_dimensions(c, width, height)) goto done;
393 if(bk->nplanes<1 || bk->nplanes>6) {
394 de_err(c, "Unsupported number of planes: %d", (int)bk->nplanes);
395 goto done;
398 de_dbg_indent(c, -1);
400 bk->pic_picdata_offset = pos + 24;
401 de_dbg(c, "picdata at %d", (int)bk->pic_picdata_offset);
403 bk->picdata_expected_unc_bytes = bytes_per_row_per_plane * bk->nplanes * height;
404 unc_pixels = dbuf_create_membuf(c, bk->picdata_expected_unc_bytes, 0);
405 picture_bank_uncompress(c, d, bk, unc_pixels);
407 img = de_bitmap_create(c, width, height, 3);
409 lumpspan = bytes_per_row_per_plane * lines_per_lump;
410 planespan = lumpspan * height_in_lumps;
411 pos_in_picdata = 0;
412 ypos=0;
413 for(lump=0; lump<height_in_lumps; lump++) {
414 xpos = 0;
415 for(strip=0; strip<bytes_per_row_per_plane; strip++) {
416 for(line_in_lump=0; line_in_lump<lines_per_lump; line_in_lump++) {
417 for(k=0; k<8; k++) {
418 palent = 0;
419 for(plane=0; plane<bk->nplanes; plane++) {
420 x = de_get_bits_symbol(unc_pixels, 1, pos_in_picdata + plane*planespan, k);
421 if(x) palent |= 1<<plane;
423 if(palent<=255) {
424 de_bitmap_setpixel_rgb(img, xpos, ypos, bk->pal[palent]);
426 xpos++;
428 pos_in_picdata++;
429 xpos-=8;
430 ypos++;
432 xpos+=8;
433 ypos -= lines_per_lump;
435 ypos += lines_per_lump;
438 de_bitmap_write_to_file(img, NULL, 0);
439 done:
440 dbuf_close(unc_pixels);
441 de_bitmap_destroy(img);
442 de_dbg_indent_restore(c, saved_indent_level);
445 static void picture_bank_make_palette(deark *c, lctx *d, struct amosbank *bk)
447 i64 k;
448 u8 v;
450 de_warn(c, "No palette found. Using grayscale palette.");
451 for(k=0; k<32; k++) {
452 v = (u8)(0.5+ ((double)k)*(255.0/31.0));
453 bk->pal[k] = DE_MAKE_GRAY(v);
454 bk->pal[k+32] = DE_MAKE_GRAY(v/2);
458 static void do_picture_bank(deark *c, lctx *d, struct amosbank *bk)
460 i64 pos = 0;
461 u32 segtype;
462 int found_screen_header = 0;
464 de_dbg(c, "picture bank");
466 pos += 20; // Advance past AmBk header
468 segtype = (u32)de_getu32be(pos);
469 if(segtype==0x12031990) {
470 found_screen_header = 1;
471 picture_bank_screen_header(c, d, bk, pos);
472 pos += 90;
474 if(bk->amiga_mode & 0x0800) {
475 de_err(c, "HAM Picture Bank images are not supported.");
476 goto done;
479 segtype = (u32)de_getu32be(pos);
482 if(segtype!=0x06071963) {
483 de_err(c, "Missing Picture Header");
484 goto done;
487 if(!found_screen_header) {
488 picture_bank_make_palette(c, d, bk);
491 picture_bank_read_picture(c, d, bk, pos);
493 done:
497 static int do_read_AmBk(deark *c, lctx *d, struct amosbank *bk)
499 i64 banknum;
500 i64 bank_len_code;
501 i64 bank_len_raw;
502 int membanktype = 0;
503 const struct membankinfo *mbi = NULL;
504 struct de_stringreaderdata *srd = NULL;
505 i64 i;
506 int retval = 0;
508 if(bk->f->len < 20) goto done;
510 banknum = dbuf_getu16be(bk->f, 4);
511 de_dbg(c, "bank number (1-15): %d", (int)banknum);
513 bank_len_code = dbuf_getu32be(bk->f, 8);
514 bank_len_raw = bank_len_code & 0x0fffffff;
515 bk->bank_len = bank_len_raw+12;
516 bk->bank_data_len = bank_len_raw-8;
517 de_dbg(c, "bank length: %d (dlen=%d, tlen=%d)", (int)bank_len_raw,
518 (int)bk->bank_data_len, (int)bk->bank_len);
520 srd = dbuf_read_string(bk->f, 12, 8, 8, 0, DE_ENCODING_ASCII);
521 de_dbg(c, "bank name: \"%s\"", ucstring_getpsz(srd->str));
523 if(bk->bank_data_len<0) goto done;
525 for(i=0; membankinfo_arr[i].type!=0; i++) {
526 if(!de_memcmp(srd->sz, membankinfo_arr[i].name, 8)) {
527 mbi = &membankinfo_arr[i];
528 break;
532 if(mbi) {
533 membanktype = mbi->type;
534 bk->file_ext = mbi->file_ext;
537 if(d->fmt==CODE_AmBs) {
538 // If original file is in AmBs format, just extract the AmBk file.
539 dbuf_create_file_from_slice(bk->f, 0, bk->bank_len, bk->file_ext, NULL, 0);
540 retval = 1;
541 goto done;
544 switch(membanktype) {
545 case MEMBANKTYPE_PICTURE:
546 do_picture_bank(c, d, bk);
547 retval = 1;
548 goto done;
551 if(c->extract_level>=2) {
552 // Extracting the raw memory-bank data can be useful sometimes.
553 dbuf_create_file_from_slice(bk->f, 20, bk->bank_data_len, "bin", NULL, 0);
556 retval = 1;
557 done:
558 de_destroy_stringreaderdata(c, srd);
559 return retval;
562 static int do_read_bank(deark *c, lctx *d, i64 pos, i64 *bytesused)
564 struct amosbank *bk = NULL;
565 int ret;
566 int retval = 0;
568 bk = de_malloc(c, sizeof(struct amosbank));
569 bk->f = dbuf_open_input_subfile(c->infile, pos, c->infile->len - pos);
571 dbuf_read_fourcc(bk->f, 0, &bk->banktype4cc, 4, 0x0);
572 de_dbg(c, "bank type '%s'", bk->banktype4cc.id_dbgstr);
574 switch(bk->banktype4cc.id) {
575 case CODE_AmIc: bk->file_ext = "icon.abk"; break;
576 case CODE_AmSp: bk->file_ext = "sprite.abk"; break;
577 case CODE_AmBk: bk->file_ext = "AmBk.abk"; break;
578 default: bk->file_ext = "abk";
581 if(bk->banktype4cc.id==CODE_AmIc || bk->banktype4cc.id==CODE_AmSp) {
582 ret = do_read_sprite(c, d, bk);
583 retval = ret;
584 *bytesused = bk->bank_len;
586 else if(bk->banktype4cc.id==CODE_AmBk) {
587 ret = do_read_AmBk(c, d, bk);
588 retval = ret;
589 *bytesused = bk->bank_len;
591 else {
592 de_err(c, "Unsupported bank type: '%s'", bk->banktype4cc.id_sanitized_sz);
595 if(bk) {
596 dbuf_close(bk->f);
597 de_free(c, bk);
599 return retval;
602 static void do_read_AmBs(deark *c, lctx *d)
604 i64 bytesused;
605 i64 nbanks;
606 i64 i;
607 i64 pos;
608 int ret;
610 nbanks = de_getu16be(4);
611 de_dbg(c, "number of banks: %d", (int)nbanks);
613 pos = 6;
614 for(i=0; i<nbanks; i++) {
615 if(pos >= c->infile->len) break;
616 de_dbg(c, "bank #%d at %d", (int)i, (int)pos);
617 bytesused = 0;
618 de_dbg_indent(c, 1);
619 ret = do_read_bank(c, d, pos, &bytesused);
620 de_dbg_indent(c, -1);
621 if(!ret || bytesused<1) break;
622 pos += bytesused;
626 static void de_run_abk(deark *c, de_module_params *mparams)
628 lctx *d = NULL;
629 i64 bytesused = 0;
631 d = de_malloc(c, sizeof(lctx));
633 d->fmt = (u32)de_getu32be(0);
635 if(d->fmt==CODE_AmBk) {
636 de_declare_fmt(c, "AMOS Memory Bank");
638 else if(d->fmt==CODE_AmSp) {
639 de_declare_fmt(c, "AMOS Sprite Bank");
641 else if(d->fmt==CODE_AmIc) {
642 de_declare_fmt(c, "AMOS Icon Bank");
644 else if(d->fmt==CODE_AmBs) {
645 de_declare_fmt(c, "AMOS AmBs format");
647 else {
648 de_err(c, "Unsupported format");
649 goto done;
652 if(d->fmt==CODE_AmBk ||d->fmt==CODE_AmSp || d->fmt==CODE_AmIc) {
653 do_read_bank(c, d, 0, &bytesused);
655 else if(d->fmt==CODE_AmBs) {
656 do_read_AmBs(c, d);
659 done:
660 de_free(c, d);
663 static int de_identify_abk(deark *c)
665 u8 b[4];
666 int ext_bonus = 0;
668 if(de_input_file_has_ext(c, "abk")) ext_bonus=40;
670 de_read(b, 0, 4);
671 if(!de_memcmp(b, "AmBk", 4))
672 return 60+ext_bonus;
673 if(!de_memcmp(b, "AmSp", 4))
674 return 60+ext_bonus;
675 if(!de_memcmp(b, "AmIc", 4))
676 return 60+ext_bonus;
677 if(!de_memcmp(b, "AmBs", 4))
678 return 60+ext_bonus;
679 return 0;
682 void de_module_abk(deark *c, struct deark_module_info *mi)
684 mi->id = "abk";
685 mi->desc = "AMOS resource (AmBk, sprite, icon, AmBs)";
686 mi->run_fn = de_run_abk;
687 mi->identify_fn = de_identify_abk;
690 static void de_run_amos_source(deark *c, de_module_params *mparams)
692 lctx *d = NULL;
693 i64 basic_len;
694 i64 pos;
695 i64 nbanks;
697 d = de_malloc(c, sizeof(lctx));
699 pos = 16;
700 basic_len = de_getu32be(pos);
701 pos += 4;
702 de_dbg(c, "BASIC code at %d, len=%d", (int)pos, (int)basic_len);
703 pos += basic_len;
704 if(pos >= c->infile->len) goto done;
705 if(dbuf_memcmp(c->infile, pos, "AmBs", 4)) {
706 de_err(c, "AmBs segment not found, expected at offset %d", (int)pos);
707 goto done;
710 de_dbg(c, "AmBs segment at %d", (int)pos);
711 nbanks = de_getu16be(pos+4);
712 de_dbg_indent(c, 1);
713 de_dbg(c, "number of banks: %d", (int)nbanks);
714 if(nbanks>0 || c->extract_level>=2) {
715 dbuf_create_file_from_slice(c->infile, pos, c->infile->len-pos, "AmBs.abk", NULL, 0);
717 else {
718 de_dbg(c, "not extracting empty AmBs segment");
720 de_dbg_indent(c, -1);
723 done:
724 de_free(c, d);
727 static int de_identify_amos_source(deark *c)
729 u8 b[10];
730 int ext_bonus = 0;
732 if(de_input_file_has_ext(c, "amos")) ext_bonus=20;
734 de_read(b, 0, 10);
735 if(!de_memcmp(b, "AMOS Basic", 10))
736 return 80+ext_bonus;
737 if(!de_memcmp(b, "AMOS Pro", 8))
738 return 80+ext_bonus;
739 return 0;
742 void de_module_amos_source(deark *c, struct deark_module_info *mi)
744 mi->id = "amos_source";
745 mi->desc = "AMOS source code";
746 mi->run_fn = de_run_amos_source;
747 mi->identify_fn = de_identify_amos_source;