Formats-related refactoring

- Remove opresolv.h from emu.h and some other base headers
- Split legacy floppy image class into a separate file
- Clean up a lot of #includes in src/lib and src/tools/imgtool
This commit is contained in:
AJR 2021-09-11 16:07:33 -04:00
parent fae732dc5d
commit 0da505b43e
206 changed files with 1484 additions and 1529 deletions

View File

@ -43,6 +43,8 @@ project "formats"
MAME_DIR .. "src/lib/formats/flopimg.cpp",
MAME_DIR .. "src/lib/formats/flopimg.h",
MAME_DIR .. "src/lib/formats/flopimg_legacy.cpp",
MAME_DIR .. "src/lib/formats/flopimg_legacy.h",
MAME_DIR .. "src/lib/formats/cqm_dsk.cpp",
MAME_DIR .. "src/lib/formats/cqm_dsk.h",

View File

@ -11,6 +11,8 @@
#include "harddisk.h"
#include "romload.h"
#include "opresolv.h"
OPTION_GUIDE_START(dsk_option_guide)
OPTION_INT('C', "cylinders", "Cylinders")

View File

@ -7,7 +7,7 @@
#pragma once
#include "formats/flopimg.h"
#include "formats/flopimg_legacy.h"
#include "softlist_dev.h"
#define FLOPPY_TYPE_REGULAR 0
@ -116,7 +116,7 @@ public:
virtual bool is_reset_on_load() const noexcept override { return false; }
virtual const char *image_interface() const noexcept override;
virtual const char *file_extensions() const noexcept override { return m_extension_list; }
virtual const util::option_guide &create_option_guide() const override { return floppy_option_guide; }
virtual const util::option_guide &create_option_guide() const override { return floppy_option_guide(); }
floppy_image_legacy *flopimg_get_image();
void floppy_drive_set_geometry(floppy_type_t type);

View File

@ -20,6 +20,8 @@
#include "harddisk.h"
#include "romload.h"
#include "opresolv.h"
OPTION_GUIDE_START(hd_option_guide)
OPTION_INT('C', "cylinders", "Cylinders")

View File

@ -18,6 +18,7 @@
#include "ui/uimain.h"
#include "corestr.h"
#include "opresolv.h"
#include "zippath.h"
#include <algorithm>

View File

@ -17,6 +17,8 @@
#ifndef MAME_EMU_DIIMAGE_H
#define MAME_EMU_DIIMAGE_H
#include "utilfwd.h"
#include <memory>
#include <string>
#include <system_error>

View File

@ -65,7 +65,6 @@
#include "addrmap.h" // Needs optional_device<> and required_device<>
#include "distate.h"
#include "dimemory.h"
#include "opresolv.h"
#include "dipalette.h"
#include "digfx.h"
#include "diimage.h"

View File

@ -8,8 +8,6 @@ Atari 2600 SuperCharger support
#include "formats/a26_cas.h"
#include <cassert>
#define A26_CAS_SIZE 8448
#define A26_WAV_FREQUENCY 44100

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/a5105_dsk.h"
a5105_format::a5105_format() : upd765_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/abc800_dsk.h"
abc800_format::abc800_format() : wd177x_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/abcfd2_dsk.h"
abc_fd2_format::abc_fd2_format() : wd177x_format(formats)

View File

@ -12,8 +12,6 @@ For more information see:
#include "ace_tap.h"
#include <cassert>
#define SMPLO -32768
#define SILENCE 0

View File

@ -9,9 +9,12 @@
***************************************************************************/
#include "acorn_dsk.h"
#include "imageutl.h"
#include "ioprocs.h"
#include <cstring>
acorn_ssd_format::acorn_ssd_format() : wd177x_format(formats)
{

View File

@ -1,8 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Curt Coder
#include "adam_cas.h"
#include <cassert>
#include "adam_cas.h"
// This code will reproduce the timing of an adam tape played back on a standard tape deck with a 1 7/8ips speed.

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/adam_dsk.h"
adam_format::adam_format() : wd177x_format(formats)

View File

@ -12,9 +12,10 @@
************************************************************************/
#include <cassert>
#include "agat840k_hle_dsk.h"
#include "imageutl.h"
#include "formats/agat840k_hle_dsk.h"
#include <cstring>
static FLOPPY_IDENTIFY(agat840k_hle_dsk_identify)

View File

@ -10,7 +10,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
#include "formats/basicdsk.h"
LEGACY_FLOPPY_OPTIONS_EXTERN(agat840k_hle);

View File

@ -13,6 +13,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
/***************************************************************************

View File

@ -99,11 +99,14 @@
*********************************************************************/
#include "ap_dsk35.h"
#include "imageutl.h"
#include "ioprocs.h"
#include "opresolv.h"
#include <cassert>
#include <cstdio>
#include <cstring>
struct apple35_tag

View File

@ -13,6 +13,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
void sony_filltrack(uint8_t *buffer, size_t buffer_len, size_t *pos, uint8_t data);
uint8_t sony_fetchtrack(const uint8_t *buffer, size_t buffer_len, size_t *pos);

View File

@ -64,8 +64,12 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*, little_endianize_int32
#include <zlib.h>
#include <cstring>
static const uint8_t APD_HEADER[8] = { 'A', 'P', 'D', 'X', '0', '0', '0', '1' };
static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b };

View File

@ -36,8 +36,6 @@ e. A checksum byte (8-bit addition)
#include "formats/apf_apt.h"
#include <cassert>
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/applix_dsk.h"
applix_format::applix_format() : wd177x_format(formats)

View File

@ -12,8 +12,6 @@
#include "coretmpl.h" // BIT
#include <cassert>
/*-------------------------------------------------
CassetteModulation aquarius_caq_modulation

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/asst128_dsk.h"
asst128_format::asst128_format() : upd765_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/atari_dsk.h"
static FLOPPY_IDENTIFY( atari_dsk_identify )

View File

@ -12,7 +12,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
LEGACY_FLOPPY_OPTIONS_EXTERN(atari_only);

View File

@ -44,8 +44,6 @@
#include "csw_cas.h"
#include "uef_cas.h"
#include <cassert>
/***************************************************************************
PARAMETERS
***************************************************************************/

View File

@ -8,12 +8,14 @@
*********************************************************************/
#include "basicdsk.h"
#include "opresolv.h"
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "basicdsk.h"
static floperr_t basicdsk_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);
static floperr_t basicdsk_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
static floperr_t basicdsk_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);

View File

