1 // license:BSD-3-Clause
2 // copyright-holders:Sergey Svishchev
3 /**********************************************************************
4 
5     formats/ds9_dsk.cpp
6 
7     Floppies used by Agat-9 840KB controller
8 
9     http://agatcomp.ru/Reading/docs/es5323.txt
10 
11     https://github.com/sintech/AGAT/blob/master/docs/agat-840k-format.txt
12 
13     http://www.torlus.com/floppy/forum/viewtopic.php?f=19&t=1385
14 
15 ************************************************************************/
16 
17 #include <cassert>
18 
19 #include "formats/ds9_dsk.h"
20 
21 
FLOPPY_IDENTIFY(ds9_dsk_identify)22 static FLOPPY_IDENTIFY(ds9_dsk_identify)
23 {
24 	switch (floppy_image_size(floppy))
25 	{
26 	case (80 * 2 * 21 * 256):
27 	case 860164:
28 	case 860288:
29 		*vote = 100;
30 		break;
31 
32 	default:
33 		*vote = 0;
34 		break;
35 	}
36 
37 	return FLOPPY_ERROR_SUCCESS;
38 }
39 
FLOPPY_CONSTRUCT(ds9_dsk_construct)40 static FLOPPY_CONSTRUCT(ds9_dsk_construct)
41 {
42 	struct basicdsk_geometry geometry;
43 	memset(&geometry, 0, sizeof(geometry));
44 	geometry.heads = 2;
45 	geometry.first_sector_id = 0;
46 	geometry.sector_length = 256;
47 	geometry.tracks = 80;
48 	geometry.sectors = 21;
49 	return basicdsk_construct(floppy, &geometry);
50 }
51 
52 LEGACY_FLOPPY_OPTIONS_START( ds9 )
53 	LEGACY_FLOPPY_OPTION( ds9_dsk, "ds9,dsk,raw", "Agat 840K DSK image",
54 		ds9_dsk_identify, ds9_dsk_construct, nullptr, nullptr)
55 LEGACY_FLOPPY_OPTIONS_END
56 
57 // exactly 6500 bytes
58 const floppy_image_format_t::desc_e ds9_format::ds9_desc[] = {
59 	/* 01 */ { MFM, 0xaa, 32 },             // GAP1
60 	/* 02 */ { SECTOR_LOOP_START, 0, 20 },  // 21 sectors
61 	/* 03 */ {   RAWBITS, 0x8924, 16 },     // sync mark: xA4, 2 us zero level interval, 0xFF
62 	/* 04 */ {   RAWBITS, 0x5555, 16 },
63 	/* 05 */ {   MFM, 0x95, 1 },            // address field prologue
64 	/* 06 */ {   MFM, 0x6a, 1 },
65 	/* 07 */ {   MFM, 0xfe, 1 },            // volume number
66 	/* 08 */ {   OFFSET_ID },
67 	/* 09 */ {   SECTOR_ID },
68 	/* 10 */ {   MFM, 0x5a, 1 },            // address field epilogue
69 	/* 11 */ {   MFM, 0xaa, 5 },            // GAP2 (min 4 bytes)
70 	/* 12 */ {   RAWBITS, 0x8924, 16 },     // sync mark
71 	/* 13 */ {   RAWBITS, 0x5555, 16 },
72 	/* 14 */ {   MFM, 0x6a, 1 },            // data field prologue
73 	/* 15 */ {   MFM, 0x95, 1 },
74 	/* 16 */ {   SECTOR_DATA_DS9, -1 },
75 	/* 17 */ {   MFM, 0x5a, 1 },            // data field epilogue
76 	/* 18 */ {   MFM, 0xaa, 33 },           // GAP3
77 	/* 19 */ { SECTOR_LOOP_END },
78 	/* 20 */ { END }
79 };
80 
ds9_format()81 ds9_format::ds9_format()
82 {
83 }
84 
name() const85 const char *ds9_format::name() const
86 {
87 	return "a9dsk";
88 }
89 
description() const90 const char *ds9_format::description() const
91 {
92 	return "Agat-9 840K floppy image";
93 }
94 
extensions() const95 const char *ds9_format::extensions() const
96 {
97 	return "ds9";
98 }
99 
find_size(io_generic * io,uint8_t & track_count,uint8_t & head_count,uint8_t & sector_count)100 void ds9_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
101 {
102 	uint32_t expected_size = 0;
103 	uint64_t size = io_generic_size(io);
104 
105 	head_count = 2;
106 	track_count = 80;
107 	sector_count = 21;
108 	expected_size = 256 * track_count * head_count * sector_count;
109 
110 	if (size >= expected_size) // standard format has 860160 bytes
111 		return;
112 
113 	track_count = head_count = sector_count = 0;
114 }
115 
identify(io_generic * io,uint32_t form_factor)116 int ds9_format::identify(io_generic *io, uint32_t form_factor)
117 {
118 	uint8_t track_count, head_count, sector_count;
119 	find_size(io, track_count, head_count, sector_count);
120 
121 	if (track_count) return 50;
122 
123 	return 0;
124 }
125 
load(io_generic * io,uint32_t form_factor,floppy_image * image)126 bool ds9_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
127 {
128 	uint8_t track_count, head_count, sector_count;
129 	find_size(io, track_count, head_count, sector_count);
130 	if (track_count == 0) return false;
131 
132 	uint8_t sectdata[21 * 256];
133 	desc_s sectors[21];
134 	for (int i = 0; i < sector_count; i++)
135 	{
136 		sectors[i].data = sectdata + 256 * i;
137 		sectors[i].size = 256;
138 		sectors[i].sector_id = i;
139 	}
140 
141 	int track_size = sector_count * 256;
142 	for (int track = 0; track < track_count; track++)
143 	{
144 		for (int head = 0; head < head_count; head++)
145 		{
146 			io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
147 			generate_track(ds9_desc, track, head, sectors, sector_count, 104000, image);
148 		}
149 	}
150 
151 	image->set_variant(floppy_image::DSQD);
152 
153 	return true;
154 }
155 
156 const floppy_format_type FLOPPY_DS9_FORMAT = &floppy_image_format_creator<ds9_format>;
157