trunk/src/lib/formats/flopimg.c
| r19188 | r19189 | |
| 20 | 20 | #include "pool.h" |
| 21 | 21 | #include "imageutl.h" |
| 22 | 22 | |
| 23 | | #define TRACK_LOADED 0x01 |
| 24 | | #define TRACK_DIRTY 0x02 |
| 23 | #define TRACK_LOADED 0x01 |
| 24 | #define TRACK_DIRTY 0x02 |
| 25 | 25 | |
| 26 | 26 | |
| 27 | 27 | struct floppy_image_legacy |
| r19188 | r19189 | |
| 57 | 57 | static floperr_t floppy_track_unload(floppy_image_legacy *floppy); |
| 58 | 58 | |
| 59 | 59 | OPTION_GUIDE_START(floppy_option_guide) |
| 60 | | OPTION_INT('H', "heads", "Heads") |
| 61 | | OPTION_INT('T', "tracks", "Tracks") |
| 62 | | OPTION_INT('S', "sectors", "Sectors") |
| 63 | | OPTION_INT('L', "sectorlength", "Sector Bytes") |
| 64 | | OPTION_INT('I', "interleave", "Interleave") |
| 65 | | OPTION_INT('F', "firstsectorid", "First Sector") |
| 60 | OPTION_INT('H', "heads", "Heads") |
| 61 | OPTION_INT('T', "tracks", "Tracks") |
| 62 | OPTION_INT('S', "sectors", "Sectors") |
| 63 | OPTION_INT('L', "sectorlength", "Sector Bytes") |
| 64 | OPTION_INT('I', "interleave", "Interleave") |
| 65 | OPTION_INT('F', "firstsectorid", "First Sector") |
| 66 | 66 | OPTION_GUIDE_END |
| 67 | 67 | |
| 68 | 68 | |
| r19188 | r19189 | |
| 485 | 485 | if ((offset > 0) || (buffer_len < sector_length)) |
| 486 | 486 | { |
| 487 | 487 | /* we will be doing an partial read/write; in other words we |
| 488 | | * will not be reading/writing a full sector */ |
| 488 | * will not be reading/writing a full sector */ |
| 489 | 489 | if (alloc_buf) free(alloc_buf); |
| 490 | 490 | alloc_buf = (UINT8*)malloc(sector_length); |
| 491 | 491 | if (!alloc_buf) |
| r19188 | r19189 | |
| 550 | 550 | |
| 551 | 551 | |
| 552 | 552 | |
| 553 | | floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len) |
| 553 | floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len) |
| 554 | 554 | { |
| 555 | 555 | return floppy_readwrite_sector(floppy, head, track, sector, offset, buffer, buffer_len, FALSE, FALSE, 0); |
| 556 | 556 | } |
| r19188 | r19189 | |
| 564 | 564 | |
| 565 | 565 | |
| 566 | 566 | |
| 567 | | floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len) |
| 567 | floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len) |
| 568 | 568 | { |
| 569 | 569 | return floppy_readwrite_sector(floppy, head, track, sector_index, offset, buffer, buffer_len, FALSE, TRUE, 0); |
| 570 | 570 | } |
| r19188 | r19189 | |
| 1015 | 1015 | goto track_done; |
| 1016 | 1016 | maxt--; |
| 1017 | 1017 | } |
| 1018 | | track_done: |
| 1018 | track_done: |
| 1019 | 1019 | if(maxt >= 0) |
| 1020 | 1020 | while(maxh >= 0) { |
| 1021 | 1021 | for(int i=0; i<=maxt; i++) |
| r19188 | r19189 | |
| 1023 | 1023 | goto head_done; |
| 1024 | 1024 | maxh--; |
| 1025 | 1025 | } |
| 1026 | | head_done: |
| 1026 | head_done: |
| 1027 | 1027 | _tracks = maxt+1; |
| 1028 | 1028 | _heads = maxh+1; |
| 1029 | 1029 | } |
| r19188 | r19189 | |
| 1373 | 1373 | raw_w(buffer, offset, 8, gcr6fw_tb[(track & 0x40 ? 1 : 0) | (head ? 0x20 : 0)]); |
| 1374 | 1374 | break; |
| 1375 | 1375 | |
| 1376 | | case SECTOR_ID: |
| 1376 | case SECTOR_ID: |
| 1377 | 1377 | mfm_w(buffer, offset, 8, sect[sector_idx].sector_id); |
| 1378 | 1378 | break; |
| 1379 | 1379 | |
| r19188 | r19189 | |
| 2131 | 2131 | |
| 2132 | 2132 | // Wrap around |
| 2133 | 2133 | if(cur_entry == tsize-1 && |
| 2134 | | (tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos) { |
| 2134 | (tbuf[cur_entry] & floppy_image::TIME_MASK) < cur_pos) { |
| 2135 | 2135 | // Wrap to index 0 or 1 depending on whether there is a transition exactly at the index hole |
| 2136 | 2136 | cur_entry = (tbuf[tsize-1] & floppy_image::MG_MASK) != (tbuf[0] & floppy_image::MG_MASK) ? |
| 2137 | 2137 | 0 : 1; |
| r19188 | r19189 | |
| 2524 | 2524 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 2525 | 2525 | fm_w (track_data, tpos, 16, crc); |
| 2526 | 2526 | for(int j=0; j<gap_2; j++) fm_w(track_data, tpos, 8, 0xff); |
| 2527 | | |
| 2527 | |
| 2528 | 2528 | if(!sects[i].data) |
| 2529 | 2529 | for(int j=0; j<6+1+sects[i].actual_size+2+gap_3; j++) fm_w(track_data, tpos, 8, 0xff); |
| 2530 | 2530 | |
| r19188 | r19189 | |
| 2543 | 2543 | } |
| 2544 | 2544 | |
| 2545 | 2545 | // Gap 4b |
| 2546 | | |
| 2546 | |
| 2547 | 2547 | while(tpos < cell_count-15) fm_w(track_data, tpos, 8, 0xff); |
| 2548 | 2548 | raw_w(track_data, tpos, cell_count-tpos, 0xffff >> (16+tpos-cell_count)); |
| 2549 | 2549 | |
| r19188 | r19189 | |
| 2586 | 2586 | for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); |
| 2587 | 2587 | cpos = tpos; |
| 2588 | 2588 | for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); |
| 2589 | | mfm_w(track_data, tpos, 8, 0xfe); |
| 2589 | mfm_w(track_data, tpos, 8, 0xfe); |
| 2590 | 2590 | mfm_w(track_data, tpos, 8, sects[i].track); |
| 2591 | 2591 | mfm_w(track_data, tpos, 8, sects[i].head); |
| 2592 | 2592 | mfm_w(track_data, tpos, 8, sects[i].sector); |
| r19188 | r19189 | |
| 2603 | 2603 | for(int j=0; j<12; j++) mfm_w(track_data, tpos, 8, 0x00); |
| 2604 | 2604 | cpos = tpos; |
| 2605 | 2605 | for(int j=0; j< 3; j++) raw_w(track_data, tpos, 16, 0x4489); |
| 2606 | | mfm_w(track_data, tpos, 8, sects[i].deleted ? 0xf8 : 0xfb); |
| 2606 | mfm_w(track_data, tpos, 8, sects[i].deleted ? 0xf8 : 0xfb); |
| 2607 | 2607 | for(int j=0; j<sects[i].actual_size; j++) mfm_w(track_data, tpos, 8, sects[i].data[j]); |
| 2608 | 2608 | crc = calc_crc_ccitt(track_data, cpos, tpos); |
| 2609 | 2609 | if(sects[i].bad_crc) |
| r19188 | r19189 | |
| 2621 | 2621 | generate_track_from_levels(track, head, track_data, cell_count, 0, image); |
| 2622 | 2622 | global_free(track_data); |
| 2623 | 2623 | } |
| 2624 | | |
trunk/src/lib/formats/flopimg.h
| r19188 | r19189 | |
| 24 | 24 | |
| 25 | 25 | ***************************************************************************/ |
| 26 | 26 | |
| 27 | | #define FLOPPY_FLAGS_READWRITE 0 |
| 28 | | #define FLOPPY_FLAGS_READONLY 1 |
| 27 | #define FLOPPY_FLAGS_READWRITE 0 |
| 28 | #define FLOPPY_FLAGS_READONLY 1 |
| 29 | 29 | |
| 30 | 30 | /* sector has a deleted data address mark */ |
| 31 | | #define ID_FLAG_DELETED_DATA 0x0001 |
| 31 | #define ID_FLAG_DELETED_DATA 0x0001 |
| 32 | 32 | /* CRC error in id field */ |
| 33 | 33 | #define ID_FLAG_CRC_ERROR_IN_ID_FIELD 0x0002 |
| 34 | 34 | /* CRC error in data field */ |
| r19188 | r19189 | |
| 43 | 43 | |
| 44 | 44 | enum floperr_t |
| 45 | 45 | { |
| 46 | | FLOPPY_ERROR_SUCCESS, /* no error */ |
| 47 | | FLOPPY_ERROR_INTERNAL, /* fatal internal error */ |
| 48 | | FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */ |
| 49 | | FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */ |
| 50 | | FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistant location */ |
| 51 | | FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */ |
| 52 | | FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */ |
| 46 | FLOPPY_ERROR_SUCCESS, /* no error */ |
| 47 | FLOPPY_ERROR_INTERNAL, /* fatal internal error */ |
| 48 | FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */ |
| 49 | FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */ |
| 50 | FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistant location */ |
| 51 | FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */ |
| 52 | FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */ |
| 53 | 53 | FLOPPY_ERROR_NOSPACE, |
| 54 | 54 | FLOPPY_ERROR_PARAMOUTOFRANGE, |
| 55 | 55 | FLOPPY_ERROR_PARAMNOTSPECIFIED |
| r19188 | r19189 | |
| 89 | 89 | const char *param_guidelines; |
| 90 | 90 | }; |
| 91 | 91 | |
| 92 | | #define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote) |
| 93 | | #define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, option_resolution *params) |
| 94 | | #define FLOPPY_DESTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format) |
| 92 | #define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote) |
| 93 | #define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, option_resolution *params) |
| 94 | #define FLOPPY_DESTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format) |
| 95 | 95 | |
| 96 | 96 | FLOPPY_IDENTIFY(td0_dsk_identify); |
| 97 | 97 | FLOPPY_CONSTRUCT(td0_dsk_construct); |
| r19188 | r19189 | |
| 112 | 112 | FLOPPY_IDENTIFY(fdi_dsk_identify); |
| 113 | 113 | FLOPPY_CONSTRUCT(fdi_dsk_construct); |
| 114 | 114 | |
| 115 | | #define LEGACY_FLOPPY_OPTIONS_NAME(name) floppyoptions_##name |
| 115 | #define LEGACY_FLOPPY_OPTIONS_NAME(name) floppyoptions_##name |
| 116 | 116 | |
| 117 | | #define LEGACY_FLOPPY_OPTIONS_START(name) \ |
| 118 | | const struct FloppyFormat floppyoptions_##name[] = \ |
| 119 | | { \ |
| 117 | #define LEGACY_FLOPPY_OPTIONS_START(name) \ |
| 118 | const struct FloppyFormat floppyoptions_##name[] = \ |
| 119 | { \ |
| 120 | 120 | |
| 121 | 121 | #define LEGACY_FLOPPY_OPTIONS_END0 \ |
| 122 | | { NULL } \ |
| 122 | { NULL } \ |
| 123 | 123 | }; |
| 124 | 124 | |
| 125 | | #define LEGACY_FLOPPY_OPTIONS_EXTERN(name) \ |
| 126 | | extern const struct FloppyFormat floppyoptions_##name[] \ |
| 125 | #define LEGACY_FLOPPY_OPTIONS_EXTERN(name) \ |
| 126 | extern const struct FloppyFormat floppyoptions_##name[] \ |
| 127 | 127 | |
| 128 | 128 | #define LEGACY_FLOPPY_OPTION(name, extensions_, description_, identify_, construct_, destruct_, ranges_)\ |
| 129 | | { #name, extensions_, description_, identify_, construct_, destruct_, ranges_ }, \ |
| 129 | { #name, extensions_, description_, identify_, construct_, destruct_, ranges_ }, \ |
| 130 | 130 | |
| 131 | | #define LEGACY_FLOPPY_OPTIONS_END \ |
| 131 | #define LEGACY_FLOPPY_OPTIONS_END \ |
| 132 | 132 | LEGACY_FLOPPY_OPTION( fdi, "fdi", "Formatted Disk Image", fdi_dsk_identify, fdi_dsk_construct, NULL, NULL) \ |
| 133 | | LEGACY_FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL) \ |
| 134 | | LEGACY_FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, NULL, NULL) \ |
| 135 | | LEGACY_FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, NULL, NULL) \ |
| 136 | | LEGACY_FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, NULL, NULL) \ |
| 133 | LEGACY_FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, NULL) \ |
| 134 | LEGACY_FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, NULL, NULL) \ |
| 135 | LEGACY_FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, NULL, NULL) \ |
| 136 | LEGACY_FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, NULL, NULL) \ |
| 137 | 137 | LEGACY_FLOPPY_OPTION( d88, "d77,d88,1dd", "D88 Floppy Disk image", d88_dsk_identify, d88_dsk_construct, NULL, NULL) \ |
| 138 | 138 | LEGACY_FLOPPY_OPTIONS_END0 |
| 139 | 139 | |
| 140 | 140 | LEGACY_FLOPPY_OPTIONS_EXTERN(default); |
| 141 | 141 | |
| 142 | | #define PARAM_END '\0' |
| 143 | | #define PARAM_HEADS 'H' |
| 144 | | #define PARAM_TRACKS 'T' |
| 145 | | #define PARAM_SECTORS 'S' |
| 146 | | #define PARAM_SECTOR_LENGTH 'L' |
| 147 | | #define PARAM_INTERLEAVE 'I' |
| 148 | | #define PARAM_FIRST_SECTOR_ID 'F' |
| 142 | #define PARAM_END '\0' |
| 143 | #define PARAM_HEADS 'H' |
| 144 | #define PARAM_TRACKS 'T' |
| 145 | #define PARAM_SECTORS 'S' |
| 146 | #define PARAM_SECTOR_LENGTH 'L' |
| 147 | #define PARAM_INTERLEAVE 'I' |
| 148 | #define PARAM_FIRST_SECTOR_ID 'F' |
| 149 | 149 | |
| 150 | | #define HEADS(range) "H" #range |
| 151 | | #define TRACKS(range) "T" #range |
| 152 | | #define SECTORS(range) "S" #range |
| 153 | | #define SECTOR_LENGTH(range) "L" #range |
| 154 | | #define INTERLEAVE(range) "I" #range |
| 155 | | #define FIRST_SECTOR_ID(range) "F" #range |
| 150 | #define HEADS(range) "H" #range |
| 151 | #define TRACKS(range) "T" #range |
| 152 | #define SECTORS(range) "S" #range |
| 153 | #define SECTOR_LENGTH(range) "L" #range |
| 154 | #define INTERLEAVE(range) "I" #range |
| 155 | #define FIRST_SECTOR_ID(range) "F" #range |
| 156 | 156 | |
| 157 | 157 | |
| 158 | 158 | /*************************************************************************** |
| r19188 | r19189 | |
| 227 | 227 | virtual ~floppy_image_format_t(); |
| 228 | 228 | |
| 229 | 229 | /*! @brief Identify an image. |
| 230 | | The identify function tests if the image is valid |
| 231 | | for this particular format. |
| 232 | | @param io buffer containing the image data. |
| 233 | | @param form_factor Physical form factor of disk, from the enum |
| 234 | | in floppy_image |
| 235 | | @return 1 if image valid, 0 otherwise. |
| 236 | | */ |
| 230 | The identify function tests if the image is valid |
| 231 | for this particular format. |
| 232 | @param io buffer containing the image data. |
| 233 | @param form_factor Physical form factor of disk, from the enum |
| 234 | in floppy_image |
| 235 | @return 1 if image valid, 0 otherwise. |
| 236 | */ |
| 237 | 237 | virtual int identify(io_generic *io, UINT32 form_factor) = 0; |
| 238 | 238 | |
| 239 | 239 | /*! @brief Load an image. |
| 240 | | The load function opens an image file and converts it to the |
| 241 | | internal MESS floppy representation. |
| 242 | | @param io source buffer containing the image data. |
| 243 | | @param form_factor Physical form factor of disk, from the enum |
| 244 | | in floppy_image |
| 245 | | @param image output buffer for data in MESS internal format. |
| 246 | | @return true on success, false otherwise. |
| 247 | | */ |
| 248 | | virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image) = 0; |
| 240 | The load function opens an image file and converts it to the |
| 241 | internal MESS floppy representation. |
| 242 | @param io source buffer containing the image data. |
| 243 | @param form_factor Physical form factor of disk, from the enum |
| 244 | in floppy_image |
| 245 | @param image output buffer for data in MESS internal format. |
| 246 | @return true on success, false otherwise. |
| 247 | */ |
| 248 | virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image) = 0; |
| 249 | 249 | |
| 250 | | /*! @brief Save an image. |
| 251 | | The save function writes back an image from the MESS internal |
| 252 | | floppy representation to the appropriate format on disk. |
| 253 | | @param io output buffer for the data in the on-disk format. |
| 254 | | @param image source buffer containing data in MESS internal format. |
| 255 | | @return true on success, false otherwise. |
| 256 | | */ |
| 250 | /*! @brief Save an image. |
| 251 | The save function writes back an image from the MESS internal |
| 252 | floppy representation to the appropriate format on disk. |
| 253 | @param io output buffer for the data in the on-disk format. |
| 254 | @param image source buffer containing data in MESS internal format. |
| 255 | @return true on success, false otherwise. |
| 256 | */ |
| 257 | 257 | virtual bool save(io_generic *io, floppy_image *image); |
| 258 | 258 | |
| 259 | 259 | //! @returns string containing name of format. |
| r19188 | r19189 | |
| 293 | 293 | //! A vector of these structures describes one track. |
| 294 | 294 | |
| 295 | 295 | struct desc_e { |
| 296 | | int type, //!< An opcode |
| 297 | | p1, //!< first param |
| 298 | | p2; //!< second param |
| 296 | int type, //!< An opcode |
| 297 | p1, //!< first param |
| 298 | p2; //!< second param |
| 299 | 299 | }; |
| 300 | 300 | |
| 301 | 301 | //! Opcodes of the format description language used by generate_track() |
| r19188 | r19189 | |
| 346 | 346 | |
| 347 | 347 | |
| 348 | 348 | /*! @brief Generate one track according to the description vector. |
| 349 | | @param desc track data description |
| 350 | | @param track |
| 351 | | @param head |
| 352 | | @param sect a vector indexed by sector id. |
| 353 | | @param sect_count number of sectors. |
| 354 | | @param track_size in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm. |
| 355 | | @param image |
| 356 | | */ |
| 349 | @param desc track data description |
| 350 | @param track |
| 351 | @param head |
| 352 | @param sect a vector indexed by sector id. |
| 353 | @param sect_count number of sectors. |
| 354 | @param track_size in _cells_, i.e. 100000 for a usual 2us-per-cell track at 300rpm. |
| 355 | @param image |
| 356 | */ |
| 357 | 357 | void generate_track(const desc_e *desc, int track, int head, const desc_s *sect, int sect_count, int track_size, floppy_image *image); |
| 358 | 358 | |
| 359 | 359 | /*! @brief Generate a track from cell binary values, MSB-first. |
| 360 | | @param track |
| 361 | | @param head |
| 362 | | @param trackbuf track input buffer. |
| 363 | | @param track_size in cells, not bytes. |
| 364 | | @param image |
| 365 | | */ |
| 360 | @param track |
| 361 | @param head |
| 362 | @param trackbuf track input buffer. |
| 363 | @param track_size in cells, not bytes. |
| 364 | @param image |
| 365 | */ |
| 366 | 366 | void generate_track_from_bitstream(int track, int head, const UINT8 *trackbuf, int track_size, floppy_image *image); |
| 367 | 367 | |
| 368 | 368 | //! @brief Generate a track from cell level values (0/1/W/D/N). |
| 369 | 369 | |
| 370 | 370 | /*! Note that this function needs to be able to split cells in two, |
| 371 | | so no time value should be less than 2, and even values are a |
| 372 | | good idea. |
| 373 | | */ |
| 371 | so no time value should be less than 2, and even values are a |
| 372 | good idea. |
| 373 | */ |
| 374 | 374 | /*! @param track |
| 375 | | @param head |
| 376 | | @param trackbuf track input buffer. |
| 377 | | @param track_size in cells, not bytes. |
| 378 | | @param splice_pos is the position of the track splice. For normal |
| 379 | | formats, use -1. For protected formats, you're supposed to |
| 380 | | know. trackbuf may be modified at that position or after. |
| 381 | | @param image |
| 382 | | */ |
| 375 | @param head |
| 376 | @param trackbuf track input buffer. |
| 377 | @param track_size in cells, not bytes. |
| 378 | @param splice_pos is the position of the track splice. For normal |
| 379 | formats, use -1. For protected formats, you're supposed to |
| 380 | know. trackbuf may be modified at that position or after. |
| 381 | @param image |
| 382 | */ |
| 383 | 383 | void generate_track_from_levels(int track, int head, UINT32 *trackbuf, int track_size, int splice_pos, floppy_image *image); |
| 384 | 384 | |
| 385 | 385 | //! Normalize the times in a cell buffer to sum up to 200000000 |
| r19188 | r19189 | |
| 421 | 421 | // **** Writer helpers **** |
| 422 | 422 | |
| 423 | 423 | /*! @brief Rebuild a cell bitstream for a track. |
| 424 | | Takes the cell standard |
| 425 | | angular size as a parameter, gives out a msb-first bitstream. |
| 424 | Takes the cell standard |
| 425 | angular size as a parameter, gives out a msb-first bitstream. |
| 426 | 426 | |
| 427 | | Beware that fuzzy bits will always give out the same value. |
| 428 | | @param track |
| 429 | | @param head |
| 430 | | @param cell_size |
| 431 | | @param trackbuf Output buffer size should be 34% more than the nominal number |
| 432 | | of cells (the dpll tolerates a cell size down to 75% of the |
| 433 | | nominal one, with gives a cell count of 1/0.75=1.333... times |
| 434 | | the nominal one). |
| 435 | | @param track_size Output size is given in bits (cells). |
| 436 | | @param image |
| 437 | | */ |
| 427 | Beware that fuzzy bits will always give out the same value. |
| 428 | @param track |
| 429 | @param head |
| 430 | @param cell_size |
| 431 | @param trackbuf Output buffer size should be 34% more than the nominal number |
| 432 | of cells (the dpll tolerates a cell size down to 75% of the |
| 433 | nominal one, with gives a cell count of 1/0.75=1.333... times |
| 434 | the nominal one). |
| 435 | @param track_size Output size is given in bits (cells). |
| 436 | @param image |
| 437 | */ |
| 438 | 438 | /*! @verbatim |
| 439 | | Computing the standard angular size of a cell is |
| 440 | | simple. Noting: |
| 441 | | d = standard cell duration in microseconds |
| 442 | | r = motor rotational speed in rpm |
| 443 | | then: |
| 444 | | a = r * d * 10 / 3. |
| 445 | | Some values: |
| 446 | | Type Cell RPM Size |
| 439 | Computing the standard angular size of a cell is |
| 440 | simple. Noting: |
| 441 | d = standard cell duration in microseconds |
| 442 | r = motor rotational speed in rpm |
| 443 | then: |
| 444 | a = r * d * 10 / 3. |
| 445 | Some values: |
| 446 | Type Cell RPM Size |
| 447 | 447 | |
| 448 | | C1541 tr 1-17 3.25 300 3250 |
| 449 | | C1541 tr 18-24 3.50 300 3500 |
| 450 | | C1541 tr 25-30 3.75 300 3750 |
| 451 | | C1541 tr 31+ 4.00 300 4000 |
| 452 | | 5.25" SD 4 300 4000 |
| 453 | | 5.25" DD 2 300 2000 |
| 454 | | 5.25" HD 1 360 1200 |
| 455 | | 3.5" SD 4 300 4000 |
| 456 | | 3.5" DD 2 300 2000 |
| 457 | | 3.5" HD 1 300 1000 |
| 458 | | 3.5" ED 0.5 300 500 |
| 459 | | @endverbatim |
| 460 | | */ |
| 448 | C1541 tr 1-17 3.25 300 3250 |
| 449 | C1541 tr 18-24 3.50 300 3500 |
| 450 | C1541 tr 25-30 3.75 300 3750 |
| 451 | C1541 tr 31+ 4.00 300 4000 |
| 452 | 5.25" SD 4 300 4000 |
| 453 | 5.25" DD 2 300 2000 |
| 454 | 5.25" HD 1 360 1200 |
| 455 | 3.5" SD 4 300 4000 |
| 456 | 3.5" DD 2 300 2000 |
| 457 | 3.5" HD 1 300 1000 |
| 458 | 3.5" ED 0.5 300 500 |
| 459 | @endverbatim |
| 460 | */ |
| 461 | 461 | |
| 462 | 462 | void generate_bitstream_from_track(int track, int head, int cell_size, UINT8 *trackbuf, int &track_size, floppy_image *image); |
| 463 | 463 | |
| 464 | 464 | //! Defines a standard sector for extracting. |
| 465 | 465 | struct desc_xs { |
| 466 | | int track, //!< Track for this sector |
| 467 | | head, //!< Head for this sector |
| 468 | | size; //!< Size of this sector |
| 466 | int track, //!< Track for this sector |
| 467 | head, //!< Head for this sector |
| 468 | size; //!< Size of this sector |
| 469 | 469 | const UINT8 *data; //!< Data within this sector |
| 470 | 470 | }; |
| 471 | 471 | |
| r19188 | r19189 | |
| 501 | 501 | |
| 502 | 502 | //! @brief Get a geometry (including sectors) from an image. |
| 503 | 503 | |
| 504 | | //! PC-type sectors with MFM encoding |
| 504 | //! PC-type sectors with MFM encoding |
| 505 | 505 | void get_geometry_mfm_pc(floppy_image *image, int cell_size, int &track_count, int &head_count, int §or_count); |
| 506 | 506 | //! PC-type sectors with FM encoding |
| 507 | 507 | void get_geometry_fm_pc(floppy_image *image, int cell_size, int &track_count, int &head_count, int §or_count); |
| r19188 | r19189 | |
| 621 | 621 | enum { |
| 622 | 622 | TIME_MASK = 0x0fffffff, |
| 623 | 623 | MG_MASK = 0xf0000000, |
| 624 | | MG_SHIFT = 28, //!< Bitshift constant for magnetic orientation data |
| 625 | | MG_A = (0 << MG_SHIFT), //!< - 0, MG_A -> Magnetic orientation A |
| 626 | | MG_B = (1 << MG_SHIFT), //!< - 1, MG_B -> Magnetic orientation B |
| 627 | | MG_N = (2 << MG_SHIFT), //!< - 2, MG_N -> Non-magnetized zone (neutral) |
| 628 | | MG_D = (3 << MG_SHIFT) //!< - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing |
| 624 | MG_SHIFT = 28, //!< Bitshift constant for magnetic orientation data |
| 625 | MG_A = (0 << MG_SHIFT), //!< - 0, MG_A -> Magnetic orientation A |
| 626 | MG_B = (1 << MG_SHIFT), //!< - 1, MG_B -> Magnetic orientation B |
| 627 | MG_N = (2 << MG_SHIFT), //!< - 2, MG_N -> Non-magnetized zone (neutral) |
| 628 | MG_D = (3 << MG_SHIFT) //!< - 3, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing |
| 629 | 629 | }; |
| 630 | 630 | |
| 631 | 631 | |
| r19188 | r19189 | |
| 643 | 643 | SSSD = 0x44535353, //!< "SSSD", Single-sided single-density |
| 644 | 644 | SSDD = 0x44445353, //!< "SSDD", Single-sided double-density |
| 645 | 645 | SSQD = 0x44515353, //!< "SSQD", Single-sided quad-density |
| 646 | DSSD = 0x44535344, //!< "DSSD", Double-sided single-density |
| 646 | 647 | DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K in 3.5, 360K in 5.25) |
| 647 | 648 | DSQD = 0x44515344, //!< "DSQD", Double-sided quad-density (720K in 5.25, means DD+80 tracks) |
| 648 | 649 | DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K) |
| r19188 | r19189 | |
| 654 | 655 | |
| 655 | 656 | //! floppy_image constructor |
| 656 | 657 | /*! |
| 657 | | @param _tracks number of tracks. |
| 658 | | @param _heads number of heads. |
| 659 | | @param _form_factor form factor of drive (from enum) |
| 660 | | */ |
| 658 | @param _tracks number of tracks. |
| 659 | @param _heads number of heads. |
| 660 | @param _form_factor form factor of drive (from enum) |
| 661 | */ |
| 661 | 662 | floppy_image(int tracks, int heads, UINT32 form_factor); |
| 662 | 663 | virtual ~floppy_image(); |
| 663 | 664 | |
| r19188 | r19189 | |
| 669 | 670 | void set_variant(UINT32 v) { variant = v; } |
| 670 | 671 | |
| 671 | 672 | /*! |
| 672 | | @param track |
| 673 | | @param head |
| 674 | | @param size size of this track |
| 675 | | */ |
| 673 | @param track |
| 674 | @param head |
| 675 | @param size size of this track |
| 676 | */ |
| 676 | 677 | void set_track_size(int track, int head, UINT32 size) { track_size[track][head] = size; ensure_alloc(track, head); } |
| 677 | 678 | |
| 678 | | /*! |
| 679 | | @param track track number |
| 680 | | @param head head number |
| 681 | | @return a pointer to the data buffer for this track and head |
| 682 | | */ |
| 679 | /*! |
| 680 | @param track track number |
| 681 | @param head head number |
| 682 | @return a pointer to the data buffer for this track and head |
| 683 | */ |
| 683 | 684 | UINT32 *get_buffer(int track, int head) { return cell_data[track][head]; } |
| 684 | 685 | //! @return the track size |
| 685 | 686 | //! @param track |
| r19188 | r19189 | |
| 694 | 695 | //! representation is the angular position relative to the index. |
| 695 | 696 | |
| 696 | 697 | /*! @param track |
| 697 | | @param head |
| 698 | | @param pos the position |
| 699 | | */ |
| 698 | @param head |
| 699 | @param pos the position |
| 700 | */ |
| 700 | 701 | void set_write_splice_position(int track, int head, UINT32 pos) { write_splice[track][head] = pos; } |
| 701 | 702 | //! @return the current write splice position. |
| 702 | 703 | UINT32 get_write_splice_position(int track, int head) const { return write_splice[track][head]; } |
| r19188 | r19189 | |
| 732 | 733 | }; |
| 733 | 734 | |
| 734 | 735 | #endif /* FLOPIMG_H */ |
| 735 | | |
trunk/src/emu/imagedev/floppy.c
| r19188 | r19189 | |
| 19 | 19 | const device_type FLOPPY_35_HD = &device_creator<floppy_35_hd>; |
| 20 | 20 | const device_type FLOPPY_35_ED = &device_creator<floppy_35_ed>; |
| 21 | 21 | const device_type FLOPPY_525_SSSD_35T = &device_creator<floppy_525_sssd_35t>; |
| 22 | const device_type FLOPPY_525_SD_35T = &device_creator<floppy_525_sd_35t>; |
| 22 | 23 | const device_type FLOPPY_525_SSSD = &device_creator<floppy_525_sssd>; |
| 24 | const device_type FLOPPY_525_SD = &device_creator<floppy_525_sd>; |
| 23 | 25 | const device_type FLOPPY_525_SSDD = &device_creator<floppy_525_ssdd>; |
| 24 | 26 | const device_type FLOPPY_525_DD = &device_creator<floppy_525_dd>; |
| 25 | 27 | const device_type FLOPPY_525_QD = &device_creator<floppy_525_qd>; |
| r19188 | r19189 | |
| 74 | 76 | //------------------------------------------------- |
| 75 | 77 | |
| 76 | 78 | floppy_image_device::floppy_image_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) |
| 77 | | : device_t(mconfig, type, name, tag, owner, clock), |
| 78 | | device_image_interface(mconfig, *this), |
| 79 | | device_slot_card_interface(mconfig, *this), |
| 80 | | image(NULL) |
| 79 | : device_t(mconfig, type, name, tag, owner, clock), |
| 80 | device_image_interface(mconfig, *this), |
| 81 | device_slot_card_interface(mconfig, *this), |
| 82 | image(NULL) |
| 81 | 83 | { |
| 82 | 84 | extension_list[0] = '\0'; |
| 83 | 85 | } |
| r19188 | r19189 | |
| 108 | 110 | void floppy_image_device::set_formats(const floppy_format_type *formats) |
| 109 | 111 | { |
| 110 | 112 | image_device_format **formatptr; |
| 111 | | image_device_format *format; |
| 112 | | formatptr = &m_formatlist; |
| 113 | image_device_format *format; |
| 114 | formatptr = &m_formatlist; |
| 113 | 115 | extension_list[0] = '\0'; |
| 114 | 116 | fif_list = 0; |
| 115 | 117 | for(int cnt=0; formats[cnt]; cnt++) |
| r19188 | r19189 | |
| 390 | 392 | |
| 391 | 393 | if (image) image->get_actual_geometry(tracks, heads); |
| 392 | 394 | |
| 393 | | return heads == 2; |
| 395 | return heads == 1; |
| 394 | 396 | } |
| 395 | 397 | |
| 396 | 398 | void floppy_image_device::stp_w(int state) |
| 397 | 399 | { |
| 398 | | if ( stp != state ) { |
| 400 | if ( stp != state ) { |
| 399 | 401 | stp = state; |
| 400 | | if ( stp == 0 ) { |
| 402 | if ( stp == 0 ) { |
| 401 | 403 | int ocyl = cyl; |
| 402 | 404 | if ( dir ) { |
| 403 | 405 | if ( cyl ) cyl--; |
| r19188 | r19189 | |
| 966 | 968 | variants[var_count++] = floppy_image::SSSD; |
| 967 | 969 | } |
| 968 | 970 | |
| 971 | floppy_525_sd_35t::floppy_525_sd_35t(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 972 | floppy_image_device(mconfig, FLOPPY_525_SD_35T, "5.25\" single density 35-track floppy drive", tag, owner, clock) |
| 973 | { |
| 974 | } |
| 975 | |
| 976 | floppy_525_sd_35t::~floppy_525_sd_35t() |
| 977 | { |
| 978 | } |
| 979 | |
| 980 | void floppy_525_sd_35t::setup_characteristics() |
| 981 | { |
| 982 | form_factor = floppy_image::FF_525; |
| 983 | tracks = 35; |
| 984 | sides = 2; |
| 985 | set_rpm(300); |
| 986 | } |
| 987 | |
| 988 | void floppy_525_sd_35t::handled_variants(UINT32 *variants, int &var_count) const |
| 989 | { |
| 990 | var_count = 0; |
| 991 | variants[var_count++] = floppy_image::SSSD; |
| 992 | } |
| 993 | |
| 969 | 994 | floppy_525_sssd::floppy_525_sssd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 970 | 995 | floppy_image_device(mconfig, FLOPPY_525_SSSD, "5.25\" single-sided single density floppy drive", tag, owner, clock) |
| 971 | 996 | { |
| r19188 | r19189 | |
| 989 | 1014 | variants[var_count++] = floppy_image::SSSD; |
| 990 | 1015 | } |
| 991 | 1016 | |
| 1017 | floppy_525_sd::floppy_525_sd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 1018 | floppy_image_device(mconfig, FLOPPY_525_SD, "5.25\" single density floppy drive", tag, owner, clock) |
| 1019 | { |
| 1020 | } |
| 1021 | |
| 1022 | floppy_525_sd::~floppy_525_sd() |
| 1023 | { |
| 1024 | } |
| 1025 | |
| 1026 | void floppy_525_sd::setup_characteristics() |
| 1027 | { |
| 1028 | form_factor = floppy_image::FF_525; |
| 1029 | tracks = 42; |
| 1030 | sides = 2; |
| 1031 | set_rpm(300); |
| 1032 | } |
| 1033 | |
| 1034 | void floppy_525_sd::handled_variants(UINT32 *variants, int &var_count) const |
| 1035 | { |
| 1036 | var_count = 0; |
| 1037 | variants[var_count++] = floppy_image::SSSD; |
| 1038 | } |
| 1039 | |
| 992 | 1040 | floppy_525_ssdd::floppy_525_ssdd(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : |
| 993 | 1041 | floppy_image_device(mconfig, FLOPPY_525_SSDD, "5.25\" single-sided double density floppy drive", tag, owner, clock) |
| 994 | 1042 | { |