@ -12,7 +12,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
struct basicdsk_geometry
{

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/bw12_dsk.h"
bw12_format::bw12_format() : upd765_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/bw2_dsk.h"
bw2_format::bw2_format() : upd765_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/c3040_dsk.h"
c3040_format::c3040_format() : d64_format(file_formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/c4040_dsk.h"
c4040_format::c4040_format() : d64_format(file_formats)

View File

@ -25,6 +25,8 @@ Each byte is 8 bits (MSB first) with no start or stop bits.
#include "camplynx_cas.h"
#include "osdcore.h" // osd_printf_*
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767

View File

@ -19,8 +19,6 @@
*********************************************************************/
#include <cassert>
#include "formats/camplynx_dsk.h"
camplynx_format::camplynx_format() : wd177x_format(formats)

View File

@ -14,16 +14,10 @@
#include "ioprocs.h"
#include "osdcore.h"
#include <memory>
#include <string>
#include <vector>
#ifndef LOG_FORMATS
#define LOG_FORMATS(...) do { if (0) osd_printf_info(__VA_ARGS__); } while (false)
#endif
// hack to get around rogues that define this
#ifdef UNSUPPORTED
#undef UNSUPPORTED

View File

@ -41,6 +41,8 @@
#include "cbm_crt.h"
#include "osdcore.h" // osd_printf_*
//**************************************************************************
// MACROS/CONSTANTS

View File

@ -94,9 +94,8 @@ Unfortunately, I have no such a .tap file to test, so my implementation
below could be not working. FP ]
*/
#include <cassert>
#include "cbm_tap.h"
#include "imageutl.h"
#define CBM_WAV_FREQUENCY 44100

View File

@ -18,9 +18,9 @@ NOTE: There exist multiples type of .cas files for Colour Genie
We now support these three types below...
********************************************************************/
#include "formats/cgen_cas.h"
#include "cgen_cas.h"
#include <cassert>
#include <cstring>
#define TAPE_HEADER "Colour Genie - Virtual Tape File"

View File

@ -36,8 +36,6 @@
*/
#include <cassert>
#include "formats/comx35_dsk.h"
comx35_format::comx35_format() : wd177x_format(formats)

View File

@ -9,6 +9,7 @@
*********************************************************************/
#include "cqm_dsk.h"
#include "flopimg_legacy.h"
#include "ioprocs.h"

View File

@ -21,11 +21,13 @@
*/
#include "csw_cas.h"
#include "imageutl.h"
#include "uef_cas.h"
#include "osdcomm.h" // little_endianize_int*
#include <zlib.h>
#include <cassert>
#include <cstring>

View File

@ -14,6 +14,10 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#include <cstring>
d64_format::d64_format()
{

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/d71_dsk.h"
d71_format::d71_format() : d64_format(formats)

View File

@ -73,8 +73,6 @@ PER SECTOR ORGANIZATION:
*/
#include <cassert>
#include "formats/d81_dsk.h"
d81_format::d81_format() : wd177x_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/d82_dsk.h"
d82_format::d82_format() : d80_format(file_formats)

View File

@ -29,7 +29,7 @@
*
*/
#include "flopimg.h"
#include "flopimg_legacy.h"
#include "imageutl.h"
#include "ioprocs.h"

View File

@ -15,6 +15,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#define NUMBER_OF_MULTIREADS 3
// thresholds for brickwall windowing

View File

@ -9,112 +9,11 @@
*********************************************************************/
#include "dim_dsk.h"
#include "basicdsk.h"
#include "ioprocs.h"
#include <cstring>
FLOPPY_IDENTIFY(dim_dsk_identify)
{
uint8_t dim_header[16];
floppy_image_read(floppy, (uint8_t*)dim_header,0xab,16);
if(strncmp((const char*)dim_header,"DIFC HEADER",11) == 0)
*vote = 100;
else
*vote = 0;
return FLOPPY_ERROR_SUCCESS;
}
FLOPPY_CONSTRUCT(dim_dsk_construct)
{
struct basicdsk_geometry geometry;
// DIM disk image header, most of this is guesswork
int tracks = 77;
int heads = 2;
int sectors = 8; // per track
int sectorlen = 1024;
int firstsector = 0x01;
uint8_t format_tmp;
int x;
uint16_t temp;
if(params)
{
// create
return FLOPPY_ERROR_UNSUPPORTED;
}
// Offset + 0 : disk format type (1 byte):
// 0 = 2HD / 2HDA (8 sector/track, 1024 bytes/sector, GAP#3 = 0x74)
// 1 = 2HS (9 sector/track, 1024 bytes/sector, GAP#3 = 0x39)
// 2 = 2HC (15 sector/track, 512 bytes/sector, GAP#3 = 0x54)
// 3 = 2HDE(68) (9 sector/track, 1024 bytes/sector, GAP#3 = 0x39)
// 9 = 2HQ (18 sector/track, 512 bytes/sector, GAP#3 = 0x54)
// 17 = N88-BASIC (26 sector/track, 256 bytes/sector, GAP#3 = 0x33)
// or (26 sector/track, 128 bytes/sector, GAP#3 = 0x1a)
//
floppy_image_read(floppy, &format_tmp,0,1);
switch(format_tmp)
{
case 0x00:
sectors = 8;
sectorlen = 1024;
break;
case 0x01:
case 0x03:
sectors = 9;
sectorlen = 1024;
break;
case 0x02:
sectors = 15;
sectorlen = 512;
break;
case 0x09:
sectors = 18;
sectorlen = 512;
break;
case 0x11:
sectors = 26;
sectorlen = 256;
break;
}
tracks = 0;
for (x=0;x<86;x++)
{
floppy_image_read(floppy,&temp,(x*2)+1,2);
if(temp == 0x0101)
tracks++;
}
// TODO: expand on this basic implementation
LOG_FORMATS("FDD: DIM image loaded - type %i, %i tracks, %i sectors per track, %i bytes per sector\n", format_tmp,tracks, sectors,sectorlen);
memset(&geometry, 0, sizeof(geometry));
geometry.heads = heads;
geometry.first_sector_id = firstsector;
geometry.sector_length = sectorlen;
geometry.tracks = tracks+1;
geometry.sectors = sectors;
geometry.offset = 0x100;
return basicdsk_construct(floppy, &geometry);
}
/*********************************************************************
formats/dim_dsk.c
DIM disk images
*********************************************************************/
#include "dim_dsk.h"
dim_format::dim_format()
{
}

View File

@ -16,10 +16,6 @@
/**************************************************************************/
FLOPPY_IDENTIFY(dim_dsk_identify);
FLOPPY_CONSTRUCT(dim_dsk_construct);
class dim_format : public floppy_image_format_t
{
public:

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/dmv_dsk.h"
dmv_format::dmv_format() : upd765_format(formats)

View File

@ -18,41 +18,8 @@
#include "ioprocs.h"
#include <cstring>
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[] = {

View File

@ -11,9 +11,6 @@
#pragma once
#include "flopimg.h"
#include "formats/basicdsk.h"
LEGACY_FLOPPY_OPTIONS_EXTERN(ds9);
class ds9_format : public floppy_image_format_t
{

View File

@ -9,6 +9,7 @@
*********************************************************************/
#include "dsk_dsk.h"
#include "flopimg_legacy.h"
#include "imageutl.h"
#include "ioprocs.h"

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/ep64_dsk.h"
ep64_format::ep64_format() : wd177x_format(formats)

View File

@ -16,6 +16,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
const floppy_image_format_t::desc_e esq8img_format::esq_6_desc[] = {
{ MFM, 0x4e, 80 },

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/excali64_dsk.h"
excali64_format::excali64_format() : wd177x_format(formats)

View File

@ -12,8 +12,6 @@ it's all a guess.
#include "fc100_cas.h"
#include <cassert>
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767

View File

@ -35,6 +35,10 @@
#include "ioprocs.h"
#include "osdcomm.h" // little_endianize_int32
#include <cstring>
fdd_format::fdd_format()
{

View File

@ -16,9 +16,8 @@
*/
#include <cassert>
#include "imageutl.h"
#include "flopimg.h"
#include "flopimg_legacy.h"
/***************************************************************************
PARAMETERS

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/fl1_dsk.h"
fl1_format::fl1_format() : wd177x_format(formats)

View File

@ -1,893 +1,22 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/*********************************************************************
flopimg.c
Floppy disk image abstraction code
*********************************************************************/
#include "flopimg.h"
#include "imageutl.h"
#include "ioprocs.h"
#include "osdcore.h"
#include <cassert>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#define TRACK_LOADED 0x01
#define TRACK_DIRTY 0x02
using util::BIT;
struct floppy_image_legacy
{
util::random_read_write::ptr io = nullptr;
const struct FloppyFormat *floppy_option = nullptr;
struct FloppyCallbacks format = { 0 };
/* loaded track stuff */
int loaded_track_head = 0;
int loaded_track_index = 0;
uint32_t loaded_track_size = 0;
std::unique_ptr<uint8_t[]> loaded_track_data;
uint8_t loaded_track_status = 0;
uint8_t flags = 0;
/* tagging system */
std::unique_ptr<uint8_t[]> tag_data;
};
struct floppy_params
{
int param;
int value;
};
static floperr_t floppy_track_unload(floppy_image_legacy *floppy);
OPTION_GUIDE_START(floppy_option_guide)
OPTION_INT('H', "heads", "Heads")
OPTION_INT('T', "tracks", "Tracks")
OPTION_INT('S', "sectors", "Sectors")
OPTION_INT('L', "sectorlength", "Sector Bytes")
OPTION_INT('I', "interleave", "Interleave")
OPTION_INT('F', "firstsectorid", "First Sector")
OPTION_GUIDE_END
static void floppy_close_internal(floppy_image_legacy *floppy);
/*********************************************************************
opening, closing and creating of floppy images
*********************************************************************/
/* basic floppy_image_legacy initialization common to floppy_open() and floppy_create() */
static floppy_image_legacy *floppy_init(util::random_read_write::ptr &&io, int flags)
{
floppy_image_legacy *floppy;
floppy = new floppy_image_legacy;
floppy->io = std::move(io);
floppy->flags = (uint8_t) flags;
return floppy;
}
/* main code for identifying and maybe opening a disk image; not exposed
* directly because this function is big and hideous */
static floperr_t floppy_open_internal(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *floppy_options, int max_options, int flags, floppy_image_legacy **outfloppy,
int *outoption)
{
floperr_t err;
floppy_image_legacy *floppy;
int best_option = -1;
int best_vote = 0;
int vote;
size_t i;
floppy = floppy_init(std::move(io), flags);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* vote on the best format */
for (i = 0; (i < max_options) && floppy_options[i].construct; i++)
{
if (extension.empty() || !floppy_options[i].extensions || image_find_extension(floppy_options[i].extensions, extension.c_str()))
{
if (floppy_options[i].identify)
{
vote = 0;
err = floppy_options[i].identify(floppy, &floppy_options[i], &vote);
if (err)
goto done;
}
else
{
vote = 1;
}
/* is this option a better one? */
if (vote > best_vote)
{
best_vote = vote;
best_option = i;
}
}
}
/* did we find a format? */
if (best_option == -1)
{
err = FLOPPY_ERROR_INVALIDIMAGE;
goto done;
}
if (outfloppy)
{
/* call the format constructor */
err = floppy_options[best_option].construct(floppy, &floppy_options[best_option], nullptr);
if (err)
goto done;
floppy->floppy_option = &floppy_options[best_option];
}
if (best_vote != 100)
{
printf("Loading image that is not 100%% recognized\n");
}
err = FLOPPY_ERROR_SUCCESS;
done:
/* if we have a floppy disk and we either errored or are not keeping it, close it */
if (floppy && (!outfloppy || err))
{
floppy_close_internal(floppy);
floppy = nullptr;
}
if (outoption)
*outoption = err ? -1 : best_option;
if (outfloppy)
*outfloppy = floppy;
return err;
}
floperr_t floppy_identify(util::random_read_write::ptr &&io, const char *extension,
const struct FloppyFormat *formats, int *identified_format)
{
return floppy_open_internal(std::move(io), extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format);
}
floperr_t floppy_open(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy)
{
return floppy_open_internal(std::move(io), extension, format, 1, flags, outfloppy, nullptr);
}
floperr_t floppy_open_choices(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy)
{
return floppy_open_internal(std::move(io), extension, formats, INT_MAX, flags, outfloppy, nullptr);
}
floperr_t floppy_create(util::random_read_write::ptr &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy)
{
floppy_image_legacy *floppy = nullptr;
floperr_t err;
int heads, tracks, h, t;
std::unique_ptr<util::option_resolution> alloc_resolution;
assert(format);
/* create the new image */
floppy = floppy_init(std::move(io), 0);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* if this format expects creation parameters and none were specified, create some */
if (!parameters && format->param_guidelines)
{
try { alloc_resolution = std::make_unique<util::option_resolution>(floppy_option_guide); }
catch (...)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
alloc_resolution->set_specification(format->param_guidelines);
parameters = alloc_resolution.get();
}
/* call the format constructor */
err = format->construct(floppy, format, parameters);
if (err)
goto done;
/* format the disk, ignoring if formatting not implemented */
if (floppy->format.format_track)
{
heads = floppy_get_heads_per_disk(floppy);
tracks = floppy_get_tracks_per_disk(floppy);
for (h = 0; h < heads; h++)
{
for (t = 0; t < tracks; t++)
{
err = floppy->format.format_track(floppy, h, t, parameters);
if (err)
goto done;
}
}
}
/* call the post_format function, if present */
if (floppy->format.post_format)
{
err = floppy->format.post_format(floppy, parameters);
if (err)
goto done;
}
floppy->floppy_option = format;
err = FLOPPY_ERROR_SUCCESS;
done:
if (err && floppy)
{
floppy_close_internal(floppy);
floppy = nullptr;
}
if (outfloppy)
*outfloppy = floppy;
else if (floppy)
floppy_close_internal(floppy);
return err;
}
static void floppy_close_internal(floppy_image_legacy *floppy)
{
if (floppy) {
floppy_track_unload(floppy);
if(floppy->floppy_option && floppy->floppy_option->destruct)
floppy->floppy_option->destruct(floppy, floppy->floppy_option);
delete floppy;
}
}
void floppy_close(floppy_image_legacy *floppy)
{
floppy_close_internal(floppy);
}
/*********************************************************************
functions useful in format constructors
*********************************************************************/
struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy)
{
assert(floppy);
return &floppy->format;
}
void *floppy_tag(floppy_image_legacy *floppy)
{
assert(floppy);
return floppy->tag_data.get();
}
void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize)
{
floppy->tag_data = std::make_unique<uint8_t[]>(tagsize);
return floppy->tag_data.get();
}
uint8_t floppy_get_filler(floppy_image_legacy *floppy)
{
// FIXME: remove this function, it's here for legacy reasons
// the caller actually sets the filler byte - in practice it's always 0xff but there's no actual guarantee
return 0xff;
}
util::random_read_write &floppy_get_io(floppy_image_legacy *floppy)
{
return *floppy->io;
}
/*********************************************************************
calls for accessing the raw disk image
*********************************************************************/
void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length)
{
size_t actual;
floppy->io->read_at(offset, buffer, length, actual);
}
void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length)
{
size_t actual;
floppy->io->write_at(offset, buffer, length, actual);
}
void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length)
{
uint8_t buffer[512];
memset(buffer, filler, std::min(sizeof(buffer), length));
while (length)
{
size_t const block = std::min(sizeof(buffer), length);
size_t actual;
floppy->io->write_at(offset, buffer, block, actual);
offset += block;
length -= block;
}
}
uint64_t floppy_image_size(floppy_image_legacy *floppy)
{
uint64_t result;
floppy->io->length(result);
return result;
}
/*********************************************************************
calls for accessing disk image data
*********************************************************************/
static floperr_t floppy_readwrite_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset,
void *buffer, size_t buffer_len, bool writing, bool indexed, int ddam)
{
floperr_t err;
const struct FloppyCallbacks *fmt;
size_t this_buffer_len;
std::vector<uint8_t> alloc_buf;
uint32_t sector_length;
uint8_t *buffer_ptr = (uint8_t *)buffer;
floperr_t (*read_sector)(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
fmt = floppy_callbacks(floppy);
/* choose proper calls for indexed vs non-indexed */
if (indexed)
{
read_sector = fmt->read_indexed_sector;
write_sector = fmt->write_indexed_sector;
if (!fmt->get_indexed_sector_info)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
else
{
read_sector = fmt->read_sector;
write_sector = fmt->write_sector;
if (!fmt->get_sector_length)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
/* check to make sure that the operation is supported */
if (!read_sector || (writing && !write_sector))
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
/* main loop */
while(buffer_len > 0)
{
/* find out the size of this sector */
if (indexed)
err = fmt->get_indexed_sector_info(floppy, head, track, sector, nullptr, nullptr, nullptr, &sector_length, nullptr);
else
err = fmt->get_sector_length(floppy, head, track, sector, &sector_length);
if (err)
goto done;
/* do we even do anything with this sector? */
if (offset < sector_length)
{
/* ok we will be doing something */
if ((offset > 0) || (buffer_len < sector_length))
{
/* we will be doing an partial read/write; in other words we
* will not be reading/writing a full sector */
alloc_buf.resize(sector_length);
/* read the sector (we need to do this even when writing */
err = read_sector(floppy, head, track, sector, &alloc_buf[0], sector_length);
if (err)
goto done;
this_buffer_len = std::min(buffer_len, size_t(sector_length - offset));
if (writing)
{
memcpy(&alloc_buf[offset], buffer_ptr, this_buffer_len);
err = write_sector(floppy, head, track, sector, &alloc_buf[0], sector_length, ddam);
if (err)
goto done;
}
else
{
memcpy(buffer_ptr, &alloc_buf[offset], this_buffer_len);
}
offset += this_buffer_len;
offset %= sector_length;
}
else
{
this_buffer_len = sector_length;
if (writing)
err = write_sector(floppy, head, track, sector, buffer_ptr, sector_length, ddam);
else
err = read_sector(floppy, head, track, sector, buffer_ptr, sector_length);
if (err)
goto done;
}
}
else
{
/* skip this sector */
offset -= sector_length;
this_buffer_len = 0;
}
buffer_ptr += this_buffer_len;
buffer_len -= this_buffer_len;
sector++;
}
err = FLOPPY_ERROR_SUCCESS;
done:
return err;
}
floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, buffer, buffer_len, false, false, 0);
}
floperr_t floppy_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, (void *) buffer, buffer_len, true, false, ddam);
}
floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, buffer, buffer_len, false, true, 0);
}
floperr_t floppy_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, (void *) buffer, buffer_len, true, true, ddam);
}
static floperr_t floppy_get_track_data_offset(floppy_image_legacy *floppy, int head, int track, uint64_t *offset)
{
floperr_t err;
const struct FloppyCallbacks *callbacks;
*offset = 0;
callbacks = floppy_callbacks(floppy);
if (callbacks->get_track_data_offset)
{
err = callbacks->get_track_data_offset(floppy, head, track, offset);
if (err)
return err;
}
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t floppy_read_track_offset(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buffer_len)
{
floperr_t err;
const struct FloppyCallbacks *format;
format = floppy_callbacks(floppy);
if (!format->read_track)
return FLOPPY_ERROR_UNSUPPORTED;
err = floppy_track_unload(floppy);
if (err)
return err;
err = format->read_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_read_track(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len)
{
return floppy_read_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_read_track_data(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len)
{
floperr_t err;
uint64_t offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_read_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
static floperr_t floppy_write_track_offset(floppy_image_legacy *floppy, int head, int track, uint64_t offset, const void *buffer, size_t buffer_len)
{
floperr_t err;
/* track writing supported? */
if (!floppy_callbacks(floppy)->write_track)
return FLOPPY_ERROR_UNSUPPORTED;
/* read only? */
if (floppy->flags & FLOPPY_FLAGS_READONLY)
return FLOPPY_ERROR_READONLY;
err = floppy_track_unload(floppy);
if (err)
return err;
err = floppy_callbacks(floppy)->write_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_write_track(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
return floppy_write_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_write_track_data(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
floperr_t err;
uint64_t offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_write_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, util::option_resolution *parameters)
{
floperr_t err;
struct FloppyCallbacks *format;
std::unique_ptr<util::option_resolution> alloc_resolution;
/* supported? */
format = floppy_callbacks(floppy);
if (!format->format_track)
return FLOPPY_ERROR_UNSUPPORTED;
/* create a dummy resolution; if no parameters were specified */
if (!parameters)
{
try
{
alloc_resolution = std::make_unique<util::option_resolution>(floppy_option_guide);
}
catch (...)
{
return FLOPPY_ERROR_OUTOFMEMORY;
}
alloc_resolution->set_specification(floppy->floppy_option->param_guidelines);
parameters = alloc_resolution.get();
}
err = format->format_track(floppy, head, track, parameters);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
int floppy_get_tracks_per_disk(floppy_image_legacy *floppy)
{
return floppy_callbacks(floppy)->get_tracks_per_disk(floppy);
}
int floppy_get_heads_per_disk(floppy_image_legacy *floppy)
{
return floppy_callbacks(floppy)->get_heads_per_disk(floppy);
}
uint32_t floppy_get_track_size(floppy_image_legacy *floppy, int head, int track)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_track_size)
return 0;
return fmt->get_track_size(floppy, head, track);
}
floperr_t floppy_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_sector_length)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_sector_length(floppy, head, track, sector, sector_length);
}
floperr_t floppy_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_indexed_sector_info)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_indexed_sector_info(floppy, head, track, sector_index, cylinder, side, sector, sector_length, flags);
}
floperr_t floppy_get_sector_count(floppy_image_legacy *floppy, int head, int track, int *sector_count)
{
floperr_t err;
int sector_index = 0;
do
{
err = floppy_get_indexed_sector_info(floppy, head, track, sector_index, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!err)
sector_index++;
}
while(!err);
if (sector_index && (err == FLOPPY_ERROR_SEEKERROR))
err = FLOPPY_ERROR_SUCCESS;
if (sector_count)
*sector_count = err ? 0 : sector_index;
return err;
}
int floppy_is_read_only(floppy_image_legacy *floppy)
{
return floppy->flags & FLOPPY_FLAGS_READONLY;
}
uint8_t floppy_random_byte(floppy_image_legacy *floppy)
{
/* can't use mame_rand(); this might not be in the core */
#ifdef rand
#undef rand
#endif
return rand();
}
/*********************************************************************
calls for track based IO
*********************************************************************/
floperr_t floppy_load_track(floppy_image_legacy *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length)
{
floperr_t err;
uint32_t track_size;
/* have we already loaded this track? */
if (((floppy->loaded_track_status & TRACK_LOADED) == 0) || (head != floppy->loaded_track_head) || (track != floppy->loaded_track_index))
{
err = floppy_track_unload(floppy);
if (err)
goto error;
track_size = floppy_callbacks(floppy)->get_track_size(floppy, head, track);
floppy->loaded_track_data = std::make_unique<uint8_t[]>(track_size);
floppy->loaded_track_size = track_size;
floppy->loaded_track_head = head;
floppy->loaded_track_index = track;
err = floppy_callbacks(floppy)->read_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data.get(), floppy->loaded_track_size);
if (err)
goto error;
floppy->loaded_track_status |= TRACK_LOADED | (dirtify ? TRACK_DIRTY : 0);
}
else
floppy->loaded_track_status |= (dirtify ? TRACK_DIRTY : 0);
if (track_data)
*track_data = floppy->loaded_track_data.get();
if (track_length)
*track_length = floppy->loaded_track_size;
return FLOPPY_ERROR_SUCCESS;
error:
if (track_data)
*track_data = nullptr;
if (track_length)
*track_length = 0;
return err;
}
static floperr_t floppy_track_unload(floppy_image_legacy *floppy)
{
int err;
if (floppy->loaded_track_status & TRACK_DIRTY)
{
err = floppy_callbacks(floppy)->write_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data.get(), floppy->loaded_track_size);
if (err)
return (floperr_t)err;
}
floppy->loaded_track_status &= ~(TRACK_LOADED | TRACK_DIRTY);
return FLOPPY_ERROR_SUCCESS;
}
/*********************************************************************
accessors for meta information about the image
*********************************************************************/
const char *floppy_format_description(floppy_image_legacy *floppy)
{
return floppy->floppy_option->description;
}
/*********************************************************************
misc calls
*********************************************************************/
const char *floppy_error(floperr_t err)
{
static const char *const error_messages[] =
{
"The operation completed successfully",
"Fatal internal error",
"This operation is unsupported",
"Out of memory",
"Seek error",
"Invalid image",
"Attempted to write to read only image",
"No space left on image",
"Parameter out of range",
"Required parameter not specified"
};
if ((err < 0) || (err >= std::size(error_messages)))
return nullptr;
return error_messages[err];
}
LEGACY_FLOPPY_OPTIONS_START(default)
LEGACY_FLOPPY_OPTIONS_END
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
New implementation
flopimg.cpp
Floppy disk image abstraction code (new implementation)
****************************************************************************/
#include "flopimg.h"
#include "ioprocs.h"
#include "strformat.h"
#include <cstdio>
#include <cstring>
#include <stdexcept>
floppy_image::floppy_image(int _tracks, int _heads, uint32_t _form_factor)
{

View File

@ -7,213 +7,20 @@
Floppy disk image abstraction code
*********************************************************************/
#ifndef MAME_FORMATS_FLOPIMG_H
#define MAME_FORMATS_FLOPIMG_H
#pragma once
#include "coretmpl.h"
#include "opresolv.h"
#include "utilfwd.h"
#include "osdcore.h"
#include <memory>
#include <vector>
#ifndef LOG_FORMATS
#define LOG_FORMATS if (0) printf
#endif
/***************************************************************************
Constants
***************************************************************************/
#define FLOPPY_FLAGS_READWRITE 0
#define FLOPPY_FLAGS_READONLY 1
/* sector has a deleted data address mark */
#define ID_FLAG_DELETED_DATA 0x0001
/* CRC error in id field */
#define ID_FLAG_CRC_ERROR_IN_ID_FIELD 0x0002
/* CRC error in data field */
#define ID_FLAG_CRC_ERROR_IN_DATA_FIELD 0x0004
/***************************************************************************
Type definitions
***************************************************************************/
enum floperr_t
{
FLOPPY_ERROR_SUCCESS, /* no error */
FLOPPY_ERROR_INTERNAL, /* fatal internal error */
FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */
FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */
FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistent location */
FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */
FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */
FLOPPY_ERROR_NOSPACE,
FLOPPY_ERROR_PARAMOUTOFRANGE,
FLOPPY_ERROR_PARAMNOTSPECIFIED
};
struct floppy_image_legacy;
struct FloppyCallbacks
{
floperr_t (*read_sector)(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, void *buffer, size_t buflen);
floperr_t (*write_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buflen);
floperr_t (*write_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, const void *buffer, size_t buflen);
floperr_t (*format_track)(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params);
floperr_t (*post_format)(floppy_image_legacy *floppy, util::option_resolution *params);
int (*get_heads_per_disk)(floppy_image_legacy *floppy);
int (*get_tracks_per_disk)(floppy_image_legacy *floppy);
int (*get_sectors_per_track)(floppy_image_legacy *floppy, int head, int track);
uint32_t (*get_track_size)(floppy_image_legacy *floppy, int head, int track);
floperr_t (*get_sector_length)(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length);
floperr_t (*get_indexed_sector_info)(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags);
floperr_t (*get_track_data_offset)(floppy_image_legacy *floppy, int head, int track, uint64_t *offset);
};
struct FloppyFormat
{
const char *name;
const char *extensions;
const char *description;
floperr_t (*identify)(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote);
floperr_t (*construct)(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params);
floperr_t (*destruct)(floppy_image_legacy *floppy, const struct FloppyFormat *format);
const char *param_guidelines;
};
#define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote)
#define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params)
#define FLOPPY_DESTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format)
FLOPPY_IDENTIFY(td0_dsk_identify);
FLOPPY_CONSTRUCT(td0_dsk_construct);
FLOPPY_DESTRUCT(td0_dsk_destruct);
FLOPPY_IDENTIFY(imd_dsk_identify);
FLOPPY_CONSTRUCT(imd_dsk_construct);
FLOPPY_IDENTIFY(cqm_dsk_identify);
FLOPPY_CONSTRUCT(cqm_dsk_construct);
FLOPPY_IDENTIFY(dsk_dsk_identify);
FLOPPY_CONSTRUCT(dsk_dsk_construct);
FLOPPY_IDENTIFY(d88_dsk_identify);
FLOPPY_CONSTRUCT(d88_dsk_construct);
FLOPPY_IDENTIFY(fdi_dsk_identify);
FLOPPY_CONSTRUCT(fdi_dsk_construct);
#define LEGACY_FLOPPY_OPTIONS_NAME(name) floppyoptions_##name
#define LEGACY_FLOPPY_OPTIONS_START(name) \
const struct FloppyFormat floppyoptions_##name[] = \
{
#define LEGACY_FLOPPY_OPTIONS_END0 \
{ nullptr } \
};
#define LEGACY_FLOPPY_OPTIONS_EXTERN(name) \
extern const struct FloppyFormat floppyoptions_##name[]
#define LEGACY_FLOPPY_OPTION(name, extensions_, description_, identify_, construct_, destruct_, ranges_)\
{ #name, extensions_, description_, identify_, construct_, destruct_, ranges_ },
#define LEGACY_FLOPPY_OPTIONS_END \
LEGACY_FLOPPY_OPTION( fdi, "fdi", "Formatted Disk Image", fdi_dsk_identify, fdi_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, nullptr) \
LEGACY_FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( d88, "d77,d88,1dd", "D88 Floppy Disk image", d88_dsk_identify, d88_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTIONS_END0
LEGACY_FLOPPY_OPTIONS_EXTERN(default);
#define PARAM_END '\0'
#define PARAM_HEADS 'H'
#define PARAM_TRACKS 'T'
#define PARAM_SECTORS 'S'
#define PARAM_SECTOR_LENGTH 'L'
#define PARAM_INTERLEAVE 'I'
#define PARAM_FIRST_SECTOR_ID 'F'
#define HEADS(range) "H" #range
#define TRACKS(range) "T" #range
#define SECTORS(range) "S" #range
#define SECTOR_LENGTH(range) "L" #range
#define INTERLEAVE(range) "I" #range
#define FIRST_SECTOR_ID(range) "F" #range
/***************************************************************************
Prototypes
***************************************************************************/
OPTION_GUIDE_EXTERN(floppy_option_guide);
/* opening, closing and creating of floppy images */
floperr_t floppy_open(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy);
floperr_t floppy_open_choices(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy);
floperr_t floppy_create(std::unique_ptr<util::random_read_write> &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy);
void floppy_close(floppy_image_legacy *floppy);
/* useful for identifying a floppy image */
floperr_t floppy_identify(std::unique_ptr<util::random_read_write> &&io, const char *extension, const struct FloppyFormat *formats, int *identified_format);
/* functions useful within format constructors */
void *floppy_tag(floppy_image_legacy *floppy);
void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize);
struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy);
uint8_t floppy_get_filler(floppy_image_legacy *floppy);
util::random_read_write &floppy_get_io(floppy_image_legacy *floppy);
/* calls for accessing disk image data */
floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_track(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_read_track_data(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track_data(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params);
int floppy_get_tracks_per_disk(floppy_image_legacy *floppy);
int floppy_get_heads_per_disk(floppy_image_legacy *floppy);
uint32_t floppy_get_track_size(floppy_image_legacy *floppy, int head, int track);
floperr_t floppy_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length);
floperr_t floppy_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags);
floperr_t floppy_get_sector_count(floppy_image_legacy *floppy, int head, int track, int *sector_count);
floperr_t floppy_load_track(floppy_image_legacy *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length);
int floppy_is_read_only(floppy_image_legacy *floppy);
uint8_t floppy_random_byte(floppy_image_legacy *floppy);
/* accessors for meta information about the image */
const char *floppy_format_description(floppy_image_legacy *floppy);
/* calls for accessing the raw disk image */
void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length);
void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length);
void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length);
uint64_t floppy_image_size(floppy_image_legacy *floppy);
/* misc */
const char *floppy_error(floperr_t err);
#include <cassert>
#include <cstddef>
#include <cstdint>
//////////////////////////////////////////////////////////

