// license:BSD-3-Clause
// copyright-holders:Sergey Svishchev
/**********************************************************************
formats/ds9_dsk.cpp
Floppies used by Agat-9 840KB controller
http://agatcomp.ru/Reading/docs/es5323.txt
https://github.com/sintech/AGAT/blob/master/docs/agat-840k-format.txt
http://www.torlus.com/floppy/forum/viewtopic.php?f=19&t=1385
************************************************************************/
#include <assert.h>
#include "formats/ds9_dsk.h"
static FLOPPY_IDENTIFY(ds9_dsk_identify)
{
switch (floppy_image_size(floppy))
{
case (80 * 2 * 21 * 256):
case 860164:
case 860288:
*vote = 100;
break;
default:
*vote = 0;
break;
}
return FLOPPY_ERROR_SUCCESS;
}
static FLOPPY_CONSTRUCT(ds9_dsk_construct)
{
struct basicdsk_geometry geometry;
memset(&geometry, 0, sizeof(geometry));
geometry.heads = 2;
geometry.first_sector_id = 0;
geometry.sector_length = 256;
geometry.tracks = 80;
geometry.sectors = 21;
return basicdsk_construct(floppy, &geometry);
}
LEGACY_FLOPPY_OPTIONS_START( ds9 )
LEGACY_FLOPPY_OPTION( ds9_dsk, "ds9,dsk,raw", "Agat 840K DSK image",
ds9_dsk_identify, ds9_dsk_construct, nullptr, nullptr)
LEGACY_FLOPPY_OPTIONS_END
// exactly 6500 bytes
const floppy_image_format_t::desc_e ds9_format::ds9_desc[] = {
/* 01 */ { MFM, 0xaa, 32 }, // GAP1
/* 02 */ { SECTOR_LOOP_START, 0, 20 }, // 21 sectors
/* 03 */ { RAWBITS, 0x8924, 16 }, // sync mark: xA4, 2 us zero level interval, 0xFF
/* 04 */ { RAWBITS, 0x5555, 16 },
/* 05 */ { MFM, 0x95, 1 }, // address field prologue
/* 06 */ { MFM, 0x6a, 1 },
/* 07 */ { MFM, 0xfe, 1 }, // volume number
/* 08 */ { OFFSET_ID },
/* 09 */ { SECTOR_ID },
/* 10 */ { MFM, 0x5a, 1 }, // address field epilogue
/* 11 */ { MFM, 0xaa, 5 }, // GAP2 (min 4 bytes)
/* 12 */ { RAWBITS, 0x8924, 16 }, // sync mark
/* 13 */ { RAWBITS, 0x5555, 16 },
/* 14 */ { MFM, 0x6a, 1 }, // data field prologue
/* 15 */ { MFM, 0x95, 1 },
/* 16 */ { SECTOR_DATA_DS9, -1 },
/* 17 */ { MFM, 0x5a, 1 }, // data field epilogue
/* 18 */ { MFM, 0xaa, 33 }, // GAP3
/* 19 */ { SECTOR_LOOP_END },
/* 20 */ { END }
};
ds9_format::ds9_format()
{
}
const char *ds9_format::name() const
{
return "a9dsk";
}
const char *ds9_format::description() const
{
return "Agat-9 840K floppy image";
}
const char *ds9_format::extensions() const
{
return "ds9";
}
void ds9_format::find_size(io_generic *io, uint8_t &track_count, uint8_t &head_count, uint8_t §or_count)
{
uint32_t expected_size = 0;
uint64_t size = io_generic_size(io);
head_count = 2;
track_count = 80;
sector_count = 21;
expected_size = 256 * track_count * head_count * sector_count;
if (size >= expected_size) // standard format has 860160 bytes
return;
track_count = head_count = sector_count = 0;
}
int ds9_format::identify(io_generic *io, uint32_t form_factor)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
if (track_count) return 50;
return 0;
}
bool ds9_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
uint8_t track_count, head_count, sector_count;
find_size(io, track_count, head_count, sector_count);
if (track_count == 0) return false;
uint8_t sectdata[21 * 256];
desc_s sectors[21];
for (int i = 0; i < sector_count; i++)
{
sectors[i].data = sectdata + 256 * i;
sectors[i].size = 256;
sectors[i].sector_id = i;
}
int track_size = sector_count * 256;
for (int track = 0; track < track_count; track++)
{
for (int head = 0; head < head_count; head++)
{
io_generic_read(io, sectdata, (track * head_count + head) * track_size, track_size);
generate_track(ds9_desc, track, head, sectors, sector_count, 104000, image);
}
}
image->set_variant(floppy_image::DSQD);
return true;
}
const floppy_format_type FLOPPY_DS9_FORMAT = &floppy_image_format_creator<ds9_format>;