summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/vdk_dsk.cpp
blob: 02e25ec5df9580cd5905aa17511f482dc1296fd0 (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
// license:BSD-3-Clause
// copyright-holders:Dirk Best
/***************************************************************************

    VDK

    Disk image format

    Used by Paul Burgin's PC-Dragon emulator

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

#include "vdk_dsk.h"

#include "ioprocs.h"


vdk_format::vdk_format()
{
}

const char *vdk_format::name() const noexcept
{
	return "vdk";
}

const char *vdk_format::description() const noexcept
{
	return "VDK disk image";
}

const char *vdk_format::extensions() const noexcept
{
	return "vdk";
}

int vdk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
	uint8_t id[2];
	auto const [err, actual] = read_at(io, 0, id, 2);
	if (err || (2 != actual))
		return 0;

	if (id[0] == 'd' && id[1] == 'k')
		return FIFID_SIGN;
	else
		return 0;
}

bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
	if (io.seek(0, SEEK_SET))
		return false;

	uint8_t header[0x100];
	read(io, header, 0x100); // FIXME: check for errors and premature EOF

	int const header_size = header[3] * 0x100 + header[2];
	int const track_count = header[8];
	int const head_count = header[9];

	if (io.seek(header_size, SEEK_SET))
		return false;

	for (int track = 0; track < track_count; track++)
	{
		for (int head = 0; head < head_count ; head++)
		{
			desc_pc_sector sectors[SECTOR_COUNT];
			uint8_t sector_data[SECTOR_COUNT * SECTOR_SIZE];
			int sector_offset = 0;

			for (int i = 0; i < SECTOR_COUNT; i++)
			{
				sectors[i].track = track;
				sectors[i].head = head;
				sectors[i].sector = FIRST_SECTOR_ID + i;
				sectors[i].actual_size = SECTOR_SIZE;
				sectors[i].size = SECTOR_SIZE >> 8;
				sectors[i].deleted = false;
				sectors[i].bad_crc = false;
				sectors[i].data = &sector_data[sector_offset];

				read(io, sectors[i].data, SECTOR_SIZE); // FIXME: check for errors and premature EOF

				sector_offset += SECTOR_SIZE;
			}

			build_wd_track_mfm(track, head, image, 100000, SECTOR_COUNT, sectors, 22, 32, 24);
		}
	}

	return true;
}

bool vdk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
	if (io.seek(0, SEEK_SET))
		return false;

	int track_count, head_count;
	image.get_actual_geometry(track_count, head_count);

	// write header
	uint8_t header[12];

	header[0] = 'd';
	header[1] = 'k';
	header[2] = sizeof(header) % 0x100;
	header[3] = sizeof(header) / 0x100;
	header[4] = 0x10;
	header[5] = 0x10;
	header[6] = 'M';
	header[7] = 0x01;
	header[8] = track_count;
	header[9] = head_count;
	header[10] = 0;
	header[11] = 0;

	write(io, header, sizeof(header)); // FIXME: check for errors

	// write disk data
	for (int track = 0; track < track_count; track++)
	{
		for (int head = 0; head < head_count; head++)
		{
			auto bitstream = generate_bitstream_from_track(track, head, 2000, image);
			auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);

			for (int i = 0; i < SECTOR_COUNT; i++)
				write(io, sectors[FIRST_SECTOR_ID + i].data(), SECTOR_SIZE); // FIXME: check for errors
		}
	}

	return true;
}

bool vdk_format::supports_save() const noexcept
{
	return true;
}

const vdk_format FLOPPY_VDK_FORMAT;