View File

@ -0,0 +1,880 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/*********************************************************************
flopimg_legacy.cpp
Floppy disk image abstraction code (legacy implementation)
*********************************************************************/
#include "flopimg_legacy.h"
#include "imageutl.h"
#include "ioprocs.h"
#include "opresolv.h"
#include <cassert>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define TRACK_LOADED 0x01
#define TRACK_DIRTY 0x02
struct floppy_image_legacy
{
util::random_read_write::ptr io = nullptr;
const struct FloppyFormat *floppy_option = nullptr;
struct FloppyCallbacks format = { 0 };
/* loaded track stuff */
int loaded_track_head = 0;
int loaded_track_index = 0;
uint32_t loaded_track_size = 0;
std::unique_ptr<uint8_t[]> loaded_track_data;
uint8_t loaded_track_status = 0;
uint8_t flags = 0;
/* tagging system */
std::unique_ptr<uint8_t[]> tag_data;
};
struct floppy_params
{
int param;
int value;
};
static floperr_t floppy_track_unload(floppy_image_legacy *floppy);
OPTION_GUIDE_START(floplgcy_option_guide)
OPTION_INT('H', "heads", "Heads")
OPTION_INT('T', "tracks", "Tracks")
OPTION_INT('S', "sectors", "Sectors")
OPTION_INT('L', "sectorlength", "Sector Bytes")
OPTION_INT('I', "interleave", "Interleave")
OPTION_INT('F', "firstsectorid", "First Sector")
OPTION_GUIDE_END
const util::option_guide &floppy_option_guide()
{
return floplgcy_option_guide;
}
static void floppy_close_internal(floppy_image_legacy *floppy);
/*********************************************************************
opening, closing and creating of floppy images
*********************************************************************/
/* basic floppy_image_legacy initialization common to floppy_open() and floppy_create() */
static floppy_image_legacy *floppy_init(util::random_read_write::ptr &&io, int flags)
{
floppy_image_legacy *floppy;
floppy = new floppy_image_legacy;
floppy->io = std::move(io);
floppy->flags = (uint8_t) flags;
return floppy;
}
/* main code for identifying and maybe opening a disk image; not exposed
* directly because this function is big and hideous */
static floperr_t floppy_open_internal(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *floppy_options, int max_options, int flags, floppy_image_legacy **outfloppy,
int *outoption)
{
floperr_t err;
floppy_image_legacy *floppy;
int best_option = -1;
int best_vote = 0;
int vote;
size_t i;
floppy = floppy_init(std::move(io), flags);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* vote on the best format */
for (i = 0; (i < max_options) && floppy_options[i].construct; i++)
{
if (extension.empty() || !floppy_options[i].extensions || image_find_extension(floppy_options[i].extensions, extension.c_str()))
{
if (floppy_options[i].identify)
{
vote = 0;
err = floppy_options[i].identify(floppy, &floppy_options[i], &vote);
if (err)
goto done;
}
else
{
vote = 1;
}
/* is this option a better one? */
if (vote > best_vote)
{
best_vote = vote;
best_option = i;
}
}
}
/* did we find a format? */
if (best_option == -1)
{
err = FLOPPY_ERROR_INVALIDIMAGE;
goto done;
}
if (outfloppy)
{
/* call the format constructor */
err = floppy_options[best_option].construct(floppy, &floppy_options[best_option], nullptr);
if (err)
goto done;
floppy->floppy_option = &floppy_options[best_option];
}
if (best_vote != 100)
{
printf("Loading image that is not 100%% recognized\n");
}
err = FLOPPY_ERROR_SUCCESS;
done:
/* if we have a floppy disk and we either errored or are not keeping it, close it */
if (floppy && (!outfloppy || err))
{
floppy_close_internal(floppy);
floppy = nullptr;
}
if (outoption)
*outoption = err ? -1 : best_option;
if (outfloppy)
*outfloppy = floppy;
return err;
}
floperr_t floppy_identify(util::random_read_write::ptr &&io, const char *extension,
const struct FloppyFormat *formats, int *identified_format)
{
return floppy_open_internal(std::move(io), extension, formats, INT_MAX, FLOPPY_FLAGS_READONLY, nullptr, identified_format);
}
floperr_t floppy_open(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy)
{
return floppy_open_internal(std::move(io), extension, format, 1, flags, outfloppy, nullptr);
}
floperr_t floppy_open_choices(util::random_read_write::ptr &&io, const std::string &extension,
const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy)
{
return floppy_open_internal(std::move(io), extension, formats, INT_MAX, flags, outfloppy, nullptr);
}
floperr_t floppy_create(util::random_read_write::ptr &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy)
{
floppy_image_legacy *floppy = nullptr;
floperr_t err;
int heads, tracks, h, t;
std::unique_ptr<util::option_resolution> alloc_resolution;
assert(format);
/* create the new image */
floppy = floppy_init(std::move(io), 0);
if (!floppy)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
/* if this format expects creation parameters and none were specified, create some */
if (!parameters && format->param_guidelines)
{
try { alloc_resolution = std::make_unique<util::option_resolution>(floplgcy_option_guide); }
catch (...)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
alloc_resolution->set_specification(format->param_guidelines);
parameters = alloc_resolution.get();
}
/* call the format constructor */
err = format->construct(floppy, format, parameters);
if (err)
goto done;
/* format the disk, ignoring if formatting not implemented */
if (floppy->format.format_track)
{
heads = floppy_get_heads_per_disk(floppy);
tracks = floppy_get_tracks_per_disk(floppy);
for (h = 0; h < heads; h++)
{
for (t = 0; t < tracks; t++)
{
err = floppy->format.format_track(floppy, h, t, parameters);
if (err)
goto done;
}
}
}
/* call the post_format function, if present */
if (floppy->format.post_format)
{
err = floppy->format.post_format(floppy, parameters);
if (err)
goto done;
}
floppy->floppy_option = format;
err = FLOPPY_ERROR_SUCCESS;
done:
if (err && floppy)
{
floppy_close_internal(floppy);
floppy = nullptr;
}
if (outfloppy)
*outfloppy = floppy;
else if (floppy)
floppy_close_internal(floppy);
return err;
}
static void floppy_close_internal(floppy_image_legacy *floppy)
{
if (floppy) {
floppy_track_unload(floppy);
if(floppy->floppy_option && floppy->floppy_option->destruct)
floppy->floppy_option->destruct(floppy, floppy->floppy_option);
delete floppy;
}
}
void floppy_close(floppy_image_legacy *floppy)
{
floppy_close_internal(floppy);
}
/*********************************************************************
functions useful in format constructors
*********************************************************************/
struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy)
{
assert(floppy);
return &floppy->format;
}
void *floppy_tag(floppy_image_legacy *floppy)
{
assert(floppy);
return floppy->tag_data.get();
}
void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize)
{
floppy->tag_data = std::make_unique<uint8_t[]>(tagsize);
return floppy->tag_data.get();
}
uint8_t floppy_get_filler(floppy_image_legacy *floppy)
{
// FIXME: remove this function, it's here for legacy reasons
// the caller actually sets the filler byte - in practice it's always 0xff but there's no actual guarantee
return 0xff;
}
util::random_read_write &floppy_get_io(floppy_image_legacy *floppy)
{
return *floppy->io;
}
/*********************************************************************
calls for accessing the raw disk image
*********************************************************************/
void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length)
{
size_t actual;
floppy->io->read_at(offset, buffer, length, actual);
}
void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length)
{
size_t actual;
floppy->io->write_at(offset, buffer, length, actual);
}
void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length)
{
uint8_t buffer[512];
memset(buffer, filler, std::min(sizeof(buffer), length));
while (length)
{
size_t const block = std::min(sizeof(buffer), length);
size_t actual;
floppy->io->write_at(offset, buffer, block, actual);
offset += block;
length -= block;
}
}
uint64_t floppy_image_size(floppy_image_legacy *floppy)
{
uint64_t result;
floppy->io->length(result);
return result;
}
/*********************************************************************
calls for accessing disk image data
*********************************************************************/
static floperr_t floppy_readwrite_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset,
void *buffer, size_t buffer_len, bool writing, bool indexed, int ddam)
{
floperr_t err;
const struct FloppyCallbacks *fmt;
size_t this_buffer_len;
std::vector<uint8_t> alloc_buf;
uint32_t sector_length;
uint8_t *buffer_ptr = (uint8_t *)buffer;
floperr_t (*read_sector)(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
fmt = floppy_callbacks(floppy);
/* choose proper calls for indexed vs non-indexed */
if (indexed)
{
read_sector = fmt->read_indexed_sector;
write_sector = fmt->write_indexed_sector;
if (!fmt->get_indexed_sector_info)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
else
{
read_sector = fmt->read_sector;
write_sector = fmt->write_sector;
if (!fmt->get_sector_length)
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
}
/* check to make sure that the operation is supported */
if (!read_sector || (writing && !write_sector))
{
err = FLOPPY_ERROR_UNSUPPORTED;
goto done;
}
/* main loop */
while(buffer_len > 0)
{
/* find out the size of this sector */
if (indexed)
err = fmt->get_indexed_sector_info(floppy, head, track, sector, nullptr, nullptr, nullptr, &sector_length, nullptr);
else
err = fmt->get_sector_length(floppy, head, track, sector, &sector_length);
if (err)
goto done;
/* do we even do anything with this sector? */
if (offset < sector_length)
{
/* ok we will be doing something */
if ((offset > 0) || (buffer_len < sector_length))
{
/* we will be doing an partial read/write; in other words we
* will not be reading/writing a full sector */
alloc_buf.resize(sector_length);
/* read the sector (we need to do this even when writing */
err = read_sector(floppy, head, track, sector, &alloc_buf[0], sector_length);
if (err)
goto done;
this_buffer_len = std::min(buffer_len, size_t(sector_length - offset));
if (writing)
{
memcpy(&alloc_buf[offset], buffer_ptr, this_buffer_len);
err = write_sector(floppy, head, track, sector, &alloc_buf[0], sector_length, ddam);
if (err)
goto done;
}
else
{
memcpy(buffer_ptr, &alloc_buf[offset], this_buffer_len);
}
offset += this_buffer_len;
offset %= sector_length;
}
else
{
this_buffer_len = sector_length;
if (writing)
err = write_sector(floppy, head, track, sector, buffer_ptr, sector_length, ddam);
else
err = read_sector(floppy, head, track, sector, buffer_ptr, sector_length);
if (err)
goto done;
}
}
else
{
/* skip this sector */
offset -= sector_length;
this_buffer_len = 0;
}
buffer_ptr += this_buffer_len;
buffer_len -= this_buffer_len;
sector++;
}
err = FLOPPY_ERROR_SUCCESS;
done:
return err;
}
floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, buffer, buffer_len, false, false, 0);
}
floperr_t floppy_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector, offset, (void *) buffer, buffer_len, true, false, ddam);
}
floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, buffer, buffer_len, false, true, 0);
}
floperr_t floppy_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam)
{
return floppy_readwrite_sector(floppy, head, track, sector_index, offset, (void *) buffer, buffer_len, true, true, ddam);
}
static floperr_t floppy_get_track_data_offset(floppy_image_legacy *floppy, int head, int track, uint64_t *offset)
{
floperr_t err;
const struct FloppyCallbacks *callbacks;
*offset = 0;
callbacks = floppy_callbacks(floppy);
if (callbacks->get_track_data_offset)
{
err = callbacks->get_track_data_offset(floppy, head, track, offset);
if (err)
return err;
}
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t floppy_read_track_offset(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buffer_len)
{
floperr_t err;
const struct FloppyCallbacks *format;
format = floppy_callbacks(floppy);
if (!format->read_track)
return FLOPPY_ERROR_UNSUPPORTED;
err = floppy_track_unload(floppy);
if (err)
return err;
err = format->read_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_read_track(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len)
{
return floppy_read_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_read_track_data(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len)
{
floperr_t err;
uint64_t offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_read_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
static floperr_t floppy_write_track_offset(floppy_image_legacy *floppy, int head, int track, uint64_t offset, const void *buffer, size_t buffer_len)
{
floperr_t err;
/* track writing supported? */
if (!floppy_callbacks(floppy)->write_track)
return FLOPPY_ERROR_UNSUPPORTED;
/* read only? */
if (floppy->flags & FLOPPY_FLAGS_READONLY)
return FLOPPY_ERROR_READONLY;
err = floppy_track_unload(floppy);
if (err)
return err;
err = floppy_callbacks(floppy)->write_track(floppy, head, track, offset, buffer, buffer_len);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
floperr_t floppy_write_track(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
return floppy_write_track_offset(floppy, head, track, 0, buffer, buffer_len);
}
floperr_t floppy_write_track_data(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len)
{
floperr_t err;
uint64_t offset;
err = floppy_get_track_data_offset(floppy, head, track, &offset);
if (err)
return err;
return floppy_write_track_offset(floppy, head, track, offset, buffer, buffer_len);
}
floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, util::option_resolution *parameters)
{
floperr_t err;
struct FloppyCallbacks *format;
std::unique_ptr<util::option_resolution> alloc_resolution;
/* supported? */
format = floppy_callbacks(floppy);
if (!format->format_track)
return FLOPPY_ERROR_UNSUPPORTED;
/* create a dummy resolution; if no parameters were specified */
if (!parameters)
{
try
{
alloc_resolution = std::make_unique<util::option_resolution>(floplgcy_option_guide);
}
catch (...)
{
return FLOPPY_ERROR_OUTOFMEMORY;
}
alloc_resolution->set_specification(floppy->floppy_option->param_guidelines);
parameters = alloc_resolution.get();
}
err = format->format_track(floppy, head, track, parameters);
if (err)
return err;
return FLOPPY_ERROR_SUCCESS;
}
int floppy_get_tracks_per_disk(floppy_image_legacy *floppy)
{
return floppy_callbacks(floppy)->get_tracks_per_disk(floppy);
}
int floppy_get_heads_per_disk(floppy_image_legacy *floppy)
{
return floppy_callbacks(floppy)->get_heads_per_disk(floppy);
}
uint32_t floppy_get_track_size(floppy_image_legacy *floppy, int head, int track)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_track_size)
return 0;
return fmt->get_track_size(floppy, head, track);
}
floperr_t floppy_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_sector_length)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_sector_length(floppy, head, track, sector, sector_length);
}
floperr_t floppy_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags)
{
const struct FloppyCallbacks *fmt;
fmt = floppy_callbacks(floppy);
if (!fmt->get_indexed_sector_info)
return FLOPPY_ERROR_UNSUPPORTED;
return fmt->get_indexed_sector_info(floppy, head, track, sector_index, cylinder, side, sector, sector_length, flags);
}
floperr_t floppy_get_sector_count(floppy_image_legacy *floppy, int head, int track, int *sector_count)
{
floperr_t err;
int sector_index = 0;
do
{
err = floppy_get_indexed_sector_info(floppy, head, track, sector_index, nullptr, nullptr, nullptr, nullptr, nullptr);
if (!err)
sector_index++;
}
while(!err);
if (sector_index && (err == FLOPPY_ERROR_SEEKERROR))
err = FLOPPY_ERROR_SUCCESS;
if (sector_count)
*sector_count = err ? 0 : sector_index;
return err;
}
int floppy_is_read_only(floppy_image_legacy *floppy)
{
return floppy->flags & FLOPPY_FLAGS_READONLY;
}
uint8_t floppy_random_byte(floppy_image_legacy *floppy)
{
/* can't use mame_rand(); this might not be in the core */
#ifdef rand
#undef rand
#endif
return rand();
}
/*********************************************************************
calls for track based IO
*********************************************************************/
floperr_t floppy_load_track(floppy_image_legacy *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length)
{
floperr_t err;
uint32_t track_size;
/* have we already loaded this track? */
if (((floppy->loaded_track_status & TRACK_LOADED) == 0) || (head != floppy->loaded_track_head) || (track != floppy->loaded_track_index))
{
err = floppy_track_unload(floppy);
if (err)
goto error;
track_size = floppy_callbacks(floppy)->get_track_size(floppy, head, track);
floppy->loaded_track_data = std::make_unique<uint8_t[]>(track_size);
floppy->loaded_track_size = track_size;
floppy->loaded_track_head = head;
floppy->loaded_track_index = track;
err = floppy_callbacks(floppy)->read_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data.get(), floppy->loaded_track_size);
if (err)
goto error;
floppy->loaded_track_status |= TRACK_LOADED | (dirtify ? TRACK_DIRTY : 0);
}
else
floppy->loaded_track_status |= (dirtify ? TRACK_DIRTY : 0);
if (track_data)
*track_data = floppy->loaded_track_data.get();
if (track_length)
*track_length = floppy->loaded_track_size;
return FLOPPY_ERROR_SUCCESS;
error:
if (track_data)
*track_data = nullptr;
if (track_length)
*track_length = 0;
return err;
}
static floperr_t floppy_track_unload(floppy_image_legacy *floppy)
{
int err;
if (floppy->loaded_track_status & TRACK_DIRTY)
{
err = floppy_callbacks(floppy)->write_track(floppy, floppy->loaded_track_head, floppy->loaded_track_index, 0, floppy->loaded_track_data.get(), floppy->loaded_track_size);
if (err)
return (floperr_t)err;
}
floppy->loaded_track_status &= ~(TRACK_LOADED | TRACK_DIRTY);
return FLOPPY_ERROR_SUCCESS;
}
/*********************************************************************
accessors for meta information about the image
*********************************************************************/
const char *floppy_format_description(floppy_image_legacy *floppy)
{
return floppy->floppy_option->description;
}
/*********************************************************************
misc calls
*********************************************************************/
const char *floppy_error(floperr_t err)
{
static const char *const error_messages[] =
{
"The operation completed successfully",
"Fatal internal error",
"This operation is unsupported",
"Out of memory",
"Seek error",
"Invalid image",
"Attempted to write to read only image",
"No space left on image",
"Parameter out of range",
"Required parameter not specified"
};
if ((err < 0) || (err >= std::size(error_messages)))
return nullptr;
return error_messages[err];
}
LEGACY_FLOPPY_OPTIONS_START(default)
LEGACY_FLOPPY_OPTIONS_END

