| 1 |
#include <ctype.h> |
| 2 |
|
| 3 |
#include "driver.h" |
| 4 |
#include "sound/samples.h" |
| 5 |
#include "info.h" |
| 6 |
#include "datafile.h" |
| 7 |
|
| 8 |
/* Output format indentation */ |
| 9 |
|
| 10 |
/* Indentation */ |
| 11 |
#define INDENT "\t" |
| 12 |
|
| 13 |
/* Output format configuration |
| 14 |
L1 first level |
| 15 |
L2 second level |
| 16 |
B begin a list of items |
| 17 |
E end a list of items |
| 18 |
P begin an item |
| 19 |
N end an item |
| 20 |
*/ |
| 21 |
|
| 22 |
/* Output unformatted */ |
| 23 |
/* |
| 24 |
#define L1B "(" |
| 25 |
#define L1P " " |
| 26 |
#define L1N "" |
| 27 |
#define L1E ")" |
| 28 |
#define L2B "(" |
| 29 |
#define L2P " " |
| 30 |
#define L2N "" |
| 31 |
#define L2E ")" |
| 32 |
*/ |
| 33 |
|
| 34 |
/* Output on one level */ |
| 35 |
#define L1B " (\n" |
| 36 |
#define L1P INDENT |
| 37 |
#define L1N "\n" |
| 38 |
#define L1E ")\n\n" |
| 39 |
#define L2B " (" |
| 40 |
#define L2P " " |
| 41 |
#define L2N "" |
| 42 |
#define L2E " )" |
| 43 |
|
| 44 |
/* Output on two levels */ |
| 45 |
/* |
| 46 |
#define L1B " (\n" |
| 47 |
#define L1P INDENT |
| 48 |
#define L1N "\n" |
| 49 |
#define L1E ")\n\n" |
| 50 |
#define L2B " (\n" |
| 51 |
#define L2P INDENT INDENT |
| 52 |
#define L2N "\n" |
| 53 |
#define L2E INDENT ")" |
| 54 |
*/ |
| 55 |
|
| 56 |
/* Print a string in C format */ |
| 57 |
static void print_c_string(FILE* out, const char* s) |
| 58 |
{ |
| 59 |
fprintf(out, "\""); |
| 60 |
if (s) |
| 61 |
{ |
| 62 |
while (*s) |
| 63 |
{ |
| 64 |
switch (*s) |
| 65 |
{ |
| 66 |
case '\a' : fprintf(out, "\\a"); break; |
| 67 |
case '\b' : fprintf(out, "\\b"); break; |
| 68 |
case '\f' : fprintf(out, "\\f"); break; |
| 69 |
case '\n' : fprintf(out, "\\n"); break; |
| 70 |
case '\r' : fprintf(out, "\\r"); break; |
| 71 |
case '\t' : fprintf(out, "\\t"); break; |
| 72 |
case '\v' : fprintf(out, "\\v"); break; |
| 73 |
case '\\' : fprintf(out, "\\\\"); break; |
| 74 |
case '\"' : fprintf(out, "\\\""); break; |
| 75 |
default: |
| 76 |
if (*s>=' ' && *s<='~') |
| 77 |
fprintf(out, "%c", *s); |
| 78 |
else |
| 79 |
fprintf(out, "\\x%02x", (unsigned)(unsigned char)*s); |
| 80 |
} |
| 81 |
++s; |
| 82 |
} |
| 83 |
} |
| 84 |
fprintf(out, "\""); |
| 85 |
} |
| 86 |
|
| 87 |
/* Print a string in statement format (remove space, parentesis, ") */ |
| 88 |
static void print_statement_string(FILE* out, const char* s) |
| 89 |
{ |
| 90 |
if (s) |
| 91 |
{ |
| 92 |
while (*s) |
| 93 |
{ |
| 94 |
if (isspace(*s)) |
| 95 |
{ |
| 96 |
fprintf(out, "_"); |
| 97 |
} |
| 98 |
else |
| 99 |
{ |
| 100 |
switch (*s) |
| 101 |
{ |
| 102 |
case '(' : |
| 103 |
case ')' : |
| 104 |
case '"' : |
| 105 |
fprintf(out, "_"); |
| 106 |
break; |
| 107 |
default: |
| 108 |
fprintf(out, "%c", *s); |
| 109 |
} |
| 110 |
} |
| 111 |
++s; |
| 112 |
} |
| 113 |
} |
| 114 |
else |
| 115 |
{ |
| 116 |
fprintf(out, "null"); |
| 117 |
} |
| 118 |
} |
| 119 |
|
| 120 |
static void print_game_switch(FILE* out, const struct GameDriver* game) |
| 121 |
{ |
| 122 |
const struct InputPortTiny* input = game->input_ports; |
| 123 |
|
| 124 |
while ((input->type & ~IPF_MASK) != IPT_END) |
| 125 |
{ |
| 126 |
if ((input->type & ~IPF_MASK)==IPT_DIPSWITCH_NAME) |
| 127 |
{ |
| 128 |
int def = input->default_value; |
| 129 |
const char* def_name = 0; |
| 130 |
|
| 131 |
fprintf(out, L1P "dipswitch" L2B); |
| 132 |
|
| 133 |
fprintf(out, L2P "name " ); |
| 134 |
print_c_string(out,input->name); |
| 135 |
fprintf(out, "%s", L2N); |
| 136 |
++input; |
| 137 |
|
| 138 |
while ((input->type & ~IPF_MASK)==IPT_DIPSWITCH_SETTING) |
| 139 |
{ |
| 140 |
if (def == input->default_value) |
| 141 |
def_name = input->name; |
| 142 |
fprintf(out, L2P "entry " ); |
| 143 |
print_c_string(out,input->name); |
| 144 |
fprintf(out, "%s", L2N); |
| 145 |
++input; |
| 146 |
} |
| 147 |
|
| 148 |
if (def_name) |
| 149 |
{ |
| 150 |
fprintf(out, L2P "default "); |
| 151 |
print_c_string(out,def_name); |
| 152 |
fprintf(out, "%s", L2N); |
| 153 |
} |
| 154 |
|
| 155 |
fprintf(out, L2E L1N); |
| 156 |
} |
| 157 |
else |
| 158 |
++input; |
| 159 |
} |
| 160 |
} |
| 161 |
|
| 162 |
static void print_game_input(FILE* out, const struct GameDriver* game) |
| 163 |
{ |
| 164 |
const struct InputPortTiny* input = game->input_ports; |
| 165 |
int nplayer = 0; |
| 166 |
const char* control = 0; |
| 167 |
int nbutton = 0; |
| 168 |
int ncoin = 0; |
| 169 |
const char* service = 0; |
| 170 |
const char* tilt = 0; |
| 171 |
|
| 172 |
while ((input->type & ~IPF_MASK) != IPT_END) |
| 173 |
{ |
| 174 |
switch (input->type & IPF_PLAYERMASK) |
| 175 |
{ |
| 176 |
case IPF_PLAYER1: |
| 177 |
if (nplayer<1) nplayer = 1; |
| 178 |
break; |
| 179 |
case IPF_PLAYER2: |
| 180 |
if (nplayer<2) nplayer = 2; |
| 181 |
break; |
| 182 |
case IPF_PLAYER3: |
| 183 |
if (nplayer<3) nplayer = 3; |
| 184 |
break; |
| 185 |
case IPF_PLAYER4: |
| 186 |
if (nplayer<4) nplayer = 4; |
| 187 |
break; |
| 188 |
} |
| 189 |
switch (input->type & ~IPF_MASK) |
| 190 |
{ |
| 191 |
case IPT_JOYSTICK_UP: |
| 192 |
case IPT_JOYSTICK_DOWN: |
| 193 |
case IPT_JOYSTICK_LEFT: |
| 194 |
case IPT_JOYSTICK_RIGHT: |
| 195 |
if (input->type & IPF_2WAY) |
| 196 |
control = "joy2way"; |
| 197 |
else if (input->type & IPF_4WAY) |
| 198 |
control = "joy4way"; |
| 199 |
else |
| 200 |
control = "joy8way"; |
| 201 |
break; |
| 202 |
case IPT_JOYSTICKRIGHT_UP: |
| 203 |
case IPT_JOYSTICKRIGHT_DOWN: |
| 204 |
case IPT_JOYSTICKRIGHT_LEFT: |
| 205 |
case IPT_JOYSTICKRIGHT_RIGHT: |
| 206 |
case IPT_JOYSTICKLEFT_UP: |
| 207 |
case IPT_JOYSTICKLEFT_DOWN: |
| 208 |
case IPT_JOYSTICKLEFT_LEFT: |
| 209 |
case IPT_JOYSTICKLEFT_RIGHT: |
| 210 |
if (input->type & IPF_2WAY) |
| 211 |
control = "doublejoy2way"; |
| 212 |
else if (input->type & IPF_4WAY) |
| 213 |
control = "doublejoy4way"; |
| 214 |
else |
| 215 |
control = "doublejoy8way"; |
| 216 |
break; |
| 217 |
case IPT_BUTTON1: |
| 218 |
if (nbutton<1) nbutton = 1; |
| 219 |
break; |
| 220 |
case IPT_BUTTON2: |
| 221 |
if (nbutton<2) nbutton = 2; |
| 222 |
break; |
| 223 |
case IPT_BUTTON3: |
| 224 |
if (nbutton<3) nbutton = 3; |
| 225 |
break; |
| 226 |
case IPT_BUTTON4: |
| 227 |
if (nbutton<4) nbutton = 4; |
| 228 |
break; |
| 229 |
case IPT_BUTTON5: |
| 230 |
if (nbutton<5) nbutton = 5; |
| 231 |
break; |
| 232 |
case IPT_BUTTON6: |
| 233 |
if (nbutton<6) nbutton = 6; |
| 234 |
break; |
| 235 |
case IPT_BUTTON7: |
| 236 |
if (nbutton<7) nbutton = 7; |
| 237 |
break; |
| 238 |
case IPT_BUTTON8: |
| 239 |
if (nbutton<8) nbutton = 8; |
| 240 |
break; |
| 241 |
case IPT_PADDLE: |
| 242 |
control = "paddle"; |
| 243 |
break; |
| 244 |
case IPT_DIAL: |
| 245 |
control = "dial"; |
| 246 |
break; |
| 247 |
case IPT_TRACKBALL_X: |
| 248 |
case IPT_TRACKBALL_Y: |
| 249 |
control = "trackball"; |
| 250 |
break; |
| 251 |
case IPT_AD_STICK_X: |
| 252 |
case IPT_AD_STICK_Y: |
| 253 |
control = "stick"; |
| 254 |
break; |
| 255 |
case IPT_COIN1: |
| 256 |
if (ncoin < 1) ncoin = 1; |
| 257 |
break; |
| 258 |
case IPT_COIN2: |
| 259 |
if (ncoin < 2) ncoin = 2; |
| 260 |
break; |
| 261 |
case IPT_COIN3: |
| 262 |
if (ncoin < 3) ncoin = 3; |
| 263 |
break; |
| 264 |
case IPT_COIN4: |
| 265 |
if (ncoin < 4) ncoin = 4; |
| 266 |
break; |
| 267 |
case IPT_SERVICE : |
| 268 |
service = "yes"; |
| 269 |
break; |
| 270 |
case IPT_TILT : |
| 271 |
tilt = "yes"; |
| 272 |
break; |
| 273 |
} |
| 274 |
++input; |
| 275 |
} |
| 276 |
|
| 277 |
fprintf(out, L1P "input" L2B); |
| 278 |
fprintf(out, L2P "players %d" L2N, nplayer ); |
| 279 |
if (control) |
| 280 |
fprintf(out, L2P "control %s" L2N, control ); |
| 281 |
if (nbutton) |
| 282 |
fprintf(out, L2P "buttons %d" L2N, nbutton ); |
| 283 |
if (ncoin) |
| 284 |
fprintf(out, L2P "coins %d" L2N, ncoin ); |
| 285 |
if (service) |
| 286 |
fprintf(out, L2P "service %s" L2N, service ); |
| 287 |
if (tilt) |
| 288 |
fprintf(out, L2P "tilt %s" L2N, tilt ); |
| 289 |
fprintf(out, L2E L1N); |
| 290 |
} |
| 291 |
|
| 292 |
static void print_game_rom(FILE* out, const struct GameDriver* game) |
| 293 |
{ |
| 294 |
const struct RomModule *region, *rom, *chunk; |
| 295 |
const struct RomModule *pregion, *prom, *fprom=NULL; |
| 296 |
extern struct GameDriver driver_0; |
| 297 |
|
| 298 |
if (!game->rom) |
| 299 |
return; |
| 300 |
|
| 301 |
if (game->clone_of && game->clone_of != &driver_0) |
| 302 |
fprintf(out, L1P "romof %s" L1N, game->clone_of->name); |
| 303 |
|
| 304 |
for (region = rom_first_region(game); region; region = rom_next_region(region)) |
| 305 |
for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) |
| 306 |
{ |
| 307 |
char name[100]; |
| 308 |
int offset, length, crc, in_parent; |
| 309 |
|
| 310 |
sprintf(name,ROM_GETNAME(rom)); |
| 311 |
offset = ROM_GETOFFSET(rom); |
| 312 |
crc = ROM_GETCRC(rom); |
| 313 |
|
| 314 |
in_parent = 0; |
| 315 |
length = 0; |
| 316 |
for (chunk = rom_first_chunk(rom); chunk; chunk = rom_next_chunk(chunk)) |
| 317 |
length += ROM_GETLENGTH(chunk); |
| 318 |
|
| 319 |
if (crc && game->clone_of) |
| 320 |
{ |
| 321 |
fprom=NULL; |
| 322 |
for (pregion = rom_first_region(game->clone_of); pregion; pregion = rom_next_region(pregion)) |
| 323 |
for (prom = rom_first_file(pregion); prom; prom = rom_next_file(prom)) |
| 324 |
if (ROM_GETCRC(prom) == crc) |
| 325 |
{ |
| 326 |
if (!fprom || !strcmp(ROM_GETNAME(prom), name)) |
| 327 |
fprom=prom; |
| 328 |
in_parent = 1; |
| 329 |
} |
| 330 |
} |
| 331 |
|
| 332 |
fprintf(out, L1P "rom" L2B); |
| 333 |
if (*name) |
| 334 |
fprintf(out, L2P "name %s" L2N, name); |
| 335 |
if(in_parent) |
| 336 |
fprintf(out, L2P "merge %s" L2N, ROM_GETNAME(fprom)); |
| 337 |
fprintf(out, L2P "size %d" L2N, length); |
| 338 |
fprintf(out, L2P "crc %08x" L2N, crc); |
| 339 |
switch (ROMREGION_GETTYPE(region)) |
| 340 |
{ |
| 341 |
case REGION_CPU1: fprintf(out, L2P "region cpu1" L2N); break; |
| 342 |
case REGION_CPU2: fprintf(out, L2P "region cpu2" L2N); break; |
| 343 |
case REGION_CPU3: fprintf(out, L2P "region cpu3" L2N); break; |
| 344 |
case REGION_CPU4: fprintf(out, L2P "region cpu4" L2N); break; |
| 345 |
case REGION_CPU5: fprintf(out, L2P "region cpu5" L2N); break; |
| 346 |
case REGION_CPU6: fprintf(out, L2P "region cpu6" L2N); break; |
| 347 |
case REGION_CPU7: fprintf(out, L2P "region cpu7" L2N); break; |
| 348 |
case REGION_CPU8: fprintf(out, L2P "region cpu8" L2N); break; |
| 349 |
case REGION_GFX1: fprintf(out, L2P "region gfx1" L2N); break; |
| 350 |
case REGION_GFX2: fprintf(out, L2P "region gfx2" L2N); break; |
| 351 |
case REGION_GFX3: fprintf(out, L2P "region gfx3" L2N); break; |
| 352 |
case REGION_GFX4: fprintf(out, L2P "region gfx4" L2N); break; |
| 353 |
case REGION_GFX5: fprintf(out, L2P "region gfx5" L2N); break; |
| 354 |
case REGION_GFX6: fprintf(out, L2P "region gfx6" L2N); break; |
| 355 |
case REGION_GFX7: fprintf(out, L2P "region gfx7" L2N); break; |
| 356 |
case REGION_GFX8: fprintf(out, L2P "region gfx8" L2N); break; |
| 357 |
case REGION_PROMS: fprintf(out, L2P "region proms" L2N); break; |
| 358 |
case REGION_SOUND1: fprintf(out, L2P "region sound1" L2N); break; |
| 359 |
case REGION_SOUND2: fprintf(out, L2P "region sound2" L2N); break; |
| 360 |
case REGION_SOUND3: fprintf(out, L2P "region sound3" L2N); break; |
| 361 |
case REGION_SOUND4: fprintf(out, L2P "region sound4" L2N); break; |
| 362 |
case REGION_SOUND5: fprintf(out, L2P "region sound5" L2N); break; |
| 363 |
case REGION_SOUND6: fprintf(out, L2P "region sound6" L2N); break; |
| 364 |
case REGION_SOUND7: fprintf(out, L2P "region sound7" L2N); break; |
| 365 |
case REGION_SOUND8: fprintf(out, L2P "region sound8" L2N); break; |
| 366 |
case REGION_USER1: fprintf(out, L2P "region user1" L2N); break; |
| 367 |
case REGION_USER2: fprintf(out, L2P "region user2" L2N); break; |
| 368 |
case REGION_USER3: fprintf(out, L2P "region user3" L2N); break; |
| 369 |
case REGION_USER4: fprintf(out, L2P "region user4" L2N); break; |
| 370 |
case REGION_USER5: fprintf(out, L2P "region user5" L2N); break; |
| 371 |
case REGION_USER6: fprintf(out, L2P "region user6" L2N); break; |
| 372 |
case REGION_USER7: fprintf(out, L2P "region user7" L2N); break; |
| 373 |
case REGION_USER8: fprintf(out, L2P "region user8" L2N); break; |
| 374 |
default: fprintf(out, L2P "region 0x%x" L2N, ROMREGION_GETTYPE(region)); |
| 375 |
} |
| 376 |
switch (ROMREGION_GETFLAGS(region)) |
| 377 |
{ |
| 378 |
case 0: |
| 379 |
break; |
| 380 |
case ROMREGION_SOUNDONLY: |
| 381 |
fprintf(out, L2P "flags soundonly" L2N); |
| 382 |
break; |
| 383 |
case ROMREGION_DISPOSE: |
| 384 |
fprintf(out, L2P "flags dispose" L2N); |
| 385 |
break; |
| 386 |
default: |
| 387 |
fprintf(out, L2P "flags 0x%x" L2N, ROMREGION_GETFLAGS(region)); |
| 388 |
} |
| 389 |
fprintf(out, L2P "offs %x", offset); |
| 390 |
fprintf(out, L2E L1N); |
| 391 |
} |
| 392 |
} |
| 393 |
|
| 394 |
static void print_game_sample(FILE* out, const struct GameDriver* game) |
| 395 |
{ |
| 396 |
#if (HAS_SAMPLES || HAS_VLM5030) |
| 397 |
struct InternalMachineDriver drv; |
| 398 |
int i; |
| 399 |
|
| 400 |
expand_machine_driver(game->drv, &drv); |
| 401 |
|
| 402 |
for( i = 0; drv.sound[i].sound_type && i < MAX_SOUND; i++ ) |
| 403 |
{ |
| 404 |
const char **samplenames = NULL; |
| 405 |
#if (HAS_SAMPLES) |
| 406 |
if( drv.sound[i].sound_type == SOUND_SAMPLES ) |
| 407 |
samplenames = ((struct Samplesinterface *)drv.sound[i].sound_interface)->samplenames; |
| 408 |
#endif |
| 409 |
if (samplenames != 0 && samplenames[0] != 0) { |
| 410 |
int k = 0; |
| 411 |
if (samplenames[k][0]=='*') |
| 412 |
{ |
| 413 |
/* output sampleof only if different from game name */ |
| 414 |
if (strcmp(samplenames[k] + 1, game->name)!=0) |
| 415 |
fprintf(out, L1P "sampleof %s" L1N, samplenames[k] + 1); |
| 416 |
++k; |
| 417 |
} |
| 418 |
while (samplenames[k] != 0) { |
| 419 |
/* Check if is not empty */ |
| 420 |
if (*samplenames[k]) { |
| 421 |
/* Check if sample is duplicate */ |
| 422 |
int l = 0; |
| 423 |
while (l<k && strcmp(samplenames[k],samplenames[l])!=0) |
| 424 |
++l; |
| 425 |
if (l==k) |
| 426 |
fprintf(out, L1P "sample %s" L1N, samplenames[k]); |
| 427 |
} |
| 428 |
++k; |
| 429 |
} |
| 430 |
} |
| 431 |
} |
| 432 |
#endif |
| 433 |
} |
| 434 |
|
| 435 |
static void print_game_micro(FILE* out, const struct GameDriver* game) |
| 436 |
{ |
| 437 |
struct InternalMachineDriver driver; |
| 438 |
const struct MachineCPU* cpu; |
| 439 |
const struct MachineSound* sound; |
| 440 |
int j; |
| 441 |
|
| 442 |
expand_machine_driver(game->drv, &driver); |
| 443 |
cpu = driver.cpu; |
| 444 |
sound = driver.sound; |
| 445 |
|
| 446 |
for(j=0;j<MAX_CPU;++j) |
| 447 |
{ |
| 448 |
if (cpu[j].cpu_type!=0) |
| 449 |
{ |
| 450 |
fprintf(out, L1P "chip" L2B); |
| 451 |
if (cpu[j].cpu_type & CPU_AUDIO_CPU) |
| 452 |
fprintf(out, L2P "type cpu flags audio" L2N); |
| 453 |
else |
| 454 |
fprintf(out, L2P "type cpu" L2N); |
| 455 |
|
| 456 |
fprintf(out, L2P "name "); |
| 457 |
print_statement_string(out, cputype_name(cpu[j].cpu_type)); |
| 458 |
fprintf(out, "%s", L2N); |
| 459 |
|
| 460 |
fprintf(out, L2P "clock %d" L2N, cpu[j].cpu_clock); |
| 461 |
fprintf(out, L2E L1N); |
| 462 |
} |
| 463 |
} |
| 464 |
|
| 465 |
for(j=0;j<MAX_SOUND;++j) if (sound[j].sound_type) |
| 466 |
{ |
| 467 |
if (sound[j].sound_type) |
| 468 |
{ |
| 469 |
int num = sound_num(&sound[j]); |
| 470 |
int l; |
| 471 |
|
| 472 |
if (num == 0) num = 1; |
| 473 |
|
| 474 |
for(l=0;l<num;++l) |
| 475 |
{ |
| 476 |
fprintf(out, L1P "chip" L2B); |
| 477 |
fprintf(out, L2P "type audio" L2N); |
| 478 |
fprintf(out, L2P "name "); |
| 479 |
print_statement_string(out, sound_name(&sound[j])); |
| 480 |
fprintf(out, "%s", L2N); |
| 481 |
if (sound_clock(&sound[j])) |
| 482 |
fprintf(out, L2P "clock %d" L2N, sound_clock(&sound[j])); |
| 483 |
fprintf(out, L2E L1N); |
| 484 |
} |
| 485 |
} |
| 486 |
} |
| 487 |
} |
| 488 |
|
| 489 |
static void print_game_video(FILE* out, const struct GameDriver* game) |
| 490 |
{ |
| 491 |
struct InternalMachineDriver driver; |
| 492 |
|
| 493 |
int dx; |
| 494 |
int dy; |
| 495 |
int ax; |
| 496 |
int ay; |
| 497 |
int showxy; |
| 498 |
int orientation; |
| 499 |
|
| 500 |
expand_machine_driver(game->drv, &driver); |
| 501 |
|
| 502 |
fprintf(out, L1P "video" L2B); |
| 503 |
if (driver.video_attributes & VIDEO_TYPE_VECTOR) |
| 504 |
{ |
| 505 |
fprintf(out, L2P "screen vector" L2N); |
| 506 |
showxy = 0; |
| 507 |
} |
| 508 |
else |
| 509 |
{ |
| 510 |
fprintf(out, L2P "screen raster" L2N); |
| 511 |
showxy = 1; |
| 512 |
} |
| 513 |
|
| 514 |
if (game->flags & ORIENTATION_SWAP_XY) |
| 515 |
{ |
| 516 |
ax = VIDEO_ASPECT_RATIO_DEN(driver.video_attributes); |
| 517 |
ay = VIDEO_ASPECT_RATIO_NUM(driver.video_attributes); |
| 518 |
if (ax == 0 && ay == 0) { |
| 519 |
ax = 3; |
| 520 |
ay = 4; |
| 521 |
} |
| 522 |
dx = driver.default_visible_area.max_y - driver.default_visible_area.min_y + 1; |
| 523 |
dy = driver.default_visible_area.max_x - driver.default_visible_area.min_x + 1; |
| 524 |
orientation = 1; |
| 525 |
} |
| 526 |
else |
| 527 |
{ |
| 528 |
ax = VIDEO_ASPECT_RATIO_NUM(driver.video_attributes); |
| 529 |
ay = VIDEO_ASPECT_RATIO_DEN(driver.video_attributes); |
| 530 |
if (ax == 0 && ay == 0) { |
| 531 |
ax = 4; |
| 532 |
ay = 3; |
| 533 |
} |
| 534 |
dx = driver.default_visible_area.max_x - driver.default_visible_area.min_x + 1; |
| 535 |
dy = driver.default_visible_area.max_y - driver.default_visible_area.min_y + 1; |
| 536 |
orientation = 0; |
| 537 |
} |
| 538 |
|
| 539 |
fprintf(out, L2P "orientation %s" L2N, orientation ? "vertical" : "horizontal" ); |
| 540 |
if (showxy) |
| 541 |
{ |
| 542 |
fprintf(out, L2P "x %d" L2N, dx); |
| 543 |
fprintf(out, L2P "y %d" L2N, dy); |
| 544 |
} |
| 545 |
|
| 546 |
fprintf(out, L2P "aspectx %d" L2N, ax); |
| 547 |
fprintf(out, L2P "aspecty %d" L2N, ay); |
| 548 |
|
| 549 |
fprintf(out, L2P "freq %f" L2N, driver.frames_per_second); |
| 550 |
fprintf(out, L2E L1N); |
| 551 |
} |
| 552 |
|
| 553 |
static void print_game_sound(FILE* out, const struct GameDriver* game) |
| 554 |
{ |
| 555 |
struct InternalMachineDriver driver; |
| 556 |
const struct MachineCPU* cpu; |
| 557 |
const struct MachineSound* sound; |
| 558 |
|
| 559 |
/* check if the game have sound emulation */ |
| 560 |
int has_sound = 0; |
| 561 |
int i; |
| 562 |
|
| 563 |
expand_machine_driver(game->drv, &driver); |
| 564 |
cpu = driver.cpu; |
| 565 |
sound = driver.sound; |
| 566 |
|
| 567 |
i = 0; |
| 568 |
while (i < MAX_SOUND && !has_sound) |
| 569 |
{ |
| 570 |
if (sound[i].sound_type) |
| 571 |
has_sound = 1; |
| 572 |
++i; |
| 573 |
} |
| 574 |
i = 0; |
| 575 |
while (i < MAX_CPU && !has_sound) |
| 576 |
{ |
| 577 |
if ((cpu[i].cpu_type & CPU_AUDIO_CPU)!=0) |
| 578 |
has_sound = 1; |
| 579 |
++i; |
| 580 |
} |
| 581 |
|
| 582 |
fprintf(out, L1P "sound" L2B); |
| 583 |
|
| 584 |
/* sound channel */ |
| 585 |
if (has_sound) |
| 586 |
{ |
| 587 |
if (driver.sound_attributes & SOUND_SUPPORTS_STEREO) |
| 588 |
fprintf(out, L2P "channels 2" L2N); |
| 589 |
else |
| 590 |
fprintf(out, L2P "channels 1" L2N); |
| 591 |
} |
| 592 |
else |
| 593 |
fprintf(out, L2P "channels 0" L2N); |
| 594 |
|
| 595 |
fprintf(out, L2E L1N); |
| 596 |
} |
| 597 |
|
| 598 |
#define HISTORY_BUFFER_MAX 16384 |
| 599 |
|
| 600 |
static void print_game_history(FILE* out, const struct GameDriver* game) |
| 601 |
{ |
| 602 |
char buffer[HISTORY_BUFFER_MAX]; |
| 603 |
|
| 604 |
if (load_driver_history(game,buffer,HISTORY_BUFFER_MAX)==0) |
| 605 |
{ |
| 606 |
fprintf(out, L1P "history "); |
| 607 |
print_c_string(out, buffer); |
| 608 |
fprintf(out, "%s", L1N); |
| 609 |
} |
| 610 |
} |
| 611 |
|
| 612 |
static void print_game_driver(FILE* out, const struct GameDriver* game) |
| 613 |
{ |
| 614 |
struct InternalMachineDriver driver; |
| 615 |
|
| 616 |
expand_machine_driver(game->drv, &driver); |
| 617 |
|
| 618 |
fprintf(out, L1P "driver" L2B); |
| 619 |
if (game->flags & GAME_NOT_WORKING) |
| 620 |
fprintf(out, L2P "status preliminary" L2N); |
| 621 |
else |
| 622 |
fprintf(out, L2P "status good" L2N); |
| 623 |
|
| 624 |
if (game->flags & GAME_WRONG_COLORS) |
| 625 |
fprintf(out, L2P "color preliminary" L2N); |
| 626 |
else if (game->flags & GAME_IMPERFECT_COLORS) |
| 627 |
fprintf(out, L2P "color imperfect" L2N); |
| 628 |
else |
| 629 |
fprintf(out, L2P "color good" L2N); |
| 630 |
|
| 631 |
if (game->flags & GAME_NO_SOUND) |
| 632 |
fprintf(out, L2P "sound preliminary" L2N); |
| 633 |
else if (game->flags & GAME_IMPERFECT_SOUND) |
| 634 |
fprintf(out, L2P "sound imperfect" L2N); |
| 635 |
else |
| 636 |
fprintf(out, L2P "sound good" L2N); |
| 637 |
|
| 638 |
fprintf(out, L2P "palettesize %d" L2N, driver.total_colors); |
| 639 |
|
| 640 |
if (driver.video_attributes & VIDEO_SUPPORTS_DIRTY) |
| 641 |
fprintf(out, L2P "blit dirty" L2N); |
| 642 |
else |
| 643 |
fprintf(out, L2P "blit plain" L2N); |
| 644 |
|
| 645 |
fprintf(out, L2E L1N); |
| 646 |
} |
| 647 |
|
| 648 |
/* Print the MAME info record for a game */ |
| 649 |
static void print_game_info(FILE* out, const struct GameDriver* game) |
| 650 |
{ |
| 651 |
|
| 652 |
#ifndef MESS |
| 653 |
fprintf(out, "game" L1B ); |
| 654 |
#else |
| 655 |
fprintf(out, "machine" L1B ); |
| 656 |
#endif |
| 657 |
|
| 658 |
fprintf(out, L1P "name %s" L1N, game->name ); |
| 659 |
|
| 660 |
if (game->description) |
| 661 |
{ |
| 662 |
fprintf(out, L1P "description "); |
| 663 |
print_c_string(out, game->description ); |
| 664 |
fprintf(out, "%s", L1N); |
| 665 |
} |
| 666 |
|
| 667 |
/* print the year only if is a number */ |
| 668 |
if (game->year && strspn(game->year,"0123456789")==strlen(game->year)) |
| 669 |
fprintf(out, L1P "year %s" L1N, game->year ); |
| 670 |
|
| 671 |
if (game->manufacturer) |
| 672 |
{ |
| 673 |
fprintf(out, L1P "manufacturer "); |
| 674 |
print_c_string(out, game->manufacturer ); |
| 675 |
fprintf(out, "%s", L1N); |
| 676 |
} |
| 677 |
|
| 678 |
print_game_history(out,game); |
| 679 |
|
| 680 |
if (game->clone_of && !(game->clone_of->flags & NOT_A_DRIVER)) |
| 681 |
fprintf(out, L1P "cloneof %s" L1N, game->clone_of->name); |
| 682 |
|
| 683 |
print_game_rom(out,game); |
| 684 |
print_game_sample(out,game); |
| 685 |
print_game_micro(out,game); |
| 686 |
print_game_video(out,game); |
| 687 |
print_game_sound(out,game); |
| 688 |
print_game_input(out,game); |
| 689 |
print_game_switch(out,game); |
| 690 |
print_game_driver(out,game); |
| 691 |
|
| 692 |
fprintf(out, L1E); |
| 693 |
} |
| 694 |
|
| 695 |
#if !defined(MESS) && !defined(TINY_COMPILE) && !defined(CPSMAME) && !defined(MMSND) |
| 696 |
/* Print the resource info */ |
| 697 |
static void print_resource_info(FILE* out, const struct GameDriver* game) |
| 698 |
{ |
| 699 |
#ifdef MAME_FIX // fix for MAME Merge |
| 700 |
extern struct GameDriver driver_neogeo; |
| 701 |
|
| 702 |
if (game == &driver_neogeo) |
| 703 |
fprintf(out, "resource" L1B ); |
| 704 |
else |
| 705 |
fprintf(out, "game" L1B ); |
| 706 |
#else |
| 707 |
fprintf(out, "resource" L1B ); |
| 708 |
#endif |
| 709 |
|
| 710 |
fprintf(out, L1P "name %s" L1N, game->name ); |
| 711 |
|
| 712 |
if (game->description) |
| 713 |
{ |
| 714 |
fprintf(out, L1P "description "); |
| 715 |
print_c_string(out, game->description ); |
| 716 |
fprintf(out, "%s", L1N); |
| 717 |
} |
| 718 |
|
| 719 |
/* print the year only if it's a number */ |
| 720 |
if (game->year && strspn(game->year,"0123456789")==strlen(game->year)) |
| 721 |
fprintf(out, L1P "year %s" L1N, game->year ); |
| 722 |
|
| 723 |
if (game->manufacturer) |
| 724 |
{ |
| 725 |
fprintf(out, L1P "manufacturer "); |
| 726 |
print_c_string(out, game->manufacturer ); |
| 727 |
fprintf(out, "%s", L1N); |
| 728 |
} |
| 729 |
|
| 730 |
print_game_rom(out,game); |
| 731 |
print_game_sample(out,game); |
| 732 |
|
| 733 |
fprintf(out, L1E); |
| 734 |
} |
| 735 |
|
| 736 |
/* Import the driver object and print it as a resource */ |
| 737 |
#define PRINT_RESOURCE(s) \ |
| 738 |
{ \ |
| 739 |
extern struct GameDriver driver_##s; \ |
| 740 |
print_resource_info( out, &driver_##s ); \ |
| 741 |
} |
| 742 |
|
| 743 |
#endif |
| 744 |
|
| 745 |
/* Print all the MAME info database */ |
| 746 |
void print_mame_info(FILE* out, const struct GameDriver* games[]) |
| 747 |
{ |
| 748 |
int j; |
| 749 |
|
| 750 |
/* print games */ |
| 751 |
for(j=0;games[j];++j) |
| 752 |
print_game_info( out, games[j] ); |
| 753 |
|
| 754 |
/* print the resources (only if linked) */ |
| 755 |
#if !defined(MESS) && !defined(TINY_COMPILE) && !defined(CPSMAME) && !defined(MMSND) |
| 756 |
PRINT_RESOURCE(neogeo); |
| 757 |
#if !defined(NEOMAME) |
| 758 |
PRINT_RESOURCE(cvs); |
| 759 |
PRINT_RESOURCE(decocass); |
| 760 |
PRINT_RESOURCE(playch10); |
| 761 |
PRINT_RESOURCE(pgm); |
| 762 |
#endif |
| 763 |
#endif |
| 764 |
} |