trunk/src/lib/formats/flopimg.c
| r20262 | r20263 | |
| 1104 | 1104 | return type == CRC_CCITT_START || |
| 1105 | 1105 | type == CRC_CCITT_FM_START || |
| 1106 | 1106 | type == CRC_AMIGA_START || |
| 1107 | type == CRC_CBM_START || |
| 1107 | 1108 | type == CRC_MACHEAD_START || |
| 1108 | 1109 | type == CRC_END || |
| 1109 | 1110 | type == SECTOR_LOOP_START || |
| r20262 | r20263 | |
| 1136 | 1137 | case CRC_AMIGA_START: |
| 1137 | 1138 | crcs[desc[i].p1].type = CRC_AMIGA; |
| 1138 | 1139 | break; |
| 1140 | case CRC_CBM_START: |
| 1141 | crcs[desc[i].p1].type = CRC_CBM; |
| 1142 | break; |
| 1139 | 1143 | case CRC_MACHEAD_START: |
| 1140 | 1144 | crcs[desc[i].p1].type = CRC_MACHEAD; |
| 1141 | 1145 | break; |
| r20262 | r20263 | |
| 1155 | 1159 | case CRC_CCITT: return 32; |
| 1156 | 1160 | case CRC_CCITT_FM: return 32; |
| 1157 | 1161 | case CRC_AMIGA: return 64; |
| 1162 | case CRC_CBM: return 10; |
| 1158 | 1163 | case CRC_MACHEAD: return 8; |
| 1159 | 1164 | default: return 0; |
| 1160 | 1165 | } |
| r20262 | r20263 | |
| 1215 | 1220 | } |
| 1216 | 1221 | } |
| 1217 | 1222 | |
| 1223 | void floppy_image_format_t::gcr5_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size) |
| 1224 | { |
| 1225 | UINT32 e0 = gcr5fw_tb[val >> 4]; |
| 1226 | UINT32 e1 = gcr5fw_tb[val & 0x0f]; |
| 1227 | raw_w(buffer, offset, 5, e0, size); |
| 1228 | raw_w(buffer, offset, 5, e1, size); |
| 1229 | } |
| 1230 | |
| 1218 | 1231 | void floppy_image_format_t::fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc) |
| 1219 | 1232 | { |
| 1220 | 1233 | UINT16 res = 0; |
| r20262 | r20263 | |
| 1227 | 1240 | mfm_w(buffer, offset, 16, res); |
| 1228 | 1241 | } |
| 1229 | 1242 | |
| 1243 | void floppy_image_format_t::fixup_crc_cbm(UINT32 *buffer, const gen_crc_info *crc) |
| 1244 | { |
| 1245 | UINT8 v = 0; |
| 1246 | for(int o = crc->start; o < crc->end; o+=10) { |
| 1247 | v = v ^ (gcr5bw_tb[bitn_r(buffer, o, 5)] << 4); |
| 1248 | v = v ^ gcr5bw_tb[bitn_r(buffer, o+5, 5)]; |
| 1249 | } |
| 1250 | int offset = crc->write; |
| 1251 | gcr5_w(buffer, offset, 8, v); |
| 1252 | } |
| 1253 | |
| 1230 | 1254 | UINT16 floppy_image_format_t::calc_crc_ccitt(const UINT32 *buffer, int start, int end) |
| 1231 | 1255 | { |
| 1232 | 1256 | UINT32 res = 0xffff; |
| r20262 | r20263 | |
| 1268 | 1292 | if(crcs[i].write != -1) { |
| 1269 | 1293 | switch(crcs[i].type) { |
| 1270 | 1294 | case CRC_AMIGA: fixup_crc_amiga(buffer, crcs+i); break; |
| 1295 | case CRC_CBM: fixup_crc_cbm(buffer, crcs+i); break; |
| 1271 | 1296 | case CRC_CCITT: fixup_crc_ccitt(buffer, crcs+i); break; |
| 1272 | 1297 | case CRC_CCITT_FM:fixup_crc_ccitt_fm(buffer, crcs+i); break; |
| 1273 | 1298 | case CRC_MACHEAD: fixup_crc_machead(buffer, crcs+i); break; |
| r20262 | r20263 | |
| 1365 | 1390 | mfm_w(buffer, offset, desc[index].p2, desc[index].p1); |
| 1366 | 1391 | break; |
| 1367 | 1392 | |
| 1393 | case GCR5: |
| 1394 | for(int i=0; i<desc[index].p2; i++) |
| 1395 | gcr5_w(buffer, offset, 8, desc[index].p1); |
| 1396 | break; |
| 1397 | |
| 1368 | 1398 | case RAW: |
| 1369 | 1399 | for(int i=0; i<desc[index].p2; i++) |
| 1370 | 1400 | raw_w(buffer, offset, 16, desc[index].p1); |
| 1371 | 1401 | break; |
| 1372 | 1402 | |
| 1403 | case RAWBYTE: |
| 1404 | for(int i=0; i<desc[index].p2; i++) |
| 1405 | raw_w(buffer, offset, 8, desc[index].p1); |
| 1406 | break; |
| 1407 | |
| 1373 | 1408 | case RAWBITS: |
| 1374 | 1409 | raw_w(buffer, offset, desc[index].p2, desc[index].p1); |
| 1375 | 1410 | break; |
| r20262 | r20263 | |
| 1410 | 1445 | fm_w(buffer, offset, 8, sect[sector_idx].sector_id); |
| 1411 | 1446 | break; |
| 1412 | 1447 | |
| 1448 | case SECTOR_ID_GCR5: |
| 1449 | gcr5_w(buffer, offset, 8, sect[sector_idx].sector_id); |
| 1450 | break; |
| 1451 | |
| 1413 | 1452 | case SECTOR_ID_GCR6: |
| 1414 | 1453 | raw_w(buffer, offset, 8, gcr6fw_tb[sect[sector_idx].sector_id]); |
| 1415 | 1454 | break; |
| r20262 | r20263 | |
| 1482 | 1521 | break; |
| 1483 | 1522 | |
| 1484 | 1523 | case CRC_AMIGA_START: |
| 1524 | case CRC_CBM_START: |
| 1485 | 1525 | case CRC_CCITT_START: |
| 1486 | 1526 | case CRC_CCITT_FM_START: |
| 1487 | 1527 | case CRC_MACHEAD_START: |
| r20262 | r20263 | |
| 1525 | 1565 | break; |
| 1526 | 1566 | } |
| 1527 | 1567 | |
| 1568 | case SECTOR_DATA_GCR5: { |
| 1569 | const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx); |
| 1570 | for(int i=0; i != csect->size; i++) |
| 1571 | gcr5_w(buffer, offset, 8, csect->data[i]); |
| 1572 | break; |
| 1573 | } |
| 1574 | |
| 1528 | 1575 | case SECTOR_DATA_MAC: { |
| 1529 | 1576 | const desc_s *csect = sect + (desc[index].p1 >= 0 ? desc[index].p1 : sector_idx); |
| 1530 | 1577 | const UINT8 *data = csect->data; |
| r20262 | r20263 | |
| 1696 | 1743 | image->set_write_splice_position(track, head, splice_angular_pos); |
| 1697 | 1744 | } |
| 1698 | 1745 | |
| 1746 | const UINT8 floppy_image_format_t::gcr5fw_tb[0x10] = |
| 1747 | { |
| 1748 | 0x0a, 0x0b, 0x12, 0x13, 0x0e, 0x0f, 0x16, 0x17, |
| 1749 | 0x09, 0x19, 0x1a, 0x1b, 0x0d, 0x1d, 0x1e, 0x15 |
| 1750 | }; |
| 1751 | |
| 1752 | const UINT8 floppy_image_format_t::gcr5bw_tb[0x20] = |
| 1753 | { |
| 1754 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 1755 | 0x00, 0x08, 0x00, 0x01, 0x00, 0x0c, 0x04, 0x05, |
| 1756 | 0x00, 0x00, 0x02, 0x03, 0x00, 0x0f, 0x06, 0x07, |
| 1757 | 0x00, 0x09, 0x0a, 0x0b, 0x00, 0x0d, 0x0e, 0x00 |
| 1758 | }; |
| 1759 | |
| 1699 | 1760 | const UINT8 floppy_image_format_t::gcr6fw_tb[0x40] = |
| 1700 | 1761 | { |
| 1701 | 1762 | 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6, |
trunk/src/lib/formats/flopimg.h
| r20262 | r20263 | |
| 301 | 301 | FM, //!< One byte in p1 to be fm-encoded, msb first, repeated p2 times |
| 302 | 302 | MFM, //!< One byte in p1 to be mfm-encoded, msb first, repeated p2 times |
| 303 | 303 | MFMBITS, //!< A value of p2 bits in p1 to be mfm-encoded, msb first |
| 304 | GCR5, //!< One byte in p1 to be gcr5-encoded, repeated p2 times |
| 304 | 305 | RAW, //!< One 16 bits word in p1 to be written raw, msb first, repeated p2 times |
| 306 | RAWBYTE, //!< One 8 bit byte in p1 to be written raw, msb first, repeated p2 times |
| 305 | 307 | RAWBITS, //!< A value of p2 bits in p1 to be copied as-is, msb first |
| 306 | 308 | TRACK_ID, //!< Track id byte, mfm-encoded |
| 307 | 309 | TRACK_ID_FM, //!< Track id byte, fm-encoded |
| r20262 | r20263 | |
| 312 | 314 | TRACK_HEAD_ID_GCR6, //!< Track id 7th bit + head, gc6-encoded |
| 313 | 315 | SECTOR_ID, //!< Sector id byte, mfm-encoded |
| 314 | 316 | SECTOR_ID_FM, //!< Sector id byte, fm-encoded |
| 317 | SECTOR_ID_GCR5, //!< Sector id byte, gcr5-encoded |
| 315 | 318 | SECTOR_ID_GCR6, //!< Sector id byte, gcr6-encoded |
| 316 | 319 | SIZE_ID, //!< Sector size code on one byte [log2(size/128)], mfm-encoded |
| 317 | 320 | SIZE_ID_FM, //!< Sector size code on one byte [log2(size/128)], fm-encoded |
| r20262 | r20263 | |
| 327 | 330 | SECTOR_DATA_FM, //!< Sector data to fm-encode, which in p1, -1 for the current one per the sector id |
| 328 | 331 | SECTOR_DATA_O, //!< Sector data to mfm-encode, odd bits only, which in p1, -1 for the current one per the sector id |
| 329 | 332 | SECTOR_DATA_E, //!< Sector data to mfm-encode, even bits only, which in p1, -1 for the current one per the sector id |
| 333 | SECTOR_DATA_GCR5, //!< Sector data to gcr5-encode, which in p1, -1 for the current one per the sector id |
| 330 | 334 | SECTOR_DATA_MAC, //!< Transformed sector data + checksum, mac style, id in p1, -1 for the current one per the sector id |
| 331 | 335 | |
| 332 | 336 | CRC_CCITT_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id |
| 333 | 337 | CRC_CCITT_FM_START, //!< Start a CCITT CRC calculation, with the usual x^16 + x^12 + x^5 + 1 (11021) polynomial, p1 = crc id |
| 334 | 338 | CRC_AMIGA_START, //!< Start an amiga checksum calculation, p1 = crc id |
| 339 | CRC_CBM_START, //<! Start a CBM checksum calculation (xor of original data values, gcr5-encoded), p1 = crc id |
| 335 | 340 | CRC_MACHEAD_START, //!< Start of the mac gcr6 sector header checksum calculation (xor of pre-encode 6-bits values, gcr6-encoded) |
| 336 | 341 | CRC_END, //!< End the checksum, p1 = crc id |
| 337 | 342 | CRC, //!< Write a checksum in the apporpriate format, p1 = crc id |
| r20262 | r20263 | |
| 391 | 396 | void normalize_times(UINT32 *buffer, int bitlen); |
| 392 | 397 | |
| 393 | 398 | // Some conversion tables for gcr |
| 394 | | static const UINT8 gcr5fw_tb[0x20], gcr5bw_tb[0x100]; |
| 399 | static const UINT8 gcr5fw_tb[0x10], gcr5bw_tb[0x20]; |
| 395 | 400 | static const UINT8 gcr6fw_tb[0x40], gcr6bw_tb[0x100]; |
| 396 | 401 | |
| 397 | 402 | // Some useful descriptions shared by multiple formats |
| r20262 | r20263 | |
| 536 | 541 | void mfm_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000); |
| 537 | 542 | //! MFM-encode every two bits and write |
| 538 | 543 | void mfm_half_w(UINT32 *buffer, int &offset, int start_bit, UINT32 val, UINT32 size = 1000); |
| 544 | //! GCR5-encode and write a series of bits |
| 545 | void gcr5_w(UINT32 *buffer, int &offset, int n, UINT32 val, UINT32 size = 1000); |
| 539 | 546 | //! GCR4 encode (Apple II sector header) |
| 540 | 547 | UINT16 gcr4_encode(UINT8 va); |
| 541 | 548 | //! GCR4 decode |
| r20262 | r20263 | |
| 546 | 553 | void gcr6_decode(UINT8 e0, UINT8 e1, UINT8 e2, UINT8 e3, UINT8 &va, UINT8 &vb, UINT8 &vc); |
| 547 | 554 | |
| 548 | 555 | private: |
| 549 | | enum { CRC_NONE, CRC_AMIGA, CRC_CCITT, CRC_CCITT_FM, CRC_MACHEAD }; |
| 556 | enum { CRC_NONE, CRC_AMIGA, CRC_CBM, CRC_CCITT, CRC_CCITT_FM, CRC_MACHEAD }; |
| 550 | 557 | enum { MAX_CRC_COUNT = 64 }; |
| 551 | 558 | |
| 552 | 559 | //! Holds data used internally for generating CRCs. |
| r20262 | r20263 | |
| 563 | 570 | |
| 564 | 571 | int crc_cells_size(int type) const; |
| 565 | 572 | void fixup_crc_amiga(UINT32 *buffer, const gen_crc_info *crc); |
| 573 | void fixup_crc_cbm(UINT32 *buffer, const gen_crc_info *crc); |
| 566 | 574 | void fixup_crc_ccitt(UINT32 *buffer, const gen_crc_info *crc); |
| 567 | 575 | void fixup_crc_ccitt_fm(UINT32 *buffer, const gen_crc_info *crc); |
| 568 | 576 | void fixup_crc_machead(UINT32 *buffer, const gen_crc_info *crc); |
trunk/src/lib/formats/d64_dsk.c
| r20262 | r20263 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Copyright Olivier Galibert |
| 4 | All rights reserved. |
| 5 | |
| 6 | Redistribution and use in source and binary forms, with or without |
| 7 | modification, are permitted provided that the following conditions are |
| 8 | met: |
| 9 | |
| 10 | * Redistributions of source code must retain the above copyright |
| 11 | notice, this list of conditions and the following disclaimer. |
| 12 | * Redistributions in binary form must reproduce the above copyright |
| 13 | notice, this list of conditions and the following disclaimer in |
| 14 | the documentation and/or other materials provided with the |
| 15 | distribution. |
| 16 | * Neither the name 'MAME' nor the names of its contributors may be |
| 17 | used to endorse or promote products derived from this software |
| 18 | without specific prior written permission. |
| 19 | |
| 20 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR |
| 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 23 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, |
| 24 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 30 | POSSIBILITY OF SUCH DAMAGE. |
| 31 | |
| 32 | ****************************************************************************/ |
| 33 | |
| 1 | 34 | /********************************************************************* |
| 2 | 35 | |
| 3 | 36 | formats/d64_dsk.c |
| r20262 | r20263 | |
| 2 | 35 | |
| 36 | Commodore 2040/8050/1541 sector disk image format |
| 37 | |
| 38 | *********************************************************************/ |
| 39 | |
| 40 | #include "emu.h" |
| 41 | #include "formats/d64_dsk.h" |
| 42 | |
| 43 | d64_format::d64_format() |
| 44 | { |
| 45 | } |
| 46 | |
| 47 | const char *d64_format::name() const |
| 48 | { |
| 49 | return "d64"; |
| 50 | } |
| 51 | |
| 52 | const char *d64_format::description() const |
| 53 | { |
| 54 | return "Commodore 2040/8050/1541 disk image"; |
| 55 | } |
| 56 | |
| 57 | const char *d64_format::extensions() const |
| 58 | { |
| 59 | return "d64,d67,d71,d80,d82"; |
| 60 | } |
| 61 | |
| 62 | const d64_format::format d64_format::formats[] = { |
| 63 | { // d67, dos 1, 35 tracks |
| 64 | floppy_image::FF_525, floppy_image::SSSD, DOS_1, 690, 35, 1, 9, 8 |
| 65 | }, |
| 66 | { // d64, dos 2, 35 tracks |
| 67 | floppy_image::FF_525, floppy_image::SSSD, DOS_2, 683, 35, 1, 9, 8 |
| 68 | }, |
| 69 | { // d64, dos 2, 40 tracks |
| 70 | floppy_image::FF_525, floppy_image::SSSD, DOS_2, 768, 35, 1, 9, 8 |
| 71 | }, |
| 72 | { // d64, dos 2, 42 tracks |
| 73 | floppy_image::FF_525, floppy_image::SSSD, DOS_2, 802, 35, 1, 9, 8 |
| 74 | }, |
| 75 | { // d71, dos 2, 35 tracks, 2 heads |
| 76 | floppy_image::FF_525, floppy_image::DSSD, DOS_2, 683, 35, 2, 9, 8 |
| 77 | }, |
| 78 | { // d80, dos 2.5, 77 tracks |
| 79 | floppy_image::FF_525, floppy_image::SSQD, DOS_25, 2083, 77, 15, 9, 8 |
| 80 | }, |
| 81 | { // d82, dos 2.5, 77 tracks, 2 heads |
| 82 | floppy_image::FF_525, floppy_image::DSQD, DOS_25, 2083, 77, 15, 9, 8 |
| 83 | }, |
| 84 | {} |
| 85 | }; |
| 86 | |
| 87 | const UINT32 d64_format::dos1_cell_size[] = |
| 88 | { |
| 89 | 4000, // 16MHz/16/4 |
| 90 | 3750, // 16MHz/15/4 |
| 91 | 3500, // 16MHz/14/4 |
| 92 | 3250 // 16MHz/13/4 |
| 93 | }; |
| 94 | |
| 95 | const UINT32 d64_format::dos25_cell_size[] = |
| 96 | { |
| 97 | 2667, // 12MHz/16/2 |
| 98 | 2500, // 12MHz/15/2 |
| 99 | 2333, // 12MHz/14/2 |
| 100 | 2167 // 12MHz/13/2 |
| 101 | }; |
| 102 | |
| 103 | const int d64_format::dos1_sectors_per_track[] = |
| 104 | { |
| 105 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, // 1-17 |
| 106 | 20, 20, 20, 20, 20, 20, 20, // 18-24 |
| 107 | 18, 18, 18, 18, 18, 18, // 25-30 |
| 108 | 17, 17, 17, 17, 17, // 31-35 |
| 109 | 17, 17, 17, 17, 17, // 36-40 |
| 110 | 17, 17 // 41-42 |
| 111 | }; |
| 112 | |
| 113 | const int d64_format::dos2_sectors_per_track[] = |
| 114 | { |
| 115 | 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, // 1-17 |
| 116 | 19, 19, 19, 19, 19, 19, 19, // 18-24 |
| 117 | 18, 18, 18, 18, 18, 18, // 25-30 |
| 118 | 17, 17, 17, 17, 17, // 31-35 |
| 119 | 17, 17, 17, 17, 17, // 36-40 |
| 120 | 17, 17 // 41-42 |
| 121 | }; |
| 122 | |
| 123 | const int d64_format::dos25_sectors_per_track[] = |
| 124 | { |
| 125 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, // 1-39 |
| 126 | 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, |
| 127 | 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, // 40-53 |
| 128 | 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, // 54-64 |
| 129 | 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, // 65-77 |
| 130 | 23, 23, 23, 23, 23, 23, 23 // 78-84 |
| 131 | }; |
| 132 | |
| 133 | const int d64_format::dos1_speed_zone[] = |
| 134 | { |
| 135 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 1-17 |
| 136 | 2, 2, 2, 2, 2, 2, 2, // 18-24 |
| 137 | 1, 1, 1, 1, 1, 1, // 25-30 |
| 138 | 0, 0, 0, 0, 0, // 31-35 |
| 139 | 0, 0, 0, 0, 0, // 36-40 |
| 140 | 0, 0 // 41-42 |
| 141 | }; |
| 142 | |
| 143 | const int d64_format::dos25_speed_zone[] = |
| 144 | { |
| 145 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 1-39 |
| 146 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 147 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 40-53 |
| 148 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 54-64 |
| 149 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 65-77 |
| 150 | 0, 0, 0, 0, 0, 0, 0 // 78-84 |
| 151 | }; |
| 152 | |
| 153 | int d64_format::find_size(io_generic *io, UINT32 form_factor) |
| 154 | { |
| 155 | int size = io_generic_size(io); |
| 156 | for(int i=0; formats[i].sector_count; i++) { |
| 157 | const format &f = formats[i]; |
| 158 | if(size == f.sector_count*SECTOR_SIZE) |
| 159 | return i; |
| 160 | if(size == (f.sector_count*SECTOR_SIZE) + f.sector_count) |
| 161 | return i; |
| 162 | } |
| 163 | return -1; |
| 164 | } |
| 165 | |
| 166 | int d64_format::identify(io_generic *io, UINT32 form_factor) |
| 167 | { |
| 168 | int type = find_size(io, form_factor); |
| 169 | |
| 170 | if(type != -1) |
| 171 | return 50; |
| 172 | return 0; |
| 173 | } |
| 174 | |
| 175 | int d64_format::get_physical_track(const format &f, int track) |
| 176 | { |
| 177 | int physical_track = 0; |
| 178 | |
| 179 | switch (f.dos) { |
| 180 | case DOS_1: physical_track = track*2; break; // skip halftracks |
| 181 | case DOS_2: physical_track = track*2; break; // skip halftracks |
| 182 | case DOS_25: physical_track = track; break; |
| 183 | } |
| 184 | |
| 185 | return physical_track; |
| 186 | } |
| 187 | |
| 188 | void d64_format::get_disk_id(const format &f, io_generic *io, UINT8 &id1, UINT8 &id2) |
| 189 | { |
| 190 | int offset = 0; |
| 191 | |
| 192 | switch (f.dos) { |
| 193 | case DOS_1: offset = DOS1_DISK_ID_OFFSET; break; |
| 194 | case DOS_2: offset = DOS1_DISK_ID_OFFSET; break; |
| 195 | case DOS_25: offset = DOS25_DISK_ID_OFFSET; break; |
| 196 | } |
| 197 | |
| 198 | UINT8 id[2]; |
| 199 | io_generic_read(io, id, offset, 2); |
| 200 | id1 = id[0]; |
| 201 | id2 = id[1]; |
| 202 | } |
| 203 | |
| 204 | UINT32 d64_format::get_cell_size(const format &f, int track) |
| 205 | { |
| 206 | int cell_size = 0; |
| 207 | |
| 208 | switch (f.dos) { |
| 209 | case DOS_1: cell_size = dos1_cell_size[dos1_speed_zone[track]]; break; |
| 210 | case DOS_2: cell_size = dos1_cell_size[dos1_speed_zone[track]]; break; |
| 211 | case DOS_25: cell_size = dos25_cell_size[dos25_speed_zone[track]]; break; |
| 212 | } |
| 213 | |
| 214 | return cell_size; |
| 215 | } |
| 216 | |
| 217 | int d64_format::get_sectors_per_track(const format &f, int track) |
| 218 | { |
| 219 | int sector_count = 0; |
| 220 | |
| 221 | switch (f.dos) { |
| 222 | case DOS_1: sector_count = dos1_sectors_per_track[track]; break; |
| 223 | case DOS_2: sector_count = dos1_sectors_per_track[track]; break; |
| 224 | case DOS_25: sector_count = dos25_sectors_per_track[track]; break; |
| 225 | } |
| 226 | |
| 227 | return sector_count; |
| 228 | } |
| 229 | |
| 230 | floppy_image_format_t::desc_e* d64_format::get_sector_desc(const format &f, int ¤t_size, int track, int sector_count, UINT8 id1, UINT8 id2, int gap_2) |
| 231 | { |
| 232 | static floppy_image_format_t::desc_e desc[] = { |
| 233 | /* 00 */ { SECTOR_LOOP_START, 0, sector_count-1 }, |
| 234 | /* 01 */ { RAWBYTE, 0xff, 5 }, |
| 235 | /* 02 */ { GCR5, 0x08, 1 }, |
| 236 | /* 03 */ { CRC, 1 }, |
| 237 | /* 04 */ { CRC_CBM_START, 1 }, |
| 238 | /* 05 */ { SECTOR_ID_GCR5 }, |
| 239 | /* 06 */ { GCR5, track, 1 }, |
| 240 | /* 07 */ { GCR5, id2, 1 }, |
| 241 | /* 08 */ { GCR5, id1, 1 }, |
| 242 | /* 09 */ { CRC_END, 1 }, |
| 243 | /* 10 */ { GCR5, 0x0f, 2 }, |
| 244 | /* 11 */ { RAWBYTE, 0x55, f.gap_1 }, |
| 245 | /* 12 */ { RAWBYTE, 0xff, 5 }, |
| 246 | /* 13 */ { GCR5, 0x07, 1 }, |
| 247 | /* 14 */ { CRC_CBM_START, 2 }, |
| 248 | /* 15 */ { SECTOR_DATA_GCR5, -1 }, |
| 249 | /* 16 */ { CRC_END, 2 }, |
| 250 | /* 17 */ { CRC, 2 }, |
| 251 | /* 18 */ { GCR5, 0x00, 2 }, |
| 252 | /* 19 */ { RAWBYTE, 0x55, gap_2 }, |
| 253 | /* 20 */ { SECTOR_LOOP_END }, |
| 254 | /* 21 */ { RAWBYTE, 0x55, 0 }, |
| 255 | /* 22 */ { RAWBITS, 0xffff, 0 }, |
| 256 | /* 23 */ { END } |
| 257 | }; |
| 258 | |
| 259 | current_size = 40 + (1+1+4+2)*10 + (f.gap_1)*8 + 40 + (1+SECTOR_SIZE+1+2)*10 + gap_2*8; |
| 260 | current_size *= sector_count; |
| 261 | |
| 262 | return desc; |
| 263 | } |
| 264 | |
| 265 | void d64_format::build_sector_description(const format &f, UINT8 *sectdata, desc_s *sectors, int sector_count, UINT8 *errordata) const |
| 266 | { |
| 267 | int cur_offset = 0; |
| 268 | |
| 269 | for(int i=0; i<f.sector_count; i++) { |
| 270 | sectors[i].data = sectdata + cur_offset; |
| 271 | sectors[i].size = SECTOR_SIZE; |
| 272 | sectors[i].sector_id = i; |
| 273 | sectors[i].sector_info = errordata[i]; |
| 274 | |
| 275 | cur_offset += sectors[i].size; |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | bool d64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 280 | { |
| 281 | int type = find_size(io, form_factor); |
| 282 | if(type == -1) |
| 283 | return false; |
| 284 | |
| 285 | const format &f = formats[type]; |
| 286 | int size = io_generic_size(io); |
| 287 | UINT8 *img; |
| 288 | |
| 289 | if(size == f.sector_count*SECTOR_SIZE) { |
| 290 | img = global_alloc_array(UINT8, size + f.sector_count); |
| 291 | memset(&img[size + f.sector_count], ERROR_00, f.sector_count); |
| 292 | } |
| 293 | else { |
| 294 | img = global_alloc_array(UINT8, size); |
| 295 | } |
| 296 | |
| 297 | io_generic_read(io, img, 0, size); |
| 298 | |
| 299 | floppy_image_format_t::desc_e *desc; |
| 300 | desc_s sectors[40]; |
| 301 | int track_offset = 0, error_offset = 0; |
| 302 | |
| 303 | UINT8 id1 = 0, id2 = 0; |
| 304 | get_disk_id(f, io, id1, id2); |
| 305 | |
| 306 | for(int head=0; head < f.head_count; head++) { |
| 307 | for(int track=0; track < f.track_count; track++) { |
| 308 | int current_size = 0; |
| 309 | int total_size = 200000000/get_cell_size(f, track); |
| 310 | |
| 311 | int physical_track = get_physical_track(f, track); |
| 312 | int sector_count = get_sectors_per_track(f, track); |
| 313 | int track_size = sector_count*SECTOR_SIZE; |
| 314 | |
| 315 | desc = get_sector_desc(f, current_size, track+1, sector_count, id1, id2, f.gap_2); |
| 316 | |
| 317 | int remaining_size = total_size - current_size; |
| 318 | if(remaining_size < 0) |
| 319 | throw emu_fatalerror("d64_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size); |
| 320 | |
| 321 | // Fixup the end gap |
| 322 | desc[21].p2 = remaining_size / 8; |
| 323 | desc[22].p2 = remaining_size & 7; |
| 324 | desc[22].p1 >>= 8-(remaining_size & 7); |
| 325 | |
| 326 | printf("track %u cursize %u totsize %u phystrack %u secnt %u trksize %u trkofs %u\n", track,current_size,total_size,physical_track,sector_count,track_size,track_offset); |
| 327 | |
| 328 | build_sector_description(f, &img[track_offset], sectors, sector_count, &img[f.sector_count*SECTOR_SIZE + error_offset]); |
| 329 | generate_track(desc, physical_track, head, sectors, sector_count, total_size, image); |
| 330 | |
| 331 | track_offset += track_size; |
| 332 | error_offset += sector_count; |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | image->set_variant(f.variant); |
| 337 | |
| 338 | return true; |
| 339 | } |
| 340 | |
| 341 | bool d64_format::save(io_generic *io, floppy_image *image) |
| 342 | { |
| 343 | return false; |
| 344 | } |
| 345 | |
| 346 | bool d64_format::supports_save() const |
| 347 | { |
| 348 | return false; |
| 349 | } |
| 350 | |
| 351 | const floppy_format_type FLOPPY_D64_FORMAT = &floppy_image_format_creator<d64_format>; |
| 352 | |
| 353 | |
| 354 | // ------ LEGACY ----- |
| 355 | |
| 356 | |
| 357 | /********************************************************************* |
| 358 | |
| 359 | formats/d64_dsk.c |
| 360 | |
| 3 | 361 | Floppy format code for Commodore 1541/2040/8050 disk images |
| r20262 | r20263 | |
| 809 | 1167 | for d80 & d82 they are at track 39 bytes 0x18 & 0x19 |
| 810 | 1168 | */ |
| 811 | 1169 | if (dos == DOS25) |
| 1170 | { |
| 1171 | printf("dos25 id offset %u\n", tag->track_offset[0][38] + 0x18); |
| 812 | 1172 | floppy_image_read(floppy, id, tag->track_offset[0][38] + 0x18, 2); |
| 1173 | } |
| 813 | 1174 | else |
| 1175 | { |
| 1176 | printf("dos2 id offset %u\n", tag->track_offset[0][38] + 0x18); |
| 814 | 1177 | floppy_image_read(floppy, id, tag->track_offset[0][34] + 0xa2, 2); |
| 1178 | } |
| 815 | 1179 | |
| 816 | 1180 | tag->id1 = id[0]; |
| 817 | 1181 | tag->id2 = id[1]; |
trunk/src/lib/formats/g64_dsk.c
| r20262 | r20263 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | Copyright Olivier Galibert |
| 4 | All rights reserved. |
| 5 | |
| 6 | Redistribution and use in source and binary forms, with or without |
| 7 | modification, are permitted provided that the following conditions are |
| 8 | met: |
| 9 | |
| 10 | * Redistributions of source code must retain the above copyright |
| 11 | notice, this list of conditions and the following disclaimer. |
| 12 | * Redistributions in binary form must reproduce the above copyright |
| 13 | notice, this list of conditions and the following disclaimer in |
| 14 | the documentation and/or other materials provided with the |
| 15 | distribution. |
| 16 | * Neither the name 'MAME' nor the names of its contributors may be |
| 17 | used to endorse or promote products derived from this software |
| 18 | without specific prior written permission. |
| 19 | |
| 20 | THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR |
| 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 23 | DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, |
| 24 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 30 | POSSIBILITY OF SUCH DAMAGE. |
| 31 | |
| 32 | ****************************************************************************/ |
| 33 | |
| 1 | 34 | /********************************************************************* |
| 2 | 35 | |
| 3 | 36 | formats/g64_dsk.c |
| r20262 | r20263 | |
| 2 | 35 | |
| 36 | Commodore 1541 GCR disk image format |
| 37 | |
| 38 | *********************************************************************/ |
| 39 | |
| 40 | #include "emu.h" |
| 41 | #include "formats/g64_dsk.h" |
| 42 | |
| 43 | #define G64_FORMAT_HEADER "GCR-1541" |
| 44 | |
| 45 | g64_format::g64_format() |
| 46 | { |
| 47 | } |
| 48 | |
| 49 | const char *g64_format::name() const |
| 50 | { |
| 51 | return "g64"; |
| 52 | } |
| 53 | |
| 54 | const char *g64_format::description() const |
| 55 | { |
| 56 | return "Commodore 1541 GCR disk image"; |
| 57 | } |
| 58 | |
| 59 | const char *g64_format::extensions() const |
| 60 | { |
| 61 | return "g64"; |
| 62 | } |
| 63 | |
| 64 | const UINT32 g64_format::c1541_cell_size[] = |
| 65 | { |
| 66 | 4000, // 16MHz/16/4 |
| 67 | 3750, // 16MHz/15/4 |
| 68 | 3500, // 16MHz/14/4 |
| 69 | 3250 // 16MHz/13/4 |
| 70 | }; |
| 71 | |
| 72 | int g64_format::identify(io_generic *io, UINT32 form_factor) |
| 73 | { |
| 74 | UINT8 header[8]; |
| 75 | |
| 76 | io_generic_read(io, &header, 0, sizeof(header)); |
| 77 | if ( memcmp( header, G64_FORMAT_HEADER, 8 ) ==0) { |
| 78 | return 100; |
| 79 | } |
| 80 | return 0; |
| 81 | } |
| 82 | |
| 83 | bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) |
| 84 | { |
| 85 | int size = io_generic_size(io); |
| 86 | UINT8 *img = global_alloc_array(UINT8, size); |
| 87 | io_generic_read(io, img, 0, size); |
| 88 | |
| 89 | int track_count = pick_integer_le(img, 9, 2); |
| 90 | |
| 91 | int pos = 0x0c; |
| 92 | int track_offset[track_count]; |
| 93 | for(int track = 0; track < track_count; track++) { |
| 94 | track_offset[track] = pick_integer_le(img, pos, 4); |
| 95 | pos += 4; |
| 96 | } |
| 97 | |
| 98 | int speed_zone_offset[track_count]; |
| 99 | for(int track = 0; track < track_count; track++) { |
| 100 | speed_zone_offset[track] = pick_integer_le(img, pos, 4); |
| 101 | pos += 4; |
| 102 | } |
| 103 | |
| 104 | for(int track = 0; track < track_count; track++) { |
| 105 | int track_size = 0; |
| 106 | pos = track_offset[track]; |
| 107 | if (pos > 0) { |
| 108 | track_size = pick_integer_le(img, pos, 2); |
| 109 | pos +=2; |
| 110 | } |
| 111 | |
| 112 | if (speed_zone_offset[track] > 3) |
| 113 | throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track); |
| 114 | |
| 115 | UINT32 cell_size = c1541_cell_size[speed_zone_offset[track]]; |
| 116 | int total_size = 200000000/cell_size; |
| 117 | UINT32 *buffer = global_alloc_array_clear(UINT32, total_size); |
| 118 | int offset = 0; |
| 119 | |
| 120 | if (pos > 0) { |
| 121 | for (int i=0; i<track_size; i++) { |
| 122 | raw_w(buffer, offset, 8, img[pos++], cell_size); |
| 123 | } |
| 124 | |
| 125 | if (offset >= total_size) |
| 126 | throw emu_fatalerror("g64_format: Too many cells for track %d", track); |
| 127 | } |
| 128 | |
| 129 | generate_track_from_levels(track, 0, buffer, total_size, 0, image); |
| 130 | global_free(buffer); |
| 131 | } |
| 132 | |
| 133 | image->set_variant(floppy_image::SSSD); |
| 134 | |
| 135 | return true; |
| 136 | } |
| 137 | |
| 138 | bool g64_format::save(io_generic *io, floppy_image *image) |
| 139 | { |
| 140 | return false; |
| 141 | } |
| 142 | |
| 143 | bool g64_format::supports_save() const |
| 144 | { |
| 145 | return false; |
| 146 | } |
| 147 | |
| 148 | const floppy_format_type FLOPPY_G64_FORMAT = &floppy_image_format_creator<g64_format>; |
| 149 | |
| 150 | |
| 151 | // ------ LEGACY ----- |
| 152 | |
| 153 | |
| 154 | /********************************************************************* |
| 155 | |
| 156 | formats/g64_dsk.c |
| 157 | |
| 3 | 158 | Floppy format code for Commodore 1541 GCR disk images |