2 * Copyright (c) 2007, 2008 Czirkos Zoltan <cirix@fw.hu>
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.
20 /* identifiers in output file */
21 static const char *s_bd1
="GDashBD1";
22 static const char *s_bd2
="GDashBD2";
23 static const char *s_plc
="GDashPLC";
24 static const char *s_pca
="GDashPCA";
25 static const char *s_crl
="GDashCRL";
26 static const char *s_cd7
="GDashCD7";
27 static const char *s_1st
="GDash1ST";
28 static const char *s_b1a
="GDashB1A"; /* boulder dash 1, atari version */
29 static const char *s_b2a
="GDashB2A"; /* boulder dash 2, atari version */
31 /* loaded memory map */
32 static unsigned char memory
[65536];
33 static unsigned char out
[65536];
36 /* default effect table, taken from afl boulder dash. used to detect if
37 game-wide diego effects are present. */
38 static unsigned char default_effect
[] = {
39 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x08, 0x09, 0x0a, 0x0b,
40 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
41 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f,
42 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3d, 0x3e, 0x3f,
43 0x40, 0x60, 0x46, 0x4e, 0x22, 0x2e, 0x62, 0x2e, 0x4a, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
44 0x64, 0x44, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x48, 0x00, 0x00, 0x00, 0x66, 0x68, 0x6a, 0x68,
45 0x66, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x62, 0x66, 0x68, 0x6a, 0x00, 0x4e, 0x4e, 0x00, 0x00, 0x00,
46 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x4c, 0x40, 0x40, 0x42, 0x2e, 0x40,
50 /* load file, and fill memory map. returns true if success, prints error and returns false if fail */
51 static int loadfile(const char *filename
)
53 const unsigned char magic
[]={0x56, 0x49, 0x43, 0x45, 0x20, 0x53, 0x6E, 0x61, 0x70, 0x73, 0x68, 0x6F, 0x74, 0x20, 0x46, 0x69, 0x6C, 0x65, 0x1A, 0x01, 0x00, 0x43, 0x36, 0x34};
54 unsigned char buf
[24];
58 fin
=fopen(filename
, "rb");
60 printf("Cannot open file %s\n", filename
);
64 assert(sizeof(magic
)==sizeof(buf
));
65 readbytes
=fread(buf
, 1, sizeof(buf
), fin
);
66 if (readbytes
!=sizeof(buf
)) {
68 printf("Could not read %d bytes.\n", (int) sizeof(buf
));
72 if (memcmp(magic
, buf
, sizeof(buf
))==0) {
73 /* FOUND a vice snapshot file. */
74 fseek(fin
, 0x80, SEEK_SET
);
75 readbytes
=fread(memory
, 1, 65536, fin
);
76 if (readbytes
!=65536) {
78 printf("Could not read 65536 bytes.\n");
81 printf("%s is a proper vice snapshot.\n", filename
);
89 fseek(fin
, 0, SEEK_END
);
91 fseek(fin
, 0, SEEK_SET
);
93 /* 65538 bytes: we hope that this is a full-memory map saved by vice. check it. */
94 if (filesize
==65538) {
95 /* check start address */
96 if (fgetc(fin
)!=0 || fgetc(fin
)!=0) {
98 printf("Memory map should begin from address 0000.\n");
99 printf("Use save \"filename\" 0 0000 ffff in vice monitor.\n");
103 readbytes
=fread(memory
, 1, 65536, fin
);
104 if (readbytes
!=65536) {
106 printf("Could not read 65536 bytes\n.\n");
110 printf("%s looks like a proper vice memory map.\n", filename
);
114 /* or maybe a 64k map saved by atari800. read it. */
115 if (filesize
==65536) {
116 readbytes
=fread(memory
, 1, 65536, fin
);
117 if (readbytes
!=65536) {
119 printf("Could not read 65536 bytes\n.\n");
123 printf("%s lookslike a proper atari800 memory map.\n", filename
);
127 /* if not 65536, not 65538: report error. */
129 printf("Memory map file should be 65536+2 bytes long or 65536 bytes long.\n");
130 printf("Use save \"filename\" 0 0000 ffff in vice monitor.\n");
131 printf("Use write 0000 ffff filename in atari800 monitor.\n");
141 /* save bd1 caves from memory map */
142 /* atari: a boolean value, true if try atari map. */
143 static int try_bd1(int atari
)
146 /* there are cave pointers at 0x5806. two byte entries pointing to caves. */
147 /* their value is relative to 0x582e. */
148 /* atari values are 3500 and 3528. */
149 int cavepointers
=atari
?0x3500:0x5806;
150 int cavestart
=atari
?0x3528:0x582e;
152 strcpy((char *)out
, atari
?s_b1a
:s_bd1
);
154 printf("\n*** Trying to interpret BD1(e) caves...\n");
156 /* try to autodetect */
158 /* fixme what is this? */
160 if (memory
[0x5f3a]!=0x44 || memory
[0x5f3b]!=0x44 || memory
[0x5f3c]!=0x48 || memory
[0x5f3d]!=0x48) {
161 printf("Assumptions failed for BD1(e).\n");
166 /* 4*5 (4 groups * 5 caves (4cave+1intermission)) */
167 for (i
=0; i
<4*5; i
++) {
168 int lo
, hi
, j
, pos
, start
;
170 lo
=memory
[cavepointers
+i
*2];
171 hi
=memory
[cavepointers
+i
*2+1];
172 start
=pos
=hi
*256+lo
+cavestart
;
173 if (pos
>(0xffff-0x0400)) {
174 printf("Cannot interpret memory contents as BD1(e) -- invalid cave pointer.\n");
177 printf("Cave %d, addr: %04x\n", i
+1, pos
);
180 /* first 32 bytes - cave options */
182 out
[outpos
++]=memory
[pos
++]; /* 5levels: 5random, 5diamond, 5time */
184 /* now cave objects */
186 while (j
!=0xFF) { /* végét jelenti; de kiÃrtuk ezt is */
187 if (pos
-start
> 0x400) {
188 /* bd1 caves cannot be this long */
189 printf("Cannot interpret memory contents as BD1(e) -- cave data too long.\n");
194 /* crazy cream 3 extension: escape byte 0x0f means raster */
195 out
[outpos
++]=memory
[pos
++]; /* param byte 1: object to draw */
196 out
[outpos
++]=memory
[pos
++]; /* param byte 2: begin column */
197 out
[outpos
++]=memory
[pos
++]; /* param byte 3: begin row */
198 out
[outpos
++]=memory
[pos
++]; /* param byte 4: amount of rows */
199 out
[outpos
++]=memory
[pos
++]; /* param byte 5: amount of columns */
200 out
[outpos
++]=memory
[pos
++]; /* param byte 6: distance between rows */
201 out
[outpos
++]=memory
[pos
++]; /* param byte 7: distance between columns */
205 out
[outpos
++]=memory
[pos
++]; /* x */
206 out
[outpos
++]=memory
[pos
++]; /* y */
209 out
[outpos
++]=memory
[pos
++]; /* x */
210 out
[outpos
++]=memory
[pos
++]; /* y */
211 out
[outpos
++]=memory
[pos
++]; /* len */
212 out
[outpos
++]=memory
[pos
++]; /* dir */
214 case 2: /* fillrect */
215 out
[outpos
++]=memory
[pos
++]; /* x */
216 out
[outpos
++]=memory
[pos
++]; /* y */
217 out
[outpos
++]=memory
[pos
++]; /* w */
218 out
[outpos
++]=memory
[pos
++]; /* h */
219 out
[outpos
++]=memory
[pos
++]; /* fill */
221 case 3: /* outline */
222 out
[outpos
++]=memory
[pos
++]; /* x */
223 out
[outpos
++]=memory
[pos
++]; /* y */
224 out
[outpos
++]=memory
[pos
++]; /* w */
225 out
[outpos
++]=memory
[pos
++]; /* h */
231 out
[outpos
++]=j
; /* lezáró 0xff kiÃrása */
233 printf("Found %d BD1 caves!\n", 20);
238 /* save plck caves from c64 memory map */
239 static int try_plck()
247 strcpy((char *)out
, s_plc
);
249 printf("\n*** Trying to interpret PLCK caves...\n");
254 /* try to detect plck cave selection table. assume there are at least 5 caves. */
255 /* selection table without names. */
257 if (memory
[0x5e8b+x
]==0x0e || memory
[0x5e8b+x
]==0x19)
264 /* selection table with names. */
267 if (memory
[0x5e8b+13*x
+12]==0x0e || memory
[0x5e8b+13*x
+12]==0x19)
274 printf("Assumptions failed for PLCK - could not find cave selection table.\n");
278 printf(has_names
?"PLCK caves have names.\n":"PLCK caves have no names.\n");
281 /* while present and (selectable or nonselectable) <- find any valid byte in cave selection table. */
282 while ((!has_names
&& (memory
[0x5e8b+i
]!=0 && (memory
[0x5e8b+i
]==0x0e || memory
[0x5e8b+i
]==0x19)))
283 || (has_names
&& (memory
[0x5e8b+i
*13+12]!=0 && (memory
[0x5e8b+i
*13+12]==0x0e || memory
[0x5e8b+i
*13+12]==0x19)))) {
288 /* check if memory is not filled with zeroes. */
290 for (j
=0; j
<512 && zero
; j
++)
291 if (memory
[pos
+j
]!=0)
296 /* check for error */
298 /* caves cannot be this long */
299 printf("Data corrupt or detection failed for plck caves -- too many caves.\n");
303 printf("Cave %d, addr: %04x ", i
+1, pos
);
304 if (memory
[pos
+0x1e5]==0x20 && memory
[pos
+0x1e6]==0x90 && memory
[pos
+0x1e7]==0x46) {
305 printf("- has diego effects.");
310 /* copy 1f0 bytes for cave */
311 for (j
=0; j
<0x1f0; ++j
)
312 out
[outpos
++]=memory
[pos
++];
314 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
315 if (has_names
) { /* we detected that it has names */
316 out
[outpos
++]=memory
[0x5e8b+i
*13+12];
317 out
[outpos
++]=memory
[0x5e8b+i
*13+12]+1; /* save twice, add +1 for second for detection in gdash */
318 if (memory
[0x5e8b+i
*13+12]!=0x0e && memory
[0x5e8b+i
*13+12]!=0x19)
319 printf("ERROR: cave selection table corrupt or autodetection failed?\n");
321 out
[outpos
++]=memory
[0x5e8b+i
*13+j
];
322 out
[outpos
++]=0; /* fill the rest with zero */
325 else { /* no names */
326 out
[outpos
++]=memory
[0x5e8b+i
];
327 out
[outpos
++]=memory
[0x5e8b+i
]+1; /* save twice for detection, add 1 to second one */
328 if (memory
[0x5e8b+i
]!=0x0e && memory
[0x5e8b+i
]!=0x19)
329 printf("ERROR: cave selection table corrupt or autodetection failed?\n");
336 printf("Found %d PLCK caves in %d bytes!\n", i
, outpos
);
338 /* now try to do something about diego effects. */
339 /* if we found at least one cave with diego effects, this check can be skipped. */
342 const int numbers
=sizeof(default_effect
)/sizeof(default_effect
[0]);
346 /* check effect table from memory at 3b00. */
348 for (j
=0; j
<numbers
; j
++)
349 if (default_effect
[j
]!=memory
[0x3b00+j
]) {
355 /* found an unstandard effect table */
356 int b_stone_to
=memory
[0x3b00 + 0x11];
357 int f_diamond_to
=memory
[0x3b00 + 0x17];
358 int explosion_to
=memory
[0x3b00 + 0x1e];
359 int dirt_pointer
=memory
[0x3b00 + 0x42];
360 int growing_pointer
=memory
[0x3b00 + 0x6b];
362 /* report effect table changes that we are able to convert to the per cave description. */
363 printf ("Found global diego effects!\n");
364 if (b_stone_to
!= 0x10)
365 printf (" - Effect for bouncing stone.\n");
366 if (f_diamond_to
!= 0x16)
367 printf (" - Effect for falling diamond.\n");
368 if (explosion_to
!= 0x1e)
369 printf (" - Effect for explosion.\n");
370 if (dirt_pointer
!= 0x46)
371 printf (" - Dirt looks like effect.\n");
372 if (growing_pointer
!= 0x4e)
373 printf (" - Growing wall looks like effect.\n");
375 /* go through all caves and add no1v5.3e compatible flags */
376 for (j
=0; j
<i
; j
++) {
377 /* flags used previously on c64; gdash also knows them */
378 out
[12+0x0200*j
+0x1e5]=0x20;
379 out
[12+0x0200*j
+0x1e6]=0x90;
380 out
[12+0x0200*j
+0x1e7]=0x46;
382 /* set detected stuff for cave */
383 out
[12+0x0200*j
+0x1ea]=b_stone_to
;
384 out
[12+0x0200*j
+0x1eb]=f_diamond_to
;
385 out
[12+0x0200*j
+0x1ec]=explosion_to
;
386 out
[12+0x0200*j
+0x1ed]=dirt_pointer
;
387 out
[12+0x0200*j
+0x1ee]=growing_pointer
;
388 out
[12+0x0200*j
+0x1ef]=200; /* FIXME AMOEBA THRESHOLD */
391 /* null out effects we could handle */
397 /* check if growing wall (delayed)==growing wall in terms of graphics, if it is, then it is no diff to original */
398 if (memory
[0x3b00+0x6b]==memory
[0x3b00+0x6c])
401 /* and check if there are others we cannot fit into a "standard" cawe */
402 for (j
=0; j
<numbers
; j
++)
404 printf("*** Don't know how to handle effect for element number %x, default %x, this one %x\n", j
, default_effect
[j
], memory
[0x3b00+j
]);
412 /* save plck caves from atari memory map */
413 static int try_atari_plck()
420 strcpy((char *)out
, s_pca
);
422 printf("\n*** Trying to interpret Atari PLCK caves...\n");
426 /* try to detect the cave selection table. assume there are at least 5 caves. */
428 6040: 66 60 4A 41 49 4C 20 20 20 20 2E 43 41 56 59 53 f.JAIL .CAVYS
429 6050: 41 46 45 20 20 20 20 2E 43 41 56 59 52 41 49 4E AFE .CAVYRAIN
430 6060: 20 20 20 20 2E 43 41 56 59 45 53 43 41 50 41 44 .CAVYESCAPAD
431 6070: 45 2E 43 41 56 59 43 48 41 53 45 20 20 20 2E 49 E.CAVYCHASE .I
432 6080: 4E 54 4E 52 45 53 43 55 45 20 20 2E 43 41 56 59 NTNRESCUE .CAVY
433 we detect the Y's and N's after CAV or INT
436 /* caves are preceded with $ab $ab $ab $ab CAVENAME */
438 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV.
439 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
440 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
442 /* try to detect this; assume at least 5 caves. */
444 for (x
=0; x
<5; x
++) {
445 int pos
=0x6ff0 + x
*0x200;
446 if (memory
[pos
]==0xAB && memory
[pos
+1]==0xAB && memory
[pos
+2]==0xAB && memory
[pos
+3]==0xAB)
450 printf("Assumptions failed for Atari PLCK - could not find $ab $ab $ab $ab before caves.\n");
454 /* check if it has a selection table */
456 for (x
=0; x
<5; x
++) {
457 if (memory
[0x604e + x
*13]=='Y' || memory
[0x604e + x
*13]=='N')
460 has_selection
=(ok
==5);
462 printf("Found selection table.\n");
468 /* detect caves by $ab bytes before them */
469 while (memory
[0x6ff0+i
*0x200]==0xAB && memory
[0x6ff1+i
*0x200]==0xAB && memory
[0x6ff2+i
*0x200]==0xAB && memory
[0x6ff3+i
*0x200]==0xAB) {
475 selectable
=memory
[0x604e + i
*13]=='Y';
477 /* has no selection table... we make intermissions unselectable. */
478 selectable
=memory
[pos
+ 0x1da]==0;
480 /* check for error */
482 /* caves cannot be this long */
483 printf("Data corrupt or detection failed for plck caves -- too many caves.\n");
487 printf("Cave %d, addr: %04x, sel: %d", i
+1, pos
, selectable
);
488 if (memory
[pos
+0x1e5]==0x20 && memory
[pos
+0x1e6]==0x90 && memory
[pos
+0x1e7]==0x46) {
489 printf("- has diego effects.");
494 /* copy 1f0 bytes for cave */
495 for (j
=0; j
<0x1f0; ++j
)
496 out
[outpos
++]=memory
[pos
++];
498 /* and fill the rest with our own data. this way we stay compatible, as cave was always 1f0 bytes */
499 /* we have to stay compatible with c64 plck import routine above. */
500 /* so we use 0x19 for selectable caves, 0x0e for nonselectable. */
501 out
[outpos
++]=selectable
?0x19:0x0e;
502 out
[outpos
++]=(selectable
?0x19:0x0e)+1; /* save twice, add +1 for second for detection in gdash */
503 /* copy cave name, which is:
504 6FE0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
505 6FF0: AB AB AB AB 4A 41 49 4C 2E 43 41 56 9B 20 20 20 ....JAIL.CAV. ... cave name
506 7000: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD ... cave data
507 7010: 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 44 DDDDDDDDDDDDDDDD
508 7020: 44 44 44 44 44 44 44 44 4E 77 77 77 77 77 77 77 DDDDDDDDNwwwwwww
512 for (j
=0; j
<12; j
++) {
513 unsigned char c
=memory
[pos
-0x10+4+j
];
515 /* somehow this character set the end-of-string in atari version */
520 out
[outpos
++]=0; /* fill the rest with zero */
525 printf("Found %d PLCK caves in %d bytes!\n", i
, outpos
);
532 /* save crazy light caves from memory map */
533 static int try_crli()
537 strcpy((char *)out
, s_crl
);
541 printf("\n*** Trying to interpret crazy light caves...\n");
543 if (memory
[0x6ffc]!='V' || memory
[0x6ffd]!='3' || memory
[0x6ffe]!='.' || memory
[0x6fff]!='0') /* version string */
545 for (x
=0x7060; x
<0x7090; x
++) /* cave selection table */
546 if (memory
[x
]!=0 && memory
[x
]!=1 && memory
[x
]!=255)
549 printf("Assumptions failed for crazy light.\n");
555 if (memory
[0x7060+i
]!=0xFF) {
562 startpos
=memory
[0x7000+i
] + memory
[0x7030+i
]*256L;
564 printf("Cave %d, addr: %04x (%d), ", caves
, pos
, pos
);
566 /* 'decompress' data, to see how many bytes there are */
567 while (cavepos
< 0x3b0) { /* <- loop until the uncompressed reaches its size */
568 if (memory
[pos
] == 0xbf) {
570 cavepos
+=memory
[pos
+2]; /* number of bytes */
579 pos
+=14; /* add 14 bytes for name */
580 n
=pos
-startpos
; /* bytes to copy */
581 startpos
-=14; /* name is BEFORE the cave data */
582 printf("length %d bytes\n", n
);
584 out
[outpos
++]=memory
[0x7060+i
]; /* is_selectable */
586 out
[outpos
++]=memory
[startpos
++];
588 printf("Found %d crazy light caves in %d bytes!\n", caves
, outpos
);
597 strcpy((char *)out
, s_cd7
);
601 printf("\n*** Trying to interpret crazy dream caves...\n");
603 // if (memory[0x6ffc]!='V' || memory[0x6ffd]!='3' || memory[0x6ffe]!='.' || memory[0x6fff]!='0') /* version string */
607 for (i
=0; i
<20; i
++) {
613 startpos
=memory
[0x7500+i
] + memory
[0x7580+i
]*256L;
615 printf("Cave %d, addr: %04x (%d), ", caves
, pos
, pos
);
619 out
[outpos
++]=memory
[0x8c00+i
*16+j
];
622 /* XXX seems to be broken; rather set unselectable intermissions */
623 out
[outpos
++]=/*memory[0x7410+caves]*/(caves
%5)!=0;
626 for (j
=0; j
<0x49; j
++)
627 out
[outpos
++]=memory
[pos
++];
629 while (memory
[pos
]!=0xff) {
630 printf("%x ", memory
[pos
]);
631 switch(memory
[pos
]) {
634 out
[outpos
++]=memory
[pos
++];
636 case 2: /* rectangle */
638 out
[outpos
++]=memory
[pos
++];
640 case 3: /* fillrect */
642 out
[outpos
++]=memory
[pos
++];
646 out
[outpos
++]=memory
[pos
++];
650 for (j
=0; j
<5; j
++) {
651 printf("%02x ", memory
[pos
]);
652 out
[outpos
++]=memory
[pos
++];
658 for (j
=0; j
<3; j
++) {
659 printf("%02x ", memory
[pos
]);
660 out
[outpos
++]=memory
[pos
++];
664 case 11: /* raster */
666 out
[outpos
++]=memory
[pos
++];
669 printf("\n*** Unknown crdr object code %x...\n", memory
[pos
]);
670 for (j
=0; j
<50; j
++) {
671 printf("%02x ", memory
[pos
]);
672 out
[outpos
++]=memory
[pos
++];
678 out
[outpos
++]=memory
[pos
++]; /* copy $ff */
679 n
=pos
-startpos
; /* bytes to copy */
680 printf("length %d bytes\n", n
);
682 printf("Found %d crazy dream caves in %d bytes!\n", caves
, outpos
);
688 /* save bd2 caves from memory map */
692 int unsupported
=0, uns
[256];
694 /* 256 counters for the 256 possible bytes (8bit). mark each unsupported extension found. */
695 /* if more than 5 types found, bail out with error */
696 for (i
=0; i
<256; ++i
)
699 strcpy((char *)out
, s_bd2
);
701 printf("\n*** Trying to interpret BD2 caves...\n");
703 /* 4*5 (4 groups * 5 caves (4cave+1intermission)) */
704 for (i
=0; i
<4*5; i
++) {
705 int lo
, hi
, j
, pos
, start
;
706 int amount
, n
, mappos
;
710 start
=pos
=memory
[hi
]*256L+memory
[lo
];
711 if (pos
> (0xffff-0x0400)) {
712 printf("Cannot interpret memory contents as BD2 -- invalid cave pointer.\n");
716 printf("Cave %c, addr: %04x\n", i
+'A', pos
);
718 printf("Intermission %d, addr: %04x\n", i
-15, pos
);
721 /* first bytes: cave options */
722 for (j
=0; j
<=0x19; j
++)
723 out
[outpos
++]=memory
[pos
++]; /* cave options */
726 while (j
!=0xFF) { /* végét jelenti; de kiÃrtuk ezt is */
727 if (pos
-start
> 0x400) {
728 /* bd1 caves cannot be this long */
729 printf("Data corrupt or detection failed for bd2 caves -- cave data too long.\n");
735 out
[outpos
++]=memory
[pos
++]; /* obj */
736 out
[outpos
++]=memory
[pos
++]; /* y */
737 out
[outpos
++]=memory
[pos
++]; /* x */
738 out
[outpos
++]=memory
[pos
++]; /* dir */
739 out
[outpos
++]=memory
[pos
++]; /* len */
741 case 1: /* rectangle (outline) */
742 out
[outpos
++]=memory
[pos
++]; /* obj */
743 out
[outpos
++]=memory
[pos
++]; /* y */
744 out
[outpos
++]=memory
[pos
++]; /* x */
745 out
[outpos
++]=memory
[pos
++]; /* h */
746 out
[outpos
++]=memory
[pos
++]; /* w */
748 case 2: /* fillrect */
749 out
[outpos
++]=memory
[pos
++]; /* obj */
750 out
[outpos
++]=memory
[pos
++]; /* y */
751 out
[outpos
++]=memory
[pos
++]; /* x */
752 out
[outpos
++]=memory
[pos
++]; /* h */
753 out
[outpos
++]=memory
[pos
++]; /* w */
754 out
[outpos
++]=memory
[pos
++]; /* fillobj */
757 out
[outpos
++]=memory
[pos
++]; /* obj */
758 out
[outpos
++]=memory
[pos
++]; /* y */
759 out
[outpos
++]=memory
[pos
++]; /* x */
762 out
[outpos
++]=memory
[pos
++]; /* obj */
763 out
[outpos
++]=memory
[pos
++]; /* y */
764 out
[outpos
++]=memory
[pos
++]; /* x */
765 out
[outpos
++]=memory
[pos
++]; /* h */
766 out
[outpos
++]=memory
[pos
++]; /* w */
767 out
[outpos
++]=memory
[pos
++]; /* dy */
768 out
[outpos
++]=memory
[pos
++]; /* dx */
770 case 5: /* profi boulder extension: bitmap */
771 out
[outpos
++]=memory
[pos
++]; /* obj */
772 amount
=memory
[pos
++];
773 out
[outpos
++]=amount
; /* amount */
774 out
[outpos
++]=memory
[pos
++]; /* target msb */
775 out
[outpos
++]=memory
[pos
++]; /* target lsb */
776 for (n
=0; n
<amount
; ++n
)
777 out
[outpos
++]=memory
[pos
++]; /* data */
780 out
[outpos
++]=memory
[pos
++]; /* add to this */
781 out
[outpos
++]=memory
[pos
++]; /* add this */
782 out
[outpos
++]=memory
[pos
++]; /* dy*40+dx */
784 case 7: /* slime permeabilty */
785 out
[outpos
++]=memory
[pos
++]; /* perm */
787 case 9: /* profi boulder extension: plck map */
791 out
[outpos
++]=memory
[pos
++]; /* inbox y */
792 out
[outpos
++]=memory
[pos
++]; /* inbox x */
793 for (n
=0; n
<40*(22-2)/2; n
++) /* 40*20 caves, upper and lower row not contained, 1byte/2 elements */
794 out
[outpos
++]=memory
[mappos
+n
];
798 /* not seen this extension previously */
799 printf(" Found unsupported bd2 extension n.%d\n", j
);
801 uns
[j
]=1; /* mark the newly found unknown extension */
804 /* found to many unsupported extensions - this can't be bd2 */
805 printf("Data corrupt or detection failed for bd2 caves --\n too many unknown extensions.\n");
810 j
=memory
[pos
++]; /* read next */
812 out
[outpos
++]=j
; /* closing 0xff */
813 out
[outpos
++]=memory
[pos
++]; /* animation */
818 pos
=memory
[hi
]*256L+memory
[lo
]; /* pointer to the three colors */
819 out
[outpos
++]=memory
[pos
++];
820 out
[outpos
++]=memory
[pos
++];
821 out
[outpos
++]=memory
[pos
++];
829 /* save bd2 caves from memory map */
830 static int try_bd2_atari()
832 const int cavepointers
=0x86b0;
833 const int cavecolors
=0x86d8;
835 int unsupported
=0, uns
[256];
837 /* 256 counters for the 256 possible bytes (8bit). mark each unsupported extension found. */
838 /* if more than 5 types found, bail out with error */
839 for (i
=0; i
<256; ++i
)
842 strcpy((char *)out
, s_b2a
);
844 printf("\n*** Trying to interpret Atari BD2 caves...\n");
846 /* 4*5 (4 groups * 5 caves (4cave+1intermission)) */
847 for (i
=0; i
<4*5; i
++) {
848 int lo
, hi
, j
, pos
, start
;
849 int amount
, n
, mappos
;
852 hi
=cavepointers
+i
*2+1;
853 start
=pos
=memory
[hi
]*256L+memory
[lo
];
854 if (pos
> (0xffff-0x0400)) {
855 printf("Cannot interpret memory contents as BD2 -- invalid cave pointer.\n");
859 printf("Cave %c, addr: %04x\n", i
+'A', pos
);
861 printf("Intermission %d, addr: %04x\n", i
-15, pos
);
864 /* first bytes: cave options */
865 for (j
=0; j
<=0x19; j
++)
866 out
[outpos
++]=memory
[pos
++]; /* cave options */
869 while (j
!=0xFF) { /* végét jelenti; de kiÃrtuk ezt is */
870 if (pos
-start
> 0x400) {
871 /* bd1 caves cannot be this long */
872 printf("Data corrupt or detection failed for bd2 caves -- cave data too long.\n");
878 out
[outpos
++]=memory
[pos
++]; /* obj */
879 out
[outpos
++]=memory
[pos
++]; /* y */
880 out
[outpos
++]=memory
[pos
++]; /* x */
881 out
[outpos
++]=memory
[pos
++]; /* dir */
882 out
[outpos
++]=memory
[pos
++]; /* len */
884 case 1: /* rectangle (outline) */
885 out
[outpos
++]=memory
[pos
++]; /* obj */
886 out
[outpos
++]=memory
[pos
++]; /* y */
887 out
[outpos
++]=memory
[pos
++]; /* x */
888 out
[outpos
++]=memory
[pos
++]; /* h */
889 out
[outpos
++]=memory
[pos
++]; /* w */
891 case 2: /* fillrect */
892 out
[outpos
++]=memory
[pos
++]; /* obj */
893 out
[outpos
++]=memory
[pos
++]; /* y */
894 out
[outpos
++]=memory
[pos
++]; /* x */
895 out
[outpos
++]=memory
[pos
++]; /* h */
896 out
[outpos
++]=memory
[pos
++]; /* w */
897 out
[outpos
++]=memory
[pos
++]; /* fillobj */
900 out
[outpos
++]=memory
[pos
++]; /* obj */
901 out
[outpos
++]=memory
[pos
++]; /* y */
902 out
[outpos
++]=memory
[pos
++]; /* x */
905 out
[outpos
++]=memory
[pos
++]; /* obj */
906 out
[outpos
++]=memory
[pos
++]; /* y */
907 out
[outpos
++]=memory
[pos
++]; /* x */
908 out
[outpos
++]=memory
[pos
++]; /* h */
909 out
[outpos
++]=memory
[pos
++]; /* w */
910 out
[outpos
++]=memory
[pos
++]; /* dy */
911 out
[outpos
++]=memory
[pos
++]; /* dx */
913 case 5: /* profi boulder extension: bitmap */
914 out
[outpos
++]=memory
[pos
++]; /* obj */
915 amount
=memory
[pos
++];
916 out
[outpos
++]=amount
; /* amount */
917 out
[outpos
++]=memory
[pos
++]; /* target msb */
918 out
[outpos
++]=memory
[pos
++]; /* target lsb */
919 for (n
=0; n
<amount
; ++n
)
920 out
[outpos
++]=memory
[pos
++]; /* data */
923 out
[outpos
++]=memory
[pos
++]; /* add to this */
924 out
[outpos
++]=memory
[pos
++]; /* add this */
925 out
[outpos
++]=memory
[pos
++]; /* dy*40+dx */
927 case 7: /* slime permeabilty */
928 out
[outpos
++]=memory
[pos
++]; /* perm */
930 case 9: /* profi boulder extension: plck map */
934 out
[outpos
++]=memory
[pos
++]; /* inbox y */
935 out
[outpos
++]=memory
[pos
++]; /* inbox x */
936 for (n
=0; n
<40*(22-2)/2; n
++) /* 40*20 caves, upper and lower row not contained, 1byte/2 elements */
937 out
[outpos
++]=memory
[mappos
+n
];
941 /* not seen this extension previously */
942 printf(" Found unsupported bd2 extension n.%d\n", j
);
944 uns
[j
]=1; /* mark the newly found unknown extension */
947 /* found to many unsupported extensions - this can't be bd2 */
948 printf("Data corrupt or detection failed for bd2 caves --\n too many unknown extensions.\n");
953 j
=memory
[pos
++]; /* read next */
955 out
[outpos
++]=j
; /* closing 0xff */
956 out
[outpos
++]=memory
[pos
++]; /* animation bits */
961 pos
=memory
[hi
]*256L+memory
[lo
]; /* pointer to the three colors */
962 out
[outpos
++]=memory
[pos
++];
963 out
[outpos
++]=memory
[pos
++];
964 out
[outpos
++]=memory
[pos
++];
965 out
[outpos
++]=memory
[pos
++]; /* slime and amoeba color */
966 out
[outpos
++]=memory
[pos
++]; /* background (and border) */
973 /* save plck caves from memory map */
974 static int try_1stb()
978 strcpy((char *)out
, s_1st
);
980 printf("\n*** Trying to interpret 1stb caves...\n");
982 /* there must be 20 caves, according to bd inside faq. */
983 for (i
=0; i
<20; i
++) {
985 int pos
=0x7010+0x400*i
;
987 /* 1stb caves have cave time, diamonds and the like encoded in bcd numbers,
988 one digit in each bytes. check that. */
989 for (j
=0x370; j
<0x379+3; j
++)
990 if (memory
[pos
+j
]>9) {
991 printf("Data corrupt or detection failed for 1stb caves.\n");
994 printf("Cave %d, addr: %04x\n", i
+1, pos
);
996 for (j
=0; j
<0x400; ++j
)
997 out
[outpos
++]=memory
[pos
++];
999 printf("Found %d 1stb caves!\n", i
);
1004 static int save(const char *outname
)
1009 /* write data length in little endian */
1010 out
[8]=((outpos
-12))&0xff;
1011 out
[9]=((outpos
-12)>>8)&0xff;
1012 out
[10]=((outpos
-12)>>16)&0xff;
1013 out
[11]=((outpos
-12)>>24)&0xff;
1016 fout
=fopen(outname
, "wb");
1018 printf("Cannot open outfile %s\n", outname
);
1021 written
=fwrite(out
, 1, outpos
, fout
);
1022 if (written
!=outpos
|| fclose(fout
)!=0) {
1023 printf("File write error to %s\n", outname
);
1027 printf("Saved to %s\n", outname
);
1033 int main(int argc
, char* argv
[])
1035 char outfilename
[512];
1038 if (argc
<2 || argc
>3) {
1039 printf("Converts memory dumps or vice snapshots of bd games\n");
1040 printf("to formats loadable by gdash.\n");
1042 printf("Usage: %s <inputfile> [outputfile]\n", argv
[0]);
1043 printf(" where inputfile is a memory map or a vice snapshot.\n");
1045 printf("Use Alt-F11 or Alt-S in vice to create a snapshot file (*.vsf),\n");
1046 printf("or the monitor command s \"filename\" 0 0 ffff for memory contents.\n");
1048 printf("Beware that memory contents depend on actual memory pages set for cpu,\n");
1049 printf("so snapshot is better. Also load the game completely: wait until the\n");
1050 printf("usual scrolling screen appears, where you press f1 or fire.\n");
1051 printf("Proper extension is added to output file automatically.\n");
1053 printf("Engines supported: BD1, BD2, PLCK, 1stB, CrLi.\n");
1054 printf("Game-wide Diego effects are also supported, and converted to\n");
1055 printf("cave-specific effects. Unknown effects are reported, so check\n");
1061 if (!loadfile(argv
[1]))
1063 /* if second cmdline option, treat as output filename */
1065 strcpy(outfilename
, argv
[2]);
1067 strcpy(outfilename
, argv
[1]); /* use input file name, and change extension */
1069 /* output filename part */
1070 strcpy(outfilename
, argv
[1]);
1071 if (strchr(outfilename
, '/') || strchr(outfilename
, '\\')) {
1072 /* yes we have a pathname. */
1074 sep
=strrchr(outfilename
, '/');
1075 if (!sep
) /* XXX should use #define for windows code */
1076 sep
=strrchr(outfilename
, '\\');
1077 dot
=strrchr(outfilename
, '.');
1078 if ((dot
-sep
) > 1) /* dot later than last separator; >1 ensures that filename is not sg like .asd */
1081 /* we have no pathname */
1082 char *dot
=strrchr(outfilename
, '.');
1084 /* if we have extension, and filename is not only an extension :) */
1085 if (dot
|| dot
!=outfilename
)
1091 strcat(outfilename
, ".gds");
1093 result
=!save(outfilename
);
1095 if (try_atari_plck()) {
1096 result
=!save(outfilename
);
1098 if (try_bd1(0)) { /* try c64 bd1 */
1099 result
=!save(outfilename
);
1101 if (try_bd1(1)) { /* try atari bd1 */
1102 result
=!save(outfilename
);
1104 if (try_bd2()) { /* try c64 bd2 */
1105 result
=!save(outfilename
);
1107 if (try_bd2_atari()) { /* try atari bd2 */
1108 result
=!save(outfilename
);
1111 result
=!save(outfilename
);
1114 result
=!save(outfilename
);
1117 result
=!save(outfilename
);
1119 printf("Could not export cave data -- unknown cave format!\n");