diff --git a/src/emu/imagedev/floppy.c b/src/emu/imagedev/floppy.c index 1036c5011b9..012b5be62b8 100644 --- a/src/emu/imagedev/floppy.c +++ b/src/emu/imagedev/floppy.c @@ -273,6 +273,7 @@ void floppy_image_device::device_start() mon = 1; cyl = 0; + subcyl = 0; ss = 0; stp = 1; wpt = 0; @@ -535,9 +536,51 @@ void floppy_image_device::stp_w(int state) if (dskchg==0) dskchg = 1; } } + subcyl = 0; } } +void floppy_image_device::seek_phase_w(int phases) +{ + int cur_pos = (cyl << 2) | subcyl; + int req_pos; + switch(phases) { + case 0x1: req_pos = 0; break; + case 0x3: req_pos = 1; break; + case 0x2: req_pos = 2; break; + case 0x6: req_pos = 3; break; + case 0x4: req_pos = 4; break; + case 0xc: req_pos = 5; break; + case 0x8: req_pos = 6; break; + case 0x9: req_pos = 7; break; + default: return; + } + + // Opposite phase, don't move + if(((cur_pos ^ req_pos) & 7) == 4) + return; + + int next_pos = (cur_pos & ~7) | req_pos; + if(next_pos < cur_pos-4) + next_pos += 8; + else if(next_pos > cur_pos+4) + next_pos -= 8; + if(next_pos < 0) + next_pos = 0; + else if(next_pos > (tracks-1)*4) + next_pos = (tracks-1)*4; + cyl = next_pos >> 2; + subcyl = next_pos & 3; + + if(TRACE_STEP && (next_pos != cur_pos)) + logerror("%s: track %d.%d\n", tag(), cyl, subcyl); + + /* Update disk detection if applicable */ + if (exists()) + if (dskchg==0) + dskchg = 1; +} + int floppy_image_device::find_index(UINT32 position, const UINT32 *buf, int buf_size) { int spos = (buf_size >> 1)-1; diff --git a/src/emu/imagedev/floppy.h b/src/emu/imagedev/floppy.h index c7d71c5dca6..0de3f83ce0d 100644 --- a/src/emu/imagedev/floppy.h +++ b/src/emu/imagedev/floppy.h @@ -105,6 +105,7 @@ public: bool ss_r() { return ss; } bool twosid_r(); + void seek_phase_w(int phases); void stp_w(int state); void dir_w(int state) { dir = state; } void ss_w(int state) { ss = state; } @@ -164,7 +165,7 @@ protected: attotime revolution_start_time, rev_time; UINT32 revolution_count; - int cyl; + int cyl, subcyl; bool image_dirty; int ready_counter; diff --git a/src/emu/machine/wozfdc.c b/src/emu/machine/wozfdc.c index c479aa3f370..9116b016482 100644 --- a/src/emu/machine/wozfdc.c +++ b/src/emu/machine/wozfdc.c @@ -72,7 +72,6 @@ void wozfdc_device::device_start() void wozfdc_device::device_reset() { - current_cyl = 0; floppy = NULL; active = MODE_IDLE; phases = 0x00; @@ -199,22 +198,8 @@ void wozfdc_device::phase(int ph, bool on) else phases &= ~(1 << ph); - if(floppy && active) { - int cph = current_cyl & 3; - int pcyl = current_cyl; - if(!(phases & (1 << cph))) { - if(current_cyl < 70 && (phases & (1 << ((cph+1) & 3)))) - current_cyl++; - if(current_cyl && (phases & (1 << ((cph+3) & 3)))) - current_cyl--; - if(current_cyl != pcyl && !(current_cyl & 1)) { - floppy->dir_w(current_cyl < pcyl); - floppy->stp_w(true); - floppy->stp_w(false); - floppy->stp_w(true); - } - } - } + if(floppy && active) + floppy->seek_phase_w(phases); } void wozfdc_device::control(int offset) @@ -238,10 +223,8 @@ void wozfdc_device::control(int offset) case 0x9: switch(active) { case MODE_IDLE: - if(floppy) { + if(floppy) floppy->mon_w(false); - current_cyl = floppy->get_cyl() << 1; - } active = MODE_ACTIVE; if(floppy) lss_start(); diff --git a/src/emu/machine/wozfdc.h b/src/emu/machine/wozfdc.h index 54851881f90..62e358d190c 100644 --- a/src/emu/machine/wozfdc.h +++ b/src/emu/machine/wozfdc.h @@ -60,7 +60,7 @@ private: }; const UINT8 *m_rom_p6; - UINT8 current_cyl, last_6502_write; + UINT8 last_6502_write; bool mode_write, mode_load; int active; UINT8 phases; diff --git a/src/lib/formats/flopimg.c b/src/lib/formats/flopimg.c index ca9af339518..a1c51d52bad 100644 --- a/src/lib/formats/flopimg.c +++ b/src/lib/formats/flopimg.c @@ -947,19 +947,13 @@ floppy_image::floppy_image(int _tracks, int _heads, UINT32 _form_factor) form_factor = _form_factor; variant = 0; - memset(cell_data, 0, sizeof(cell_data)); - memset(track_size, 0, sizeof(track_size)); - memset(track_alloc_size, 0, sizeof(track_alloc_size)); - memset(write_splice, 0, sizeof(write_splice)); + track_array.resize(tracks*4+1); + for(int i=0; i= 0) { for(int i=0; i<=maxh; i++) @@ -987,22 +981,29 @@ void floppy_image::get_actual_geometry(int &_tracks, int &_heads) maxh--; } head_done: - _tracks = maxt+1; + _tracks = (maxt+4)/4; _heads = maxh+1; } +int floppy_image::get_resolution() const +{ + int mask = 0; + for(int i=0; i track_alloc_size[track][head]) { - UINT32 new_size = track_size[track][head]*11/10; - UINT32 *new_array = global_alloc_array(UINT32, new_size); - if(track_alloc_size[track][head]) { - memcpy(new_array, cell_data[track][head], track_alloc_size[track][head]*4); - global_free_array(cell_data[track][head]); - } - cell_data[track][head] = new_array; - track_alloc_size[track][head] = new_size; - } + track_info &tr = track_array[track][head]; + if(tr.track_size > tr.cell_data.count()) + tr.cell_data.resize_keep_and_clear_new(tr.track_size); } const char *floppy_image::get_variant_name(UINT32 form_factor, UINT32 variant) diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h index 536c001f4ae..c35daa4d693 100644 --- a/src/lib/formats/flopimg.h +++ b/src/lib/formats/flopimg.h @@ -12,6 +12,7 @@ #include "osdcore.h" #include "ioprocs.h" #include "opresolv.h" +#include "coretmpl.h" #ifndef LOG_FORMATS #define LOG_FORMATS if (0) printf @@ -637,7 +638,13 @@ floppy_image_format_t *floppy_image_format_creator() //! form factor can be physically inserted in a reader that handles //! it. The second half indicates the variants which are usually //! detectable by the reader, such as density and number of sides. - +//! +//! Resolution is quarter-track. The optional subtrack parameter is +//! 0-3: +//! - 0 = Track itself +//! - 1 = 1st quarter track +//! - 2 = Half track +//! - 3 = 2nd quarter track class floppy_image { @@ -682,7 +689,7 @@ public: M2FM = 0x4D32464D, //!< "M2FM", modified modified frequency modulation }; -// construction/destruction + // construction/destruction //! floppy_image constructor @@ -703,21 +710,25 @@ public: /*! @param track + @param subtrack @param head @param size size of this track */ - void set_track_size(int track, int head, UINT32 size) { track_size[track][head] = size; ensure_alloc(track, head); } + void set_track_size(int track, int head, UINT32 size, int subtrack = 0) { track_array[track*4+subtrack][head].track_size = size; ensure_alloc(track*4+subtrack, head); } /*! - @param track track number + @param track + @param subtrack @param head head number @return a pointer to the data buffer for this track and head */ - UINT32 *get_buffer(int track, int head) { return cell_data[track][head]; } + UINT32 *get_buffer(int track, int head, int subtrack = 0) { return track_array[track*4+subtrack][head].cell_data; } + //! @return the track size //! @param track + //! @param subtrack //! @param head - UINT32 get_track_size(int track, int head) { return track_size[track][head]; } + UINT32 get_track_size(int track, int head, int subtrack = 0) { return track_array[track*4+subtrack][head].track_size; } //! Sets the write splice position. //! The "track splice" information indicates where to start writing @@ -727,18 +738,22 @@ public: //! representation is the angular position relative to the index. /*! @param track + @param subtrack @param head @param pos the position */ - void set_write_splice_position(int track, int head, UINT32 pos) { write_splice[track][head] = pos; } + void set_write_splice_position(int track, int head, UINT32 pos, int subtrack = 0) { track_array[track*4+subtrack][head].write_splice = pos; } //! @return the current write splice position. - UINT32 get_write_splice_position(int track, int head) const { return write_splice[track][head]; } + UINT32 get_write_splice_position(int track, int head, int subtrack = 0) const { return track_array[track*4+subtrack][head].write_splice; } //! @return the maximal geometry supported by this format. void get_maximal_geometry(int &tracks, int &heads); //! @return the current geometry of the loaded image. void get_actual_geometry(int &tracks, int &heads); + //! @return the track resolution (0=full track, 1 = half-track, 2 = quarter track) + int get_resolution() const; + //! Returns the variant name for the particular disk form factor/variant //! @param form_factor //! @param variant @@ -746,20 +761,21 @@ public: static const char *get_variant_name(UINT32 form_factor, UINT32 variant); private: - - enum { - MAX_FLOPPY_HEADS = 2, - MAX_FLOPPY_TRACKS = 84 - }; - int tracks, heads; UINT32 form_factor, variant; - UINT32 *cell_data[MAX_FLOPPY_TRACKS][MAX_FLOPPY_HEADS]; - UINT32 track_size[MAX_FLOPPY_TRACKS][MAX_FLOPPY_HEADS]; - UINT32 track_alloc_size[MAX_FLOPPY_TRACKS][MAX_FLOPPY_HEADS]; - UINT32 write_splice[MAX_FLOPPY_TRACKS][MAX_FLOPPY_HEADS]; + struct track_info { + dynamic_array cell_data; + UINT32 track_size; + UINT32 write_splice; + + track_info() { track_size = write_splice = 0; } + }; + + // track number multiplied by 4 then head + // last array size may be bigger than actual track size + dynamic_array > track_array; void ensure_alloc(int track, int head); }; diff --git a/src/lib/formats/mfi_dsk.c b/src/lib/formats/mfi_dsk.c index ccb441c7a25..4c4e023591e 100644 --- a/src/lib/formats/mfi_dsk.c +++ b/src/lib/formats/mfi_dsk.c @@ -8,10 +8,12 @@ Mess floppy image structure: - header with signature, number of cylinders, number of heads. Min - track and min head are considered to always be 0. + track and min head are considered to always be 0. The two top bits + of the cylinder count is the resolution: 0=tracks, 1=half tracks, + 2=quarter tracks. - - vector of track descriptions, looping on cylinders and sub-lopping - on heads, each description composed of: + - vector of track descriptions, looping on cylinders with the given + resolution and sub-lopping on heads, each description composed of: - offset of the track data in bytes from the start of the file - size of the compressed track data in bytes (0 for unformatted) - size of the uncompressed track data in bytes (0 for unformatted) @@ -97,7 +99,8 @@ int mfi_format::identify(io_generic *io, UINT32 form_factor) io_generic_read(io, &h, 0, sizeof(header)); if(memcmp( h.sign, sign, 16 ) == 0 && - h.cyl_count <= 160 && + (h.cyl_count & CYLINDER_MASK) <= 84 && + (h.cyl_count >> RESOLUTION_SHIFT) < 3 && h.head_count <= 2 && (!form_factor || !h.form_factor || h.form_factor == form_factor)) return 100; @@ -107,22 +110,24 @@ int mfi_format::identify(io_generic *io, UINT32 form_factor) bool mfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) { header h; - entry entries[84*2]; + entry entries[84*2*4]; io_generic_read(io, &h, 0, sizeof(header)); - io_generic_read(io, &entries, sizeof(header), h.cyl_count*h.head_count*sizeof(entry)); + int resolution = h.cyl_count >> RESOLUTION_SHIFT; + h.cyl_count &= CYLINDER_MASK; + io_generic_read(io, &entries, sizeof(header), (h.cyl_count << resolution)*h.head_count*sizeof(entry)); image->set_variant(h.variant); dynamic_buffer compressed; entry *ent = entries; - for(unsigned int cyl=0; cyl != h.cyl_count; cyl++) + for(unsigned int cyl=0; cyl <= (h.cyl_count - 1) << 2; cyl += 4 >> resolution) for(unsigned int head=0; head != h.head_count; head++) { - image->set_write_splice_position(cyl, head, ent->write_splice); + image->set_write_splice_position(cyl >> 2, head, ent->write_splice, cyl & 3); if(ent->uncompressed_size == 0) { // Unformatted track - image->set_track_size(cyl, head, 0); + image->set_track_size(cyl >> 2, head, 0, cyl & 3); ent++; continue; } @@ -132,8 +137,8 @@ bool mfi_format::load(io_generic *io, UINT32 form_factor, floppy_image *image) io_generic_read(io, compressed, ent->offset, ent->compressed_size); unsigned int cell_count = ent->uncompressed_size/4; - image->set_track_size(cyl, head, cell_count); - UINT32 *trackbuf = image->get_buffer(cyl, head); + image->set_track_size(cyl >> 2, head, cell_count, cyl & 3); + UINT32 *trackbuf = image->get_buffer(cyl >> 2, head, cyl & 3); uLongf size = ent->uncompressed_size; if(uncompress((Bytef *)trackbuf, &size, compressed, ent->compressed_size) != Z_OK) @@ -158,18 +163,19 @@ bool mfi_format::save(io_generic *io, floppy_image *image) { int tracks, heads; image->get_actual_geometry(tracks, heads); + int resolution = image->get_resolution(); int max_track_size = 0; - for(int track=0; track> resolution) for(int head=0; headget_track_size(track, head); + int tsize = image->get_track_size(track >> 2, head, track & 3); if(tsize > max_track_size) max_track_size = tsize; } header h; - entry entries[84*2]; + entry entries[84*2*4]; memcpy(h.sign, sign, 16); - h.cyl_count = tracks; + h.cyl_count = tracks | (resolution << RESOLUTION_SHIFT); h.head_count = heads; h.form_factor = image->get_form_factor(); h.variant = image->get_variant(); @@ -178,20 +184,20 @@ bool mfi_format::save(io_generic *io, floppy_image *image) memset(entries, 0, sizeof(entries)); - int pos = sizeof(header) + tracks*heads*sizeof(entry); + int pos = sizeof(header) + (tracks << resolution)*heads*sizeof(entry); int epos = 0; UINT32 *precomp = global_alloc_array(UINT32, max_track_size); UINT8 *postcomp = global_alloc_array(UINT8, max_track_size*4 + 1000); - for(int track=0; track> resolution) for(int head=0; headget_track_size(track, head); + int tsize = image->get_track_size(track >> 2, head, track & 3); if(!tsize) { epos++; continue; } - memcpy(precomp, image->get_buffer(track, head), tsize*4); + memcpy(precomp, image->get_buffer(track >> 2, head, track & 3), tsize*4); for(int j=0; jget_write_splice_position(track, head); + entries[epos].write_splice = image->get_write_splice_position(track >> 2, head, track & 3); epos++; io_generic_write(io, postcomp, pos, csize); pos += csize; } - io_generic_write(io, entries, sizeof(header), tracks*heads*sizeof(entry)); + io_generic_write(io, entries, sizeof(header), (tracks << resolution)*heads*sizeof(entry)); return true; } diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h index 7f3739e25b2..cca3fce527e 100644 --- a/src/lib/formats/mfi_dsk.h +++ b/src/lib/formats/mfi_dsk.h @@ -26,7 +26,10 @@ private: MG_A = (0 << MG_SHIFT), MG_B = (1 << MG_SHIFT), MG_N = (2 << MG_SHIFT), - MG_D = (3 << MG_SHIFT) + MG_D = (3 << MG_SHIFT), + + RESOLUTION_SHIFT = 30, + CYLINDER_MASK = 0x3fffffff }; static const char sign[16];