trunk/src/lib/formats/g64_dsk.c
| r25352 | r25353 | |
| 196 | 196 | ***************************************************************************/ |
| 197 | 197 | |
| 198 | 198 | #define HEADER_LENGTH 0x2ac // standard length for 84 half tracks |
| 199 | #define MAX_HEADS 2 |
| 199 | 200 | #define MAX_TRACKS 84 |
| 200 | 201 | |
| 201 | 202 | /*************************************************************************** |
| r25352 | r25353 | |
| 205 | 206 | struct g64dsk_tag |
| 206 | 207 | { |
| 207 | 208 | int version; |
| 208 | | int heads; // number of physical heads |
| 209 | | int tracks; // number of physical tracks |
| 210 | | UINT16 track_size[MAX_TRACKS]; // size of each track |
| 211 | | UINT32 track_offset[MAX_TRACKS]; // offset within data for each track |
| 212 | | UINT32 speed_zone_offset[MAX_TRACKS]; // offset within data for each track |
| 209 | int heads; // number of physical heads |
| 210 | int tracks; // number of physical tracks |
| 211 | UINT16 track_size[MAX_HEADS][MAX_TRACKS]; // size of each track |
| 212 | UINT32 track_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track |
| 213 | UINT32 speed_zone_offset[MAX_HEADS][MAX_TRACKS]; // offset within data for each track |
| 213 | 214 | }; |
| 214 | 215 | |
| 215 | 216 | /*************************************************************************** |
| r25352 | r25353 | |
| 260 | 261 | struct g64dsk_tag *tag = get_tag(floppy); |
| 261 | 262 | UINT64 offs = 0; |
| 262 | 263 | |
| 263 | | if ((track < 0) || (track >= tag->tracks)) |
| 264 | if ((track < 0) || (track >= MAX_TRACKS)) |
| 264 | 265 | return FLOPPY_ERROR_SEEKERROR; |
| 265 | 266 | |
| 266 | | offs = tag->track_offset[track]; |
| 267 | offs = tag->track_offset[head][track]; |
| 267 | 268 | |
| 268 | 269 | if (offset) |
| 269 | 270 | *offset = offs; |
| r25352 | r25353 | |
| 317 | 318 | struct g64dsk_tag *tag = get_tag(floppy); |
| 318 | 319 | floperr_t err; |
| 319 | 320 | UINT64 track_offset; |
| 320 | | UINT16 track_length = tag->track_size[track]; |
| 321 | UINT16 track_length = tag->track_size[head][track]; |
| 321 | 322 | |
| 322 | 323 | // get track offset |
| 323 | 324 | err = get_track_offset(floppy, head, track, &track_offset); |
| r25352 | r25353 | |
| 325 | 326 | if (err) |
| 326 | 327 | return err; |
| 327 | 328 | |
| 328 | | if (!head && track_offset) |
| 329 | if ((head <= tag->heads) && track_offset) |
| 329 | 330 | { |
| 330 | 331 | if (buflen < track_length) { printf("G64 track buffer too small: %u < %u!", (UINT32)buflen, track_length); exit(-1); } |
| 331 | 332 | |
| 332 | 333 | // read track data |
| 333 | 334 | floppy_image_read(floppy, ((UINT8*)buffer), track_offset + 2, track_length); // skip the 2 track length bytes in the beginning of track data |
| 334 | 335 | |
| 335 | | if (tag->speed_zone_offset[track] > 3) |
| 336 | if (tag->speed_zone_offset[head][track] > 3) |
| 336 | 337 | { |
| 337 | 338 | // read speed block |
| 338 | | floppy_image_read(floppy, ((UINT8*)buffer) + track_length, tag->speed_zone_offset[track], G64_SPEED_BLOCK_SIZE); |
| 339 | floppy_image_read(floppy, ((UINT8*)buffer) + track_length, tag->speed_zone_offset[head][track], G64_SPEED_BLOCK_SIZE); |
| 339 | 340 | } |
| 340 | 341 | else |
| 341 | 342 | { |
| 342 | 343 | // create a speed block with the same speed zone for the whole track |
| 343 | | UINT8 speed = tag->speed_zone_offset[track] & 0x03; |
| 344 | UINT8 speed = tag->speed_zone_offset[head][track] & 0x03; |
| 344 | 345 | UINT8 speed_byte = (speed << 6) | (speed << 4) | (speed << 2) | speed; |
| 345 | 346 | |
| 346 | 347 | memset(((UINT8*)buffer) + track_length, speed_byte, G64_SPEED_BLOCK_SIZE); |
| 347 | 348 | } |
| 349 | |
| 350 | LOG_FORMATS("G64 side %u track %.1f length %u\n", head, get_dos_track(track), track_length); |
| 348 | 351 | } |
| 349 | 352 | else |
| 350 | 353 | { |
| 351 | 354 | // no data for given track, or tried to read side 1 |
| 352 | 355 | memset(((UINT8*)buffer), 0, buflen); |
| 356 | |
| 357 | LOG_FORMATS("G64 side %u track %.1f\n", head, get_dos_track(track)); |
| 353 | 358 | } |
| 354 | 359 | |
| 355 | | LOG_FORMATS("G64 track %.1f length %u\n", get_dos_track(track), track_length); |
| 356 | | |
| 357 | 360 | return FLOPPY_ERROR_SUCCESS; |
| 358 | 361 | } |
| 359 | 362 | |
| r25352 | r25353 | |
| 424 | 427 | |
| 425 | 428 | */ |
| 426 | 429 | |
| 427 | | FLOPPY_CONSTRUCT( g64_dsk_construct ) |
| 430 | static void read_g64_header(floppy_image_legacy *floppy, struct g64dsk_tag *tag, int head, UINT64 &pos) |
| 428 | 431 | { |
| 429 | | struct FloppyCallbacks *callbacks; |
| 430 | | struct g64dsk_tag *tag; |
| 431 | 432 | UINT8 header[HEADER_LENGTH]; |
| 432 | | UINT64 pos = 0xc; |
| 433 | | int i; |
| 434 | 433 | |
| 435 | | if (params) |
| 436 | | { |
| 437 | | // create not supported |
| 438 | | return FLOPPY_ERROR_UNSUPPORTED; |
| 439 | | } |
| 434 | UINT64 start_pos = pos; |
| 440 | 435 | |
| 441 | | tag = (struct g64dsk_tag *) floppy_create_tag(floppy, sizeof(struct g64dsk_tag)); |
| 442 | | |
| 443 | | if (!tag) return FLOPPY_ERROR_OUTOFMEMORY; |
| 444 | | |
| 445 | 436 | // read header |
| 446 | | floppy_image_read(floppy, header, 0, HEADER_LENGTH); |
| 437 | floppy_image_read(floppy, header, pos, HEADER_LENGTH); |
| 447 | 438 | |
| 448 | 439 | // get version |
| 449 | 440 | tag->version = header[8]; |
| 450 | | LOG_FORMATS("G64 version: %u\n", tag->version); |
| 441 | if (!head) LOG_FORMATS("G64 version: %u\n", tag->version); |
| 451 | 442 | |
| 452 | 443 | // get number of tracks |
| 453 | | tag->heads = 1; |
| 454 | 444 | tag->tracks = header[9]; |
| 455 | | LOG_FORMATS("G64 tracks: %u\n", tag->tracks); |
| 445 | LOG_FORMATS("G64 side %u tracks: %u\n", head, tag->tracks); |
| 456 | 446 | |
| 447 | // get track size |
| 448 | UINT16 track_size = (header[0xb] << 8) | header[0xa]; |
| 449 | |
| 457 | 450 | // get data offsets |
| 458 | | for (i = 0; i < tag->tracks; i++) |
| 451 | pos = 0xc; |
| 452 | for (int i = 0; i < tag->tracks; i++) |
| 459 | 453 | { |
| 460 | | tag->track_offset[i] = pick_integer_le(header, pos, 4); |
| 454 | tag->track_offset[head][i] = pick_integer_le(header, pos, 4); |
| 455 | |
| 456 | if (tag->track_offset[head][i]) |
| 457 | { |
| 458 | tag->track_offset[head][i] += start_pos; |
| 459 | } |
| 460 | |
| 461 | 461 | pos += 4; |
| 462 | 462 | } |
| 463 | 463 | |
| 464 | 464 | // get speed zone information |
| 465 | | for (i = 0; i < tag->tracks; i++) |
| 465 | UINT32 track_offs = 0; |
| 466 | for (int i = 0; i < tag->tracks; i++) |
| 466 | 467 | { |
| 467 | | tag->speed_zone_offset[i] = pick_integer_le(header, pos, 4); |
| 468 | tag->speed_zone_offset[head][i] = pick_integer_le(header, pos, 4); |
| 469 | |
| 470 | if (tag->speed_zone_offset[head][i] >= 4) |
| 471 | { |
| 472 | tag->speed_zone_offset[head][i] += start_pos; |
| 473 | } |
| 474 | |
| 468 | 475 | pos += 4; |
| 469 | 476 | |
| 470 | | tag->track_size[i] = g64_get_track_size(floppy, 0, i); |
| 477 | tag->track_size[head][i] = g64_get_track_size(floppy, head, i); |
| 471 | 478 | |
| 472 | | if (tag->track_offset[i] > 0) |
| 479 | if (tag->track_offset[head][i] != 0) |
| 473 | 480 | { |
| 474 | | LOG_FORMATS("G64 track %.1f offset %05x length %04x ", get_dos_track(i), tag->track_offset[i], tag->track_size[i]); |
| 481 | LOG_FORMATS("G64 side %u track %.1f offset %05x length %04x ", head, get_dos_track(i), tag->track_offset[head][i], tag->track_size[head][i]); |
| 475 | 482 | |
| 476 | | if (tag->speed_zone_offset[i] < 4) { |
| 477 | | LOG_FORMATS("speed %u\n", tag->speed_zone_offset[i]); |
| 483 | track_offs = tag->track_offset[head][i]; |
| 484 | |
| 485 | if (tag->speed_zone_offset[head][i] < 4) { |
| 486 | LOG_FORMATS("speed %u\n", tag->speed_zone_offset[head][i]); |
| 478 | 487 | } else { |
| 479 | | LOG_FORMATS("speed offset %04x\n", tag->speed_zone_offset[i]); |
| 488 | LOG_FORMATS("speed offset %04x\n", tag->speed_zone_offset[head][i]); |
| 480 | 489 | } |
| 481 | 490 | } |
| 482 | 491 | } |
| 483 | 492 | |
| 493 | pos = track_offs + 2 + track_size; |
| 494 | } |
| 495 | |
| 496 | FLOPPY_CONSTRUCT( g64_dsk_construct ) |
| 497 | { |
| 498 | struct FloppyCallbacks *callbacks; |
| 499 | struct g64dsk_tag *tag; |
| 500 | UINT64 pos = 0; |
| 501 | |
| 502 | if (params) |
| 503 | { |
| 504 | // create not supported |
| 505 | return FLOPPY_ERROR_UNSUPPORTED; |
| 506 | } |
| 507 | |
| 508 | tag = (struct g64dsk_tag *) floppy_create_tag(floppy, sizeof(struct g64dsk_tag)); |
| 509 | |
| 510 | if (!tag) return FLOPPY_ERROR_OUTOFMEMORY; |
| 511 | |
| 512 | tag->heads = 0; |
| 513 | int head = 0; |
| 514 | |
| 515 | read_g64_header(floppy, tag, head, pos); |
| 516 | |
| 517 | if (floppy_image_size(floppy) > pos) |
| 518 | { |
| 519 | tag->heads++; |
| 520 | head++; |
| 521 | |
| 522 | read_g64_header(floppy, tag, head, pos); |
| 523 | } |
| 524 | |
| 484 | 525 | // set callbacks |
| 485 | 526 | callbacks = floppy_callbacks(floppy); |
| 486 | 527 | |