View File

@ -0,0 +1,214 @@
// license:BSD-3-Clause
// copyright-holders:Nathan Woods
/*********************************************************************
flopimg_legacy.h
Floppy disk image abstraction code (legacy implementation)
*********************************************************************/
#ifndef MAME_FORMATS_FLOPIMG_LEGACY_H
#define MAME_FORMATS_FLOPIMG_LEGACY_H
#pragma once
#include "utilfwd.h"
#include <memory>
#include <string>
#include <cstddef>
#include <cstdint>
/***************************************************************************
Constants
***************************************************************************/
#define FLOPPY_FLAGS_READWRITE 0
#define FLOPPY_FLAGS_READONLY 1
/* sector has a deleted data address mark */
#define ID_FLAG_DELETED_DATA 0x0001
/* CRC error in id field */
#define ID_FLAG_CRC_ERROR_IN_ID_FIELD 0x0002
/* CRC error in data field */
#define ID_FLAG_CRC_ERROR_IN_DATA_FIELD 0x0004
/***************************************************************************
Type definitions
***************************************************************************/
enum floperr_t
{
FLOPPY_ERROR_SUCCESS, /* no error */
FLOPPY_ERROR_INTERNAL, /* fatal internal error */
FLOPPY_ERROR_UNSUPPORTED, /* this operation is unsupported */
FLOPPY_ERROR_OUTOFMEMORY, /* ran out of memory */
FLOPPY_ERROR_SEEKERROR, /* attempted to seek to nonexistent location */
FLOPPY_ERROR_INVALIDIMAGE, /* this image in invalid */
FLOPPY_ERROR_READONLY, /* attempt to write to read-only image */
FLOPPY_ERROR_NOSPACE,
FLOPPY_ERROR_PARAMOUTOFRANGE,
FLOPPY_ERROR_PARAMNOTSPECIFIED
};
struct floppy_image_legacy;
struct FloppyCallbacks
{
floperr_t (*read_sector)(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen);
floperr_t (*write_sector)(floppy_image_legacy *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, void *buffer, size_t buflen);
floperr_t (*write_indexed_sector)(floppy_image_legacy *floppy, int head, int track, int sector_index, const void *buffer, size_t buflen, int ddam);
floperr_t (*read_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, void *buffer, size_t buflen);
floperr_t (*write_track)(floppy_image_legacy *floppy, int head, int track, uint64_t offset, const void *buffer, size_t buflen);
floperr_t (*format_track)(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params);
floperr_t (*post_format)(floppy_image_legacy *floppy, util::option_resolution *params);
int (*get_heads_per_disk)(floppy_image_legacy *floppy);
int (*get_tracks_per_disk)(floppy_image_legacy *floppy);
int (*get_sectors_per_track)(floppy_image_legacy *floppy, int head, int track);
uint32_t (*get_track_size)(floppy_image_legacy *floppy, int head, int track);
floperr_t (*get_sector_length)(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length);
floperr_t (*get_indexed_sector_info)(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags);
floperr_t (*get_track_data_offset)(floppy_image_legacy *floppy, int head, int track, uint64_t *offset);
};
struct FloppyFormat
{
const char *name;
const char *extensions;
const char *description;
floperr_t (*identify)(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote);
floperr_t (*construct)(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params);
floperr_t (*destruct)(floppy_image_legacy *floppy, const struct FloppyFormat *format);
const char *param_guidelines;
};
#define FLOPPY_IDENTIFY(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, int *vote)
#define FLOPPY_CONSTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format, util::option_resolution *params)
#define FLOPPY_DESTRUCT(name) floperr_t name(floppy_image_legacy *floppy, const struct FloppyFormat *format)
FLOPPY_IDENTIFY(td0_dsk_identify);
FLOPPY_CONSTRUCT(td0_dsk_construct);
FLOPPY_DESTRUCT(td0_dsk_destruct);
FLOPPY_IDENTIFY(imd_dsk_identify);
FLOPPY_CONSTRUCT(imd_dsk_construct);
FLOPPY_IDENTIFY(cqm_dsk_identify);
FLOPPY_CONSTRUCT(cqm_dsk_construct);
FLOPPY_IDENTIFY(dsk_dsk_identify);
FLOPPY_CONSTRUCT(dsk_dsk_construct);
FLOPPY_IDENTIFY(d88_dsk_identify);
FLOPPY_CONSTRUCT(d88_dsk_construct);
FLOPPY_IDENTIFY(fdi_dsk_identify);
FLOPPY_CONSTRUCT(fdi_dsk_construct);
#define LEGACY_FLOPPY_OPTIONS_NAME(name) floppyoptions_##name
#define LEGACY_FLOPPY_OPTIONS_START(name) \
const struct FloppyFormat floppyoptions_##name[] = \
{
#define LEGACY_FLOPPY_OPTIONS_END0 \
{ nullptr } \
};
#define LEGACY_FLOPPY_OPTIONS_EXTERN(name) \
extern const struct FloppyFormat floppyoptions_##name[]
#define LEGACY_FLOPPY_OPTION(name, extensions_, description_, identify_, construct_, destruct_, ranges_)\
{ #name, extensions_, description_, identify_, construct_, destruct_, ranges_ },
#define LEGACY_FLOPPY_OPTIONS_END \
LEGACY_FLOPPY_OPTION( fdi, "fdi", "Formatted Disk Image", fdi_dsk_identify, fdi_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( td0, "td0", "Teledisk floppy disk image", td0_dsk_identify, td0_dsk_construct, td0_dsk_destruct, nullptr) \
LEGACY_FLOPPY_OPTION( imd, "imd", "IMD floppy disk image", imd_dsk_identify, imd_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( cqm, "cqm,dsk", "CopyQM floppy disk image", cqm_dsk_identify, cqm_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( dsk, "dsk", "DSK floppy disk image", dsk_dsk_identify, dsk_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTION( d88, "d77,d88,1dd", "D88 Floppy Disk image", d88_dsk_identify, d88_dsk_construct, nullptr, nullptr) \
LEGACY_FLOPPY_OPTIONS_END0
LEGACY_FLOPPY_OPTIONS_EXTERN(default);
#define PARAM_END '\0'
#define PARAM_HEADS 'H'
#define PARAM_TRACKS 'T'
#define PARAM_SECTORS 'S'
#define PARAM_SECTOR_LENGTH 'L'
#define PARAM_INTERLEAVE 'I'
#define PARAM_FIRST_SECTOR_ID 'F'
#define HEADS(range) "H" #range
#define TRACKS(range) "T" #range
#define SECTORS(range) "S" #range
#define SECTOR_LENGTH(range) "L" #range
#define INTERLEAVE(range) "I" #range
#define FIRST_SECTOR_ID(range) "F" #range
/***************************************************************************
Prototypes
***************************************************************************/
/* opening, closing and creating of floppy images */
floperr_t floppy_open(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *format, int flags, floppy_image_legacy **outfloppy);
floperr_t floppy_open_choices(std::unique_ptr<util::random_read_write> &&io, const std::string &extension, const struct FloppyFormat *formats, int flags, floppy_image_legacy **outfloppy);
floperr_t floppy_create(std::unique_ptr<util::random_read_write> &&io, const struct FloppyFormat *format, util::option_resolution *parameters, floppy_image_legacy **outfloppy);
void floppy_close(floppy_image_legacy *floppy);
/* useful for identifying a floppy image */
floperr_t floppy_identify(std::unique_ptr<util::random_read_write> &&io, const char *extension, const struct FloppyFormat *formats, int *identified_format);
/* functions useful within format constructors */
void *floppy_tag(floppy_image_legacy *floppy);
void *floppy_create_tag(floppy_image_legacy *floppy, size_t tagsize);
struct FloppyCallbacks *floppy_callbacks(floppy_image_legacy *floppy);
uint8_t floppy_get_filler(floppy_image_legacy *floppy);
util::random_read_write &floppy_get_io(floppy_image_legacy *floppy);
/* calls for accessing disk image data */
floperr_t floppy_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_sector(floppy_image_legacy *floppy, int head, int track, int sector, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, void *buffer, size_t buffer_len);
floperr_t floppy_write_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector_index, int offset, const void *buffer, size_t buffer_len, int ddam);
floperr_t floppy_read_track(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_read_track_data(floppy_image_legacy *floppy, int head, int track, void *buffer, size_t buffer_len);
floperr_t floppy_write_track_data(floppy_image_legacy *floppy, int head, int track, const void *buffer, size_t buffer_len);
floperr_t floppy_format_track(floppy_image_legacy *floppy, int head, int track, util::option_resolution *params);
int floppy_get_tracks_per_disk(floppy_image_legacy *floppy);
int floppy_get_heads_per_disk(floppy_image_legacy *floppy);
uint32_t floppy_get_track_size(floppy_image_legacy *floppy, int head, int track);
floperr_t floppy_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, uint32_t *sector_length);
floperr_t floppy_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, uint32_t *sector_length, unsigned long *flags);
floperr_t floppy_get_sector_count(floppy_image_legacy *floppy, int head, int track, int *sector_count);
floperr_t floppy_load_track(floppy_image_legacy *floppy, int head, int track, int dirtify, void **track_data, size_t *track_length);
int floppy_is_read_only(floppy_image_legacy *floppy);
uint8_t floppy_random_byte(floppy_image_legacy *floppy);
/* accessors for meta information about the image */
const char *floppy_format_description(floppy_image_legacy *floppy);
/* calls for accessing the raw disk image */
void floppy_image_read(floppy_image_legacy *floppy, void *buffer, uint64_t offset, size_t length);
void floppy_image_write(floppy_image_legacy *floppy, const void *buffer, uint64_t offset, size_t length);
void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint64_t offset, size_t length);
uint64_t floppy_image_size(floppy_image_legacy *floppy);
/* misc */
const char *floppy_error(floperr_t err);
const util::option_guide &floppy_option_guide();
#endif // MAME_FORMATS_FLOPIMG_LEGACY_H

View File

@ -6,7 +6,7 @@
#include "fm7_cas.h"
#include <cassert>
#include <cstring>
#define WAVE_HIGH 0x5a9e
#define WAVE_LOW -0x5a9e

View File

@ -1,8 +1,9 @@
// license:BSD-3-Clause
// copyright-holders:Sean Young
#include <cassert>
#include "formats/fmsx_cas.h"
#include "fmsx_cas.h"
#include <cstring>
#define CAS_PERIOD (16)

View File

@ -8,8 +8,6 @@
* Created on: 23/03/2014
*/
#include <cassert>
#include "formats/fmtowns_dsk.h"
fmtowns_format::fmtowns_format() : wd177x_format(formats)

View File

@ -9,9 +9,12 @@
***************************************************************************/
#include "fsd_dsk.h"
#include "imageutl.h"
#include "ioprocs.h"
#include <cstring>
/*********************************************************************

View File

@ -12,7 +12,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
#include "wd177x_dsk.h"
/**************************************************************************/

View File

@ -14,6 +14,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#define G64_FORMAT_HEADER "GCR-1541"

View File

@ -6,9 +6,8 @@
Miodrag Milanovic
*/
#include "gtp_cas.h"
#include <cassert>
#include "gtp_cas.h"
#define GTP_WAV_FREQUENCY 44100

View File

@ -13,8 +13,6 @@ We output a leader, followed by the contents of the H8T file.
#include "h8_cas.h"
#include <cassert>
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767

View File

@ -8,10 +8,10 @@
*********************************************************************/
#include <cassert>
#include "hect_dsk.h"
#include "basicdsk.h"
#include "formats/hect_dsk.h"
#include "formats/basicdsk.h"
#include <cstring>
/*****************************************************************************/
/****** Management of the floppy images 200Ko and 800Ko *********************/

View File

@ -12,7 +12,7 @@
#pragma once
#include "flopimg.h"
#include "flopimg_legacy.h"
/**************************************************************************/

View File

@ -14,7 +14,6 @@ You can find some *.K7 file on serveral server in France
Updated 3/1/10 : use real value for timing.
********************************************************************/
#include <cassert>
#include "hect_tap.h"

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/hp_ipc_dsk.h"
hp_ipc_format::hp_ipc_format() : wd177x_format(formats)

View File

@ -50,6 +50,8 @@
#include "coretmpl.h" // BIT
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
// Debugging
#define VERBOSE 0

View File

@ -103,6 +103,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#define HFE_FORMAT_HEADER "HXCPICFE"

View File

@ -5,6 +5,8 @@
#include "ioprocs.h"
#include <cstring>
#define MFM_FORMAT_HEADER "HXCMFM"

View File

@ -31,6 +31,7 @@
*********************************************************************/
#include "ibmxdf_dsk.h"
#include "imageutl.h"
#include "ioprocs.h"

View File

@ -14,6 +14,10 @@
#include "osdcore.h"
#ifndef LOG_FORMATS
#define LOG_FORMATS(...) do { if (0) osd_printf_info(__VA_ARGS__); } while (false)
#endif
/* -----------------------------------------------------------------------
* CRC stuff
* ----------------------------------------------------------------------- */

View File

@ -9,9 +9,12 @@
*********************************************************************/
#include "imd_dsk.h"
#include "flopimg_legacy.h"
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#include <cstring>

View File

@ -19,6 +19,8 @@
#include "coretmpl.h" // BIT
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
// Debugging
#define VERBOSE 0

View File

@ -4,7 +4,7 @@
#include "ioprocs.h"
#include <cassert>
#include <cstring>
const floppy_format_type FLOPPY_IPF_FORMAT = &floppy_image_format_creator<ipf_format>;

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/iq151_dsk.h"
iq151_format::iq151_format() : upd765_format(formats)

View File

@ -10,8 +10,6 @@
*********************************************************************/
#include <cassert>
#include "formats/itt3030_dsk.h"
itt3030_format::itt3030_format() : wd177x_format(formats)

View File

@ -162,6 +162,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
#include <zlib.h>

View File

@ -108,6 +108,8 @@
#include "ioprocs.h"
#include "osdcore.h" // osd_printf_*
jvc_format::jvc_format()
{

View File

@ -16,8 +16,6 @@
*********************************************************************/
#include <cassert>
#include "formats/kaypro_dsk.h"
kayproii_format::kayproii_format() : upd765_format(formats)

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/kc85_dsk.h"
kc85_format::kc85_format() : upd765_format(formats)

View File

@ -15,7 +15,7 @@
#include "kc_cas.h"
#include <cassert>
#include <cstring>
#define SMPLO -32768
#define SMPHI 32767

View File

@ -2,7 +2,7 @@
// copyright-holders:Wilbert Pol
#include "kim1_cas.h"
#include <cassert>
#include <cstring>
#define SMPLO -32768
#define SMPHI 32767

View File

@ -1,9 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Krzysztof Strzecha
/* .LVT tape images */
#include "lviv_lvt.h"
#include <cassert>
#include "lviv_lvt.h"
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/m5_dsk.h"
m5_format::m5_format() : upd765_format(formats)

View File

@ -56,8 +56,6 @@ TAP - has an ID header of TAP_DGOS_BEE or MBEE, null terminated.
********************************************************************/
#include <cassert>
#include "mbee_cas.h"
#define WAVEENTRY_LOW -32768

View File

@ -6,6 +6,8 @@
#include <zlib.h>
#include <cstring>
/*
Mess floppy image structure:

View File

@ -8,8 +8,6 @@
*********************************************************************/
#include <cassert>
#include "formats/mm_dsk.h"
mm1_format::mm1_format() : upd765_format(formats)

View File

@ -10,8 +10,6 @@
#include "formats/ms0515_dsk.h"
#include <cassert>
ms0515_format::ms0515_format() : wd177x_format(formats)
{
}

Some files were not shown because too many files have changed in this diff Show More