Previous 199869 Revisions Next

r18860 Monday 5th November, 2012 at 13:22:55 UTC by O. Galibert
(mess) Add a generic wd format [O. Galibert]
[src/lib]lib.mak
[src/lib/formats]wd177x_dsk.c wd177x_dsk.h

trunk/src/lib/formats/wd177x_dsk.c
r18859r18860
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
34/*********************************************************************
35
36    formats/wd177x_dsk.h
37
38    helper for simple wd177x-formatted disk images
39
40*********************************************************************/
41
42#include "emu.h"
43#include "formats/wd177x_dsk.h"
44
45wd177x_format::wd177x_format(const format *_formats)
46{
47   formats = _formats;
48}
49
50int wd177x_format::find_size(io_generic *io, UINT32 form_factor)
51{
52   int size = io_generic_size(io);
53   for(int i=0; formats[i].form_factor; i++) {
54      const format &f = formats[i];
55      if(form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
56         continue;
57
58      if(size == compute_track_size(f) * f.track_count * f.head_count)
59         return i;
60   }
61   return -1;
62}
63
64int wd177x_format::identify(io_generic *io, UINT32 form_factor)
65{
66   int type = find_size(io, form_factor);
67
68   if(type != -1)
69      return 50;
70   return 0;
71}
72
73int wd177x_format::compute_track_size(const format &f) const
74{
75   int track_size;
76   if(f.sector_base_size)
77      track_size = f.sector_base_size * f.sector_count;
78   else {
79      track_size = 0;
80      for(int i=0; i != f.sector_count; i++)
81         track_size += f.per_sector_size[i];
82   }
83   return track_size;
84}
85
86void wd177x_format::build_sector_description(const format &f, UINT8 *sectdata, desc_s *sectors) const
87{
88   if(f.sector_base_id == -1) {
89      for(int i=0; i<f.sector_count; i++) {
90         int cur_offset = 0;
91         for(int j=0; j<f.sector_count; j++)
92            if(f.per_sector_id[j] < f.per_sector_id[i])
93               cur_offset += f.sector_base_size ? f.sector_base_size : f.per_sector_size[j];
94         sectors[i].data = sectdata + cur_offset;
95         sectors[i].size = f.sector_base_size ? f.sector_base_size : f.per_sector_size[i];
96         sectors[i].sector_id = f.per_sector_id[i];
97      }
98   } else {
99      int cur_offset = 0;
100      for(int i=0; i<f.sector_count; i++) {
101         sectors[i].data = sectdata + cur_offset;
102         sectors[i].size = f.sector_base_size ? f.sector_base_size : f.per_sector_size[i];
103         cur_offset += sectors[i].size;
104         sectors[i].sector_id = i + f.sector_base_id;
105      }
106   }
107}
108
109bool wd177x_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
110{
111   int type = find_size(io, form_factor);
112   if(type == -1)
113      return false;
114
115   const format &f = formats[type];
116
117   floppy_image_format_t::desc_e desc[] = {
118      /* 00 */ { MFM, 0x4e, f.gap_1 },
119      /* 01 */ { SECTOR_LOOP_START, 0, f.sector_count-1 },
120      /* 02 */ {   MFM, 0x00, 12 },
121      /* 03 */ {   CRC_CCITT_START, 1 },
122      /* 04 */ {     RAW, 0x4489, 3 },
123      /* 05 */ {     MFM, 0xfe, 1 },
124      /* 06 */ {     TRACK_ID },
125      /* 07 */ {     HEAD_ID },
126      /* 08 */ {     SECTOR_ID },
127      /* 09 */ {     SIZE_ID },
128      /* 10 */ {   CRC_END, 1 },
129      /* 11 */ {   CRC, 1 },
130      /* 12 */ {   MFM, 0x4e, f.gap_2 },
131      /* 13 */ {   MFM, 0x00, 12 },
132      /* 14 */ {   CRC_CCITT_START, 2 },
133      /* 15 */ {     RAW, 0x4489, 3 },
134      /* 16 */ {     MFM, 0xfb, 1 },
135      /* 17 */ {     SECTOR_DATA, -1 },
136      /* 18 */ {   CRC_END, 2 },
137      /* 19 */ {   CRC, 2 },
138      /* 20 */ {   MFM, 0x4e, f.gap_3 },
139      /* 21 */ { SECTOR_LOOP_END },
140      /* 22 */ { MFM, 0x4e, 0 },
141      /* 23 */ { RAWBITS, 0x9254, 0 },
142      /* 24 */ { END }
143   };
144
145   int current_size = f.gap_1*16;
146   if(f.sector_base_size)
147      current_size += f.sector_base_size * f.sector_count * 16;
148   else {
149      for(int j=0; j != f.sector_count; j++)
150         current_size += f.per_sector_size[j] * 16;
151   }
152   current_size += (12+3+1+4+2+f.gap_2+12+3+1+2+f.gap_3) * f.sector_count * 16;
153
154   int total_size = 200000000/f.cell_size;
155   int remaining_size = total_size - current_size;
156   if(remaining_size < 0)
157      throw emu_fatalerror("wd177x_format: Incorrect track layout, max_size=%d, current_size=%d", total_size, current_size);
158
159   // Fixup the end gap
160   desc[22].p2 = remaining_size / 16;
161   desc[23].p2 = remaining_size & 15;
162   desc[23].p1 >>= 16-(remaining_size & 15);
163
164   int track_size = compute_track_size(f);
165
166   UINT8 sectdata[40*512];
167   desc_s sectors[40];
168   build_sector_description(f, sectdata, sectors);
169
170   for(int track=0; track < f.track_count; track++)
171      for(int head=0; head < f.head_count; head++) {
172         io_generic_read(io, sectdata, (track*f.head_count + head)*track_size, track_size);
173         generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
174      }
175
176   image->set_variant(f.variant);
177
178   return true;
179}
180
181bool wd177x_format::supports_save() const
182{
183   return true;
184}
185
186bool wd177x_format::save(io_generic *io, floppy_image *image)
187{
188   // Count the number of formats
189   int formats_count;
190   for(formats_count=0; formats[formats_count].form_factor; formats_count++);
191
192   // Allocate the storage for the list of testable formats for a
193   // given cell size
194   int *candidates = global_alloc_array(int, formats_count);
195
196   // Format we're finally choosing
197   int chosen_candidate = -1;
198
199   // Previously tested cell size
200   int min_cell_size = 0;
201   for(;;) {
202      // Build the list of all formats for the immediatly superior cell size
203      int cur_cell_size = 0;
204      int candidates_count = 0;
205      for(int i=0; i != formats_count; i++) {
206         if(image->get_form_factor() == floppy_image::FF_UNKNOWN ||
207            image->get_form_factor() == formats[i].form_factor) {
208            if(formats[i].cell_size == cur_cell_size)
209               candidates[candidates_count++] = i;
210            else if((!cur_cell_size || formats[i].cell_size < cur_cell_size) &&
211                  formats[i].cell_size > min_cell_size) {
212               candidates[0] = i;
213               candidates_count = 1;
214               cur_cell_size = formats[i].cell_size;
215            }
216         }
217      }
218
219      min_cell_size = cur_cell_size;
220
221      // No candidates with a cell size bigger than the previously
222      // tested one, we're done
223      if(!candidates_count)
224         break;
225
226      // Filter with track 0 head 0
227      check_compatibility(image, candidates, candidates_count);
228
229      // Nobody matches, try with the next cell size
230      if(!candidates_count)
231         continue;
232
233      // We have a match at that cell size, we just need to find the
234      // best one given the geometry
235
236      // If there's only one, we're done
237      if(candidates_count == 1) {
238         chosen_candidate = candidates[0];
239         break;
240      }
241
242      // Otherwise, find the best
243      int tracks, heads;
244      image->get_actual_geometry(tracks, heads);
245      chosen_candidate = candidates[0];
246      for(int i=1; i != candidates_count; i++) {
247         const format &cc = formats[chosen_candidate];
248         const format &cn = formats[candidates[i]];
249
250         // Handling enough sides is better than not
251         if(cn.head_count >= heads && cc.head_count < heads)
252            goto change;
253         else if(cc.head_count >= heads && cn.head_count < heads)
254            goto dont_change;
255
256         // Since we're limited to two heads, at that point head
257         // count is identical for both formats.
258
259         // Handling enough tracks is better than not
260         if(cn.track_count >= tracks && cc.track_count < tracks)
261            goto change;
262         else if(cn.track_count >= tracks && cc.track_count < tracks)
263            goto dont_change;
264
265         // Both are on the same side of the track count, so closest is best
266         if(cc.track_count < tracks && cn.track_count > cc.track_count)
267            goto change;
268         if(cc.track_count >= tracks && cn.track_count < cc.track_count)
269            goto change;
270         goto dont_change;
271
272      change:
273         chosen_candidate = candidates[i];
274      dont_change:
275         ;
276      }
277      // We have a winner, bail out
278      break;
279   }
280
281   // No match, pick the first one and be done with it
282   if(chosen_candidate == -1)
283      chosen_candidate = 0;
284
285
286   const format &f = formats[chosen_candidate];
287   int track_size = compute_track_size(f);
288
289   UINT8 sectdata[40*512];
290   desc_s sectors[40];
291   build_sector_description(f, sectdata, sectors);
292
293   for(int track=0; track < f.track_count; track++)
294      for(int head=0; head < f.head_count; head++) {
295         extract_sectors(image, f, sectors, track, head);
296         io_generic_write(io, sectdata, (track*f.head_count + head)*track_size, track_size);
297      }
298
299   return true;
300}
301
302void wd177x_format::check_compatibility(floppy_image *image, int *candidates, int &candidates_count)
303{
304   UINT8 bitstream[500000/8];
305   UINT8 sectdata[50000];
306   desc_xs sectors[256];
307   int track_size;
308
309   // Extract the sectors
310   generate_bitstream_from_track(0, 0, formats[candidates[0]].cell_size, bitstream, track_size, image);
311   extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
312
313   // Check compatibility with every candidate, copy in-place
314   int *ok_cands = candidates;
315   for(int i=0; i != candidates_count; i++) {
316      const format &f = formats[candidates[i]];
317      int ns = 0;
318      for(int j=0; j<256; j++)
319         if(sectors[j].data) {
320            int sid;
321            if(f.sector_base_id == -1) {
322               for(sid=0; sid < f.sector_count; sid++)
323                  if(f.per_sector_id[sid] == j)
324                     break;
325            } else
326               sid = j - f.sector_base_id;
327            if(sid < 0 || sid > f.sector_count)
328               goto fail;
329            if(f.sector_base_size) {
330               if(sectors[j].size != f.sector_base_size)
331                  goto fail;
332            } else {
333               if(sectors[j].size != f.per_sector_size[sid])
334                  goto fail;
335            }
336            ns++;
337         }
338      if(ns == f.sector_count)
339         *ok_cands++ = candidates[i];
340   fail:
341      ;
342   }
343   candidates_count = ok_cands - candidates;
344}
345
346
347void wd177x_format::extract_sectors(floppy_image *image, const format &f, desc_s *sdesc, int track, int head)
348{
349   UINT8 bitstream[500000/8];
350   UINT8 sectdata[50000];
351   desc_xs sectors[256];
352   int track_size;
353
354   // Extract the sectors
355   generate_bitstream_from_track(track, head, f.cell_size, bitstream, track_size, image);
356   extract_sectors_from_bitstream_mfm_pc(bitstream, track_size, sectors, sectdata, sizeof(sectdata));
357
358   for(int i=0; i<f.sector_count; i++) {
359      desc_s &ds = sdesc[i];
360      desc_xs &xs = sectors[ds.sector_id];
361      if(!xs.data)
362         memset((void *)ds.data, 0, ds.size);
363      else if(xs.size < ds.size) {
364         memcpy((void *)ds.data, xs.data, xs.size);
365         memset((UINT8 *)ds.data + xs.size, 0, xs.size - ds.size);
366      } else
367         memcpy((void *)ds.data, xs.data, ds.size);
368   }
369}
trunk/src/lib/formats/wd177x_dsk.h
r18859r18860
1/*********************************************************************
2
3    formats/wd177x_sk.h
4
5    helper for simple wd177x-formatted disk images
6
7*********************************************************************/
8
9#ifndef WD177X_DSK_H
10#define WD177X_DSK_H
11
12#include "flopimg.h"
13
14class wd177x_format : public floppy_image_format_t
15{
16public:
17   struct format {
18      UINT32 form_factor;      // See floppy_image for possible values
19      UINT32 variant;          // See floppy_image for possible values
20
21      int cell_size;           // See floppy_image_format_t for details
22      int sector_count;
23      int track_count;
24      int head_count;
25      int sector_base_size;
26      int per_sector_size[40]; // if sector_base_size is 0
27      int sector_base_id;      // 0 or 1 usually, -1 if there's interleave
28      int per_sector_id[40];   // if sector_base_id is -1.  If both per are used, then sector per_sector_id[i] has size per_sector_size[i]
29      int gap_1;               // Usually around 544 - number of 4e between index and first IDAM sync
30      int gap_2;               // 22 for <=1.44Mb, 41 for 2.88Mb - number of 4e between sector header and data sync
31      int gap_3;               // Usually 84 - number of 4e between sector crc and next IDAM
32   };
33
34   // End the array with {}
35   wd177x_format(const format *formats);
36
37   virtual int identify(io_generic *io, UINT32 form_factor);
38   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
39   virtual bool save(io_generic *io, floppy_image *image);
40   virtual bool supports_save() const;
41
42private:
43   const format *formats;
44   int find_size(io_generic *io, UINT32 form_factor);
45   int compute_track_size(const format &f) const;
46   void build_sector_description(const format &d, UINT8 *sectdata, desc_s *sectors) const;
47   void check_compatibility(floppy_image *image, int *candidates, int &candidates_count);
48   void extract_sectors(floppy_image *image, const format &f, desc_s *sdesc, int track, int head);
49};
50
51#endif /* WD177X_DSK_H */
trunk/src/lib/lib.mak
r18859r18860
172172   $(LIBOBJ)/formats/tvc_cas.o      \
173173   $(LIBOBJ)/formats/tzx_cas.o      \
174174   $(LIBOBJ)/formats/uef_cas.o      \
175   $(LIBOBJ)/formats/upd765_dsk.o      \
175   $(LIBOBJ)/formats/upd765_dsk.o   \
176176   $(LIBOBJ)/formats/vg5k_cas.o   \
177177   $(LIBOBJ)/formats/vt_cas.o      \
178178   $(LIBOBJ)/formats/vt_dsk.o      \
179179   $(LIBOBJ)/formats/vtech1_dsk.o   \
180180   $(LIBOBJ)/formats/wavfile.o      \
181   $(LIBOBJ)/formats/wd177x_dsk.o   \
181182   $(LIBOBJ)/formats/x07_cas.o      \
182183   $(LIBOBJ)/formats/x1_tap.o      \
183184   $(LIBOBJ)/formats/xdf_dsk.o      \

Previous 199869 Revisions Next


© 1997-2024 The MAME Team