trunk/src/lib/formats/pc98fdd_dsk.c
| r0 | r242335 | |
| 1 | // license:BSD-3-Clause |
| 2 | // copyright-holders:etabeta |
| 3 | /********************************************************************* |
| 4 | |
| 5 | formats/pc98fdd_dsk.h |
| 6 | |
| 7 | PC98FDD disk images |
| 8 | |
| 9 | 0xC3FC header, followed by track data |
| 10 | Sector map starts at offset 0xDC, with 12bytes for each sector |
| 11 | |
| 12 | Each entry of the sector map has the following structure |
| 13 | - 0x0 = track number (if 0xff the sector/track is unformatted/unused) |
| 14 | - 0x1 = head number |
| 15 | - 0x2 = sector number |
| 16 | - 0x3 = sector size (128 << this byte) |
| 17 | - 0x4 = fill byte. if it's not 0xff, then this sector in the original |
| 18 | disk consisted of this single value repeated for the whole |
| 19 | sector size, and the sector is skipped in the .fdd file. |
| 20 | if it's 0xff, then this sector is wholly contained in the .fdd |
| 21 | file |
| 22 | - 0x5 = ?? |
| 23 | - 0x6 = ?? |
| 24 | - 0x7 = ?? |
| 25 | - 0x8-0x0b = absolute offset of the data for this sector, or 0xfffffff |
| 26 | if the sector was skipped in the .fdd (and it has to be |
| 27 | filled with the value at 0x4) |
| 28 | |
| 29 | TODO: |
| 30 | - Investigate remaining sector map bytes (maybe related to protections?) |
| 31 | |
| 32 | *********************************************************************/ |
| 33 | |
| 34 | #include "emu.h" |
| 35 | #include "pc98fdd_dsk.h" |
| 36 | |
| 37 | pc98fdd_format::pc98fdd_format() |
| 38 | { |
| 39 | } |
| 40 | |
| 41 | const char *pc98fdd_format::name() const |
| 42 | { |
| 43 | return "pc98_fdd"; |
| 44 | } |
| 45 | |
| 46 | const char *pc98fdd_format::description() const |
| 47 | { |
| 48 | return "PC98 FDD disk image"; |
| 49 | } |
| 50 | |
| 51 | const char *pc98fdd_format::extensions() const |
| 52 | { |
| 53 | return "fdd"; |
| 54 | } |
| 55 | |
| 56 | int pc98fdd_format::identify(io_generic *io, UINT32 form_factor) |
| 57 | { |
| 58 | UINT8 h[7]; |
| 59 | io_generic_read(io, h, 0, 7); |
| 60 | |
| 61 | if (strncmp((const char *)h, "VFD1.0", 6) == 0) |
| 62 | return 100; |
| 63 | |
| 64 | return 0; |
| 65 | } |
| 66 | |
| 67 | bool pc98fdd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 68 | { |
| 69 | UINT8 hsec[0x0c]; |
| 70 | |
| 71 | // sector map |
| 72 | UINT8 num_secs[160]; |
| 73 | UINT32 track_sizes[160]; |
| 74 | UINT8 tracks[160 * 26]; |
| 75 | UINT8 heads[160 * 26]; |
| 76 | UINT8 secs[160 * 26]; |
| 77 | UINT8 fill_vals[160 * 26]; |
| 78 | UINT32 sec_offs[160 * 26]; |
| 79 | UINT8 sec_sizes[160 * 26]; |
| 80 | |
| 81 | int pos = 0xdc; |
| 82 | |
| 83 | for (int track = 0; track < 160; track++) |
| 84 | { |
| 85 | int curr_num_sec = 0, curr_track_size = 0; |
| 86 | for (int sect = 0; sect < 26; sect++) |
| 87 | { |
| 88 | // read sector map for this sector |
| 89 | io_generic_read(io, hsec, pos, 0x0c); |
| 90 | pos += 0x0c; |
| 91 | |
| 92 | if (hsec[0] == 0xff) // unformatted/unused sector |
| 93 | continue; |
| 94 | |
| 95 | tracks[(track * 26) + sect] = hsec[0]; |
| 96 | heads[(track * 26) + sect] = hsec[1]; |
| 97 | secs[(track * 26) + sect] = hsec[2]; |
| 98 | sec_sizes[(track * 26) + sect] = hsec[3]; |
| 99 | fill_vals[(track * 26) + sect] = hsec[4]; |
| 100 | sec_offs[(track * 26) + sect] = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x08)); |
| 101 | |
| 102 | curr_track_size += (128 << hsec[3]); |
| 103 | curr_num_sec++; |
| 104 | } |
| 105 | num_secs[track] = curr_num_sec; |
| 106 | track_sizes[track] = curr_track_size; |
| 107 | } |
| 108 | |
| 109 | int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666; |
| 110 | desc_pc_sector sects[256]; |
| 111 | UINT8 sect_data[65536]; |
| 112 | int cur_sec_map = 0, sector_size; |
| 113 | |
| 114 | for (int track = 0; track < 160; track++) |
| 115 | { |
| 116 | int cur_pos = 0; |
| 117 | for (int i = 0; i < num_secs[track]; i++) |
| 118 | { |
| 119 | cur_sec_map = track * 26 + i; |
| 120 | sector_size = 128 << sec_sizes[cur_sec_map]; |
| 121 | |
| 122 | if (sec_offs[cur_sec_map] == 0xffffffff) |
| 123 | memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size); |
| 124 | else |
| 125 | io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size); |
| 126 | |
| 127 | sects[i].track = tracks[cur_sec_map]; |
| 128 | sects[i].head = heads[cur_sec_map]; |
| 129 | sects[i].sector = secs[cur_sec_map]; |
| 130 | sects[i].size = sec_sizes[cur_sec_map]; |
| 131 | sects[i].actual_size = sector_size; |
| 132 | sects[i].deleted = false; |
| 133 | sects[i].bad_crc = false; |
| 134 | sects[i].data = sect_data + cur_pos; |
| 135 | cur_pos += sector_size; |
| 136 | } |
| 137 | |
| 138 | build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26]))); |
| 139 | } |
| 140 | |
| 141 | return true; |
| 142 | } |
| 143 | |
| 144 | bool pc98fdd_format::supports_save() const |
| 145 | { |
| 146 | return false; |
| 147 | } |
| 148 | |
| 149 | const floppy_format_type FLOPPY_PC98FDD_FORMAT = &floppy_image_format_creator<pc98fdd_format>; |