mirror of
https://github.com/holub/mame
synced 2025-06-04 03:46:29 +03:00
(MESS) pc98: added preliminary support for disks in DCP, DCU, DIP
and NFD formats. [Fabio Priuli]
This commit is contained in:
parent
6082fc6772
commit
83e89c1ff9
@ -75,7 +75,7 @@ const pc98_format::format pc98_format::formats[] = {
|
||||
},
|
||||
{ /* 2880K 3 1/2 inch extended density - gaps unverified */
|
||||
floppy_image::FF_35, floppy_image::DSED, floppy_image::MFM,
|
||||
500, 36, 80, 2, 512, {}, 1, {}, 80, 50, 41, 80
|
||||
500, 36, 80, 2, 512, {}, 1, {}, 80, 50, 41, 80
|
||||
},
|
||||
{
|
||||
floppy_image::FF_525, floppy_image::DSHD, floppy_image::MFM,
|
||||
|
301
src/lib/formats/pc98dcp_dsk.c
Normal file
301
src/lib/formats/pc98dcp_dsk.c
Normal file
@ -0,0 +1,301 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:etabeta
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98dcp_dsk.h
|
||||
|
||||
PC98 DCP & DCU disk images
|
||||
|
||||
0xA2 header, followed by track data
|
||||
header[0] - disk format
|
||||
header[1-0xA1] - track map (1=track used, 0=track unused/unformatted)
|
||||
header[0xA2] - all tracks used?
|
||||
(there seems to be a diff in its usage between DCP and DCU)
|
||||
|
||||
TODO:
|
||||
- add support for track map. images available for tests were all
|
||||
of type 0x01, with all 154 tracks present. combined with pete_j
|
||||
reporting some images have faulty track map, we need some more
|
||||
test cases to properly handle these disks!
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "pc98dcp_dsk.h"
|
||||
|
||||
pc98dcp_format::pc98dcp_format()
|
||||
{
|
||||
}
|
||||
|
||||
const char *pc98dcp_format::name() const
|
||||
{
|
||||
return "pc98_dcx";
|
||||
}
|
||||
|
||||
const char *pc98dcp_format::description() const
|
||||
{
|
||||
return "PC98 DCP/DCU disk image";
|
||||
}
|
||||
|
||||
const char *pc98dcp_format::extensions() const
|
||||
{
|
||||
return "dcp,dcu";
|
||||
}
|
||||
|
||||
int pc98dcp_format::identify(io_generic *io, UINT32 form_factor)
|
||||
{
|
||||
UINT64 size = io_generic_size(io);
|
||||
UINT8 h[0xa2];
|
||||
int heads, tracks, spt, bps, count_tracks = 0;
|
||||
bool is_hdb = false;
|
||||
|
||||
io_generic_read(io, h, 0, 0xa2);
|
||||
|
||||
// First byte is the disk format (see below in load() for details)
|
||||
switch (h[0])
|
||||
{
|
||||
case 0x01:
|
||||
default:
|
||||
heads = 2; tracks = 77;
|
||||
spt = 8; bps = 1024;
|
||||
break;
|
||||
case 0x02:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 15; bps = 512;
|
||||
break;
|
||||
case 0x03:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 18; bps = 512;
|
||||
break;
|
||||
case 0x04:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 8; bps = 512;
|
||||
break;
|
||||
case 0x05:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 9; bps = 512;
|
||||
break;
|
||||
case 0x08:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 9; bps = 1024;
|
||||
break;
|
||||
case 0x11:
|
||||
is_hdb = true;
|
||||
heads = 2; tracks = 77;
|
||||
spt = 26; bps = 256;
|
||||
break;
|
||||
case 0x19:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 16; bps = 256;
|
||||
break;
|
||||
case 0x21:
|
||||
heads = 2; tracks = 80;
|
||||
spt = 26; bps = 256;
|
||||
break;
|
||||
}
|
||||
|
||||
// bytes 0x01 to 0xa1 are track map (0x01 if track is used, 0x00 if track is unformatted/unused)
|
||||
for (int i = 1; i < 0xa1; i++)
|
||||
if (h[i])
|
||||
count_tracks++;
|
||||
|
||||
// in theory track map should be enough (former check), but some images have it wrong!
|
||||
// hence, if this check fails, we also allow for images with all tracks and wrong track map
|
||||
if (size - 0xa2 == (heads * count_tracks * spt * bps) || size - 0xa2 == (heads * tracks * spt * bps))
|
||||
return 100;
|
||||
|
||||
// for disk type 0x11 the head 0 track 0 has 26 sectors of half width, so we need to compensate calculation
|
||||
if (is_hdb && (size - 0xa2 + (0x80 * 26) == (heads * count_tracks * spt * bps) || size - 0xa2 + (0x80 * 26) == (heads * tracks * spt * bps)))
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pc98dcp_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
|
||||
{
|
||||
UINT8 h[0xa2];
|
||||
int heads, tracks, spt, bps;
|
||||
bool is_hdb = false;
|
||||
|
||||
io_generic_read(io, h, 0, 0xa2);
|
||||
|
||||
// First byte is the disk format:
|
||||
switch (h[0])
|
||||
{
|
||||
case 0x01:
|
||||
default:
|
||||
//01h: 2HD-8 sector (1.25MB) (BKDSK .HDM) (aka 2HS)
|
||||
//2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
|
||||
heads = 2;
|
||||
tracks = 77;
|
||||
spt = 8;
|
||||
bps = 1024;
|
||||
break;
|
||||
case 0x02:
|
||||
//02H: 2HD-15 sector (1.21MB) (BKDSK .HD5) (aka 2HC)
|
||||
//2 sides, 80 tracks, 15 sectors/track, 512 bytes/sector = 1228800 bytes (360rpm)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 15;
|
||||
bps = 512;
|
||||
break;
|
||||
case 0x03:
|
||||
//03H: 2HQ-18 sector (1.44MB) (BKDSK .HD4) (aka 2HDE)
|
||||
//2 sides, 80 tracks, 18 sectors/track, 512 bytes/sector = 1474560 bytes (300rpm)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 18;
|
||||
bps = 512;
|
||||
break;
|
||||
case 0x04:
|
||||
//04H: 2DD-8 sector (640KB) (BKDSK .DD6)
|
||||
//2 sides, 80 tracks, 8 sectors/track, 512 bytes/sector = 655360 bytes (300rpm)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 8;
|
||||
bps = 512;
|
||||
break;
|
||||
case 0x05:
|
||||
//05h: 2DD-9 sector ( 720KB) (BKDSK .DD9)
|
||||
//2 sides, 80 tracks, 9 sectors/track, 512 bytes/sector = 737280 bytes (300rpm)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 9;
|
||||
bps = 512;
|
||||
break;
|
||||
case 0x08:
|
||||
//08h: 2HD-9 sector (1.44MB)
|
||||
//2 sides, 80 tracks, 9 sectors/track, 1024 bytes/sector = 1474560 bytes (300rpm)(??)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 9;
|
||||
bps = 1024;
|
||||
break;
|
||||
case 0x11:
|
||||
//11h: BASIC-2HD (BKDSK .HDB)
|
||||
//Head 0 Track 0 - FM encoding - 26 sectors of 128 bytes = 1 track
|
||||
//Head 1 Track 0 - MFM encoding - 26 sectors of 256 bytes = 1 track
|
||||
//Head 0 Track 1 to Head 1 Track 77 - 26 sectors of 256 bytes = 152 tracks
|
||||
//2 sides, 77 tracks, 26 sectors/track, 256 bytes/sector (except for head 0 track 0) = 1021696 bytes (360rpm)
|
||||
is_hdb = true;
|
||||
heads = 2;
|
||||
tracks = 77;
|
||||
spt = 26;
|
||||
bps = 256;
|
||||
break;
|
||||
case 0x19:
|
||||
//19h: BASIC 2DD (BKDSK .DDB)
|
||||
//2 sides, 80 tracks, 16 sectors/track, 256 bytes/sector = 655360 bytes (300rpm)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 16;
|
||||
bps = 256;
|
||||
break;
|
||||
case 0x21:
|
||||
//21H: 2HD-26 sector
|
||||
//2 sides, 80 tracks, 26 sectors/track, 256 bytes/sector = 1064960 bytes (??rpm)(??)
|
||||
heads = 2;
|
||||
tracks = 80;
|
||||
spt = 26;
|
||||
bps = 256;
|
||||
break;
|
||||
}
|
||||
|
||||
int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
|
||||
|
||||
int ssize;
|
||||
for (ssize = 0; (128 << ssize) < bps; ssize++);
|
||||
|
||||
desc_pc_sector sects[256];
|
||||
UINT8 sect_data[bps * spt];
|
||||
|
||||
if (!is_hdb)
|
||||
{
|
||||
for (int track = 0; track < tracks; track++)
|
||||
for (int head = 0; head < heads; head++)
|
||||
{
|
||||
io_generic_read(io, sect_data, 0xa2 + bps * spt * (track * heads + head), bps * spt);
|
||||
|
||||
for (int i = 0; i < spt; i++)
|
||||
{
|
||||
sects[i].track = track;
|
||||
sects[i].head = head;
|
||||
sects[i].sector = i + 1;
|
||||
sects[i].size = ssize;
|
||||
sects[i].actual_size = bps;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * bps;
|
||||
}
|
||||
|
||||
build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
|
||||
}
|
||||
}
|
||||
else // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
|
||||
{
|
||||
// Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
|
||||
io_generic_read(io, sect_data, 0xa2, 128 * spt);
|
||||
|
||||
for (int i = 0; i < spt; i++)
|
||||
{
|
||||
sects[i].track = 0;
|
||||
sects[i].head = 0;
|
||||
sects[i].sector = i + 1;
|
||||
sects[i].size = 0;
|
||||
sects[i].actual_size = 128;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * 128;
|
||||
}
|
||||
|
||||
build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));
|
||||
|
||||
// Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
|
||||
io_generic_read(io, sect_data, 0xa2 + 128 * spt, bps * spt);
|
||||
|
||||
for (int i = 0; i < spt; i++)
|
||||
{
|
||||
sects[i].track = 0;
|
||||
sects[i].head = 1;
|
||||
sects[i].sector = i + 1;
|
||||
sects[i].size = ssize;
|
||||
sects[i].actual_size = bps;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * bps;
|
||||
}
|
||||
|
||||
build_pc_track_mfm(0, 1, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
|
||||
|
||||
// Read other tracks as usual
|
||||
UINT32 data_offs = 0xa2 + (26 * 0x80) + (26 * 0x100);
|
||||
for (int track = 1; track < tracks; track++)
|
||||
for (int head = 0; head < heads; head++)
|
||||
{
|
||||
io_generic_read(io, sect_data, data_offs + bps * spt * ((track - 1) * heads + head), bps * spt);
|
||||
|
||||
for (int i = 0; i < spt; i++)
|
||||
{
|
||||
sects[i].track = track;
|
||||
sects[i].head = head;
|
||||
sects[i].sector = i + 1;
|
||||
sects[i].size = ssize;
|
||||
sects[i].actual_size = bps;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * bps;
|
||||
}
|
||||
|
||||
build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pc98dcp_format::supports_save() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const floppy_format_type FLOPPY_PC98DCP_FORMAT = &floppy_image_format_creator<pc98dcp_format>;
|
31
src/lib/formats/pc98dcp_dsk.h
Normal file
31
src/lib/formats/pc98dcp_dsk.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98dcp_dsk.h
|
||||
|
||||
PC98 DCP & DCU disk images
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef PC98DCP_DSK_H
|
||||
#define PC98DCP_DSK_H
|
||||
|
||||
#include "flopimg.h"
|
||||
|
||||
|
||||
class pc98dcp_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
pc98dcp_format();
|
||||
|
||||
virtual int identify(io_generic *io, UINT32 form_factor);
|
||||
virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
|
||||
|
||||
virtual const char *name() const;
|
||||
virtual const char *description() const;
|
||||
virtual const char *extensions() const;
|
||||
virtual bool supports_save() const;
|
||||
};
|
||||
|
||||
extern const floppy_format_type FLOPPY_PC98DCP_FORMAT;
|
||||
|
||||
#endif /* PC98DCP_DSK_H */
|
96
src/lib/formats/pc98dip_dsk.c
Normal file
96
src/lib/formats/pc98dip_dsk.c
Normal file
@ -0,0 +1,96 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:etabeta
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98dip_dsk.h
|
||||
|
||||
PC98DIP disk images
|
||||
|
||||
0x100 header, followed by track data
|
||||
|
||||
TODO:
|
||||
- Investigate header structure
|
||||
- can this format be used to support different disc types?
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "pc98dip_dsk.h"
|
||||
|
||||
pc98dip_format::pc98dip_format()
|
||||
{
|
||||
}
|
||||
|
||||
const char *pc98dip_format::name() const
|
||||
{
|
||||
return "pc98_dip";
|
||||
}
|
||||
|
||||
const char *pc98dip_format::description() const
|
||||
{
|
||||
return "PC98 DIP disk image";
|
||||
}
|
||||
|
||||
const char *pc98dip_format::extensions() const
|
||||
{
|
||||
return "dip";
|
||||
}
|
||||
|
||||
int pc98dip_format::identify(io_generic *io, UINT32 form_factor)
|
||||
{
|
||||
UINT64 size = io_generic_size(io);
|
||||
|
||||
if (size == 0x134000 + 0x100)
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pc98dip_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
|
||||
{
|
||||
int heads, tracks, spt, bps;
|
||||
|
||||
//For the moment we only support this disk structure...
|
||||
//2 sides, 77 tracks, 8 sectors/track, 1024 bytes/sector = 1261568 bytes (360rpm)
|
||||
heads = 2;
|
||||
tracks = 77;
|
||||
spt = 8;
|
||||
bps = 1024;
|
||||
|
||||
int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
|
||||
|
||||
int ssize;
|
||||
for (ssize = 0; (128 << ssize) < bps; ssize++);
|
||||
|
||||
desc_pc_sector sects[256];
|
||||
UINT8 sect_data[bps * spt];
|
||||
|
||||
for (int track = 0; track < tracks; track++)
|
||||
for (int head = 0; head < heads; head++)
|
||||
{
|
||||
io_generic_read(io, sect_data, 0x100 + bps * spt * (track * heads + head), bps * spt);
|
||||
|
||||
for (int i = 0; i < spt; i++)
|
||||
{
|
||||
sects[i].track = track;
|
||||
sects[i].head = head;
|
||||
sects[i].sector = i + 1;
|
||||
sects[i].size = ssize;
|
||||
sects[i].actual_size = bps;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * bps;
|
||||
}
|
||||
|
||||
build_pc_track_mfm(track, head, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, bps));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pc98dip_format::supports_save() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const floppy_format_type FLOPPY_PC98DIP_FORMAT = &floppy_image_format_creator<pc98dip_format>;
|
31
src/lib/formats/pc98dip_dsk.h
Normal file
31
src/lib/formats/pc98dip_dsk.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98dip_dsk.h
|
||||
|
||||
PC98DIP disk images
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef PC98DIP_DSK_H
|
||||
#define PC98DIP_DSK_H
|
||||
|
||||
#include "flopimg.h"
|
||||
|
||||
|
||||
class pc98dip_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
pc98dip_format();
|
||||
|
||||
virtual int identify(io_generic *io, UINT32 form_factor);
|
||||
virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
|
||||
|
||||
virtual const char *name() const;
|
||||
virtual const char *description() const;
|
||||
virtual const char *extensions() const;
|
||||
virtual bool supports_save() const;
|
||||
};
|
||||
|
||||
extern const floppy_format_type FLOPPY_PC98DIP_FORMAT;
|
||||
|
||||
#endif /* PC98DIP_DSK_H */
|
283
src/lib/formats/pc98nfd_dsk.c
Normal file
283
src/lib/formats/pc98nfd_dsk.c
Normal file
@ -0,0 +1,283 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:etabeta
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98nfd_dsk.h
|
||||
|
||||
PC98NFD disk images (info from: http://www.geocities.jp/t98next/dev.html )
|
||||
|
||||
Revision 0
|
||||
==========
|
||||
|
||||
header structure (variable length > 0x120, header length = DWORD at 0x110)
|
||||
0x000-0x00F = T98FDDIMAGE.R* followed by 2 0x00 bytes, * = format revision (0 or 1 so far)
|
||||
0x010-0x10F = space for image info / comments
|
||||
0x110-0x113 = header length (DWORD)
|
||||
0x114 = write protect (any value > 0 means not writeable)
|
||||
0x115 = number of heads
|
||||
0x116-0x11F = reserved
|
||||
0x120-EOHeader = sector map (0x10 for each sector of the disk!)
|
||||
last 0x10 are fixed to 0x00, probably it marks the end of sector map?
|
||||
|
||||
sector map structure
|
||||
0x0 = track number
|
||||
0x1 = head
|
||||
0x2 = sector number
|
||||
0x3 = sector size (in 128byte chunks)
|
||||
0x4 = MFM/FM (1 = MFM, 0 = FM)?
|
||||
0x5 = DDAM/DAM (1 = DDAM, 0 = DAM)
|
||||
0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
|
||||
0xA = PDA (disk type)
|
||||
0xB-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
|
||||
|
||||
|
||||
Revision 1
|
||||
==========
|
||||
|
||||
header structure (variable length > 0x120, header length = DWORD at 0x110)
|
||||
0x000-0x11F = same as Rev. 0 format
|
||||
0x120-0x3AF = 164 DWORDs containing, for each track, the absolute position of the sector maps
|
||||
for sectors of the track. for unformatted/unused tracks 0 is used
|
||||
0x3B0-0x3B3 = absolute position of addintional info in the header, if any
|
||||
0x3B4-0x3BF = reserved
|
||||
0x120-EOHeader = sector map + special data for each track:
|
||||
first 0x10 of each track = #sectors (WORD), #extra data (WORD), reserved 0xc bytes zeroed
|
||||
then 0x10 for each sector of this track and 0x10 for each extra data chunk
|
||||
|
||||
sector map structure
|
||||
0x0 = track number
|
||||
0x1 = head
|
||||
0x2 = sector number
|
||||
0x3 = sector size (in 128byte chunks)
|
||||
0x4 = MFM/FM (1 = MFM, 0 = FM)?
|
||||
0x5 = DDAM/DAM (1 = DDAM, 0 = DAM)
|
||||
0x6-0x9 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
|
||||
0xA = RETRY DATA (1 = Yes, 0 = No)
|
||||
0xB = PDA (disk type)
|
||||
0xC-0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
|
||||
|
||||
extra data map structure
|
||||
0x0 = command
|
||||
0x1 = track number
|
||||
0x2 = head
|
||||
0x3 = sector number
|
||||
0x4 = sector size (in 128byte chunks)
|
||||
0x5-0x8 = READ DATA (FDDBIOS) Results (Status, St0, St1, St2) ??
|
||||
0x9 = Number of times to RETRY loading data
|
||||
0xA-0xD = length of RETRY DATA
|
||||
0xE = PDA (disk type)
|
||||
0xF = reserved and equal to 0x00 (possibly available for future format extensions?)
|
||||
|
||||
TODO:
|
||||
- add support for write protect header bit? apparently, some disks try to write and
|
||||
fail to boot if they succeed which is the reason this bit was added
|
||||
- add support for DDAM in Rev. 0 (need an image which set it in some sector)
|
||||
- investigate the READ DATA bytes of sector headers
|
||||
- investigate RETRY DATA chunks
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "pc98nfd_dsk.h"
|
||||
|
||||
pc98nfd_format::pc98nfd_format()
|
||||
{
|
||||
}
|
||||
|
||||
const char *pc98nfd_format::name() const
|
||||
{
|
||||
return "pc98_nfd";
|
||||
}
|
||||
|
||||
const char *pc98nfd_format::description() const
|
||||
{
|
||||
return "PC98 NFD disk image";
|
||||
}
|
||||
|
||||
const char *pc98nfd_format::extensions() const
|
||||
{
|
||||
return "nfd";
|
||||
}
|
||||
|
||||
int pc98nfd_format::identify(io_generic *io, UINT32 form_factor)
|
||||
{
|
||||
UINT8 h[16];
|
||||
io_generic_read(io, h, 0, 16);
|
||||
|
||||
if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0)
|
||||
return 100;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pc98nfd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
|
||||
{
|
||||
UINT64 size = io_generic_size(io);
|
||||
UINT8 h[0x120], hsec[0x10];
|
||||
io_generic_read(io, h, 0, 0x120);
|
||||
int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
|
||||
|
||||
// sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
|
||||
UINT8 disk_type = 0;
|
||||
UINT8 num_secs[164];
|
||||
UINT8 num_specials[164];
|
||||
UINT32 track_sizes[164];
|
||||
UINT8 tracks[164 * 26];
|
||||
UINT8 heads[164 * 26];
|
||||
UINT8 secs[164 * 26];
|
||||
UINT8 mfm[164 * 26];
|
||||
UINT8 sec_sizes[164 * 26];
|
||||
|
||||
UINT32 hsize = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(h+0x110));
|
||||
|
||||
int pos = 0x120;
|
||||
|
||||
// set up sector map
|
||||
if (format_version == 1)
|
||||
{
|
||||
for (int track = 0; track < 164; track++)
|
||||
{
|
||||
int curr_track_size = 0;
|
||||
// read sector map absolute location
|
||||
io_generic_read(io, hsec, pos, 4);
|
||||
pos += 4;
|
||||
UINT32 secmap_addr = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec));
|
||||
|
||||
if (secmap_addr)
|
||||
{
|
||||
// read actual sector map for the sectors of this track
|
||||
// for rev.1 format the first 0x10 are a track summary:
|
||||
// first WORD is # of sectors, second WORD is # of special data sectors
|
||||
io_generic_read(io, hsec, secmap_addr, 0x10);
|
||||
secmap_addr += 0x10;
|
||||
num_secs[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec));
|
||||
num_specials[track] = LITTLE_ENDIANIZE_INT16(*(UINT16 *)(hsec + 0x2));
|
||||
|
||||
for (int sect = 0; sect < num_secs[track]; sect++)
|
||||
{
|
||||
io_generic_read(io, hsec, secmap_addr, 0x10);
|
||||
|
||||
if (track == 0 && sect == 0)
|
||||
disk_type = hsec[0xb]; // can this change across the disk? I don't think so...
|
||||
secmap_addr += 0x10;
|
||||
|
||||
tracks[(track * 26) + sect] = hsec[0];
|
||||
heads[(track * 26) + sect] = hsec[1];
|
||||
secs[(track * 26) + sect] = hsec[2];
|
||||
sec_sizes[(track * 26) + sect] = hsec[3];
|
||||
mfm[(track * 26) + sect] = hsec[4];
|
||||
|
||||
curr_track_size += (128 << hsec[3]);
|
||||
}
|
||||
|
||||
if (num_specials[track] > 0)
|
||||
{
|
||||
for (int sect = 0; sect < num_specials[track]; sect++)
|
||||
{
|
||||
io_generic_read(io, hsec, secmap_addr, 0x10);
|
||||
secmap_addr += 0x10;
|
||||
curr_track_size += (hsec[9] + 1) * LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x0a));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num_secs[track] = 0;
|
||||
num_specials[track] = 0;
|
||||
}
|
||||
track_sizes[track] = curr_track_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int track = 0; track < 163 && pos < hsize; track++)
|
||||
{
|
||||
int curr_num_sec = 0, curr_track_size = 0;
|
||||
for (int sect = 0; sect < 26; sect++)
|
||||
{
|
||||
// read sector map for this sector
|
||||
// for rev.0 format each sector uses 0x10 bytes
|
||||
io_generic_read(io, hsec, pos, 0x10);
|
||||
|
||||
if (track == 0 && sect == 0)
|
||||
disk_type = hsec[0xa]; // can this change across the disk? I don't think so...
|
||||
pos += 0x10;
|
||||
|
||||
if (hsec[0] == 0xff) // unformatted/unused sector
|
||||
continue;
|
||||
|
||||
tracks[(track * 26) + sect] = hsec[0];
|
||||
heads[(track * 26) + sect] = hsec[1];
|
||||
secs[(track * 26) + sect] = hsec[2];
|
||||
sec_sizes[(track * 26) + sect] = hsec[3];
|
||||
mfm[(track * 26) + sect] = hsec[4];
|
||||
|
||||
curr_track_size += (128 << hsec[3]);
|
||||
curr_num_sec++;
|
||||
}
|
||||
if (num_specials[track] > 0)
|
||||
{
|
||||
}
|
||||
num_secs[track] = curr_num_sec;
|
||||
track_sizes[track] = curr_track_size;
|
||||
}
|
||||
}
|
||||
|
||||
// shouln't this be set-up depending on disk_type? gaplus does not like having less than 166666 cells
|
||||
int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
|
||||
|
||||
switch (disk_type)
|
||||
{
|
||||
case 0x10: // 640K disk, 2DD
|
||||
image->set_variant(floppy_image::DSDD);
|
||||
break;
|
||||
//case 0x30: // 1.44M disk, ?? (no images found)
|
||||
// break;
|
||||
case 0x90: // 1.2M disk, 2HD
|
||||
default:
|
||||
image->set_variant(floppy_image::DSHD);
|
||||
break;
|
||||
}
|
||||
|
||||
desc_pc_sector sects[256];
|
||||
UINT8 sect_data[65536];
|
||||
int cur_sec_map = 0, sector_size;
|
||||
pos = hsize;
|
||||
|
||||
for (int track = 0; track < 163 && pos < size; track++)
|
||||
{
|
||||
io_generic_read(io, sect_data, pos, track_sizes[track]);
|
||||
|
||||
for (int i = 0; i < num_secs[track]; i++)
|
||||
{
|
||||
cur_sec_map = track * 26 + i;
|
||||
sector_size = 128 << sec_sizes[cur_sec_map];
|
||||
sects[i].track = tracks[cur_sec_map];
|
||||
sects[i].head = heads[cur_sec_map];
|
||||
sects[i].sector = secs[cur_sec_map];
|
||||
sects[i].size = sec_sizes[cur_sec_map];
|
||||
sects[i].actual_size = sector_size;
|
||||
sects[i].deleted = false;
|
||||
sects[i].bad_crc = false;
|
||||
sects[i].data = sect_data + i * sector_size;
|
||||
}
|
||||
pos += track_sizes[track];
|
||||
|
||||
// notice that the operation below might fail if sectors of the same track have variable sec_sizes,
|
||||
// because the gap3 calculation would account correctly only for the first sector...
|
||||
// examined images had constant sec_sizes in the each track, so probably this is not an issue
|
||||
if (mfm[track * 26])
|
||||
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])));
|
||||
else
|
||||
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])));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pc98nfd_format::supports_save() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const floppy_format_type FLOPPY_PC98NFD_FORMAT = &floppy_image_format_creator<pc98nfd_format>;
|
31
src/lib/formats/pc98nfd_dsk.h
Normal file
31
src/lib/formats/pc98nfd_dsk.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*********************************************************************
|
||||
|
||||
formats/pc98nfd_dsk.h
|
||||
|
||||
PC98NFD disk images
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef PC98NFD_DSK_H
|
||||
#define PC98NFD_DSK_H
|
||||
|
||||
#include "flopimg.h"
|
||||
|
||||
|
||||
class pc98nfd_format : public floppy_image_format_t
|
||||
{
|
||||
public:
|
||||
pc98nfd_format();
|
||||
|
||||
virtual int identify(io_generic *io, UINT32 form_factor);
|
||||
virtual bool load(io_generic *io, UINT32 form_factor, floppy_image *image);
|
||||
|
||||
virtual const char *name() const;
|
||||
virtual const char *description() const;
|
||||
virtual const char *extensions() const;
|
||||
virtual bool supports_save() const;
|
||||
};
|
||||
|
||||
extern const floppy_format_type FLOPPY_PC98NFD_FORMAT;
|
||||
|
||||
#endif /* PC98NFD_DSK_H */
|
@ -183,6 +183,9 @@ FORMATSOBJS = \
|
||||
$(LIBOBJ)/formats/pc_dsk.o \
|
||||
$(LIBOBJ)/formats/pc98_dsk.o \
|
||||
$(LIBOBJ)/formats/pc98fdi_dsk.o \
|
||||
$(LIBOBJ)/formats/pc98dcp_dsk.o \
|
||||
$(LIBOBJ)/formats/pc98dip_dsk.o \
|
||||
$(LIBOBJ)/formats/pc98nfd_dsk.o \
|
||||
$(LIBOBJ)/formats/phc25_cas.o \
|
||||
$(LIBOBJ)/formats/pmd_cas.o \
|
||||
$(LIBOBJ)/formats/primoptp.o \
|
||||
|
@ -416,6 +416,9 @@ Keyboard TX commands:
|
||||
|
||||
#include "formats/pc98_dsk.h"
|
||||
#include "formats/pc98fdi_dsk.h"
|
||||
#include "formats/pc98dcp_dsk.h"
|
||||
#include "formats/pc98dip_dsk.h"
|
||||
#include "formats/pc98nfd_dsk.h"
|
||||
|
||||
#include "machine/pc9801_26.h"
|
||||
#include "machine/pc9801_86.h"
|
||||
@ -2869,7 +2872,10 @@ INTERRUPT_GEN_MEMBER(pc9801_state::pc9801_vrtc_irq)
|
||||
|
||||
FLOPPY_FORMATS_MEMBER( pc9801_state::floppy_formats )
|
||||
FLOPPY_PC98_FORMAT,
|
||||
FLOPPY_PC98FDI_FORMAT
|
||||
FLOPPY_PC98FDI_FORMAT,
|
||||
FLOPPY_PC98DCP_FORMAT,
|
||||
FLOPPY_PC98DIP_FORMAT,
|
||||
FLOPPY_PC98NFD_FORMAT
|
||||
FLOPPY_FORMATS_END
|
||||
|
||||
TIMER_DEVICE_CALLBACK_MEMBER( pc9801_state::mouse_irq_cb )
|
||||
|
Loading…
Reference in New Issue
Block a user