Previous 199869 Revisions Next

r33825 Thursday 11th December, 2014 at 13:30:57 UTC by Fabio Priuli
renamed the disk formats, since I cannot exclude some of them are used
also for x68000 disks... nw.
[hash]vsmile_cart.xml
[src/lib]lib.mak
[src/lib/formats]dcp_dsk.c* dcp_dsk.h* dip_dsk.c* dip_dsk.h* fdd_dsk.c* fdd_dsk.h* nfd_dsk.c* nfd_dsk.h* pc98dcp_dsk.c pc98dcp_dsk.h pc98dip_dsk.c pc98dip_dsk.h pc98fdd_dsk.c pc98fdd_dsk.h pc98nfd_dsk.c pc98nfd_dsk.h
[src/mess/drivers]pc9801.c

trunk/hash/vsmile_cart.xml
r242336r242337
11681168      </part>
11691169   </software>
11701170
1171   <software name="spiderman" supported="no">
1171   <software name="spidermn" supported="no">
11721172      <description>Spider-Man &amp; Freunde - Wettkampf im Space-Labor (Ger)</description>
11731173      <year>200?</year>
11741174      <publisher>VTech</publisher>
trunk/src/lib/formats/dcp_dsk.c
r0r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/dcp_dsk.h
6
7    PC98 DCP & DCU disk images
8
9    0xA2 header, followed by track data
10   header[0] - disk format
11    header[1-0xA1] - track map (1=track used, 0=track unused/unformatted)
12    header[0xA2] - all tracks used?
13                   (there seems to be a diff in its usage between DCP and DCU)
14
15    TODO:
16     - add support for track map. images available for tests were all
17       of type 0x01, with all 154 tracks present. combined with pete_j
18       reporting some images have faulty track map, we need some more
19       test cases to properly handle these disks!
20 
21*********************************************************************/
22
23#include "emu.h"
24#include "dcp_dsk.h"
25
26dcp_format::dcp_format()
27{
28}
29
30const char *dcp_format::name() const
31{
32   return "dcx";
33}
34
35const char *dcp_format::description() const
36{
37   return "DCP/DCU disk image";
38}
39
40const char *dcp_format::extensions() const
41{
42   return "dcp,dcu";
43}
44
45int dcp_format::identify(io_generic *io, UINT32 form_factor)
46{
47   UINT64 size = io_generic_size(io);
48   UINT8 h[0xa2];
49   int heads, tracks, spt, bps, count_tracks = 0;
50   bool is_hdb = false;
51
52   io_generic_read(io, h, 0, 0xa2);
53
54   // First byte is the disk format (see below in load() for details)
55   switch (h[0])
56   {
57      case 0x01:
58      default:
59         heads = 2; tracks = 77;
60         spt = 8; bps = 1024;
61         break;
62      case 0x02:
63         heads = 2; tracks = 80;
64         spt = 15; bps = 512;
65         break;
66      case 0x03:
67         heads = 2; tracks = 80;
68         spt = 18; bps = 512;
69         break;
70      case 0x04:
71         heads = 2; tracks = 80;
72         spt = 8; bps = 512;
73         break;
74      case 0x05:
75         heads = 2; tracks = 80;
76         spt = 9; bps = 512;
77         break;
78      case 0x08:
79         heads = 2; tracks = 80;
80         spt = 9; bps = 1024;
81         break;
82      case 0x11:
83         is_hdb = true;
84         heads = 2; tracks = 77;
85         spt = 26; bps = 256;
86         break;
87      case 0x19:
88         heads = 2; tracks = 80;
89         spt = 16; bps = 256;
90         break;
91      case 0x21:
92         heads = 2; tracks = 80;
93         spt = 26; bps = 256;
94         break;
95   }
96
97   // bytes 0x01 to 0xa1 are track map (0x01 if track is used, 0x00 if track is unformatted/unused)
98   for (int i = 1; i < 0xa1; i++)
99      if (h[i])
100         count_tracks++;
101
102   // in theory track map should be enough (former check), but some images have it wrong!
103   // hence, if this check fails, we also allow for images with all tracks and wrong track map
104   if (size - 0xa2 == (heads * count_tracks * spt * bps) || size - 0xa2 == (heads * tracks * spt * bps))
105      return 100;
106
107   // for disk type 0x11 the head 0 track 0 has 26 sectors of half width, so we need to compensate calculation
108   if (is_hdb && (size - 0xa2 + (0x80 * 26) == (heads * count_tracks * spt * bps) || size - 0xa2 + (0x80 * 26) == (heads * tracks * spt * bps)))
109      return 100;
110   
111   return 0;
112}
113
114bool dcp_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
115{
116   UINT8 h[0xa2];
117   int heads, tracks, spt, bps;
118   bool is_hdb = false;
119   
120   io_generic_read(io, h, 0, 0xa2);
121   
122   // First byte is the disk format:
123   switch (h[0])
124   {
125      case 0x01:
126      default:
127         //01h: 2HD-8 sector (1.25MB) (BKDSK .HDM) (aka 2HS)
128         //2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
129         heads = 2;
130         tracks = 77;
131         spt = 8;
132         bps = 1024;
133         break;
134      case 0x02:
135         //02H: 2HD-15 sector (1.21MB) (BKDSK .HD5) (aka 2HC)
136         //2 sides, 80 tracks, 15 sectors/track, 512 bytes/sector = 1228800 bytes (360rpm)
137         heads = 2;
138         tracks = 80;
139         spt = 15;
140         bps = 512;
141         break;
142      case 0x03:
143         //03H: 2HQ-18 sector (1.44MB) (BKDSK .HD4) (aka 2HDE)
144         //2 sides, 80 tracks, 18 sectors/track, 512 bytes/sector = 1474560 bytes (300rpm)
145         heads = 2;
146         tracks = 80;
147         spt = 18;
148         bps = 512;
149         break;
150      case 0x04:
151         //04H: 2DD-8 sector (640KB) (BKDSK .DD6)
152         //2 sides, 80 tracks, 8 sectors/track, 512 bytes/sector = 655360 bytes (300rpm)
153         heads = 2;
154         tracks = 80;
155         spt = 8;
156         bps = 512;
157         break;
158      case 0x05:
159         //05h: 2DD-9 sector ( 720KB) (BKDSK .DD9)
160         //2 sides, 80 tracks, 9 sectors/track, 512 bytes/sector = 737280 bytes (300rpm)
161         heads = 2;
162         tracks = 80;
163         spt = 9;
164         bps = 512;
165         break;
166      case 0x08:
167         //08h: 2HD-9 sector (1.44MB)
168         //2 sides, 80 tracks, 9 sectors/track, 1024 bytes/sector = 1474560 bytes (300rpm)(??)
169         heads = 2;
170         tracks = 80;
171         spt = 9;
172         bps = 1024;
173         break;
174      case 0x11:
175         //11h: BASIC-2HD (BKDSK .HDB)
176         //Head 0 Track 0 - FM encoding - 26 sectors of 128 bytes = 1 track
177         //Head 1 Track 0 - MFM encoding - 26 sectors of 256 bytes = 1 track
178         //Head 0 Track 1 to Head 1 Track 77 - 26 sectors of 256 bytes = 152 tracks
179         //2 sides, 77 tracks, 26 sectors/track, 256 bytes/sector (except for head 0 track 0) = 1021696 bytes (360rpm)
180         is_hdb = true;
181         heads = 2;
182         tracks = 77;
183         spt = 26;
184         bps = 256;
185         break;
186      case 0x19:
187         //19h: BASIC 2DD (BKDSK .DDB)
188         //2 sides, 80 tracks, 16 sectors/track, 256 bytes/sector = 655360 bytes (300rpm)
189         heads = 2;
190         tracks = 80;
191         spt = 16;
192         bps = 256;
193         break;
194      case 0x21:
195         //21H: 2HD-26 sector
196         //2 sides, 80 tracks, 26 sectors/track, 256 bytes/sector = 1064960 bytes (??rpm)(??)
197         heads = 2;
198         tracks = 80;
199         spt = 26;
200         bps = 256;
201         break;
202   }
203
204   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
205
206   int ssize;
207   for (ssize = 0; (128 << ssize) < bps; ssize++);
208
209   desc_pc_sector sects[256];
210   UINT8 sect_data[65536];
211
212   if (!is_hdb)
213   {
214      for (int track = 0; track < tracks; track++)
215         for (int head = 0; head < heads; head++)
216         {
217            io_generic_read(io, sect_data, 0xa2 + bps * spt * (track * heads + head), bps * spt);
218           
219            for (int i = 0; i < spt; i++)
220            {
221               sects[i].track       = track;
222               sects[i].head        = head;
223               sects[i].sector      = i + 1;
224               sects[i].size        = ssize;
225               sects[i].actual_size = bps;
226               sects[i].deleted     = false;
227               sects[i].bad_crc     = false;
228               sects[i].data        = sect_data + i * bps;
229            }
230           
231            build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
232         }
233   }
234   else   // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
235   {
236      // Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
237      io_generic_read(io, sect_data, 0xa2, 128 * spt);
238     
239      for (int i = 0; i < spt; i++)
240      {
241         sects[i].track       = 0;
242         sects[i].head        = 0;
243         sects[i].sector      = i + 1;
244         sects[i].size        = 0;
245         sects[i].actual_size = 128;
246         sects[i].deleted     = false;
247         sects[i].bad_crc     = false;
248         sects[i].data        = sect_data + i * 128;
249      }
250     
251      build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));
252     
253      // Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
254      io_generic_read(io, sect_data, 0xa2 + 128 * spt, bps * spt);
255     
256      for (int i = 0; i < spt; i++)
257      {
258         sects[i].track       = 0;
259         sects[i].head        = 1;
260         sects[i].sector      = i + 1;
261         sects[i].size        = ssize;
262         sects[i].actual_size = bps;
263         sects[i].deleted     = false;
264         sects[i].bad_crc     = false;
265         sects[i].data        = sect_data + i * bps;
266      }
267     
268      build_pc_track_mfm(0, 1, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
269     
270      // Read other tracks as usual
271      UINT32 data_offs = 0xa2 + (26 * 0x80) + (26 * 0x100);
272      for (int track = 1; track < tracks; track++)
273         for (int head = 0; head < heads; head++)
274         {
275            io_generic_read(io, sect_data, data_offs + bps * spt * ((track - 1) * heads + head), bps * spt);
276           
277            for (int i = 0; i < spt; i++)
278            {
279               sects[i].track       = track;
280               sects[i].head        = head;
281               sects[i].sector      = i + 1;
282               sects[i].size        = ssize;
283               sects[i].actual_size = bps;
284               sects[i].deleted     = false;
285               sects[i].bad_crc     = false;
286               sects[i].data        = sect_data + i * bps;
287            }
288           
289            build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
290         }
291   }
292   
293   return true;
294}
295
296bool dcp_format::supports_save() const
297{
298   return false;
299}
300
301const floppy_format_type FLOPPY_DCP_FORMAT = &floppy_image_format_creator<dcp_format>;
trunk/src/lib/formats/dcp_dsk.h
r0r242337
1/*********************************************************************
2
3    formats/dcp_dsk.h
4
5    PC98 DCP & DCU disk images
6
7*********************************************************************/
8
9#ifndef DCP_DSK_H
10#define DCP_DSK_H
11
12#include "flopimg.h"
13
14
15class dcp_format : public floppy_image_format_t
16{
17public:
18   dcp_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_DCP_FORMAT;
30
31#endif /* PC98DCP_DSK_H */
trunk/src/lib/formats/dip_dsk.c
r0r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/dip_dsk.h
6
7    PC98 DIP disk images
8 
9    0x100 header, followed by track data
10
11    TODO:
12    - Investigate header structure
13    - can this format be used to support different disc types?
14
15*********************************************************************/
16
17#include "emu.h"
18#include "dip_dsk.h"
19
20dip_format::dip_format()
21{
22}
23
24const char *dip_format::name() const
25{
26   return "dip";
27}
28
29const char *dip_format::description() const
30{
31   return "DIP disk image";
32}
33
34const char *dip_format::extensions() const
35{
36   return "dip";
37}
38
39int dip_format::identify(io_generic *io, UINT32 form_factor)
40{
41   UINT64 size = io_generic_size(io);
42
43   if (size == 0x134000 + 0x100)
44      return 100;
45
46   return 0;
47}
48
49bool dip_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
50{
51   int heads, tracks, spt, bps;
52
53   //For the moment we only support this disk structure...
54   //2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
55   heads = 2;
56   tracks = 77;
57   spt = 8;
58   bps = 1024;
59   
60   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
61   
62   int ssize;
63   for (ssize = 0; (128 << ssize) < bps; ssize++);
64   
65   desc_pc_sector sects[256];
66   UINT8 sect_data[65536];
67   
68   for (int track = 0; track < tracks; track++)
69      for (int head = 0; head < heads; head++)
70      {
71         io_generic_read(io, sect_data, 0x100 + bps * spt * (track * heads + head), bps * spt);
72         
73         for (int i = 0; i < spt; i++)
74         {
75            sects[i].track       = track;
76            sects[i].head        = head;
77            sects[i].sector      = i + 1;
78            sects[i].size        = ssize;
79            sects[i].actual_size = bps;
80            sects[i].deleted     = false;
81            sects[i].bad_crc     = false;
82            sects[i].data        = sect_data + i * bps;
83         }
84         
85         build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
86      }
87
88   return true;
89}
90
91bool dip_format::supports_save() const
92{
93   return false;
94}
95
96const floppy_format_type FLOPPY_DIP_FORMAT = &floppy_image_format_creator<dip_format>;
trunk/src/lib/formats/dip_dsk.h
r0r242337
1/*********************************************************************
2
3    formats/dip_dsk.h
4
5    PC98DIP disk images
6
7*********************************************************************/
8
9#ifndef DIP_DSK_H
10#define DIP_DSK_H
11
12#include "flopimg.h"
13
14
15class dip_format : public floppy_image_format_t
16{
17public:
18   dip_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_DIP_FORMAT;
30
31#endif /* DIP_DSK_H */
trunk/src/lib/formats/fdd_dsk.c
r0r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/fdd_dsk.h
6
7    PC98 FDD disk images
8 
9    0xC3FC header, followed by track data
10    Sector map starts at offset 0xDC, with 12bytes for each sector
11
12    Each entry of the sector map has the following structure
13    - 0x0 = track number (if 0xff the sector/track is unformatted/unused)
14    - 0x1 = head number
15    - 0x2 = sector number
16    - 0x3 = sector size (128 << this byte)
17    - 0x4 = fill byte. if it's not 0xff, then this sector in the original
18            disk consisted of this single value repeated for the whole
19            sector size, and the sector is skipped in the .fdd file.
20            if it's 0xff, then this sector is wholly contained in the .fdd
21            file
22    - 0x5 = ??
23    - 0x6 = ??
24    - 0x7 = ??
25    - 0x8-0x0b = absolute offset of the data for this sector, or 0xfffffff
26                 if the sector was skipped in the .fdd (and it has to be
27                 filled with the value at 0x4)
28
29 TODO:
30    - Investigate remaining sector map bytes (maybe related to protections?)
31
32*********************************************************************/
33
34#include "emu.h"
35#include "fdd_dsk.h"
36
37fdd_format::fdd_format()
38{
39}
40
41const char *fdd_format::name() const
42{
43   return "fdd";
44}
45
46const char *fdd_format::description() const
47{
48   return "FDD disk image";
49}
50
51const char *fdd_format::extensions() const
52{
53   return "fdd";
54}
55
56int fdd_format::identify(io_generic *io, UINT32 form_factor)
57{
58   UINT8 h[7];   
59   io_generic_read(io, h, 0, 7);
60   
61   if (strncmp((const char *)h, "VFD1.0", 6) == 0)
62      return 100;
63   
64   return 0;
65}
66
67bool fdd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
68{
69   UINT8 hsec[0x0c];   
70   
71   // sector map
72   UINT8 num_secs[160];
73   UINT32 track_sizes[160];
74   UINT8 tracks[160 * 26];
75   UINT8 heads[160 * 26];
76   UINT8 secs[160 * 26];
77   UINT8 fill_vals[160 * 26];
78   UINT32 sec_offs[160 * 26];
79   UINT8 sec_sizes[160 * 26];
80   
81   int pos = 0xdc;
82   
83   for (int track = 0; track < 160; track++)
84   {
85      int curr_num_sec = 0, curr_track_size = 0;
86      for (int sect = 0; sect < 26; sect++)
87      {
88         // read sector map for this sector
89         io_generic_read(io, hsec, pos, 0x0c);
90         pos += 0x0c;
91         
92         if (hsec[0] == 0xff)   // unformatted/unused sector
93            continue;
94         
95         tracks[(track * 26) + sect] = hsec[0];
96         heads[(track * 26) + sect] = hsec[1];
97         secs[(track * 26) + sect] = hsec[2];
98         sec_sizes[(track * 26) + sect] = hsec[3];
99         fill_vals[(track * 26) + sect] = hsec[4];
100         sec_offs[(track * 26) + sect] = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x08));
101
102         curr_track_size += (128 << hsec[3]);
103         curr_num_sec++;
104      }
105      num_secs[track] = curr_num_sec;
106      track_sizes[track] = curr_track_size;
107   }
108
109   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
110   desc_pc_sector sects[256];
111   UINT8 sect_data[65536];
112   int cur_sec_map = 0, sector_size;
113
114   for (int track = 0; track < 160; track++)
115   {     
116      int cur_pos = 0;
117      for (int i = 0; i < num_secs[track]; i++)
118      {
119         cur_sec_map = track * 26 + i;
120         sector_size = 128 << sec_sizes[cur_sec_map];
121
122         if (sec_offs[cur_sec_map] == 0xffffffff)
123            memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
124         else
125            io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size);
126         
127         sects[i].track       = tracks[cur_sec_map];
128         sects[i].head        = heads[cur_sec_map];
129         sects[i].sector      = secs[cur_sec_map];
130         sects[i].size        = sec_sizes[cur_sec_map];
131         sects[i].actual_size = sector_size;
132         sects[i].deleted     = false;
133         sects[i].bad_crc     = false;
134         sects[i].data        = sect_data + cur_pos;
135         cur_pos += sector_size;
136      }
137
138      build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
139   }
140   
141   return true;
142}
143
144bool fdd_format::supports_save() const
145{
146   return false;
147}
148
149const floppy_format_type FLOPPY_FDD_FORMAT = &floppy_image_format_creator<fdd_format>;
trunk/src/lib/formats/fdd_dsk.h
r0r242337
1/*********************************************************************
2
3    formats/fdd_dsk.h
4
5    PC98 FDD disk images
6
7*********************************************************************/
8
9#ifndef FDD_DSK_H
10#define FDD_DSK_H
11
12#include "flopimg.h"
13
14
15class fdd_format : public floppy_image_format_t
16{
17public:
18   fdd_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_FDD_FORMAT;
30
31#endif /* FDD_DSK_H */
trunk/src/lib/formats/nfd_dsk.c
r0r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/nfd_dsk.h
6
7    PC98 NFD disk images (info from: http://www.geocities.jp/t98next/dev.html )
8
9    Revision 0
10    ==========
11
12    header structure (variable length > 0x120, header length = DWORD at 0x110)
13    0x000-0x00F = T98FDDIMAGE.R* followed by 2 0x00 bytes, * = format revision (0 or 1 so far)
14    0x010-0x10F = space for image info / comments
15    0x110-0x113 = header length (DWORD)
16    0x114       = write protect (any value > 0 means not writeable)
17    0x115       = number of heads
18    0x116-0x11F = reserved
19    0x120-EOHeader = sector map (0x10 for each sector of the disk!)
20    last 0x10 are fixed to 0x00, probably it marks the end of sector map?
21
22    sector map structure
23    0x0     = track number
24    0x1     = head
25    0x2     = sector number
26    0x3     = sector size (in 128byte chunks)
27    0x4     = MFM/FM (1 = MFM, 0 = FM)?
28    0x5     = DDAM/DAM (1 = DDAM, 0 = DAM)
29    0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
30    0xA     = PDA (disk type)
31    0xB-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
32
33 
34   Revision 1
35    ==========
36 
37    header structure (variable length > 0x120, header length = DWORD at 0x110)
38    0x000-0x11F = same as Rev. 0 format
39   0x120-0x3AF = 164 DWORDs containing, for each track, the absolute position of the sector maps
40                  for sectors of the track. for unformatted/unused tracks 0 is used
41    0x3B0-0x3B3 = absolute position of addintional info in the header, if any
42    0x3B4-0x3BF = reserved
43    0x120-EOHeader = sector map + special data for each track:
44                     first 0x10 of each track = #sectors (WORD), #extra data (WORD), reserved 0xc bytes zeroed
45                     then 0x10 for each sector of this track and 0x10 for each extra data chunk
46
47    sector map structure
48   0x0     = track number
49    0x1     = head
50    0x2     = sector number
51    0x3     = sector size (in 128byte chunks)
52    0x4     = MFM/FM (1 = MFM, 0 = FM)?
53    0x5     = DDAM/DAM (1 = DDAM, 0 = DAM)
54    0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
55    0xA     = RETRY DATA (1 = Yes, 0 = No)
56    0xB     = PDA (disk type)
57    0xC-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
58
59    extra data map structure
60    0x0     = command
61    0x1     = track number
62    0x2     = head
63    0x3     = sector number
64    0x4     = sector size (in 128byte chunks)
65    0x5-0x8 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
66    0x9     = Number of times to RETRY loading data
67    0xA-0xD = length of RETRY DATA
68    0xE     = PDA (disk type)
69    0xF     = reserved and equal to 0x00 (possibly available for future format extensions?)
70
71    TODO:
72    - add support for write protect header bit? apparently, some disks try to write and
73      fail to boot if they succeed which is the reason this bit was added
74    - add support for DDAM in Rev. 0 (need an image which set it in some sector)
75    - investigate the READ DATA bytes of sector headers
76    - investigate RETRY DATA chunks
77 
78 *********************************************************************/
79
80#include "emu.h"
81#include "nfd_dsk.h"
82
83nfd_format::nfd_format()
84{
85}
86
87const char *nfd_format::name() const
88{
89   return "nfd";
90}
91
92const char *nfd_format::description() const
93{
94   return "NFD disk image";
95}
96
97const char *nfd_format::extensions() const
98{
99   return "nfd";
100}
101
102int nfd_format::identify(io_generic *io, UINT32 form_factor)
103{
104   UINT8 h[16];   
105   io_generic_read(io, h, 0, 16);
106   
107   if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0)
108      return 100;
109
110   return 0;
111}
112
113bool nfd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
114{
115   UINT64 size = io_generic_size(io);
116   UINT8 h[0x120], hsec[0x10];   
117   io_generic_read(io, h, 0, 0x120);
118   int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
119
120   // sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
121   UINT8 disk_type = 0;
122   UINT8 num_secs[164];
123   UINT8 num_specials[164];
124   UINT32 track_sizes[164];
125   UINT8 tracks[164 * 26];
126   UINT8 heads[164 * 26];
127   UINT8 secs[164 * 26];
128   UINT8 mfm[164 * 26];
129   UINT8 sec_sizes[164 * 26];
130
131   UINT32 hsize = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x110));
132
133   int pos = 0x120;
134
135   // set up sector map
136   if (format_version == 1)
137   {
138      for (int track = 0; track < 164; track++)
139      {
140         int curr_track_size = 0;
141         // read sector map absolute location
142         io_generic_read(io, hsec, pos, 4);
143         pos += 4;
144         UINT32 secmap_addr = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec));
145
146         if (secmap_addr)
147         {
148            // read actual sector map for the sectors of this track
149            // for rev.1 format the first 0x10 are a track summary:
150            // first WORD is # of sectors, second WORD is # of special data sectors
151            io_generic_read(io, hsec, secmap_addr, 0x10);
152            secmap_addr += 0x10;
153            num_secs[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec));
154            num_specials[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec + 0x2));
155
156            for (int sect = 0; sect < num_secs[track]; sect++)
157            {
158               io_generic_read(io, hsec, secmap_addr, 0x10);
159               
160               if (track == 0 && sect == 0)
161                  disk_type = hsec[0xb];   // can this change across the disk? I don't think so...
162               secmap_addr += 0x10;
163               
164               tracks[(track * 26) + sect] = hsec[0];
165               heads[(track * 26) + sect] = hsec[1];
166               secs[(track * 26) + sect] = hsec[2];
167               sec_sizes[(track * 26) + sect] = hsec[3];
168               mfm[(track * 26) + sect] = hsec[4];
169               
170               curr_track_size += (128 << hsec[3]);
171            }
172
173            if (num_specials[track] > 0)
174            {
175               for (int sect = 0; sect < num_specials[track]; sect++)
176               {
177                  io_generic_read(io, hsec, secmap_addr, 0x10);   
178                  secmap_addr += 0x10;
179                  curr_track_size += (hsec[9] + 1) * LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x0a));
180               }
181            }
182         }
183         else
184         {
185            num_secs[track] = 0;
186            num_specials[track] = 0;
187         }
188         track_sizes[track] = curr_track_size;
189      }
190   }
191   else
192   {
193      for (int track = 0; track < 163 && pos < hsize; track++)
194      {
195         int curr_num_sec = 0, curr_track_size = 0;
196         for (int sect = 0; sect < 26; sect++)
197         {
198            // read sector map for this sector
199            // for rev.0 format each sector uses 0x10 bytes
200            io_generic_read(io, hsec, pos, 0x10);
201
202            if (track == 0 && sect == 0)
203               disk_type = hsec[0xa];   // can this change across the disk? I don't think so...
204            pos += 0x10;
205           
206            if (hsec[0] == 0xff)   // unformatted/unused sector
207               continue;
208           
209            tracks[(track * 26) + sect] = hsec[0];
210            heads[(track * 26) + sect] = hsec[1];
211            secs[(track * 26) + sect] = hsec[2];
212            sec_sizes[(track * 26) + sect] = hsec[3];
213            mfm[(track * 26) + sect] = hsec[4];
214           
215            curr_track_size += (128 << hsec[3]);
216            curr_num_sec++;
217         }
218
219         num_secs[track] = curr_num_sec;
220         track_sizes[track] = curr_track_size;
221      }
222   }
223
224   // shouln't this be set-up depending on disk_type? gaplus does not like having less than 166666 cells
225   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
226
227   switch (disk_type)
228   {
229      case 0x10:   // 640K disk, 2DD
230         image->set_variant(floppy_image::DSDD);
231         break;
232      //case 0x30:   // 1.44M disk, ?? (no images found)
233      //   break;
234      case 0x90:   // 1.2M disk, 2HD
235      default:
236         image->set_variant(floppy_image::DSHD);
237         break;
238   }
239
240   desc_pc_sector sects[256];
241   UINT8 sect_data[65536];
242   int cur_sec_map = 0, sector_size;
243   pos = hsize;
244
245   for (int track = 0; track < 163 && pos < size; track++)
246   {
247      io_generic_read(io, sect_data, pos, track_sizes[track]);
248
249      for (int i = 0; i < num_secs[track]; i++)
250      {
251         cur_sec_map = track * 26 + i;
252         sector_size = 128 << sec_sizes[cur_sec_map];
253         sects[i].track       = tracks[cur_sec_map];
254         sects[i].head        = heads[cur_sec_map];
255         sects[i].sector      = secs[cur_sec_map];
256         sects[i].size        = sec_sizes[cur_sec_map];
257         sects[i].actual_size = sector_size;
258         sects[i].deleted     = false;
259         sects[i].bad_crc     = false;
260         sects[i].data        = sect_data + i * sector_size;
261      }
262      pos += track_sizes[track];
263
264      // notice that the operation below might fail if sectors of the same track have variable sec_sizes,
265      // because the gap3 calculation would account correctly only for the first sector...
266      // examined images had constant sec_sizes in the each track, so probably this is not an issue
267      if (mfm[track * 26])
268         build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
269      else
270         build_pc_track_fm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
271   }
272   
273   return true;
274}
275
276bool nfd_format::supports_save() const
277{
278   return false;
279}
280
281const floppy_format_type FLOPPY_NFD_FORMAT = &floppy_image_format_creator<nfd_format>;
trunk/src/lib/formats/nfd_dsk.h
r0r242337
1/*********************************************************************
2
3    formats/nfd_dsk.h
4
5    PC98 NFD disk images
6
7*********************************************************************/
8
9#ifndef NFD_DSK_H
10#define NFD_DSK_H
11
12#include "flopimg.h"
13
14
15class nfd_format : public floppy_image_format_t
16{
17public:
18   nfd_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_NFD_FORMAT;
30
31#endif /* NFD_DSK_H */
trunk/src/lib/formats/pc98dcp_dsk.c
r242336r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/pc98dcp_dsk.h
6
7    PC98 DCP & DCU disk images
8
9    0xA2 header, followed by track data
10   header[0] - disk format
11    header[1-0xA1] - track map (1=track used, 0=track unused/unformatted)
12    header[0xA2] - all tracks used?
13                   (there seems to be a diff in its usage between DCP and DCU)
14
15    TODO:
16     - add support for track map. images available for tests were all
17       of type 0x01, with all 154 tracks present. combined with pete_j
18       reporting some images have faulty track map, we need some more
19       test cases to properly handle these disks!
20 
21*********************************************************************/
22
23#include "emu.h"
24#include "pc98dcp_dsk.h"
25
26pc98dcp_format::pc98dcp_format()
27{
28}
29
30const char *pc98dcp_format::name() const
31{
32   return "pc98_dcx";
33}
34
35const char *pc98dcp_format::description() const
36{
37   return "PC98 DCP/DCU disk image";
38}
39
40const char *pc98dcp_format::extensions() const
41{
42   return "dcp,dcu";
43}
44
45int pc98dcp_format::identify(io_generic *io, UINT32 form_factor)
46{
47   UINT64 size = io_generic_size(io);
48   UINT8 h[0xa2];
49   int heads, tracks, spt, bps, count_tracks = 0;
50   bool is_hdb = false;
51
52   io_generic_read(io, h, 0, 0xa2);
53
54   // First byte is the disk format (see below in load() for details)
55   switch (h[0])
56   {
57      case 0x01:
58      default:
59         heads = 2; tracks = 77;
60         spt = 8; bps = 1024;
61         break;
62      case 0x02:
63         heads = 2; tracks = 80;
64         spt = 15; bps = 512;
65         break;
66      case 0x03:
67         heads = 2; tracks = 80;
68         spt = 18; bps = 512;
69         break;
70      case 0x04:
71         heads = 2; tracks = 80;
72         spt = 8; bps = 512;
73         break;
74      case 0x05:
75         heads = 2; tracks = 80;
76         spt = 9; bps = 512;
77         break;
78      case 0x08:
79         heads = 2; tracks = 80;
80         spt = 9; bps = 1024;
81         break;
82      case 0x11:
83         is_hdb = true;
84         heads = 2; tracks = 77;
85         spt = 26; bps = 256;
86         break;
87      case 0x19:
88         heads = 2; tracks = 80;
89         spt = 16; bps = 256;
90         break;
91      case 0x21:
92         heads = 2; tracks = 80;
93         spt = 26; bps = 256;
94         break;
95   }
96
97   // bytes 0x01 to 0xa1 are track map (0x01 if track is used, 0x00 if track is unformatted/unused)
98   for (int i = 1; i < 0xa1; i++)
99      if (h[i])
100         count_tracks++;
101
102   // in theory track map should be enough (former check), but some images have it wrong!
103   // hence, if this check fails, we also allow for images with all tracks and wrong track map
104   if (size - 0xa2 == (heads * count_tracks * spt * bps) || size - 0xa2 == (heads * tracks * spt * bps))
105      return 100;
106
107   // for disk type 0x11 the head 0 track 0 has 26 sectors of half width, so we need to compensate calculation
108   if (is_hdb && (size - 0xa2 + (0x80 * 26) == (heads * count_tracks * spt * bps) || size - 0xa2 + (0x80 * 26) == (heads * tracks * spt * bps)))
109      return 100;
110   
111   return 0;
112}
113
114bool pc98dcp_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
115{
116   UINT8 h[0xa2];
117   int heads, tracks, spt, bps;
118   bool is_hdb = false;
119   
120   io_generic_read(io, h, 0, 0xa2);
121   
122   // First byte is the disk format:
123   switch (h[0])
124   {
125      case 0x01:
126      default:
127         //01h: 2HD-8 sector (1.25MB) (BKDSK .HDM) (aka 2HS)
128         //2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
129         heads = 2;
130         tracks = 77;
131         spt = 8;
132         bps = 1024;
133         break;
134      case 0x02:
135         //02H: 2HD-15 sector (1.21MB) (BKDSK .HD5) (aka 2HC)
136         //2 sides, 80 tracks, 15 sectors/track, 512 bytes/sector = 1228800 bytes (360rpm)
137         heads = 2;
138         tracks = 80;
139         spt = 15;
140         bps = 512;
141         break;
142      case 0x03:
143         //03H: 2HQ-18 sector (1.44MB) (BKDSK .HD4) (aka 2HDE)
144         //2 sides, 80 tracks, 18 sectors/track, 512 bytes/sector = 1474560 bytes (300rpm)
145         heads = 2;
146         tracks = 80;
147         spt = 18;
148         bps = 512;
149         break;
150      case 0x04:
151         //04H: 2DD-8 sector (640KB) (BKDSK .DD6)
152         //2 sides, 80 tracks, 8 sectors/track, 512 bytes/sector = 655360 bytes (300rpm)
153         heads = 2;
154         tracks = 80;
155         spt = 8;
156         bps = 512;
157         break;
158      case 0x05:
159         //05h: 2DD-9 sector ( 720KB) (BKDSK .DD9)
160         //2 sides, 80 tracks, 9 sectors/track, 512 bytes/sector = 737280 bytes (300rpm)
161         heads = 2;
162         tracks = 80;
163         spt = 9;
164         bps = 512;
165         break;
166      case 0x08:
167         //08h: 2HD-9 sector (1.44MB)
168         //2 sides, 80 tracks, 9 sectors/track, 1024 bytes/sector = 1474560 bytes (300rpm)(??)
169         heads = 2;
170         tracks = 80;
171         spt = 9;
172         bps = 1024;
173         break;
174      case 0x11:
175         //11h: BASIC-2HD (BKDSK .HDB)
176         //Head 0 Track 0 - FM encoding - 26 sectors of 128 bytes = 1 track
177         //Head 1 Track 0 - MFM encoding - 26 sectors of 256 bytes = 1 track
178         //Head 0 Track 1 to Head 1 Track 77 - 26 sectors of 256 bytes = 152 tracks
179         //2 sides, 77 tracks, 26 sectors/track, 256 bytes/sector (except for head 0 track 0) = 1021696 bytes (360rpm)
180         is_hdb = true;
181         heads = 2;
182         tracks = 77;
183         spt = 26;
184         bps = 256;
185         break;
186      case 0x19:
187         //19h: BASIC 2DD (BKDSK .DDB)
188         //2 sides, 80 tracks, 16 sectors/track, 256 bytes/sector = 655360 bytes (300rpm)
189         heads = 2;
190         tracks = 80;
191         spt = 16;
192         bps = 256;
193         break;
194      case 0x21:
195         //21H: 2HD-26 sector
196         //2 sides, 80 tracks, 26 sectors/track, 256 bytes/sector = 1064960 bytes (??rpm)(??)
197         heads = 2;
198         tracks = 80;
199         spt = 26;
200         bps = 256;
201         break;
202   }
203
204   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
205
206   int ssize;
207   for (ssize = 0; (128 << ssize) < bps; ssize++);
208
209   desc_pc_sector sects[256];
210   UINT8 sect_data[65536];
211
212   if (!is_hdb)
213   {
214      for (int track = 0; track < tracks; track++)
215         for (int head = 0; head < heads; head++)
216         {
217            io_generic_read(io, sect_data, 0xa2 + bps * spt * (track * heads + head), bps * spt);
218           
219            for (int i = 0; i < spt; i++)
220            {
221               sects[i].track       = track;
222               sects[i].head        = head;
223               sects[i].sector      = i + 1;
224               sects[i].size        = ssize;
225               sects[i].actual_size = bps;
226               sects[i].deleted     = false;
227               sects[i].bad_crc     = false;
228               sects[i].data        = sect_data + i * bps;
229            }
230           
231            build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
232         }
233   }
234   else   // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
235   {
236      // Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
237      io_generic_read(io, sect_data, 0xa2, 128 * spt);
238     
239      for (int i = 0; i < spt; i++)
240      {
241         sects[i].track       = 0;
242         sects[i].head        = 0;
243         sects[i].sector      = i + 1;
244         sects[i].size        = 0;
245         sects[i].actual_size = 128;
246         sects[i].deleted     = false;
247         sects[i].bad_crc     = false;
248         sects[i].data        = sect_data + i * 128;
249      }
250     
251      build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));
252     
253      // Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
254      io_generic_read(io, sect_data, 0xa2 + 128 * spt, bps * spt);
255     
256      for (int i = 0; i < spt; i++)
257      {
258         sects[i].track       = 0;
259         sects[i].head        = 1;
260         sects[i].sector      = i + 1;
261         sects[i].size        = ssize;
262         sects[i].actual_size = bps;
263         sects[i].deleted     = false;
264         sects[i].bad_crc     = false;
265         sects[i].data        = sect_data + i * bps;
266      }
267     
268      build_pc_track_mfm(0, 1, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
269     
270      // Read other tracks as usual
271      UINT32 data_offs = 0xa2 + (26 * 0x80) + (26 * 0x100);
272      for (int track = 1; track < tracks; track++)
273         for (int head = 0; head < heads; head++)
274         {
275            io_generic_read(io, sect_data, data_offs + bps * spt * ((track - 1) * heads + head), bps * spt);
276           
277            for (int i = 0; i < spt; i++)
278            {
279               sects[i].track       = track;
280               sects[i].head        = head;
281               sects[i].sector      = i + 1;
282               sects[i].size        = ssize;
283               sects[i].actual_size = bps;
284               sects[i].deleted     = false;
285               sects[i].bad_crc     = false;
286               sects[i].data        = sect_data + i * bps;
287            }
288           
289            build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
290         }
291   }
292   
293   return true;
294}
295
296bool pc98dcp_format::supports_save() const
297{
298   return false;
299}
300
301const floppy_format_type FLOPPY_PC98DCP_FORMAT = &floppy_image_format_creator<pc98dcp_format>;
trunk/src/lib/formats/pc98dcp_dsk.h
r242336r242337
1/*********************************************************************
2
3    formats/pc98dcp_dsk.h
4
5    PC98 DCP & DCU disk images
6
7*********************************************************************/
8
9#ifndef PC98DCP_DSK_H
10#define PC98DCP_DSK_H
11
12#include "flopimg.h"
13
14
15class pc98dcp_format : public floppy_image_format_t
16{
17public:
18   pc98dcp_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_PC98DCP_FORMAT;
30
31#endif /* PC98DCP_DSK_H */
trunk/src/lib/formats/pc98dip_dsk.c
r242336r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/pc98dip_dsk.h
6
7    PC98DIP disk images
8 
9    0x100 header, followed by track data
10
11    TODO:
12    - Investigate header structure
13    - can this format be used to support different disc types?
14
15*********************************************************************/
16
17#include "emu.h"
18#include "pc98dip_dsk.h"
19
20pc98dip_format::pc98dip_format()
21{
22}
23
24const char *pc98dip_format::name() const
25{
26   return "pc98_dip";
27}
28
29const char *pc98dip_format::description() const
30{
31   return "PC98 DIP disk image";
32}
33
34const char *pc98dip_format::extensions() const
35{
36   return "dip";
37}
38
39int pc98dip_format::identify(io_generic *io, UINT32 form_factor)
40{
41   UINT64 size = io_generic_size(io);
42
43   if (size == 0x134000 + 0x100)
44      return 100;
45
46   return 0;
47}
48
49bool pc98dip_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
50{
51   int heads, tracks, spt, bps;
52
53   //For the moment we only support this disk structure...
54   //2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
55   heads = 2;
56   tracks = 77;
57   spt = 8;
58   bps = 1024;
59   
60   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
61   
62   int ssize;
63   for (ssize = 0; (128 << ssize) < bps; ssize++);
64   
65   desc_pc_sector sects[256];
66   UINT8 sect_data[65536];
67   
68   for (int track = 0; track < tracks; track++)
69      for (int head = 0; head < heads; head++)
70      {
71         io_generic_read(io, sect_data, 0x100 + bps * spt * (track * heads + head), bps * spt);
72         
73         for (int i = 0; i < spt; i++)
74         {
75            sects[i].track       = track;
76            sects[i].head        = head;
77            sects[i].sector      = i + 1;
78            sects[i].size        = ssize;
79            sects[i].actual_size = bps;
80            sects[i].deleted     = false;
81            sects[i].bad_crc     = false;
82            sects[i].data        = sect_data + i * bps;
83         }
84         
85         build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
86      }
87
88   return true;
89}
90
91bool pc98dip_format::supports_save() const
92{
93   return false;
94}
95
96const floppy_format_type FLOPPY_PC98DIP_FORMAT = &floppy_image_format_creator<pc98dip_format>;
trunk/src/lib/formats/pc98dip_dsk.h
r242336r242337
1/*********************************************************************
2
3    formats/pc98dip_dsk.h
4
5    PC98DIP disk images
6
7*********************************************************************/
8
9#ifndef PC98DIP_DSK_H
10#define PC98DIP_DSK_H
11
12#include "flopimg.h"
13
14
15class pc98dip_format : public floppy_image_format_t
16{
17public:
18   pc98dip_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_PC98DIP_FORMAT;
30
31#endif /* PC98DIP_DSK_H */
trunk/src/lib/formats/pc98fdd_dsk.c
r242336r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/pc98fdd_dsk.h
6
7    PC98FDD disk images
8 
9    0xC3FC header, followed by track data
10    Sector map starts at offset 0xDC, with 12bytes for each sector
11
12    Each entry of the sector map has the following structure
13    - 0x0 = track number (if 0xff the sector/track is unformatted/unused)
14    - 0x1 = head number
15    - 0x2 = sector number
16    - 0x3 = sector size (128 << this byte)
17    - 0x4 = fill byte. if it's not 0xff, then this sector in the original
18            disk consisted of this single value repeated for the whole
19            sector size, and the sector is skipped in the .fdd file.
20            if it's 0xff, then this sector is wholly contained in the .fdd
21            file
22    - 0x5 = ??
23    - 0x6 = ??
24    - 0x7 = ??
25    - 0x8-0x0b = absolute offset of the data for this sector, or 0xfffffff
26                 if the sector was skipped in the .fdd (and it has to be
27                 filled with the value at 0x4)
28
29 TODO:
30    - Investigate remaining sector map bytes (maybe related to protections?)
31
32*********************************************************************/
33
34#include "emu.h"
35#include "pc98fdd_dsk.h"
36
37pc98fdd_format::pc98fdd_format()
38{
39}
40
41const char *pc98fdd_format::name() const
42{
43   return "pc98_fdd";
44}
45
46const char *pc98fdd_format::description() const
47{
48   return "PC98 FDD disk image";
49}
50
51const char *pc98fdd_format::extensions() const
52{
53   return "fdd";
54}
55
56int pc98fdd_format::identify(io_generic *io, UINT32 form_factor)
57{
58   UINT8 h[7];   
59   io_generic_read(io, h, 0, 7);
60   
61   if (strncmp((const char *)h, "VFD1.0", 6) == 0)
62      return 100;
63   
64   return 0;
65}
66
67bool pc98fdd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
68{
69   UINT8 hsec[0x0c];   
70   
71   // sector map
72   UINT8 num_secs[160];
73   UINT32 track_sizes[160];
74   UINT8 tracks[160 * 26];
75   UINT8 heads[160 * 26];
76   UINT8 secs[160 * 26];
77   UINT8 fill_vals[160 * 26];
78   UINT32 sec_offs[160 * 26];
79   UINT8 sec_sizes[160 * 26];
80   
81   int pos = 0xdc;
82   
83   for (int track = 0; track < 160; track++)
84   {
85      int curr_num_sec = 0, curr_track_size = 0;
86      for (int sect = 0; sect < 26; sect++)
87      {
88         // read sector map for this sector
89         io_generic_read(io, hsec, pos, 0x0c);
90         pos += 0x0c;
91         
92         if (hsec[0] == 0xff)   // unformatted/unused sector
93            continue;
94         
95         tracks[(track * 26) + sect] = hsec[0];
96         heads[(track * 26) + sect] = hsec[1];
97         secs[(track * 26) + sect] = hsec[2];
98         sec_sizes[(track * 26) + sect] = hsec[3];
99         fill_vals[(track * 26) + sect] = hsec[4];
100         sec_offs[(track * 26) + sect] = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x08));
101
102         curr_track_size += (128 << hsec[3]);
103         curr_num_sec++;
104      }
105      num_secs[track] = curr_num_sec;
106      track_sizes[track] = curr_track_size;
107   }
108
109   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
110   desc_pc_sector sects[256];
111   UINT8 sect_data[65536];
112   int cur_sec_map = 0, sector_size;
113
114   for (int track = 0; track < 160; track++)
115   {     
116      int cur_pos = 0;
117      for (int i = 0; i < num_secs[track]; i++)
118      {
119         cur_sec_map = track * 26 + i;
120         sector_size = 128 << sec_sizes[cur_sec_map];
121
122         if (sec_offs[cur_sec_map] == 0xffffffff)
123            memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
124         else
125            io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size);
126         
127         sects[i].track       = tracks[cur_sec_map];
128         sects[i].head        = heads[cur_sec_map];
129         sects[i].sector      = secs[cur_sec_map];
130         sects[i].size        = sec_sizes[cur_sec_map];
131         sects[i].actual_size = sector_size;
132         sects[i].deleted     = false;
133         sects[i].bad_crc     = false;
134         sects[i].data        = sect_data + cur_pos;
135         cur_pos += sector_size;
136      }
137
138      build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
139   }
140   
141   return true;
142}
143
144bool pc98fdd_format::supports_save() const
145{
146   return false;
147}
148
149const floppy_format_type FLOPPY_PC98FDD_FORMAT = &floppy_image_format_creator<pc98fdd_format>;
trunk/src/lib/formats/pc98fdd_dsk.h
r242336r242337
1/*********************************************************************
2
3    formats/pc98fdd_dsk.h
4
5    PC98FDD disk images
6
7*********************************************************************/
8
9#ifndef PC98FDD_DSK_H
10#define PC98FDD_DSK_H
11
12#include "flopimg.h"
13
14
15class pc98fdd_format : public floppy_image_format_t
16{
17public:
18   pc98fdd_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_PC98FDD_FORMAT;
30
31#endif /* PC98FDD_DSK_H */
trunk/src/lib/formats/pc98nfd_dsk.c
r242336r242337
1// license:BSD-3-Clause
2// copyright-holders:etabeta
3/*********************************************************************
4
5    formats/pc98nfd_dsk.h
6
7    PC98NFD disk images (info from: http://www.geocities.jp/t98next/dev.html )
8
9    Revision 0
10    ==========
11
12    header structure (variable length > 0x120, header length = DWORD at 0x110)
13    0x000-0x00F = T98FDDIMAGE.R* followed by 2 0x00 bytes, * = format revision (0 or 1 so far)
14    0x010-0x10F = space for image info / comments
15    0x110-0x113 = header length (DWORD)
16    0x114       = write protect (any value > 0 means not writeable)
17    0x115       = number of heads
18    0x116-0x11F = reserved
19    0x120-EOHeader = sector map (0x10 for each sector of the disk!)
20    last 0x10 are fixed to 0x00, probably it marks the end of sector map?
21
22    sector map structure
23    0x0     = track number
24    0x1     = head
25    0x2     = sector number
26    0x3     = sector size (in 128byte chunks)
27    0x4     = MFM/FM (1 = MFM, 0 = FM)?
28    0x5     = DDAM/DAM (1 = DDAM, 0 = DAM)
29    0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
30    0xA     = PDA (disk type)
31    0xB-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
32
33 
34   Revision 1
35    ==========
36 
37    header structure (variable length > 0x120, header length = DWORD at 0x110)
38    0x000-0x11F = same as Rev. 0 format
39   0x120-0x3AF = 164 DWORDs containing, for each track, the absolute position of the sector maps
40                  for sectors of the track. for unformatted/unused tracks 0 is used
41    0x3B0-0x3B3 = absolute position of addintional info in the header, if any
42    0x3B4-0x3BF = reserved
43    0x120-EOHeader = sector map + special data for each track:
44                     first 0x10 of each track = #sectors (WORD), #extra data (WORD), reserved 0xc bytes zeroed
45                     then 0x10 for each sector of this track and 0x10 for each extra data chunk
46
47    sector map structure
48   0x0     = track number
49    0x1     = head
50    0x2     = sector number
51    0x3     = sector size (in 128byte chunks)
52    0x4     = MFM/FM (1 = MFM, 0 = FM)?
53    0x5     = DDAM/DAM (1 = DDAM, 0 = DAM)
54    0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
55    0xA     = RETRY DATA (1 = Yes, 0 = No)
56    0xB     = PDA (disk type)
57    0xC-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
58
59    extra data map structure
60    0x0     = command
61    0x1     = track number
62    0x2     = head
63    0x3     = sector number
64    0x4     = sector size (in 128byte chunks)
65    0x5-0x8 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
66    0x9     = Number of times to RETRY loading data
67    0xA-0xD = length of RETRY DATA
68    0xE     = PDA (disk type)
69    0xF     = reserved and equal to 0x00 (possibly available for future format extensions?)
70
71    TODO:
72    - add support for write protect header bit? apparently, some disks try to write and
73      fail to boot if they succeed which is the reason this bit was added
74    - add support for DDAM in Rev. 0 (need an image which set it in some sector)
75    - investigate the READ DATA bytes of sector headers
76    - investigate RETRY DATA chunks
77 
78 *********************************************************************/
79
80#include "emu.h"
81#include "pc98nfd_dsk.h"
82
83pc98nfd_format::pc98nfd_format()
84{
85}
86
87const char *pc98nfd_format::name() const
88{
89   return "pc98_nfd";
90}
91
92const char *pc98nfd_format::description() const
93{
94   return "PC98 NFD disk image";
95}
96
97const char *pc98nfd_format::extensions() const
98{
99   return "nfd";
100}
101
102int pc98nfd_format::identify(io_generic *io, UINT32 form_factor)
103{
104   UINT8 h[16];   
105   io_generic_read(io, h, 0, 16);
106   
107   if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0)
108      return 100;
109
110   return 0;
111}
112
113bool pc98nfd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
114{
115   UINT64 size = io_generic_size(io);
116   UINT8 h[0x120], hsec[0x10];   
117   io_generic_read(io, h, 0, 0x120);
118   int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
119
120   // sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
121   UINT8 disk_type = 0;
122   UINT8 num_secs[164];
123   UINT8 num_specials[164];
124   UINT32 track_sizes[164];
125   UINT8 tracks[164 * 26];
126   UINT8 heads[164 * 26];
127   UINT8 secs[164 * 26];
128   UINT8 mfm[164 * 26];
129   UINT8 sec_sizes[164 * 26];
130
131   UINT32 hsize = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x110));
132
133   int pos = 0x120;
134
135   // set up sector map
136   if (format_version == 1)
137   {
138      for (int track = 0; track < 164; track++)
139      {
140         int curr_track_size = 0;
141         // read sector map absolute location
142         io_generic_read(io, hsec, pos, 4);
143         pos += 4;
144         UINT32 secmap_addr = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec));
145
146         if (secmap_addr)
147         {
148            // read actual sector map for the sectors of this track
149            // for rev.1 format the first 0x10 are a track summary:
150            // first WORD is # of sectors, second WORD is # of special data sectors
151            io_generic_read(io, hsec, secmap_addr, 0x10);
152            secmap_addr += 0x10;
153            num_secs[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec));
154            num_specials[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec + 0x2));
155
156            for (int sect = 0; sect < num_secs[track]; sect++)
157            {
158               io_generic_read(io, hsec, secmap_addr, 0x10);
159               
160               if (track == 0 && sect == 0)
161                  disk_type = hsec[0xb];   // can this change across the disk? I don't think so...
162               secmap_addr += 0x10;
163               
164               tracks[(track * 26) + sect] = hsec[0];
165               heads[(track * 26) + sect] = hsec[1];
166               secs[(track * 26) + sect] = hsec[2];
167               sec_sizes[(track * 26) + sect] = hsec[3];
168               mfm[(track * 26) + sect] = hsec[4];
169               
170               curr_track_size += (128 << hsec[3]);
171            }
172
173            if (num_specials[track] > 0)
174            {
175               for (int sect = 0; sect < num_specials[track]; sect++)
176               {
177                  io_generic_read(io, hsec, secmap_addr, 0x10);   
178                  secmap_addr += 0x10;
179                  curr_track_size += (hsec[9] + 1) * LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x0a));
180               }
181            }
182         }
183         else
184         {
185            num_secs[track] = 0;
186            num_specials[track] = 0;
187         }
188         track_sizes[track] = curr_track_size;
189      }
190   }
191   else
192   {
193      for (int track = 0; track < 163 && pos < hsize; track++)
194      {
195         int curr_num_sec = 0, curr_track_size = 0;
196         for (int sect = 0; sect < 26; sect++)
197         {
198            // read sector map for this sector
199            // for rev.0 format each sector uses 0x10 bytes
200            io_generic_read(io, hsec, pos, 0x10);
201
202            if (track == 0 && sect == 0)
203               disk_type = hsec[0xa];   // can this change across the disk? I don't think so...
204            pos += 0x10;
205           
206            if (hsec[0] == 0xff)   // unformatted/unused sector
207               continue;
208           
209            tracks[(track * 26) + sect] = hsec[0];
210            heads[(track * 26) + sect] = hsec[1];
211            secs[(track * 26) + sect] = hsec[2];
212            sec_sizes[(track * 26) + sect] = hsec[3];
213            mfm[(track * 26) + sect] = hsec[4];
214           
215            curr_track_size += (128 << hsec[3]);
216            curr_num_sec++;
217         }
218
219         num_secs[track] = curr_num_sec;
220         track_sizes[track] = curr_track_size;
221      }
222   }
223
224   // shouln't this be set-up depending on disk_type? gaplus does not like having less than 166666 cells
225   int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
226
227   switch (disk_type)
228   {
229      case 0x10:   // 640K disk, 2DD
230         image->set_variant(floppy_image::DSDD);
231         break;
232      //case 0x30:   // 1.44M disk, ?? (no images found)
233      //   break;
234      case 0x90:   // 1.2M disk, 2HD
235      default:
236         image->set_variant(floppy_image::DSHD);
237         break;
238   }
239
240   desc_pc_sector sects[256];
241   UINT8 sect_data[65536];
242   int cur_sec_map = 0, sector_size;
243   pos = hsize;
244
245   for (int track = 0; track < 163 && pos < size; track++)
246   {
247      io_generic_read(io, sect_data, pos, track_sizes[track]);
248
249      for (int i = 0; i < num_secs[track]; i++)
250      {
251         cur_sec_map = track * 26 + i;
252         sector_size = 128 << sec_sizes[cur_sec_map];
253         sects[i].track       = tracks[cur_sec_map];
254         sects[i].head        = heads[cur_sec_map];
255         sects[i].sector      = secs[cur_sec_map];
256         sects[i].size        = sec_sizes[cur_sec_map];
257         sects[i].actual_size = sector_size;
258         sects[i].deleted     = false;
259         sects[i].bad_crc     = false;
260         sects[i].data        = sect_data + i * sector_size;
261      }
262      pos += track_sizes[track];
263
264      // notice that the operation below might fail if sectors of the same track have variable sec_sizes,
265      // because the gap3 calculation would account correctly only for the first sector...
266      // examined images had constant sec_sizes in the each track, so probably this is not an issue
267      if (mfm[track * 26])
268         build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
269      else
270         build_pc_track_fm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
271   }
272   
273   return true;
274}
275
276bool pc98nfd_format::supports_save() const
277{
278   return false;
279}
280
281const floppy_format_type FLOPPY_PC98NFD_FORMAT = &floppy_image_format_creator<pc98nfd_format>;
trunk/src/lib/formats/pc98nfd_dsk.h
r242336r242337
1/*********************************************************************
2
3    formats/pc98nfd_dsk.h
4
5    PC98NFD disk images
6
7*********************************************************************/
8
9#ifndef PC98NFD_DSK_H
10#define PC98NFD_DSK_H
11
12#include "flopimg.h"
13
14
15class pc98nfd_format : public floppy_image_format_t
16{
17public:
18   pc98nfd_format();
19
20   virtual int identify(io_generic *io, UINT32 form_factor);
21   virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
22
23   virtual const char *name() const;
24   virtual const char *description() const;
25   virtual const char *extensions() const;
26   virtual bool supports_save() const;
27};
28
29extern const floppy_format_type FLOPPY_PC98NFD_FORMAT;
30
31#endif /* PC98NFD_DSK_H */
trunk/src/lib/lib.mak
r242336r242337
138138   $(LIBOBJ)/formats/d81_dsk.o     \
139139   $(LIBOBJ)/formats/d82_dsk.o     \
140140   $(LIBOBJ)/formats/d88_dsk.o     \
141   $(LIBOBJ)/formats/dcp_dsk.o     \
141142   $(LIBOBJ)/formats/dfi_dsk.o     \
142143   $(LIBOBJ)/formats/dim_dsk.o     \
144   $(LIBOBJ)/formats/dip_dsk.o     \
143145   $(LIBOBJ)/formats/dmk_dsk.o     \
144146   $(LIBOBJ)/formats/dmv_dsk.o     \
145147   $(LIBOBJ)/formats/dsk_dsk.o     \
r242336r242337
148150   $(LIBOBJ)/formats/esq16_dsk.o   \
149151   $(LIBOBJ)/formats/fc100_cas.o   \
150152   $(LIBOBJ)/formats/fdi_dsk.o     \
153   $(LIBOBJ)/formats/fdd_dsk.o     \
151154   $(LIBOBJ)/formats/flex_dsk.o    \
152155   $(LIBOBJ)/formats/fm7_cas.o     \
153156   $(LIBOBJ)/formats/fmsx_cas.o    \
r242336r242337
175178   $(LIBOBJ)/formats/nanos_dsk.o   \
176179   $(LIBOBJ)/formats/naslite_dsk.o \
177180   $(LIBOBJ)/formats/nes_dsk.o     \
181   $(LIBOBJ)/formats/nfd_dsk.o     \
178182   $(LIBOBJ)/formats/orao_cas.o    \
179183   $(LIBOBJ)/formats/oric_dsk.o    \
180184   $(LIBOBJ)/formats/oric_tap.o    \
r242336r242337
183187   $(LIBOBJ)/formats/pc_dsk.o      \
184188   $(LIBOBJ)/formats/pc98_dsk.o    \
185189   $(LIBOBJ)/formats/pc98fdi_dsk.o \
186   $(LIBOBJ)/formats/pc98fdd_dsk.o \
187   $(LIBOBJ)/formats/pc98dcp_dsk.o \
188   $(LIBOBJ)/formats/pc98dip_dsk.o \
189   $(LIBOBJ)/formats/pc98nfd_dsk.o \
190190   $(LIBOBJ)/formats/phc25_cas.o   \
191191   $(LIBOBJ)/formats/pmd_cas.o     \
192192   $(LIBOBJ)/formats/primoptp.o    \
trunk/src/mess/drivers/pc9801.c
r242336r242337
416416
417417#include "formats/pc98_dsk.h"
418418#include "formats/pc98fdi_dsk.h"
419#include "formats/pc98fdd_dsk.h"
420#include "formats/pc98dcp_dsk.h"
421#include "formats/pc98dip_dsk.h"
422#include "formats/pc98nfd_dsk.h"
419#include "formats/fdd_dsk.h"
420#include "formats/dcp_dsk.h"
421#include "formats/dip_dsk.h"
422#include "formats/nfd_dsk.h"
423423
424424#include "machine/pc9801_26.h"
425425#include "machine/pc9801_86.h"
r242336r242337
31003100FLOPPY_FORMATS_MEMBER( pc9801_state::floppy_formats )
31013101   FLOPPY_PC98_FORMAT,
31023102   FLOPPY_PC98FDI_FORMAT,
3103   FLOPPY_PC98FDD_FORMAT,
3104   FLOPPY_PC98DCP_FORMAT,
3105   FLOPPY_PC98DIP_FORMAT,
3106   FLOPPY_PC98NFD_FORMAT
3103   FLOPPY_FDD_FORMAT,
3104   FLOPPY_DCP_FORMAT,
3105   FLOPPY_DIP_FORMAT,
3106   FLOPPY_NFD_FORMAT
31073107FLOPPY_FORMATS_END
31083108
31093109TIMER_DEVICE_CALLBACK_MEMBER( pc9801_state::mouse_irq_cb )


Previous 199869 Revisions Next


© 1997-2024 The MAME Team