2 * Copyright (c) 2007-2013 Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include "fileops/binaryimport.hpp"
23 #include "fileops/c64import.hpp"
24 #include "misc/logger.hpp"
25 #include "misc/printf.hpp"
28 class ResizingByteArray
: public std::vector
<unsigned char> {
30 using std::vector
<unsigned char>::size
;
31 using std::vector
<unsigned char>::empty
;
32 using std::vector
<unsigned char>::clear
;
33 unsigned char & operator[] (size_t s
) {
36 // call op[] of parent class
37 return this->std::vector
<unsigned char>::operator[](s
);
42 static ResizingByteArray out
;
46 /* default effect table, taken from afl boulder dash. used to detect if
47 game-wide diego effects are present. */
48 static unsigned char default_effect
[] = {
49 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b,
50 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
51 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f,
52 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3d, 0x3e, 0x3f,
53 0x40, 0x60, 0x46, 0x4e, 0x22, 0x2e, 0x62, 0x2e, 0x4a, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
54 0x64, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x66, 0x68, 0x6a, 0x68,
55 0x66, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x62, 0x66, 0x68, 0x6a, 0x00, 0x4e, 0x4e, 0x00, 0x00, 0x00,
56 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x40, 0x40, 0x42, 0x2e, 0x40,
60 static void startwith(C64Import::GdCavefileFormat format
) {
62 for (size_t i
= 0; C64Import::gd_format_strings
[format
][i
] != 0; ++i
) {
63 out
[i
] = C64Import::gd_format_strings
[format
][i
];
69 /* save bd1 caves from memory map */
70 /* atari: a boolean value, true if try atari map. */
71 static bool try_bd1(std::vector
<unsigned char> const &memory
, bool atari
) {
72 /* there are cave pointers at 0x5806. two byte entries pointing to caves. */
73 /* their value is relative to 0x582e. */
74 /* atari values are 3500 and 3528. */
75 int cavepointers
=atari
?0x3500:0x5806;
76 int cavestart
=atari
?0x3528:0x582e;
78 const char *type
=atari
?"atari":"c64";
79 SetLoggerContextForFunction
context(SPrintf("BD1 import %s") % type
);
81 startwith(atari
? C64Import::GD_FORMAT_BD1_ATARI
: C64Import::GD_FORMAT_BD1
);
83 /* try to autodetect */
85 /* fixme what is this? */
87 if (memory
[0x5f3a]!=0x44 || memory
[0x5f3b]!=0x44 || memory
[0x5f3c]!=0x48 || memory
[0x5f3d]!=0x48) {
88 gd_debug("Assumptions failed for BD1(e).");
93 /* 20 (4 groups * 5 caves (4cave+1intermission)) */
94 for (int i
=0; i
<20; i
++) {
95 int lo
= memory
[cavepointers
+i
*2];
96 int hi
= memory
[cavepointers
+i
*2+1];
97 int start
= hi
*256+lo
+cavestart
, pos
= start
;
99 /* check if position is not the same as any previous cave */
100 for (int j
=0; j
<i
; ++j
)
101 if (positions
[j
]==positions
[i
]) {
102 gd_debug(CPrintf("Invalid cave position %x at index %d - same as for cave at index %d") % pos
% i
% j
);
106 if (pos
>(0xffff-0x0400)) {
107 gd_debug("Cannot interpret memory contents as BD1(e) -- invalid cave pointer.");
111 gd_debug(CPrintf("Cave %c, addr: %04x") % char(i
+'A') % pos
);
113 gd_debug(CPrintf("Intermission %d, addr: %04x") % int(i
-15) % pos
);
116 /* first 32 bytes - cave options */
117 for (int j
=0; j
<32; j
++)
118 out
[outpos
++]=memory
[pos
++]; /* 5levels: 5random, 5diamond, 5time */
120 /* now cave objects */
122 while (j
!=0xFF) { /* végét jelenti; de kiírtuk ezt is */
123 if (pos
-start
> 0x400) {
124 /* bd1 caves cannot be this long */
125 gd_debug("Cannot interpret memory contents as BD1(e) -- cave data too long.");
130 /* crazy cream 3 extension: escape byte 0x0f means raster */
131 out
[outpos
++]=memory
[pos
++]; /* param byte 1: object to draw */
132 out
[outpos
++]=memory
[pos
++]; /* param byte 2: begin column */
133 out
[outpos
++]=memory
[pos
++]; /* param byte 3: begin row */
134 out
[outpos
++]=memory
[pos
++]; /* param byte 4: amount of rows */
135 out
[outpos
++]=memory
[pos
++]; /* param byte 5: amount of columns */
136 out
[outpos
++]=memory
[pos
++]; /* param byte 6: distance between rows */
137 out
[outpos
++]=memory
[pos
++]; /* param byte 7: distance between columns */
141 out
[outpos
++]=memory
[pos
++]; /* x */
142 out
[outpos
++]=memory
[pos
++]; /* y */
145 out
[outpos
++]=memory
[pos
++]; /* x */
146 out
[outpos
++]=memory
[pos
++]; /* y */
147 out
[outpos
++]=memory
[pos
++]; /* len */
148 out
[outpos
++]=memory
[pos
++]; /* dir */
150 case 2: /* fillrect */
151 out
[outpos
++]=memory
[pos
++]; /* x */
152 out
[outpos
++]=memory
[pos
++]; /* y */
153 out
[outpos
++]=memory
[pos
++]; /* w */
154 out
[outpos
++]=memory
[pos
++]; /* h */
155 out
[outpos
++]=memory
[pos
++]; /* fill */
157 case 3: /* outline */
158 out
[outpos
++]=memory
[pos
++]; /* x */
159 out
[outpos
++]=memory
[pos
++]; /* y */
160 out
[outpos
++]=memory
[pos
++]; /* w */
161 out
[outpos
++]=memory
[pos
++]; /* h */
167 out
[outpos
++]=j
; /* lezáró 0xff kiírása */
169 gd_debug("Found 20 BD1 caves!");
174 /* save plck caves from c64 memory map */
175 static bool try_plck(std::vector
<unsigned char> const &memory
) {
176 SetLoggerContextForFunction
context("PLCK import");
183 startwith(C64Import::GD_FORMAT_PLC
);
187 /* try to detect plck cave selection table. assume there are at least 5 caves. */
188 /* selection table without names. */
191 if (memory
[0x5e8b+x
]==0x0e || memory
[0x5e8b+x
]==0x19)
198 /* selection table with names. */
201 if (memory
[0x5e8b+13*x
+12]==0x0e || memory
[0x5e8b+13*x
+12]==0x19)
208 gd_debug("Assumptions failed for PLCK - could not find cave selection table.");
212 gd_debug(has_names
? "PLCK caves have names." : "PLCK caves have no names.");
215 /* while present and (selectable or nonselectable) <- find any valid byte in cave selection table. */
216 while ((!has_names
&& (memory
[0x5e8b+i
]!=0 && (memory
[0x5e8b+i
]==0x0e || memory
[0x5e8b+i
]==0x19)))
217 || (has_names
&& (memory
[0x5e8b+i
*13+12]!=0 && (memory
[0x5e8b+i
*13+12]==0x0e || memory
[0x5e8b+i
*13+12]==0x19)))) {
222 /* check if memory is not filled with zeroes. */
224 for (j
=0; j
<512 && zero
; j
++)
225 if (memory
[pos
+j
]!=0)
230 /* check for error */
232 /* caves cannot be this long */
233 gd_debug("Data corrupt or detection failed for plck caves -- too many caves.");
237 if (memory
[pos
+0x1e5]==0x20 && memory
[pos
+0x1e6]==0x90 && memory
[pos
+0x1e7]==0x46)
239 gd_debug(CPrintf("Cave %d, addr: %04x%s") % int(i
+1) % pos
% (has_diego
? " - has diego effects." : ""));
241 /* copy 1f0 bytes for cave */
242 for (j
=0; j
<0x1f0; ++j
)
243 out
[outpos
++]=memory
[pos
++];
245 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
246 if (has_names
) { /* we detected that it has names */
247 out
[outpos
++]=memory
[0x5e8b+i
*13+12];
248 out
[outpos
++]=memory
[0x5e8b+i
*13+12]+1; /* save twice, add +1 for second for detection in gdash */
249 if (memory
[0x5e8b+i
*13+12]!=0x0e && memory
[0x5e8b+i
*13+12]!=0x19)
250 gd_debug("ERROR: cave selection table corrupt or autodetection failed");
252 out
[outpos
++]=memory
[0x5e8b+i
*13+j
];
253 out
[outpos
++]=0; /* fill the rest with zero */
256 else { /* no names */
257 out
[outpos
++]=memory
[0x5e8b+i
];
258 out
[outpos
++]=memory
[0x5e8b+i
]+1; /* save twice for detection, add 1 to second one */
259 if (memory
[0x5e8b+i
]!=0x0e && memory
[0x5e8b+i
]!=0x19)
260 gd_debug("ERROR: cave selection table corrupt or autodetection failed");
267 gd_debug(CPrintf("Found %d PLCK caves in %d bytes!") % i
% outpos
);
269 /* now try to do something about diego effects. */
270 /* if we found at least one cave with diego effects, this check can be skipped. */
273 const int numbers
=sizeof(default_effect
)/sizeof(default_effect
[0]);
277 /* check effect table from memory at 3b00. */
279 for (j
=0; j
<numbers
; j
++)
280 if (default_effect
[j
]!=memory
[0x3b00+j
]) {
286 /* found an unstandard effect table */
287 int b_stone_to
=memory
[0x3b00 + 0x11];
288 int f_diamond_to
=memory
[0x3b00 + 0x17];
289 int explosion_to
=memory
[0x3b00 + 0x1e];
290 int dirt_pointer
=memory
[0x3b00 + 0x42];
291 int growing_pointer
=memory
[0x3b00 + 0x6b];
293 /* report effect table changes that we are able to convert to the per cave description. */
294 gd_debug("Found global diego effects!");
295 if (b_stone_to
!= 0x10)
296 gd_debug("Effect for bouncing stone.");
297 if (f_diamond_to
!= 0x16)
298 gd_debug("Effect for falling diamond.");
299 if (explosion_to
!= 0x1e)
300 gd_debug("Effect for explosion.");
301 if (dirt_pointer
!= 0x46)
302 gd_debug("Dirt looks like effect.");
303 if (growing_pointer
!= 0x4e)
304 gd_debug("Growing wall looks like effect.");
306 /* go through all caves and add no1v5.3e compatible flags */
307 for (j
=0; j
<i
; j
++) {
308 /* flags used previously on c64; gdash also knows them */
309 out
[12+0x0200*j
+0x1e5]=0x20;
310 out
[12+0x0200*j
+0x1e6]=0x90;
311 out
[12+0x0200*j
+0x1e7]=0x46;
313 /* set detected stuff for cave */
314 out
[12+0x0200*j
+0x1ea]=b_stone_to
;
315 out
[12+0x0200*j
+0x1eb]=f_diamond_to
;
316 out
[12+0x0200*j
+0x1ec]=explosion_to
;
317 out
[12+0x0200*j
+0x1ed]=dirt_pointer
;
318 out
[12+0x0200*j
+0x1ee]=growing_pointer
;
319 out
[12+0x0200*j
+0x1ef]=200; /* FIXME AMOEBA THRESHOLD */
322 /* null out effects we could handle */
328 /* check if growing wall (delayed)==growing wall in terms of graphics, if it is, then it is no diff to original */
329 if (memory
[0x3b00+0x6b]==memory
[0x3b00+0x6c])
332 /* and check if there are others we cannot fit into a "standard" cawe */
333 for (j
=0; j
<numbers
; j
++)
335 gd_debug(CPrintf("Don't know how to handle effect for element number %x, default %x, this one %x") % j
% default_effect
[j
] % memory
[0x3b00+j
]);
343 /* save plck caves from atari memory map */
344 static bool try_atari_plck(std::vector
<unsigned char> const &memory
) {
345 SetLoggerContextForFunction
context("PLCK import Atari");
350 startwith(C64Import::GD_FORMAT_PLC_ATARI
);
352 /* try to detect the cave selection table. assume there are at least 5 caves. */
354 6040: 66 60 4A 41 49 4C 20 20 20 20 2E 43 41 56 59 53 f.JAIL .CAVYS
355 6050: 41 46 45 20 20 20 20 2E 43 41 56 59 52 41 49 4E AFE .CAVYRAIN
356 6060: 20 20 20 20 2E 43 41 56 59 45 53 43 41 50 41 44 .CAVYESCAPAD
357 6070: 45 2E 43 41 56 59 43 48 41 53 45 20 20 20 2E 49 E.CAVYCHASE .I
358 6080: 4E 54 4E 52 45 53 43 55 45 20 20 2E 43 41 56 59 NTNRESCUE .CAVY
359 we detect the Y's and N's after CAV or INT
362 /* caves are preceded with $ab $ab $ab $ab CAVENAME */
364 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV.
365 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
366 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
368 /* try to detect this; assume at least 5 caves. */
370 for (x
=0; x
<5; x
++) {
371 int pos
=0x6ff0 + x
*0x200;
372 if (memory
[pos
]==0xAB && memory
[pos
+1]==0xAB && memory
[pos
+2]==0xAB && memory
[pos
+3]==0xAB)
376 gd_debug("Assumptions failed for Atari PLCK - could not find $ab $ab $ab $ab before caves.");
380 /* check if it has a selection table */
382 for (x
=0; x
<5; x
++) {
383 if (memory
[0x604e + x
*13]=='Y' || memory
[0x604e + x
*13]=='N')
386 has_selection
=(ok
==5);
388 gd_debug("Found selection table.");
391 /* detect caves by $ab bytes before them */
392 while (memory
[0x6ff0+i
*0x200]==0xAB && memory
[0x6ff1+i
*0x200]==0xAB && memory
[0x6ff2+i
*0x200]==0xAB && memory
[0x6ff3+i
*0x200]==0xAB) {
398 selectable
=memory
[0x604e + i
*13]=='Y';
400 /* has no selection table... we make intermissions unselectable. */
401 selectable
=memory
[pos
+ 0x1da]==0;
403 /* check for error */
405 /* caves cannot be this long */
406 gd_debug("Data corrupt or detection failed for plck caves -- too many caves.");
410 bool has_diego
= false;
411 if (memory
[pos
+0x1e5]==0x20 && memory
[pos
+0x1e6]==0x90 && memory
[pos
+0x1e7]==0x46)
413 gd_debug(CPrintf("Cave %d, addr: %04x, sel: %d%s") % (i
+1) % pos
% selectable
% (has_diego
? " - has diego effects." : ""));
415 /* copy 1f0 bytes for cave */
416 for (j
=0; j
<0x1f0; ++j
)
417 out
[outpos
++]=memory
[pos
++];
419 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
420 /* we have to stay compatible with c64 plck import routine above. */
421 /* so we use 0x19 for selectable caves, 0x0e for nonselectable. */
422 out
[outpos
++]=selectable
?0x19:0x0e;
423 out
[outpos
++]=(selectable
?0x19:0x0e)+1; /* save twice, add +1 for second for detection in gdash */
424 /* copy cave name, which is:
425 6FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
426 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV. ... cave name
427 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD ... cave data
428 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
429 7020: 44 44 44 44 44 44 44 44 4E 77 77 77 77 77 77 77 DDDDDDDDNwwwwwww
433 for (j
=0; j
<12; j
++) {
434 unsigned char c
=memory
[pos
-0x10+4+j
];
436 /* somehow this character set the end-of-string in atari version */
441 out
[outpos
++]=0; /* fill the rest with zero */
446 gd_debug(CPrintf("Found %d PLCK caves in %d bytes!") % i
% outpos
);
453 /* save crazy light caves from memory map */
454 static bool try_crli(std::vector
<unsigned char> const &memory
) {
455 SetLoggerContextForFunction
context("CrLi import");
457 startwith(C64Import::GD_FORMAT_CRLI
);
461 if (memory
[0x6ffc]!='V' || memory
[0x6ffd]!='3' || memory
[0x6ffe]!='.' || memory
[0x6fff]!='0') /* version string */
463 for (int x
=0x7060; x
<0x7090; x
++) /* cave selection table */
464 if (memory
[x
]!=0 && memory
[x
]!=1 && memory
[x
]!=255)
467 gd_debug("Assumptions failed for crazy light.");
472 for (int i
=0; i
<48; i
++) {
473 if (memory
[0x7060+i
]!=0xFF) {
476 int startpos
=memory
[0x7000+i
] + memory
[0x7030+i
]*256L;
479 /* 'decompress' data, to see how many bytes there are */
480 while (cavepos
< 0x3b0) { /* <- loop until the uncompressed reaches its size */
481 if (memory
[pos
] == 0xbf) {
483 cavepos
+=memory
[pos
+2]; /* number of bytes */
492 pos
+=14; /* add 14 bytes for name */
493 int n
=pos
-startpos
; /* bytes to copy */
494 startpos
-=14; /* name is BEFORE the cave data */
495 gd_debug(CPrintf("Cave %d, addr: %04x (%d), length %d bytes") % caves
% pos
% pos
% n
);
497 out
[outpos
++]=memory
[0x7060+i
]; /* is_selectable */
498 for (int j
=0; j
<n
; j
++)
499 out
[outpos
++]=memory
[startpos
++];
502 gd_debug(CPrintf("Found %d crazy light caves in %d bytes!") % caves
% outpos
);
506 static bool try_crdr(std::vector
<unsigned char> const &memory
) {
507 SetLoggerContextForFunction
context("CrDr import");
510 startwith(C64Import::GD_FORMAT_CRDR_7
);
513 // if (memory[0x6ffc]!='V' || memory[0x6ffd]!='3' || memory[0x6ffe]!='.' || memory[0x6fff]!='0') /* version string */
517 for (i
=0; i
<20; i
++) {
520 int startpos
=memory
[0x7500+i
] + memory
[0x7580+i
]*256L;
524 for (int j
=0; j
<14; j
++)
525 out
[outpos
++]=memory
[0x8c00+i
*16+j
];
528 /* XXX seems to be broken; rather set unselectable intermissions */
529 out
[outpos
++]=/*memory[0x7410+caves]*/(caves
%5)!=0;
532 for (int j
=0; j
<0x49; j
++)
533 out
[outpos
++]=memory
[pos
++];
535 while (memory
[pos
]!=0xff) {
536 switch(memory
[pos
]) {
538 for (int j
=0; j
<4; j
++)
539 out
[outpos
++]=memory
[pos
++];
541 case 2: /* rectangle */
542 for (int j
=0; j
<6; j
++)
543 out
[outpos
++]=memory
[pos
++];
545 case 3: /* fillrect */
546 for (int j
=0; j
<6; j
++)
547 out
[outpos
++]=memory
[pos
++];
550 for (int j
=0; j
<6; j
++)
551 out
[outpos
++]=memory
[pos
++];
554 for (int j
=0; j
<5; j
++) {
555 out
[outpos
++]=memory
[pos
++];
559 for (int j
=0; j
<3; j
++) {
560 out
[outpos
++]=memory
[pos
++];
563 case 11: /* raster */
564 for (int j
=0; j
<8; j
++)
565 out
[outpos
++]=memory
[pos
++];
568 gd_debug(CPrintf("Unknown crdr object code %x at %d. Aborting.") % memory
[pos
] % pos
);
573 out
[outpos
++]=memory
[pos
++]; /* copy $ff */
574 int n
=pos
-startpos
; /* bytes to copied */
575 gd_debug(CPrintf("Cave %d, addr: %04x (%d), length %d bytes") % caves
% pos
% pos
% n
);
577 gd_debug(CPrintf("Found %d crazy dream caves in %d bytes!") % caves
% outpos
);
583 /* save bd2 caves from memory map */
584 static bool try_bd2(std::vector
<unsigned char> const &memory
, bool atari
) {
585 const int cavepointers
=atari
? 0x86b0 : 0x89b0;
586 const int cavecolors
=atari
? 0x86d8 : 0x89d8;
588 int unsupported
=0, uns
[256];
589 const char *type
=atari
?"atari":"c64";
590 SetLoggerContextForFunction
context(SPrintf("BD2 import %s") % type
);
592 /* 256 counters for the 256 possible bytes (8bit). mark each unsupported extension found. */
593 /* if more than 5 types found, bail out with error */
594 for (i
=0; i
<256; ++i
)
597 startwith(C64Import::GD_FORMAT_BD2
);
599 /* 4*5 (4 groups * 5 caves (4cave+1intermission)) */
600 for (i
=0; i
<4*5; i
++) {
601 int lo
, hi
, j
, pos
, start
;
602 int amount
, n
, mappos
;
605 hi
=cavepointers
+i
*2+1;
606 start
=pos
=memory
[hi
]*256L+memory
[lo
];
607 if (pos
> (0xffff-0x0400)) {
608 gd_debug("Cannot interpret memory contents as BD2 -- invalid cave pointer.");
612 gd_debug(CPrintf("Cave %c, addr: %04x") % char(i
+'A') % pos
);
614 gd_debug(CPrintf("Intermission %d, addr: %04x") % int(i
-15) % pos
);
617 /* first bytes: cave options */
618 for (j
=0; j
<=0x19; j
++)
619 out
[outpos
++]=memory
[pos
++]; /* cave options */
622 while (j
!=0xFF) { /* végét jelenti; de kiírtuk ezt is */
623 if (pos
-start
> 0x400) {
624 /* bd1 caves cannot be this long */
625 gd_debug("Data corrupt or detection failed for bd2 caves -- cave data too long.");
631 out
[outpos
++]=memory
[pos
++]; /* obj */
632 out
[outpos
++]=memory
[pos
++]; /* y */
633 out
[outpos
++]=memory
[pos
++]; /* x */
634 out
[outpos
++]=memory
[pos
++]; /* dir */
635 out
[outpos
++]=memory
[pos
++]; /* len */
637 case 1: /* rectangle (outline) */
638 out
[outpos
++]=memory
[pos
++]; /* obj */
639 out
[outpos
++]=memory
[pos
++]; /* y */
640 out
[outpos
++]=memory
[pos
++]; /* x */
641 out
[outpos
++]=memory
[pos
++]; /* h */
642 out
[outpos
++]=memory
[pos
++]; /* w */
644 case 2: /* fillrect */
645 out
[outpos
++]=memory
[pos
++]; /* obj */
646 out
[outpos
++]=memory
[pos
++]; /* y */
647 out
[outpos
++]=memory
[pos
++]; /* x */
648 out
[outpos
++]=memory
[pos
++]; /* h */
649 out
[outpos
++]=memory
[pos
++]; /* w */
650 out
[outpos
++]=memory
[pos
++]; /* fillobj */
653 out
[outpos
++]=memory
[pos
++]; /* obj */
654 out
[outpos
++]=memory
[pos
++]; /* y */
655 out
[outpos
++]=memory
[pos
++]; /* x */
658 out
[outpos
++]=memory
[pos
++]; /* obj */
659 out
[outpos
++]=memory
[pos
++]; /* y */
660 out
[outpos
++]=memory
[pos
++]; /* x */
661 out
[outpos
++]=memory
[pos
++]; /* h */
662 out
[outpos
++]=memory
[pos
++]; /* w */
663 out
[outpos
++]=memory
[pos
++]; /* dy */
664 out
[outpos
++]=memory
[pos
++]; /* dx */
666 case 5: /* profi boulder extension: bitmap */
667 out
[outpos
++]=memory
[pos
++]; /* obj */
668 amount
=memory
[pos
++];
669 out
[outpos
++]=amount
; /* amount */
670 out
[outpos
++]=memory
[pos
++]; /* target msb */
671 out
[outpos
++]=memory
[pos
++]; /* target lsb */
672 for (n
=0; n
<amount
; ++n
)
673 out
[outpos
++]=memory
[pos
++]; /* data */
676 out
[outpos
++]=memory
[pos
++]; /* add to this */
677 out
[outpos
++]=memory
[pos
++]; /* add this */
678 out
[outpos
++]=memory
[pos
++]; /* dy*40+dx */
680 case 7: /* slime permeabilty */
681 out
[outpos
++]=memory
[pos
++]; /* perm */
683 case 9: /* profi boulder extension: plck map */
687 out
[outpos
++]=memory
[pos
++]; /* inbox y */
688 out
[outpos
++]=memory
[pos
++]; /* inbox x */
689 for (n
=0; n
<40*(22-2)/2; n
++) /* 40*20 caves, upper and lower row not contained, 1byte/2 elements */
690 out
[outpos
++]=memory
[mappos
+n
];
694 /* not seen this extension previously */
695 gd_debug(CPrintf("Found unsupported bd2 extension n.%d") % j
);
697 uns
[j
]=1; /* mark the newly found unknown extension */
700 /* found to many unsupported extensions - this can't be bd2 */
701 gd_debug("Data corrupt or detection failed for bd2 caves -- too many unknown extensions.");
706 j
=memory
[pos
++]; /* read next */
708 out
[outpos
++]=j
; /* closing 0xff */
709 out
[outpos
++]=memory
[pos
++]; /* animation */
714 pos
=memory
[hi
]*256L+memory
[lo
]; /* pointer to the three colors */
715 out
[outpos
++]=memory
[pos
++];
716 out
[outpos
++]=memory
[pos
++];
717 out
[outpos
++]=memory
[pos
++];
724 /* save plck caves from memory map */
725 static bool try_1stb(std::vector
<unsigned char> const &memory
) {
726 SetLoggerContextForFunction
context("1stB import");
727 startwith(C64Import::GD_FORMAT_FIRSTB
);
729 /* there must be exactly 20 caves, according to bd inside faq. */
731 for (i
=0; i
<20; i
++) {
732 int pos
=0x7010+0x400*i
;
734 /* 1stb caves have cave time, diamonds and the like encoded in bcd numbers,
735 one digit in each bytes. check that. */
736 for (int j
=0x370; j
<0x379+3; j
++)
737 if (memory
[pos
+j
]>9) {
738 gd_debug("Data corrupt or detection failed for 1stb caves.");
741 gd_debug(CPrintf("Cave %d, addr: %04x") % (i
+1) % pos
);
743 for (int j
=0; j
<0x400; ++j
)
744 out
[outpos
++]=memory
[pos
++];
746 gd_debug(CPrintf("Found %d 1stb caves!") % i
);
751 /** load memory dump, and fill memory map. returns the memory dump, or throws an exception describing the problem. */
752 std::vector
<unsigned char> load_memory_dump(unsigned char const *file
, size_t length
) {
753 const unsigned char vicemagic
[] = {
754 0x56, 0x49, 0x43, 0x45, 0x20, 0x53, 0x6E, 0x61, 0x70, 0x73, 0x68, 0x6F,
755 0x74, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x1A, 0x01, 0x00, 0x43, 0x36, 0x34
757 std::vector
<unsigned char> memory(65536);
759 if (memcmp(vicemagic
, file
, sizeof(vicemagic
))==0) {
760 /* FOUND a vice snapshot file. */
761 gd_debug("File is a VICE snapshot.");
762 memcpy(&memory
[0], file
+ 0x80, 65536);
766 /* 65538 bytes: we hope that this is a full-memory map saved by vice. check it. */
768 /* check start address */
769 if (file
[0]!=0 || file
[1]!=0)
770 throw std::runtime_error(
771 "Memory map should begin from address 0000. "
772 "Use save \"filename\" 0 0000 ffff in vice monitor.");
773 memcpy(&memory
[0], file
+ 2, 65536);
774 gd_debug("%s looks like a proper VICE memory map.");
778 /* or maybe a 64k map saved by atari800. read it. */
780 memcpy(&memory
[0], file
, 65536);
781 gd_debug("%s is maybe an atari800 memory map.");
785 throw std::runtime_error(
786 "Memory map file should be 65536+2 bytes long or 65536 bytes long. "
787 "Use save \"filename\" 0 0000 ffff in vice monitor. "
788 "Use write 0000 ffff filename in atari800 monitor.");
792 std::vector
<unsigned char> gdash_binary_import(std::vector
<unsigned char> const &memory
) {
793 if (try_plck(memory
) || try_atari_plck(memory
) || try_bd1(memory
, false) || try_bd1(memory
, true)
794 || try_bd2(memory
, false) || try_bd2(memory
, true) || try_crli(memory
) || try_1stb(memory
) || try_crdr(memory
)) {
795 /* write data length in little endian */
796 out
[8]=((outpos
-12))&0xff;
797 out
[9]=((outpos
-12)>>8)&0xff;
798 out
[10]=((outpos
-12)>>16)&0xff;
799 out
[11]=((outpos
-12)>>24)&0xff;
804 throw std::runtime_error("Could not import cave data -- unknown cave format!");