summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fdd_dsk.c
blob: e9d76a99973e001d3f45846911741fcc34500dec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// license:BSD-3-Clause
// copyright-holders:etabeta
/*********************************************************************

    formats/fdd_dsk.h

    PC98 FDD disk images

    0xC3FC header, followed by track data
    Sector map starts at offset 0xDC, with 12bytes for each sector

    Each entry of the sector map has the following structure
    - 0x0 = track number (if 0xff the sector/track is unformatted/unused)
    - 0x1 = head number
    - 0x2 = sector number
    - 0x3 = sector size (128 << this byte)
    - 0x4 = fill byte. if it's not 0xff, then this sector in the original
            disk consisted of this single value repeated for the whole
            sector size, and the sector is skipped in the .fdd file.
            if it's 0xff, then this sector is wholly contained in the .fdd
            file
    - 0x5 = ??
    - 0x6 = ??
    - 0x7 = ??
    - 0x8-0x0b = absolute offset of the data for this sector, or 0xfffffff
                 if the sector was skipped in the .fdd (and it has to be
                 filled with the value at 0x4)

 TODO:
    - Investigate remaining sector map bytes (maybe related to protections?)

*********************************************************************/

#include "emu.h"
#include "fdd_dsk.h"

fdd_format::fdd_format()
{
}

const char *fdd_format::name() const
{
	return "fdd";
}

const char *fdd_format::description() const
{
	return "FDD disk image";
}

const char *fdd_format::extensions() const
{
	return "fdd";
}

int fdd_format::identify(io_generic *io, UINT32 form_factor)
{
	UINT8 h[7];
	io_generic_read(io, h, 0, 7);

	if (strncmp((const char *)h, "VFD1.0", 6) == 0)
		return 100;

	return 0;
}

bool fdd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT8 hsec[0x0c];

	// sector map
	UINT8 num_secs[160];
	UINT8 tracks[160 * 26];
	UINT8 heads[160 * 26];
	UINT8 secs[160 * 26];
	UINT8 fill_vals[160 * 26];
	UINT32 sec_offs[160 * 26];
	UINT8 sec_sizes[160 * 26];

	int pos = 0xdc;

	for (int track = 0; track < 160; track++)
	{
		int curr_num_sec = 0, curr_track_size = 0;
		for (int sect = 0; sect < 26; sect++)
		{
			// read sector map for this sector
			io_generic_read(io, hsec, pos, 0x0c);
			pos += 0x0c;

			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];
			fill_vals[(track * 26) + sect] = hsec[4];
			sec_offs[(track * 26) + sect] = LITTLE_ENDIANIZE_INT32(*(UINT32 *)(hsec + 0x08));

			curr_track_size += (128 << hsec[3]);
			curr_num_sec++;
		}
		num_secs[track] = curr_num_sec;
	}

	int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
	desc_pc_sector sects[256];
	UINT8 sect_data[65536];
	int cur_sec_map = 0, sector_size;

	for (int track = 0; track < 160; track++)
	{
		int cur_pos = 0;
		for (int i = 0; i < num_secs[track]; i++)
		{
			cur_sec_map = track * 26 + i;
			sector_size = 128 << sec_sizes[cur_sec_map];

			if (sec_offs[cur_sec_map] == 0xffffffff)
				memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
			else
				io_generic_read(io, sect_data + cur_pos, sec_offs[cur_sec_map], sector_size);

			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 + cur_pos;
			cur_pos += sector_size;
		}

		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])));
	}

	return true;
}

bool fdd_format::supports_save() const
{
	return false;
}

const floppy_format_type FLOPPY_FDD_FORMAT = &floppy_image_format_creator<fdd_format>;