trunk/src/lib/formats/imd_dsk.c
| r18975 | r18976 | |
| 273 | 273 | return FLOPPY_ERROR_SUCCESS; |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | |
| 277 | /*************************************************************************** |
| 278 | |
| 279 | Copyright Olivier Galibert |
| 280 | All rights reserved. |
| 281 | |
| 282 | Redistribution and use in source and binary forms, with or without |
| 283 | modification, are permitted provided that the following conditions are |
| 284 | met: |
| 285 | |
| 286 | * Redistributions of source code must retain the above copyright |
| 287 | notice, this list of conditions and the following disclaimer. |
| 288 | * Redistributions in binary form must reproduce the above copyright |
| 289 | notice, this list of conditions and the following disclaimer in |
| 290 | the documentation and/or other materials provided with the |
| 291 | distribution. |
| 292 | * Neither the name 'MAME' nor the names of its contributors may be |
| 293 | used to endorse or promote products derived from this software |
| 294 | without specific prior written permission. |
| 295 | |
| 296 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR |
| 297 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 298 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 299 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, |
| 300 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 301 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 302 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 303 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 304 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| 305 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 306 | POSSIBILITY OF SUCH DAMAGE. |
| 307 | |
| 308 | ****************************************************************************/ |
| 309 | |
| 310 | /********************************************************************* |
| 311 | |
| 312 | formats/imd_dsk.h |
| 313 | |
| 314 | IMD disk images |
| 315 | |
| 316 | *********************************************************************/ |
| 317 | |
| 318 | #include "emu.h" |
| 319 | #include "imd_dsk.h" |
| 320 | |
| 321 | imd_format::imd_format() |
| 322 | { |
| 323 | } |
| 324 | |
| 325 | const char *imd_format::name() const |
| 326 | { |
| 327 | return "imd"; |
| 328 | } |
| 329 | |
| 330 | const char *imd_format::description() const |
| 331 | { |
| 332 | return "IMD disk image"; |
| 333 | } |
| 334 | |
| 335 | const char *imd_format::extensions() const |
| 336 | { |
| 337 | return "imd"; |
| 338 | } |
| 339 | |
| 340 | void imd_format::fixnum(char *start, char *end) const |
| 341 | { |
| 342 | end--; |
| 343 | if(*end != '0') |
| 344 | return; |
| 345 | while(end > start) { |
| 346 | end--; |
| 347 | if(*end == ' ') |
| 348 | *end = '0'; |
| 349 | else if(*end != '0') |
| 350 | return; |
| 351 | }; |
| 352 | } |
| 353 | |
| 354 | int imd_format::identify(io_generic *io, UINT32 form_factor) |
| 355 | { |
| 356 | char h[32]; |
| 357 | |
| 358 | io_generic_read(io, h, 0, 31); |
| 359 | h[31] = 0; |
| 360 | for(int i=0; i != 31; i++) |
| 361 | if(h[i] >= '0' && h[i] <= '9')\ |
| 362 | h[i] = '0'; |
| 363 | |
| 364 | fixnum(h+10, h+12); |
| 365 | fixnum(h+13, h+15); |
| 366 | fixnum(h+16, h+20); |
| 367 | fixnum(h+21, h+23); |
| 368 | fixnum(h+24, h+26); |
| 369 | fixnum(h+27, h+29); |
| 370 | |
| 371 | if(!strcmp(h, "IMD 0.00: 00/00/0000 00:00:00\015\012")) |
| 372 | return 100; |
| 373 | |
| 374 | return 0; |
| 375 | } |
| 376 | |
| 377 | // 1.1.1.1.1.1.0.0 - fc |
| 378 | // 1.1.0.1.0.1.1.1 |
| 379 | // f77a |
| 380 | |
| 381 | // 1.1.1.1.1.1.1.0 - fe |
| 382 | // 1.1.0.0.0.1.1.1 |
| 383 | // f57e |
| 384 | |
| 385 | // 1.1.1.1.1.0.1.1 - fb |
| 386 | // 1.1.0.0.0.1.1.1 |
| 387 | // f56f |
| 388 | |
| 389 | // 1.1.1.1.1.0.0.0 - f8 |
| 390 | // 1.1.0.0.0.1.1.1 |
| 391 | // f56a |
| 392 | |
| 393 | bool imd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 394 | { |
| 395 | int size = io_generic_size(io); |
| 396 | UINT8 *img = global_alloc_array(UINT8, size); |
| 397 | io_generic_read(io, img, 0, size); |
| 398 | |
| 399 | int pos; |
| 400 | for(pos=0; pos < size && img[pos] != 0x1a; pos++); |
| 401 | pos++; |
| 402 | |
| 403 | if(pos >= size) |
| 404 | return false; |
| 405 | |
| 406 | while(pos < size) { |
| 407 | UINT8 mode = img[pos++]; |
| 408 | UINT8 track = img[pos++]; |
| 409 | UINT8 head = img[pos++]; |
| 410 | UINT8 sector_count = img[pos++]; |
| 411 | UINT8 ssize = img[pos++]; |
| 412 | |
| 413 | if(ssize == 0xff) |
| 414 | throw emu_fatalerror("imd_format: Unsupported variable sector size on track %d head %d", track, head); |
| 415 | |
| 416 | UINT32 size = ssize < 7 ? 128 << ssize : 8192; |
| 417 | |
| 418 | static const int rates[3] = { 500000, 300000, 250000 }; |
| 419 | bool fm = mode < 3; |
| 420 | int rate = rates[mode % 3]; |
| 421 | int rpm = form_factor == floppy_image::FF_8 || (floppy_image::FF_525 && rate >= 300) ? 360 : 300; |
| 422 | int cell_count = (fm ? 1 : 2)*rate*60/rpm; |
| 423 | |
| 424 | const UINT8 *snum = img+pos; |
| 425 | pos += sector_count; |
| 426 | const UINT8 *tnum = head & 0x80 ? img+pos : NULL; |
| 427 | if(tnum) |
| 428 | pos += sector_count; |
| 429 | const UINT8 *hnum = head & 0x40 ? img+pos : NULL; |
| 430 | if(hnum) |
| 431 | pos += sector_count; |
| 432 | |
| 433 | head &= 0x3f; |
| 434 | |
| 435 | UINT32 *track_data = global_alloc_array(UINT32, cell_count+10000); |
| 436 | int tpos = 0; |
| 437 | |
| 438 | // gap 4a , IAM and gap 1 |
| 439 | if(fm) { |
| 440 | for(int i=0; i<40; i++) fm_w(track_data, tpos, 8, 0xff); |
| 441 | for(int i=0; i< 6; i++) fm_w(track_data, tpos, 8, 0x00); |
| 442 | raw_w(track_data, tpos, 16, 0xf77a); |
| 443 | for(int i=0; i<26; i++) fm_w(track_data, tpos, 8, 0xff); |
| 444 | } else { |
| 445 | for(int i=0; i<80; i++) mfm_w(track_data, tpos, 8, 0x4e); |
| 446 | for(int i=0; i<12; i++) mfm_w(track_data, tpos, 8, 0x00); |
| 447 | for(int i=0; i< 3; i++) raw_w(track_data, tpos, 16, 0x5224); |
| 448 | mfm_w(track_data, tpos, 8, 0xfc); |
| 449 | for(int i=0; i<50; i++) mfm_w(track_data, tpos, 8, 0x4e); |
| 450 | } |
| 451 | |
| 452 | // Compute the available and expected size for gap3 |
| 453 | int gap3 = form_factor == floppy_image::FF_8 ? 25 : |
| 454 | ssize < 512 ? |
| 455 | (form_factor == floppy_image::FF_35 ? 54 : 50) : |
| 456 | (form_factor == floppy_image::FF_35 ? 84 : 80); |
| 457 | |
| 458 | int etpos = tpos; |
| 459 | if(fm) |
| 460 | etpos += sector_count*(6+5+2+11+6+1+ssize+2)*16; |
| 461 | else |
| 462 | etpos += sector_count*(12+3+5+2+22+12+3+1+ssize+2)*16; |
| 463 | |
| 464 | if(etpos > cell_count) |
| 465 | throw emu_fatalerror("imd_format: Incorrect layout on track %d head %d, expected_size=%d, current_size=%d", track, head, cell_count, etpos); |
| 466 | |
| 467 | if(etpos + gap3*16*(sector_count-1) > cell_count) |
| 468 | gap3 = (cell_count - etpos) / 16 / (sector_count-1); |
| 469 | |
| 470 | // Build the track |
| 471 | if(fm) { |
| 472 | for(int i=0; i<sector_count; i++) { |
| 473 | UINT8 stype = img[pos++]; |
| 474 | |
| 475 | int cpos; |
| 476 | UINT16 crc; |
| 477 | // sync and IDAM and gap 2 |
| 478 | for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0xff); |
| 479 | cpos = tpos; |
| 480 | raw_w(track_data, tpos, 8, 0xf57e); |
| 481 | fm_w (track_data, tpos, 8, tnum ? tnum[i] : track); |
| 482 | fm_w (track_data, tpos, 8, hnum ? hnum[i] : head); |
| 483 | fm_w (track_data, tpos, 8, snum[i]); |
| 484 | fm_w (track_data, tpos, 8, ssize); |
| 485 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 486 | fm_w (track_data, tpos, 16, crc); |
| 487 | for(int j=0; j<11; j++) fm_w(track_data, tpos, 8, 0xff); |
| 488 | |
| 489 | if(stype == 0 || stype > 8) |
| 490 | for(int j=0; j<6+1+size+2+gap3; j++) fm_w(track_data, tpos, 8, 0xff); |
| 491 | |
| 492 | else { |
| 493 | // sync, DAM, data and gap 3 |
| 494 | for(int j=0; j< 6; j++) fm_w(track_data, tpos, 8, 0xff); |
| 495 | cpos = tpos; |
| 496 | raw_w(track_data, tpos, 8, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf56a : 0xf56f); |
| 497 | if(stype == 2 || stype == 4 || stype == 6 || stype == 8) { |
| 498 | for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos]); |
| 499 | pos++; |
| 500 | } else |
| 501 | for(int j=0; j<size; j++) fm_w(track_data, tpos, 8, img[pos++]); |
| 502 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 503 | if(stype == 5 || stype == 6 || stype == 7 || stype == 8) |
| 504 | crc = 0xffff^crc; |
| 505 | fm_w(track_data, tpos, 16, crc); |
| 506 | for(int j=0; j<gap3; j++) fm_w(track_data, tpos, 8, 0xff); |
| 507 | } |
| 508 | } |
| 509 | |
| 510 | // Gap 4b |
| 511 | |
| 512 | while(tpos < cell_count-15) fm_w(track_data, tpos, 8, 0xff); |
| 513 | raw_w(track_data, tpos, cell_count-tpos, 0xffff >> (16+tpos-cell_count)); |
| 514 | |
| 515 | } else { |
| 516 | for(int i=0; i<sector_count; i++) { |
| 517 | UINT8 stype = img[pos++]; |
| 518 | |
| 519 | int cpos; |
| 520 | UINT16 crc; |
| 521 | // sync and IDAM and gap 2 |
| 522 | for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); |
| 523 | cpos = tpos; |
| 524 | for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); |
| 525 | mfm_w(track_data, tpos, 8, 0xfe); |
| 526 | mfm_w(track_data, tpos, 8, tnum ? tnum[i] : track); |
| 527 | mfm_w(track_data, tpos, 8, hnum ? hnum[i] : head); |
| 528 | mfm_w(track_data, tpos, 8, snum[i]); |
| 529 | mfm_w(track_data, tpos, 8, ssize); |
| 530 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 531 | mfm_w(track_data, tpos, 16, crc); |
| 532 | for(int j=0; j<22; j++) mfm_w(track_data, tpos, 8, 0x4e); |
| 533 | |
| 534 | if(stype == 0 || stype > 8) |
| 535 | for(int j=0; j<12+4+size+2+gap3; j++) mfm_w(track_data, tpos, 8, 0x4e); |
| 536 | |
| 537 | else { |
| 538 | // sync, DAM, data and gap 3 |
| 539 | for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); |
| 540 | cpos = tpos; |
| 541 | for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); |
| 542 | mfm_w(track_data, tpos, 8, stype == 3 || stype == 4 || stype == 7 || stype == 8 ? 0xf8 : 0xfb); |
| 543 | if(stype == 2 || stype == 4 || stype == 6 || stype == 8) { |
| 544 | for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos]); |
| 545 | pos++; |
| 546 | } else |
| 547 | for(int j=0; j<size; j++) mfm_w(track_data, tpos, 8, img[pos++]); |
| 548 | if(stype == 5 || stype == 6 || stype == 7 || stype == 8) |
| 549 | crc = 0xffff^crc; |
| 550 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 551 | mfm_w(track_data, tpos, 16, crc); |
| 552 | for(int j=0; j<gap3; j++) mfm_w(track_data, tpos, 8, 0x4e); |
| 553 | } |
| 554 | } |
| 555 | |
| 556 | // Gap 4b |
| 557 | |
| 558 | while(tpos < cell_count-15) mfm_w(track_data, tpos, 8, 0x4e); |
| 559 | raw_w(track_data, tpos, cell_count-tpos, 0x9254 >> (16+tpos-cell_count)); |
| 560 | } |
| 561 | |
| 562 | generate_track_from_levels(track, head, track_data, cell_count, 0, image); |
| 563 | global_free(track_data); |
| 564 | } |
| 565 | |
| 566 | global_free(img); |
| 567 | return true; |
| 568 | } |
| 569 | |
| 570 | |
| 571 | bool imd_format::supports_save() const |
| 572 | { |
| 573 | return false; |
| 574 | } |
| 575 | |
| 576 | const floppy_format_type FLOPPY_IMD_FORMAT = &floppy_image_format_creator<imd_format>; |