trunk/hash/spectrum_cass.xml
| r18720 | r18721 | |
| 19 | 19 | The MESS emulation at the time of writing isn't very good, the following emulators are used to determine how things should work |
| 20 | 20 | |
| 21 | 21 | Fuse (Free Unix Spectrum Emulator) - Free, High Compatibility can run some of the trickier images, Windows port available - http://fuse-emulator.sourceforge.net/ |
| 22 | | Spectaculator - Commercial, a bit more user friendly than above, similar compatibility - http://www.spectaculator.com/ |
| 22 | Spectaculator - Commercial, a bit more user friendly than above, similar compatibility - http://www.spectaculator.com/ |
| 23 | 23 | |
| 24 | 24 | Note, even with those emulators you'll have to turn off some of the speed cheats on loading to get good compatibilty for example, in Fuse |
| 25 | 25 | Use Tape Traps |
| r18720 | r18721 | |
| 30 | 30 | MESS doesn't have any accelerated loading so some games which require the tricks to be disabled in other emulators work in MESS without trickery, eg Xanthius |
| 31 | 31 | |
| 32 | 32 | http://newton.sunderland.ac.uk/~specfreak/Schemes/schemes.html is a rather outdated guide mentioning some of the custom loaders, and showing disassemblies of them. |
| 33 | |
| 34 | legacy emulators including Real Spectrum ( http://zxm.speccy.cz/realspec/ ) appear to struggle with some of the more complex tape protections |
| 35 | |
| 36 | |
| 37 | ToDo: Find an emulator which works with the 'Gremlin 2' protected tapes 'M.A.S.K' and 'Basil The Great Mouse Detective' all TZX images I've found fail in the |
| 38 | above emulators, although RealSpectrum does load some copies of MASK but fails loading the 2nd part of the game. |
| 33 | 39 | |
| 34 | 40 | |
| 35 | | legacy emulators including Real Spectrum ( http://zxm.speccy.cz/realspec/ ) appear to struggle with some of the more complex tape protections |
| 36 | 41 | |
| 37 | 42 | --> |
| 38 | 43 | |
| r18720 | r18721 | |
| 344 | 349 | </part> |
| 345 | 350 | </software> |
| 346 | 351 | |
| 347 | | <!-- loader fails before title screen, works in other emus --> |
| 348 | | <software name="batmana" cloneof="batman" supported="no"> |
| 352 | <!-- OK --> |
| 353 | <software name="batmana" cloneof="batman" > |
| 349 | 354 | <description>Batman (set 2)</description> |
| 350 | 355 | <year>1986</year> |
| 351 | 356 | <publisher>Ocean</publisher> |
| r18720 | r18721 | |
| 356 | 361 | </part> |
| 357 | 362 | </software> |
| 358 | 363 | |
| 359 | | <!-- loader fails, doesn't boot after countdown completes, works in other emus --> |
| 360 | | <software name="batmanb" cloneof="batman" supported="no"> |
| 364 | <!-- OK --> |
| 365 | <!-- has load timer --> |
| 366 | <software name="batmanb" cloneof="batman" > |
| 361 | 367 | <description>Batman (set 3)</description> |
| 362 | 368 | <year>1986</year> |
| 363 | 369 | <publisher>Ocean</publisher> |
| r18720 | r18721 | |
| 368 | 374 | </part> |
| 369 | 375 | </software> |
| 370 | 376 | |
| 371 | | <!-- loader fails after first block is loaded, suspect image, doesn't even run in 'realspectrum' --> |
| 377 | <!-- Unsupported block type (0x19 - Generalized Data Block) encountered --> |
| 372 | 378 | <software name="batmanc" cloneof="batman" supported ="no"> |
| 373 | 379 | <description>Batman (set 4)</description> |
| 374 | 380 | <year>1986</year> |
| r18720 | r18721 | |
| 381 | 387 | </software> |
| 382 | 388 | |
| 383 | 389 | <!-- OK --> |
| 390 | <!-- colourful loader --> |
| 384 | 391 | <software name="batmand" cloneof="batman"> |
| 385 | 392 | <description>Batman (set 5)</description> |
| 386 | 393 | <year>1986</year> |
| r18720 | r18721 | |
| 392 | 399 | </part> |
| 393 | 400 | </software> |
| 394 | 401 | |
| 395 | | <!-- loader fails after first block is loaded, works in other emus --> |
| 396 | | <software name="batmane" cloneof="batman" supported="no"> |
| 402 | <!-- OK --> |
| 403 | <software name="batmane" cloneof="batman"> |
| 397 | 404 | <description>Batman (set 6)</description> |
| 398 | 405 | <year>1986</year> |
| 399 | 406 | <publisher>Ocean</publisher> |
| r18720 | r18721 | |
| 404 | 411 | </part> |
| 405 | 412 | </software> |
| 406 | 413 | |
| 407 | | <!-- loader fails before title screen --> |
| 408 | | <software name="batmanf" cloneof="batman" supported="no"> |
| 414 | <!-- OK --> |
| 415 | <software name="batmanf" cloneof="batman"> |
| 409 | 416 | <description>Batman (set 7)</description> |
| 410 | 417 | <year>1986</year> |
| 411 | 418 | <publisher>Ocean</publisher> |
| r18720 | r18721 | |
| 416 | 423 | </part> |
| 417 | 424 | </software> |
| 418 | 425 | |
| 419 | | <!-- MESS doesn't see full length of tape?, suspect image--> |
| 420 | | <software name="batmang" cloneof="batman"> |
| 426 | <!-- Unsupported block type (0x19 - Generalized Data Block) encountered --> |
| 427 | <software name="batmang" cloneof="batman" supported="no"> |
| 421 | 428 | <description>Batman (set 8)</description> |
| 422 | 429 | <year>1986</year> |
| 423 | 430 | <publisher>Ocean</publisher> |
trunk/src/lib/formats/tzx_cas.c
| r18720 | r18721 | |
| 80 | 80 | { |
| 81 | 81 | int pos = sizeof(TZX_HEADER) + 2; |
| 82 | 82 | int max_block_count = INITIAL_MAX_BLOCK_COUNT; |
| 83 | | |
| 83 | int loopcount = 0, loopoffset = 0; |
| 84 | 84 | blocks = (UINT8**)malloc(max_block_count * sizeof(UINT8*)); |
| 85 | 85 | memset(blocks,0,max_block_count); |
| 86 | 86 | block_count = 0; |
| r18720 | r18721 | |
| 134 | 134 | datasize = casdata[pos] + (casdata[pos + 1] << 8) + (casdata[pos + 2] << 16); |
| 135 | 135 | pos += 3 + datasize; |
| 136 | 136 | break; |
| 137 | | case 0x20: case 0x23: case 0x24: |
| 137 | case 0x20: case 0x23: |
| 138 | 138 | pos += 2; |
| 139 | 139 | break; |
| 140 | |
| 141 | case 0x24: |
| 142 | loopcount = casdata[pos] + (casdata[pos + 1] << 8); |
| 143 | pos +=2; |
| 144 | loopoffset = pos; |
| 145 | break; |
| 146 | |
| 140 | 147 | case 0x21: case 0x30: |
| 141 | 148 | datasize = casdata[pos]; |
| 142 | 149 | pos += 1 + datasize; |
| 143 | 150 | break; |
| 144 | | case 0x22: case 0x25: case 0x27: |
| 151 | case 0x22: case 0x27: |
| 145 | 152 | break; |
| 153 | |
| 154 | case 0x25: |
| 155 | if (loopcount>0) |
| 156 | { |
| 157 | pos = loopoffset; |
| 158 | loopcount--; |
| 159 | } |
| 160 | break; |
| 161 | |
| 146 | 162 | case 0x26: |
| 147 | 163 | datasize = casdata[pos] + (casdata[pos + 1] << 8); |
| 148 | 164 | pos += 2 + 2 * datasize; |
| r18720 | r18721 | |
| 313 | 329 | |
| 314 | 330 | wave_data = WAVE_LOW; |
| 315 | 331 | |
| 332 | int loopcount = 0, loopoffset = 0; |
| 333 | |
| 316 | 334 | while (current_block < block_count) |
| 317 | 335 | { |
| 318 | 336 | int pause_time; |
| r18720 | r18721 | |
| 322 | 340 | UINT8 *cur_block = blocks[current_block]; |
| 323 | 341 | UINT8 block_type = cur_block[0]; |
| 324 | 342 | |
| 343 | |
| 325 | 344 | /* Uncomment this to include into error.log a list of the types each block */ |
| 326 | | // LOG_FORMATS("tzx_cas_fill_wave: block %d, block_type %02x\n", current_block, block_type); |
| 345 | LOG_FORMATS("tzx_cas_fill_wave: block %d, block_type %02x\n", current_block, block_type); |
| 327 | 346 | |
| 328 | 347 | switch (block_type) |
| 329 | 348 | { |
| r18720 | r18721 | |
| 460 | 479 | LOG_FORMATS("Please use a .tzx handling utility to split the merged tape files.\n"); |
| 461 | 480 | current_block++; |
| 462 | 481 | break; |
| 463 | | case 0x15: /* Direct Recording */ |
| 464 | | case 0x18: /* CSW Recording */ |
| 465 | | case 0x19: /* Generalized Data Block */ |
| 482 | case 0x24: /* Loop Start */ |
| 483 | loopcount = cur_block[1] + (cur_block[2] << 8); |
| 484 | current_block++; |
| 485 | loopoffset = current_block; |
| 486 | |
| 487 | LOG_FORMATS("loop start %d %d\n", loopcount, current_block); |
| 488 | break; |
| 489 | case 0x25: /* Loop End */ |
| 490 | if (loopcount>0) |
| 491 | { |
| 492 | current_block = loopoffset; |
| 493 | loopcount--; |
| 494 | LOG_FORMATS("do loop\n"); |
| 495 | } |
| 496 | else |
| 497 | { |
| 498 | current_block++; |
| 499 | } |
| 500 | break; |
| 501 | |
| 466 | 502 | case 0x21: /* Group Start */ |
| 467 | 503 | case 0x22: /* Group End */ |
| 468 | 504 | case 0x23: /* Jump To Block */ |
| 469 | | case 0x24: /* Loop Start */ |
| 470 | | case 0x25: /* Loop End */ |
| 471 | 505 | case 0x26: /* Call Sequence */ |
| 472 | 506 | case 0x27: /* Return From Sequence */ |
| 473 | 507 | case 0x28: /* Select Block */ |
| r18720 | r18721 | |
| 477 | 511 | LOG_FORMATS("Unsupported block type (%02x) encountered.\n", block_type); |
| 478 | 512 | current_block++; |
| 479 | 513 | break; |
| 514 | |
| 515 | case 0x15: /* Direct Recording */ |
| 516 | // having this missing is fatal |
| 517 | printf("Unsupported block type (0x15 - Direct Recording) encountered.\n"); |
| 518 | current_block++; |
| 519 | break; |
| 520 | |
| 521 | case 0x18: /* CSW Recording */ |
| 522 | // having this missing is fatal |
| 523 | printf("Unsupported block type (0x15 - CSW Recording) encountered.\n"); |
| 524 | current_block++; |
| 525 | break; |
| 526 | |
| 527 | case 0x19: /* Generalized Data Block */ |
| 528 | // having this missing is fatal |
| 529 | printf("Unsupported block type (0x19 - Generalized Data Block) encountered.\n"); |
| 530 | current_block++; |
| 531 | break; |
| 532 | |
| 480 | 533 | } |
| 481 | 534 | } |
| 482 | 535 | return size; |