2 * Copyright (c) 2007-2013 Czirkos Zoltan http://code.google.com/p/gdash/
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
19 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #include "fileops/binaryimport.hpp"
25 #include "fileops/c64import.hpp"
30 #include "misc/logger.hpp"
31 #include "misc/printf.hpp"
34 class ResizingByteArray
: public std::vector
<unsigned char> {
36 using std::vector
<unsigned char>::size
;
37 using std::vector
<unsigned char>::empty
;
38 using std::vector
<unsigned char>::clear
;
39 unsigned char &operator[](size_t s
) {
42 // call op[] of parent class
43 return this->std::vector
<unsigned char>::operator[](s
);
48 static ResizingByteArray out
;
52 /* default effect table, taken from afl boulder dash. used to detect if
53 game-wide diego effects are present. */
54 static unsigned char default_effect
[] = {
55 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b,
56 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
57 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f,
58 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3d, 0x3e, 0x3f,
59 0x40, 0x60, 0x46, 0x4e, 0x22, 0x2e, 0x62, 0x2e, 0x4a, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
60 0x64, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x66, 0x68, 0x6a, 0x68,
61 0x66, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x62, 0x66, 0x68, 0x6a, 0x00, 0x4e, 0x4e, 0x00, 0x00, 0x00,
62 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x40, 0x40, 0x42, 0x2e, 0x40,
66 static void startwith(C64Import::GdCavefileFormat format
) {
68 for (size_t i
= 0; C64Import::gd_format_strings
[format
][i
] != 0; ++i
) {
69 out
[i
] = C64Import::gd_format_strings
[format
][i
];
75 /* save bd1 caves from memory map */
76 /* atari: a boolean value, true if try atari map. */
77 static bool try_bd1(std::vector
<unsigned char> const &memory
, bool atari
) {
78 /* there are cave pointers at 0x5806. two byte entries pointing to caves. */
79 /* their value is relative to 0x582e. */
80 /* atari values are 3500 and 3528. */
81 int cavepointers
= atari
? 0x3500 : 0x5806;
82 int cavestart
= atari
? 0x3528 : 0x582e;
84 const char *type
= atari
? "atari" : "c64";
85 SetLoggerContextForFunction
context(SPrintf("BD1 import %s") % type
);
87 startwith(atari
? C64Import::GD_FORMAT_BD1_ATARI
: C64Import::GD_FORMAT_BD1
);
89 /* try to autodetect */
91 /* fixme what is this? */
93 if (memory
[0x5f3a] != 0x44 || memory
[0x5f3b] != 0x44 || memory
[0x5f3c] != 0x48 || memory
[0x5f3d] != 0x48) {
94 gd_debug("Assumptions failed for BD1(e).");
99 /* 20 (4 groups * 5 caves (4cave+1intermission)) */
100 for (int i
= 0; i
< 20; i
++) {
101 int lo
= memory
[cavepointers
+ i
* 2];
102 int hi
= memory
[cavepointers
+ i
* 2 + 1];
103 int start
= hi
* 256 + lo
+ cavestart
, pos
= start
;
104 positions
[i
] = start
;
105 /* check if position is not the same as any previous cave */
106 for (int j
= 0; j
< i
; ++j
)
107 if (positions
[j
] == positions
[i
]) {
108 gd_debug(CPrintf("Invalid cave position %x at index %d - same as for cave at index %d") % pos
% i
% j
);
112 if (pos
> (0xffff - 0x0400)) {
113 gd_debug("Cannot interpret memory contents as BD1(e) -- invalid cave pointer.");
117 gd_debug(CPrintf("Cave %c, addr: %04x") % char(i
+ 'A') % pos
);
119 gd_debug(CPrintf("Intermission %d, addr: %04x") % int(i
- 15) % pos
);
122 /* first 32 bytes - cave options */
123 for (int j
= 0; j
< 32; j
++)
124 out
[outpos
++] = memory
[pos
++]; /* 5levels: 5random, 5diamond, 5time */
126 /* now cave objects */
127 int j
= memory
[pos
++];
128 while (j
!= 0xFF) { /* végét jelenti; de kiírtuk ezt is */
129 if (pos
- start
> 0x400) {
130 /* bd1 caves cannot be this long */
131 gd_debug("Cannot interpret memory contents as BD1(e) -- cave data too long.");
136 /* crazy cream 3 extension: escape byte 0x0f means raster */
137 out
[outpos
++] = memory
[pos
++]; /* param byte 1: object to draw */
138 out
[outpos
++] = memory
[pos
++]; /* param byte 2: begin column */
139 out
[outpos
++] = memory
[pos
++]; /* param byte 3: begin row */
140 out
[outpos
++] = memory
[pos
++]; /* param byte 4: amount of rows */
141 out
[outpos
++] = memory
[pos
++]; /* param byte 5: amount of columns */
142 out
[outpos
++] = memory
[pos
++]; /* param byte 6: distance between rows */
143 out
[outpos
++] = memory
[pos
++]; /* param byte 7: distance between columns */
147 out
[outpos
++] = memory
[pos
++]; /* x */
148 out
[outpos
++] = memory
[pos
++]; /* y */
151 out
[outpos
++] = memory
[pos
++]; /* x */
152 out
[outpos
++] = memory
[pos
++]; /* y */
153 out
[outpos
++] = memory
[pos
++]; /* len */
154 out
[outpos
++] = memory
[pos
++]; /* dir */
156 case 2: /* fillrect */
157 out
[outpos
++] = memory
[pos
++]; /* x */
158 out
[outpos
++] = memory
[pos
++]; /* y */
159 out
[outpos
++] = memory
[pos
++]; /* w */
160 out
[outpos
++] = memory
[pos
++]; /* h */
161 out
[outpos
++] = memory
[pos
++]; /* fill */
163 case 3: /* outline */
164 out
[outpos
++] = memory
[pos
++]; /* x */
165 out
[outpos
++] = memory
[pos
++]; /* y */
166 out
[outpos
++] = memory
[pos
++]; /* w */
167 out
[outpos
++] = memory
[pos
++]; /* h */
173 out
[outpos
++] = j
; /* lezáró 0xff kiírása */
175 gd_debug("Found 20 BD1 caves!");
180 /* save plck caves from c64 memory map */
181 static bool try_plck(std::vector
<unsigned char> const &memory
) {
182 SetLoggerContextForFunction
context("PLCK import");
189 startwith(C64Import::GD_FORMAT_PLC
);
193 /* try to detect plck cave selection table. assume there are at least 5 caves. */
194 /* selection table without names. */
196 for (x
= 0; x
< 5; x
++)
197 if (memory
[0x5e8b + x
] == 0x0e || memory
[0x5e8b + x
] == 0x19)
204 /* selection table with names. */
206 for (x
= 0; x
< 5; x
++)
207 if (memory
[0x5e8b + 13 * x
+ 12] == 0x0e || memory
[0x5e8b + 13 * x
+ 12] == 0x19)
214 gd_debug("Assumptions failed for PLCK - could not find cave selection table.");
218 gd_debug(has_names
? "PLCK caves have names." : "PLCK caves have no names.");
221 //~ while (i<17) { // For Bert Bogger Pro 2
222 /* while present and (selectable or nonselectable) <- find any valid byte in cave selection table. */
223 while ((!has_names
&& (memory
[0x5e8b + i
] != 0 && (memory
[0x5e8b + i
] == 0x0e || memory
[0x5e8b + i
] == 0x19)))
224 || (has_names
&& (memory
[0x5e8b + i
* 13 + 12] != 0 && (memory
[0x5e8b + i
* 13 + 12] == 0x0e || memory
[0x5e8b + i
* 13 + 12] == 0x19)))) {
227 pos
= 0x7000 + 0x200 * i
;
229 /* check if memory is not filled with zeroes. */
231 for (j
= 0; j
< 512 && zero
; j
++)
232 if (memory
[pos
+ j
] != 0)
237 /* check for error */
239 /* caves cannot be this long */
240 gd_debug("Data corrupt or detection failed for plck caves -- too many caves.");
244 if (memory
[pos
+ 0x1e5] == 0x20 && memory
[pos
+ 0x1e6] == 0x90 && memory
[pos
+ 0x1e7] == 0x46)
246 gd_debug(CPrintf("Cave %d, addr: %04x%s") % int(i
+ 1) % pos
% (has_diego
? " - has diego effects." : ""));
248 /* copy 1f0 bytes for cave */
249 for (j
= 0; j
< 0x1f0; ++j
)
250 out
[outpos
++] = memory
[pos
++];
252 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
253 if (has_names
) { /* we detected that it has names */
254 if (memory
[0x5e8b + i
* 13 + 12] != 0x0e && memory
[0x5e8b + i
* 13 + 12] != 0x19) {
255 gd_debug("ERROR: cave selection table corrupt or autodetection failed");
256 out
[outpos
++] = 0x19;
257 out
[outpos
++] = 0x19 + 1;
259 out
[outpos
++] = memory
[0x5e8b + i
* 13 + 12];
260 out
[outpos
++] = memory
[0x5e8b + i
* 13 + 12] + 1; /* save twice, add +1 for second for detection in gdash */
262 for (j
= 0; j
< 12; j
++)
263 out
[outpos
++] = memory
[0x5e8b + i
* 13 + j
];
264 out
[outpos
++] = 0; /* fill the rest with zero */
266 } else { /* no names */
267 if (memory
[0x5e8b + i
] != 0x0e && memory
[0x5e8b + i
] != 0x19) {
268 gd_debug("ERROR: cave selection table corrupt or autodetection failed");
269 out
[outpos
++] = 0x19;
270 out
[outpos
++] = 0x19 + 1;
272 out
[outpos
++] = memory
[0x5e8b + i
];
273 out
[outpos
++] = memory
[0x5e8b + i
] + 1; /* save twice for detection, add 1 to second one */
275 for (j
= 2; j
< 16; j
++)
281 gd_debug(CPrintf("Found %d PLCK caves in %d bytes!") % i
% outpos
);
283 /* now try to do something about diego effects. */
284 /* if we found at least one cave with diego effects, this check can be skipped. */
287 const int numbers
= sizeof(default_effect
) / sizeof(default_effect
[0]);
291 /* check effect table from memory at 3b00. */
293 for (j
= 0; j
< numbers
; j
++)
294 if (default_effect
[j
] != memory
[0x3b00 + j
]) {
300 /* found an unstandard effect table */
301 int b_stone_to
= memory
[0x3b00 + 0x11];
302 int f_diamond_to
= memory
[0x3b00 + 0x17];
303 int explosion_to
= memory
[0x3b00 + 0x1e];
304 int dirt_pointer
= memory
[0x3b00 + 0x42];
305 int growing_pointer
= memory
[0x3b00 + 0x6b];
307 /* report effect table changes that we are able to convert to the per cave description. */
308 gd_debug("Found global diego effects!");
309 if (b_stone_to
!= 0x10)
310 gd_debug("Effect for bouncing stone.");
311 if (f_diamond_to
!= 0x16)
312 gd_debug("Effect for falling diamond.");
313 if (explosion_to
!= 0x1e)
314 gd_debug("Effect for explosion.");
315 if (dirt_pointer
!= 0x46)
316 gd_debug("Dirt looks like effect.");
317 if (growing_pointer
!= 0x4e)
318 gd_debug("Growing wall looks like effect.");
320 /* go through all caves and add no1v5.3e compatible flags */
321 for (j
= 0; j
< i
; j
++) {
322 /* flags used previously on c64; gdash also knows them */
323 out
[12 + 0x0200 * j
+ 0x1e5] = 0x20;
324 out
[12 + 0x0200 * j
+ 0x1e6] = 0x90;
325 out
[12 + 0x0200 * j
+ 0x1e7] = 0x46;
327 /* set detected stuff for cave */
328 out
[12 + 0x0200 * j
+ 0x1ea] = b_stone_to
;
329 out
[12 + 0x0200 * j
+ 0x1eb] = f_diamond_to
;
330 out
[12 + 0x0200 * j
+ 0x1ec] = explosion_to
;
331 out
[12 + 0x0200 * j
+ 0x1ed] = dirt_pointer
;
332 out
[12 + 0x0200 * j
+ 0x1ee] = growing_pointer
;
333 out
[12 + 0x0200 * j
+ 0x1ef] = 200; /* FIXME AMOEBA THRESHOLD */
336 /* null out effects we could handle */
342 /* check if growing wall (delayed)==growing wall in terms of graphics, if it is, then it is no diff to original */
343 if (memory
[0x3b00 + 0x6b] == memory
[0x3b00 + 0x6c])
346 /* and check if there are others we cannot fit into a "standard" cawe */
347 for (j
= 0; j
< numbers
; j
++)
349 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
]);
357 /* save plck caves from atari memory map */
358 static bool try_atari_plck(std::vector
<unsigned char> const &memory
) {
359 SetLoggerContextForFunction
context("PLCK import Atari");
364 startwith(C64Import::GD_FORMAT_PLC_ATARI
);
366 /* try to detect the cave selection table. assume there are at least 5 caves. */
368 6040: 66 60 4A 41 49 4C 20 20 20 20 2E 43 41 56 59 53 f.JAIL .CAVYS
369 6050: 41 46 45 20 20 20 20 2E 43 41 56 59 52 41 49 4E AFE .CAVYRAIN
370 6060: 20 20 20 20 2E 43 41 56 59 45 53 43 41 50 41 44 .CAVYESCAPAD
371 6070: 45 2E 43 41 56 59 43 48 41 53 45 20 20 20 2E 49 E.CAVYCHASE .I
372 6080: 4E 54 4E 52 45 53 43 55 45 20 20 2E 43 41 56 59 NTNRESCUE .CAVY
373 we detect the Y's and N's after CAV or INT
376 /* caves are preceded with $ab $ab $ab $ab CAVENAME */
378 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV.
379 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
380 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
382 /* try to detect this; assume at least 5 caves. */
384 for (x
= 0; x
< 5; x
++) {
385 int pos
= 0x6ff0 + x
* 0x200;
386 if (memory
[pos
] == 0xAB && memory
[pos
+ 1] == 0xAB && memory
[pos
+ 2] == 0xAB && memory
[pos
+ 3] == 0xAB)
390 gd_debug("Assumptions failed for Atari PLCK - could not find $ab $ab $ab $ab before caves.");
394 /* check if it has a selection table */
396 for (x
= 0; x
< 5; x
++) {
397 if (memory
[0x604e + x
* 13] == 'Y' || memory
[0x604e + x
* 13] == 'N')
400 has_selection
= (ok
== 5);
402 gd_debug("Found selection table.");
405 /* detect caves by $ab bytes before them */
406 while (memory
[0x6ff0 + i
* 0x200] == 0xAB && memory
[0x6ff1 + i
* 0x200] == 0xAB && memory
[0x6ff2 + i
* 0x200] == 0xAB && memory
[0x6ff3 + i
* 0x200] == 0xAB) {
410 pos
= 0x7000 + 0x200 * i
;
412 selectable
= memory
[0x604e + i
* 13] == 'Y';
414 /* has no selection table... we make intermissions unselectable. */
415 selectable
= memory
[pos
+ 0x1da] == 0;
417 /* check for error */
419 /* caves cannot be this long */
420 gd_debug("Data corrupt or detection failed for plck caves -- too many caves.");
424 bool has_diego
= false;
425 if (memory
[pos
+ 0x1e5] == 0x20 && memory
[pos
+ 0x1e6] == 0x90 && memory
[pos
+ 0x1e7] == 0x46)
427 gd_debug(CPrintf("Cave %d, addr: %04x, sel: %d%s") % (i
+ 1) % pos
% selectable
% (has_diego
? " - has diego effects." : ""));
429 /* copy 1f0 bytes for cave */
430 for (j
= 0; j
< 0x1f0; ++j
)
431 out
[outpos
++] = memory
[pos
++];
433 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
434 /* we have to stay compatible with c64 plck import routine above. */
435 /* so we use 0x19 for selectable caves, 0x0e for nonselectable. */
436 out
[outpos
++] = selectable
? 0x19 : 0x0e;
437 out
[outpos
++] = (selectable
? 0x19 : 0x0e) + 1; /* save twice, add +1 for second for detection in gdash */
438 /* copy cave name, which is:
439 6FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
440 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV. ... cave name
441 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD ... cave data
442 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
443 7020: 44 44 44 44 44 44 44 44 4E 77 77 77 77 77 77 77 DDDDDDDDNwwwwwww
446 pos
= 0x7000 + 0x200 * i
;
447 for (j
= 0; j
< 12; j
++) {
448 unsigned char c
= memory
[pos
- 0x10 + 4 + j
];
450 /* somehow this character set the end-of-string in atari version */
455 out
[outpos
++] = 0; /* fill the rest with zero */
460 gd_debug(CPrintf("Found %d PLCK caves in %d bytes!") % i
% outpos
);
467 /* save crazy light caves from memory map */
468 static bool try_crli(std::vector
<unsigned char> const &memory
) {
469 SetLoggerContextForFunction
context("CrLi import");
471 startwith(C64Import::GD_FORMAT_CRLI
);
475 if (memory
[0x6ffc] != 'V' || memory
[0x6ffd] != '3' || memory
[0x6ffe] != '.' || memory
[0x6fff] != '0') /* version string */
477 for (int x
= 0x7060; x
< 0x7090; x
++) /* cave selection table */
478 if (memory
[x
] != 0 && memory
[x
] != 1 && memory
[x
] != 255)
481 gd_debug("Assumptions failed for crazy light.");
486 for (int i
= 0; i
< 48; i
++) {
487 if (memory
[0x7060 + i
] != 0xFF) {
490 int startpos
= memory
[0x7000 + i
] + memory
[0x7030 + i
] * 256L;
493 /* 'decompress' data, to see how many bytes there are */
494 while (cavepos
< 0x3b0) { /* <- loop until the uncompressed reaches its size */
495 if (memory
[pos
] == 0xbf) {
497 cavepos
+= memory
[pos
+ 2]; /* number of bytes */
505 pos
+= 14; /* add 14 bytes for name */
506 int n
= pos
- startpos
; /* bytes to copy */
507 startpos
-= 14; /* name is BEFORE the cave data */
508 gd_debug(CPrintf("Cave %d, addr: %04x (%d), length %d bytes") % caves
% pos
% pos
% n
);
510 out
[outpos
++] = memory
[0x7060 + i
]; /* is_selectable */
511 for (int j
= 0; j
< n
; j
++)
512 out
[outpos
++] = memory
[startpos
++];
515 gd_debug(CPrintf("Found %d crazy light caves in %d bytes!") % caves
% outpos
);
519 static bool try_crdr(std::vector
<unsigned char> const &memory
) {
520 SetLoggerContextForFunction
context("CrDr import");
523 startwith(C64Import::GD_FORMAT_CRDR_7
);
526 // if (memory[0x6ffc]!='V' || memory[0x6ffd]!='3' || memory[0x6ffe]!='.' || memory[0x6fff]!='0') /* version string */
530 for (i
= 0; i
< 20; i
++) {
533 int startpos
= memory
[0x7500 + i
] + memory
[0x7580 + i
] * 256L;
537 for (int j
= 0; j
< 14; j
++)
538 out
[outpos
++] = memory
[0x8c00 + i
* 16 + j
];
541 /* XXX seems to be broken; rather set unselectable intermissions */
542 out
[outpos
++] =/*memory[0x7410+caves]*/(caves
% 5) != 0;
545 for (int j
= 0; j
< 0x49; j
++)
546 out
[outpos
++] = memory
[pos
++];
548 while (memory
[pos
] != 0xff) {
549 switch (memory
[pos
]) {
551 for (int j
= 0; j
< 4; j
++)
552 out
[outpos
++] = memory
[pos
++];
554 case 2: /* rectangle */
555 for (int j
= 0; j
< 6; j
++)
556 out
[outpos
++] = memory
[pos
++];
558 case 3: /* fillrect */
559 for (int j
= 0; j
< 6; j
++)
560 out
[outpos
++] = memory
[pos
++];
563 for (int j
= 0; j
< 6; j
++)
564 out
[outpos
++] = memory
[pos
++];
567 for (int j
= 0; j
< 5; j
++) {
568 out
[outpos
++] = memory
[pos
++];
572 for (int j
= 0; j
< 3; j
++) {
573 out
[outpos
++] = memory
[pos
++];
576 case 11: /* raster */
577 for (int j
= 0; j
< 8; j
++)
578 out
[outpos
++] = memory
[pos
++];
581 gd_debug(CPrintf("Unknown crdr object code %x at %d. Aborting.") % memory
[pos
] % pos
);
586 out
[outpos
++] = memory
[pos
++]; /* copy $ff */
587 int n
= pos
- startpos
; /* bytes to copied */
588 gd_debug(CPrintf("Cave %d, addr: %04x (%d), length %d bytes") % caves
% pos
% pos
% n
);
590 gd_debug(CPrintf("Found %d crazy dream caves in %d bytes!") % caves
% outpos
);
596 /* save bd2 caves from memory map */
597 static bool try_bd2(std::vector
<unsigned char> const &memory
, bool atari
) {
598 const int cavepointers
= atari
? 0x86b0 : 0x89b0;
599 const int cavecolors
= atari
? 0x86d8 : 0x89d8;
601 int unsupported
= 0, uns
[256];
602 const char *type
= atari
? "atari" : "c64";
603 SetLoggerContextForFunction
context(SPrintf("BD2 import %s") % type
);
605 /* 256 counters for the 256 possible bytes (8bit). mark each unsupported extension found. */
606 /* if more than 5 types found, bail out with error */
607 for (i
= 0; i
< 256; ++i
)
610 startwith(C64Import::GD_FORMAT_BD2
);
612 /* 4*5 (4 groups * 5 caves (4cave+1intermission)) */
613 for (i
= 0; i
< 4 * 5; i
++) {
614 int lo
, hi
, j
, pos
, start
;
615 int amount
, n
, mappos
;
617 lo
= cavepointers
+ i
* 2;
618 hi
= cavepointers
+ i
* 2 + 1;
619 start
= pos
= memory
[hi
] * 256L + memory
[lo
];
620 if (pos
> (0xffff - 0x0400)) {
621 gd_debug("Cannot interpret memory contents as BD2 -- invalid cave pointer.");
625 gd_debug(CPrintf("Cave %c, addr: %04x") % char(i
+ 'A') % pos
);
627 gd_debug(CPrintf("Intermission %d, addr: %04x") % int(i
- 15) % pos
);
630 /* first bytes: cave options */
631 for (j
= 0; j
<= 0x19; j
++)
632 out
[outpos
++] = memory
[pos
++]; /* cave options */
635 while (j
!= 0xFF) { /* végét jelenti; de kiírtuk ezt is */
636 if (pos
- start
> 0x400) {
637 /* bd1 caves cannot be this long */
638 gd_debug("Data corrupt or detection failed for bd2 caves -- cave data too long.");
644 out
[outpos
++] = memory
[pos
++]; /* obj */
645 out
[outpos
++] = memory
[pos
++]; /* y */
646 out
[outpos
++] = memory
[pos
++]; /* x */
647 out
[outpos
++] = memory
[pos
++]; /* dir */
648 out
[outpos
++] = memory
[pos
++]; /* len */
650 case 1: /* rectangle (outline) */
651 out
[outpos
++] = memory
[pos
++]; /* obj */
652 out
[outpos
++] = memory
[pos
++]; /* y */
653 out
[outpos
++] = memory
[pos
++]; /* x */
654 out
[outpos
++] = memory
[pos
++]; /* h */
655 out
[outpos
++] = memory
[pos
++]; /* w */
657 case 2: /* fillrect */
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
++]; /* fillobj */
666 out
[outpos
++] = memory
[pos
++]; /* obj */
667 out
[outpos
++] = memory
[pos
++]; /* y */
668 out
[outpos
++] = memory
[pos
++]; /* x */
671 out
[outpos
++] = memory
[pos
++]; /* obj */
672 out
[outpos
++] = memory
[pos
++]; /* y */
673 out
[outpos
++] = memory
[pos
++]; /* x */
674 out
[outpos
++] = memory
[pos
++]; /* h */
675 out
[outpos
++] = memory
[pos
++]; /* w */
676 out
[outpos
++] = memory
[pos
++]; /* dy */
677 out
[outpos
++] = memory
[pos
++]; /* dx */
679 case 5: /* profi boulder extension: bitmap */
680 out
[outpos
++] = memory
[pos
++]; /* obj */
681 amount
= memory
[pos
++];
682 out
[outpos
++] = amount
; /* amount */
683 out
[outpos
++] = memory
[pos
++]; /* target msb */
684 out
[outpos
++] = memory
[pos
++]; /* target lsb */
685 for (n
= 0; n
< amount
; ++n
)
686 out
[outpos
++] = memory
[pos
++]; /* data */
689 out
[outpos
++] = memory
[pos
++]; /* add to this */
690 out
[outpos
++] = memory
[pos
++]; /* add this */
691 out
[outpos
++] = memory
[pos
++]; /* dy*40+dx */
693 case 7: /* slime permeabilty */
694 out
[outpos
++] = memory
[pos
++]; /* perm */
696 case 9: /* profi boulder extension: plck map */
699 mappos
= hi
* 256 + lo
;
700 out
[outpos
++] = memory
[pos
++]; /* inbox y */
701 out
[outpos
++] = memory
[pos
++]; /* inbox x */
702 for (n
= 0; n
< 40 * (22 - 2) / 2; n
++) /* 40*20 caves, upper and lower row not contained, 1byte/2 elements */
703 out
[outpos
++] = memory
[mappos
+ n
];
707 /* not seen this extension previously */
708 gd_debug(CPrintf("Found unsupported bd2 extension n.%d") % j
);
710 uns
[j
] = 1; /* mark the newly found unknown extension */
712 if (unsupported
> 5) {
713 /* found to many unsupported extensions - this can't be bd2 */
714 gd_debug("Data corrupt or detection failed for bd2 caves -- too many unknown extensions.");
719 j
= memory
[pos
++]; /* read next */
721 out
[outpos
++] = j
; /* closing 0xff */
722 out
[outpos
++] = memory
[pos
++]; /* animation */
725 lo
= cavecolors
+ i
* 2;
726 hi
= cavecolors
+ i
* 2 + 1;
727 pos
= memory
[hi
] * 256L + memory
[lo
]; /* pointer to the three colors */
728 out
[outpos
++] = memory
[pos
++];
729 out
[outpos
++] = memory
[pos
++];
730 out
[outpos
++] = memory
[pos
++];
737 /* save plck caves from memory map */
738 static bool try_1stb(std::vector
<unsigned char> const &memory
) {
739 SetLoggerContextForFunction
context("1stB import");
740 startwith(C64Import::GD_FORMAT_FIRSTB
);
742 /* there must be exactly 20 caves, according to bd inside faq. */
744 for (i
= 0; i
< 20; i
++) {
745 int pos
= 0x7010 + 0x400 * i
;
747 /* 1stb caves have cave time, diamonds and the like encoded in bcd numbers,
748 one digit in each bytes. check that. */
749 for (int j
= 0x370; j
< 0x379 + 3; j
++)
750 if (memory
[pos
+ j
] > 9) {
751 gd_debug("Data corrupt or detection failed for 1stb caves.");
754 gd_debug(CPrintf("Cave %d, addr: %04x") % (i
+ 1) % pos
);
756 for (int j
= 0; j
< 0x400; ++j
)
757 out
[outpos
++] = memory
[pos
++];
759 gd_debug(CPrintf("Found %d 1stb caves!") % i
);
764 /** load memory dump, and fill memory map. returns the memory dump, or throws an exception describing the problem. */
765 std::vector
<unsigned char> load_memory_dump(unsigned char const *file
, size_t length
) {
766 const unsigned char vicemagic
[] = {
767 0x56, 0x49, 0x43, 0x45, 0x20, 0x53, 0x6E, 0x61, 0x70, 0x73, 0x68, 0x6F,
768 0x74, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x1A, 0x01, 0x00, 0x43, 0x36, 0x34
770 std::vector
<unsigned char> memory(65536);
772 if (memcmp(vicemagic
, file
, sizeof(vicemagic
)) == 0) {
773 /* FOUND a vice snapshot file. */
774 gd_debug("File is a VICE snapshot.");
775 memcpy(&memory
[0], file
+ 0x80, 65536);
779 /* 65538 bytes: we hope that this is a full-memory map saved by vice. check it. */
780 if (length
== 65538) {
781 /* check start address */
782 if (file
[0] != 0 || file
[1] != 0)
783 throw std::runtime_error(
784 "Memory map should begin from address 0000. "
785 "Use save \"filename\" 0 0000 ffff in vice monitor.");
786 memcpy(&memory
[0], file
+ 2, 65536);
787 gd_debug("%s looks like a proper VICE memory map.");
791 /* or maybe a 64k map saved by atari800. read it. */
792 if (length
== 65536) {
793 memcpy(&memory
[0], file
, 65536);
794 gd_debug("%s is maybe an atari800 memory map.");
798 throw std::runtime_error(
799 "Memory map file should be 65536+2 bytes long or 65536 bytes long. "
800 "Use save \"filename\" 0 0000 ffff in vice monitor. "
801 "Use write 0000 ffff filename in atari800 monitor.");
805 std::vector
<unsigned char> gdash_binary_import(std::vector
<unsigned char> const &memory
) {
806 if (try_plck(memory
) || try_atari_plck(memory
) || try_bd1(memory
, false) || try_bd1(memory
, true)
807 || try_bd2(memory
, false) || try_bd2(memory
, true) || try_crli(memory
) || try_1stb(memory
) || try_crdr(memory
)) {
808 /* write data length in little endian */
809 out
[8] = ((outpos
- 12)) & 0xff;
810 out
[9] = ((outpos
- 12) >> 8) & 0xff;
811 out
[10] = ((outpos
- 12) >> 16) & 0xff;
812 out
[11] = ((outpos
- 12) >> 24) & 0xff;
817 throw std::runtime_error("Could not import cave data -- unknown cave format!");