summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/formats/86f_dsk.cpp272
-rw-r--r--src/lib/formats/86f_dsk.h37
-rw-r--r--src/lib/formats/a26_cas.cpp2
-rw-r--r--src/lib/formats/abc800i_dsk.cpp5
-rw-r--r--src/lib/formats/ace_tap.cpp2
-rw-r--r--src/lib/formats/acorn_dsk.cpp88
-rw-r--r--src/lib/formats/aim_dsk.cpp4
-rw-r--r--src/lib/formats/all.cpp19
-rw-r--r--src/lib/formats/ami_dsk.cpp14
-rw-r--r--src/lib/formats/ap2_dsk.cpp562
-rw-r--r--src/lib/formats/ap2_dsk.h32
-rw-r--r--src/lib/formats/ap_dsk35.cpp62
-rw-r--r--src/lib/formats/apd_dsk.cpp12
-rw-r--r--src/lib/formats/apf_apt.cpp4
-rw-r--r--src/lib/formats/apridisk.cpp13
-rw-r--r--src/lib/formats/as_dsk.cpp250
-rw-r--r--src/lib/formats/as_dsk.h12
-rw-r--r--src/lib/formats/bk0010_dsk.cpp39
-rw-r--r--src/lib/formats/bk0010_dsk.h30
-rw-r--r--src/lib/formats/camplynx_cas.cpp2
-rw-r--r--src/lib/formats/cassimg.cpp54
-rw-r--r--src/lib/formats/cassimg.h2
-rw-r--r--src/lib/formats/cbm_crt.cpp23
-rw-r--r--src/lib/formats/cbm_tap.cpp2
-rw-r--r--src/lib/formats/ccvf_dsk.cpp12
-rw-r--r--src/lib/formats/cgen_cas.cpp2
-rw-r--r--src/lib/formats/concept_dsk.cpp6
-rw-r--r--src/lib/formats/coupedsk.cpp6
-rw-r--r--src/lib/formats/cp68_dsk.cpp14
-rw-r--r--src/lib/formats/cqm_dsk.cpp13
-rw-r--r--src/lib/formats/d64_dsk.cpp9
-rw-r--r--src/lib/formats/d88_dsk.cpp39
-rw-r--r--src/lib/formats/dcp_dsk.cpp14
-rw-r--r--src/lib/formats/dfi_dsk.cpp19
-rw-r--r--src/lib/formats/dim_dsk.cpp15
-rw-r--r--src/lib/formats/dip_dsk.cpp3
-rw-r--r--src/lib/formats/dmk_dsk.cpp138
-rw-r--r--src/lib/formats/ds9_dsk.cpp3
-rw-r--r--src/lib/formats/dsk_dsk.cpp23
-rw-r--r--src/lib/formats/dvk_mx_dsk.cpp145
-rw-r--r--src/lib/formats/dvk_mx_dsk.h13
-rw-r--r--src/lib/formats/esq16_dsk.cpp6
-rw-r--r--src/lib/formats/esq8_dsk.cpp6
-rw-r--r--src/lib/formats/fc100_cas.cpp2
-rw-r--r--src/lib/formats/fdd_dsk.cpp13
-rw-r--r--src/lib/formats/fdos_dsk.cpp9
-rw-r--r--src/lib/formats/flacfile.cpp78
-rw-r--r--src/lib/formats/flex_dsk.cpp9
-rw-r--r--src/lib/formats/flopimg.cpp66
-rw-r--r--src/lib/formats/flopimg.h69
-rw-r--r--src/lib/formats/flopimg_legacy.cpp9
-rw-r--r--src/lib/formats/fm7_cas.cpp2
-rw-r--r--src/lib/formats/fmsx_cas.cpp2
-rw-r--r--src/lib/formats/fs_cbmdos.cpp433
-rw-r--r--src/lib/formats/fs_coco_os9.cpp212
-rw-r--r--src/lib/formats/fs_coco_rsdos.cpp352
-rw-r--r--src/lib/formats/fs_fat.cpp686
-rw-r--r--src/lib/formats/fs_hp98x5.cpp116
-rw-r--r--src/lib/formats/fs_hplif.cpp72
-rw-r--r--src/lib/formats/fs_isis.cpp84
-rw-r--r--src/lib/formats/fs_oric_jasmin.cpp230
-rw-r--r--src/lib/formats/fs_prodos.cpp267
-rw-r--r--src/lib/formats/fs_unformatted.cpp40
-rw-r--r--src/lib/formats/fs_unformatted.h4
-rw-r--r--src/lib/formats/fs_vtech.cpp192
-rw-r--r--src/lib/formats/fsblk.cpp174
-rw-r--r--src/lib/formats/fsblk.h221
-rw-r--r--src/lib/formats/fsblk_vec.cpp14
-rw-r--r--src/lib/formats/fsblk_vec.h11
-rw-r--r--src/lib/formats/fsd_dsk.cpp14
-rw-r--r--src/lib/formats/fsmeta.cpp1
-rw-r--r--src/lib/formats/fsmeta.h1
-rw-r--r--src/lib/formats/g64_dsk.cpp28
-rw-r--r--src/lib/formats/gtp_cas.cpp2
-rw-r--r--src/lib/formats/h17disk.cpp253
-rw-r--r--src/lib/formats/h17disk.h38
-rw-r--r--src/lib/formats/h8_cas.cpp171
-rw-r--r--src/lib/formats/h8_cas.h4
-rw-r--r--src/lib/formats/hect_tap.cpp10
-rw-r--r--src/lib/formats/hp300_dsk.cpp2
-rw-r--r--src/lib/formats/hpi_dsk.cpp10
-rw-r--r--src/lib/formats/hti_tape.cpp137
-rw-r--r--src/lib/formats/hti_tape.h54
-rw-r--r--src/lib/formats/hxchfe_dsk.cpp29
-rw-r--r--src/lib/formats/hxcmfm_dsk.cpp24
-rw-r--r--src/lib/formats/ibmxdf_dsk.cpp8
-rw-r--r--src/lib/formats/idpart_dsk.cpp53
-rw-r--r--src/lib/formats/idpart_dsk.h32
-rw-r--r--src/lib/formats/imd_dsk.cpp11
-rw-r--r--src/lib/formats/img_dsk.cpp15
-rw-r--r--src/lib/formats/ipf_dsk.cpp96
-rw-r--r--src/lib/formats/ipf_dsk.h66
-rw-r--r--src/lib/formats/jfd_dsk.cpp14
-rw-r--r--src/lib/formats/juku_dsk.cpp10
-rw-r--r--src/lib/formats/juku_dsk.h4
-rw-r--r--src/lib/formats/jvc_dsk.cpp18
-rw-r--r--src/lib/formats/kc_cas.cpp12
-rw-r--r--src/lib/formats/kim1_cas.cpp2
-rw-r--r--src/lib/formats/lviv_lvt.cpp2
-rw-r--r--src/lib/formats/lw30_dsk.cpp11
-rw-r--r--src/lib/formats/m20_dsk.cpp13
-rw-r--r--src/lib/formats/mbee_cas.cpp2
-rw-r--r--src/lib/formats/mdos_dsk.cpp32
-rw-r--r--src/lib/formats/mfi_dsk.cpp50
-rw-r--r--src/lib/formats/mfi_dsk.h8
-rw-r--r--src/lib/formats/mz_cas.cpp2
-rw-r--r--src/lib/formats/nabupc_dsk.cpp7
-rw-r--r--src/lib/formats/nfd_dsk.cpp26
-rw-r--r--src/lib/formats/orao_cas.cpp2
-rw-r--r--src/lib/formats/oric_dsk.cpp31
-rw-r--r--src/lib/formats/oric_tap.cpp184
-rw-r--r--src/lib/formats/os9_dsk.cpp3
-rw-r--r--src/lib/formats/p6001_cas.cpp2
-rw-r--r--src/lib/formats/pasti_dsk.cpp12
-rw-r--r--src/lib/formats/pc98_dsk.cpp4
-rw-r--r--src/lib/formats/pc98fdi_dsk.cpp42
-rw-r--r--src/lib/formats/phc25_cas.cpp2
-rw-r--r--src/lib/formats/pmd_cas.cpp2
-rw-r--r--src/lib/formats/poly_dsk.cpp8
-rw-r--r--src/lib/formats/primoptp.cpp4
-rw-r--r--src/lib/formats/rk_cas.cpp8
-rw-r--r--src/lib/formats/rx50_dsk.cpp8
-rw-r--r--src/lib/formats/sap_dsk.cpp169
-rw-r--r--src/lib/formats/sap_dsk.h30
-rw-r--r--src/lib/formats/sdf_dsk.cpp12
-rw-r--r--src/lib/formats/sol_cas.cpp2
-rw-r--r--src/lib/formats/sorc_cas.cpp2
-rw-r--r--src/lib/formats/spc1000_cas.cpp4
-rw-r--r--src/lib/formats/st_dsk.cpp25
-rw-r--r--src/lib/formats/svi_cas.cpp2
-rw-r--r--src/lib/formats/svi_dsk.cpp9
-rw-r--r--src/lib/formats/td0_dsk.cpp20
-rw-r--r--src/lib/formats/thom_cas.cpp22
-rw-r--r--src/lib/formats/thom_dsk.cpp13
-rw-r--r--src/lib/formats/thom_dsk.h4
-rw-r--r--src/lib/formats/ti99_dsk.cpp23
-rw-r--r--src/lib/formats/trd_dsk.cpp9
-rw-r--r--src/lib/formats/trs80_dsk.cpp34
-rw-r--r--src/lib/formats/trs_cas.cpp2
-rw-r--r--src/lib/formats/tzx_cas.cpp117
-rw-r--r--src/lib/formats/uef_cas.cpp17
-rw-r--r--src/lib/formats/uniflex_dsk.cpp5
-rw-r--r--src/lib/formats/upd765_dsk.cpp10
-rw-r--r--src/lib/formats/vdk_dsk.cpp15
-rw-r--r--src/lib/formats/vg5k_cas.cpp2
-rw-r--r--src/lib/formats/vgi_dsk.cpp32
-rw-r--r--src/lib/formats/victor9k_dsk.cpp37
-rw-r--r--src/lib/formats/vt_cas.cpp6
-rw-r--r--src/lib/formats/vt_dsk.cpp73
-rw-r--r--src/lib/formats/vt_dsk.h2
-rw-r--r--src/lib/formats/wavfile.cpp1
-rw-r--r--src/lib/formats/wd177x_dsk.cpp6
-rw-r--r--src/lib/formats/x07_cas.cpp2
-rw-r--r--src/lib/formats/x1_tap.cpp2
-rw-r--r--src/lib/formats/zx81_p.cpp4
-rw-r--r--src/lib/netlist/build/makefile11
-rw-r--r--src/lib/netlist/generated/static_solvers.cpp8602
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx_lib.cpp6
-rwxr-xr-x[-rw-r--r--]src/lib/netlist/nl_create_mame_solvers.sh2
-rw-r--r--src/lib/netlist/nl_dice_compat.h2
-rw-r--r--src/lib/netlist/plib/pexception.cpp2
-rw-r--r--src/lib/netlist/plib/ppreprocessor.cpp2
-rw-r--r--src/lib/netlist/plib/ptests.h4
-rw-r--r--src/lib/netlist/tests/test_penum.cpp2
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp2
-rw-r--r--src/lib/util/aviio.cpp2
-rw-r--r--src/lib/util/bitstream.h68
-rw-r--r--src/lib/util/cdrom.cpp1766
-rw-r--r--src/lib/util/cdrom.h81
-rw-r--r--src/lib/util/chd.cpp1351
-rw-r--r--src/lib/util/chd.h53
-rw-r--r--src/lib/util/chdcodec.cpp87
-rw-r--r--src/lib/util/chdcodec.h7
-rw-r--r--src/lib/util/corefile.cpp124
-rw-r--r--src/lib/util/corefile.h2
-rw-r--r--src/lib/util/corestr.cpp1
-rw-r--r--src/lib/util/coretmpl.h2
-rw-r--r--src/lib/util/coreutil.cpp12
-rw-r--r--src/lib/util/coreutil.h7
-rw-r--r--src/lib/util/delegate.cpp208
-rw-r--r--src/lib/util/dvdrom.cpp4
-rw-r--r--src/lib/util/flac.cpp47
-rw-r--r--src/lib/util/flac.h10
-rw-r--r--src/lib/util/harddisk.cpp7
-rw-r--r--src/lib/util/hash.cpp5
-rw-r--r--src/lib/util/ioprocs.cpp201
-rw-r--r--src/lib/util/ioprocs.h127
-rw-r--r--src/lib/util/ioprocsfill.h65
-rw-r--r--src/lib/util/ioprocsfilter.cpp28
-rw-r--r--src/lib/util/ioprocsvec.h8
-rw-r--r--src/lib/util/jedparse.cpp24
-rw-r--r--src/lib/util/language.cpp7
-rw-r--r--src/lib/util/mfpresolve.cpp431
-rw-r--r--src/lib/util/mfpresolve.h151
-rw-r--r--src/lib/util/msdib.cpp26
-rw-r--r--src/lib/util/options.h2
-rw-r--r--src/lib/util/plaparse.cpp40
-rw-r--r--src/lib/util/png.cpp62
-rw-r--r--src/lib/util/server_http_impl.hpp8
-rw-r--r--src/lib/util/simh_tape_file.cpp6
-rw-r--r--src/lib/util/un7z.cpp3
-rw-r--r--src/lib/util/unzip.cpp45
-rw-r--r--src/lib/util/xmlfile.cpp18
203 files changed, 13086 insertions, 8337 deletions
diff --git a/src/lib/formats/86f_dsk.cpp b/src/lib/formats/86f_dsk.cpp
new file mode 100644
index 00000000000..654e847d8db
--- /dev/null
+++ b/src/lib/formats/86f_dsk.cpp
@@ -0,0 +1,272 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, Carl
+
+#include "86f_dsk.h"
+
+#include "ioprocs.h"
+
+#include <cstring>
+#include <tuple>
+
+
+namespace {
+
+#define _86F_FORMAT_HEADER "86BF"
+
+#pragma pack(1)
+
+struct _86FIMG
+{
+ uint8_t headername[4];
+ uint8_t minor_version;
+ uint8_t major_version;
+ uint16_t flags;
+ uint32_t firsttrackoffs;
+};
+
+#pragma pack()
+
+enum
+{
+ SURFACE_DESC = 1,
+ TYPE_MASK = 6,
+ TYPE_DD = 0,
+ TYPE_HD = 2,
+ TYPE_ED = 4,
+ TYPE_ED2000 = 6,
+ TWO_SIDES = 8,
+ WRITE_PROTECT = 0x10,
+ RPM_MASK = 0x60,
+ RPM_0 = 0,
+ RPM_1 = 0x20,
+ RPM_15 = 0x40,
+ RPM_2 = 0x60,
+ EXTRA_BC = 0x80,
+ ZONED_RPM = 0x100,
+ ZONE_PREA2_1 = 0,
+ ZONE_PREA2_2 = 0x200,
+ ZONE_A2 = 0x400,
+ ZONE_C64 = 0x600,
+ ENDIAN_BIG = 0x800,
+ RPM_FAST = 0x1000,
+ TOTAL_BC = 0x1000
+};
+
+} // anonymous namespace
+
+
+_86f_format::_86f_format() : floppy_image_format_t()
+{
+}
+
+const char *_86f_format::name() const noexcept
+{
+ return "86f";
+}
+
+const char *_86f_format::description() const noexcept
+{
+ return "86f floppy image";
+}
+
+const char *_86f_format::extensions() const noexcept
+{
+ return "86f";
+}
+
+bool _86f_format::supports_save() const noexcept
+{
+ return false;
+}
+
+int _86f_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint8_t header[4];
+ auto const [err, actual] = read_at(io, 0, &header, sizeof(header));
+ if (err) {
+ return 0;
+ }
+ if (!memcmp(header, _86F_FORMAT_HEADER, 4)) {
+ return FIFID_SIGN;
+ }
+ return 0;
+}
+
+void _86f_format::generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const
+{
+ int j = 0;
+ std::vector<uint32_t> &dest = image.get_buffer(track, head);
+ dest.clear();
+
+ for(int i=index_cell; i != track_size; i++, j++) {
+ int databit = trackbuf[i >> 3] & (0x80 >> (i & 7));
+ int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0;
+ if(weakbit && databit)
+ dest.push_back(floppy_image::MG_D | (j*2+1));
+ else if(weakbit && !databit)
+ dest.push_back(floppy_image::MG_N | (j*2+1));
+ else if(databit)
+ dest.push_back(floppy_image::MG_F | (j*2+1));
+ }
+ for(int i=0; i != index_cell; i++, j++) {
+ int databit = trackbuf[i >> 3] & (0x80 >> (i & 7));
+ int weakbit = weak ? weak[i >> 3] & (0x80 >> (i & 7)) : 0;
+ if(weakbit && databit)
+ dest.push_back(floppy_image::MG_D | (j*2+1));
+ else if(weakbit && !databit)
+ dest.push_back(floppy_image::MG_N | (j*2+1));
+ else if(databit)
+ dest.push_back(floppy_image::MG_F | (j*2+1));
+ }
+
+ normalize_times(dest, track_size*2);
+ image.set_write_splice_position(track, head, 0, 0);
+}
+
+bool _86f_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
+{
+ std::error_condition err;
+ size_t actual;
+ _86FIMG header;
+
+ // read header
+ std::tie(err, actual) = read_at(io, 0, &header, sizeof(header));
+ if(err || (actual != sizeof(header)))
+ return false;
+
+ int drivecyl, driveheads;
+ image.get_maximal_geometry(drivecyl, driveheads);
+ bool skip_odd = drivecyl < 50;
+ int imagesides = header.flags & TWO_SIDES ? 2 : 1;
+ int sides = (imagesides == 2) && (driveheads == 2) ? 2 : 1;
+
+ std::vector<uint32_t> tracklist;
+ int tracklistsize = header.firsttrackoffs - 8;
+ tracklist.resize(tracklistsize / 4);
+ std::tie(err, actual) = read_at(io, 8, &tracklist[0], tracklistsize);
+ if(err || (actual != tracklistsize))
+ return false;
+
+ uint32_t tracklen = 0;
+ if((header.flags & (TOTAL_BC | EXTRA_BC | RPM_MASK)) != (TOTAL_BC | EXTRA_BC)) {
+ switch(header.flags & (RPM_MASK | RPM_FAST | TYPE_MASK)) {
+ case TYPE_DD | RPM_2:
+ case TYPE_HD | RPM_2:
+ tracklen = 12750;
+ break;
+ case TYPE_DD | RPM_15:
+ case TYPE_HD | RPM_15:
+ tracklen = 12687;
+ break;
+ case TYPE_DD | RPM_1:
+ case TYPE_HD | RPM_1:
+ tracklen = 12625;
+ break;
+ case TYPE_DD | RPM_0:
+ case TYPE_HD | RPM_0:
+ tracklen = 12500;
+ break;
+ case TYPE_DD | RPM_1 | RPM_FAST:
+ case TYPE_HD | RPM_1 | RPM_FAST:
+ tracklen = 12376;
+ break;
+ case TYPE_DD | RPM_15 | RPM_FAST:
+ case TYPE_HD | RPM_15 | RPM_FAST:
+ tracklen = 12315;
+ break;
+ case TYPE_DD | RPM_2 | RPM_FAST:
+ case TYPE_HD | RPM_2 | RPM_FAST:
+ tracklen = 12254;
+ break;
+
+ case TYPE_ED | RPM_2:
+ tracklen = 25500;
+ break;
+ case TYPE_ED | RPM_15:
+ tracklen = 25375;
+ break;
+ case TYPE_ED | RPM_1:
+ tracklen = 25250;
+ break;
+ case TYPE_ED | RPM_0:
+ tracklen = 25000;
+ break;
+ case TYPE_ED | RPM_1 | RPM_FAST:
+ tracklen = 25752;
+ break;
+ case TYPE_ED | RPM_15 | RPM_FAST:
+ tracklen = 24630;
+ break;
+ case TYPE_ED | RPM_2 | RPM_FAST:
+ tracklen = 24509;
+ break;
+ }
+ }
+ uint32_t trackoff;
+ int trackinfolen = header.flags & EXTRA_BC ? 10 : 6;
+ if(skip_odd)
+ drivecyl *= 2;
+ std::vector<uint8_t> trackbuf;
+ std::vector<uint8_t> weakbuf;
+ int track;
+ for(track=0; (track < (tracklistsize / 4)) && (track < drivecyl); track++) {
+ for(int side=0; side < sides; side++) {
+ trackoff = tracklist[(track * imagesides) + side];
+ if(!trackoff) break;
+ if(!skip_odd || track%2 == 0) {
+ char trackinfo[10];
+ std::tie(err, actual) = read_at(io, trackoff, &trackinfo, trackinfolen); // FIXME: check for errors and premature EOF
+ if(err || (actual != trackinfolen))
+ return false;
+ uint32_t bitcells = tracklen << 4;
+ uint32_t index_cell;
+ if(header.flags & EXTRA_BC)
+ {
+ uint32_t extra = *(uint32_t *)(trackinfo + 2);
+ index_cell = *(uint32_t *)(trackinfo + 6);
+ if((header.flags & TOTAL_BC) && !tracklen)
+ bitcells = extra;
+ else
+ bitcells += (int32_t)extra;
+ }
+ else
+ index_cell = *(uint32_t *)(trackinfo + 2);
+ uint32_t fulltracklen = (bitcells >> 3) + (bitcells & 7 ? 1 : 0);
+ uint8_t *weak = nullptr;
+ trackbuf.resize(fulltracklen);
+ std::tie(err, actual) = read_at(io, trackoff + trackinfolen, &trackbuf[0], fulltracklen);
+ if(err || (actual != fulltracklen))
+ return false;
+ if(header.flags & SURFACE_DESC)
+ {
+ weakbuf.resize(fulltracklen);
+ std::tie(err, actual) = read_at(io, trackoff + trackinfolen + fulltracklen, &weakbuf[0], fulltracklen);
+ if(err || (actual != fulltracklen))
+ return false;
+ weak = &weakbuf[0];
+ }
+ if(skip_odd) {
+ generate_track_from_bitstream_with_weak(track/2, side, &trackbuf[0], weak, index_cell, bitcells, image);
+ }
+ else {
+ generate_track_from_bitstream_with_weak(track, side, &trackbuf[0], weak, index_cell, bitcells, image);
+ }
+ }
+ }
+ if(!trackoff) break;
+ }
+
+ if(imagesides == 2)
+ image.set_variant(track > 50 ? floppy_image::DSHD : floppy_image::DSDD);
+ else
+ image.set_variant(floppy_image::SSDD);
+ return true;
+}
+
+/*
+bool _86f_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
+{
+ return true;
+}
+*/
+const _86f_format FLOPPY_86F_FORMAT;
diff --git a/src/lib/formats/86f_dsk.h b/src/lib/formats/86f_dsk.h
new file mode 100644
index 00000000000..0afbe4d65ee
--- /dev/null
+++ b/src/lib/formats/86f_dsk.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert, Carl
+/*********************************************************************
+
+ formats/86f_dsk.h
+
+ 86f disk images
+
+*********************************************************************/
+#ifndef MAME_FORMATS_86F_DSK_H
+#define MAME_FORMATS_86F_DSK_H
+
+#pragma once
+
+#include "flopimg.h"
+
+class _86f_format : public floppy_image_format_t
+{
+public:
+ _86f_format();
+
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
+ //virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const override;
+
+ virtual const char *name() const noexcept override;
+ virtual const char *description() const noexcept override;
+ virtual const char *extensions() const noexcept override;
+ virtual bool supports_save() const noexcept override;
+
+private:
+ void generate_track_from_bitstream_with_weak(int track, int head, const uint8_t *trackbuf, const uint8_t *weak, int index_cell, int track_size, floppy_image &image) const;
+};
+
+extern const _86f_format FLOPPY_86F_FORMAT;
+
+#endif // MAME_FORMATS_86F_DSK_H
diff --git a/src/lib/formats/a26_cas.cpp b/src/lib/formats/a26_cas.cpp
index 46522bd50de..c609f922348 100644
--- a/src/lib/formats/a26_cas.cpp
+++ b/src/lib/formats/a26_cas.cpp
@@ -120,7 +120,7 @@ static int a26_cas_do_work( int16_t **buffer, const uint8_t *bytes ) {
return size;
}
-static int a26_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int a26_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int16_t *p = buffer;
return a26_cas_do_work( &p, (const uint8_t *)bytes );
diff --git a/src/lib/formats/abc800i_dsk.cpp b/src/lib/formats/abc800i_dsk.cpp
index 1961dd9a9de..9a5a798c886 100644
--- a/src/lib/formats/abc800i_dsk.cpp
+++ b/src/lib/formats/abc800i_dsk.cpp
@@ -89,11 +89,10 @@ const abc800i_format FLOPPY_ABC800I_FORMAT;
int abc800i_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[1];
- size_t actual;
- io.read_at(0x810, h, 1, actual);
+ auto const [err, actual] = read_at(io, 0x810, h, 1);
// start of directory
- if (h[0] == 0x03)
+ if (!err && (actual == 1) && (h[0] == 0x03))
return FIFID_SIGN;
return 0;
diff --git a/src/lib/formats/ace_tap.cpp b/src/lib/formats/ace_tap.cpp
index a2fa9fe8b80..9613450e59e 100644
--- a/src/lib/formats/ace_tap.cpp
+++ b/src/lib/formats/ace_tap.cpp
@@ -135,7 +135,7 @@ static int ace_handle_tap(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int ace_tap_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int ace_tap_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return ace_handle_tap( buffer, bytes );
}
diff --git a/src/lib/formats/acorn_dsk.cpp b/src/lib/formats/acorn_dsk.cpp
index 42a3aa61bdf..682b6424556 100644
--- a/src/lib/formats/acorn_dsk.cpp
+++ b/src/lib/formats/acorn_dsk.cpp
@@ -16,6 +16,7 @@
#include "multibyte.h"
#include <cstring>
+#include <tuple>
acorn_ssd_format::acorn_ssd_format() : wd177x_format(formats)
@@ -45,25 +46,24 @@ int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, con
if (io.length(size))
return -1;
- for (int i=0; formats[i].form_factor; i++)
+ for (int i = 0; formats[i].form_factor; i++)
{
- size_t actual;
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// test for Torch CPN - test pattern at sector &0018
- io.read_at(0x32800, cat, 8, actual);
+ read_at(io, 0x32800, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 8) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for HADFS - test pattern at sector 70
- io.read_at(0x04610, cat, 8, actual);
+ read_at(io, 0x04610, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 8) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for Kenda SD - offset &0962 = 0 SD/1 DD, offset &0963 = disk size blocks / 4 (block size = 1K, ie. 0x400 bytes), reserved tracks = 3, ie. 0x1e00 bytes, soft stagger = 2 sectors, ie. 0x200 bytes
- io.read_at(0x0960, cat, 8, actual);
+ read_at(io, 0x0960, cat, 8); // FIXME: check for errors and premature EOF
if (cat[2] == 0 && ((uint64_t)cat[3] * 4 * 0x400 + 0x2000) == size && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
{
// valid blocks for single sided
@@ -75,7 +75,7 @@ int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, con
}
// read sector count from side 0 catalogue
- io.read_at(0x100, cat, 8, actual);
+ read_at(io, 0x100, cat, 8); // FIXME: check for errors and premature EOF
sectors0 = get_u16be(&cat[6]) & 0x3ff;
LOG_FORMATS("ssd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : "");
@@ -84,11 +84,11 @@ int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, con
if (f.head_count == 2)
{
// read sector count from side 2 catalogue
- io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x100, cat, 8, actual); // sequential
+ read_at(io, (uint64_t)compute_track_size(f) * f.track_count + 0x100, cat, 8); // sequential
sectors2 = get_u16be(&cat[6]) & 0x3ff;
// exception case for Acorn CP/M System Disc 1
- io.read_at(0x367ec, cat, 8, actual);
+ read_at(io, 0x367ec, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "/M ", 4) == 0)
sectors2 = get_u16be(&cat[6]) & 0x3ff;
@@ -99,7 +99,7 @@ int acorn_ssd_format::find_size(util::random_read &io, uint32_t form_factor, con
sectors2 = sectors0;
}
- if (sectors0 > 0 && sectors2 > 0 && size <= (sectors0 + sectors2) * 256)
+ if (sectors0 > 0 && sectors2 > 0 && sectors0 % 10 == 0 && sectors2 % 10 == 0 && size <= (sectors0 + sectors2) * 256)
return i;
}
}
@@ -192,39 +192,38 @@ int acorn_dsd_format::find_size(util::random_read &io, uint32_t form_factor, con
for (int i = 0; formats[i].form_factor; i++)
{
- size_t actual;
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
continue;
// test for Torch CPN - test pattern at sector &0018
- io.read_at(0x1200, cat, 8, actual);
+ read_at(io, 0x1200, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd", 8) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for HADFS - test pattern at sector 70
- io.read_at(0x08c10, cat, 8, actual);
+ read_at(io, 0x08c10, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "\x00\x28\x43\x29\x4a\x47\x48\x00", 8) == 0 && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// test for FLEX - from System Information Record
- io.read_at(0x0226, cat, 2, actual);
+ read_at(io, 0x0226, cat, 2); // FIXME: check for errors and premature EOF
if ((memcmp(cat, "\x4f\x14", 2) == 0 || memcmp(cat, "\x4f\x0a", 2) == 0) && size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
return i;
// read sector count from side 0 catalogue
- io.read_at(0x100, cat, 8, actual);
+ read_at(io, 0x100, cat, 8); // FIXME: check for errors and premature EOF
sectors0 = get_u16be(&cat[6]) & 0x3ff;
LOG_FORMATS("dsd: sector count 0: %d %s\n", sectors0, sectors0 % 10 != 0 ? "invalid" : "");
if ((size <= (uint64_t)compute_track_size(f) * f.track_count * f.head_count) && (sectors0 <= f.track_count * f.sector_count))
{
// read sector count from side 2 catalogue
- io.read_at(0xb00, cat, 8, actual); // interleaved
+ read_at(io, 0xb00, cat, 8); // interleaved
sectors2 = get_u16be(&cat[6]) & 0x3ff;
// exception case for Acorn CP/M System Disc 1
- io.read_at(0x97ec, cat, 8, actual);
+ read_at(io, 0x97ec, cat, 8); // FIXME: check for errors and premature EOF
if (memcmp(cat, "/M ", 4) == 0)
sectors2 = get_u16be(&cat[6]) & 0x3ff;
@@ -295,12 +294,11 @@ const char *opus_ddos_format::extensions() const noexcept
int opus_ddos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- size_t actual;
uint8_t cat[8];
uint32_t sectors0, sectors2;
// read sector count from side 0 catalogue
- io.read_at(0x1000, cat, 8, actual);
+ read_at(io, 0x1000, cat, 8); // FIXME: check for errors and premature EOF
sectors0 = get_u16be(&cat[1]);
LOG_FORMATS("ddos: sector count 0: %d %s\n", sectors0, sectors0 % 18 != 0 ? "invalid" : "");
@@ -319,7 +317,7 @@ int opus_ddos_format::find_size(util::random_read &io, uint32_t form_factor, con
if (f.head_count == 2)
{
// read sector count from side 2 catalogue
- io.read_at((uint64_t)compute_track_size(f) * f.track_count + 0x1000, cat, 8, actual); // sequential
+ read_at(io, (uint64_t)compute_track_size(f) * f.track_count + 0x1000, cat, 8); // sequential
sectors2 = get_u16be(&cat[1]);
LOG_FORMATS("ddos: sector count 2: %d %s\n", sectors2, sectors2 % 18 != 0 ? "invalid" : "");
}
@@ -393,25 +391,30 @@ const char *acorn_adfs_old_format::extensions() const noexcept
int acorn_adfs_old_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
+ std::error_condition err;
size_t actual;
uint8_t map[3];
uint32_t sectors;
uint8_t oldmap[4];
// read sector count from free space map
- io.read_at(0xfc, map, 3, actual);
+ std::tie(err, actual) = read_at(io, 0xfc, map, 3);
+ if (err || (3 != actual))
+ return -1;
sectors = get_u24le(map);
LOG_FORMATS("adfs_o: sector count %d %s\n", sectors, sectors % 16 != 0 ? "invalid" : "");
// read map identifier
- io.read_at(0x201, oldmap, 4, actual);
+ std::tie(err, actual) = read_at(io, 0x201, oldmap, 4);
+ if (err || (4 != actual))
+ return -1;
LOG_FORMATS("adfs_o: map identifier %s %s\n", oldmap, memcmp(oldmap, "Hugo", 4) != 0 ? "invalid" : "");
uint64_t size;
if (io.length(size))
return -1;
- for (int i=0; formats[i].form_factor; i++)
+ for (int i = 0; formats[i].form_factor; i++)
{
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
@@ -429,7 +432,7 @@ int acorn_adfs_old_format::identify(util::random_read &io, uint32_t form_factor,
{
int type = find_size(io, form_factor, variants);
- if(type != -1)
+ if (type != -1)
return FIFID_STRUCT | FIFID_SIZE;
return 0;
@@ -491,14 +494,19 @@ const char *acorn_adfs_new_format::extensions() const noexcept
int acorn_adfs_new_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
+ std::error_condition err;
size_t actual;
uint8_t dform[4];
uint8_t eform[4];
// read map identifiers for D and E formats
- io.read_at(0x401, dform, 4, actual);
+ std::tie(err, actual) = read_at(io, 0x401, dform, 4);
+ if (err || (4 != actual))
+ return -1;
LOG_FORMATS("adfs_n: map identifier (D format) %s %s\n", dform, (memcmp(dform, "Hugo", 4) != 0 && memcmp(dform, "Nick", 4) != 0) ? "invalid" : "");
- io.read_at(0x801, eform, 4, actual);
+ std::tie(err, actual) = read_at(io, 0x801, eform, 4);
+ if (err || (4 != actual))
+ return -1;
LOG_FORMATS("adfs_n: map identifier (E format) %s %s\n", eform, memcmp(eform, "Nick", 4) != 0 ? "invalid" : "");
uint64_t size;
@@ -585,12 +593,14 @@ int acorn_dos_format::find_size(util::random_read &io, uint32_t form_factor, con
if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
{
// read media type ID from FAT - Acorn DOS = 0xfd
- size_t actual;
uint8_t type;
- io.read_at(0, &type, 1, actual);
- LOG_FORMATS("dos: 800k media type id %02X %s\n", type, type != 0xfd ? "invalid" : "");
- if (type == 0xfd)
- return i;
+ auto const [err, actual] = read_at(io, 0, &type, 1);
+ if (!err && (1 == actual))
+ {
+ LOG_FORMATS("dos: 800k media type id %02X %s\n", type, type != 0xfd ? "invalid" : "");
+ if (type == 0xfd)
+ return i;
+ }
}
}
return -1;
@@ -647,14 +657,14 @@ bool opus_ddcpm_format::supports_save() const noexcept
int opus_ddcpm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- size_t actual;
uint8_t h[8];
-
- io.read_at(0, h, 8, actual);
+ auto const [err, actual] = read_at(io, 0, h, 8);
+ if (err || (8 != actual))
+ return 0;
uint64_t size;
if (io.length(size))
- return -1;
+ return 0;
if (size == 819200 && memcmp(h, "Slogger ", 8) == 0)
return FIFID_SIGN | FIFID_SIZE;
@@ -686,8 +696,7 @@ bool opus_ddcpm_format::load(util::random_read &io, uint32_t form_factor, const
desc_pc_sector sects[10];
uint8_t sectdata[10*512];
- size_t actual;
- io.read_at(head * 80 * spt * 512 + track * spt * 512, sectdata, spt * 512, actual);
+ /*auto const [err, actual] =*/ read_at(io, head * 80 * spt * 512 + track * spt * 512, sectdata, spt * 512); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
@@ -742,7 +751,7 @@ int cumana_dfs_format::find_size(util::random_read &io, uint32_t form_factor, co
if (io.length(size))
return -1;
- for (int i=0; formats[i].form_factor; i++)
+ for (int i = 0; formats[i].form_factor; i++)
{
const format &f = formats[i];
if (form_factor != floppy_image::FF_UNKNOWN && form_factor != f.form_factor)
@@ -750,9 +759,10 @@ int cumana_dfs_format::find_size(util::random_read &io, uint32_t form_factor, co
if (size == (uint64_t)compute_track_size(f) * f.track_count * f.head_count)
{
- size_t actual;
uint8_t info;
- io.read_at(14, &info, 1, actual);
+ auto const [err, actual] = read_at(io, 14, &info, 1);
+ if (err || (actual != 1))
+ return -1;
if (f.head_count == (util::BIT(info, 6) ? 2 : 1) && f.track_count == (util::BIT(info, 7) ? 80 : 40))
return i;
}
diff --git a/src/lib/formats/aim_dsk.cpp b/src/lib/formats/aim_dsk.cpp
index 88399204f37..c33cab8fb12 100644
--- a/src/lib/formats/aim_dsk.cpp
+++ b/src/lib/formats/aim_dsk.cpp
@@ -72,8 +72,8 @@ bool aim_format::load(util::random_read &io, uint32_t form_factor, const std::ve
bool header = false;
// Read track
- size_t actual;
- io.read_at((heads * track + head) * track_size, &track_data[0], track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (heads * track + head) * track_size, &track_data[0], track_size);
+ // FIXME: check for error and premature EOF
// Find first sector header or index mark
for (int offset = 0; offset < track_size; offset += 2)
diff --git a/src/lib/formats/all.cpp b/src/lib/formats/all.cpp
index 02f5b636cf5..bab86919cb7 100644
--- a/src/lib/formats/all.cpp
+++ b/src/lib/formats/all.cpp
@@ -320,6 +320,10 @@
#include "guab_dsk.h"
#endif
+#ifdef HAS_FORMATS_H17D_DSK
+#include "h17disk.h"
+#endif
+
#ifdef HAS_FORMATS_H8_CAS
#include "h8_cas.h"
#endif
@@ -576,6 +580,10 @@
#include "rx50_dsk.h"
#endif
+#ifdef HAS_FORMATS_SAP_DSK
+#include "sap_dsk.h"
+#endif
+
#ifdef HAS_FORMATS_SC3000_BIT
#include "sc3000_bit.h"
#endif
@@ -785,6 +793,7 @@ void mame_formats_full_list(mame_formats_enumerator &en)
en.add(fs::PRODOS);
#endif
#ifdef HAS_FORMATS_AP2_DSK
+ en.add(FLOPPY_A213S_FORMAT); // ap2_dsk.h
en.add(FLOPPY_A216S_DOS_FORMAT); // ap2_dsk.h
en.add(FLOPPY_A216S_PRODOS_FORMAT); // ap2_dsk.h
en.add(FLOPPY_RWTS18_FORMAT); // ap2_dsk.h
@@ -1339,6 +1348,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
en.add(FLOPPY_THOMSON_525_FORMAT); // thom_dsk.h
en.add(FLOPPY_THOMSON_35_FORMAT); // thom_dsk.h
#endif
+#ifdef HAS_FORMATS_SAP_DSK
+ en.add(FLOPPY_SAP_FORMAT);
+#endif
en.category("Texas Instruments");
#ifdef HAS_FORMATS_TI99_DSK
@@ -1510,7 +1522,7 @@ void mame_formats_full_list(mame_formats_enumerator &en)
en.add(vtech1_cassette_formats); // vt_cas.h
en.add(vtech2_cassette_formats); // vt_cas.h
#endif
-#ifdef HAS_FORMATS_VT_DSJ
+#ifdef HAS_FORMATS_VT_DSK
en.add(FLOPPY_VTECH_BIN_FORMAT); // vt_dsk.h
en.add(FLOPPY_VTECH_DSK_FORMAT); // vt_dsk.h
#endif
@@ -1522,4 +1534,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
#ifdef HAS_FORMATS_X07_CAS
en.add(x07_cassette_formats); // x07_cas.h
#endif
+
+ en.category("Heath");
+#ifdef HAS_FORMATS_H17D_DSK
+ en.add(FLOPPY_H17D_FORMAT); // h17disk.h
+#endif
}
diff --git a/src/lib/formats/ami_dsk.cpp b/src/lib/formats/ami_dsk.cpp
index 6ad9145c7d8..d4c567050c8 100644
--- a/src/lib/formats/ami_dsk.cpp
+++ b/src/lib/formats/ami_dsk.cpp
@@ -81,8 +81,9 @@ bool adf_format::load(util::random_read &io, uint32_t form_factor, const std::ve
image.set_variant(floppy_image::DSDD);
for (int track=0; track < tracks; track++) {
for (int side=0; side < 2; side++) {
- size_t actual;
- io.read_at((track*2 + side)*512*11, sectdata, 512*11, actual);
+ auto const [err, actual] = read_at(io, (track*2 + side)*512*11, sectdata, 512*11);
+ if (err || (512*11 != actual))
+ return false;
generate_track(amiga_11, track, side, sectors, 11, 100000, image);
}
}
@@ -90,8 +91,9 @@ bool adf_format::load(util::random_read &io, uint32_t form_factor, const std::ve
image.set_variant(floppy_image::DSHD);
for (int track=0; track < tracks; track++) {
for (int side=0; side < 2; side++) {
- size_t actual;
- io.read_at((track*2 + side)*512*22, sectdata, 512*22, actual);
+ auto const [err, actual] = read_at(io, (track*2 + side)*512*22, sectdata, 512*22);
+ if (err || (512*22 != actual))
+ return false;
generate_track(amiga_22, track, side, sectors, 22, 200000, image);
}
}
@@ -151,8 +153,8 @@ bool adf_format::save(util::random_read_write &io, const std::vector<uint32_t> &
*dest++ = val;
}
- size_t actual;
- io.write_at((track*2 + side) * data_track_size, sectdata, data_track_size, actual);
+ // FIXME: check for errors
+ /*auto const [err, actual] =*/ write_at(io, (track*2 + side) * data_track_size, sectdata, data_track_size);
}
}
}
diff --git a/src/lib/formats/ap2_dsk.cpp b/src/lib/formats/ap2_dsk.cpp
index 557800dcec2..1880ad7bd23 100644
--- a/src/lib/formats/ap2_dsk.cpp
+++ b/src/lib/formats/ap2_dsk.cpp
@@ -18,6 +18,128 @@
#include <cstdlib>
#include <cstring>
+static const uint8_t translate5[] = {
+ 0xab, 0xad, 0xae, 0xaf, 0xb5, 0xb6, 0xb7, 0xba,
+ 0xbb, 0xbd, 0xbe, 0xbf, 0xd6, 0xd7, 0xda, 0xdb,
+ 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xed, 0xee, 0xef,
+ 0xf5, 0xf6, 0xf7, 0xfa, 0xfb, 0xfd, 0xfe, 0xff,
+};
+
+a2_13sect_format::a2_13sect_format() : floppy_image_format_t()
+{
+}
+
+int a2_13sect_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint64_t size;
+ if (io.length(size))
+ return 0;
+
+ if (size != APPLE2_STD_TRACK_COUNT * 13 * APPLE2_SECTOR_SIZE)
+ return 0;
+
+ return FIFID_SIZE;
+}
+
+bool a2_13sect_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
+{
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
+ image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
+
+ int tracks = size / 13 / APPLE2_SECTOR_SIZE;
+
+ for(int track = 0; track < tracks; track++) {
+ std::vector<uint32_t> track_data;
+ uint8_t sector_data[APPLE2_SECTOR_SIZE * 13];
+
+ auto const [err, actual] = read_at(
+ io, track * sizeof sector_data, sector_data, sizeof sector_data);
+ if (err || actual != sizeof sector_data)
+ return false;
+
+ for(int i=0; i<13; i++) {
+ int sector = (i * 10) % 13;
+
+ // write inter-sector padding
+ for(int j=0; j<40; j++)
+ raw_w(track_data, 9, 0x1fe);
+ raw_w(track_data, 8, 0xff);
+
+ // write sector address
+ raw_w(track_data, 24, 0xd5aab5);
+ raw_w(track_data, 16, gcr4_encode(0xfe));
+ raw_w(track_data, 16, gcr4_encode(track));
+ raw_w(track_data, 16, gcr4_encode(sector));
+ raw_w(track_data, 16, gcr4_encode(0xfe ^ track ^ sector));
+ raw_w(track_data, 24, 0xdeaaeb);
+
+ // write intra-sector padding
+ for(int j=0; j<11; j++)
+ raw_w(track_data, 9, 0x1fe);
+
+ // write sector data
+ raw_w(track_data, 24, 0xd5aaad);
+
+ uint8_t pval = 0x00;
+ auto write_data_byte = [&track_data, &pval](uint8_t nval) {
+ raw_w(track_data, 8, translate5[nval ^ pval]);
+ pval = nval;
+ };
+
+ const uint8_t *sdata = sector_data + APPLE2_SECTOR_SIZE * sector;
+
+ // write 154 bytes encoding bits 2-0
+ write_data_byte(sdata[255] & 7);
+ for (int k=2; k>-1; k--)
+ for (int j=0; j<51; j++)
+ write_data_byte(
+ (sdata[j*5+k] & 7) << 2
+ | ((sdata[j*5+3] >> (2-k)) & 1) << 1
+ | ((sdata[j*5+4] >> (2-k)) & 1));
+
+ // write 256 bytes encoding bits 7-3
+ for (int k=0; k<5; k++)
+ for (int j=50; j>-1; j--)
+ write_data_byte(sdata[j*5+k] >> 3);
+ write_data_byte(sdata[255] >> 3);
+
+ raw_w(track_data, 8, translate5[pval]);
+ raw_w(track_data, 24, 0xdeaaeb);
+ raw_w(track_data, 8, 0xff);
+ }
+
+ generate_track_from_levels(track, 0, track_data, 0, image);
+ }
+
+ return true;
+}
+
+
+const char *a2_13sect_format::name() const noexcept
+{
+ return "a2_13sect";
+}
+
+const char *a2_13sect_format::description() const noexcept
+{
+ return "Apple II 13-sector d13 image";
+}
+
+const char *a2_13sect_format::extensions() const noexcept
+{
+ return "d13";
+}
+
+bool a2_13sect_format::supports_save() const noexcept
+{
+ return false;
+}
+
+const a2_13sect_format FLOPPY_A213S_FORMAT;
+
static const uint8_t translate6[0x40] =
{
0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, 0xa6,
@@ -96,16 +218,17 @@ int a2_16sect_format::identify(util::random_read &io, uint32_t form_factor, cons
if (io.length(size))
return 0;
- //uint32_t expected_size = 35 * 16 * 256;
- uint32_t expected_size = APPLE2_TRACK_COUNT * 16 * 256;
-
// check standard size plus some oddball sizes in our softlist
- if ((size != expected_size) && (size != 35 * 16 * 256) && (size != 143403) && (size != 143363) && (size != 143358))
+ if (
+ size != APPLE2_TRACK_COUNT * 16 * APPLE2_SECTOR_SIZE
+ && size != APPLE2_STD_TRACK_COUNT * 16 * APPLE2_SECTOR_SIZE
+ && size != 143403 && size != 143363 && size != 143358 && size != 143195
+ )
{
return 0;
}
- uint8_t sector_data[256*2];
+ uint8_t sector_data[APPLE2_SECTOR_SIZE*2];
static const unsigned char pascal_block1[4] = { 0x08, 0xa5, 0x0f, 0x29 };
static const unsigned char pascal2_block1[4] = { 0xff, 0xa2, 0x00, 0x8e };
static const unsigned char dos33_block1[4] = { 0xa2, 0x02, 0x8e, 0x52 };
@@ -114,8 +237,9 @@ int a2_16sect_format::identify(util::random_read &io, uint32_t form_factor, cons
static const unsigned char cpm22_block1[8] = { 0xa2, 0x55, 0xa9, 0x00, 0x9d, 0x00, 0x0d, 0xca };
static const unsigned char subnod_block1[8] = { 0x63, 0xaa, 0xf0, 0x76, 0x8d, 0x63, 0xaa, 0x8e };
- size_t actual;
- io.read_at(0, sector_data, 256*2, actual);
+ auto const [err, actual] = read_at(io, 0, sector_data, sizeof sector_data);
+ if (err || actual != sizeof sector_data)
+ return 0;
bool prodos_order = false;
// check ProDOS boot block
@@ -181,17 +305,20 @@ bool a2_16sect_format::load(util::random_read &io, uint32_t form_factor, const s
image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
- int tracks = (size == (40 * 16 * 256)) ? 40 : 35;
+ int tracks = (size == (APPLE2_TRACK_COUNT * 16 * APPLE2_SECTOR_SIZE)) ? APPLE2_TRACK_COUNT : APPLE2_STD_TRACK_COUNT;
int fpos = 0;
for(int track=0; track < tracks; track++) {
std::vector<uint32_t> track_data;
- uint8_t sector_data[256*16];
+ uint8_t sector_data[APPLE2_SECTOR_SIZE*16];
- size_t actual;
- io.read_at(fpos, sector_data, 256*16, actual);
+ auto const [err, actual] = read_at(io, fpos, sector_data, sizeof sector_data);
+ // Some supported images have oddball sizes, where the last track is incomplete.
+ // Skip the `actual` check to avoid rejecting them.
+ if (err /* || actual != sizeof sector_data */)
+ return false;
- fpos += 256*16;
+ fpos += APPLE2_SECTOR_SIZE*16;
for(int i=0; i<49; i++)
raw_w(track_data, 10, 0x3fc);
for(int i=0; i<16; i++) {
@@ -206,7 +333,7 @@ bool a2_16sect_format::load(util::random_read &io, uint32_t form_factor, const s
sector = dos_skewing[i];
}
- const uint8_t *sdata = sector_data + 256 * sector;
+ const uint8_t *sdata = sector_data + APPLE2_SECTOR_SIZE * sector;
for(int j=0; j<20; j++)
raw_w(track_data, 10, 0x3fc);
raw_w(track_data, 8, 0xff);
@@ -269,212 +396,215 @@ uint8_t a2_16sect_format::gb(const std::vector<bool> &buf, int &pos, int &wrap)
return v;
}
-//#define VERBOSE_SAVE
-
bool a2_16sect_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
- int g_tracks, g_heads;
- int visualgrid[16][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below
-
-// lenient addr check: if unset, only accept an addr mark if the checksum was good
-// if set, accept an addr mark if the track and sector values are both sane
-#undef LENIENT_ADDR_CHECK
-// if set, use the old, not as robust logic for choosing which copy of a decoded sector to write
-// to the resulting image if the sector has a bad checksum and/or postamble
-#undef USE_OLD_BEST_SECTOR_PRIORITY
-// nothing found
-#define NOTFOUND 0
-// address mark was found
-#define ADDRFOUND 1
-// address checksum is good
-#define ADDRGOOD 2
-// data mark was found (requires addrfound and sane values)
-#define DATAFOUND 4
-// data checksum is good
-#define DATAGOOD 8
-// data postamble is good
-#define DATAPOST 16
- for (auto & elem : visualgrid) {
- for (int j = 0; j < APPLE2_TRACK_COUNT; j++) {
- elem[j] = 0;
- }
+ int g_tracks, g_heads;
+ int visualgrid[16][APPLE2_TRACK_COUNT]; // visualizer grid, cleared/initialized below
+
+ constexpr bool VERBOSE_SAVE = false;
+
+ // if false, only accept an addr mark if the checksum was good
+ // if true, accept an addr mark if the track and sector values are both sane
+ constexpr bool LENIENT_ADDR_CHECK = false;
+
+ // if true, use the old, not as robust logic for choosing which copy of a decoded sector to write
+ // to the resulting image if the sector has a bad checksum and/or postamble
+ constexpr bool USE_OLD_BEST_SECTOR_PRIORITY = false;
+
+ // nothing found
+ constexpr int NOTFOUND = 0;
+ // address mark was found
+ constexpr int ADDRFOUND = 1;
+ // address checksum is good
+ constexpr int ADDRGOOD = 2;
+ // data mark was found (requires addrfound and sane values)
+ constexpr int DATAFOUND = 4;
+ // data checksum is good
+ constexpr int DATAGOOD = 8;
+ // data postamble is good
+ constexpr int DATAPOST = 16;
+
+ for (auto & elem : visualgrid) {
+ for (int j = 0; j < APPLE2_TRACK_COUNT; j++) {
+ elem[j] = NOTFOUND;
}
- image.get_actual_geometry(g_tracks, g_heads);
+ }
+ image.get_actual_geometry(g_tracks, g_heads);
- int head = 0;
+ int head = 0;
- int pos_data = 0;
+ int pos_data = 0;
- for(int track=0; track < g_tracks; track++) {
- uint8_t sectdata[(256)*16];
- memset(sectdata, 0, sizeof(sectdata));
- int nsect = 16;
- #ifdef VERBOSE_SAVE
- fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from track %d...", track);
- #endif
- auto buf = generate_bitstream_from_track(track, head, 3915, image);
- #ifdef VERBOSE_SAVE
- fprintf(stderr,"done.\n");
- #endif
- int pos = 0;
- int wrap = 0;
- int hb = 0;
- int dosver = 0; // apple dos version; 0 = >=3.3, 1 = <3.3
- for(;;) {
- uint8_t v = gb(buf, pos, wrap);
- if(v == 0xff) {
+ for(int track=0; track < g_tracks; track++) {
+ uint8_t sectdata[APPLE2_SECTOR_SIZE*16];
+ memset(sectdata, 0, sizeof(sectdata));
+ int nsect = 16;
+ if(VERBOSE_SAVE) {
+ fprintf(stderr,"DEBUG: a2_16sect_format::save() about to generate bitstream from track %d...", track);
+ }
+ auto buf = generate_bitstream_from_track(track, head, 3915, image);
+ if(VERBOSE_SAVE) {
+ fprintf(stderr,"done.\n");
+ }
+ int pos = 0;
+ int wrap = 0;
+ int hb = 0;
+ int dosver = 0; // apple dos version; 0 = >=3.3, 1 = <3.3
+ for(;;) {
+ uint8_t v = gb(buf, pos, wrap);
+ if(v == 0xff) {
+ hb = 1;
+ }
+ else if(hb == 1 && v == 0xd5){
+ hb = 2;
+ }
+ else if(hb == 2 && v == 0xaa) {
+ hb = 3;
+ }
+ else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec
+ hb = 4;
+ if (v == 0xab) dosver = 1;
+ }
+ else
+ hb = 0;
+
+ if(hb == 4) {
+ uint8_t h[11];
+ for(auto & elem : h)
+ elem = gb(buf, pos, wrap);
+ //uint8_t v2 = gcr6bw_tb[h[2]];
+ uint8_t vl = gcr4_decode(h[0],h[1]);
+ uint8_t tr = gcr4_decode(h[2],h[3]);
+ uint8_t se = gcr4_decode(h[4],h[5]);
+ uint8_t chk = gcr4_decode(h[6],h[7]);
+ if(VERBOSE_SAVE) {
+ uint32_t post = get_u24be(&h[8]);
+ printf("Address Mark:\tVolume %d, Track %d, Sector %2d, Checksum %02X: %s, Postamble %03X: %s\n",
+ vl, tr, se, chk, (chk ^ vl ^ tr ^ se)==0?"OK":"BAD", post, (post&0xFFFF00)==0xDEAA00?"OK":"BAD");
+ }
+ // sanity check
+ if (tr == track && se < nsect) {
+ visualgrid[se][track] |= ADDRFOUND;
+ visualgrid[se][track] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0;
+
+ if (visualgrid[se][track] & (LENIENT_ADDR_CHECK ? ADDRFOUND : ADDRGOOD)) {
+ int opos = pos;
+ int owrap = wrap;
+ hb = 0;
+ for(int i=0; i<20 && hb != 4; i++) {
+ v = gb(buf, pos, wrap);
+ if(v == 0xff)
hb = 1;
- }
- else if(hb == 1 && v == 0xd5){
+ else if(hb == 1 && v == 0xd5)
hb = 2;
- }
- else if(hb == 2 && v == 0xaa) {
+ else if(hb == 2 && v == 0xaa)
hb = 3;
- }
- else if(hb == 3 && ((v == 0x96) || (v == 0xab))) { // 0x96 = dos 3.3/16sec, 0xab = dos 3.21 and below/13sec
+ else if(hb == 3 && v == 0xad)
hb = 4;
- if (v == 0xab) dosver = 1;
- }
else
hb = 0;
+ }
+ if((hb == 4)&&(dosver == 0)) {
+ visualgrid[se][track] |= DATAFOUND;
+ uint8_t *dest;
+ uint8_t data[0x157];
+ uint32_t dpost = 0;
+ uint8_t c = 0;
+
+ if (m_prodos_order)
+ {
+ dest = sectdata+APPLE2_SECTOR_SIZE*prodos_skewing[se];
+ }
+ else
+ {
+ dest = sectdata+APPLE2_SECTOR_SIZE*dos_skewing[se];
+ }
- if(hb == 4) {
- uint8_t h[11];
- for(auto & elem : h)
- elem = gb(buf, pos, wrap);
- //uint8_t v2 = gcr6bw_tb[h[2]];
- uint8_t vl = gcr4_decode(h[0],h[1]);
- uint8_t tr = gcr4_decode(h[2],h[3]);
- uint8_t se = gcr4_decode(h[4],h[5]);
- uint8_t chk = gcr4_decode(h[6],h[7]);
- #ifdef VERBOSE_SAVE
- uint32_t post = get_u24be(&h[8]);
- printf("Address Mark:\tVolume %d, Track %d, Sector %2d, Checksum %02X: %s, Postamble %03X: %s\n", vl, tr, se, chk, (chk ^ vl ^ tr ^ se)==0?"OK":"BAD", post, (post&0xFFFF00)==0xDEAA00?"OK":"BAD");
- #endif
- // sanity check
- if (tr == track && se < nsect) {
- visualgrid[se][track] |= ADDRFOUND;
- visualgrid[se][track] |= ((chk ^ vl ^ tr ^ se)==0)?ADDRGOOD:0;
-#ifdef LENIENT_ADDR_CHECK
- if ((visualgrid[se][track] & ADDRFOUND) == ADDRFOUND) {
-#else
- if ((visualgrid[se][track] & ADDRGOOD) == ADDRGOOD) {
-#endif
- int opos = pos;
- int owrap = wrap;
- hb = 0;
- for(int i=0; i<20 && hb != 4; i++) {
- v = gb(buf, pos, wrap);
- if(v == 0xff)
- hb = 1;
- else if(hb == 1 && v == 0xd5)
- hb = 2;
- else if(hb == 2 && v == 0xaa)
- hb = 3;
- else if(hb == 3 && v == 0xad)
- hb = 4;
- else
- hb = 0;
- }
- if((hb == 4)&&(dosver == 0)) {
- visualgrid[se][track] |= DATAFOUND;
- uint8_t *dest;
- uint8_t data[0x157];
- uint32_t dpost = 0;
- uint8_t c = 0;
-
- if (m_prodos_order)
- {
- dest = sectdata+(256)*prodos_skewing[se];
- }
- else
- {
- dest = sectdata+(256)*dos_skewing[se];
- }
-
- // first read in sector and decode to 6bit form
- for(int i=0; i<0x156; i++) {
- data[i] = gcr6bw_tb[gb(buf, pos, wrap)] ^ c;
- c = data[i];
- // printf("%02x ", c);
- // if (((i&0xf)+1)==0x10) printf("\n");
- }
- // read the checksum byte
- data[0x156] = gcr6bw_tb[gb(buf,pos,wrap)];
- // now read the postamble bytes
- for(int i=0; i<3; i++) {
- dpost <<= 8;
- dpost |= gb(buf, pos, wrap);
- }
- // next combine in the upper 2 bits of each byte
- uint8_t bit_swap[4] = { 0, 2, 1, 3 };
- for(int i=0; i<0x56; i++)
- data[i+0x056] = data[i+0x056]<<2 | bit_swap[data[i]&3];
- for(int i=0; i<0x56; i++)
- data[i+0x0ac] = data[i+0x0ac]<<2 | bit_swap[(data[i]>>2)&3];
- for(int i=0; i<0x54; i++)
- data[i+0x102] = data[i+0x102]<<2 | bit_swap[(data[i]>>4)&3];
- // now decode it into 256 bytes
- // but only write it if the bitfield of the track shows datagood is NOT set.
- // if it is set we don't want to overwrite a guaranteed good read with a bad one
- // if past read had a bad checksum or bad postamble...
-#ifndef USE_OLD_BEST_SECTOR_PRIORITY
- if (((visualgrid[se][track]&DATAGOOD)==0)||((visualgrid[se][track]&DATAPOST)==0)) {
- // if the current read is good, and postamble is good, write it in, no matter what.
- // if the current read is good and the current postamble is bad, write it in unless the postamble was good before
- // if the current read is bad and the current postamble is good and the previous read had neither good, write it in
- // if the current read isn't good and neither is the postamble but nothing better
- // has been written before, write it anyway.
- if ( ((data[0x156] == c) && (dpost&0xFFFF00)==0xDEAA00) ||
- (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track]&DATAPOST)==0)) ||
- (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0)) ||
- (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0))
- ) {
- for(int i=0x56; i<0x156; i++) {
- uint8_t dv = data[i];
- *dest++ = dv;
- }
- }
- }
-#else
- if ((visualgrid[se][track]&DATAGOOD)==0) {
- for(int i=0x56; i<0x156; i++) {
- uint8_t dv = data[i];
- *dest++ = dv;
- }
- }
-#endif
- // do some checking
- #ifdef VERBOSE_SAVE
- if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00)
- fprintf(stderr,"Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n", data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD");
- #endif
- if (data[0x156] == c) visualgrid[se][track] |= DATAGOOD;
- if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track] |= DATAPOST;
- } else if ((hb == 4)&&(dosver == 1)) {
- fprintf(stderr,"ERROR: We don't handle dos sectors below 3.3 yet!\n");
- } else {
- pos = opos;
- wrap = owrap;
+ // first read in sector and decode to 6bit form
+ for(int i=0; i<0x156; i++) {
+ data[i] = gcr6bw_tb[gb(buf, pos, wrap)] ^ c;
+ c = data[i];
+ // printf("%02x ", c);
+ // if (((i&0xf)+1)==0x10) printf("\n");
+ }
+ // read the checksum byte
+ data[0x156] = gcr6bw_tb[gb(buf,pos,wrap)];
+ // now read the postamble bytes
+ for(int i=0; i<3; i++) {
+ dpost <<= 8;
+ dpost |= gb(buf, pos, wrap);
+ }
+ // next combine in the upper 2 bits of each byte
+ uint8_t bit_swap[4] = { 0, 2, 1, 3 };
+ for(int i=0; i<0x56; i++)
+ data[i+0x056] = data[i+0x056]<<2 | bit_swap[data[i]&3];
+ for(int i=0; i<0x56; i++)
+ data[i+0x0ac] = data[i+0x0ac]<<2 | bit_swap[(data[i]>>2)&3];
+ for(int i=0; i<0x54; i++)
+ data[i+0x102] = data[i+0x102]<<2 | bit_swap[(data[i]>>4)&3];
+ // now decode it into 256 bytes
+ // but only write it if the bitfield of the track shows datagood is NOT set.
+ // if it is set we don't want to overwrite a guaranteed good read with a bad one
+ // if past read had a bad checksum or bad postamble...
+ if(USE_OLD_BEST_SECTOR_PRIORITY) {
+ if ((visualgrid[se][track]&DATAGOOD)==0) {
+ for(int i=0x56; i<0x156; i++) {
+ uint8_t dv = data[i];
+ *dest++ = dv;
+ }
+ }
+ } else {
+ if (((visualgrid[se][track]&DATAGOOD)==0)||((visualgrid[se][track]&DATAPOST)==0)) {
+ // if the current read is good, and postamble is good, write it in, no matter what.
+ // if the current read is good and the current postamble is bad, write it in unless the postamble was good before
+ // if the current read is bad and the current postamble is good and the previous read had neither good, write it in
+ // if the current read isn't good and neither is the postamble but nothing better
+ // has been written before, write it anyway.
+ if ( ((data[0x156] == c) && (dpost&0xFFFF00)==0xDEAA00) ||
+ (((data[0x156] == c) && (dpost&0xFFFF00)!=0xDEAA00) && ((visualgrid[se][track]&DATAPOST)==0)) ||
+ (((data[0x156] != c) && (dpost&0xFFFF00)==0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0)) ||
+ (((data[0x156] != c) && (dpost&0xFFFF00)!=0xDEAA00) && (((visualgrid[se][track]&DATAGOOD)==0)&&(visualgrid[se][track]&DATAPOST)==0))
+ ) {
+ for(int i=0x56; i<0x156; i++) {
+ uint8_t dv = data[i];
+ *dest++ = dv;
}
}
}
- hb = 0;
+ }
+ // do some checking
+ if(VERBOSE_SAVE) {
+ if ((data[0x156] != c) || (dpost&0xFFFF00)!=0xDEAA00)
+ fprintf(stderr,"Data Mark:\tChecksum xpctd %d found %d: %s, Postamble %03X: %s\n",
+ data[0x156], c, (data[0x156]==c)?"OK":"BAD", dpost, (dpost&0xFFFF00)==0xDEAA00?"OK":"BAD");
+ }
+ if (data[0x156] == c) visualgrid[se][track] |= DATAGOOD;
+ if ((dpost&0xFFFF00)==0xDEAA00) visualgrid[se][track] |= DATAPOST;
+ } else if ((hb == 4)&&(dosver == 1)) {
+ fprintf(stderr,"ERROR: We don't handle dos sectors below 3.3 yet!\n");
+ } else {
+ pos = opos;
+ wrap = owrap;
}
- if(wrap)
- break;
+ }
}
- for(int i=0; i<nsect; i++) {
- //if(nsect>0) printf("t%d,", track);
- uint8_t const *const data = sectdata + (256)*i;
- size_t actual;
- io.write_at(pos_data, data, 256, actual);
- pos_data += 256;
- }
- //printf("\n");
+ hb = 0;
+ }
+ if(wrap)
+ break;
}
- // display a little table of which sectors decoded ok
- #ifdef VERBOSE_SAVE
+ for(int i=0; i<nsect; i++) {
+ //if(nsect>0) printf("t%d,", track);
+ uint8_t const *const data = sectdata + APPLE2_SECTOR_SIZE*i;
+ auto const [err, actual] = write_at(io, pos_data, data, APPLE2_SECTOR_SIZE);
+ if (err || actual != APPLE2_SECTOR_SIZE)
+ return false;
+ pos_data += APPLE2_SECTOR_SIZE;
+ }
+ //printf("\n");
+ }
+ // display a little table of which sectors decoded ok
+ if(VERBOSE_SAVE) {
int total_good = 0;
for (int j = 0; j < APPLE2_TRACK_COUNT; j++) {
printf("T%2d: ",j);
@@ -491,9 +621,9 @@ bool a2_16sect_format::save(util::random_read_write &io, const std::vector<uint3
printf("\n");
}
printf("Total Good Sectors: %d\n", total_good);
- #endif
+ }
- return true;
+ return true;
}
const a2_16sect_dos_format FLOPPY_A216S_DOS_FORMAT;
@@ -796,8 +926,7 @@ bool a2_rwts18_format::save(util::random_read_write &io, const std::vector<uint3
for(int i=0; i<nsect; i++) {
//if(nsect>0) printf("t%d,", track);
uint8_t const *const data = sectdata + (256)*i;
- size_t actual;
- io.write_at(pos_data, data, 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, pos_data, data, 256); // FIXME: check for errors
pos_data += 256;
}
@@ -978,8 +1107,7 @@ bool a2_rwts18_format::save(util::random_read_write &io, const std::vector<uint3
for(int i=0; i<nsect; i++) {
//if(nsect>0) printf("t%d,", track);
uint8_t const *const data = sectdata + (256)*i;
- size_t actual;
- io.write_at(pos_data, data, 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, pos_data, data, 256); // FIXME: check for errors
pos_data += 256;
}
//printf("\n");
@@ -1048,14 +1176,12 @@ bool a2_edd_format::load(util::random_read &io, uint32_t form_factor, const std:
{
uint8_t nibble[16384], stream[16384];
int npos[16384];
+ static const size_t img_size = 2'244'608;
- std::unique_ptr<uint8_t []> img(new (std::nothrow) uint8_t[2244608]);
- if (!img)
+ auto [err, img, actual] = read_at(io, 0, img_size);
+ if(err || actual != img_size)
return false;
- size_t actual;
- io.read_at(0, img.get(), 2244608, actual);
-
for(int i=0; i<137; i++) {
uint8_t const *const trk = &img[16384*i];
int pos = 0;
@@ -1286,16 +1412,18 @@ bool a2_nib_format::load(util::random_read &io, uint32_t form_factor, const std:
if (size != expected_size_35t && size != expected_size_40t)
return false;
- const auto nr_tracks = size == expected_size_35t? 35 : 40;
+ const auto nr_tracks = size / nibbles_per_track;
std::vector<uint8_t> nibbles(nibbles_per_track);
for (unsigned track = 0; track < nr_tracks; ++track) {
- size_t actual;
- io.read_at(track * nibbles_per_track, &nibbles[0], nibbles_per_track, actual);
+ auto const [err, actual] = read_at(io, track * nibbles_per_track, &nibbles[0], nibbles_per_track);
+ if (err || actual != nibbles_per_track)
+ return false;
+
auto levels = generate_levels_from_nibbles(nibbles);
- generate_track_from_levels(track, 0,
- levels,
- 0, image);
+ if (!levels.empty()) {
+ generate_track_from_levels(track, 0, levels, 0, image);
+ }
}
image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
diff --git a/src/lib/formats/ap2_dsk.h b/src/lib/formats/ap2_dsk.h
index cbeea73f2d3..33117ecbd84 100644
--- a/src/lib/formats/ap2_dsk.h
+++ b/src/lib/formats/ap2_dsk.h
@@ -21,14 +21,30 @@
***************************************************************************/
-#define APPLE2_NIBBLE_SIZE 416
-#define APPLE2_SMALL_NIBBLE_SIZE 374
-#define APPLE2_STD_TRACK_COUNT 35
-#define APPLE2_TRACK_COUNT 40
-#define APPLE2_SECTOR_COUNT 16
-#define APPLE2_SECTOR_SIZE 256
+constexpr int APPLE2_STD_TRACK_COUNT = 35;
+constexpr int APPLE2_TRACK_COUNT = 40;
+constexpr int APPLE2_SECTOR_SIZE = 256;
/**************************************************************************/
+class a2_13sect_format : public floppy_image_format_t
+{
+public:
+ a2_13sect_format();
+
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
+
+ virtual const char *name() const noexcept override;
+ virtual const char *description() const noexcept override;
+ virtual const char *extensions() const noexcept override;
+ virtual bool supports_save() const noexcept override;
+
+private:
+ static uint8_t gb(const std::vector<bool> &buf, int &pos, int &wrap);
+};
+
+extern const a2_13sect_format FLOPPY_A213S_FORMAT;
+
class a2_16sect_format : public floppy_image_format_t
{
public:
@@ -126,8 +142,8 @@ public:
private:
static constexpr size_t nibbles_per_track = 0x1a00;
static constexpr size_t min_sync_bytes = 4;
- static constexpr auto expected_size_35t = 35 * nibbles_per_track;
- static constexpr auto expected_size_40t = 40 * nibbles_per_track;
+ static constexpr auto expected_size_35t = APPLE2_STD_TRACK_COUNT * nibbles_per_track;
+ static constexpr auto expected_size_40t = APPLE2_TRACK_COUNT * nibbles_per_track;
static std::vector<uint32_t> generate_levels_from_nibbles(const std::vector<uint8_t>& nibbles);
};
diff --git a/src/lib/formats/ap_dsk35.cpp b/src/lib/formats/ap_dsk35.cpp
index b4a82e5ff56..4096215c35f 100644
--- a/src/lib/formats/ap_dsk35.cpp
+++ b/src/lib/formats/ap_dsk35.cpp
@@ -142,27 +142,26 @@ int dc42_format::identify(util::random_read &io, uint32_t form_factor, const std
return 0;
uint8_t h[0x54];
- size_t actual;
- io.read_at(0, h, 0x54, actual);
- uint32_t dsize = get_u32be(&h[0x40]);
- uint32_t tsize = get_u32be(&h[0x44]);
+ auto const [err, actual] = read_at(io, 0, h, 0x54);
+ if (err || (0x54 != actual))
+ return 0;
- uint8_t encoding = h[0x50];
- uint8_t format = h[0x51];
+ uint32_t const dsize = get_u32be(&h[0x40]);
+ uint32_t const tsize = get_u32be(&h[0x44]);
+
+ uint8_t const encoding = h[0x50];
+ uint8_t const format = h[0x51];
// if it's a 1.44MB DC42 image, reject it so the generic PC MFM handler picks it up
if ((encoding == 0x03) && (format == 0x02))
- {
return 0;
- }
return (size == 0x54+tsize+dsize && h[0] < 64 && h[0x52] == 1 && h[0x53] == 0) ? FIFID_STRUCT : 0;
}
bool dc42_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint8_t h[0x54];
- io.read_at(0, h, 0x54, actual);
+ read_at(io, 0, h, 0x54); // FIXME: check for errors and premature EOF
int dsize = get_u32be(&h[0x40]);
int tsize = get_u32be(&h[0x44]);
@@ -218,14 +217,14 @@ bool dc42_format::load(util::random_read &io, uint32_t form_factor, const std::v
sectors[si].sector = i;
sectors[si].info = format;
if(tsize) {
- io.read_at(pos_tag, data, 12, actual);
+ read_at(io, pos_tag, data, 12); // FIXME: check for errors and premature EOF
sectors[si].tag = data;
pos_tag += 12;
} else {
sectors[si].tag = nullptr;
}
sectors[si].data = data+12;
- io.read_at(pos_data, data+12, 512, actual);
+ read_at(io, pos_data, data+12, 512); // FIXME: check for errors and premature EOF
pos_data += 512;
si = (si + 2) % ns;
if(si == 0)
@@ -279,9 +278,8 @@ bool dc42_format::save(util::random_read_write &io, const std::vector<uint32_t>
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- size_t actual;
- io.write_at(pos_tag, &sdata[0], 12, actual);
- io.write_at(pos_data, &sdata[12], 512, actual);
+ write_at(io, pos_tag, &sdata[0], 12); // FIXME: check for errors
+ write_at(io, pos_data, &sdata[12], 512); // FIXME: check for errors
pos_tag += 12;
pos_data += 512;
if(track || head || i)
@@ -294,8 +292,7 @@ bool dc42_format::save(util::random_read_write &io, const std::vector<uint32_t>
put_u32be(&h[0x48], dchk);
put_u32be(&h[0x4c], tchk);
- size_t actual;
- io.write_at(0, h, 0x54, actual);
+ write_at(io, 0, h, 0x54); // FIXME: check for errors
return true;
}
@@ -340,14 +337,13 @@ int apple_gcr_format::identify(util::random_read &io, uint32_t form_factor, cons
bool apple_gcr_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
desc_gcr_sector sectors[12];
uint8_t sdata[512*12];
int pos_data = 0;
uint8_t header[64];
- io.read_at(0, header, 64, actual);
+ read_at(io, 0, header, 64); // FIXME: check for errors and premature EOF
uint64_t size;
if(io.length(size))
@@ -361,7 +357,7 @@ bool apple_gcr_format::load(util::random_read &io, uint32_t form_factor, const s
for(int track=0; track < 80; track++) {
for(int head=0; head < head_count; head++) {
int ns = 12 - (track/16);
- io.read_at(pos_data, sdata, 512*ns, actual);
+ read_at(io, pos_data, sdata, 512*ns); // FIXME: check for errors and premature EOF
pos_data += 512*ns;
int si = 0;
@@ -398,8 +394,7 @@ bool apple_gcr_format::save(util::random_read_write &io, const std::vector<uint3
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- size_t actual;
- io.write_at(pos_data, &sdata[12], 512, actual);
+ /*auto const [err, actual] =*/ write_at(io, pos_data, &sdata[12], 512); // FIXME: check for errors
pos_data += 512;
}
}
@@ -438,15 +433,19 @@ bool apple_2mg_format::supports_save() const noexcept
int apple_2mg_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t signature[4];
- size_t actual;
- io.read_at(0, signature, 4, actual);
- if (!strncmp(reinterpret_cast<char *>(signature), "2IMG", 4))
+ auto const [err, actual] = read_at(io, 0, signature, 4);
+ if (err || (4 != actual))
+ {
+ return 0;
+ }
+
+ if (!memcmp(signature, "2IMG", 4))
{
return FIFID_SIGN;
}
// Bernie ][ The Rescue wrote 2MGs with the signature byte-flipped, other fields are valid
- if (!strncmp(reinterpret_cast<char *>(signature), "GMI2", 4))
+ if (!memcmp(signature, "GMI2", 4))
{
return FIFID_SIGN;
}
@@ -456,10 +455,9 @@ int apple_2mg_format::identify(util::random_read &io, uint32_t form_factor, cons
bool apple_2mg_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
desc_gcr_sector sectors[12];
uint8_t sdata[512*12], header[64];
- io.read_at(0, header, 64, actual);
+ read_at(io, 0, header, 64); // FIXME: check for errors and premature EOF
uint32_t blocks = get_u32le(&header[0x14]);
uint32_t pos_data = get_u32le(&header[0x18]);
@@ -471,7 +469,7 @@ bool apple_2mg_format::load(util::random_read &io, uint32_t form_factor, const s
for(int track=0; track < 80; track++) {
for(int head=0; head < 2; head++) {
int ns = 12 - (track/16);
- io.read_at(pos_data, sdata, 512*ns, actual);
+ read_at(io, pos_data, sdata, 512*ns); // FIXME: check for errors and premature EOF
pos_data += 512*ns;
int si = 0;
@@ -494,8 +492,6 @@ bool apple_2mg_format::load(util::random_read &io, uint32_t form_factor, const s
bool apple_2mg_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
- size_t actual;
-
uint8_t header[0x40];
int pos_data = 0x40;
@@ -516,7 +512,7 @@ bool apple_2mg_format::save(util::random_read_write &io, const std::vector<uint3
header[0x18] = 0x40;
// bytes of disk data
header[0x1c] = 0x00; header[0x1d] = 0x80; header[0x1e] = 0x0c; // 0xC8000 (819200)
- io.write_at(0, header, 0x40, actual);
+ write_at(io, 0, header, 0x40); // FIXME: check for errors
for(int track=0; track < 80; track++) {
for(int head=0; head < 2; head++) {
@@ -524,7 +520,7 @@ bool apple_2mg_format::save(util::random_read_write &io, const std::vector<uint3
for(unsigned int i=0; i < sectors.size(); i++) {
auto &sdata = sectors[i];
sdata.resize(512+12);
- io.write_at(pos_data, &sdata[12], 512, actual);
+ write_at(io, pos_data, &sdata[12], 512); // FIXME: check for errors
pos_data += 512;
}
}
diff --git a/src/lib/formats/apd_dsk.cpp b/src/lib/formats/apd_dsk.cpp
index c1319e43cf4..55d722bdf38 100644
--- a/src/lib/formats/apd_dsk.cpp
+++ b/src/lib/formats/apd_dsk.cpp
@@ -101,8 +101,9 @@ int apd_format::identify(util::random_read &io, uint32_t form_factor, const std:
return 0;
std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [ioerr, actual] = read_at(io, 0, &img[0], size);
+ if (ioerr || (actual != size))
+ return 0;
int err;
std::vector<uint8_t> gz_ptr(8);
@@ -126,7 +127,7 @@ int apd_format::identify(util::random_read &io, uint32_t form_factor, const std:
err = inflateEnd(&d_stream);
if (err != Z_OK) return 0;
- img = gz_ptr;
+ img = std::move(gz_ptr);
}
if (!memcmp(&img[0], APD_HEADER, sizeof(APD_HEADER))) {
@@ -143,8 +144,9 @@ bool apd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return false;
std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [ioerr, actual] = read_at(io, 0, &img[0], size);
+ if (ioerr || (actual != size))
+ return false;
int err;
std::vector<uint8_t> gz_ptr;
diff --git a/src/lib/formats/apf_apt.cpp b/src/lib/formats/apf_apt.cpp
index dd1d119b010..9930d501652 100644
--- a/src/lib/formats/apf_apt.cpp
+++ b/src/lib/formats/apf_apt.cpp
@@ -152,12 +152,12 @@ static int apf_cpf_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int apf_apt_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int apf_apt_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return apf_apt_handle_cassette(buffer, bytes);
}
-static int apf_cpf_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int apf_cpf_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return apf_cpf_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/apridisk.cpp b/src/lib/formats/apridisk.cpp
index fafc12d9f3c..36ad6018336 100644
--- a/src/lib/formats/apridisk.cpp
+++ b/src/lib/formats/apridisk.cpp
@@ -38,8 +38,9 @@ const char *apridisk_format::extensions() const noexcept
int apridisk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[APR_HEADER_SIZE];
- size_t actual;
- io.read_at(0, header, APR_HEADER_SIZE, actual);
+ auto const [err, actual] = read_at(io, 0, header, APR_HEADER_SIZE);
+ if (err || (APR_HEADER_SIZE != actual))
+ return 0;
const char magic[] = "ACT Apricot disk image\x1a\x04";
@@ -64,11 +65,9 @@ bool apridisk_format::load(util::random_read &io, uint32_t form_factor, const st
while (file_offset < file_size)
{
- size_t actual;
-
// read sector header
uint8_t sector_header[16];
- io.read_at(file_offset, sector_header, 16, actual);
+ read_at(io, file_offset, sector_header, 16); // FIXME: check for errors and premature EOF
uint32_t type = get_u32le(&sector_header[0]);
uint16_t compression = get_u16le(&sector_header[4]);
@@ -103,7 +102,7 @@ bool apridisk_format::load(util::random_read &io, uint32_t form_factor, const st
case APR_COMPRESSED:
{
uint8_t comp[3];
- io.read_at(file_offset, comp, 3, actual);
+ read_at(io, file_offset, comp, 3); // FIXME: check for errors and premature EOF
uint16_t length = get_u16le(&comp[0]);
if (length != SECTOR_SIZE)
@@ -117,7 +116,7 @@ bool apridisk_format::load(util::random_read &io, uint32_t form_factor, const st
break;
case APR_UNCOMPRESSED:
- io.read_at(file_offset, data_ptr, SECTOR_SIZE, actual);
+ read_at(io, file_offset, data_ptr, SECTOR_SIZE); // FIXME: check for errors and premature EOF
break;
default:
diff --git a/src/lib/formats/as_dsk.cpp b/src/lib/formats/as_dsk.cpp
index 5c8a0545870..0fad7217585 100644
--- a/src/lib/formats/as_dsk.cpp
+++ b/src/lib/formats/as_dsk.cpp
@@ -4,55 +4,17 @@
// Applesauce solved output formats
#include "as_dsk.h"
+
#include "ioprocs.h"
+#include "multibyte.h"
#include <string.h>
-as_format::as_format() : floppy_image_format_t()
-{
-}
-uint32_t as_format::find_tag(const std::vector<uint8_t> &data, uint32_t tag)
-{
- uint32_t offset = 12;
- do {
- if(r32(data, offset) == tag)
- return offset + 8;
- offset += r32(data, offset+4) + 8;
- } while(offset < data.size() - 8);
- return 0;
-}
+namespace {
-uint32_t as_format::r32(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8) | (data[offset+2] << 16) | (data[offset+3] << 24);
-}
-
-uint16_t as_format::r16(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset] | (data[offset+1] << 8);
-}
-
-void as_format::w32(std::vector<uint8_t> &data, int offset, uint32_t value)
-{
- data[offset] = value;
- data[offset+1] = value >> 8;
- data[offset+2] = value >> 16;
- data[offset+3] = value >> 24;
-}
-
-void as_format::w16(std::vector<uint8_t> &data, int offset, uint16_t value)
-{
- data[offset] = value;
- data[offset+1] = value >> 8;
-}
-
-uint8_t as_format::r8(const std::vector<uint8_t> &data, uint32_t offset)
-{
- return data[offset];
-}
-
-uint32_t as_format::crc32r(const uint8_t *data, uint32_t size)
+template <typename T>
+uint32_t crc32r(T &&data, uint32_t size)
{
// Reversed crc32
uint32_t crc = 0xffffffff;
@@ -67,15 +29,35 @@ uint32_t as_format::crc32r(const uint8_t *data, uint32_t size)
return ~crc;
}
-bool as_format::load_bitstream_track(const std::vector<uint8_t> &img, floppy_image &image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant)
+template <typename T>
+uint32_t find_tag(T &&data, size_t size, uint32_t tag)
+{
+ uint32_t offset = 12;
+ do {
+ if(get_u32le(&data[offset]) == tag)
+ return offset + 8;
+ offset += get_u32le(&data[offset+4]) + 8;
+ } while(offset < (size - 8));
+ return 0;
+}
+
+} // anonymous namespace
+
+
+as_format::as_format() : floppy_image_format_t()
+{
+}
+
+
+bool as_format::load_bitstream_track(const uint8_t *img, floppy_image &image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant)
{
uint32_t trks_off = off_trks + (idx * 8);
- uint32_t track_size = r32(img, trks_off + 4);
+ uint32_t track_size = get_u32le(&img[trks_off + 4]);
if (track_size == 0)
return false;
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
+ uint32_t boff = (uint32_t)get_u16le(&img[trks_off + 0]) * 512;
// With 5.25 floppies the end-of-track may be missing
// if unformatted. Accept track length down to 95% of
@@ -92,15 +74,15 @@ bool as_format::load_bitstream_track(const std::vector<uint8_t> &img, floppy_ima
generate_track_from_bitstream(track, head, &img[boff], track_size, image, subtrack, 0xffff);
if(set_variant)
- image.set_variant(r32(img, trks_off + 4) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
+ image.set_variant(get_u32le(&img[trks_off + 4]) >= 90000 ? floppy_image::DSHD : floppy_image::DSDD);
return true;
}
-void as_format::load_flux_track(const std::vector<uint8_t> &img, floppy_image &image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks)
+void as_format::load_flux_track(const uint8_t *img, floppy_image &image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks)
{
uint32_t trks_off = off_trks + (fidx * 8);
- uint32_t boff = (uint32_t)r16(img, trks_off + 0) * 512;
- uint32_t track_size = r32(img, trks_off + 4);
+ uint32_t boff = (uint32_t)get_u16le(&img[trks_off + 0]) * 512;
+ uint32_t track_size = get_u32le(&img[trks_off + 4]);
uint32_t total_ticks = 0;
for(uint32_t i=0; i != track_size; i++)
@@ -239,13 +221,13 @@ bool as_format::test_flux(const std::vector<tdata> &tracks)
void as_format::save_tracks(std::vector<uint8_t> &data, const std::vector<tdata> &tracks, uint32_t total_blocks, bool has_flux)
{
- w32(data, 80, 0x50414D54); // TMAP
- w32(data, 84, 160); // size
+ put_u32le(&data[80], 0x50414d54); // TMAP
+ put_u32le(&data[84], 160); // size
uint32_t fstart = 1536 + total_blocks*512;
if(has_flux) {
- w32(data, fstart, 0x58554c46);
- w32(data, fstart+4, 160);
+ put_u32le(&data[fstart], 0x58554c46);
+ put_u32le(&data[fstart+4], 160);
fstart += 8;
}
@@ -264,8 +246,8 @@ void as_format::save_tracks(std::vector<uint8_t> &data, const std::vector<tdata>
}
}
- w32(data, 248, 0x534B5254); // TRKS
- w32(data, 252, 1280 + total_blocks*512); // size
+ put_u32le(&data[248], 0x534b5254); // TRKS
+ put_u32le(&data[252], 1280 + total_blocks*512); // size
uint8_t tid = 0;
uint16_t tb = 3;
@@ -274,14 +256,14 @@ void as_format::save_tracks(std::vector<uint8_t> &data, const std::vector<tdata>
int size = tracks[i].data.size();
int blocks = (size + 511) / 512;
memcpy(data.data() + tb*512, tracks[i].data.data(), size);
- w16(data, 256 + tid*8, tb);
- w16(data, 256 + tid*8 + 2, blocks);
- w32(data, 256 + tid*8 + 4, tracks[i].track_size);
+ put_u16le(&data[256 + tid*8], tb);
+ put_u16le(&data[256 + tid*8 + 2], blocks);
+ put_u32le(&data[256 + tid*8 + 4], tracks[i].track_size);
tb += blocks;
tid ++;
}
- w32(data, 8, crc32r(&data[12], data.size() - 12));
+ put_u32le(&data[8], crc32r(&data[12], data.size() - 12));
}
@@ -316,10 +298,10 @@ const uint8_t woz_format::signature2[8] = { 0x57, 0x4f, 0x5a, 0x32, 0xff, 0x0a,
int woz_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[8];
- size_t actual;
- io.read_at(0, header, 8, actual);
- if (!memcmp(header, signature, 8)) return FIFID_SIGN;
- if (!memcmp(header, signature2, 8)) return FIFID_SIGN;
+ auto const [err, actual] = read_at(io, 0, header, 8);
+ if(err || (8 != actual)) return 0;
+ if(!memcmp(header, signature, 8)) return FIFID_SIGN;
+ if(!memcmp(header, signature2, 8)) return FIFID_SIGN;
return 0;
}
@@ -328,9 +310,9 @@ bool woz_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t image_size;
if(io.length(image_size))
return false;
- std::vector<uint8_t> img(image_size);
- size_t actual;
- io.read_at(0, &img[0], img.size(), actual);
+ auto const [err, img, actual] = read_at(io, 0, image_size);
+ if(err || (actual != image_size))
+ return false;
// Check signature
if((memcmp(&img[0], signature, 8)) && (memcmp(&img[0], signature2, 8)))
@@ -340,29 +322,29 @@ bool woz_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(!memcmp(&img[0], signature2, 8)) woz_vers = 2;
// Check integrity
- uint32_t crc = crc32r(&img[12], img.size() - 12);
- if(crc != r32(img, 8))
+ uint32_t crc = crc32r(&img[12], image_size - 12);
+ if(crc != get_u32le(&img[8]))
return false;
- uint32_t off_info = find_tag(img, 0x4f464e49);
- uint32_t off_tmap = find_tag(img, 0x50414d54);
- uint32_t off_trks = find_tag(img, 0x534b5254);
-// uint32_t off_writ = find_tag(img, 0x54495257);
+ uint32_t off_info = find_tag(img, image_size, 0x4f464e49);
+ uint32_t off_tmap = find_tag(img, image_size, 0x50414d54);
+ uint32_t off_trks = find_tag(img, image_size, 0x534b5254);
+// uint32_t off_writ = find_tag(img, image_size, 0x54495257);
if(!off_info || !off_tmap || !off_trks)
return false;
- uint32_t info_vers = r8(img, off_info + 0);
+ uint32_t info_vers = img[off_info + 0];
if(info_vers < 1 || info_vers > 3)
return false;
- uint16_t off_flux = info_vers < 3 ? 0 : r16(img, off_info + 46);
- uint16_t flux_size = info_vers < 3 ? 0 : r16(img, off_info + 48);
+ uint16_t off_flux = (info_vers < 3) ? 0 : get_u16le(&img[off_info + 46]);
+ uint16_t flux_size = (info_vers < 3) ? 0 : get_u16le(&img[off_info + 48]);
if(!flux_size)
off_flux = 0;
- bool is_35 = r8(img, off_info + 1) == 2;
+ bool is_35 = img[off_info + 1] == 2;
if((form_factor == floppy_image::FF_35 && !is_35) || (form_factor == floppy_image::FF_525 && is_35))
return false;
@@ -374,36 +356,36 @@ bool woz_format::load(util::random_read &io, uint32_t form_factor, const std::ve
else
image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
- if (woz_vers == 1) {
+ if(woz_vers == 1) {
for (unsigned int trkid = 0; trkid != limit; trkid++) {
int head = is_35 && trkid >= 80 ? 1 : 0;
int track = is_35 ? trkid % 80 : trkid / 4;
int subtrack = is_35 ? 0 : trkid & 3;
- uint8_t idx = r8(img, off_tmap + trkid);
+ uint8_t idx = img[off_tmap + trkid];
if(idx != 0xff) {
uint32_t boff = off_trks + 6656*idx;
- if (r16(img, boff + 6648) == 0)
+ if (get_u16le(&img[boff + 6648]) == 0)
return false;
- generate_track_from_bitstream(track, head, &img[boff], r16(img, boff + 6648), image, subtrack, r16(img, boff + 6650));
+ generate_track_from_bitstream(track, head, &img[boff], get_u16le(&img[boff + 6648]), image, subtrack, get_u16le(&img[boff + 6650]));
if(is_35 && !track && head)
image.set_variant(floppy_image::DSDD);
}
}
- } else if (woz_vers == 2) {
+ } else if(woz_vers == 2) {
for (unsigned int trkid = 0; trkid != limit; trkid++) {
int head = is_35 && trkid & 1 ? 1 : 0;
int track = is_35 ? trkid >> 1 : trkid / 4;
int subtrack = is_35 ? 0 : trkid & 3;
- uint8_t idx = r8(img, off_tmap + trkid);
- uint8_t fidx = off_flux ? r8(img, off_flux*512 + 8 + trkid) : 0xff;
+ uint8_t idx = img[off_tmap + trkid];
+ uint8_t fidx = off_flux ? img[off_flux*512 + 8 + trkid] : 0xff;
- if(fidx != 0xff)
- load_flux_track(img, image, head, track, subtrack, fidx, off_trks);
+ if(fidx != 0xff) {
+ load_flux_track(&img[0], image, head, track, subtrack, fidx, off_trks);
- else if(idx != 0xff) {
- if(!load_bitstream_track(img, image, head, track, subtrack, idx, off_trks, !is_35, is_35 && !track && head))
+ } else if(idx != 0xff) {
+ if(!load_bitstream_track(&img[0], image, head, track, subtrack, idx, off_trks, !is_35, is_35 && !track && head))
return false;
}
}
@@ -445,31 +427,30 @@ bool woz_format::save(util::random_read_write &io, const std::vector<uint32_t> &
memcpy(&data[0], signature2, 8);
- w32(data, 12, 0x4F464E49); // INFO
- w32(data, 16, 60); // size
- data[20] = 3; // chunk version
+ put_u32le(&data[12], 0x4f464e49); // INFO
+ put_u32le(&data[16], 60); // size
+ data[20] = 3; // chunk version
data[21] = image.get_form_factor() == floppy_image::FF_525 ? 1 : 2;
- data[22] = 0; // not write protected
- data[23] = 1; // synchronized, since our internal format is
- data[24] = 1; // weak bits are generated, not stored
+ data[22] = 0; // not write protected
+ data[23] = 1; // synchronized, since our internal format is
+ data[24] = 1; // weak bits are generated, not stored
data[25] = 'M';
data[26] = 'A';
data[27] = 'M';
data[28] = 'E';
memset(&data[29], ' ', 32-4);
data[57] = twosided ? 2 : 1;
- data[58] = 0; // boot sector unknown
+ data[58] = 0; // boot sector unknown
data[59] = image.get_form_factor() == floppy_image::FF_525 ? 32 : image.get_variant() == floppy_image::DSHD ? 8 : 16;
- w16(data, 60, 0); // compatibility unknown
- w16(data, 62, 0); // needed ram unknown
- w16(data, 64, max_blocks);
- w16(data, 66, has_flux ? total_blocks+3 : 0);
- w16(data, 68, max_blocks);
+ put_u16le(&data[60], 0); // compatibility unknown
+ put_u16le(&data[62], 0); // needed RAM unknown
+ put_u16le(&data[64], max_blocks);
+ put_u16le(&data[66], has_flux ? total_blocks+3 : 0);
+ put_u16le(&data[68], max_blocks);
save_tracks(data, tracks, total_blocks, has_flux);
- size_t actual;
- io.write_at(0, data.data(), data.size(), actual);
+ /*auto const [err, actual] =*/ write_at(io, 0, data.data(), data.size()); // FIXME: check for errors
return true;
}
@@ -505,9 +486,9 @@ const uint8_t moof_format::signature[8] = { 0x4d, 0x4f, 0x4f, 0x46, 0xff, 0x0a,
int moof_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[8];
- size_t actual;
- io.read_at(0, header, 8, actual);
- if (!memcmp(header, signature, 8)) return FIFID_SIGN;
+ auto const [err, actual] = read_at(io, 0, header, 8);
+ if(err || (8 != actual)) return 0;
+ if(!memcmp(header, signature, 8)) return FIFID_SIGN;
return 0;
}
@@ -516,37 +497,37 @@ bool moof_format::load(util::random_read &io, uint32_t form_factor, const std::v
uint64_t image_size;
if(io.length(image_size))
return false;
- std::vector<uint8_t> img(image_size);
- size_t actual;
- io.read_at(0, &img[0], img.size(), actual);
+ auto const [err, img, actual] = read_at(io, 0, image_size);
+ if(err || (actual != image_size))
+ return false;
// Check signature
if(memcmp(&img[0], signature, 8))
return false;
// Check integrity
- uint32_t crc = crc32r(&img[12], img.size() - 12);
- if(crc != r32(img, 8))
+ uint32_t crc = crc32r(&img[12], image_size - 12);
+ if(crc != get_u32le(&img[8]))
return false;
- uint32_t off_info = find_tag(img, 0x4f464e49);
- uint32_t off_tmap = find_tag(img, 0x50414d54);
- uint32_t off_trks = find_tag(img, 0x534b5254);
+ uint32_t off_info = find_tag(img, image_size, 0x4f464e49);
+ uint32_t off_tmap = find_tag(img, image_size, 0x50414d54);
+ uint32_t off_trks = find_tag(img, image_size, 0x534b5254);
if(!off_info || !off_tmap || !off_trks)
return false;
- uint32_t info_vers = r8(img, off_info + 0);
+ uint32_t info_vers = img[off_info + 0];
if(info_vers != 1)
return false;
- uint16_t off_flux = r16(img, off_info + 40);
- uint16_t flux_size = r16(img, off_info + 42);
+ uint16_t off_flux = get_u16le(&img[off_info + 40]);
+ uint16_t flux_size = get_u16le(&img[off_info + 42]);
if(!flux_size)
off_flux = 0;
- switch(r8(img, off_info + 1)) {
+ switch(img[off_info + 1]) {
case 1:
image.set_form_variant(floppy_image::FF_35, floppy_image::SSDD);
break;
@@ -564,14 +545,14 @@ bool moof_format::load(util::random_read &io, uint32_t form_factor, const std::v
int head = trkid & 1;
int track = trkid >> 1;
- uint8_t idx = r8(img, off_tmap + trkid);
- uint8_t fidx = off_flux ? r8(img, off_flux*512 + 8 + trkid) : 0xff;
+ uint8_t idx = img[off_tmap + trkid];
+ uint8_t fidx = off_flux ? img[off_flux*512 + 8 + trkid] : 0xff;
- if(fidx != 0xff)
- load_flux_track(img, image, head, track, 0, fidx, off_trks);
+ if(fidx != 0xff) {
+ load_flux_track(&img[0], image, head, track, 0, fidx, off_trks);
- else if(idx != 0xff) {
- if(!load_bitstream_track(img, image, head, track, 0, idx, off_trks, false, false))
+ } else if(idx != 0xff) {
+ if(!load_bitstream_track(&img[0], image, head, track, 0, idx, off_trks, false, false))
return false;
}
}
@@ -606,27 +587,26 @@ bool moof_format::save(util::random_read_write &io, const std::vector<uint32_t>
memcpy(&data[0], signature, 8);
- w32(data, 12, 0x4F464E49); // INFO
- w32(data, 16, 60); // size
- data[20] = 1; // chunk version
+ put_u32le(&data[12], 0x4f464e49); // INFO
+ put_u32le(&data[16], 60); // size
+ data[20] = 1; // chunk version
data[21] = is_hd ? 3 : twosided ? 2 : 1; // variant
- data[22] = 0; // not write protected
- data[23] = 1; // synchronized, since our internal format is
- data[24] = is_hd ? 8 : 16; // optimal timing
+ data[22] = 0; // not write protected
+ data[23] = 1; // synchronized, since our internal format is
+ data[24] = is_hd ? 8 : 16; // optimal timing
data[25] = 'M';
data[26] = 'A';
data[27] = 'M';
data[28] = 'E';
memset(&data[29], ' ', 32-4);
- data[57] = 0; // pad
- w16(data, 58, max_blocks);
- w16(data, 60, has_flux ? total_blocks+3 : 0);
- w16(data, 62, max_blocks);
+ data[57] = 0; // pad
+ put_u16le(&data[58], max_blocks);
+ put_u16le(&data[60], has_flux ? total_blocks+3 : 0);
+ put_u16le(&data[62], max_blocks);
save_tracks(data, tracks, total_blocks, has_flux);
- size_t actual;
- io.write_at(0, data.data(), data.size(), actual);
+ /*auto const [err, actual] =*/ write_at(io, 0, data.data(), data.size()); // FIXME: check for errors
return true;
}
diff --git a/src/lib/formats/as_dsk.h b/src/lib/formats/as_dsk.h
index ec0a785d151..8871bc1ed11 100644
--- a/src/lib/formats/as_dsk.h
+++ b/src/lib/formats/as_dsk.h
@@ -23,16 +23,8 @@ protected:
bool flux = false;
};
- static uint32_t r32(const std::vector<uint8_t> &data, uint32_t offset);
- static uint16_t r16(const std::vector<uint8_t> &data, uint32_t offset);
- static uint8_t r8(const std::vector<uint8_t> &data, uint32_t offset);
- static void w32(std::vector<uint8_t> &data, int offset, uint32_t value);
- static void w16(std::vector<uint8_t> &data, int offset, uint16_t value);
- static uint32_t crc32r(const uint8_t *data, uint32_t size);
- static uint32_t find_tag(const std::vector<uint8_t> &data, uint32_t tag);
-
- static bool load_bitstream_track(const std::vector<uint8_t> &img, floppy_image &image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant);
- static void load_flux_track(const std::vector<uint8_t> &img, floppy_image &image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks);
+ static bool load_bitstream_track(const uint8_t *img, floppy_image &image, int head, int track, int subtrack, uint8_t idx, uint32_t off_trks, bool may_be_short, bool set_variant);
+ static void load_flux_track(const uint8_t *img, floppy_image &image, int head, int track, int subtrack, uint8_t fidx, uint32_t off_trks);
static tdata analyze_for_save(const floppy_image &image, int head, int track, int subtrack, int speed_zone);
static std::pair<int, int> count_blocks(const std::vector<tdata> &tracks);
diff --git a/src/lib/formats/bk0010_dsk.cpp b/src/lib/formats/bk0010_dsk.cpp
new file mode 100644
index 00000000000..8922b144fcd
--- /dev/null
+++ b/src/lib/formats/bk0010_dsk.cpp
@@ -0,0 +1,39 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/bk0010_dsk.cpp
+
+ Floppies used by BK (BY: device), DVK (MY: device) and UKNC
+ (MZ: device)
+
+*********************************************************************/
+
+#include "formats/bk0010_dsk.h"
+
+bk0010_format::bk0010_format() : wd177x_format(formats)
+{
+}
+
+// gap sizes taken from BKBTL emulator
+const bk0010_format::format bk0010_format::formats[] = {
+ {
+ floppy_image::FF_525, floppy_image::SSQD, floppy_image::MFM,
+ 2000, // 2us, 300rpm
+ 10, 80, 1,
+ 512, {},
+ 1, {},
+ 42, 22, 36
+ },
+ {
+ floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM,
+ 2000, // 2us, 300rpm
+ 10, 80, 2,
+ 512, {},
+ 1, {},
+ 42, 22, 36
+ },
+ {}
+};
+
+const bk0010_format FLOPPY_BK0010_FORMAT;
diff --git a/src/lib/formats/bk0010_dsk.h b/src/lib/formats/bk0010_dsk.h
new file mode 100644
index 00000000000..96b00ebede7
--- /dev/null
+++ b/src/lib/formats/bk0010_dsk.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:Sergey Svishchev
+/*********************************************************************
+
+ formats/bk0010_dsk.h
+
+*********************************************************************/
+#ifndef MAME_FORMATS_BK0010_DSK_H
+#define MAME_FORMATS_BK0010_DSK_H
+
+#pragma once
+
+#include "wd177x_dsk.h"
+
+class bk0010_format : public wd177x_format
+{
+public:
+ bk0010_format();
+
+ virtual const char *name() const noexcept override { return "bk0010"; }
+ virtual const char *description() const noexcept override { return "BK-0010 disk image"; }
+ virtual const char *extensions() const noexcept override { return "img,bkd"; }
+
+private:
+ static const format formats[];
+};
+
+extern const bk0010_format FLOPPY_BK0010_FORMAT;
+
+#endif // MAME_FORMATS_BK0010_DSK_H
diff --git a/src/lib/formats/camplynx_cas.cpp b/src/lib/formats/camplynx_cas.cpp
index a6151462911..545814b954f 100644
--- a/src/lib/formats/camplynx_cas.cpp
+++ b/src/lib/formats/camplynx_cas.cpp
@@ -179,7 +179,7 @@ static int camplynx_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int camplynx_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int camplynx_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return camplynx_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/cassimg.cpp b/src/lib/formats/cassimg.cpp
index 38be38db9b1..cea484f2735 100644
--- a/src/lib/formats/cassimg.cpp
+++ b/src/lib/formats/cassimg.cpp
@@ -366,8 +366,7 @@ void cassette_image::change(util::random_read_write::ptr &&io, const Format *for
void cassette_image::image_read(void *buffer, uint64_t offset, size_t length)
{
- size_t actual;
- m_io->read_at(offset, buffer, length, actual);
+ /*auto const [err, actual] =*/ read_at(*m_io, offset, buffer, length); // FIXME: check for errors and premature EOF
}
@@ -383,8 +382,7 @@ uint8_t cassette_image::image_read_byte(uint64_t offset)
void cassette_image::image_write(const void *buffer, uint64_t offset, size_t length)
{
- size_t actual;
- m_io->write_at(offset, buffer, length, actual);
+ /*auto const [err, actual] =*/ write_at(*m_io, offset, buffer, length); // FIXME: check for errors
}
@@ -793,8 +791,8 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
error err;
int length;
int sample_count;
- std::vector<uint8_t> bytes;
- std::vector<int16_t> samples;
+ std::unique_ptr<int16_t []> samples;
+ std::unique_ptr<uint8_t []> chunk;
int pos = 0;
uint64_t offset = 0;
@@ -803,7 +801,7 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
assert(legacy_args->trailer_samples >= 0);
assert(legacy_args->fill_wave);
- uint64_t size = image_size();
+ const uint64_t size = image_size();
/* normalize the args */
LegacyWaveFiller args = *legacy_args;
@@ -814,21 +812,24 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
if (args.sample_frequency == 0)
args.sample_frequency = 11025;
- /* allocate a buffer for the binary data */
- std::vector<uint8_t> chunk(args.chunk_size);
-
/* determine number of samples */
if (args.chunk_sample_calc != nullptr)
{
- if (size > 0x7FFFFFFF)
+ if (size > 0x7fffffff)
+ {
+ err = error::OUT_OF_MEMORY;
+ goto done;
+ }
+
+ std::unique_ptr<uint8_t []> bytes(new (std::nothrow) uint8_t [size]);
+ if (!bytes)
{
err = error::OUT_OF_MEMORY;
goto done;
}
- bytes.resize(size);
- image_read(&bytes[0], 0, size);
- sample_count = args.chunk_sample_calc(&bytes[0], (int)size);
+ image_read(bytes.get(), 0, size);
+ sample_count = args.chunk_sample_calc(bytes.get(), (int)size);
// chunk_sample_calc functions report errors by returning negative numbers
if (sample_count < 0)
@@ -848,12 +849,17 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
sample_count += args.header_samples + args.trailer_samples;
/* allocate a buffer for the completed samples */
- samples.resize(sample_count);
+ samples.reset(new (std::nothrow) int16_t [sample_count]);
+ if (!samples)
+ {
+ err = error::OUT_OF_MEMORY;
+ goto done;
+ }
/* if there has to be a header */
if (args.header_samples > 0)
{
- length = args.fill_wave(&samples[pos], sample_count - pos, CODE_HEADER);
+ length = args.fill_wave(&samples[pos], sample_count - pos, CODE_HEADER, -1);
if (length < 0)
{
err = error::INVALID_IMAGE;
@@ -863,12 +869,19 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
}
/* convert the file data to samples */
+ chunk.reset(new (std::nothrow) uint8_t [args.chunk_size]);
+ if (!chunk)
+ {
+ err = error::OUT_OF_MEMORY;
+ goto done;
+ }
while ((pos < sample_count) && (offset < size))
{
- image_read(&chunk[0], offset, args.chunk_size);
- offset += args.chunk_size;
+ const int slice = std::min<int>(args.chunk_size, size - offset);
+ image_read(chunk.get(), offset, slice);
+ offset += slice;
- length = args.fill_wave(&samples[pos], sample_count - pos, &chunk[0]);
+ length = args.fill_wave(&samples[pos], sample_count - pos, chunk.get(), slice);
if (length < 0)
{
err = error::INVALID_IMAGE;
@@ -878,11 +891,12 @@ cassette_image::error cassette_image::legacy_construct(const LegacyWaveFiller *l
if (length == 0)
break;
}
+ chunk.reset();
/* if there has to be a trailer */
if (args.trailer_samples > 0)
{
- length = args.fill_wave(&samples[pos], sample_count - pos, CODE_TRAILER);
+ length = args.fill_wave(&samples[pos], sample_count - pos, CODE_TRAILER, -1);
if (length < 0)
{
err = error::INVALID_IMAGE;
diff --git a/src/lib/formats/cassimg.h b/src/lib/formats/cassimg.h
index 9714e8e223b..9867ecbdf4a 100644
--- a/src/lib/formats/cassimg.h
+++ b/src/lib/formats/cassimg.h
@@ -120,7 +120,7 @@ public:
/* code to adapt existing legacy fill_wave functions */
struct LegacyWaveFiller
{
- int (*fill_wave)(int16_t *, int, uint8_t *) = nullptr;
+ int (*fill_wave)(int16_t *, int, const uint8_t *, int) = nullptr;
int chunk_size = 0;
int chunk_samples = 0;
int (*chunk_sample_calc)(const uint8_t *bytes, int length) = nullptr;
diff --git a/src/lib/formats/cbm_crt.cpp b/src/lib/formats/cbm_crt.cpp
index b088507208f..6bc9e0f8d23 100644
--- a/src/lib/formats/cbm_crt.cpp
+++ b/src/lib/formats/cbm_crt.cpp
@@ -46,6 +46,8 @@
#include "osdcore.h" // osd_printf_*
+#include <tuple>
+
//**************************************************************************
// MACROS/CONSTANTS
@@ -137,8 +139,7 @@ std::string cbm_crt_get_card(util::core_file &file)
{
// read the header
cbm_crt_header header;
- size_t actual;
- std::error_condition err = file.read(&header, CRT_HEADER_LENGTH, actual);
+ auto const [err, actual] = read(file, &header, CRT_HEADER_LENGTH);
if (!err && (CRT_HEADER_LENGTH == actual) && !memcmp(header.signature, CRT_SIGNATURE, 16))
{
@@ -157,11 +158,13 @@ std::string cbm_crt_get_card(util::core_file &file)
bool cbm_crt_read_header(util::core_file &file, size_t *roml_size, size_t *romh_size, int *exrom, int *game)
{
+ std::error_condition err;
size_t actual;
// read the header
cbm_crt_header header;
- if (file.read(&header, CRT_HEADER_LENGTH, actual))
+ std::tie(err, actual) = read(file, &header, CRT_HEADER_LENGTH);
+ if (err)
return false;
if ((CRT_HEADER_LENGTH != actual) || (memcmp(header.signature, CRT_SIGNATURE, 16) != 0))
@@ -184,7 +187,8 @@ bool cbm_crt_read_header(util::core_file &file, size_t *roml_size, size_t *romh_
while (!file.eof())
{
cbm_crt_chip chip;
- if (file.read(&chip, CRT_CHIP_LENGTH, actual) || (CRT_CHIP_LENGTH != actual))
+ std::tie(err, actual) = read(file, &chip, CRT_CHIP_LENGTH);
+ if (err || (CRT_CHIP_LENGTH != actual))
return false;
const uint16_t address = get_u16be(chip.start_address);
@@ -228,21 +232,22 @@ bool cbm_crt_read_data(util::core_file &file, uint8_t *roml, uint8_t *romh)
while (!file.eof())
{
+ std::error_condition err;
size_t actual;
cbm_crt_chip chip;
- if (file.read(&chip, CRT_CHIP_LENGTH, actual) || (CRT_CHIP_LENGTH != actual))
+ std::tie(err, actual) = read(file, &chip, CRT_CHIP_LENGTH);
+ if (err || (CRT_CHIP_LENGTH != actual))
return false;
const uint16_t address = get_u16be(chip.start_address);
const uint16_t size = get_u16be(chip.image_size);
- std::error_condition err;
switch (address)
{
- case 0x8000: err = file.read(roml + roml_offset, size, actual); roml_offset += size; break;
- case 0xa000: err = file.read(romh + romh_offset, size, actual); romh_offset += size; break;
- case 0xe000: err = file.read(romh + romh_offset, size, actual); romh_offset += size; break;
+ case 0x8000: std::tie(err, actual) = read(file, roml + roml_offset, size); roml_offset += size; break;
+ case 0xa000: std::tie(err, actual) = read(file, romh + romh_offset, size); romh_offset += size; break;
+ case 0xe000: std::tie(err, actual) = read(file, romh + romh_offset, size); romh_offset += size; break;
// FIXME: surely one needs to report an error or skip over the data if the load address is not recognised?
}
if (err) // TODO: check size - all bets are off if the address isn't recognised anyway
diff --git a/src/lib/formats/cbm_tap.cpp b/src/lib/formats/cbm_tap.cpp
index 743ad4282d2..65c265ac86f 100644
--- a/src/lib/formats/cbm_tap.cpp
+++ b/src/lib/formats/cbm_tap.cpp
@@ -330,7 +330,7 @@ static int cbm_tap_to_wav_size( const uint8_t *tapdata, int taplen )
return size;
}
-static int cbm_tap_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
+static int cbm_tap_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int )
{
int16_t *p = buffer;
diff --git a/src/lib/formats/ccvf_dsk.cpp b/src/lib/formats/ccvf_dsk.cpp
index 829be2a0019..d2c8da8e083 100644
--- a/src/lib/formats/ccvf_dsk.cpp
+++ b/src/lib/formats/ccvf_dsk.cpp
@@ -50,8 +50,10 @@ const ccvf_format::format ccvf_format::file_formats[] = {
int ccvf_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
char h[36];
- size_t actual;
- io.read_at(0, h, 36, actual);
+ auto const [err, actual] = read_at(io, 0, h, 36);
+ if (err || (36 != actual))
+ return 0;
+
if (!memcmp(h, "Compucolor Virtual Floppy Disk Image", 36))
return FIFID_SIGN;
@@ -96,9 +98,9 @@ bool ccvf_format::load(util::random_read &io, uint32_t form_factor, const std::v
if (io.length(size))
return false;
- std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto [err, img, actual] = read_at(io, 0, size);
+ if (err || (actual != size))
+ return false;
std::string ccvf = std::string((const char *)&img[0], size);
std::vector<uint8_t> bytes(78720);
diff --git a/src/lib/formats/cgen_cas.cpp b/src/lib/formats/cgen_cas.cpp
index c0737db635b..1ae1682cba9 100644
--- a/src/lib/formats/cgen_cas.cpp
+++ b/src/lib/formats/cgen_cas.cpp
@@ -108,7 +108,7 @@ static int cgenie_handle_cas(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int cgenie_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int cgenie_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return cgenie_handle_cas(buffer, bytes);
}
diff --git a/src/lib/formats/concept_dsk.cpp b/src/lib/formats/concept_dsk.cpp
index e026090e19f..52950b3e57d 100644
--- a/src/lib/formats/concept_dsk.cpp
+++ b/src/lib/formats/concept_dsk.cpp
@@ -114,8 +114,7 @@ bool cc525dsdd_format::load(util::random_read &io, uint32_t form_factor, const s
int track_size = sector_count*512;
for (int track=0; track < track_count; track++) {
for (int head=0; head < head_count; head++) {
- size_t actual;
- io.read_at((track*head_count + head) * track_size, sectdata, track_size, actual);
+ /*auto const [err, acutal] =*/ read_at(io, (track*head_count + head) * track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(cc_9_desc, track, head, sectors, sector_count, 100000, image);
}
}
@@ -146,8 +145,7 @@ bool cc525dsdd_format::save(util::random_read_write &io, const std::vector<uint3
for (int track=0; track < track_count; track++) {
for (int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- size_t actual;
- io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/coupedsk.cpp b/src/lib/formats/coupedsk.cpp
index 6e43aa9c301..a3edc5c7b40 100644
--- a/src/lib/formats/coupedsk.cpp
+++ b/src/lib/formats/coupedsk.cpp
@@ -94,8 +94,7 @@ bool mgt_format::load(util::random_read &io, uint32_t form_factor, const std::ve
int track_size = sector_count*512;
for(int head=0; head < 2; head++) {
for(int track=0; track < 80; track++) {
- size_t actual;
- io.read_at((track*2+head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*2+head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(desc_10, track, head, sectors, sector_count+1, 100000, image);
}
}
@@ -120,8 +119,7 @@ bool mgt_format::save(util::random_read_write &io, const std::vector<uint32_t> &
for(int head=0; head < 2; head++) {
for(int track=0; track < 80; track++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- size_t actual;
- io.write_at((track*2+head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*2+head)*track_size, sectdata, track_size); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/cp68_dsk.cpp b/src/lib/formats/cp68_dsk.cpp
index c6eb005f1c0..5872da350b6 100644
--- a/src/lib/formats/cp68_dsk.cpp
+++ b/src/lib/formats/cp68_dsk.cpp
@@ -51,6 +51,9 @@
#include "ioprocs.h"
+#include <tuple>
+
+
namespace
{
class cp68_formats : public wd177x_format
@@ -115,8 +118,8 @@ int cp68_format::find_size(util::random_read &io, uint32_t form_factor, const st
std::error_condition ec;
// Look at the boot sector.
- ec = io.read_at(128 * 0, &boot0, sizeof(boot0), actual);
- if (ec || actual == 0)
+ std::tie(ec, actual) = read_at(io, 128 * 0, &boot0, sizeof(boot0));
+ if (ec || actual == 0) // FIXME: what's the actual minimum size boot sector to probe?
return -1;
uint8_t boot0_sector_id = 1;
// uint8_t boot1_sector_id = 2;
@@ -125,8 +128,7 @@ int cp68_format::find_size(util::random_read &io, uint32_t form_factor, const st
// set the numbering of the first two sectors. If this is shown to not
// be practical in some common cases then a separate format variant
// might be needed.
- if (boot0[0] == 0xbd && boot0[3] == 0x86)
- {
+ if (boot0[0] == 0xbd && boot0[3] == 0x86) {
// Found a 6800 jsr and ldaa, looks like a CP68 6800 boot sector.
boot0_sector_id = 0;
}
@@ -135,8 +137,8 @@ int cp68_format::find_size(util::random_read &io, uint32_t form_factor, const st
const format &f = cp68_formats::formats[i];
// Look at the system information sector.
- ec = io.read_at(f.sector_base_size * 2, &info, sizeof(struct cp68_formats::sysinfo_sector_cp68), actual);
- if (ec || actual == 0)
+ std::tie(ec, actual) = read_at(io, f.sector_base_size * 2, &info, sizeof(struct cp68_formats::sysinfo_sector_cp68));
+ if (ec || actual == 0) // FIXME: what's the actual minimum sector size?
continue;
LOG_FORMATS("CP68 floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / f.sector_base_size, (uint32_t)size % f.sector_base_size, form_factor);
diff --git a/src/lib/formats/cqm_dsk.cpp b/src/lib/formats/cqm_dsk.cpp
index 47fa0fddfbe..850d223da7a 100644
--- a/src/lib/formats/cqm_dsk.cpp
+++ b/src/lib/formats/cqm_dsk.cpp
@@ -258,8 +258,9 @@ const char *cqm_format::extensions() const noexcept
int cqm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[3];
- size_t actual;
- io.read_at(0, h, 3, actual);
+ auto const [err, actual] = read_at(io, 0, h, 3);
+ if (err || (3 != actual))
+ return 0;
if (h[0] == 'C' && h[1] == 'Q' && h[2] == 0x14)
return FIFID_SIGN;
@@ -269,11 +270,10 @@ int cqm_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool cqm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
std::vector<uint8_t> imagebuf(max_size);
uint8_t header[CQM_HEADER_SIZE];
- io.read_at(0, header, CQM_HEADER_SIZE, actual);
+ read_at(io, 0, header, CQM_HEADER_SIZE); // FIXME: check for errors and premature EOF
int sector_size = get_u16le(&header[0x03]);
int sector_per_track = get_u16le(&header[0x10]);
@@ -317,8 +317,9 @@ bool cqm_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t cqm_size;
if (io.length(cqm_size))
return false;
- std::vector<uint8_t> cqmbuf(cqm_size);
- io.read_at(0, &cqmbuf[0], cqm_size, actual);
+ auto const [err, cqmbuf, actual] = read_at(io, 0, cqm_size);
+ if (err || (actual != cqm_size))
+ return false;
// decode the RLE data
for (int s = 0, pos = CQM_HEADER_SIZE + comment_size; pos < cqm_size; )
diff --git a/src/lib/formats/d64_dsk.cpp b/src/lib/formats/d64_dsk.cpp
index 56fec80c8c9..e1fb024e74d 100644
--- a/src/lib/formats/d64_dsk.cpp
+++ b/src/lib/formats/d64_dsk.cpp
@@ -127,8 +127,7 @@ int d64_format::get_disk_id_offset(const format &f) const
void d64_format::get_disk_id(const format &f, util::random_read &io, uint8_t &id1, uint8_t &id2) const
{
uint8_t id[2];
- size_t actual;
- io.read_at(get_disk_id_offset(f), id, 2, actual);
+ /*auto const [err, actual] =*/ read_at(io, get_disk_id_offset(f), id, 2); // FIXME: check for errors and premature EOF
id1 = id[0];
id2 = id[1];
}
@@ -238,8 +237,7 @@ bool d64_format::load(util::random_read &io, uint32_t form_factor, const std::ve
img.resize(size);
}
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, &img[0], size); // FIXME: check for errors and premature EOF
int track_offset = 0, error_offset = f.sector_count*f.sector_base_size;
@@ -294,8 +292,7 @@ bool d64_format::save(util::random_read_write &io, const std::vector<uint32_t> &
build_sector_description(f, sectdata, 0, 0, sectors, sector_count);
extract_sectors(image, f, sectors, track, head, sector_count);
- size_t actual;
- io.write_at(offset, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, offset, sectdata, track_size); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/d88_dsk.cpp b/src/lib/formats/d88_dsk.cpp
index e0482dadbf3..93a995a47fb 100644
--- a/src/lib/formats/d88_dsk.cpp
+++ b/src/lib/formats/d88_dsk.cpp
@@ -35,6 +35,8 @@
#include "ioprocs.h"
#include "multibyte.h"
+#include <tuple>
+
#define D88_HEADER_LEN 0x2b0
@@ -411,9 +413,11 @@ int d88_format::identify(util::random_read &io, uint32_t form_factor, const std:
return 0;
uint8_t h[32];
- size_t actual;
- io.read_at(0, h, 32, actual);
- if((little_endianize_int32(*(uint32_t *)(h+0x1c)) == size) &&
+ auto const [err, actual] = read_at(io, 0, h, 32);
+ if(err || (32 != actual))
+ return 0;
+
+ if(((get_u32le(h+0x1c) == size) || (get_u32le(h+0x1c) == (size >> 1))) &&
(h[0x1b] == 0x00 || h[0x1b] == 0x10 || h[0x1b] == 0x20 || h[0x1b] == 0x30 || h[0x1b] == 0x40))
return FIFID_SIZE|FIFID_STRUCT;
@@ -422,10 +426,13 @@ int d88_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
uint8_t h[32];
- io.read_at(0, h, 32, actual);
+ std::tie(err, actual) = read_at(io, 0, h, 32);
+ if(err || (32 != actual))
+ return false;
int cell_count = 0;
int track_count = 0;
@@ -470,8 +477,16 @@ bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(!head_count)
return false;
+ int img_tracks, img_heads;
+ image.get_maximal_geometry(img_tracks, img_heads);
+ if (track_count > img_tracks)
+ osd_printf_warning("d88: Floppy disk has too many tracks for this drive (floppy tracks=%d, drive tracks=%d).\n", track_count, img_tracks);
+
+ if (head_count > img_heads)
+ osd_printf_warning("d88: Floppy disk has excess of heads for this drive that will be discarded (floppy heads=%d, drive heads=%d).\n", head_count, img_heads);
+
uint32_t track_pos[164];
- io.read_at(32, track_pos, 164*4, actual);
+ std::tie(err, actual) = read_at(io, 32, track_pos, 164*4); // FIXME: check for errors and premature EOF
uint64_t file_size;
if(io.length(file_size))
@@ -493,7 +508,7 @@ bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return true;
uint8_t hs[16];
- io.read_at(pos, hs, 16, actual);
+ std::tie(err, actual) = read_at(io, pos, hs, 16); // FIXME: check for errors and premature EOF
pos += 16;
uint16_t size = little_endianize_int16(*(uint16_t *)(hs+14));
@@ -520,7 +535,7 @@ bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(size) {
sects[i].data = sect_data + sdatapos;
- io.read_at(pos, sects[i].data, size, actual);
+ std::tie(err, actual) = read_at(io, pos, sects[i].data, size); // FIXME: check for errors and premature EOF
pos += size;
sdatapos += size;
@@ -528,10 +543,12 @@ bool d88_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sects[i].data = nullptr;
}
- if(density == 0x40)
- build_pc_track_fm(track, head, image, cell_count / 2, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
- else
- build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
+ if(head < img_heads) {
+ if(density == 0x40)
+ build_pc_track_fm(track, head, image, cell_count / 2, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
+ else
+ build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
+ }
}
return true;
diff --git a/src/lib/formats/dcp_dsk.cpp b/src/lib/formats/dcp_dsk.cpp
index f7740a0ea29..dfc9eea27dc 100644
--- a/src/lib/formats/dcp_dsk.cpp
+++ b/src/lib/formats/dcp_dsk.cpp
@@ -54,8 +54,7 @@ int dcp_format::identify(util::random_read &io, uint32_t form_factor, const std:
int heads, tracks, spt, bps, count_tracks = 0;
bool is_hdb = false;
- size_t actual;
- io.read_at(0, h, 0xa2, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, h, 0xa2); // FIXME: check for errors and premature EOF
// First byte is the disk format (see below in load() for details)
switch (h[0])
@@ -119,12 +118,11 @@ int dcp_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint8_t h[0xa2];
int heads, tracks, spt, bps;
bool is_hdb = false;
- io.read_at(0, h, 0xa2, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, h, 0xa2); // FIXME: check for errors and premature EOF
// First byte is the disk format:
switch (h[0])
@@ -221,7 +219,7 @@ bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for (int track = 0; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- io.read_at(0xa2 + bps * spt * (track * heads + head), sect_data, bps * spt, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0xa2 + bps * spt * (track * heads + head), sect_data, bps * spt); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
@@ -241,7 +239,7 @@ bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::ve
else // FIXME: the code below is untested, because no image was found... there might be some silly mistake in the disk geometry!
{
// Read Head 0 Track 0 is FM with 26 sectors of 128bytes instead of 256
- io.read_at(0xa2, sect_data, 128 * spt, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0xa2, sect_data, 128 * spt); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
@@ -258,7 +256,7 @@ bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::ve
build_pc_track_fm(0, 0, image, cell_count, spt, sects, calc_default_pc_gap3_size(form_factor, 128));
// Read Head 1 Track 0 is MFM with 26 sectors of 256bytes
- io.read_at(0xa2 + 128 * spt, sect_data, bps * spt, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0xa2 + 128 * spt, sect_data, bps * spt); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
@@ -279,7 +277,7 @@ bool dcp_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for (int track = 1; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- io.read_at(data_offs + bps * spt * ((track - 1) * heads + head), sect_data, bps * spt, actual);
+ /*auto const [err, actual] =*/ read_at(io, data_offs + bps * spt * ((track - 1) * heads + head), sect_data, bps * spt); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
diff --git a/src/lib/formats/dfi_dsk.cpp b/src/lib/formats/dfi_dsk.cpp
index a0d216002bd..e2ea1fda0e3 100644
--- a/src/lib/formats/dfi_dsk.cpp
+++ b/src/lib/formats/dfi_dsk.cpp
@@ -18,6 +18,8 @@
#include "osdcore.h" // osd_printf_*
+#include <tuple>
+
#define NUMBER_OF_MULTIREADS 3
// thresholds for brickwall windowing
@@ -63,16 +65,23 @@ bool dfi_format::supports_save() const noexcept
int dfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
char sign[4];
- size_t actual;
- io.read_at(0, sign, 4, actual);
+ auto const [err, actual] = read_at(io, 0, sign, 4);
+ if(err || (4 != actual)) {
+ return 0;
+ }
return memcmp(sign, "DFE2", 4) ? 0 : FIFID_SIGN;
}
bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
+
char sign[4];
- io.read_at(0, sign, 4, actual);
+ std::tie(err, actual) = read_at(io, 0, sign, 4);
+ if(err || (4 != actual)) {
+ return false;
+ }
if(memcmp(sign, "DFER", 4) == 0) {
osd_printf_error("dfi_dsk: Old type Discferret image detected; the MAME Discferret decoder will not handle this properly, bailing out!\n");
return false;
@@ -89,7 +98,7 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
[[maybe_unused]] int rpm=360; // drive rpm
while(pos < size) {
uint8_t h[10];
- io.read_at(pos, h, 10, actual);
+ std::tie(err, actual) = read_at(io, pos, h, 10); // FIXME: check for errors and premature EOF
uint16_t track = get_u16be(&h[0]);
uint16_t head = get_u16be(&h[2]);
// Ignore sector
@@ -105,7 +114,7 @@ bool dfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
data.resize(tsize);
pos += 10; // skip the header, we already read it
- io.read_at(pos, &data[0], tsize, actual);
+ std::tie(err, actual) = read_at(io, pos, &data[0], tsize); // FIXME: check for errors and premature EOF
pos += tsize; // for next time we read, increment to the beginning of next header
int index_time = 0; // what point the last index happened
diff --git a/src/lib/formats/dim_dsk.cpp b/src/lib/formats/dim_dsk.cpp
index 52d3dfc1566..1f0902c2859 100644
--- a/src/lib/formats/dim_dsk.cpp
+++ b/src/lib/formats/dim_dsk.cpp
@@ -13,6 +13,8 @@
#include "ioprocs.h"
#include <cstring>
+#include <tuple>
+
dim_format::dim_format()
{
@@ -36,9 +38,9 @@ const char *dim_format::extensions() const noexcept
int dim_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[16];
-
- size_t actual;
- io.read_at(0xab, h, 16, actual);
+ auto const [err, actual] = read_at(io, 0xab, h, 16);
+ if(err || (16 != actual))
+ return 0;
if(strncmp((const char *)h, "DIFC HEADER", 11) == 0)
return FIFID_SIGN;
@@ -48,13 +50,16 @@ int dim_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool dim_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
int offset = 0x100;
uint8_t h;
uint8_t track_total = 77;
int cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
- io.read_at(0, &h, 1, actual);
+ std::tie(err, actual) = read_at(io, 0, &h, 1);
+ if (err || (1 != actual))
+ return false;
int spt, gap3, bps, size;
switch(h) {
@@ -114,7 +119,7 @@ bool dim_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sects[i].deleted = false;
sects[i].bad_crc = false;
sects[i].data = &sect_data[sdatapos];
- io.read_at(offset, sects[i].data, bps, actual);
+ std::tie(err, actual) = read_at(io, offset, sects[i].data, bps); // FIXME: check for errors and premature EOF
offset += bps;
sdatapos += bps;
}
diff --git a/src/lib/formats/dip_dsk.cpp b/src/lib/formats/dip_dsk.cpp
index ecbd12bde1e..3ef8261d1da 100644
--- a/src/lib/formats/dip_dsk.cpp
+++ b/src/lib/formats/dip_dsk.cpp
@@ -72,8 +72,7 @@ bool dip_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for (int track = 0; track < tracks; track++)
for (int head = 0; head < heads; head++)
{
- size_t actual;
- io.read_at(0x100 + bps * spt * (track * heads + head), sect_data, bps * spt, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0x100 + bps * spt * (track * heads + head), sect_data, bps * spt); // FIXME: check for errors and premature EOF
for (int i = 0; i < spt; i++)
{
diff --git a/src/lib/formats/dmk_dsk.cpp b/src/lib/formats/dmk_dsk.cpp
index 68257ff1f2b..d02401b56cf 100644
--- a/src/lib/formats/dmk_dsk.cpp
+++ b/src/lib/formats/dmk_dsk.cpp
@@ -8,7 +8,7 @@
TODO:
- Add write/format support.
-- Check support on other drivers besides msx.
+- Check support on other drivers besides MSX.
*********************************************************************/
@@ -18,14 +18,18 @@ TODO:
#include "ioprocs.h"
#include "multibyte.h"
+#include <tuple>
+
namespace {
+constexpr int HEADER_SIZE = 16;
+
uint32_t wide_fm(uint16_t val)
{
uint32_t res = 0;
for (int i = 15; i >= 0; i--) {
- res |= (util::BIT(val, i) << (i*2 + 1));
+ res |= (util::BIT(val, i) << (i * 2 + 1));
}
return res;
}
@@ -34,7 +38,7 @@ uint32_t data_to_wide_fm(uint8_t val)
{
uint16_t res = 0xaaaa; // clock
for (int i = 7; i >= 0; i--) {
- res |= (util::BIT(val, i) << i*2); // data
+ res |= (util::BIT(val, i) << i * 2); // data
}
return wide_fm(res);
}
@@ -72,14 +76,17 @@ int dmk_format::identify(util::random_read &io, uint32_t form_factor, const std:
if (io.length(size))
return 0;
- const int header_size = 16;
- uint8_t header[header_size];
+ std::error_condition err;
size_t actual;
- io.read_at(0, header, header_size, actual);
- int tracks = header[1];
- int track_size = get_u16le(&header[2]);
- int heads = (header[4] & 0x10) ? 1 : 2;
+ uint8_t header[HEADER_SIZE];
+ std::tie(err, actual) = read_at(io, 0, header, HEADER_SIZE);
+ if (err || (HEADER_SIZE != actual))
+ return 0;
+
+ const int tracks_from_header = header[1];
+ const int track_size = get_u16le(&header[2]);
+ const int heads = util::BIT(header[4], 4) ? 1 : 2;
// The first header byte must be 00 or FF
if (header[0] != 0x00 && header[0] != 0xff)
@@ -87,66 +94,73 @@ int dmk_format::identify(util::random_read &io, uint32_t form_factor, const std:
return 0;
}
- // Bytes C-F must be zero
- if (header[0x0c] != 0 || header[0xd] != 0 || header[0xe] != 0 || header[0xf] != 0)
+ // Verify reserved/unsupported header bytes
+ for (int i = 5; i < 0x10; i++)
{
- return 0;
+ if (header[i] != 0x00)
+ return 0;
}
// Check track size within limits
- if (track_size < 0x80 || track_size > 0x3FFF )
- {
+ if (track_size < 0x80 || track_size > 0x3fff)
return 0;
- }
- if (size == header_size + heads * tracks * track_size)
+ const int tracks_in_file = (size - HEADER_SIZE) / (heads * track_size);
+ for (int track = 0; track < tracks_in_file; track++)
{
- return FIFID_STRUCT|FIFID_SIZE;
- }
+ for (int head = 0; head < heads; head++)
+ {
+ // Read track
+ std::vector<uint8_t> track_data(track_size);
+ std::tie(err, actual) = read_at(io, HEADER_SIZE + (heads * track + head) * track_size, &track_data[0], track_size);
+ if (err || track_size != actual)
+ return 0;
- return 0;
+ // Verify idam entries
+ for (int idam_index = 0; idam_index < 64; idam_index++)
+ {
+ const uint16_t idam_entry = get_u16le(&track_data[2 * idam_index]);
+ if (idam_entry == 0x0000)
+ continue;
+ const uint16_t idam_offset = idam_entry & 0x3fff;
+ if (idam_offset >= track_size)
+ return 0;
+ if (track_data[idam_offset] != 0xfe)
+ return 0;
+ }
+ }
+ }
+ if (size == HEADER_SIZE + heads * tracks_from_header * track_size)
+ return FIFID_HINT|FIFID_SIZE;
+ else
+ return FIFID_HINT;
}
bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
- const int header_size = 16;
- uint8_t header[header_size];
- io.read_at(0, header, header_size, actual);
+ uint64_t size;
+ if (io.length(size))
+ return false;
+
+ uint8_t header[HEADER_SIZE];
+ std::tie(err, actual) = read_at(io, 0, header, HEADER_SIZE);
+ if (err || (HEADER_SIZE != actual))
+ return false;
- const int tracks = header[1];
const int track_size = get_u16le(&header[2]);
- const int heads = (header[4] & 0x10) ? 1 : 2;
- const bool is_sd = (header[4] & 0x40) ? true : false;
+ const int heads = util::BIT(header[4], 4) ? 1 : 2;
+ const bool is_sd = util::BIT(header[4], 6);
+ const int tracks = (size - HEADER_SIZE) / (heads * track_size);
- auto variant = floppy_image::SSDD;
- if (is_sd)
- {
- if (heads == 2)
- {
- variant = floppy_image::DSSD;
- }
- else
- {
- variant = floppy_image::SSSD;
- }
- }
- else
- {
- if (heads == 2)
- {
- variant = floppy_image::DSDD;
- }
- else
- {
- variant = floppy_image::SSDD;
- }
- }
+ const auto variant = is_sd ? (heads == 2 ? floppy_image::DSSD : floppy_image::SSSD)
+ : (heads == 2 ? floppy_image::DSDD : floppy_image::SSDD);
image.set_variant(variant);
- int fm_stride = is_sd ? 1 : 2;
+ const int fm_stride = is_sd ? 1 : 2;
for (int track = 0; track < tracks; track++)
{
@@ -155,15 +169,17 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
int fm_loss = 0;
std::vector<uint8_t> track_data(track_size);
std::vector<uint32_t> raw_track_data;
- int mark_location[64*2+1];
- uint8_t mark_value[64*2+1];
- bool mark_is_mfm[64*2+1];
+ int mark_location[64 * 2 + 1];
+ uint8_t mark_value[64 * 2 + 1];
+ bool mark_is_mfm[64 * 2 + 1];
int iam_location = -1;
// Read track
- io.read_at(header_size + (heads * track + head) * track_size, &track_data[0], track_size, actual);
+ std::tie(err, actual) = read_at(io, HEADER_SIZE + (heads * track + head) * track_size, &track_data[0], track_size);
+ if (err || track_size != actual)
+ return false;
- for (int i = 0; i < 64*2+1; i++)
+ for (int i = 0; i < 64 * 2 + 1; i++)
{
mark_location[i] = -1;
mark_value[i] = 0xfe;
@@ -174,10 +190,10 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
// Find IDAM/DAM locations
uint16_t track_header_offset = 0;
uint16_t track_offset = get_u16le(&track_data[track_header_offset]) & 0x3fff;
- bool idam_is_mfm = (track_data[track_header_offset + 1] & 0x80) ? true : false;
+ bool idam_is_mfm = util::BIT(track_data[track_header_offset + 1], 7);
track_header_offset += 2;
- while ( track_offset != 0 && track_offset >= 0x83 && track_offset < track_size && track_header_offset < 0x80 )
+ while (track_offset != 0 && track_offset >= 0x83 && track_offset < track_size && track_header_offset < 0x80)
{
// Assume 3 bytes before IDAM pointers are the start of IDAM indicators
int mark_offset = idam_is_mfm ? 3 : 0;
@@ -188,11 +204,11 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
int stride = idam_is_mfm ? 1 : fm_stride;
// Scan for DAM location
- for (int i = track_offset + 10*stride; i < track_offset + 53*stride; i++)
+ for (int i = track_offset + 10 * stride; i < track_offset + 53 * stride; i++)
{
if ((track_data[i] >= 0xf8 && track_data[i] <= 0xfb))
{
- if (!idam_is_mfm || (track_data[i-1] == 0xa1 && track_data[i-2] == 0xa1))
+ if (!idam_is_mfm || get_u16le(&track_data[i - 2]) == 0xa1a1)
{
mark_location[mark_count] = i - mark_offset;
mark_value[mark_count] = track_data[i];
@@ -204,7 +220,7 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
}
}
- idam_is_mfm = (track_data[track_header_offset + 1] & 0x80) ? true : false;
+ idam_is_mfm = util::BIT(track_data[track_header_offset + 1], 7);
track_offset = get_u16le(&track_data[track_header_offset]) & 0x3fff;
track_header_offset += 2;
}
@@ -216,10 +232,10 @@ bool dmk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
}
// Find IAM location
- for(int i = mark_location[0] - 1; i >= 3; i--)
+ for (int i = mark_location[0] - 1; i >= 3; i--)
{
// It's usually 3 bytes but several dumped tracks seem to contain only 2 bytes
- if (track_data[i] == 0xfc && (is_sd || (track_data[i-1] == 0xc2 && track_data[i-2] == 0xc2)))
+ if (track_data[i] == 0xfc && (is_sd || get_u16le(&track_data[i - 2]) == 0xc2c2))
{
iam_location = i - (is_sd ? 0 : 3);
break;
diff --git a/src/lib/formats/ds9_dsk.cpp b/src/lib/formats/ds9_dsk.cpp
index 396a6ae3235..c0cbf0dccbc 100644
--- a/src/lib/formats/ds9_dsk.cpp
+++ b/src/lib/formats/ds9_dsk.cpp
@@ -109,8 +109,7 @@ bool ds9_format::load(util::random_read &io, uint32_t form_factor, const std::ve
{
for (int head = 0; head < head_count; head++)
{
- size_t actual;
- io.read_at((track * head_count + head) * track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track * head_count + head) * track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(ds9_desc, track, head, sectors, sector_count, 104000, image);
}
}
diff --git a/src/lib/formats/dsk_dsk.cpp b/src/lib/formats/dsk_dsk.cpp
index adfbe7735ed..e10e94f80be 100644
--- a/src/lib/formats/dsk_dsk.cpp
+++ b/src/lib/formats/dsk_dsk.cpp
@@ -311,13 +311,14 @@ bool dsk_format::supports_save() const noexcept
int dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[16];
-
- size_t actual;
- io.read_at(0, &header, sizeof(header), actual);
- if ( memcmp( header, DSK_FORMAT_HEADER, 8 ) ==0) {
+ auto const [err, actual] = read_at(io, 0, &header, sizeof(header));
+ if (err) {
+ return 0;
+ }
+ if ((8 <= actual) && !memcmp(header, DSK_FORMAT_HEADER, 8)) {
return FIFID_SIGN;
}
- if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) {
+ if ((16 <= actual) && !memcmp(header, EXT_FORMAT_HEADER, 16)) {
return FIFID_SIGN;
}
return 0;
@@ -356,8 +357,6 @@ struct sector_header
bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
-
uint8_t header[0x100];
bool extendformat = false;
@@ -365,7 +364,7 @@ bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if (io.length(image_size))
return false;
- io.read_at(0, &header, sizeof(header), actual);
+ read_at(io, 0, &header, sizeof(header)); // FIXME: check for errors and premature EOF
if ( memcmp( header, EXT_FORMAT_HEADER, 16 ) ==0) {
extendformat = true;
}
@@ -431,7 +430,7 @@ bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(track_offsets[(track<<1)+side] >= image_size)
continue;
track_header tr;
- io.read_at(track_offsets[(track<<1)+side], &tr, sizeof(tr), actual);
+ read_at(io, track_offsets[(track<<1)+side], &tr, sizeof(tr)); // FIXME: check for errors and premature EOF
// skip if there are no sectors in this track
if (tr.number_of_sector == 0)
@@ -441,7 +440,7 @@ bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
int first_sector_code = -1;
for(int j=0;j<tr.number_of_sector;j++) {
sector_header sector;
- io.read_at(track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector), actual);
+ read_at(io, track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector)); // FIXME: check for errors and premature EOF
if (j == 0)
first_sector_code = sector.sector_size_code;
@@ -460,7 +459,7 @@ bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for(int j=0;j<tr.number_of_sector;j++) {
sector_header sector;
- io.read_at(track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector), actual);
+ read_at(io, track_offsets[(track<<1)+side]+sizeof(tr)+(sizeof(sector)*j), &sector, sizeof(sector)); // FIXME: check for errors and premature EOF
sects[j].track = sector.track;
sects[j].head = sector.side;
@@ -483,7 +482,7 @@ bool dsk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if(!(sector.fdc_status_reg1 & 0x04)) {
sects[j].data = sect_data + sdatapos;
- io.read_at(pos, sects[j].data, sects[j].actual_size, actual);
+ read_at(io, pos, sects[j].data, sects[j].actual_size); // FIXME: check for errors and premature EOF
sdatapos += sects[j].actual_size;
} else
diff --git a/src/lib/formats/dvk_mx_dsk.cpp b/src/lib/formats/dvk_mx_dsk.cpp
index 981bed010e7..c384dc38e00 100644
--- a/src/lib/formats/dvk_mx_dsk.cpp
+++ b/src/lib/formats/dvk_mx_dsk.cpp
@@ -23,65 +23,45 @@
#include "ioprocs.h"
#include "multibyte.h"
+constexpr uint32_t ID_PATTERN = 0xaaaaffaf;
const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_new_desc[] = {
/* 01 */ { FM, 0x00, 8*2 }, // eight 0x0000 words
- /* 03 */ { FM, 0x00, 1 },
- /* 02 */ { FM, 0xf3, 1 }, // word 0x00f3
- /* 05 */ { FM, 0x00, 1 },
- /* 04 */ { TRACK_ID_FM }, // track number word
- /* 05 */ { SECTOR_LOOP_START, 0, 10 }, // 11 sectors
+ /* 02 */ { FM, 0x00, 1 },
+ /* 03 */ { FM, 0xf3, 1 }, // word 0x00f3
+ /* 04 */ { FM, 0x00, 1 },
+ /* 05 */ { TRACK_ID_FM }, // track number word
+ /* 06 */ { SECTOR_LOOP_START, 0, 10 }, // 11 sectors
/* 07 */ { SECTOR_DATA_MX, -1 },
- /* 10 */ { SECTOR_LOOP_END },
- /* 13 */ { FM, 0x83, 1 },
+ /* 08 */ { SECTOR_LOOP_END },
+ /* 09 */ { FM, 0x83, 1 },
+ /* 10 */ { OFFSET_ID_FM },
+ /* 11 */ { FM, 0x83, 1 },
/* 12 */ { OFFSET_ID_FM },
- /* 15 */ { FM, 0x83, 1 },
+ /* 13 */ { FM, 0x83, 1 },
/* 14 */ { OFFSET_ID_FM },
- /* 17 */ { FM, 0x83, 1 },
- /* 16 */ { OFFSET_ID_FM },
- /* 18 */ { END }
+ /* 15 */ { END }
};
const floppy_image_format_t::desc_e dvk_mx_format::dvk_mx_old_desc[] = {
/* 01 */ { FM, 0x00, 30*2 },
- /* 03 */ { FM, 0x00, 1 },
- /* 02 */ { FM, 0xf3, 1 }, // word 0x00f3
- /* 05 */ { FM, 0x00, 1 },
- /* 04 */ { TRACK_ID_FM }, // track number word
+ /* 02 */ { FM, 0x00, 1 },
+ /* 03 */ { FM, 0xf3, 1 }, // word 0x00f3
+ /* 04 */ { FM, 0x00, 1 },
+ /* 05 */ { TRACK_ID_FM }, // track number word
/* 06 */ { SECTOR_LOOP_START, 0, 10 }, // 11 sectors
/* 07 */ { SECTOR_DATA_MX, -1 },
- /* 10 */ { SECTOR_LOOP_END },
- /* 13 */ { FM, 0x83, 1 },
- /* 11 */ { FM, 0x01, 1 },
- /* 15 */ { FM, 0x83, 1 },
- /* 14 */ { FM, 0x01, 1 },
- /* 16 */ { END }
+ /* 08 */ { SECTOR_LOOP_END },
+ /* 09 */ { FM, 0x00, 1 },
+ /* 10 */ { FM, 0116, 1 },
+ /* 11 */ { FM, 0x00, 4*2 }, // four 0x0000 words
+ /* 12 */ { END }
};
dvk_mx_format::dvk_mx_format()
{
}
-const char *dvk_mx_format::name() const noexcept
-{
- return "mx";
-}
-
-const char *dvk_mx_format::description() const noexcept
-{
- return "DVK MX: floppy image";
-}
-
-const char *dvk_mx_format::extensions() const noexcept
-{
- return "mx";
-}
-
-bool dvk_mx_format::supports_save() const noexcept
-{
- return false;
-}
-
void dvk_mx_format::find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count)
{
uint64_t size;
@@ -95,17 +75,17 @@ void dvk_mx_format::find_size(util::random_read &io, uint8_t &track_count, uint8
{
case 112640:
track_count = 40;
- sector_count = 11;
+ sector_count = MX_SECTORS;
head_count = 1;
break;
case 225280:
track_count = 40;
- sector_count = 11;
+ sector_count = MX_SECTORS;
head_count = 2;
break;
case 450560:
track_count = 80;
- sector_count = 11;
+ sector_count = MX_SECTORS;
head_count = 2;
break;
default:
@@ -123,8 +103,7 @@ int dvk_mx_format::identify(util::random_read &io, uint32_t form_factor, const s
if (track_count)
{
uint8_t sectdata[512];
- size_t actual;
- io.read_at(512, sectdata, 512, actual);
+ /*auto const [err, actual] =*/ read_at(io, 512, sectdata, 512); // FIXME: check for errors and premature EOF
// check value in RT-11 home block. see src/tools/imgtool/modules/rt11.cpp
if (get_u16le(&sectdata[0724]) == 6)
return FIFID_SIGN|FIFID_SIZE;
@@ -143,22 +122,21 @@ bool dvk_mx_format::load(util::random_read &io, uint32_t form_factor, const std:
find_size(io, track_count, head_count, sector_count);
if (track_count == 0) return false;
- uint8_t sectdata[11 * 256];
- desc_s sectors[11];
+ uint8_t sectdata[MX_SECTORS * MX_SECTOR_SIZE];
+ desc_s sectors[MX_SECTORS];
for (int i = 0; i < sector_count; i++)
{
- sectors[i].data = sectdata + 256 * i;
- sectors[i].size = 256;
+ sectors[i].data = sectdata + MX_SECTOR_SIZE * i;
+ sectors[i].size = MX_SECTOR_SIZE;
sectors[i].sector_id = i;
}
- int track_size = sector_count * 256;
+ int track_size = sector_count * MX_SECTOR_SIZE;
for (int track = 0; track < track_count; track++)
{
for (int head = 0; head < head_count; head++)
{
- size_t actual;
- io.read_at((track * head_count + head) * track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track * head_count + head) * track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(dvk_mx_new_desc, track, head, sectors, sector_count, 45824, image);
}
}
@@ -182,4 +160,65 @@ bool dvk_mx_format::load(util::random_read &io, uint32_t form_factor, const std:
return true;
}
+bool dvk_mx_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
+{
+ int tracks;
+ int heads;
+ bool res = false;
+ image.get_actual_geometry(tracks, heads);
+
+ for (int cyl = 0; cyl < tracks; cyl++)
+ {
+ for (int head = 0; head < heads; head++)
+ {
+ auto bitstream = generate_bitstream_from_track(cyl, head, 4000, image, 0);
+ uint8_t sector_data[MX_SECTORS * MX_SECTOR_SIZE];
+ if (get_next_sector(bitstream, sector_data))
+ {
+ unsigned const offset_in_image = (cyl * heads + head) * MX_SECTOR_SIZE * MX_SECTORS;
+ res = true;
+ // FIXME: check for errors
+ /*auto const [err, actual] =*/ write_at(io, offset_in_image, sector_data, MX_SECTOR_SIZE * MX_SECTORS);
+ }
+ }
+ }
+ return res;
+}
+
+bool dvk_mx_format::get_next_sector(const std::vector<bool> &bitstream, uint8_t *sector_data)
+{
+ uint32_t sr = 0;
+ int pos = 0;
+ while (pos < bitstream.size() && sr != ID_PATTERN)
+ {
+ sr = (sr << 1) | bitstream[pos];
+ pos++;
+ }
+ if (pos == bitstream.size())
+ {
+ // End of track reached
+ return false;
+ }
+ unsigned to_dump = MX_SECTORS * (MX_SECTOR_SIZE + 2);
+ pos += 32; // skip track ID
+ for (unsigned i = 0, k = 0; i < to_dump && pos < bitstream.size(); i++)
+ {
+ uint8_t byte = 0;
+ unsigned j;
+ for (j = 0; j < 8 && pos < bitstream.size(); j++)
+ {
+ bool bit = bitstream[pos + 1];
+ pos += 2;
+ byte <<= 1;
+ byte |= bit;
+ }
+ if (j == 8 && (i % (MX_SECTOR_SIZE + 2)) < MX_SECTOR_SIZE)
+ {
+ sector_data[k ^ 1] = byte;
+ k++;
+ }
+ }
+ return true;
+}
+
const dvk_mx_format FLOPPY_DVK_MX_FORMAT;
diff --git a/src/lib/formats/dvk_mx_dsk.h b/src/lib/formats/dvk_mx_dsk.h
index 83f93fd0878..b0d64deab9f 100644
--- a/src/lib/formats/dvk_mx_dsk.h
+++ b/src/lib/formats/dvk_mx_dsk.h
@@ -19,17 +19,22 @@ public:
virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
+ virtual bool save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const override;
- virtual const char *name() const noexcept override;
- virtual const char *description() const noexcept override;
- virtual const char *extensions() const noexcept override;
- virtual bool supports_save() const noexcept override;
+ virtual const char *name() const noexcept override { return "mx"; }
+ virtual const char *description() const noexcept override { return "DVK MX disk image"; }
+ virtual const char *extensions() const noexcept override { return "mx"; }
+ virtual bool supports_save() const noexcept override { return true; }
static const desc_e dvk_mx_old_desc[];
static const desc_e dvk_mx_new_desc[];
private:
+ static constexpr unsigned MX_SECTORS = 11;
+ static constexpr unsigned MX_SECTOR_SIZE = 256;
+
static void find_size(util::random_read &io, uint8_t &track_count, uint8_t &head_count, uint8_t &sector_count);
+ static bool get_next_sector(const std::vector<bool> &bitstream , uint8_t *sector_data);
};
extern const dvk_mx_format FLOPPY_DVK_MX_FORMAT;
diff --git a/src/lib/formats/esq16_dsk.cpp b/src/lib/formats/esq16_dsk.cpp
index a7e181b2cc7..f487e835665 100644
--- a/src/lib/formats/esq16_dsk.cpp
+++ b/src/lib/formats/esq16_dsk.cpp
@@ -113,8 +113,7 @@ bool esqimg_format::load(util::random_read &io, uint32_t form_factor, const std:
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- size_t actual;
- io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(esq_10_desc, track, head, sectors, sector_count, 110528, image);
}
}
@@ -145,8 +144,7 @@ bool esqimg_format::save(util::random_read_write &io, const std::vector<uint32_t
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- size_t actual;
- io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/esq8_dsk.cpp b/src/lib/formats/esq8_dsk.cpp
index fb3bdb112d6..b7225d839a9 100644
--- a/src/lib/formats/esq8_dsk.cpp
+++ b/src/lib/formats/esq8_dsk.cpp
@@ -132,8 +132,7 @@ bool esq8img_format::load(util::random_read &io, uint32_t form_factor, const std
{
for(int head=0; head < head_count; head++)
{
- size_t actual;
- io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(esq_6_desc, track, head, sectors, sector_count, 109376, image);
}
}
@@ -180,8 +179,7 @@ bool esq8img_format::save(util::random_read_write &io, const std::vector<uint32_
return false;
}
- size_t actual;
- io.write_at(file_offset, sectors[sector].data(), sector_expected_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, sectors[sector].data(), sector_expected_size); // FIXME: check for errors
file_offset += sector_expected_size;
}
}
diff --git a/src/lib/formats/fc100_cas.cpp b/src/lib/formats/fc100_cas.cpp
index da2247d49b5..d991ce8de6a 100644
--- a/src/lib/formats/fc100_cas.cpp
+++ b/src/lib/formats/fc100_cas.cpp
@@ -104,7 +104,7 @@ static int fc100_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int fc100_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int fc100_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return fc100_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/fdd_dsk.cpp b/src/lib/formats/fdd_dsk.cpp
index fc0741f2f5a..7519eb593dd 100644
--- a/src/lib/formats/fdd_dsk.cpp
+++ b/src/lib/formats/fdd_dsk.cpp
@@ -62,10 +62,11 @@ const char *fdd_format::extensions() const noexcept
int fdd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[7];
- size_t actual;
- io.read_at(0, h, 7, actual);
+ auto const [err, actual] = read_at(io, 0, h, 7); // FIXME: should it really be reading six bytes? also check for premature EOF.
+ if (err)
+ return false;
- if (strncmp((const char *)h, "VFD1.0", 6) == 0)
+ if (memcmp(h, "VFD1.0", 6) == 0)
return FIFID_SIGN;
return 0;
@@ -92,8 +93,7 @@ bool fdd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for (int sect = 0; sect < 26; sect++)
{
// read sector map for this sector
- size_t actual;
- io.read_at(pos, hsec, 0x0c, actual);
+ /*auto const [err, actual] =*/ read_at(io, pos, hsec, 0x0c); // FIXME: check for errors and premature EOF
pos += 0x0c;
if (hsec[0] == 0xff) // unformatted/unused sector
@@ -125,11 +125,10 @@ bool fdd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
cur_sec_map = track * 26 + i;
sector_size = 128 << sec_sizes[cur_sec_map];
- size_t actual;
if (sec_offs[cur_sec_map] == 0xffffffff)
memset(sect_data + cur_pos, fill_vals[cur_sec_map], sector_size);
else
- io.read_at(sec_offs[cur_sec_map], sect_data + cur_pos, sector_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, sec_offs[cur_sec_map], sect_data + cur_pos, sector_size); // FIXME: check for errors and premature EOF
sects[i].track = tracks[cur_sec_map];
sects[i].head = heads[cur_sec_map];
diff --git a/src/lib/formats/fdos_dsk.cpp b/src/lib/formats/fdos_dsk.cpp
index 2980376160e..138ad986011 100644
--- a/src/lib/formats/fdos_dsk.cpp
+++ b/src/lib/formats/fdos_dsk.cpp
@@ -39,9 +39,12 @@
#include "fdos_dsk.h"
#include "imageutl.h"
-#include "multibyte.h"
#include "ioprocs.h"
+#include "multibyte.h"
+
+#include <tuple>
+
namespace
{
@@ -116,7 +119,7 @@ int fdos_format::find_size(util::random_read &io, uint32_t form_factor, const st
// 00330 2403 DE OB RESTRT LDX PROGX
// Should be $BD and $DE respectively
// There could be additional variations
- ec = io.read_at(0, &boot0, f.sector_base_size, actual);
+ std::tie(ec, actual) = read_at(io, 0, &boot0, f.sector_base_size);
if (ec || actual != f.sector_base_size)
return -1;
if (boot0[0] != 0xbd && boot0[3] != 0xde)
@@ -129,7 +132,7 @@ int fdos_format::find_size(util::random_read &io, uint32_t form_factor, const st
form_factor);
// Directory entries start at Track 2 Sector 0
- ec = io.read_at(2 * f.sector_count * f.sector_base_size, &info, sizeof(struct fdos_formats::dirent_entry_fdos), actual);
+ std::tie(ec, actual) = read_at(io, 2 * f.sector_count * f.sector_base_size, &info, sizeof(struct fdos_formats::dirent_entry_fdos));
if (ec || actual != sizeof(struct fdos_formats::dirent_entry_fdos))
continue;
diff --git a/src/lib/formats/flacfile.cpp b/src/lib/formats/flacfile.cpp
index f3ccb676e52..c594a809a8e 100644
--- a/src/lib/formats/flacfile.cpp
+++ b/src/lib/formats/flacfile.cpp
@@ -16,10 +16,27 @@
#include <new>
-static constexpr int MAX_CHANNELS = 8;
+namespace {
+constexpr int MAX_CHANNELS = 8;
-static cassette_image::error flacfile_identify(cassette_image *cassette, cassette_image::Options *opts)
+
+// Copied from cassimg.cpp; put somewhere central?
+/*********************************************************************
+ helper code
+*********************************************************************/
+constexpr double map_double(double d, uint64_t low, uint64_t high, uint64_t value)
+{
+ return d * (value - low) / (high - low);
+}
+
+constexpr size_t waveform_bytes_per_sample(int waveform_flags)
+{
+ return size_t(1 << ((waveform_flags & 0x06) / 2));
+}
+
+
+cassette_image::error flacfile_identify(cassette_image *cassette, cassette_image::Options *opts)
{
cassette->get_raw_cassette_image()->seek(0, SEEK_SET);
flac_decoder decoder(*cassette->get_raw_cassette_image());
@@ -42,7 +59,7 @@ static cassette_image::error flacfile_identify(cassette_image *cassette, cassett
}
-static cassette_image::error flacfile_load(cassette_image *cassette)
+cassette_image::error flacfile_load(cassette_image *cassette)
{
cassette->get_raw_cassette_image()->seek(0, SEEK_SET);
flac_decoder decoder(*cassette->get_raw_cassette_image());
@@ -73,10 +90,63 @@ static cassette_image::error flacfile_load(cassette_image *cassette)
}
+cassette_image::error flacfile_save(cassette_image *cassette, const cassette_image::Info *info)
+{
+ if (info->channels > MAX_CHANNELS)
+ return cassette_image::error::INVALID_IMAGE;
+
+ cassette->get_raw_cassette_image()->seek(0, SEEK_SET);
+ flac_encoder encoder;
+ encoder.set_num_channels(info->channels);
+ encoder.set_sample_rate(info->sample_frequency);
+ if (!encoder.reset(*cassette->get_raw_cassette_image()))
+ return cassette_image::error::INTERNAL;
+
+ size_t samples_saved = 0;
+ int16_t buffer[MAX_CHANNELS][4096];
+ int16_t *buffer_ptr[MAX_CHANNELS];
+ const size_t bytes_per_sample = waveform_bytes_per_sample(cassette_image::WAVEFORM_16BIT);
+ const size_t sample_spacing = bytes_per_sample * info->channels;
+ const double sample_period = info->sample_count / (double) info->sample_frequency;
+
+ for (int channel = 0; channel < MAX_CHANNELS; channel++)
+ {
+ buffer_ptr[channel] = &buffer[channel][0];
+ }
+
+ while (samples_saved < info->sample_count)
+ {
+ size_t chunk_sample_count = std::min(sizeof(buffer) / sample_spacing, (info->sample_count - samples_saved));
+ double chunk_sample_period = map_double(sample_period, 0, info->sample_count, chunk_sample_count);
+ double chunk_time_index = map_double(sample_period, 0, info->sample_count, samples_saved);
+
+ for (int channel = 0; channel < info->channels; channel++)
+ {
+ cassette_image::error err = cassette->get_samples(channel, chunk_time_index, chunk_sample_period,
+ chunk_sample_count, sample_spacing, &buffer[channel * bytes_per_sample], cassette_image::WAVEFORM_16BIT);
+
+ if (err != cassette_image::error::SUCCESS)
+ return err;
+ }
+
+ if (!encoder.encode(buffer_ptr, chunk_sample_count))
+ return cassette_image::error::INTERNAL;
+
+ samples_saved += chunk_sample_count;
+ }
+
+ encoder.finish();
+
+ return cassette_image::error::SUCCESS;
+}
+
+} // anonymous namespace
+
+
const cassette_image::Format cassette_image::flacfile_format =
{
"flac",
flacfile_identify,
flacfile_load,
- nullptr
+ flacfile_save
};
diff --git a/src/lib/formats/flex_dsk.cpp b/src/lib/formats/flex_dsk.cpp
index 778e6c990b9..11a72963471 100644
--- a/src/lib/formats/flex_dsk.cpp
+++ b/src/lib/formats/flex_dsk.cpp
@@ -91,12 +91,11 @@ int flex_format::find_size(util::random_read &io, uint32_t form_factor, const st
return -1;
uint8_t boot0[256], boot1[256];
- size_t actual;
// Look at the boot sector.
// Density, sides, link??
- io.read_at(256 * 0, &boot0, sizeof(boot0), actual);
- io.read_at(256 * 1, &boot1, sizeof(boot1), actual);
+ read_at(io, 256 * 0, &boot0, sizeof(boot0)); // FIXME: check for errors and premature EOF
+ read_at(io, 256 * 1, &boot1, sizeof(boot1)); // FIXME: check for errors and premature EOF
LOG_FORMATS("FLEX floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 256, (uint32_t)size % 256, form_factor);
@@ -129,7 +128,7 @@ int flex_format::find_size(util::random_read &io, uint32_t form_factor, const st
if (f.sector_base_size == 128) {
// FLEX 1.0: Look at the system information sector.
sysinfo_sector_flex10 info;
- io.read_at(f.sector_base_size * 2, &info, sizeof(struct sysinfo_sector_flex10), actual);
+ read_at(io, f.sector_base_size * 2, &info, sizeof(struct sysinfo_sector_flex10)); // FIXME: check for errors and premature EOF
LOG_FORMATS("FLEX floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / f.sector_base_size, (uint32_t)size % f.sector_base_size, form_factor);
@@ -142,7 +141,7 @@ int flex_format::find_size(util::random_read &io, uint32_t form_factor, const st
} else {
// FLEX 2+: Look at the system information sector.
sysinfo_sector info;
- io.read_at(f.sector_base_size * 2, &info, sizeof(struct sysinfo_sector), actual);
+ read_at(io, f.sector_base_size * 2, &info, sizeof(struct sysinfo_sector)); // FIXME: check for errors and premature EOF
LOG_FORMATS("FLEX floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / f.sector_base_size, (uint32_t)size % f.sector_base_size, form_factor);
diff --git a/src/lib/formats/flopimg.cpp b/src/lib/formats/flopimg.cpp
index ec978817a6e..fa4903447fb 100644
--- a/src/lib/formats/flopimg.cpp
+++ b/src/lib/formats/flopimg.cpp
@@ -39,6 +39,39 @@ floppy_image::~floppy_image()
{
}
+void floppy_image::set_variant(uint32_t _variant)
+{
+ variant = _variant;
+
+ // Initialize hard sectors
+ index_array.clear();
+
+ uint32_t sectors;
+ switch(variant) {
+ case SSDD16:
+ case SSQD16:
+ case DSDD16:
+ case DSQD16:
+ sectors = 16;
+ break;
+ default:
+ sectors = 0;
+ }
+ if(sectors) {
+ uint32_t sector_angle = 200000000/sectors;
+ for(int i = 1; i < sectors; i++)
+ index_array.push_back(i*sector_angle);
+ index_array.push_back((sectors-1)*sector_angle + sector_angle/2);
+ }
+}
+
+void floppy_image::find_index_hole(uint32_t pos, uint32_t &last, uint32_t &next) const
+{
+ auto nexti = std::lower_bound(index_array.begin(), index_array.end(), pos+1);
+ next = nexti == index_array.end() ? 200000000 : *nexti;
+ last = nexti == index_array.begin() ? 0 : *--nexti;
+}
+
void floppy_image::get_maximal_geometry(int &_tracks, int &_heads) const noexcept
{
_tracks = tracks;
@@ -104,13 +137,30 @@ bool floppy_image::track_is_formatted(int track, int head, int subtrack) const n
const char *floppy_image::get_variant_name(uint32_t form_factor, uint32_t variant) noexcept
{
switch(variant) {
- case SSSD: return "Single side, single density";
- case SSDD: return "Single side, double density";
- case SSQD: return "Single side, quad density";
- case DSDD: return "Double side, double density";
- case DSQD: return "Double side, quad density";
- case DSHD: return "Double side, high density";
- case DSED: return "Double side, extended density";
+ case SSSD: return "Single side, single density";
+ case SSSD10: return "Single side, single density, 10-sector";
+ case SSSD16: return "Single side, single density, 16-sector";
+ case SSSD32: return "Single side, single density, 32-sector";
+ case SSDD: return "Single side, double density";
+ case SSDD10: return "Single side, double density, 10-sector";
+ case SSDD16: return "Single side, double density, 16 hard sector";
+ case SSDD32: return "Single side, double density, 32-sector";
+ case SSQD: return "Single side, quad density";
+ case SSQD10: return "Single side, quad density, 10-sector";
+ case SSQD16: return "Single side, quad density, 16 hard sector";
+ case DSSD: return "Double side, single density";
+ case DSSD10: return "Double side, single density, 10-sector";
+ case DSSD16: return "Double side, single density, 16-sector";
+ case DSSD32: return "Double side, single density, 32-sector";
+ case DSDD: return "Double side, double density";
+ case DSDD10: return "Double side, double density, 10-sector";
+ case DSDD16: return "Double side, double density, 16 hard sector";
+ case DSDD32: return "Double side, double density, 32-sector";
+ case DSQD: return "Double side, quad density";
+ case DSQD10: return "Double side, quad density, 10-sector";
+ case DSQD16: return "Double side, quad density, 16 hard sector";
+ case DSHD: return "Double side, high density";
+ case DSED: return "Double side, extended density";
}
return "Unknown";
}
@@ -864,7 +914,7 @@ void floppy_image_format_t::generate_track_from_bitstream(int track, int head, c
normalize_times(dest, track_size*2);
- if(splice >= 0 || splice < track_size) {
+ if(splice >= 0 && splice < track_size) {
int splpos = uint64_t(200000000) * splice / track_size;
image.set_write_splice_position(track, head, splpos, subtrack);
}
diff --git a/src/lib/formats/flopimg.h b/src/lib/formats/flopimg.h
index 4098ab3d418..18cc17ea73b 100644
--- a/src/lib/formats/flopimg.h
+++ b/src/lib/formats/flopimg.h
@@ -525,14 +525,30 @@ public:
//! Variants
enum {
- SSSD = 0x44535353, //!< "SSSD", Single-sided single-density
- SSDD = 0x44445353, //!< "SSDD", Single-sided double-density
- SSQD = 0x44515353, //!< "SSQD", Single-sided quad-density
- DSSD = 0x44535344, //!< "DSSD", Double-sided single-density
- DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K in 3.5, 360K in 5.25)
- DSQD = 0x44515344, //!< "DSQD", Double-sided quad-density (720K in 5.25, means DD+80 tracks)
- DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K)
- DSED = 0x44455344 //!< "DSED", Double-sided extra-density (2880K)
+ SSSD = 0x44535353, //!< "SSSD", Single-sided single-density
+ SSSD10 = 0x30315353, //!< "SS10", Single-sided single-density 10 hard sector
+ SSSD16 = 0x36315353, //!< "SS16", Single-sided single-density 16 hard sector
+ SSSD32 = 0x32335353, //!< "SS32", Single-sided single-density 32 hard sector
+ SSDD = 0x44445353, //!< "SSDD", Single-sided double-density
+ SSDD10 = 0x30314453, //!< "SD10", Single-sided double-density 10 hard sector
+ SSDD16 = 0x36314453, //!< "SD16", Single-sided double-density 16 hard sector
+ SSDD32 = 0x32334453, //!< "SD32", Single-sided double-density 32 hard sector
+ SSQD = 0x44515353, //!< "SSQD", Single-sided quad-density
+ SSQD10 = 0x30315153, //!< "SQ10", Single-sided quad-density 10 hard sector
+ SSQD16 = 0x36315153, //!< "SQ16", Single-sided quad-density 16 hard sector
+ DSSD = 0x44535344, //!< "DSSD", Double-sided single-density
+ DSSD10 = 0x30315344, //!< "DS10", Double-sided single-density 10 hard sector
+ DSSD16 = 0x36315344, //!< "DS16", Double-sided single-density 16 hard sector
+ DSSD32 = 0x32335344, //!< "DS32", Double-sided single-density 32 hard sector
+ DSDD = 0x44445344, //!< "DSDD", Double-sided double-density (720K in 3.5, 360K in 5.25)
+ DSDD10 = 0x30314444, //!< "DD10", Double-sided double-density 10 hard sector
+ DSDD16 = 0x36314444, //!< "DD16", Double-sided double-density 16 hard sector (360K in 5.25)
+ DSDD32 = 0x32334444, //!< "DD32", Double-sided double-density 32 hard sector
+ DSQD = 0x44515344, //!< "DSQD", Double-sided quad-density (720K in 5.25, means DD+80 tracks)
+ DSQD10 = 0x30315144, //!< "DQ10", Double-sided quad-density 10 hard sector
+ DSQD16 = 0x36315144, //!< "DQ16", Double-sided quad-density 16 hard sector (720K in 5.25, means DD+80 tracks)
+ DSHD = 0x44485344, //!< "DSHD", Double-sided high-density (1440K)
+ DSED = 0x44455344 //!< "DSED", Double-sided extra-density (2880K)
};
//! Encodings
@@ -542,6 +558,14 @@ public:
M2FM = 0x4D32464D //!< "M2FM", modified modified frequency modulation
};
+ //! Sectoring
+ enum {
+ SOFT = 0x54464F53, //!< "SOFT", Soft-sectored
+ H10 = 0x20303148, //!< "H10 ", Hard 10-sectored
+ H16 = 0x20363148, //!< "H16 ", Hard 16-sectored
+ H32 = 0x20323348 //!< "H32 ", Hard 32-sectored (8 inch disk)
+ };
+
// construction/destruction
@@ -558,10 +582,25 @@ public:
uint32_t get_form_factor() const noexcept { return form_factor; }
//! @return the variant.
uint32_t get_variant() const noexcept { return variant; }
+ //! @return the disk sectoring.
+ uint32_t get_sectoring() const noexcept { return sectoring; }
//! @param v the variant.
- void set_variant(uint32_t v) { variant = v; }
+ void set_variant(uint32_t v);
//! @param v the variant.
- void set_form_variant(uint32_t f, uint32_t v) { if(form_factor == FF_UNKNOWN) form_factor = f; variant = v; }
+ void set_form_variant(uint32_t f, uint32_t v) { if(form_factor == FF_UNKNOWN) form_factor = f; set_variant(v); }
+ //! @param s the sectoring.
+ void set_sectoring(uint32_t s) { sectoring = s; }
+
+ //! Find most recent and next index hole for provided angular position.
+ //! The most recent hole may be equal to provided position. The next
+ //! hole will be 200000000 if all holes of the current rotation are in
+ //! the past.
+
+ /*! @param pos angular position
+ @param last most recent index hole
+ @param next next index hole
+ */
+ void find_index_hole(uint32_t pos, uint32_t &last, uint32_t &next) const;
/*!
@param track
@@ -608,7 +647,7 @@ public:
private:
int tracks, heads;
- uint32_t form_factor, variant;
+ uint32_t form_factor, variant, sectoring;
struct track_info
{
@@ -621,6 +660,14 @@ private:
// track number multiplied by 4 then head
// last array size may be bigger than actual track size
std::vector<std::vector<track_info> > track_array;
+
+ // Additional index holes in increasing order. Entries are absolute
+ // positions of index holes in the same units as cell_data. The
+ // positions are the start of the hole, not the center of the hole. The
+ // hole at angular position 0 is implicit, so an empty list encodes a
+ // regular soft-sectored disk. Additional holes are found on
+ // hard-sectored disks.
+ std::vector<uint32_t> index_array;
};
#endif // MAME_FORMATS_FLOPIMG_H
diff --git a/src/lib/formats/flopimg_legacy.cpp b/src/lib/formats/flopimg_legacy.cpp
index 5b8aee0a72b..c209b7cab58 100644
--- a/src/lib/formats/flopimg_legacy.cpp
+++ b/src/lib/formats/flopimg_legacy.cpp
@@ -349,16 +349,14 @@ util::random_read_write &floppy_get_io(floppy_image_legacy *floppy)
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);
+ /*auto const [err, actual] =*/ read_at(*floppy->io, offset, buffer, length); // FIXME: check for errors and premature EOF
}
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);
+ /*auto const [err, actual] =*/ write_at(*floppy->io, offset, buffer, length); // FIXME: check for errors
}
@@ -371,8 +369,7 @@ void floppy_image_write_filler(floppy_image_legacy *floppy, uint8_t filler, uint
while (length)
{
size_t const block = std::min(sizeof(buffer), length);
- size_t actual;
- floppy->io->write_at(offset, buffer, block, actual);
+ /*auto const [err, actual] =*/ write_at(*floppy->io, offset, buffer, block); // FIXME: check for errors
offset += block;
length -= block;
}
diff --git a/src/lib/formats/fm7_cas.cpp b/src/lib/formats/fm7_cas.cpp
index 54a5095547a..25953627361 100644
--- a/src/lib/formats/fm7_cas.cpp
+++ b/src/lib/formats/fm7_cas.cpp
@@ -72,7 +72,7 @@ static int fm7_cas_to_wav_size (const uint8_t *casdata, int caslen)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int fm7_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int fm7_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return fm7_handle_t77(buffer,bytes);
}
diff --git a/src/lib/formats/fmsx_cas.cpp b/src/lib/formats/fmsx_cas.cpp
index b6642568b55..c7969b28eca 100644
--- a/src/lib/formats/fmsx_cas.cpp
+++ b/src/lib/formats/fmsx_cas.cpp
@@ -49,7 +49,7 @@ static int fmsx_cas_to_wav_size (const uint8_t *casdata, int caslen)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int fmsx_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int fmsx_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
int cas_pos, bit, state = 1, samples_pos, size, n, i, p;
diff --git a/src/lib/formats/fs_cbmdos.cpp b/src/lib/formats/fs_cbmdos.cpp
index 51d1369b04f..44c810a04a6 100644
--- a/src/lib/formats/fs_cbmdos.cpp
+++ b/src/lib/formats/fs_cbmdos.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
+// copyright-holders:Nathan Woods, Wilbert Pol
/***************************************************************************
fs_cbmdos.cpp
@@ -8,21 +8,30 @@
http://fileformats.archiveteam.org/wiki/CBMFS
+Current limitations:
+- Writing is limited to the first 35 tracks.
+- Determine or select the file type. Currently defaulting to PRG; 0 byte files
+ will be assigned file type DEL.
+
***************************************************************************/
#include "fs_cbmdos.h"
+
#include "d64_dsk.h"
#include "fsblk.h"
#include "corestr.h"
+#include "multibyte.h"
#include "strformat.h"
#include <array>
#include <optional>
+#include <regex>
#include <set>
#include <string_view>
#include <tuple>
+
namespace fs {
const cbmdos_image CBMDOS;
};
@@ -33,6 +42,8 @@ namespace {
class impl : public filesystem_t {
public:
+ static constexpr u8 SECTOR_DIRECTORY_COUNT = 8;
+
struct cbmdos_dirent
{
u8 m_next_directory_track;
@@ -55,30 +66,74 @@ public:
block_iterator(const impl &fs, u8 first_track, u8 first_sector);
bool next();
const void *data() const;
- const std::array<cbmdos_dirent, 4> &dirent_data() const;
+ const std::array<cbmdos_dirent, SECTOR_DIRECTORY_COUNT> &dirent_data() const;
u8 size() const;
+ u8 track() const { return m_track; }
+ u8 sector() const { return m_sector; }
private:
const impl & m_fs;
- fsblk_t::block_t m_block;
+ fsblk_t::block_t::ptr m_block;
std::set<std::tuple<u8, u8>> m_visited_set;
u8 m_track;
u8 m_sector;
+ u8 m_next_track;
+ u8 m_next_sector;
};
impl(fsblk_t &blockdev);
virtual ~impl() = default;
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
private:
- fsblk_t::block_t read_sector(int track, int sector) const;
+ static constexpr u32 BLOCK_SIZE = 256;
+ static constexpr u8 DIRECTORY_ENTRY_SIZE = 0x20;
+ static constexpr u8 FILE_TYPE_DEL = 0x80;
+ static constexpr u8 FILE_TYPE_SEQ = 0x81;
+ static constexpr u8 FILE_TYPE_PRG = 0x82;
+ static constexpr u8 FILE_TYPE_USR = 0x83;
+ static constexpr u8 FILE_TYPE_REL = 0x84;
+ static constexpr u8 TRACK_VARIANTS = 5;
+ static constexpr u8 MAX_SECTORS = 21;
+ static constexpr u8 MAX_TRACKS = 40;
+ static constexpr u8 DIRECTORY_TRACK = 18;
+ static constexpr u8 BAM_SECTOR = 0;
+ static constexpr u8 FIRST_DIRECTORY_SECTOR = 1;
+ static constexpr u8 SECTOR_DATA_BYTES = 254;
+ static constexpr u8 OFFSET_FILE_TYPE = 0x02;
+ static constexpr u8 OFFSET_FILE_FIRST_TRACK = 0x03;
+ static constexpr u8 OFFSET_FILE_FIRST_SECTOR = 0x04;
+ static constexpr u8 OFFSET_FILE_NAME = 0x05;
+ static constexpr u8 OFFSET_SECTOR_COUNT = 0x1e;
+ static constexpr u8 OFFSET_CHAIN_TRACK = 0x00;
+ static constexpr u8 OFFSET_CHAIN_SECTOR = 0x01;
+ static constexpr u8 CHAIN_END = 0x00;
+
+ static const struct smap
+ {
+ u8 first_track;
+ u8 last_track;
+ int sector[MAX_SECTORS];
+ } s_track_sector_map[TRACK_VARIANTS];
+ static const u8 s_data_track_order[MAX_TRACKS - 1];
+ u8 m_max_track;
+
+ fsblk_t::block_t::ptr read_sector(int track, int sector) const;
std::optional<cbmdos_dirent> dirent_from_path(const std::vector<std::string> &path) const;
- void iterate_directory_entries(const std::function<bool(const cbmdos_dirent &dirent)> &callback) const;
+ void iterate_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const;
+ void iterate_all_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const;
meta_data metadata_from_dirent(const cbmdos_dirent &dirent) const;
+ bool is_valid_filename(const std::string &filename) const;
+ std::pair<std::error_condition, u8> claim_track_sector(u8 track) const;
+ std::tuple<std::error_condition, u8, u8> claim_sector() const;
+ std::error_condition free_sector(u8 track, u8 sector) const;
+ u8 determine_file_type(const std::vector<u8> &data) const;
};
// methods
@@ -145,7 +200,7 @@ bool fs::cbmdos_image::can_read() const
bool fs::cbmdos_image::can_write() const
{
- return false;
+ return true;
}
@@ -223,8 +278,22 @@ std::string_view strtrimright_cbm(const char (&str)[N])
// impl ctor
//-------------------------------------------------
+const u8 impl::s_data_track_order[MAX_TRACKS - 1] = {
+ 17, 19, 16, 20, 15, 21, 14, 22, 13, 23, 12, 24, 11, 25, 10, 26, 9, 27, 8, 28, 7, 29, 6, 30, 5, 31, 4, 32, 3, 33, 2, 34, 1, 35, 36, 37, 38, 39, 40
+};
+
+const impl::smap impl::s_track_sector_map[TRACK_VARIANTS] = {
+ { 1, 17, { 0, 11, 1, 12, 2, 13, 3, 14, 4, 15, 5, 16, 6, 17, 7, 18, 8, 19, 9, 20, 10 } },
+ { 18, 18, { 0, 1, 4, 7, 10, 13, 16, 2, 5, 8, 11, 14, 17, 3, 6, 9, 12, 15, 18, -1, -1 } },
+ { 19, 24, { 0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, -1, -1 } },
+ { 25, 30, { 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, 17, -1, -1, -1 } },
+ { 31, 40, { 0, 9, 1, 10, 2, 11, 3, 12, 4, 13, 5, 14, 6, 15, 7, 16, 8, -1, -1, -1, -1 } }
+};
+
+
impl::impl(fsblk_t &blockdev)
- : filesystem_t(blockdev, 256)
+ : filesystem_t(blockdev, BLOCK_SIZE)
+ , m_max_track(35)
{
}
@@ -235,8 +304,8 @@ impl::impl(fsblk_t &blockdev)
meta_data impl::volume_metadata()
{
- auto bam_block = read_sector(18, 0);
- std::string_view disk_name = std::string_view((const char *) bam_block.rodata() + 0x90, 16);
+ auto bam_block = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ std::string_view disk_name = bam_block->rstr(0x90, 16);
meta_data results;
results.set(meta_name::name, strtrimright_cbm(disk_name));
@@ -248,13 +317,13 @@ meta_data impl::volume_metadata()
// impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> impl::metadata(const std::vector<std::string> &path)
{
std::optional<cbmdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, metadata_from_dirent(*dirent));
+ return std::make_pair(std::error_condition(), metadata_from_dirent(*dirent));
}
@@ -262,16 +331,16 @@ std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
// impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
{
std::vector<dir_entry> results;
- auto callback = [this, &results](const cbmdos_dirent &ent)
+ auto callback = [this, &results](u8 track, u8 sector, u8 file_index, const cbmdos_dirent &ent)
{
results.emplace_back(dir_entry_type::file, metadata_from_dirent(ent));
return false;
};
iterate_directory_entries(callback);
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -279,12 +348,12 @@ std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vec
// impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
{
// find the file
std::optional<cbmdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
// and get the data
std::vector<u8> result;
@@ -292,7 +361,263 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
while (iter.next())
result.insert(result.end(), (const u8 *)iter.data(), (const u8 *)iter.data() + iter.size());
- return std::make_pair(ERR_OK, std::move(result));
+ return std::make_pair(std::error_condition(), std::move(result));
+}
+
+
+std::error_condition impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+{
+ std::string filename = meta.get_string(meta_name::name, "");
+ if (!is_valid_filename(filename))
+ return error::invalid_name;
+
+ std::optional<cbmdos_dirent> result;
+ u8 track = 0;
+ u8 sector = 0;
+ u8 file_index = 0;
+ auto callback = [&result, &track, &sector, &file_index](u8 t, u8 s, u8 i, const cbmdos_dirent &dirent)
+ {
+ bool found = dirent.m_file_type == 0x00;
+ if (found)
+ {
+ result = dirent;
+ track = t;
+ sector = s;
+ file_index = i;
+ }
+ return found;
+ };
+ iterate_all_directory_entries(callback);
+
+ if (!result)
+ {
+ // Claim a next directory sector
+ auto const [err, new_sector] = claim_track_sector(DIRECTORY_TRACK);
+ if (err)
+ return err;
+ auto new_block = read_sector(DIRECTORY_TRACK, new_sector);
+ for (int i = 2; i < BLOCK_SIZE; i++)
+ new_block->w8(i, 0);
+ // Find last directory sector
+ u8 last_sector = 0;
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
+ while (iter.next())
+ last_sector = iter.sector();
+ // Update chain on last directory sector
+ auto last_dir_block = read_sector(DIRECTORY_TRACK, last_sector);
+ last_dir_block->w8(OFFSET_CHAIN_TRACK, DIRECTORY_TRACK);
+ last_dir_block->w8(OFFSET_CHAIN_SECTOR, new_sector);
+ track = DIRECTORY_TRACK;
+ sector = new_sector;
+ }
+
+ auto const [err, file_track, file_sector] = claim_sector();
+ if (err)
+ return err;
+
+ // Create the file
+ auto dirblk = read_sector(track, sector);
+ u32 offset = file_index * DIRECTORY_ENTRY_SIZE;
+ for (int i = 0; i < DIRECTORY_ENTRY_SIZE; i++)
+ dirblk->w8(offset + i, (i >= 5 && i < 5 + 16) ? 0xa0 : 0x00);
+ dirblk->w8(offset + OFFSET_FILE_TYPE, FILE_TYPE_PRG);
+ dirblk->w8(offset + OFFSET_FILE_FIRST_TRACK, file_track);
+ dirblk->w8(offset + OFFSET_FILE_FIRST_SECTOR, file_sector);
+ dirblk->wstr(offset + OFFSET_FILE_NAME, filename);
+ // TODO set first side sector block track (rel file)
+ // TODO set first side sector block sector (rel file)
+ // TODO set rel file record length
+ // sector count will be set while writing the data
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+{
+ if (path.size() != 1)
+ return error::not_found;
+ std::string_view path_part = path[0];
+
+ std::optional<cbmdos_dirent> result;
+ u8 dir_track = 0;
+ u8 dir_sector = 0;
+ u8 dir_file_index = 0;
+ auto const callback = [&result, &dir_track, &dir_sector, &dir_file_index, path_part] (u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)
+ {
+ bool found = strtrimright_cbm(dirent.m_file_name) == path_part;
+ if (found)
+ {
+ dir_track = track;
+ dir_sector = sector;
+ dir_file_index = file_index;
+ result = dirent;
+ }
+ return found;
+ };
+ iterate_directory_entries(callback);
+
+ if (!result)
+ return error::not_found;
+
+ u8 data_track = result->m_file_first_track;
+ u8 data_sector = result->m_file_first_sector;
+
+ const size_t data_length = data.size();
+ size_t offset = 0;
+ u32 sector_count = 0;
+ while (offset < data_length)
+ {
+ auto datablk = read_sector(data_track, data_sector);
+ u8 bytes = (data_length - offset) > SECTOR_DATA_BYTES ? SECTOR_DATA_BYTES : data_length - offset;
+ datablk->write(2, data.data() + offset, bytes);
+ offset += SECTOR_DATA_BYTES;
+ sector_count++;
+ if (datablk->r8(OFFSET_CHAIN_TRACK) == CHAIN_END)
+ {
+ if (offset < data_length)
+ {
+ auto [err, next_track, next_sector] = claim_sector();
+ if (err)
+ return err;
+ datablk->w8(OFFSET_CHAIN_TRACK, next_track);
+ datablk->w8(OFFSET_CHAIN_SECTOR, next_sector);
+ data_track = next_track;
+ data_sector = next_sector;
+ }
+ }
+ else
+ {
+ if (offset < data_length)
+ {
+ data_track = datablk->r8(OFFSET_CHAIN_TRACK);
+ data_sector = datablk->r8(OFFSET_CHAIN_SECTOR);
+ }
+ else
+ {
+ // Free the rest of the chain
+ u8 track_to_free = datablk->r8(OFFSET_CHAIN_TRACK);
+ u8 sector_to_free = datablk->r8(OFFSET_CHAIN_SECTOR);
+
+ while (track_to_free != CHAIN_END)
+ {
+ std::error_condition const err = free_sector(track_to_free, sector_to_free);
+ if (err)
+ return err;
+ datablk = read_sector(track_to_free, sector_to_free);
+ track_to_free = datablk->r8(OFFSET_CHAIN_TRACK);
+ sector_to_free = datablk->r8(OFFSET_CHAIN_SECTOR);
+ }
+ }
+ }
+ if (offset >= data_length)
+ {
+ datablk->w8(OFFSET_CHAIN_TRACK, CHAIN_END);
+ datablk->w8(OFFSET_CHAIN_SECTOR, bytes + 1);
+ }
+ }
+
+ // Write sector count and file type to directory entry
+ auto dirblk = read_sector(dir_track, dir_sector);
+ u8 file_type = determine_file_type(data);
+ if (file_type == FILE_TYPE_DEL)
+ {
+ // Free sector, update first file sector to 00
+ u8 file_track = dirblk->r8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_TRACK);
+ u8 file_sector = dirblk->r8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_SECTOR);
+ std::error_condition err = free_sector(file_track, file_sector);
+ if (err)
+ return err;
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_TRACK, 0);
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_FIRST_SECTOR, 0);
+ sector_count = 0;
+ }
+ dirblk->w8(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_FILE_TYPE, file_type);
+ dirblk->w16l(DIRECTORY_ENTRY_SIZE * dir_file_index + OFFSET_SECTOR_COUNT, sector_count);
+
+ return std::error_condition();
+}
+
+
+u8 impl::determine_file_type(const std::vector<u8> &data) const
+{
+ // TODO: Determine/set the actual file type, defaulting to PRG for now.
+ const size_t data_length = data.size();
+ if (data_length == 0)
+ return FILE_TYPE_DEL;
+ return FILE_TYPE_PRG;
+}
+
+
+bool impl::is_valid_filename(const std::string &filename) const
+{
+ // We only support a subset of the character set supported by Commodore for filenames.
+ std::regex filename_regex("[A-Z0-9!\"#\\$%&'\\(\\)*+,-./:;<=>?]{1,16}");
+ return std::regex_match(filename, filename_regex);
+}
+
+
+std::pair<std::error_condition, u8> impl::claim_track_sector(u8 track) const
+{
+ if (track == 0 || track > m_max_track)
+ return std::make_pair(error::invalid_block, 0);
+
+ u8 map_index;
+ for (map_index = 0; map_index < TRACK_VARIANTS && !(s_track_sector_map[map_index].first_track <= track && track <= s_track_sector_map[map_index].last_track) ; map_index++);
+ if (map_index >= TRACK_VARIANTS)
+ return std::make_pair(error::invalid_block, 0);
+
+ auto bamblk = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ u8 free_count = bamblk->r8(4 * track);
+ u32 free_bitmap = bamblk->r24l(4 * track + 1);
+
+ for (int s = 0; s < MAX_SECTORS; s++)
+ {
+ int sector = s_track_sector_map[map_index].sector[s];
+ if (sector >= 0 && free_count > 0 && util::BIT(free_bitmap, sector))
+ {
+ free_bitmap &= ~(1 << sector);
+ free_count--;
+ bamblk->w8(4 * track, free_count);
+ bamblk->w24l(4 * track + 1, free_bitmap);
+ // Write chain end marker in new sector
+ auto claimedlk = read_sector(track, sector);
+ claimedlk->w8(OFFSET_CHAIN_TRACK, CHAIN_END);
+ claimedlk->w8(OFFSET_CHAIN_SECTOR, 0xff);
+ return std::make_pair(std::error_condition(), sector);
+ }
+ }
+ return std::make_pair(error::no_space, 0);
+}
+
+
+std::tuple<std::error_condition, u8, u8> impl::claim_sector() const
+{
+ for (int track = 0; track < m_max_track - 1; track++)
+ {
+ auto const [err, sector] = claim_track_sector(s_data_track_order[track]);
+ if (!err)
+ return std::make_tuple(std::error_condition(), s_data_track_order[track], sector);
+ if (err != error::no_space)
+ return std::make_tuple(err, 0, 0);
+ }
+ return std::make_tuple(error::no_space, 0, 0);
+}
+
+
+std::error_condition impl::free_sector(u8 track, u8 sector) const
+{
+ if (track == 0 || track > m_max_track)
+ return error::invalid_block;
+
+ auto bamblk = read_sector(DIRECTORY_TRACK, BAM_SECTOR);
+ u8 free_count = bamblk->r8(4 * track);
+ u32 free_bitmap = bamblk->r24l(4 * track + 1);
+ free_bitmap |= (1 << sector);
+ free_count++;
+ bamblk->w8(4 * track, free_count);
+ bamblk->w24l(4 * track + 1, free_bitmap);
+ return std::error_condition();
}
@@ -300,7 +625,7 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
// impl::read_sector
//-------------------------------------------------
-fsblk_t::block_t impl::read_sector(int track, int sector) const
+fsblk_t::block_t::ptr impl::read_sector(int track, int sector) const
{
// CBM thinks in terms of tracks/sectors, but we have a block device abstraction
u32 block = 0;
@@ -320,13 +645,13 @@ fsblk_t::block_t impl::read_sector(int track, int sector) const
std::optional<impl::cbmdos_dirent> impl::dirent_from_path(const std::vector<std::string> &path) const
{
if (path.size() != 1)
- return { };
+ return std::nullopt;
std::string_view path_part = path[0];
std::optional<cbmdos_dirent> result;
- auto callback = [&result, path_part](const cbmdos_dirent &dirent)
+ auto const callback = [&result, path_part] (u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)
{
- bool found = strtrimright_cbm(dirent.m_file_name) == path_part;
+ bool const found = strtrimright_cbm(dirent.m_file_name) == path_part;
if (found)
result = dirent;
return found;
@@ -340,22 +665,38 @@ std::optional<impl::cbmdos_dirent> impl::dirent_from_path(const std::vector<std:
// impl::iterate_directory_entries
//-------------------------------------------------
-void impl::iterate_directory_entries(const std::function<bool(const cbmdos_dirent &dirent)> &callback) const
+void impl::iterate_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const
{
- block_iterator iter(*this, 18, 1);
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
while (iter.next())
{
- for (const cbmdos_dirent &ent : iter.dirent_data())
+ auto entries = iter.dirent_data();
+
+ for (int file_index = 0; file_index < SECTOR_DIRECTORY_COUNT; file_index++)
{
- if (ent.m_file_type != 0x00)
+ if (entries[file_index].m_file_type != 0x00)
{
- if (callback(ent))
+ if (callback(iter.track(), iter.sector(), file_index, entries[file_index]))
return;
}
}
}
}
+void impl::iterate_all_directory_entries(const std::function<bool(u8 track, u8 sector, u8 file_index, const cbmdos_dirent &dirent)> &callback) const
+{
+ block_iterator iter(*this, DIRECTORY_TRACK, FIRST_DIRECTORY_SECTOR);
+ while (iter.next())
+ {
+ auto entries = iter.dirent_data();
+
+ for (int file_index = 0; file_index < SECTOR_DIRECTORY_COUNT; file_index++)
+ {
+ if (callback(iter.track(), iter.sector(), file_index, entries[file_index]))
+ return;
+ }
+ }
+}
//-------------------------------------------------
// impl::metadata_from_dirent
@@ -366,19 +707,19 @@ meta_data impl::metadata_from_dirent(const cbmdos_dirent &dirent) const
std::string file_type;
switch (dirent.m_file_type)
{
- case 0x80:
+ case FILE_TYPE_DEL:
file_type = "DEL";
break;
- case 0x81:
+ case FILE_TYPE_SEQ:
file_type = "SEQ";
break;
- case 0x82:
+ case FILE_TYPE_PRG:
file_type = "PRG";
break;
- case 0x83:
+ case FILE_TYPE_USR:
file_type = "USR";
break;
- case 0x84:
+ case FILE_TYPE_REL:
file_type = "REL";
break;
default:
@@ -409,6 +750,8 @@ impl::block_iterator::block_iterator(const impl &fs, u8 first_track, u8 first_se
: m_fs(fs)
, m_track(first_track)
, m_sector(first_sector)
+ , m_next_track(first_track)
+ , m_next_sector(first_sector)
{
}
@@ -420,19 +763,21 @@ impl::block_iterator::block_iterator(const impl &fs, u8 first_track, u8 first_se
bool impl::block_iterator::next()
{
bool result;
- if (m_track != 0x00)
+ m_track = m_next_track;
+ m_sector = m_next_sector;
+ if (m_track != CHAIN_END)
{
// check for the degenerate scenario where we have a cycle (this should not happen
// on a non-corrupt disk)
- auto visited_tuple = std::make_tuple(m_track, m_sector);
+ auto visited_tuple = std::make_tuple(m_next_track, m_next_sector);
if (m_visited_set.find(visited_tuple) != m_visited_set.end())
return false;
m_visited_set.insert(visited_tuple);
// with that out of the way, proceed
- m_block = m_fs.read_sector(m_track, m_sector);
- m_track = m_block.r8(0);
- m_sector = m_block.r8(1);
+ m_block = m_fs.read_sector(m_next_track, m_next_sector);
+ m_next_track = m_block->r8(OFFSET_CHAIN_TRACK);
+ m_next_sector = m_block->r8(OFFSET_CHAIN_SECTOR);
result = true;
}
else
@@ -450,7 +795,7 @@ bool impl::block_iterator::next()
const void *impl::block_iterator::data() const
{
- return m_block.rodata() + 2;
+ return m_block->rodata() + 2;
}
@@ -458,9 +803,9 @@ const void *impl::block_iterator::data() const
// impl::block_iterator::dirent_data
//-------------------------------------------------
-const std::array<impl::cbmdos_dirent, 4> &impl::block_iterator::dirent_data() const
+const std::array<impl::cbmdos_dirent, impl::SECTOR_DIRECTORY_COUNT> &impl::block_iterator::dirent_data() const
{
- return *reinterpret_cast<const std::array<impl::cbmdos_dirent, 4> *>(m_block.rodata());
+ return *reinterpret_cast<const std::array<impl::cbmdos_dirent, SECTOR_DIRECTORY_COUNT> *>(m_block->rodata());
}
@@ -470,7 +815,7 @@ const std::array<impl::cbmdos_dirent, 4> &impl::block_iterator::dirent_data() co
u8 impl::block_iterator::size() const
{
- return m_track != 0x00 ? 254 : m_sector - 1;
+ return (m_track != CHAIN_END) ? SECTOR_DATA_BYTES : (m_sector - 1);
}
} // anonymous namespace
diff --git a/src/lib/formats/fs_coco_os9.cpp b/src/lib/formats/fs_coco_os9.cpp
index f8a14c7acdd..8e9d9e8c8d0 100644
--- a/src/lib/formats/fs_coco_os9.cpp
+++ b/src/lib/formats/fs_coco_os9.cpp
@@ -39,23 +39,23 @@ public:
class volume_header
{
public:
- volume_header(fsblk_t::block_t &&block);
+ volume_header(fsblk_t::block_t::ptr &&block);
volume_header(const volume_header &) = delete;
volume_header(volume_header &&) = default;
- u32 total_sectors() const { return m_block.r24b(0); }
- u8 track_size_in_sectors() const { return m_block.r8(3); }
- u16 allocation_bitmap_bytes() const { return m_block.r16b(4); }
- u16 cluster_size() const { return m_block.r16b(6); }
- u32 root_dir_lsn() const { return m_block.r24b(8); }
- u16 owner_id() const { return m_block.r16b(11); }
- u16 disk_id() const { return m_block.r16b(14); }
- u8 format_flags() const { return m_block.r8(16); }
- u16 sectors_per_track() const { return m_block.r16b(17); }
- u32 bootstrap_lsn() const { return m_block.r24b(21); }
- u16 bootstrap_size() const { return m_block.r16b(24); }
- util::arbitrary_datetime creation_date() const { return from_os9_date(m_block.r24b(26), m_block.r16b(29)); }
- u16 sector_size() const { u16 result = m_block.r16b(104); return result != 0 ? result : 256; }
+ u32 total_sectors() const { return m_block->r24b(0); }
+ u8 track_size_in_sectors() const { return m_block->r8(3); }
+ u16 allocation_bitmap_bytes() const { return m_block->r16b(4); }
+ u16 cluster_size() const { return m_block->r16b(6); }
+ u32 root_dir_lsn() const { return m_block->r24b(8); }
+ u16 owner_id() const { return m_block->r16b(11); }
+ u16 disk_id() const { return m_block->r16b(14); }
+ u8 format_flags() const { return m_block->r8(16); }
+ u16 sectors_per_track() const { return m_block->r16b(17); }
+ u32 bootstrap_lsn() const { return m_block->r24b(21); }
+ u16 bootstrap_size() const { return m_block->r16b(24); }
+ util::arbitrary_datetime creation_date() const { return from_os9_date(m_block->r24b(26), m_block->r16b(29)); }
+ u16 sector_size() const { u16 result = m_block->r16b(104); return result != 0 ? result : 256; }
u8 sides() const { return (format_flags() & 0x01) ? 2 : 1; }
bool double_density() const { return (format_flags() & 0x02) != 0; }
bool double_track() const { return (format_flags() & 0x04) != 0; }
@@ -65,7 +65,7 @@ public:
std::string name() const;
private:
- fsblk_t::block_t m_block;
+ fsblk_t::block_t::ptr m_block;
};
@@ -74,17 +74,17 @@ public:
class file_header
{
public:
- file_header(fsblk_t::block_t &&block, std::string &&filename);
+ file_header(fsblk_t::block_t::ptr &&block, std::string &&filename);
file_header(const file_header &) = delete;
file_header(file_header &&) = default;
file_header &operator=(const file_header &) = delete;
file_header &operator=(file_header &&) = default;
- u8 attributes() const { return m_block.r8(0); }
- u16 owner_id() const { return m_block.r16b(1); }
- u8 link_count() const { return m_block.r8(8); }
- u32 file_size() const { return m_block.r32b(9); }
+ u8 attributes() const { return m_block->r8(0); }
+ u16 owner_id() const { return m_block->r16b(1); }
+ u8 link_count() const { return m_block->r8(8); }
+ u32 file_size() const { return m_block->r32b(9); }
util::arbitrary_datetime creation_date() const;
bool is_directory() const { return (attributes() & 0x80) != 0; }
bool is_non_sharable() const { return (attributes() & 0x40) != 0; }
@@ -100,8 +100,8 @@ public:
void get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const;
private:
- fsblk_t::block_t m_block;
- std::string m_filename;
+ fsblk_t::block_t::ptr m_block;
+ std::string m_filename;
};
// ctor/dtor
@@ -109,10 +109,10 @@ public:
virtual ~coco_os9_impl() = default;
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition format(const meta_data &meta) override;
std::optional<file_header> find(const std::vector<std::string> &path, std::optional<dir_entry_type> expected_entry_type) const;
void iterate_directory_entries(const file_header &header, const std::function<bool(std::string &&, u32)> callback) const;
@@ -301,14 +301,14 @@ meta_data coco_os9_impl::volume_metadata()
// coco_os9_impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> coco_os9_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> coco_os9_impl::metadata(const std::vector<std::string> &path)
{
// look up the path
std::optional<file_header> header = find(path, { });
if (!header)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, header->metadata());
+ return std::make_pair(std::error_condition(), header->metadata());
}
@@ -316,12 +316,12 @@ std::pair<err_t, meta_data> coco_os9_impl::metadata(const std::vector<std::strin
// coco_os9_impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> coco_os9_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> coco_os9_impl::directory_contents(const std::vector<std::string> &path)
{
// look up the path
std::optional<file_header> header = find(path, dir_entry_type::dir);
if (!header)
- return std::make_pair(ERR_NOT_FOUND, std::vector<dir_entry>());
+ return std::make_pair(error::not_found, std::vector<dir_entry>());
// iterate through the directory
std::vector<dir_entry> results;
@@ -337,7 +337,7 @@ std::pair<err_t, std::vector<dir_entry>> coco_os9_impl::directory_contents(const
iterate_directory_entries(*header, callback);
// and we're done
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -345,15 +345,15 @@ std::pair<err_t, std::vector<dir_entry>> coco_os9_impl::directory_contents(const
// coco_os9_impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> coco_os9_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> coco_os9_impl::file_read(const std::vector<std::string> &path)
{
// look up the path
std::optional<file_header> header = find(path, dir_entry_type::file);
if (!header)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
std::vector<u8> data = read_file_data(*header);
- return std::make_pair(ERR_OK, std::move(data));
+ return std::make_pair(std::error_condition(), std::move(data));
}
@@ -361,10 +361,10 @@ std::pair<err_t, std::vector<u8>> coco_os9_impl::file_read(const std::vector<std
// coco_os9_impl::format
//-------------------------------------------------
-err_t coco_os9_impl::format(const meta_data &meta)
+std::error_condition coco_os9_impl::format(const meta_data &meta)
{
// for some reason, the OS-9 world favored filling with 0xE5
- m_blockdev.fill(0xE5);
+ m_blockdev.fill_all(0xe5);
// identify geometry info
u8 sectors = 18; // TODO - we need a definitive technique to get the floppy geometry
@@ -390,33 +390,33 @@ err_t coco_os9_impl::format(const meta_data &meta)
// volume header
auto volume_header = m_blockdev.get(0);
- volume_header.fill(0x00);
- volume_header.w24b(0, lsn_count); // DD.TOT - total secctors
- volume_header.w8(3, sectors); // DD.TKS - track size in sectors
- volume_header.w16b(4, (allocation_bitmap_bits + 7) / 8); // DD.MAP - allocation bitmap in bytes
- volume_header.w16b(6, cluster_size); // DD.BIT - cluster size
- volume_header.w24b(8, 1 + allocation_bitmap_lsns); // DD.DIR - root directory LSN
- volume_header.w16b(11, owner_id); // DD.OWN - owner ID
- volume_header.w8(13, attributes); // DD.ATT - Dattributes
- volume_header.w16b(14, disk_id); // DD.DSK - disk ID
- volume_header.w8(16, format_flags); // DD.FMT - format flags
- volume_header.w16b(17, sectors); // DD.SPT - sectors per track
- volume_header.w24b(26, creation_os9date); // DD.DAT - date of creation
- volume_header.w16b(29, creation_os9time); // DD.DAT - time of creation
- volume_header.wstr(31, to_os9_string(volume_title, 32)); // DD.NAM - title
- volume_header.w16b(103, sector_bytes / 256); // sector bytes
+ volume_header->fill(0x00);
+ volume_header->w24b(0, lsn_count); // DD.TOT - total secctors
+ volume_header->w8(3, sectors); // DD.TKS - track size in sectors
+ volume_header->w16b(4, (allocation_bitmap_bits + 7) / 8); // DD.MAP - allocation bitmap in bytes
+ volume_header->w16b(6, cluster_size); // DD.BIT - cluster size
+ volume_header->w24b(8, 1 + allocation_bitmap_lsns); // DD.DIR - root directory LSN
+ volume_header->w16b(11, owner_id); // DD.OWN - owner ID
+ volume_header->w8(13, attributes); // DD.ATT - Dattributes
+ volume_header->w16b(14, disk_id); // DD.DSK - disk ID
+ volume_header->w8(16, format_flags); // DD.FMT - format flags
+ volume_header->w16b(17, sectors); // DD.SPT - sectors per track
+ volume_header->w24b(26, creation_os9date); // DD.DAT - date of creation
+ volume_header->w16b(29, creation_os9time); // DD.DAT - time of creation
+ volume_header->wstr(31, to_os9_string(volume_title, 32)); // DD.NAM - title
+ volume_header->w16b(103, sector_bytes / 256); // sector bytes
// path descriptor options
- volume_header.w8(0x3f + 0x00, 1); // device class
- volume_header.w8(0x3f + 0x01, 1); // drive number
- volume_header.w8(0x3f + 0x03, 0x20); // device type
- volume_header.w8(0x3f + 0x04, 1); // density capability
- volume_header.w16b(0x3f + 0x05, tracks); // number of tracks
- volume_header.w8(0x3f + 0x07, heads); // number of sides
- volume_header.w16b(0x3f + 0x09, sectors); // sectors per track
- volume_header.w16b(0x3f + 0x0b, sectors); // sectors on track zero
- volume_header.w8(0x3f + 0x0d, 3); // sector interleave factor
- volume_header.w8(0x3f + 0x0e, 8); // default sectors per allocation
+ volume_header->w8(0x3f + 0x00, 1); // device class
+ volume_header->w8(0x3f + 0x01, 1); // drive number
+ volume_header->w8(0x3f + 0x03, 0x20); // device type
+ volume_header->w8(0x3f + 0x04, 1); // density capability
+ volume_header->w16b(0x3f + 0x05, tracks); // number of tracks
+ volume_header->w8(0x3f + 0x07, heads); // number of sides
+ volume_header->w16b(0x3f + 0x09, sectors); // sectors per track
+ volume_header->w16b(0x3f + 0x0b, sectors); // sectors on track zero
+ volume_header->w8(0x3f + 0x0d, 3); // sector interleave factor
+ volume_header->w8(0x3f + 0x0e, 8); // default sectors per allocation
// allocation bitmap
u32 total_allocated_sectors = 1 + allocation_bitmap_lsns + 1 + 8;
@@ -428,7 +428,7 @@ err_t coco_os9_impl::format(const meta_data &meta)
{
u32 pos = (i * sector_bytes + j) * 8;
if (pos + 8 < total_allocated_sectors)
- abblk_bytes[j] = 0xFF;
+ abblk_bytes[j] = 0xff;
else if (pos >= total_allocated_sectors)
abblk_bytes[j] = 0x00;
else
@@ -436,35 +436,35 @@ err_t coco_os9_impl::format(const meta_data &meta)
}
auto abblk = m_blockdev.get(1 + i);
- abblk.copy(0, abblk_bytes.data(), sector_bytes);
+ abblk->write(0, abblk_bytes.data(), sector_bytes);
}
// root directory header
auto roothdr_blk = m_blockdev.get(1 + allocation_bitmap_lsns);
- roothdr_blk.fill(0x00);
- roothdr_blk.w8(0x00, 0xBF);
- roothdr_blk.w8(0x01, 0x00);
- roothdr_blk.w8(0x02, 0x00);
- roothdr_blk.w24b(0x03, creation_os9date);
- roothdr_blk.w16b(0x06, creation_os9time);
- roothdr_blk.w8(0x08, 0x01);
- roothdr_blk.w8(0x09, 0x00);
- roothdr_blk.w8(0x0A, 0x00);
- roothdr_blk.w8(0x0B, 0x00);
- roothdr_blk.w8(0x0C, 0x40);
- roothdr_blk.w24b(0x0D, creation_os9date);
- roothdr_blk.w24b(0x10, 1 + allocation_bitmap_lsns + 1);
- roothdr_blk.w16b(0x13, 8);
+ roothdr_blk->fill(0x00);
+ roothdr_blk->w8(0x00, 0xbf);
+ roothdr_blk->w8(0x01, 0x00);
+ roothdr_blk->w8(0x02, 0x00);
+ roothdr_blk->w24b(0x03, creation_os9date);
+ roothdr_blk->w16b(0x06, creation_os9time);
+ roothdr_blk->w8(0x08, 0x01);
+ roothdr_blk->w8(0x09, 0x00);
+ roothdr_blk->w8(0x0a, 0x00);
+ roothdr_blk->w8(0x0b, 0x00);
+ roothdr_blk->w8(0x0c, 0x40);
+ roothdr_blk->w24b(0x0d, creation_os9date);
+ roothdr_blk->w24b(0x10, 1 + allocation_bitmap_lsns + 1);
+ roothdr_blk->w16b(0x13, 8);
// root directory data
auto rootdata_blk = m_blockdev.get(1 + allocation_bitmap_lsns + 1);
- rootdata_blk.fill(0x00);
- rootdata_blk.w8(0x00, 0x2E);
- rootdata_blk.w8(0x01, 0xAE);
- rootdata_blk.w8(0x1F, 1 + allocation_bitmap_lsns);
- rootdata_blk.w8(0x20, 0xAE);
- rootdata_blk.w8(0x3F, 1 + allocation_bitmap_lsns);
- return ERR_OK;
+ rootdata_blk->fill(0x00);
+ rootdata_blk->w8(0x00, 0x2e);
+ rootdata_blk->w8(0x01, 0xae);
+ rootdata_blk->w8(0x1f, 1 + allocation_bitmap_lsns);
+ rootdata_blk->w8(0x20, 0xae);
+ rootdata_blk->w8(0x3f, 1 + allocation_bitmap_lsns);
+ return std::error_condition();
}
@@ -554,9 +554,9 @@ std::vector<u8> coco_os9_impl::read_file_data(const file_header &header) const
for (u32 lsn = start_lsn; lsn < start_lsn + count; lsn++)
{
auto block = m_blockdev.get(lsn);
- size_t block_size = std::min(std::min(u32(m_volume_header.sector_size()), block.size()), header.file_size() - u32(data.size()));
+ size_t block_size = std::min(std::min(u32(m_volume_header.sector_size()), block->size()), header.file_size() - u32(data.size()));
for (auto i = 0; i < block_size; i++)
- data.push_back(block.rodata()[i]);
+ data.push_back(block->rodata()[i]);
}
}
return data;
@@ -580,7 +580,7 @@ std::string coco_os9_impl::pick_os9_string(std::string_view raw_string)
// and add the final character if we have to
if (iter < raw_string.end() && *iter & 0x80)
- result.append(1, *iter & 0x7F);
+ result.append(1, *iter & 0x7f);
return result;
}
@@ -595,7 +595,7 @@ std::string coco_os9_impl::to_os9_string(std::string_view s, size_t length)
std::string result(length, '\0');
for (auto i = 0; i < std::min(length, s.size()); i++)
{
- result[i] = (s[i] & 0x7F)
+ result[i] = (s[i] & 0x7f)
| (i == s.size() ? 0x80 : 0x00);
}
return result;
@@ -610,11 +610,11 @@ util::arbitrary_datetime coco_os9_impl::from_os9_date(u32 os9_date, u16 os9_time
{
util::arbitrary_datetime dt;
memset(&dt, 0, sizeof(dt));
- dt.year = ((os9_date >> 16) & 0xFF) + 1900;
- dt.month = (os9_date >> 8) & 0xFF;
- dt.day_of_month = (os9_date >> 0) & 0xFF;
- dt.hour = (os9_time >> 8) & 0xFF;
- dt.minute = (os9_time >> 0) & 0xFF;
+ dt.year = ((os9_date >> 16) & 0xff) + 1900;
+ dt.month = (os9_date >> 8) & 0xff;
+ dt.day_of_month = (os9_date >> 0) & 0xff;
+ dt.hour = (os9_time >> 8) & 0xff;
+ dt.minute = (os9_time >> 0) & 0xff;
return dt;
}
@@ -625,11 +625,11 @@ util::arbitrary_datetime coco_os9_impl::from_os9_date(u32 os9_date, u16 os9_time
std::tuple<u32, u16> coco_os9_impl::to_os9_date(const util::arbitrary_datetime &datetime)
{
- u32 os9_date = ((datetime.year - 1900) & 0xFF) << 16
- | (datetime.month & 0xFF) << 8
- | (datetime.day_of_month & 0xFF) << 0;
- u16 os9_time = (datetime.hour & 0xFF) << 8
- | (datetime.minute & 0xFF) << 0;
+ u32 os9_date = ((datetime.year - 1900) & 0xff) << 16
+ | (datetime.month & 0xff) << 8
+ | (datetime.day_of_month & 0xff) << 0;
+ u16 os9_time = (datetime.hour & 0xff) << 8
+ | (datetime.minute & 0xff) << 0;
return std::make_tuple(os9_date, os9_time);
}
@@ -664,7 +664,7 @@ bool coco_os9_impl::is_ignored_filename(std::string_view name)
// volume_header ctor
//-------------------------------------------------
-coco_os9_impl::volume_header::volume_header(fsblk_t::block_t &&block)
+coco_os9_impl::volume_header::volume_header(fsblk_t::block_t::ptr &&block)
: m_block(std::move(block))
{
}
@@ -676,7 +676,7 @@ coco_os9_impl::volume_header::volume_header(fsblk_t::block_t &&block)
std::string coco_os9_impl::volume_header::name() const
{
- std::string_view raw_name((const char *)&m_block.rodata()[31], 32);
+ std::string_view raw_name(m_block->rstr(31, 32));
return pick_os9_string(raw_name);
}
@@ -685,7 +685,7 @@ std::string coco_os9_impl::volume_header::name() const
// file_header ctor
//-------------------------------------------------
-coco_os9_impl::file_header::file_header(fsblk_t::block_t &&block, std::string &&filename)
+coco_os9_impl::file_header::file_header(fsblk_t::block_t::ptr &&block, std::string &&filename)
: m_block(std::move(block))
, m_filename(std::move(filename))
{
@@ -698,7 +698,7 @@ coco_os9_impl::file_header::file_header(fsblk_t::block_t &&block, std::string &&
util::arbitrary_datetime coco_os9_impl::file_header::creation_date() const
{
- return from_os9_date(m_block.r24b(13));
+ return from_os9_date(m_block->r24b(13));
}
@@ -735,7 +735,7 @@ meta_data coco_os9_impl::file_header::metadata() const
int coco_os9_impl::file_header::get_sector_map_entry_count() const
{
- return (m_block.size() - 16) / 5;
+ return (m_block->size() - 16) / 5;
}
@@ -745,6 +745,6 @@ int coco_os9_impl::file_header::get_sector_map_entry_count() const
void coco_os9_impl::file_header::get_sector_map_entry(int entry_number, u32 &start_lsn, u16 &count) const
{
- start_lsn = m_block.r24b(16 + (entry_number * 5) + 0);
- count = m_block.r16b(16 + (entry_number * 5) + 3);
+ start_lsn = m_block->r24b(16 + (entry_number * 5) + 0);
+ count = m_block->r16b(16 + (entry_number * 5) + 3);
}
diff --git a/src/lib/formats/fs_coco_rsdos.cpp b/src/lib/formats/fs_coco_rsdos.cpp
index 76b737d9011..0ce88cf01df 100644
--- a/src/lib/formats/fs_coco_rsdos.cpp
+++ b/src/lib/formats/fs_coco_rsdos.cpp
@@ -1,11 +1,14 @@
// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
+// copyright-holders:Nathan Woods, Wilbert Pol
/***************************************************************************
fs_coco_rsdos.cpp
Management of CoCo "RS-DOS" floppy images
+Limitation:
+- The determination of the file type is very limited.
+
***************************************************************************/
#include "fs_coco_rsdos.h"
@@ -16,6 +19,7 @@
#include <bitset>
#include <optional>
+#include <regex>
#include <string_view>
using namespace fs;
@@ -30,6 +34,8 @@ public:
coco_rsdos_impl(fsblk_t &blockdev);
virtual ~coco_rsdos_impl() = default;
+ static constexpr int SECTOR_DIRECTORY_ENTRY_COUNT = 8;
+
struct rsdos_dirent
{
char m_filename[11];
@@ -46,7 +52,7 @@ public:
{
rsdos_dirent m_dirent;
u8 m_unused[16];
- } m_entries[8];
+ } m_entries[SECTOR_DIRECTORY_ENTRY_COUNT];
};
class granule_iterator
@@ -56,27 +62,54 @@ public:
bool next(u8 &granule, u16 &byte_count);
private:
- fsblk_t::block_t m_granule_map;
- std::optional<u8> m_current_granule;
- u8 m_maximum_granules;
- u16 m_last_sector_bytes;
- std::bitset<256> m_visited_granules;
+ fsblk_t::block_t::ptr m_granule_map;
+ std::optional<u8> m_current_granule;
+ u8 m_maximum_granules;
+ u16 m_last_sector_bytes;
+ std::bitset<256> m_visited_granules;
};
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition format(const meta_data &meta) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
static bool validate_filename(std::string_view name);
private:
- fsblk_t::block_t read_sector(int track, int sector) const;
+ static constexpr u8 TRACK_GRANULE_COUNT = 2;
+ static constexpr u8 GRANULE_SECTOR_COUNT = 9;
+ static constexpr u8 TRACK_SECTOR_COUNT = TRACK_GRANULE_COUNT * GRANULE_SECTOR_COUNT;
+ static constexpr u8 DIRECTORY_TRACK = 17;
+ static constexpr u8 DIRECTORY_ENTRY_SIZE = 0x20;
+ static constexpr u8 FNAME_LENGTH = 11;
+ static constexpr u16 SECTOR_SIZE = 0x100;
+ static constexpr u8 OFFSET_FILE_TYPE = 0x0b;
+ static constexpr u8 OFFSET_ASCII_FLAG = 0x0c;
+ static constexpr u8 OFFSET_FIRST_GRANULE = 0x0d;
+ static constexpr u8 OFFSET_LAST_SECTOR_BYTES = 0x0e;
+ static constexpr u8 FILE_TYPE_BASIC = 0x00;
+ static constexpr u8 FILE_TYPE_BASIC_DATA = 0x01;
+ static constexpr u8 FILE_TYPE_MACHINE_CODE = 0x02;
+ static constexpr u8 FILE_TYPE_TEXT_EDITOR = 0x03;
+ static constexpr u8 FILE_LAST_GRANULE_INDICATOR = 0xc0;
+
+ fsblk_t::block_t::ptr read_sector(int track, int sector) const;
+ fsblk_t::block_t::ptr read_granule_sector(u8 granule, u8 sector) const;
u8 maximum_granules() const;
std::optional<rsdos_dirent> dirent_from_path(const std::vector<std::string> &path);
- void iterate_directory_entries(const std::function<bool(const rsdos_dirent &dirent)> &callback);
+ template <typename T>
+ void iterate_directory_entries(T &&callback);
meta_data get_metadata_from_dirent(const rsdos_dirent &dirent);
static std::string get_filename_from_dirent(const rsdos_dirent &dirent);
+ std::pair<std::error_condition, std::string> build_direntry_filename(const std::string &filename);
+ std::pair<std::error_condition, u8> claim_granule();
+ void write_granule_map(u8 granule, u8 map_data);
+ u8 read_granule_map(u8 granule) const;
+ bool is_ascii(const std::vector<u8> &data) const;
+ u8 determine_file_type(const std::vector<u8> &data) const;
};
} // anonymous namespace
@@ -139,7 +172,7 @@ bool coco_rsdos_image::can_read() const
bool coco_rsdos_image::can_write() const
{
- return false;
+ return true;
}
@@ -197,7 +230,7 @@ bool coco_rsdos_impl::validate_filename(std::string_view name)
//-------------------------------------------------
coco_rsdos_impl::coco_rsdos_impl(fsblk_t &blockdev)
- : filesystem_t(blockdev, 256)
+ : filesystem_t(blockdev, SECTOR_SIZE)
{
}
@@ -206,14 +239,14 @@ coco_rsdos_impl::coco_rsdos_impl(fsblk_t &blockdev)
// coco_rsdos_impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> coco_rsdos_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> coco_rsdos_impl::metadata(const std::vector<std::string> &path)
{
// attempt to find the file
const std::optional<rsdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, get_metadata_from_dirent(*dirent));
+ return std::make_pair(std::error_condition(), get_metadata_from_dirent(*dirent));
}
@@ -221,16 +254,16 @@ std::pair<err_t, meta_data> coco_rsdos_impl::metadata(const std::vector<std::str
// coco_rsdos_impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> coco_rsdos_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> coco_rsdos_impl::directory_contents(const std::vector<std::string> &path)
{
std::vector<dir_entry> results;
- auto callback = [this, &results](const rsdos_dirent &dirent)
+ auto const callback = [this, &results](u8 s, u8 i, const rsdos_dirent &dirent)
{
results.emplace_back(dir_entry_type::file, get_metadata_from_dirent(dirent));
return false;
};
iterate_directory_entries(callback);
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -238,12 +271,12 @@ std::pair<err_t, std::vector<dir_entry>> coco_rsdos_impl::directory_contents(con
// coco_rsdos_impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> coco_rsdos_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> coco_rsdos_impl::file_read(const std::vector<std::string> &path)
{
// attempt to find the file
const std::optional<rsdos_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
std::vector<u8> result;
u8 granule;
@@ -264,11 +297,10 @@ std::pair<err_t, std::vector<u8>> coco_rsdos_impl::file_read(const std::vector<s
{
// read this sector
auto block = read_sector(track, sector);
- const u8 *data = block.rodata();
- u16 data_length = std::min(byte_count, u16(256));
+ u16 data_length = std::min(byte_count, u16(SECTOR_SIZE));
// and append it to the results
- memcpy(result.data() + current_size, data, data_length);
+ block->read(0, result.data() + current_size, data_length);
// and advance
current_size += data_length;
@@ -276,7 +308,7 @@ std::pair<err_t, std::vector<u8>> coco_rsdos_impl::file_read(const std::vector<s
sector++;
}
}
- return std::make_pair(ERR_OK, std::move(result));
+ return std::make_pair(std::error_condition(), std::move(result));
}
@@ -284,23 +316,248 @@ std::pair<err_t, std::vector<u8>> coco_rsdos_impl::file_read(const std::vector<s
// coco_rsdos_impl::format
//-------------------------------------------------
-err_t coco_rsdos_impl::format(const meta_data &meta)
+std::error_condition coco_rsdos_impl::format(const meta_data &meta)
{
// formatting RS-DOS is easy - just fill everything with 0xFF
- m_blockdev.fill(0xFF);
- return ERR_OK;
+ m_blockdev.fill_all(0xFF);
+ return std::error_condition();
+}
+
+
+std::pair<std::error_condition, std::string> coco_rsdos_impl::build_direntry_filename(const std::string &filename)
+{
+ // The manual does not say anything about valid characters for a file name.
+ const std::regex filename_regex("([^.]{0,8})(\\.([^.]{0,3}))?");
+ std::smatch smatch;
+ if (!std::regex_match(filename, smatch, filename_regex))
+ return std::make_pair(error::invalid_name, std::string());
+ if (smatch.size() != 4)
+ return std::make_pair(error::invalid_name, std::string());
+
+ std::string fname;
+ fname.resize(FNAME_LENGTH, ' ');
+
+ for (int i = 0; i < 8 && i < smatch.str(1).size(); i++)
+ fname[i] = smatch.str(1)[i];
+
+ for (int j = 0; j < 3 && j < smatch.str(3).size(); j++)
+ fname[8 + j] = smatch.str(3)[j];
+
+ return std::make_pair(std::error_condition(), std::move(fname));
+}
+
+
+std::error_condition coco_rsdos_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+{
+ if (!path.empty())
+ return error::unsupported;
+
+ const std::string filename = meta.get_string(meta_name::name, "");
+ auto [err, fname] = build_direntry_filename(filename);
+ if (err)
+ return err;
+
+ bool found_entry = false;
+ u8 dir_sector = 0;
+ u8 file_index = 0;
+ for (dir_sector = 3; !found_entry && dir_sector <= TRACK_SECTOR_COUNT; dir_sector++)
+ {
+ auto dir_block = read_sector(DIRECTORY_TRACK, dir_sector);
+
+ for (file_index = 0; !found_entry && file_index < SECTOR_DIRECTORY_ENTRY_COUNT; file_index++)
+ {
+ const u8 first_byte = dir_block->r8(file_index * DIRECTORY_ENTRY_SIZE);
+ // 0xff marks the end of the directory, 0x00 marks a deleted file
+ found_entry = (first_byte == 0xff || first_byte == 0x00);
+ if (found_entry)
+ {
+ for (int i = 0; i < DIRECTORY_ENTRY_SIZE; i++)
+ dir_block->w8(file_index * DIRECTORY_ENTRY_SIZE + i, 0);
+
+ auto [cerr, granule] = claim_granule();
+ if (cerr != std::error_condition())
+ return cerr;
+
+ dir_block->wstr(file_index * DIRECTORY_ENTRY_SIZE + 0, fname);
+ dir_block->w8(file_index * DIRECTORY_ENTRY_SIZE + OFFSET_FIRST_GRANULE, granule);
+ // The file type, ASCII flag, and number of bytes in last sector of file will be set during writing.
+ }
+ }
+ }
+ if (!found_entry)
+ return error::no_space;
+
+ return std::error_condition();
+}
+
+
+std::error_condition coco_rsdos_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+{
+ if (path.size() != 1)
+ return error::not_found;
+ const std::string &target = path[0];
+
+ std::optional<rsdos_dirent> result;
+ u8 dir_sector = 0;
+ u8 dir_file_index = 0;
+ auto const callback = [&result, &target, &dir_sector, &dir_file_index](u8 s, u8 i, const rsdos_dirent &dirent)
+ {
+ const bool found = get_filename_from_dirent(dirent) == target;
+ if (found)
+ {
+ result = dirent;
+ dir_sector = s;
+ dir_file_index = i;
+ }
+ return found;
+ };
+ iterate_directory_entries(callback);
+
+ if (!result)
+ return error::not_found;
+
+ const size_t data_length = data.size();
+ const u8 max_granule = maximum_granules();
+ u8 granule = result->m_first_granule;
+ u8 granule_sector = 1;
+ size_t offset = 0;
+ u16 bytes_in_last_sector = 0;
+ u8 linked_granule = read_granule_map(granule);
+
+ while (offset < data_length)
+ {
+ auto data_block = read_granule_sector(granule, granule_sector);
+ bytes_in_last_sector = (data_length - offset) > SECTOR_SIZE ? SECTOR_SIZE : data_length - offset;
+ data_block->write(0, data.data() + offset, bytes_in_last_sector);
+ offset += SECTOR_SIZE;
+ write_granule_map(granule, FILE_LAST_GRANULE_INDICATOR + granule_sector);
+ if (offset < data_length)
+ {
+ granule_sector++;
+ if (granule_sector > GRANULE_SECTOR_COUNT)
+ {
+ // Re-use linked granule or claim a new granule
+ if (linked_granule < max_granule)
+ {
+ granule = linked_granule;
+ linked_granule = read_granule_map(linked_granule);
+ }
+ else
+ {
+ auto [err, next_granule] = claim_granule();
+ if (err)
+ return err;
+ write_granule_map(granule, next_granule);
+ granule = next_granule;
+ }
+ granule_sector = 1;
+ }
+ }
+ }
+
+ // Free unused space
+ while (linked_granule < max_granule)
+ {
+ const u8 granule_to_free = linked_granule;
+ linked_granule = read_granule_map(granule_to_free);
+ write_granule_map(granule_to_free, 0xff);
+ }
+
+ // Update directory entry
+ auto dir_block = read_sector(DIRECTORY_TRACK, dir_sector);
+ dir_block->w8(dir_file_index * DIRECTORY_ENTRY_SIZE + OFFSET_FILE_TYPE, determine_file_type(data));
+ dir_block->w8(dir_file_index * DIRECTORY_ENTRY_SIZE + OFFSET_ASCII_FLAG, is_ascii(data) ? 0xff : 0x00);
+ dir_block->w16b(dir_file_index * DIRECTORY_ENTRY_SIZE + OFFSET_LAST_SECTOR_BYTES, bytes_in_last_sector);
+
+ return std::error_condition();
+}
+
+
+bool coco_rsdos_impl::is_ascii(const std::vector<u8> &data) const
+{
+ const size_t data_length = data.size();
+
+ if (data_length == 0)
+ return false;
+
+ for (int i = 0; i < data_length; i++)
+ {
+ if (!(data[i] == 0x0d || data[i] == 0x0a || (data[i] >= 0x20 && data[i] < 0x60)))
+ return false;
+ }
+
+ return true;
+}
+
+
+u8 coco_rsdos_impl::determine_file_type(const std::vector<u8> &data) const
+{
+ if (is_ascii(data))
+ {
+ // TODO: Distinguish between BASIC code and text editor data
+ return FILE_TYPE_BASIC;
+ }
+
+ const size_t data_length = data.size();
+ // Binary BASIC code seems to begin with ff <16bit size> 26
+ if (data_length > 4 && data[0] == 0xff && data[3] == 0x26 && ((data[1] << 8) | data[2]) == data_length - 3)
+ return FILE_TYPE_BASIC;
+
+ // TODO: Distinguish between Machine Code and Basic Data
+
+ return FILE_TYPE_MACHINE_CODE;
+}
+
+
+std::pair<std::error_condition, u8> coco_rsdos_impl::claim_granule()
+{
+ // Granules are likely not assigned in this order on hardware.
+ auto granule_block = read_sector(DIRECTORY_TRACK, 2);
+ for (int g = 0; g < maximum_granules(); g++)
+ {
+ if (granule_block->r8(g) == 0xff)
+ {
+ granule_block->w8(g, FILE_LAST_GRANULE_INDICATOR);
+ return std::make_pair(std::error_condition(), g);
+ }
+ }
+ return std::make_pair(error::no_space, 0);
+}
+
+
+void coco_rsdos_impl::write_granule_map(u8 granule, u8 map_data)
+{
+ auto granule_block = read_sector(DIRECTORY_TRACK, 2);
+ granule_block->w8(granule, map_data);
+}
+
+
+u8 coco_rsdos_impl::read_granule_map(u8 granule) const
+{
+ auto granule_block = read_sector(DIRECTORY_TRACK, 2);
+ return granule_block->r8(granule);
}
//-------------------------------------------------
-// fsblk_t::block_t coco_rsdos_impl::read_sector
+// coco_rsdos_impl::read_sector
//-------------------------------------------------
-fsblk_t::block_t coco_rsdos_impl::read_sector(int track, int sector) const
+fsblk_t::block_t::ptr coco_rsdos_impl::read_sector(int track, int sector) const
{
// the CoCo RS-DOS world thinks in terms of tracks/sectors, but we have a block device
// abstraction
- return m_blockdev.get(track * 18 + sector - 1);
+ return m_blockdev.get(track * TRACK_SECTOR_COUNT + sector - 1);
+}
+
+
+fsblk_t::block_t::ptr coco_rsdos_impl::read_granule_sector(u8 granule, u8 sector) const
+{
+ // Track 17 does not hold granules
+ if (granule < (DIRECTORY_TRACK * TRACK_GRANULE_COUNT))
+ return m_blockdev.get(granule * GRANULE_SECTOR_COUNT + sector - 1);
+ else
+ return m_blockdev.get((granule + TRACK_GRANULE_COUNT) * GRANULE_SECTOR_COUNT + sector - 1);
}
@@ -311,7 +568,7 @@ fsblk_t::block_t coco_rsdos_impl::read_sector(int track, int sector) const
u8 coco_rsdos_impl::maximum_granules() const
{
u32 sector_count = m_blockdev.block_count();
- u32 granule_count = (sector_count / 9) - 2;
+ u32 granule_count = (sector_count / GRANULE_SECTOR_COUNT) - 2;
return granule_count <= 0xFF ? u8(granule_count) : 0xFF;
}
@@ -327,7 +584,7 @@ std::optional<coco_rsdos_impl::rsdos_dirent> coco_rsdos_impl::dirent_from_path(c
const std::string &target = path[0];
std::optional<rsdos_dirent> result;
- auto callback = [&result, &target](const rsdos_dirent &dirent)
+ auto const callback = [&result, &target](u8 s, u8 i, const rsdos_dirent &dirent)
{
bool found = get_filename_from_dirent(dirent) == target;
if (found)
@@ -343,28 +600,29 @@ std::optional<coco_rsdos_impl::rsdos_dirent> coco_rsdos_impl::dirent_from_path(c
// coco_rsdos_impl::iterate_directory_entries
//-------------------------------------------------
-void coco_rsdos_impl::iterate_directory_entries(const std::function<bool(const rsdos_dirent &dirent)> &callback)
+template <typename T>
+void coco_rsdos_impl::iterate_directory_entries(T &&callback)
{
bool done = false;
for (int dir_sector = 3; !done && dir_sector <= 18; dir_sector++)
{
// read this directory sector
- auto dir_block = read_sector(17, dir_sector);
- const rsdos_dirent_sector &sector = *reinterpret_cast<const rsdos_dirent_sector *>(dir_block.rodata());
+ auto dir_block = read_sector(DIRECTORY_TRACK, dir_sector);
+ const rsdos_dirent_sector &sector = *reinterpret_cast<const rsdos_dirent_sector *>(dir_block->rodata());
// and loop through all entries
- for (const auto &ent : sector.m_entries)
+ for (int file_index = 0; file_index < 8; file_index++)
{
// 0xFF marks the end of the directory
- if (ent.m_dirent.m_filename[0] == '\xFF')
+ if (sector.m_entries[file_index].m_dirent.m_filename[0] == '\xFF')
{
done = true;
}
else
{
// 0x00 marks a deleted file
- if (ent.m_dirent.m_filename[0] != '\0')
- done = callback(ent.m_dirent);
+ if (sector.m_entries[file_index].m_dirent.m_filename[0] != '\0')
+ done = callback(dir_sector, 0, sector.m_entries[file_index].m_dirent);
}
if (done)
@@ -427,7 +685,7 @@ std::string coco_rsdos_impl::get_filename_from_dirent(const rsdos_dirent &dirent
//-------------------------------------------------
coco_rsdos_impl::granule_iterator::granule_iterator(coco_rsdos_impl &fs, const rsdos_dirent &dirent)
- : m_granule_map(fs.read_sector(17, 2))
+ : m_granule_map(fs.read_sector(DIRECTORY_TRACK, 2))
, m_current_granule(dirent.m_first_granule)
, m_maximum_granules(fs.maximum_granules())
, m_last_sector_bytes((u16(dirent.m_last_sector_bytes_msb) << 8) | dirent.m_last_sector_bytes_lsb)
@@ -450,13 +708,13 @@ bool coco_rsdos_impl::granule_iterator::next(u8 &granule, u16 &byte_count)
if (m_current_granule)
{
std::optional<u8> next_granule;
- const u8 *granule_map_data = m_granule_map.rodata();
+ const u8 *granule_map_data = m_granule_map->rodata();
if (granule_map_data[*m_current_granule] < m_maximum_granules)
{
// this entry points to the next granule
success = true;
granule = *m_current_granule;
- byte_count = 9 * 256;
+ byte_count = GRANULE_SECTOR_COUNT * SECTOR_SIZE;
next_granule = granule_map_data[*m_current_granule];
// check for cycles, which should only happen if the disk is corrupt (or not in RS-DOS format)
@@ -465,13 +723,13 @@ bool coco_rsdos_impl::granule_iterator::next(u8 &granule, u16 &byte_count)
else
m_visited_granules.set(*next_granule);
}
- else if (granule_map_data[*m_current_granule] >= 0xC0 && granule_map_data[*m_current_granule] <= 0xC9)
+ else if (granule_map_data[*m_current_granule] >= FILE_LAST_GRANULE_INDICATOR && granule_map_data[*m_current_granule] <= FILE_LAST_GRANULE_INDICATOR + GRANULE_SECTOR_COUNT)
{
// this is the last granule in the file
success = true;
granule = *m_current_granule;
u16 sector_count = std::max(granule_map_data[*m_current_granule], u8(0xC1)) - 0xC1;
- byte_count = sector_count * 256 + m_last_sector_bytes;
+ byte_count = sector_count * SECTOR_SIZE + m_last_sector_bytes;
next_granule = std::nullopt;
}
else
diff --git a/src/lib/formats/fs_fat.cpp b/src/lib/formats/fs_fat.cpp
index f4cd99e36ed..8e47bbc5abe 100644
--- a/src/lib/formats/fs_fat.cpp
+++ b/src/lib/formats/fs_fat.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Nathan Woods
+// copyright-holders:Nathan Woods,Wilbert Pol
/***************************************************************************
fs_fat.cpp
@@ -7,11 +7,13 @@
PC FAT disk images
Current Limitations:
- - Read only
- Only supports floppy disks
- No FAT32 support
- No Long Filenames Support
+ Removal of files is untested; floptool does not have a command to delete
+ a file.
+
*****************************************************************************
Master boot record format:
@@ -66,13 +68,13 @@
14 2 Reserved sector count (including boot sector)
16 1 Number of FATs (file allocation tables)
17 2 Number of root directory entries
- 19 2 Total sectors (bits 0-15)
+ 19 2 Total sectors (0 if 0x10000 or more)
21 1 Media descriptor
22 2 Sectors per FAT
24 2 Sectors per track
26 2 Number of heads
28 4 Hidden sectors
- 32 4 Total sectors (bits 16-47)
+ 32 4 Total sectors (0 if less than 0x10000)
36 1 Physical drive number
37 1 Current head
38 1 Signature
@@ -147,6 +149,9 @@
#include "strformat.h"
#include <optional>
+#include <regex>
+#include <string_view>
+
using namespace fs;
@@ -163,41 +168,58 @@ namespace {
class directory_entry
{
public:
- static const int SIZE = 32;
-
- directory_entry(const fsblk_t::block_t &block, u32 offset)
+ static constexpr int SIZE = 32;
+ static constexpr int OFFSET_FNAME = 0;
+ static constexpr int FNAME_LENGTH = 11;
+ static constexpr int OFFSET_ATTRIBUTES = 11;
+ static constexpr int OFFSET_CREATE_DATETIME = 14;
+ static constexpr int OFFSET_START_CLUSTER_HI = 20;
+ static constexpr int OFFSET_MODIFIED_DATETIME = 22;
+ static constexpr int OFFSET_START_CLUSTER = 26;
+ static constexpr int OFFSET_FILE_SIZE = 28;
+ static constexpr u8 DELETED_FILE_MARKER = 0xe5;
+ static constexpr u8 ATTR_READ_ONLY = 0x01;
+ static constexpr u8 ATTR_HIDDEN = 0x02;
+ static constexpr u8 ATTR_SYSTEM = 0x04;
+ static constexpr u8 ATTR_VOLUME_LABEL = 0x08;
+ static constexpr u8 ATTR_DIRECTORY = 0x10;
+ static constexpr u8 ATTR_ARCHIVE = 0x20;
+
+ directory_entry(fsblk_t::block_t::ptr block, u32 offset)
: m_block(block)
, m_offset(offset)
{
}
- std::string_view raw_stem() const { return std::string_view((const char *) &m_block.rodata()[m_offset + 0], 8); }
- std::string_view raw_ext() const { return std::string_view((const char *) &m_block.rodata()[m_offset + 8], 3); }
- u8 attributes() const { return m_block.r8(m_offset + 11); }
- u32 raw_create_datetime() const { return m_block.r32l(m_offset + 14); }
- u32 raw_modified_datetime() const { return m_block.r32l(m_offset + 22); }
- u32 start_cluster() const { return ((u32)m_block.r16l(m_offset + 20)) << 16 | m_block.r16l(m_offset + 26); }
- u32 file_size() const { return m_block.r32l(m_offset + 28); }
+ std::string_view raw_stem() const { return m_block->rstr(m_offset + OFFSET_FNAME, 8); }
+ std::string_view raw_ext() const { return m_block->rstr(m_offset + OFFSET_FNAME + 8, 3); }
+ u8 attributes() const { return m_block->r8(m_offset + OFFSET_ATTRIBUTES); }
+ u32 raw_create_datetime() const { return m_block->r32l(m_offset + OFFSET_CREATE_DATETIME); }
+ u32 raw_modified_datetime() const { return m_block->r32l(m_offset + OFFSET_MODIFIED_DATETIME); }
+ u32 start_cluster() const { return ((u32)m_block->r16l(m_offset + OFFSET_START_CLUSTER_HI)) << 16 | m_block->r16l(m_offset + OFFSET_START_CLUSTER); }
+ u32 file_size() const { return m_block->r32l(m_offset + OFFSET_FILE_SIZE); }
bool is_read_only() const { return (attributes() & 0x01) != 0x00; }
bool is_hidden() const { return (attributes() & 0x02) != 0x00; }
bool is_system() const { return (attributes() & 0x04) != 0x00; }
bool is_volume_label() const { return (attributes() & 0x08) != 0x00; }
+ bool is_long_file_name() const { return attributes() == 0x0f; }
bool is_subdirectory() const { return (attributes() & 0x10) != 0x00; }
bool is_archive() const { return (attributes() & 0x20) != 0x00; }
- bool is_deleted() const { return m_block.r8(m_offset) == DELETED_FILE_MARKER; }
+ bool is_deleted() const { return m_block->r8(m_offset) == DELETED_FILE_MARKER; }
std::string name() const;
meta_data metadata() const;
-private:
- static constexpr u8 DELETED_FILE_MARKER = 0xe5;
+ void set_file_size(u32 file_size) { m_block->w32l(m_offset + OFFSET_FILE_SIZE, file_size); }
+ void set_raw_modified_datetime(u32 datetime) { m_block->w32l(m_offset + OFFSET_MODIFIED_DATETIME, datetime); }
+ void mark_deleted() { m_block->w8(m_offset + OFFSET_FNAME, DELETED_FILE_MARKER); }
- fsblk_t::block_t m_block;
- u32 m_offset;
+private:
+ fsblk_t::block_t::ptr m_block;
+ u32 m_offset;
};
-
// ======================> directory_span
class directory_span
@@ -218,7 +240,7 @@ class impl : public filesystem_t
{
public:
// ctor/dtor
- impl(fsblk_t &blockdev, fsblk_t::block_t &&boot_sector_block, std::vector<u8> &&file_allocation_table, u32 starting_sector, u32 sector_count, u16 reserved_sector_count, u8 bits_per_fat_entry);
+ impl(fsblk_t &blockdev, fsblk_t::block_t::ptr &&boot_sector_block, std::vector<u8> &&file_allocation_table, u32 starting_sector, u32 sector_count, u16 reserved_sector_count, u8 bits_per_fat_entry);
virtual ~impl() = default;
// accessors
@@ -228,27 +250,60 @@ public:
// virtuals
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
+ virtual std::error_condition remove(const std::vector<std::string> &path) override;
// methods
std::vector<u32> get_sectors_from_fat(const directory_entry &dirent) const;
+ // Boot sector settings
+ static constexpr u32 OFFSET_BYTES_PER_SECTOR = 0x0b;
+ static constexpr u32 OFFSET_CLUSTER_SECTOR_COUNT = 0x0d;
+ static constexpr u32 OFFSET_RESERVED_SECTOR_COUNT = 0x0e;
+ static constexpr u32 OFFSET_FAT_COUNT = 0x10;
+ static constexpr u32 OFFSET_DIRECTORY_ENTRY_COUNT = 0x11;
+ static constexpr u32 OFFSET_FAT_SECTOR_COUNT = 0x16;
+
private:
- fsblk_t::block_t m_boot_sector_block;
+ static constexpr u32 FIRST_VALID_CLUSTER = 2;
+
+ fsblk_t::block_t::ptr m_boot_sector_block;
std::vector<u8> m_file_allocation_table;
u32 m_starting_sector;
u32 m_sector_count;
u16 m_reserved_sector_count;
u16 m_bytes_per_sector;
+ u16 m_root_directory_size;
+ u16 m_sectors_per_cluster;
+ u8 m_fat_count;
+ u16 m_fat_sector_count;
u8 m_bits_per_fat_entry;
+ u32 m_last_cluster_indicator;
+ u32 m_last_valid_cluster;
// methods
std::optional<directory_entry> find_entity(const std::vector<std::string> &path) const;
directory_span::ptr find_directory(std::vector<std::string>::const_iterator path_begin, std::vector<std::string>::const_iterator path_end) const;
std::optional<directory_entry> find_child(const directory_span &current_dir, std::string_view target) const;
- void iterate_directory_entries(const directory_span &dir, const std::function<bool(const directory_entry &dirent)> &callback) const;
+ template <typename T> void iterate_directory_entries(const directory_span &dir, T &&callback) const;
+ bool is_valid_short_filename(std::string const &filename);
+ std::error_condition build_direntry_filename(std::string const &filename, std::string &fname);
+ std::error_condition file_create_root(std::string &fname, u8 attributes = 0);
+ std::error_condition file_create_directory(directory_entry &dirent, std::string &fname, u8 attributes = 0);
+ std::error_condition file_create_sector(u32 sector, std::string &fname, u8 attributes);
+ std::error_condition initialize_directory(u32 directory_cluster, u32 parent_cluster);
+ std::error_condition initialize_directory_entry(fsblk_t::block_t &dirblk, u32 offset, std::string_view fname, u8 attributes, u32 start_cluster);
+ std::error_condition free_clusters(u32 start_cluster);
+ void clear_cluster_sectors(u32 cluster, u8 fill_byte);
+ u32 first_cluster_sector(u32 cluster);
+ u32 get_next_cluster(u32 cluster);
+ void set_next_cluster(u32 cluster, u32 next_cluster);
+ u32 find_free_cluster();
+
};
@@ -297,7 +352,7 @@ private:
namespace {
bool validate_filename(std::string_view name)
{
- auto is_invalid_filename_char = [](char ch)
+ auto const is_invalid_filename_char = [] (char ch)
{
return ch == '\0' || strchr("\\/:*?\"<>|", ch);
};
@@ -316,15 +371,27 @@ util::arbitrary_datetime decode_fat_datetime(u32 dt)
util::arbitrary_datetime result;
memset(&result, 0, sizeof(result));
- result.year = ((dt >> 25) & 0x7F) + 1980;
- result.month = (dt >> 21) & 0x0F;
- result.day_of_month = (dt >> 16) & 0x1F;
- result.hour = (dt >> 11) & 0x1F;
- result.minute = (dt >> 5) & 0x3F;
- result.second = ((dt >> 0) & 0x1F) * 2;
+ result.year = ((dt >> 25) & 0x7f) + 1980;
+ result.month = (dt >> 21) & 0x0f;
+ result.day_of_month = (dt >> 16) & 0x1f;
+ result.hour = (dt >> 11) & 0x1f;
+ result.minute = (dt >> 5) & 0x3f;
+ result.second = ((dt >> 0) & 0x1f) * 2;
return result;
}
+u32 encode_now_fat_datetime()
+{
+ auto now = util::arbitrary_datetime::now();
+
+ return u32((((now.year - 1980) & 0x7f) << 25) |
+ ((now.month & 0x0f) << 21) |
+ ((now.day_of_month & 0x1f) << 16) |
+ ((now.hour & 0x1f) << 11) |
+ ((now.minute & 0x3f) << 5) |
+ ((now.second >> 1) & 0x1f));
+}
+
}
@@ -354,7 +421,7 @@ bool fs::fat_image::can_read() const
bool fs::fat_image::can_write() const
{
- return false;
+ return true;
}
@@ -385,8 +452,8 @@ char fs::fat_image::directory_separator() const
std::vector<meta_description> fs::fat_image::volume_meta_description() const
{
std::vector<meta_description> results;
- results.emplace_back(meta_name::name, "UNTITLED", false, [](const meta_value &m) { return m.as_string().size() <= 11; }, "Volume name, up to 11 characters");
- results.emplace_back(meta_name::oem_name, "", false, [](const meta_value &m) { return m.as_string().size() <= 8; }, "OEM name, up to 8 characters");
+ results.emplace_back(meta_name::name, "UNTITLED", false, [] (const meta_value &m) { return validate_filename(m.as_string()); }, "Volume name");
+ results.emplace_back(meta_name::oem_name, "", false, [] (const meta_value &m) { return m.as_string().size() <= 8; }, "OEM name, up to 8 characters");
return results;
}
@@ -398,7 +465,7 @@ std::vector<meta_description> fs::fat_image::volume_meta_description() const
std::vector<meta_description> fs::fat_image::file_meta_description() const
{
std::vector<meta_description> results;
- results.emplace_back(meta_name::name, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name");
+ results.emplace_back(meta_name::name, "", false, [] (const meta_value &m) { return validate_filename(m.as_string()); }, "File name");
results.emplace_back(meta_name::creation_date, util::arbitrary_datetime::now(), false, nullptr, "Creation time");
results.emplace_back(meta_name::modification_date, util::arbitrary_datetime::now(), false, nullptr, "Modification time");
results.emplace_back(meta_name::length, 0, true, nullptr, "Size of the file in bytes");
@@ -413,7 +480,7 @@ std::vector<meta_description> fs::fat_image::file_meta_description() const
std::vector<meta_description> fs::fat_image::directory_meta_description() const
{
std::vector<meta_description> results;
- results.emplace_back(meta_name::name, "", false, [](const meta_value &m) { return validate_filename(m.as_string()); }, "File name");
+ results.emplace_back(meta_name::name, "", false, [] (const meta_value &m) { return validate_filename(m.as_string()); }, "File name");
results.emplace_back(meta_name::creation_date, util::arbitrary_datetime::now(), false, nullptr, "Creation time");
results.emplace_back(meta_name::modification_date, util::arbitrary_datetime::now(), false, nullptr, "Modification time");
return results;
@@ -427,19 +494,19 @@ std::vector<meta_description> fs::fat_image::directory_meta_description() const
std::unique_ptr<filesystem_t> fs::fat_image::mount_partition(fsblk_t &blockdev, u32 starting_sector, u32 sector_count, u8 bits_per_fat_entry)
{
// load the boot sector block and get some basic info
- fsblk_t::block_t boot_sector_block = blockdev.get(starting_sector);
- u16 reserved_sector_count = boot_sector_block.r16l(14);
+ fsblk_t::block_t::ptr boot_sector_block = blockdev.get(starting_sector);
+ u16 reserved_sector_count = boot_sector_block->r16l(impl::OFFSET_RESERVED_SECTOR_COUNT);
// load all file allocation table sectors
- u32 fat_count = boot_sector_block.r8(16);
- u32 sectors_per_fat = boot_sector_block.r16l(22);
- u16 bytes_per_sector = boot_sector_block.r16l(11);
+ u32 fat_count = boot_sector_block->r8(impl::OFFSET_FAT_COUNT);
+ u32 sectors_per_fat = boot_sector_block->r16l(impl::OFFSET_FAT_SECTOR_COUNT);
+ u16 bytes_per_sector = boot_sector_block->r16l(impl::OFFSET_BYTES_PER_SECTOR);
std::vector<u8> file_allocation_table;
file_allocation_table.reserve(fat_count * sectors_per_fat * bytes_per_sector);
for (auto i = 0; i < fat_count * sectors_per_fat; i++)
{
- fsblk_t::block_t fatblk = blockdev.get(starting_sector + reserved_sector_count + i);
- file_allocation_table.insert(file_allocation_table.end(), fatblk.rodata(), fatblk.rodata() + bytes_per_sector);
+ fsblk_t::block_t::ptr fatblk = blockdev.get(starting_sector + reserved_sector_count + i);
+ file_allocation_table.insert(file_allocation_table.end(), fatblk->rodata(), fatblk->rodata() + bytes_per_sector);
}
// and return the implementation
@@ -481,16 +548,24 @@ meta_data directory_entry::metadata() const
// impl ctor
//-------------------------------------------------
-impl::impl(fsblk_t &blockdev, fsblk_t::block_t &&boot_sector_block, std::vector<u8> &&file_allocation_table, u32 starting_sector, u32 sector_count, u16 reserved_sector_count, u8 bits_per_fat_entry)
+impl::impl(fsblk_t &blockdev, fsblk_t::block_t::ptr &&boot_sector_block, std::vector<u8> &&file_allocation_table, u32 starting_sector, u32 sector_count, u16 reserved_sector_count, u8 bits_per_fat_entry)
: filesystem_t(blockdev, 512)
, m_boot_sector_block(std::move(boot_sector_block))
, m_file_allocation_table(std::move(file_allocation_table))
, m_starting_sector(starting_sector)
, m_sector_count(sector_count)
, m_reserved_sector_count(reserved_sector_count)
- , m_bytes_per_sector(m_boot_sector_block.r16l(11))
+ , m_bytes_per_sector(m_boot_sector_block->r16l(OFFSET_BYTES_PER_SECTOR))
+ , m_root_directory_size(m_boot_sector_block->r16l(OFFSET_DIRECTORY_ENTRY_COUNT))
+ , m_sectors_per_cluster(m_boot_sector_block->r8(OFFSET_CLUSTER_SECTOR_COUNT))
+ , m_fat_count(m_boot_sector_block->r8(OFFSET_FAT_COUNT))
+ , m_fat_sector_count(m_boot_sector_block->r16l(OFFSET_FAT_SECTOR_COUNT))
, m_bits_per_fat_entry(bits_per_fat_entry)
+ , m_last_cluster_indicator(((u64)1 << bits_per_fat_entry) - 1)
+ , m_last_valid_cluster(m_last_cluster_indicator - 0x10)
{
+ if (m_bytes_per_sector == 0)
+ m_bytes_per_sector = 512;
}
@@ -500,9 +575,26 @@ impl::impl(fsblk_t &blockdev, fsblk_t::block_t &&boot_sector_block, std::vector<
meta_data impl::volume_metadata()
{
+ std::vector<std::string> root_path;
+ directory_span::ptr root_dir = find_directory(root_path.begin(), root_path.end());
+ assert(root_dir);
+
+ // Get the volume label from the root directory, not the extended BPB (whose name field may not be kept up-to-date even when it exists)
meta_data results;
- results.set(meta_name::name, m_boot_sector_block.rstr(43, 11));
- results.set(meta_name::oem_name, m_boot_sector_block.rstr(3, 8));
+ auto const callback = [&results] (const directory_entry &dirent)
+ {
+ if (dirent.is_volume_label())
+ {
+ results.set(meta_name::name, dirent.name());
+ return true;
+ }
+ return false;
+ };
+ iterate_directory_entries(*root_dir, callback);
+ if (!results.has(meta_name::name))
+ results.set(meta_name::name, "UNTITLED");
+
+ results.set(meta_name::oem_name, m_boot_sector_block->rstr(3, 8));
return results;
}
@@ -511,13 +603,13 @@ meta_data impl::volume_metadata()
// impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> impl::metadata(const std::vector<std::string> &path)
{
std::optional<directory_entry> dirent = find_entity(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, dirent->metadata());
+ return std::make_pair(std::error_condition(), dirent->metadata());
}
@@ -525,21 +617,24 @@ std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
// impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
{
directory_span::ptr dir = find_directory(path.begin(), path.end());
if (!dir)
- return std::make_pair(ERR_NOT_FOUND, std::vector<dir_entry>());
+ return std::make_pair(error::not_found, std::vector<dir_entry>());
std::vector<dir_entry> results;
- auto callback = [&results](const directory_entry &dirent)
+ auto const callback = [&results] (const directory_entry &dirent)
{
- dir_entry_type entry_type = dirent.is_subdirectory() ? dir_entry_type::dir : dir_entry_type::file;
- results.emplace_back(entry_type, dirent.metadata());
+ if (!dirent.is_volume_label())
+ {
+ dir_entry_type entry_type = dirent.is_subdirectory() ? dir_entry_type::dir : dir_entry_type::file;
+ results.emplace_back(entry_type, dirent.metadata());
+ }
return false;
};
iterate_directory_entries(*dir, callback);
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -547,12 +642,14 @@ std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vec
// impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
{
// find the file
std::optional<directory_entry> dirent = find_entity(path);
- if (!dirent || dirent->is_subdirectory())
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ if (!dirent)
+ return std::make_pair(error::not_found, std::vector<u8>());
+ if (dirent->is_subdirectory())
+ return std::make_pair(error::invalid_name, std::vector<u8>());
// get the list of sectors for this file
std::vector<u32> sectors = get_sectors_from_fat(*dirent);
@@ -564,15 +661,353 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
// and add data from all sectors
for (u32 sector : sectors)
{
- fsblk_t::block_t block = m_blockdev.get(sector);
- const u8 *data = block.rodata();
- size_t length = std::min((size_t)dirent->file_size() - result.size(), (size_t)block.size());
+ fsblk_t::block_t::ptr block = m_blockdev.get(sector);
+ const u8 *data = block->rodata();
+ size_t length = std::min((size_t)dirent->file_size() - result.size(), (size_t)block->size());
result.insert(result.end(), data, data + length);
}
- return std::make_pair(ERR_OK, std::move(result));
+ return std::make_pair(std::error_condition(), std::move(result));
+}
+
+
+bool impl::is_valid_short_filename(std::string const &filename)
+{
+ /*
+ Valid characters in DOS file names:
+ - Upper case letters A-Z
+ - Numbers 0-9
+ - Space (though there is no way to identify a trailing space)
+ - ! # $ % & ( ) - @ ^ _ ` { } ~
+ - Characters 128-255, except e5 (though the code page is indeterminate)
+ We currently do not check for characters 128-255.
+ */
+ std::regex filename_regex("([A-Z0-9!#\\$%&\\(\\)\\-@^_`\\{\\}~]{0,8})(\\.([A-Z0-9!#\\$%&\\(\\)\\-@^_`\\{\\}~]{0,3}))?");
+ return std::regex_match(filename, filename_regex);
+}
+
+
+std::error_condition impl::build_direntry_filename(std::string const &filename, std::string &fname)
+{
+ std::regex filename_regex("([A-Z0-9!#\\$%&\\(\\)\\-@^_`\\{\\}~]{0,8})(\\.([A-Z0-9!#\\$%&\\(\\)\\-@^_`\\{\\}~]{0,3}))?");
+ std::smatch smatch;
+ if (!std::regex_match(filename, smatch, filename_regex))
+ return error::invalid_name;
+ if (smatch.size() != 4)
+ return error::invalid_name;
+
+ fname.resize(directory_entry::FNAME_LENGTH, ' ');
+
+ for (int i = 0; i < 8 && i < smatch.str(1).size(); i++)
+ fname[i] = smatch.str(1)[i];
+
+ for (int j = 0; j < 3 && j < smatch.str(3).size(); j++)
+ fname[8 + j] = smatch.str(3)[j];
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+{
+ std::string filename = meta.get_string(meta_name::name, "");
+ std::string fname;
+ std::error_condition err = build_direntry_filename(filename, fname);
+ if (err)
+ return err;
+
+ if (path.empty())
+ {
+ return file_create_root(fname);
+ }
+ else
+ {
+ // Make sure that all parts of the path exist, creating the path parts as needed.
+ std::optional<directory_entry> dirent = find_entity(path);
+ if (!dirent)
+ {
+ std::vector<std::string> partial_path;
+ std::optional<directory_entry> parent_entry;
+ for (auto const &path_part : path)
+ {
+ partial_path.emplace_back(path_part);
+ std::optional<directory_entry> dir_entry = find_entity(partial_path);
+ if (!dir_entry)
+ {
+ if (!is_valid_short_filename(path_part))
+ return error::invalid_name;
+
+ std::string part_fname;
+ std::error_condition err = build_direntry_filename(path_part, part_fname);
+ if (err)
+ return err;
+ err = !parent_entry ?
+ file_create_root(part_fname, directory_entry::ATTR_DIRECTORY) :
+ file_create_directory(parent_entry.value(), part_fname, directory_entry::ATTR_DIRECTORY);
+ if (err)
+ return err;
+
+ dir_entry = find_entity(partial_path);
+ if (!dir_entry)
+ return error::invalid_name;
+
+ err = initialize_directory(dir_entry->start_cluster(), parent_entry ? parent_entry->start_cluster() : 0);
+ if (err)
+ return err;
+ }
+ else
+ {
+ if (!dir_entry->is_subdirectory())
+ return error::invalid_name;
+ }
+ parent_entry = dir_entry;
+ }
+
+ dirent = find_entity(path);
+ if (!dirent)
+ return error::invalid_name;
+ }
+
+ return file_create_directory(*dirent, fname);
+ }
+}
+
+
+std::error_condition impl::initialize_directory(u32 directory_cluster, u32 parent_cluster)
+{
+ clear_cluster_sectors(directory_cluster, 0x00);
+
+ auto dirblk = m_blockdev.get(first_cluster_sector(directory_cluster));
+
+ // Add special directory entries for . and ..
+ std::string dir_fname;
+ dir_fname.resize(directory_entry::FNAME_LENGTH, ' ');
+ dir_fname[0] = '.';
+ std::error_condition err = initialize_directory_entry(*dirblk, 0, dir_fname, directory_entry::ATTR_DIRECTORY, directory_cluster);
+ if (err)
+ return err;
+
+ dir_fname[1] = '.';
+ err = initialize_directory_entry(*dirblk, directory_entry::SIZE, dir_fname, directory_entry::ATTR_DIRECTORY, parent_cluster);
+ if (err)
+ return err;
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::initialize_directory_entry(fsblk_t::block_t &dirblk, u32 offset, std::string_view fname, u8 attributes, u32 start_cluster)
+{
+ if (fname.size() != directory_entry::FNAME_LENGTH)
+ return error::invalid_name;
+
+ for (int i = 0; i < directory_entry::SIZE; i += 4)
+ dirblk.w32l(offset + i, 0);
+
+ dirblk.wstr(offset + directory_entry::OFFSET_FNAME, fname);
+ dirblk.w8(offset + directory_entry::OFFSET_ATTRIBUTES, attributes);
+ dirblk.w32l(offset + directory_entry::OFFSET_CREATE_DATETIME, encode_now_fat_datetime());
+ dirblk.w32l(offset + directory_entry::OFFSET_MODIFIED_DATETIME, encode_now_fat_datetime());
+ dirblk.w16l(offset + directory_entry::OFFSET_START_CLUSTER_HI, u16(start_cluster >> 16));
+ dirblk.w16l(offset + directory_entry::OFFSET_START_CLUSTER, u16(start_cluster & 0xffff));
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::file_create_root(std::string &fname, u8 attributes)
+{
+ const u32 first_directory_sector = m_starting_sector + m_reserved_sector_count + ((u32)m_file_allocation_table.size() / m_bytes_per_sector);
+ const u32 directory_sector_count = (m_root_directory_size * directory_entry::SIZE) / m_bytes_per_sector;
+ for (u32 sector = first_directory_sector; sector < first_directory_sector + directory_sector_count; sector++)
+ {
+ std::error_condition err = file_create_sector(sector, fname, attributes);
+ if (err != error::not_found)
+ return err;
+ }
+ return error::no_space;
+}
+
+
+std::error_condition impl::file_create_directory(directory_entry &dirent, std::string &fname, u8 attributes)
+{
+ u32 current_cluster = dirent.start_cluster();
+ do {
+ const u32 first_sector = first_cluster_sector(current_cluster);
+ for (int i = 0; i < m_sectors_per_cluster; i++)
+ {
+ std::error_condition err = file_create_sector(first_sector + i, fname, attributes);
+ if (err != error::not_found)
+ return err;
+ }
+
+ // File could not be created yet. Move to next cluster, allocating a new cluster when needed.
+ u32 next_cluster = get_next_cluster(current_cluster);
+ if (next_cluster >= m_last_valid_cluster)
+ {
+ next_cluster = find_free_cluster();
+ if (next_cluster == 0)
+ return error::no_space;
+
+ set_next_cluster(current_cluster, next_cluster);
+ set_next_cluster(next_cluster, m_last_cluster_indicator);
+
+ clear_cluster_sectors(next_cluster, 0x00);
+ }
+ current_cluster = next_cluster;
+ } while (current_cluster > FIRST_VALID_CLUSTER && current_cluster < m_last_valid_cluster);
+ return error::no_space;
+}
+
+
+u32 impl::first_cluster_sector(u32 cluster)
+{
+ return m_starting_sector + m_reserved_sector_count +
+ ((u32)m_file_allocation_table.size() / m_bytes_per_sector) +
+ ((m_root_directory_size + 1) / dirents_per_sector()) +
+ ((cluster - FIRST_VALID_CLUSTER) * m_sectors_per_cluster);
+}
+
+
+void impl::clear_cluster_sectors(u32 cluster, u8 fill_byte)
+{
+ const u32 sector = first_cluster_sector(cluster);
+ for (int i = 0; i < m_sectors_per_cluster; i++)
+ {
+ auto dirblk = m_blockdev.get(sector + i);
+ for (int offset = 0; offset < m_bytes_per_sector; offset++)
+ dirblk->w8(offset, fill_byte);
+ }
}
+// Returns error::not_found when no room could be found to create the file in the sector.
+std::error_condition impl::file_create_sector(u32 sector, std::string &fname, u8 attributes)
+{
+ auto dirblk = m_blockdev.get(sector);
+ for (u32 blkoffset = 0; blkoffset < m_bytes_per_sector; blkoffset += directory_entry::SIZE)
+ {
+ u8 first_byte = dirblk->r8(blkoffset);
+ if (first_byte == 0x00 || first_byte == directory_entry::DELETED_FILE_MARKER)
+ {
+ u32 start_cluster = find_free_cluster();
+ if (start_cluster == 0)
+ return error::no_space;
+ set_next_cluster(start_cluster, m_last_cluster_indicator);
+
+ std::error_condition err = initialize_directory_entry(*dirblk, blkoffset, fname, attributes, start_cluster);
+ if (err)
+ return err;
+
+ return std::error_condition();
+ }
+ }
+ return error::not_found;
+}
+
+
+std::error_condition impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+{
+ std::optional<directory_entry> dirent = find_entity(path);
+ if (!dirent)
+ return error::not_found;
+
+ if (dirent->is_subdirectory())
+ return error::invalid_name;
+
+ u32 current_length = dirent->file_size();
+ const size_t data_length = data.size();
+ const u32 bytes_per_cluster = m_sectors_per_cluster * bytes_per_sector();
+ const u32 current_clusters = (current_length + bytes_per_cluster - 1) / bytes_per_cluster;
+ const u32 required_clusters = (data_length + bytes_per_cluster - 1) / bytes_per_cluster;
+
+ if (required_clusters > current_clusters)
+ {
+ u32 current_cluster = dirent->start_cluster();
+ u32 next_cluster = 0;
+ do {
+ next_cluster = get_next_cluster(current_cluster);
+ if (next_cluster < FIRST_VALID_CLUSTER)
+ return error::invalid_block;
+ } while (next_cluster < m_last_valid_cluster);
+ for (int i = current_clusters; i < required_clusters; i++)
+ {
+ u32 free_cluster = find_free_cluster();
+ if (free_cluster < FIRST_VALID_CLUSTER)
+ return error::no_space;
+
+ set_next_cluster(current_cluster, free_cluster);
+ set_next_cluster(free_cluster, m_last_cluster_indicator);
+ current_cluster = free_cluster;
+ }
+ }
+ if (required_clusters < current_clusters)
+ {
+ u32 current_cluster = dirent->start_cluster();
+ for (int i = 0; i < required_clusters; i++)
+ {
+ current_cluster = get_next_cluster(current_cluster);
+ }
+ u32 next_cluster = get_next_cluster(current_cluster);
+ set_next_cluster(current_cluster, m_last_cluster_indicator);
+
+ std::error_condition err = free_clusters(next_cluster);
+ if (err)
+ return err;
+ }
+
+ auto sectors = get_sectors_from_fat(*dirent);
+ size_t offset = 0;
+ for (auto sector : sectors)
+ {
+ if (offset < data_length)
+ {
+ auto datablk = m_blockdev.get(sector);
+ u32 bytes = (data_length - offset > m_bytes_per_sector) ? m_bytes_per_sector : data_length - offset;
+ datablk->write(0, data.data() + offset, bytes);
+ offset += m_bytes_per_sector;
+ }
+ }
+
+ dirent->set_raw_modified_datetime(encode_now_fat_datetime());
+ dirent->set_file_size(data_length);
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::remove(const std::vector<std::string> &path)
+{
+ if (path.size() != 0)
+ return error::unsupported;
+
+ std::optional<directory_entry> dirent = find_entity(path);
+ if (!dirent)
+ return std::error_condition();
+
+ // Removing directories is not supported yet
+ if (dirent->is_subdirectory())
+ return error::unsupported;
+
+ dirent->mark_deleted();
+
+ return std::error_condition();
+}
+
+
+std::error_condition impl::free_clusters(u32 start_cluster)
+{
+ while (start_cluster < m_last_valid_cluster)
+ {
+ if (start_cluster < FIRST_VALID_CLUSTER)
+ return error::invalid_block;
+
+ u32 next_cluster = get_next_cluster(start_cluster);
+ set_next_cluster(start_cluster, 0);
+ start_cluster = next_cluster;
+ }
+ return std::error_condition();
+}
+
//-------------------------------------------------
// impl::get_sectors_from_fat
//-------------------------------------------------
@@ -584,22 +1019,20 @@ std::vector<u32> impl::get_sectors_from_fat(const directory_entry &dirent) const
results.reserve(dirent.file_size() / bytes_per_sector());
// get critical information
- u8 sectors_per_cluster = m_boot_sector_block.r8(13);
- u16 root_directory_entry_count = m_boot_sector_block.r16l(17);
- u16 root_directory_sector_count = (root_directory_entry_count + 1) / dirents_per_sector();
- u32 fat_sector_count = (u32)(m_file_allocation_table.size() / m_bytes_per_sector);
+ u16 root_directory_sector_count = (m_root_directory_size + 1) / dirents_per_sector();
+ u32 fat_sector_count = m_fat_count * m_fat_sector_count;
u32 data_starting_sector = m_starting_sector + m_reserved_sector_count + fat_sector_count + root_directory_sector_count;
- u32 data_cluster_count = (m_sector_count - data_starting_sector) / sectors_per_cluster;
+ u32 data_cluster_count = (m_sector_count - data_starting_sector) / m_sectors_per_cluster;
// find all clusters
u32 start_cluster_mask = ((u64)1 << m_bits_per_fat_entry) - 1;
u32 cluster = dirent.start_cluster() & start_cluster_mask;
- while (cluster >= 2 && cluster < (data_cluster_count + 2))
+ while (cluster >= FIRST_VALID_CLUSTER && cluster < (data_cluster_count + 2))
{
// add the sectors for this cluster
- for (auto i = 0; i < sectors_per_cluster; i++)
- results.push_back(data_starting_sector + (cluster - 2) * sectors_per_cluster + i);
+ for (auto i = 0; i < m_sectors_per_cluster; i++)
+ results.push_back(data_starting_sector + (cluster - FIRST_VALID_CLUSTER) * m_sectors_per_cluster + i);
// determine the bit position of this entry
u32 entry_bit_position = cluster * m_bits_per_fat_entry;
@@ -623,8 +1056,8 @@ std::vector<u32> impl::get_sectors_from_fat(const directory_entry &dirent) const
}
// normalize special cluster IDs
- if (new_cluster > ((u32)1 << m_bits_per_fat_entry) - 0x10)
- new_cluster |= ~(((u32)1 << m_bits_per_fat_entry) - 1);
+ if (new_cluster > m_last_valid_cluster)
+ new_cluster |= ~m_last_cluster_indicator;
}
cluster = new_cluster;
}
@@ -633,6 +1066,91 @@ std::vector<u32> impl::get_sectors_from_fat(const directory_entry &dirent) const
}
+u32 impl::get_next_cluster(u32 cluster)
+{
+ u32 entry_bit_position = cluster * m_bits_per_fat_entry;
+ u32 new_cluster = 0;
+ if (entry_bit_position + m_bits_per_fat_entry <= m_file_allocation_table.size() * 8)
+ {
+ u32 current_bit = 0;
+ while (current_bit < m_bits_per_fat_entry)
+ {
+ u32 pos = entry_bit_position + current_bit;
+ u32 shift = pos % 8;
+ u32 bit_count = std::min(8 - shift, m_bits_per_fat_entry - current_bit);
+ u32 bits = (m_file_allocation_table[pos / 8] >> shift) & ((1 << bit_count) - 1);
+
+ new_cluster |= (bits << current_bit);
+ current_bit += bit_count;
+ }
+ }
+ return new_cluster;
+}
+
+
+void impl::set_next_cluster(u32 cluster, u32 next_cluster)
+{
+ const u32 m_fat_start_sector = m_starting_sector + m_reserved_sector_count;
+ const u32 entry_bit_position = cluster * m_bits_per_fat_entry;
+ if (entry_bit_position + m_bits_per_fat_entry <= m_file_allocation_table.size() * 8)
+ {
+ u32 current_bit = 0;
+ while (current_bit < m_bits_per_fat_entry)
+ {
+ u32 pos = entry_bit_position + current_bit;
+ u32 shift = pos % 8;
+ u32 bit_count = std::min(8 - shift, m_bits_per_fat_entry - current_bit);
+ u32 byte_pos = pos / 8;
+ u32 mask = ((1 << bit_count) - 1);
+ m_file_allocation_table[byte_pos] = (m_file_allocation_table[byte_pos] & ~(mask << shift)) | ((next_cluster & mask) << shift);
+ next_cluster = next_cluster >> bit_count;
+ current_bit += bit_count;
+ // Write back to backing blocks
+ for (int i = 0; i < m_fat_count; i++)
+ {
+ u32 fat_sector = m_fat_start_sector + (i * m_fat_sector_count) + (byte_pos / m_bytes_per_sector);
+ auto fatblk = m_blockdev.get(fat_sector);
+ fatblk->w8(byte_pos % m_bytes_per_sector, m_file_allocation_table[byte_pos]);
+ }
+ }
+ }
+}
+
+
+// Returns 0 if no free cluster could be found
+u32 impl::find_free_cluster()
+{
+ u16 root_directory_sector_count = (m_root_directory_size + 1) / dirents_per_sector();
+ u32 fat_sector_count = m_fat_count * m_fat_sector_count;
+ u32 data_starting_sector = m_starting_sector + m_reserved_sector_count + fat_sector_count + root_directory_sector_count;
+ u32 data_cluster_count = (m_sector_count - data_starting_sector) / m_sectors_per_cluster;
+
+ for (u32 cluster = FIRST_VALID_CLUSTER; cluster < (data_cluster_count + 2); cluster++)
+ {
+ u32 entry_bit_position = cluster * m_bits_per_fat_entry;
+
+ if (entry_bit_position + m_bits_per_fat_entry <= m_file_allocation_table.size() * 8)
+ {
+ u32 new_cluster = 0;
+ u32 current_bit = 0;
+ while (current_bit < m_bits_per_fat_entry)
+ {
+ u32 pos = entry_bit_position + current_bit;
+ u32 shift = pos % 8;
+ u32 bit_count = std::min(8 - shift, m_bits_per_fat_entry - current_bit);
+ u32 bits = (m_file_allocation_table[pos / 8] >> shift) & ((1 << bit_count) - 1);
+
+ new_cluster |= (bits << current_bit);
+ current_bit += bit_count;
+ }
+
+ if (new_cluster == 0)
+ return cluster;
+ }
+ }
+ return 0;
+}
+
//-------------------------------------------------
// impl::find_entity
//-------------------------------------------------
@@ -661,8 +1179,7 @@ directory_span::ptr impl::find_directory(std::vector<std::string>::const_iterato
{
// the root directory is treated differently
u32 first_sector = m_starting_sector + m_reserved_sector_count + (u32)m_file_allocation_table.size() / m_bytes_per_sector;
- u16 directory_entry_count = m_boot_sector_block.r16l(17);
- directory_span::ptr current_dir = std::make_unique<root_directory_span>(*this, first_sector, directory_entry_count);
+ directory_span::ptr current_dir = std::make_unique<root_directory_span>(*this, first_sector, m_root_directory_size);
// traverse the directory
for (auto iter = path_begin; iter != path_end; iter++)
@@ -687,7 +1204,7 @@ directory_span::ptr impl::find_directory(std::vector<std::string>::const_iterato
std::optional<directory_entry> impl::find_child(const directory_span &current_dir, std::string_view target) const
{
std::optional<directory_entry> result;
- auto callback = [&result, target](const directory_entry &dirent)
+ auto const callback = [&result, target] (const directory_entry &dirent)
{
bool found = dirent.name() == target;
if (found)
@@ -703,17 +1220,18 @@ std::optional<directory_entry> impl::find_child(const directory_span &current_di
// impl::iterate_directory_entries
//-------------------------------------------------
-void impl::iterate_directory_entries(const directory_span &dir, const std::function<bool(const directory_entry &dirent)> &callback) const
+template <typename T>
+void impl::iterate_directory_entries(const directory_span &dir, T &&callback) const
{
std::vector<u32> sectors = dir.get_directory_sectors();
for (u32 sector : sectors)
{
bool done = false;
- fsblk_t::block_t block = m_blockdev.get(sector);
+ fsblk_t::block_t::ptr block = m_blockdev.get(sector);
for (u32 index = 0; !done && (index < dirents_per_sector()); index++)
{
directory_entry dirent(block, index * 32);
- if (dirent.raw_stem()[0] != 0x00 && !dirent.is_deleted())
+ if (dirent.raw_stem()[0] != 0x00 && !dirent.is_deleted() && !dirent.is_long_file_name())
{
// get the filename
std::string_view stem = trim_end_spaces(dirent.raw_stem());
@@ -815,6 +1333,12 @@ void pc_fat_image::enumerate_f(floppy_enumerator &fe) const
fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 737280, "pc_fat_dsdd", "PC FAT 3.5\" dual-sided double density");
fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_35, floppy_image::DSHD, 1474560, "pc_fat_dshd", "PC FAT 3.5\" dual-sided high density");
fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_35, floppy_image::DSED, 2949120, "pc_fat_dsed", "PC FAT 3.5\" dual-sided extra density");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::SSDD, 163840, "pc_fat_525ssdd_8", "PC FAT 5.25\" single-sided double density, 8 sectors/track");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::SSDD, 184320, "pc_fat_525ssdd", "PC FAT 5.25\" single-sided double density, 9 sectors/track");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::DSDD, 327680, "pc_fat_525dsdd_8", "PC FAT 5.25\" dual-sided double density, 8 sectors/track");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::DSDD, 368640, "pc_fat_525dsdd", "PC FAT 5.25\" dual-sided double density, 9 sectors/track");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::DSQD, 737280, "pc_fat_525dsqd", "PC FAT 5.25\" dual-sided quad density");
+ fe.add(FLOPPY_PC_FORMAT, floppy_image::FF_525, floppy_image::DSHD, 1228800, "pc_fat_525dshd", "PC FAT 5.25\" dual-sided high density");
}
diff --git a/src/lib/formats/fs_hp98x5.cpp b/src/lib/formats/fs_hp98x5.cpp
index a8eb139ef7a..f070d01b30f 100644
--- a/src/lib/formats/fs_hp98x5.cpp
+++ b/src/lib/formats/fs_hp98x5.cpp
@@ -107,17 +107,17 @@ namespace {
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::error_condition format(const meta_data &meta) override;
private:
// Map of used/free sectors
@@ -202,7 +202,7 @@ namespace {
using dir_t = std::vector<entry>;
- err_t parse_filename(const std::string& name, std::string& basename, int& bpr, u8& file_type) const;
+ std::error_condition parse_filename(const std::string& name, std::string& basename, int& bpr, u8& file_type) const;
bool validate_filename(const std::string& s) const;
void ensure_dir_loaded();
std::pair<dir_t, sect_map> decode_dir() const;
@@ -323,10 +323,10 @@ meta_data hp98x5_impl::volume_metadata()
return res;
}
-std::pair<err_t, meta_data> hp98x5_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> hp98x5_impl::metadata(const std::vector<std::string> &path)
{
if (path.size() != 1) {
- return std::make_pair(ERR_NOT_FOUND, meta_data{});
+ return std::make_pair(error::not_found, meta_data{});
}
std::string basename;
@@ -334,21 +334,21 @@ std::pair<err_t, meta_data> hp98x5_impl::metadata(const std::vector<std::string>
u8 file_type;
auto err = parse_filename(path.front(), basename, bpr, file_type);
- if (err != ERR_OK) {
- return std::make_pair(ERR_NOT_FOUND, meta_data{});
+ if (err) {
+ return std::make_pair(error::not_found, meta_data{});
}
ensure_dir_loaded();
auto it = scan_dir(m_dir, basename);
if (it == m_dir.end()) {
- return std::make_pair(ERR_NOT_FOUND, meta_data{});
+ return std::make_pair(error::not_found, meta_data{});
}
auto meta = get_metadata(*it);
- return std::make_pair(ERR_OK, std::move(meta));
+ return std::make_pair(std::error_condition(), std::move(meta));
}
-std::pair<err_t, std::vector<dir_entry>> hp98x5_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> hp98x5_impl::directory_contents(const std::vector<std::string> &path)
{
if (path.empty()) {
ensure_dir_loaded();
@@ -360,16 +360,16 @@ std::pair<err_t, std::vector<dir_entry>> hp98x5_impl::directory_contents(const s
dir_entries.emplace_back(dir_entry_type::file, std::move(meta));
}
}
- return std::make_pair(ERR_OK, dir_entries);
+ return std::make_pair(std::error_condition(), dir_entries);
} else {
- return std::make_pair(ERR_NOT_FOUND, std::vector<dir_entry>{});
+ return std::make_pair(error::not_found, std::vector<dir_entry>{});
}
}
-err_t hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
if (!path.empty()) {
- return ERR_INVALID;
+ return error::invalid_name;
}
auto name = meta.get_string(meta_name::name);
@@ -381,9 +381,13 @@ err_t hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_
// Parse & validate filename
// Extension must be specified
auto err = parse_filename(name, basename, bpr, file_type);
- if (err != ERR_OK || file_type == NO_FILE_TYPE) {
- return ERR_INVALID;
+ if (err) {
+ return err;
+ }
+ if (file_type == NO_FILE_TYPE) {
+ return error::invalid_name;
}
+
if (bpr < 0) {
// Use default bpr when not specified
bpr = DEF_BPR;
@@ -393,7 +397,7 @@ err_t hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_
ensure_dir_loaded();
auto it = scan_dir(m_dir, basename);
if (it != m_dir.end()) {
- return ERR_INVALID;
+ return error::already_exists;
}
// Find a free entry in directory
@@ -404,7 +408,7 @@ err_t hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_
m_dir.emplace_back(entry());
it2 = m_dir.end() - 1;
} else {
- return ERR_NO_SPACE;
+ return error::no_space;
}
}
@@ -421,13 +425,13 @@ err_t hp98x5_impl::file_create(const std::vector<std::string> &path, const meta_
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
-std::pair<err_t, std::vector<u8>> hp98x5_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> hp98x5_impl::file_read(const std::vector<std::string> &path)
{
if (path.size() != 1) {
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>{});
+ return std::make_pair(error::not_found, std::vector<u8>{});
}
std::string basename;
int bpr;
@@ -435,10 +439,10 @@ std::pair<err_t, std::vector<u8>> hp98x5_impl::file_read(const std::vector<std::
auto err = parse_filename(path.front(), basename, bpr, file_type);
- if (err == ERR_OK) {
+ if (!err) {
auto it = find_file(basename, bpr, file_type);
if (it == m_dir.end()) {
- err = ERR_NOT_FOUND;
+ err = error::not_found;
} else {
auto file_data = get_sector_range(it->m_1st_sect, it->m_sectors);
if (file_type == TEXT_TYPE) {
@@ -446,16 +450,16 @@ std::pair<err_t, std::vector<u8>> hp98x5_impl::file_read(const std::vector<std::
} else {
file_data.resize(it->m_size);
}
- return std::make_pair(ERR_OK, std::move(file_data));
+ return std::make_pair(std::error_condition(), std::move(file_data));
}
}
return std::make_pair(err, std::vector<u8>{});
}
-err_t hp98x5_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::error_condition hp98x5_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
if (path.size() != 1) {
- return ERR_NOT_FOUND;
+ return error::not_found;
}
std::string basename;
@@ -463,13 +467,13 @@ err_t hp98x5_impl::file_write(const std::vector<std::string> &path, const std::v
u8 file_type;
auto err = parse_filename(path.front(), basename, bpr, file_type);
- if (err != ERR_OK) {
+ if (err) {
return err;
}
// Check that file already exists
auto it = find_file(basename, bpr, file_type);
if (it == m_dir.end()) {
- return ERR_NOT_FOUND;
+ return error::not_found;
}
// De-allocate current blocks
@@ -488,7 +492,7 @@ err_t hp98x5_impl::file_write(const std::vector<std::string> &path, const std::v
// Allocate space
it->m_sectors = (data_ptr->size() + SECTOR_SIZE - 1) / SECTOR_SIZE;
if (!allocate(it->m_sectors, it->m_1st_sect)) {
- return ERR_NO_SPACE;
+ return error::no_space;
}
// Store file content
@@ -498,10 +502,10 @@ err_t hp98x5_impl::file_write(const std::vector<std::string> &path, const std::v
// Update directory & map
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
-err_t hp98x5_impl::format(const meta_data &meta)
+std::error_condition hp98x5_impl::format(const meta_data &meta)
{
bool is_ds = m_blockdev.block_count() == DS_SECTORS;
@@ -540,11 +544,11 @@ err_t hp98x5_impl::format(const meta_data &meta)
// Interleave factor
w16b(out_ins, m_fmt_interleave[ m_fs_type ]);
- m_blockdev.get(0).copy(0, sys_rec.data(), sys_rec.size());
+ m_blockdev.get(0)->write(0, sys_rec.data(), sys_rec.size());
// 9825 & 9831 have a backup copy of system record in spare track but 9845 hasn't, go figure
if (m_fs_type != FS_TYPE_9845) {
- m_blockdev.get(m_spare_start).copy(0, sys_rec.data(), sys_rec.size());
+ m_blockdev.get(m_spare_start)->write(0, sys_rec.data(), sys_rec.size());
}
m_dir.clear();
@@ -553,10 +557,10 @@ err_t hp98x5_impl::format(const meta_data &meta)
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
-err_t hp98x5_impl::parse_filename(const std::string& name, std::string& basename, int& bpr, u8& file_type) const
+std::error_condition hp98x5_impl::parse_filename(const std::string& name, std::string& basename, int& bpr, u8& file_type) const
{
// General form of filenames:
// basename[[.&bpr].ext]
@@ -579,18 +583,18 @@ err_t hp98x5_impl::parse_filename(const std::string& name, std::string& basename
if (p2 != std::string::npos) {
// [p1+1 p2) should have "&bpr"
if (name[ p1 + 1 ] != '&') {
- return ERR_INVALID;
+ return error::invalid_name;
}
if (!std::all_of(name.cbegin() + p1 + 2, name.cbegin() + p2, [](char c) { return c >= '0' && c <= '9'; })) {
- return ERR_INVALID;
+ return error::invalid_name;
}
try {
bpr = std::stoul(std::string{name, p1 + 2, p2 - p1 - 2});
} catch (...) {
- return ERR_INVALID;
+ return error::invalid_name;
}
if (bpr < 4 || bpr > 32767 || (bpr & 1) != 0) {
- return ERR_INVALID;
+ return error::invalid_name;
}
} else {
p2 = p1;
@@ -607,7 +611,7 @@ err_t hp98x5_impl::parse_filename(const std::string& name, std::string& basename
}
}
if (file_type == NO_FILE_TYPE) {
- return ERR_INVALID;
+ return error::invalid_name;
}
}
}
@@ -615,9 +619,9 @@ err_t hp98x5_impl::parse_filename(const std::string& name, std::string& basename
// [0 p1) has "basename"
basename = std::string(name, 0, p1);
if (validate_filename(basename)) {
- return ERR_OK;
+ return std::error_condition();
} else {
- return ERR_INVALID;
+ return error::invalid_name;
}
}
@@ -659,14 +663,14 @@ void hp98x5_impl::ensure_dir_loaded()
// 8 Count of data tracks
// 9 Interleave factor
// 10..127 N/U
- u16 sects_per_track = sys_rec.r16b(2);
- u16 tot_tracks = sys_rec.r16b(4);
- u16 spare_track = sys_rec.r16b(6);
- u16 dir_start = sys_rec.r16b(8);
- u16 av_start = sys_rec.r16b(10);
- u16 av_end = sys_rec.r16b(12);
- u16 sys_tracks = sys_rec.r16b(14);
- u16 data_tracks = sys_rec.r16b(16);
+ u16 sects_per_track = sys_rec->r16b(2);
+ u16 tot_tracks = sys_rec->r16b(4);
+ u16 spare_track = sys_rec->r16b(6);
+ u16 dir_start = sys_rec->r16b(8);
+ u16 av_start = sys_rec->r16b(10);
+ u16 av_end = sys_rec->r16b(12);
+ u16 sys_tracks = sys_rec->r16b(14);
+ u16 data_tracks = sys_rec->r16b(16);
m_img_tracks = m_blockdev.block_count() / SECTORS;
@@ -1155,7 +1159,7 @@ std::vector<u8> hp98x5_impl::get_sector_range(lba_t first, unsigned size) const
for (lba_t idx = first; idx < first + size; idx++) {
auto data_sect = m_blockdev.get(u32(idx));
- memcpy(ptr, data_sect.rodata(), SECTOR_SIZE);
+ data_sect->read(0, ptr, SECTOR_SIZE);
ptr += SECTOR_SIZE;
}
return res;
@@ -1169,7 +1173,7 @@ void hp98x5_impl::store_sector_range(lba_t first, const std::vector<u8>& data)
for (lba_t idx = first; idx < first + sects; idx++) {
u32 count = std::min<u32>(to_go, SECTOR_SIZE);
auto blk = m_blockdev.get(u32(idx));
- blk.copy(0, ptr, count);
+ blk->write(0, ptr, count);
ptr += count;
to_go -= count;
}
diff --git a/src/lib/formats/fs_hplif.cpp b/src/lib/formats/fs_hplif.cpp
index 48dde255cb4..8a3d2c52da4 100644
--- a/src/lib/formats/fs_hplif.cpp
+++ b/src/lib/formats/fs_hplif.cpp
@@ -64,27 +64,27 @@ public:
u8 size() const;
private:
- const impl & m_fs;
- fsblk_t::block_t m_block;
- u8 m_sector;
- u32 m_sector_count;
+ const impl & m_fs;
+ fsblk_t::block_t::ptr m_block;
+ u8 m_sector;
+ u32 m_sector_count;
};
impl(fsblk_t &blockdev);
virtual ~impl() = default;
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
private:
- fsblk_t::block_t read_sector(u32 starting_sector) const;
+ fsblk_t::block_t::ptr read_sector(u32 starting_sector) const;
std::optional<hplif_dirent> dirent_from_path(const std::vector<std::string> &path) const;
void iterate_directory_entries(const std::function<bool(const hplif_dirent &dirent)> &callback) const;
util::arbitrary_datetime decode_datetime(const hplif_time *time) const;
meta_data metadata_from_dirent(const hplif_dirent &dirent) const;
- err_t format(const meta_data &meta) override;
+ std::error_condition format(const meta_data &meta) override;
};
// methods
@@ -120,10 +120,10 @@ const char *fs::hplif_image::description() const
void fs::hplif_image::enumerate_f(floppy_enumerator &fe) const
{
- fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 630784, "hp_lif_9121_format_1", "HP 9212 LIF 3.5\" dual-sided double density Format 1");
+ fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 630784, "hp_lif_9121_format_1", "HP 9121 LIF 3.5\" dual-sided double density Format 1");
fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 709632, "hp_lif_9121_format_2", "HP 9121 LIF 3.5\" dual-sided double density Format 2");
fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 788480, "hp_lif_9121_format_3", "HP 9121 LIF 3.5\" dual-sided double density Format 3");
- fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::SSDD, 286720, "hp_lif_9121_format_4", "HP 9121 LIF 3.5\" single-sided double density Format 4");
+ fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::SSDD, 270336, "hp_lif_9121_format_4", "HP 9121 LIF 3.5\" single-sided double density Format 4");
fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 737280, "hp_lif_9121_format_16", "HP 9121 LIF 3.5\" dual-sided double density Format 16");
fe.add(FLOPPY_HP300_FORMAT, floppy_image::FF_35, floppy_image::DSHD, 1261568, "hp_lif_9122_format_014", "HP 9122 LIF 3.5\" dual-sided high density Format 0, 1, 4");
@@ -252,11 +252,11 @@ impl::impl(fsblk_t &blockdev)
meta_data impl::volume_metadata()
{
auto block = read_sector(0);
- std::string_view disk_name = std::string_view((const char *) block.rodata() + 2, 6);
+ std::string_view disk_name = block->rstr(2, 6);
meta_data results;
results.set(meta_name::name, strtrimright_hplif(disk_name));
- results.set(meta_name::creation_date, decode_datetime(reinterpret_cast<const hplif_time *>(block.rodata() + 36)));
+ results.set(meta_name::creation_date, decode_datetime(reinterpret_cast<const hplif_time *>(block->rodata() + 36)));
return results;
}
@@ -265,13 +265,13 @@ meta_data impl::volume_metadata()
// impl::metadata
//-------------------------------------------------
-std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> impl::metadata(const std::vector<std::string> &path)
{
std::optional<hplif_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, metadata_from_dirent(*dirent));
+ return std::make_pair(std::error_condition(), metadata_from_dirent(*dirent));
}
@@ -279,7 +279,7 @@ std::pair<err_t, meta_data> impl::metadata(const std::vector<std::string> &path)
// impl::directory_contents
//-------------------------------------------------
-std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> impl::directory_contents(const std::vector<std::string> &path)
{
std::vector<dir_entry> results;
auto callback = [this, &results](const hplif_dirent &ent)
@@ -288,7 +288,7 @@ std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vec
return false;
};
iterate_directory_entries(callback);
- return std::make_pair(ERR_OK, std::move(results));
+ return std::make_pair(std::error_condition(), std::move(results));
}
@@ -296,12 +296,12 @@ std::pair<err_t, std::vector<dir_entry>> impl::directory_contents(const std::vec
// impl::file_read
//-------------------------------------------------
-std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> impl::file_read(const std::vector<std::string> &path)
{
// find the file
std::optional<hplif_dirent> dirent = dirent_from_path(path);
if (!dirent)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
// and get the data
u32 sector_count = big_endianize_int32(dirent->m_sector_count);
@@ -316,7 +316,7 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
while (iter.next())
result.insert(result.end(), (const u8 *)iter.data(), (const u8 *)iter.data() + 256);
- return std::make_pair(ERR_OK, std::move(result));
+ return std::make_pair(std::error_condition(), std::move(result));
}
@@ -324,7 +324,7 @@ std::pair<err_t, std::vector<u8>> impl::file_read(const std::vector<std::string>
// impl::read_sector
//-------------------------------------------------
-fsblk_t::block_t impl::read_sector(u32 sector) const
+fsblk_t::block_t::ptr impl::read_sector(u32 sector) const
{
return m_blockdev.get(sector);
}
@@ -359,10 +359,10 @@ std::optional<impl::hplif_dirent> impl::dirent_from_path(const std::vector<std::
void impl::iterate_directory_entries(const std::function<bool(const hplif_dirent &dirent)> &callback) const
{
- fsblk_t::block_t block = m_blockdev.get(0);
- block_iterator iter(*this, block.r32b(8), block.r32b(16));
+ fsblk_t::block_t::ptr block = m_blockdev.get(0);
+ block_iterator iter(*this, block->r32b(8), block->r32b(16));
- if (block.r16b(0) != 0x8000)
+ if (block->r16b(0) != 0x8000)
{
return;
}
@@ -461,30 +461,30 @@ bool impl::block_iterator::next()
const void *impl::block_iterator::data() const
{
- return m_block.rodata();
+ return m_block->rodata();
}
//-------------------------------------------------
// impl::format
//-------------------------------------------------
-err_t impl::format(const meta_data &meta)
+std::error_condition impl::format(const meta_data &meta)
{
std::string volume_name = meta.get_string(meta_name::name, "B9826 ");
- fsblk_t::block_t block = m_blockdev.get(0);
+ fsblk_t::block_t::ptr block = m_blockdev.get(0);
if (volume_name.size() < 6)
volume_name.insert(volume_name.end(), 6 - volume_name.size(), ' ');
if (volume_name.size() > 6)
volume_name.resize(6);
- block.w16b(0, 0x8000); // LIF magic
- block.wstr(2, volume_name);
- block.w32b(8, 2); // directory start
- block.w16b(12, 0x1000); // LIF identifier
- block.w32b(16, 14); // directory size
- block.w16b(20, 1); // LIF version
- return ERR_OK;
+ block->w16b(0, 0x8000); // LIF magic
+ block->wstr(2, volume_name);
+ block->w32b(8, 2); // directory start
+ block->w16b(12, 0x1000); // LIF identifier
+ block->w32b(16, 14); // directory size
+ block->w16b(20, 1); // LIF version
+ return std::error_condition();
}
//-------------------------------------------------
@@ -493,7 +493,7 @@ err_t impl::format(const meta_data &meta)
const std::array<impl::hplif_dirent, 8> &impl::block_iterator::dirent_data() const
{
- return *reinterpret_cast<const std::array<impl::hplif_dirent, 8> *>(m_block.rodata());
+ return *reinterpret_cast<const std::array<impl::hplif_dirent, 8> *>(m_block->rodata());
}
} // anonymous namespace
diff --git a/src/lib/formats/fs_isis.cpp b/src/lib/formats/fs_isis.cpp
index 3b79851522b..fb79314a360 100644
--- a/src/lib/formats/fs_isis.cpp
+++ b/src/lib/formats/fs_isis.cpp
@@ -45,17 +45,17 @@ namespace {
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::error_condition format(const meta_data &meta) override;
private:
using sect_map = std::bitset<DD_SECTORS>;
@@ -225,24 +225,24 @@ meta_data isis_impl::volume_metadata()
return res;
}
-std::pair<err_t, meta_data> isis_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> isis_impl::metadata(const std::vector<std::string> &path)
{
if (path.size() != 1) {
- return std::make_pair(ERR_NOT_FOUND, meta_data{});
+ return std::make_pair(error::not_found, meta_data{});
}
ensure_dir_loaded();
auto it = scan_dir(path.front());
if (it == m_dir.end()) {
- return std::make_pair(ERR_NOT_FOUND, meta_data{});
+ return std::make_pair(error::not_found, meta_data{});
}
auto meta = get_metadata(*it);
- return std::make_pair(ERR_OK, std::move(meta));
+ return std::make_pair(std::error_condition(), std::move(meta));
}
-std::pair<err_t, std::vector<dir_entry>> isis_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> isis_impl::directory_contents(const std::vector<std::string> &path)
{
if (path.empty()) {
ensure_dir_loaded();
@@ -254,16 +254,16 @@ std::pair<err_t, std::vector<dir_entry>> isis_impl::directory_contents(const std
dir_entries.emplace_back(dir_entry_type::file, std::move(meta));
}
}
- return std::make_pair(ERR_OK, dir_entries);
+ return std::make_pair(std::error_condition(), dir_entries);
} else {
- return std::make_pair(ERR_NOT_FOUND, std::vector<dir_entry>{});
+ return std::make_pair(error::not_found, std::vector<dir_entry>{});
}
}
-err_t isis_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition isis_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
if (!path.empty()) {
- return ERR_INVALID;
+ return error::invalid_name;
}
auto name = meta.get_string(meta_name::name);
@@ -274,13 +274,13 @@ err_t isis_impl::file_create(const std::vector<std::string> &path, const meta_da
std::string filename = name.substr(0, pt_pos);
if (filename.size() < 1 || filename.size() > 6 || !validate_filename(filename)) {
- return ERR_INVALID;
+ return error::invalid_name;
}
if (pt_pos != std::string::npos) {
auto ext = name.substr(pt_pos + 1);
if (ext.size() < 1 || ext.size() > 3 || !validate_filename(ext)) {
- return ERR_INVALID;
+ return error::invalid_name;
}
filename.push_back('.');
filename += ext;
@@ -288,14 +288,14 @@ err_t isis_impl::file_create(const std::vector<std::string> &path, const meta_da
// Check that file can be created by user
if (!user_can_create(filename)) {
- return ERR_INVALID;
+ return error::unsupported;
}
// Check that file doesn't exist
ensure_dir_loaded();
auto it = scan_dir(filename);
if (it != m_dir.end()) {
- return ERR_INVALID;
+ return error::already_exists;
}
// Find a free entry in directory
@@ -305,13 +305,13 @@ err_t isis_impl::file_create(const std::vector<std::string> &path, const meta_da
}
}
if (it == m_dir.end()) {
- return ERR_NO_SPACE;
+ return error::no_space;
}
// Allocate space
lba_list lbas;
if (!allocate(0, lbas)) {
- return ERR_NO_SPACE;
+ return error::no_space;
}
// Fill dir entry
@@ -326,42 +326,42 @@ err_t isis_impl::file_create(const std::vector<std::string> &path, const meta_da
// Update directory & map
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
-std::pair<err_t, std::vector<u8>> isis_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> isis_impl::file_read(const std::vector<std::string> &path)
{
const auto& [ lbas, size ] = find_file(path);
if (lbas != nullptr) {
auto file_data = get_file_content(*lbas, size);
- return std::make_pair(ERR_OK, std::move(file_data));
+ return std::make_pair(std::error_condition(), std::move(file_data));
}
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>{});
+ return std::make_pair(error::not_found, std::vector<u8>{});
}
-err_t isis_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::error_condition isis_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
if (path.size() != 1) {
- return ERR_NOT_FOUND;
+ return error::not_found;
}
// Check that file is user-writeable
const auto& filename = path.front();
if (!user_can_write(filename)) {
- return ERR_INVALID;
+ return error::unsupported;
}
// ISIS.T0 can only be 2944 bytes long
bool is_t0 = filename == ISIS_T0;
if (is_t0 && data.size() != ISIS_T0_SIZE) {
- return ERR_INVALID;
+ return error::incorrect_size;
}
// Check that file already exists
ensure_dir_loaded();
auto it = scan_dir(filename);
if (it == m_dir.end()) {
- return ERR_NOT_FOUND;
+ return error::not_found;
}
// De-allocate current blocks
@@ -372,7 +372,7 @@ err_t isis_impl::file_write(const std::vector<std::string> &path, const std::vec
if (is_t0) {
allocate_t0(lbas);
} else if (!allocate(data.size(), lbas)) {
- return ERR_NO_SPACE;
+ return error::no_space;
}
// Update dir entry
@@ -386,10 +386,10 @@ err_t isis_impl::file_write(const std::vector<std::string> &path, const std::vec
// Update directory & map
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
-err_t isis_impl::format(const meta_data &meta)
+std::error_condition isis_impl::format(const meta_data &meta)
{
entry dir_e;
dir_e.m_alloc_state = DIR_IN_USE;
@@ -442,7 +442,7 @@ err_t isis_impl::format(const meta_data &meta)
}
store_dir_map();
- return ERR_OK;
+ return std::error_condition();
}
isis_impl::lba_t isis_impl::ts_2_lba(const track_sect &ts) const
@@ -786,14 +786,14 @@ isis_impl::lba_list isis_impl::get_file_allocation(lba_t first_link, unsigned si
res.push_back(curr_map);
// Get a linkage block
auto map_sect = m_blockdev.get(curr_map);
- auto prev_ptr = lba_from_2b(map_sect , 0);
- auto next_ptr = lba_from_2b(map_sect , 2);
+ auto prev_ptr = lba_from_2b(*map_sect , 0);
+ auto next_ptr = lba_from_2b(*map_sect , 2);
if (prev_lba != prev_ptr) {
throw std::runtime_error(util::string_format("Incorrect backward linking in sector %d", curr_map));
}
// Scan all pointers in linkage block
for (u32 i = 4; i < SECTOR_SIZE; i += 2) {
- auto ptr = lba_from_2b(map_sect , i);
+ auto ptr = lba_from_2b(*map_sect , i);
if (size > 0) {
if (ptr < 0) {
throw std::runtime_error(util::string_format("Unexpected end of pointer list in sector %d", curr_map));
@@ -839,7 +839,7 @@ std::vector<u8> isis_impl::get_file_content(const lba_list& sects, unsigned size
if ((idx % (PTRS_PER_BLOCK + 1)) != 0) {
unsigned to_copy = std::min(size, SECTOR_SIZE);
auto data_sect = m_blockdev.get(sects[ idx ]);
- memcpy(res.data() + pos, data_sect.rodata(), to_copy);
+ data_sect->read(0, res.data() + pos, to_copy);
size -= to_copy;
pos += to_copy;
}
@@ -856,7 +856,7 @@ void isis_impl::store_file_content(const lba_list& sects, const std::vector<u8>&
lba_t link_lba = sects[ idx ];
auto blk = m_blockdev.get(link_lba);
// Pointer to previous block
- lba_to_2b(prev_ptr, blk, 0);
+ lba_to_2b(prev_ptr, *blk, 0);
prev_ptr = link_lba;
lba_t next_ptr;
if (sects.size() - idx > (PTRS_PER_BLOCK + 1)) {
@@ -867,10 +867,10 @@ void isis_impl::store_file_content(const lba_list& sects, const std::vector<u8>&
next_ptr = -1;
}
// Pointer to next block
- lba_to_2b(next_ptr, blk, 2);
+ lba_to_2b(next_ptr, *blk, 2);
// Pointers to data blocks
for (unsigned j = 0; j < PTRS_PER_BLOCK; j++) {
- lba_to_2b((j + idx + 1 < sects.size()) ? sects[ j + idx + 1 ] : -1, blk, 4 + 2 * j);
+ lba_to_2b((j + idx + 1 < sects.size()) ? sects[ j + idx + 1 ] : -1, *blk, 4 + 2 * j);
}
}
// Write data blocks
@@ -883,7 +883,7 @@ void isis_impl::store_file_content(const lba_list& sects, const std::vector<u8>&
}
u32 count = std::min<u32>(to_go, SECTOR_SIZE);
auto blk = m_blockdev.get(sects[ idx ]);
- blk.copy(0, ptr, count);
+ blk->write(0, ptr, count);
ptr += count;
to_go -= count;
}
diff --git a/src/lib/formats/fs_oric_jasmin.cpp b/src/lib/formats/fs_oric_jasmin.cpp
index 8cc79d917a1..db24a4a93f8 100644
--- a/src/lib/formats/fs_oric_jasmin.cpp
+++ b/src/lib/formats/fs_oric_jasmin.cpp
@@ -56,20 +56,20 @@ public:
virtual ~oric_jasmin_impl() = default;
virtual meta_data volume_metadata() override;
- virtual err_t volume_metadata_change(const meta_data &info) override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition volume_metadata_change(const meta_data &info) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::error_condition metadata_change(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath) override;
- virtual err_t remove(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::error_condition rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath) override;
+ virtual std::error_condition remove(const std::vector<std::string> &path) override;
- virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::error_condition format(const meta_data &meta) override;
static bool validate_filename(std::string name);
@@ -88,7 +88,7 @@ private:
static std::string file_name_prepare(std::string name);
static bool file_is_system(const u8 *entry);
meta_data file_metadata(const u8 *entry);
- std::tuple<fsblk_t::block_t, u32, bool> file_find(std::string name);
+ std::tuple<fsblk_t::block_t::ptr, u32, bool> file_find(std::string name);
};
}
@@ -196,40 +196,40 @@ bool oric_jasmin_impl::validate_filename(std::string name)
return name.size() > 0 && name.size() <= 8;
}
-err_t oric_jasmin_impl::format(const meta_data &meta)
+std::error_condition oric_jasmin_impl::format(const meta_data &meta)
{
std::string volume_name = meta.get_string(meta_name::name, "UNTITLED");
u32 blocks = m_blockdev.block_count();
- m_blockdev.fill(0x6c);
+ m_blockdev.fill_all(0x6c);
u32 bblk = 20*17;
auto fmap = m_blockdev.get(bblk);
u32 off = 0;
for(u32 blk = 0; blk != blocks; blk += 17) {
if(blk == bblk)
- fmap.w24l(off, 0x07fff);
+ fmap->w24l(off, 0x07fff);
else
- fmap.w24l(off, 0x1ffff);
+ fmap->w24l(off, 0x1ffff);
off += 3;
}
for(u32 blk = blocks; blk != 17*42*2; blk += 17) {
- fmap.w24l(off, 0x800000);
+ fmap->w24l(off, 0x800000);
off += 3;
}
- fmap.w8(0xf6, 0x80);
- fmap.w8(0xf7, 0x80);
+ fmap->w8(0xf6, 0x80);
+ fmap->w8(0xf7, 0x80);
volume_name.resize(8, ' ');
- fmap.wstr(0xf8, volume_name);
+ fmap->wstr(0xf8, volume_name);
auto bdir = m_blockdev.get(20*17+1);
- bdir.fill(0xff);
- bdir.w16l(0, 0x0000);
- bdir.w16l(2, 0x0000);
+ bdir->fill(0xff);
+ bdir->w16l(0, 0x0000);
+ bdir->w16l(2, 0x0000);
- return ERR_OK;
+ return std::error_condition();
}
meta_data oric_jasmin_impl::volume_metadata()
@@ -237,21 +237,21 @@ meta_data oric_jasmin_impl::volume_metadata()
meta_data res;
auto bdir = m_blockdev.get(20*17);
int len = 8;
- while(len > 0 && bdir.rodata()[0xf8 + len - 1] == ' ')
+ while(len > 0 && bdir->rodata()[0xf8 + len - 1] == ' ')
len--;
- res.set(meta_name::name, bdir.rstr(0xf8, len));
+ res.set(meta_name::name, bdir->rstr(0xf8, len));
return res;
}
-err_t oric_jasmin_impl::volume_metadata_change(const meta_data &meta)
+std::error_condition oric_jasmin_impl::volume_metadata_change(const meta_data &meta)
{
if(meta.has(meta_name::name)) {
std::string volume_name = meta.get_string(meta_name::name);
volume_name.resize(8, ' ');
- m_blockdev.get(20*17).wstr(0xf8, volume_name);
+ m_blockdev.get(20*17)->wstr(0xf8, volume_name);
}
- return ERR_OK;
+ return std::error_condition();
}
std::string oric_jasmin_impl::file_name_prepare(std::string fname)
@@ -315,28 +315,28 @@ meta_data oric_jasmin_impl::file_metadata(const u8 *entry)
else {
u16 ref = get_u16be(entry);
auto dblk = m_blockdev.get(cs_to_block(ref));
- res.set(meta_name::loading_address, dblk.r16l(2));
- res.set(meta_name::length, dblk.r16l(4));
+ res.set(meta_name::loading_address, dblk->r16l(2));
+ res.set(meta_name::length, dblk->r16l(4));
}
return res;
}
-std::tuple<fsblk_t::block_t, u32, bool> oric_jasmin_impl::file_find(std::string name)
+std::tuple<fsblk_t::block_t::ptr, u32, bool> oric_jasmin_impl::file_find(std::string name)
{
name = file_name_prepare(name);
auto bdir = m_blockdev.get(20*17+1);
for(;;) {
for(u32 i = 0; i != 14; i ++) {
u32 off = 4 + i*18;
- u16 fref = bdir.r16b(off);
- if(ref_valid(fref) || file_is_system(bdir.rodata()+off)) {
- if(memcmp(bdir.rodata() + off + 3, name.data(), 12)) {
- bool sys = file_is_system(bdir.rodata() + off);
+ u16 fref = bdir->r16b(off);
+ if(ref_valid(fref) || file_is_system(bdir->rodata()+off)) {
+ if(memcmp(bdir->rodata() + off + 3, name.data(), 12)) {
+ bool sys = file_is_system(bdir->rodata() + off);
return std::make_tuple(bdir, off, sys);
}
}
}
- u16 ref = bdir.r16b(2);
+ u16 ref = bdir->r16b(2);
if(!ref || !ref_valid(ref))
return std::make_tuple(bdir, 0U, false);
@@ -344,29 +344,29 @@ std::tuple<fsblk_t::block_t, u32, bool> oric_jasmin_impl::file_find(std::string
}
}
-std::pair<err_t, meta_data> oric_jasmin_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> oric_jasmin_impl::metadata(const std::vector<std::string> &path)
{
if(path.size() != 1)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
auto [bdir, off, sys] = file_find(path[0]);
std::ignore = sys;
if(!off)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, file_metadata(bdir.rodata() + off));
+ return std::make_pair(std::error_condition(), file_metadata(bdir->rodata() + off));
}
-err_t oric_jasmin_impl::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition oric_jasmin_impl::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
{
if(path.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off, sys] = file_find(path[0]);
if(!off)
- return ERR_NOT_FOUND;
+ return error::not_found;
- u8 *entry = bdir.data() + off;
+ u8 *entry = bdir->data() + off;
if(meta.has(meta_name::locked))
entry[0x02] = meta.get_flag(meta_name::locked) ? 'L' : 'U';
if(meta.has(meta_name::name))
@@ -374,33 +374,33 @@ err_t oric_jasmin_impl::metadata_change(const std::vector<std::string> &path, co
if(meta.has(meta_name::sequential))
entry[0x0f] = meta.get_flag(meta_name::sequential) ? 'D' : 'S';
if(!sys && meta.has(meta_name::loading_address))
- m_blockdev.get(cs_to_block(get_u16be(entry))).w16l(2, meta.get_number(meta_name::loading_address));
+ m_blockdev.get(cs_to_block(get_u16be(entry)))->w16l(2, meta.get_number(meta_name::loading_address));
- return ERR_OK;
+ return std::error_condition();
}
-std::pair<err_t, std::vector<dir_entry>> oric_jasmin_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> oric_jasmin_impl::directory_contents(const std::vector<std::string> &path)
{
- std::pair<err_t, std::vector<dir_entry>> res;
+ std::pair<std::error_condition, std::vector<dir_entry>> res;
if(path.size() != 0) {
- res.first = ERR_NOT_FOUND;
+ res.first = error::not_found;
return res;
}
- res.first = ERR_OK;
+ res.first = std::error_condition();
auto bdir = m_blockdev.get(20*17+1);
for(;;) {
for(u32 i = 0; i != 14; i ++) {
u32 off = 4 + i*18;
- u16 fref = bdir.r16b(off);
- if(ref_valid(fref) || file_is_system(bdir.rodata()+off)) {
- meta_data meta = file_metadata(bdir.rodata()+off);
+ u16 fref = bdir->r16b(off);
+ if(ref_valid(fref) || file_is_system(bdir->rodata()+off)) {
+ meta_data meta = file_metadata(bdir->rodata()+off);
res.second.emplace_back(dir_entry(dir_entry_type::file, meta));
}
}
- u16 ref = bdir.r16b(2);
+ u16 ref = bdir->r16b(2);
if(!ref || !ref_valid(ref))
break;
bdir = m_blockdev.get(cs_to_block(ref));
@@ -408,30 +408,30 @@ std::pair<err_t, std::vector<dir_entry>> oric_jasmin_impl::directory_contents(co
return res;
}
-err_t oric_jasmin_impl::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
+std::error_condition oric_jasmin_impl::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
{
if(opath.size() != 1 || npath.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off, sys] = file_find(opath[0]);
std::ignore = sys;
if(!off)
- return ERR_NOT_FOUND;
+ return error::not_found;
- wstr(bdir.data() + off + 0x03, file_name_prepare(npath[0]));
+ wstr(bdir->data() + off + 0x03, file_name_prepare(npath[0]));
- return ERR_OK;
+ return std::error_condition();
}
-err_t oric_jasmin_impl::remove(const std::vector<std::string> &path)
+std::error_condition oric_jasmin_impl::remove(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return error::unsupported;
}
-err_t oric_jasmin_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition oric_jasmin_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
if(path.size() != 0)
- return ERR_NOT_FOUND;
+ return error::not_found;
// One block of sector list, one block of data
u32 nb = 2;
@@ -442,12 +442,12 @@ err_t oric_jasmin_impl::file_create(const std::vector<std::string> &path, const
for(;;) {
for(u32 i = 0; i != 14; i ++) {
u32 off = 4 + i*18;
- u16 ref = bdir.r16b(off);
+ u16 ref = bdir->r16b(off);
if(!ref_valid(ref))
goto found;
id++;
}
- u16 ref = bdir.r16b(2);
+ u16 ref = bdir->r16b(2);
if(!ref || !ref_valid(ref)) {
nb ++;
break;
@@ -457,68 +457,68 @@ err_t oric_jasmin_impl::file_create(const std::vector<std::string> &path, const
found:
auto block = allocate_blocks(nb);
if(block.empty())
- return ERR_NO_SPACE;
+ return error::no_space;
auto sblk = m_blockdev.get(cs_to_block(block[0]));
- sblk.w16b(0, 0xff00); // Next sector
- sblk.w16l(2, meta.get_number(meta_name::loading_address, 0x500));
- sblk.w16l(4, 0); // Length
- sblk.w16b(6, block[1]); // Data block
+ sblk->w16b(0, 0xff00); // Next sector
+ sblk->w16l(2, meta.get_number(meta_name::loading_address, 0x500));
+ sblk->w16l(4, 0); // Length
+ sblk->w16b(6, block[1]); // Data block
if(nb == 3) {
- bdir.w16l(0, block[2]); // Link to the next directory sector
+ bdir->w16l(0, block[2]); // Link to the next directory sector
bdir = m_blockdev.get(cs_to_block(block[2]));
- bdir.fill(0xff);
- bdir.w16l(0, block[2]); // Reference to itself
- bdir.w16l(2, 0xff00); // No next directory sector
+ bdir->fill(0xff);
+ bdir->w16l(0, block[2]); // Reference to itself
+ bdir->w16l(2, 0xff00); // No next directory sector
}
u32 off = 4 + (id % 14) * 18;
- bdir.w16b(off+0x00, block[0]); // First (and only) sector in the sector list
- bdir.w8 (off+0x02, meta.get_flag(meta_name::locked, false) ? 'L' : 'U');
- bdir.wstr(off+0x03, file_name_prepare(meta.get_string(meta_name::name, "")));
- bdir.w8 (off+0x0f, meta.get_flag(meta_name::sequential, true) ? 'S' : 'D');
- bdir.w16l(off+0x10, 2); // 2 sectors for an empty file
+ bdir->w16b(off+0x00, block[0]); // First (and only) sector in the sector list
+ bdir->w8 (off+0x02, meta.get_flag(meta_name::locked, false) ? 'L' : 'U');
+ bdir->wstr(off+0x03, file_name_prepare(meta.get_string(meta_name::name, "")));
+ bdir->w8 (off+0x0f, meta.get_flag(meta_name::sequential, true) ? 'S' : 'D');
+ bdir->w16l(off+0x10, 2); // 2 sectors for an empty file
- return ERR_OK;
+ return std::error_condition();
}
-std::pair<err_t, std::vector<u8>> oric_jasmin_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> oric_jasmin_impl::file_read(const std::vector<std::string> &path)
{
std::vector<u8> data;
if(path.size() != 1)
- return std::make_pair(ERR_NOT_FOUND, data);
+ return std::make_pair(error::not_found, data);
auto [bdir, off, sys] = file_find(path[0]);
if(!off)
- return std::make_pair(ERR_NOT_FOUND, data);
+ return std::make_pair(error::not_found, data);
if(sys) {
data.resize(0x3e00);
for(u32 i = 0; i != 62; i++) {
auto dblk = m_blockdev.get(i);
- memcpy(data.data() + 256 * i, dblk.rodata(), 256);
+ dblk->read(0, data.data() + 256 * i, 256);
}
} else {
- const u8 *entry = bdir.rodata() + off;
+ const u8 *entry = bdir->rodata() + off;
u16 ref = get_u16be(entry);
auto iblk = m_blockdev.get(cs_to_block(ref));
- u32 length = iblk.r16l(4);
+ u32 length = iblk->r16l(4);
while(ref_valid(ref)) {
for(u32 pos = 6; pos != 256 && data.size() < length; pos += 2) {
- u16 dref = iblk.r16b(pos);
+ u16 dref = iblk->r16b(pos);
if(!ref_valid(dref))
goto done;
auto dblk = m_blockdev.get(cs_to_block(dref));
u32 dpos = data.size();
data.resize(dpos + 256);
- memcpy(data.data() + dpos, dblk.rodata(), 256);
+ dblk->read(0, data.data() + dpos, 256);
if(data.size() >= length)
goto done;
}
- ref = iblk.r16b(2);
+ ref = iblk->r16b(2);
if(!ref_valid(ref))
break;
iblk = m_blockdev.get(cs_to_block(ref));
@@ -527,27 +527,27 @@ std::pair<err_t, std::vector<u8>> oric_jasmin_impl::file_read(const std::vector<
data.resize(length);
}
- return std::make_pair(ERR_OK, data);
+ return std::make_pair(std::error_condition(), data);
}
-err_t oric_jasmin_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::error_condition oric_jasmin_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
if(path.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off, sys] = file_find(path[0]);
if(!off)
- return ERR_NOT_FOUND;
+ return error::not_found;
if(sys) {
if(data.size() != 0x3e00)
- return ERR_INVALID;
+ return error::incorrect_size;
for(u32 i=0; i != 0x3e; i++)
- m_blockdev.get(i).copy(0, data.data() + i * 256, 256);
+ m_blockdev.get(i)->write(0, data.data() + i * 256, 256);
} else {
- u8 *entry = bdir.data() + off;
+ u8 *entry = bdir->data() + off;
u32 cur_ns = get_u16le(entry + 0x10);
// Data sectors first
u32 need_ns = (data.size() + 255) / 256;
@@ -558,7 +558,7 @@ err_t oric_jasmin_impl::file_write(const std::vector<std::string> &path, const s
// Enough space?
if(cur_ns < need_ns && free_block_count() < need_ns - cur_ns)
- return ERR_NO_SPACE;
+ return error::no_space;
u16 load_address = 0;
std::vector<u16> tofree;
@@ -566,44 +566,44 @@ err_t oric_jasmin_impl::file_write(const std::vector<std::string> &path, const s
for(u32 i=0; i < cur_ns; i += 125+1) {
auto iblk = m_blockdev.get(cs_to_block(iref));
if(!i)
- load_address = iblk.r16l(2);
+ load_address = iblk->r16l(2);
tofree.push_back(iref);
for(u32 j=0; j != 125 && i+j+1 != cur_ns; j++)
- tofree.push_back(iblk.r16b(6+2*j));
- iref = iblk.r16b(2);
+ tofree.push_back(iblk->r16b(6+2*j));
+ iref = iblk->r16b(2);
}
free_blocks(tofree);
std::vector<u16> blocks = allocate_blocks(need_ns);
for(u32 i=0; i < need_ns; i += 125+1) {
auto iblk = m_blockdev.get(cs_to_block(blocks[i]));
- iblk.fill(0xff);
+ iblk->fill(0xff);
if(!i) {
- iblk.w16l(2, load_address);
- iblk.w16l(4, data.size());
+ iblk->w16l(2, load_address);
+ iblk->w16l(4, data.size());
}
if(i + 126 < need_ns)
- iblk.w16b(0, blocks[i+126]);
+ iblk->w16b(0, blocks[i+126]);
else
- iblk.w16b(0, 0xff00);
+ iblk->w16b(0, 0xff00);
for(u32 j=0; j != 125 && i+j+1 != need_ns; j++) {
u32 dpos = 256 * (j + i/126*125);
u32 size = data.size() - dpos;
- iblk.w16b(6+j*2, blocks[i+j+1]);
+ iblk->w16b(6+j*2, blocks[i+j+1]);
auto dblk = m_blockdev.get(cs_to_block(blocks[i+j+1]));
if(size >= 256)
- dblk.copy(0, data.data() + dpos, 256);
+ dblk->write(0, data.data() + dpos, 256);
else {
- dblk.copy(0, data.data() + dpos, size);
- dblk.fill(size, 0x55, 256-size);
+ dblk->write(0, data.data() + dpos, size);
+ dblk->fill(size, 0x55, 256-size);
}
}
}
put_u16le(entry + 0x10, need_ns);
put_u16be(entry + 0x00, blocks[0]);
}
- return ERR_OK;
+ return std::error_condition();
}
std::vector<u16> oric_jasmin_impl::allocate_blocks(u32 count)
@@ -615,7 +615,7 @@ std::vector<u16> oric_jasmin_impl::allocate_blocks(u32 count)
auto fmap = m_blockdev.get(20*17);
u32 nf = 0;
for(u32 track = 0; track != 2*41 && nf != count; track++) {
- u32 map = fmap.r24l(track*3);
+ u32 map = fmap->r24l(track*3);
if(map != 0x800000) {
for(u32 sect = 1; sect <= 17 && nf != count; sect++)
if(map & (0x20000 >> sect)) {
@@ -625,7 +625,7 @@ std::vector<u16> oric_jasmin_impl::allocate_blocks(u32 count)
}
if(!map)
map = 0x800000;
- fmap.w24l(track*3, map);
+ fmap->w24l(track*3, map);
}
}
return blocks;
@@ -637,11 +637,11 @@ void oric_jasmin_impl::free_blocks(const std::vector<u16> &blocks)
for(u16 ref : blocks) {
u32 track = ref >> 8;
u32 sect = ref & 0xff;
- u32 map = fmap.r24l(track*3);
+ u32 map = fmap->r24l(track*3);
if(map == 0x800000)
map = 0;
map |= 0x20000 >> sect;
- fmap.w24l(track*3, map);
+ fmap->w24l(track*3, map);
}
}
@@ -650,7 +650,7 @@ u32 oric_jasmin_impl::free_block_count()
auto fmap = m_blockdev.get(20*17);
u32 nf = 0;
for(u32 track = 0; track != 2*41; track++) {
- u32 map = fmap.r24l(track*3);
+ u32 map = fmap->r24l(track*3);
if(map != 0x800000) {
for(u32 sect = 1; sect <= 17; sect++)
if(map & (0x20000 >> sect))
diff --git a/src/lib/formats/fs_prodos.cpp b/src/lib/formats/fs_prodos.cpp
index 826aecec91f..f7c77d47ff8 100644
--- a/src/lib/formats/fs_prodos.cpp
+++ b/src/lib/formats/fs_prodos.cpp
@@ -5,11 +5,14 @@
#include "fs_prodos.h"
#include "ap_dsk35.h"
+#include "ap2_dsk.h"
#include "fsblk.h"
+#include "corestr.h"
#include "multibyte.h"
#include "strformat.h"
+#include <map>
#include <stdexcept>
using namespace fs;
@@ -23,22 +26,22 @@ public:
virtual ~prodos_impl() = default;
virtual meta_data volume_metadata() override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual std::pair<err_t, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::error_condition format(const meta_data &meta) override;
private:
static const u8 boot[512];
static util::arbitrary_datetime prodos_to_dt(u32 date);
- std::tuple<fsblk_t::block_t, u32> path_find_step(const std::string &name, u16 block);
- std::tuple<fsblk_t::block_t, u32, bool> path_find(const std::vector<std::string> &path);
- std::pair<err_t, std::vector<u8>> any_read(u8 type, u16 block, u32 length);
+ std::tuple<fsblk_t::block_t::ptr, u32> path_find_step(const std::string &name, u16 block);
+ std::tuple<fsblk_t::block_t::ptr, u32, bool> path_find(const std::vector<std::string> &path);
+ std::pair<std::error_condition, std::vector<u8>> any_read(u8 type, u16 block, u32 length);
};
}
@@ -90,8 +93,9 @@ const u8 prodos_impl::boot[512] = {
void prodos_image::enumerate_f(floppy_enumerator &fe) const
{
- fe.add(FLOPPY_APPLE_GCR_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 819200, "prodos_800k", "Apple ProDOS 800K");
- fe.add(FLOPPY_APPLE_GCR_FORMAT, floppy_image::FF_35, floppy_image::SSDD, 409600, "prodos_400k", "Apple ProDOS 400K");
+ fe.add(FLOPPY_APPLE_GCR_FORMAT, floppy_image::FF_35, floppy_image::DSDD, 819200, "prodos_800k", "Apple ProDOS 3.5\" 800K");
+ fe.add(FLOPPY_APPLE_GCR_FORMAT, floppy_image::FF_35, floppy_image::SSDD, 409600, "prodos_400k", "Apple ProDOS 3.5\" 400K");
+ fe.add(FLOPPY_A216S_PRODOS_FORMAT, floppy_image::FF_525, floppy_image::SSSD, 143360, "prodos_140k", "Apple ProDOS 5.25\" 140K");
}
std::unique_ptr<filesystem_t> prodos_image::mount(fsblk_t &blockdev) const
@@ -124,6 +128,46 @@ char prodos_image::directory_separator() const
return '/';
}
+// TODO: this list is incomplete
+static const std::map<u8, const char *> s_file_types =
+{
+ { 0x00, "UNK" },
+ { 0x01, "BAD" },
+ { 0x04, "TXT" },
+ { 0x06, "BIN" },
+ { 0x0f, "DIR" },
+ { 0x19, "ADB" },
+ { 0x1a, "AWP" },
+ { 0x1b, "ASP" },
+ { 0xc9, "FND" },
+ { 0xca, "ICN" },
+ { 0xef, "PAS" },
+ { 0xf0, "CMD" },
+ { 0xfa, "INT" },
+ { 0xfb, "IVR" },
+ { 0xfc, "BAS" },
+ { 0xfd, "VAR" },
+ { 0xfe, "REL" },
+ { 0xff, "SYS" }
+};
+
+static std::string file_type_to_string(uint8_t type)
+{
+ auto res = s_file_types.find(type);
+ if (res != s_file_types.end())
+ return res->second;
+ else
+ return util::string_format("0x%02x", type);
+}
+
+static bool validate_file_type(std::string str)
+{
+ if ((str.length() == 3 || str.length() == 4) && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ return str.find_first_not_of("0123456789ABCDEFabcdef", 2) == std::string::npos;
+ else
+ return std::any_of(s_file_types.begin(), s_file_types.end(), [&str](const auto &pair) { return util::strequpper(str, pair.second); });
+}
+
std::vector<meta_description> prodos_image::volume_meta_description() const
{
std::vector<meta_description> res;
@@ -143,6 +187,7 @@ std::vector<meta_description> prodos_image::file_meta_description() const
res.emplace_back(meta_description(meta_name::name, "Empty file", false, [](const meta_value &m) { return m.as_string().size() <= 15; }, "File name, up to 15 characters"));
res.emplace_back(meta_description(meta_name::length, 0, true, nullptr, "Size of the file in bytes"));
res.emplace_back(meta_description(meta_name::rsrc_length, 0, true, nullptr, "Size of the resource fork in bytes"));
+ res.emplace_back(meta_description(meta_name::file_type, "UNK", false, [](const meta_value &m) { return validate_file_type(m.as_string()); }, "File type, 3 letters or hex code preceded by 0x"));
res.emplace_back(meta_description(meta_name::os_version, 5, false, [](const meta_value &m) { return m.as_number() <= 255; }, "Creator OS version"));
res.emplace_back(meta_description(meta_name::os_minimum_version, 5, false, [](const meta_value &m) { return m.as_number() <= 255; }, "Minimum OS version"));
@@ -165,7 +210,7 @@ std::vector<meta_description> prodos_image::directory_meta_description() const
return res;
}
-err_t prodos_impl::format(const meta_data &meta)
+std::error_condition prodos_impl::format(const meta_data &meta)
{
std::string volume_name = meta.get_string(meta_name::name, "UNTITLED");
u32 blocks = m_blockdev.block_count();
@@ -174,36 +219,36 @@ err_t prodos_impl::format(const meta_data &meta)
if(blocks >= 0x10000)
blocks = 0xffff;
- m_blockdev.get(0).copy(0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs
- m_blockdev.get(1).fill(0x00); // No SOS boot sector
+ m_blockdev.get(0)->write(0x000, boot, 0x200); // Standard ProDOS boot sector as written by a 2gs
+ m_blockdev.get(1)->fill(0x00); // No SOS boot sector
auto kblk1 = m_blockdev.get(2); // key block first block
auto kblk2 = m_blockdev.get(3); // key block second block
auto kblk3 = m_blockdev.get(4); // key block third block
auto kblk4 = m_blockdev.get(5); // key block fourth block
- kblk1.w16l(0x00, 0x0000); // Backwards key block pointer (null)
- kblk1.w16l(0x02, 0x0003); // Forwards key block pointer
- kblk1.w8 (0x04, 0xf0 | volume_name.size()); // Block type (f, key block) and name size
- kblk1.wstr(0x05, volume_name); // Volume name, up to 15 characters
- kblk1.w32b(0x16, 0x642a250d); // ??? date & time
- kblk1.w16b(0x1a, 0x80ff); // ???
- kblk1.w32b(0x1c, 0x642a250d); // Creation date & time
- kblk1.w8 (0x20, 0x05); // ProDOS version (2gs)
- kblk1.w8 (0x21, 0x00); // ProDOS minimum version
- kblk1.w8 (0x22, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read)
- kblk1.w8 (0x23, 0x27); // Directory entry length (fixed)
- kblk1.w8 (0x24, 0x0d); // Entries per block (fixed)
- kblk1.w16l(0x25, 0x0000); // Number of file entries in the directory
- kblk1.w16l(0x27, 0x0006); // Bitmap block pointer
- kblk1.w16l(0x29, blocks); // Number of blocks
-
- kblk2.w16l(0x00, 0x0002); // Backwards block pointer of the second volume block
- kblk2.w16l(0x02, 0x0004); // Forwards block pointer of the second volume block
- kblk3.w16l(0x00, 0x0003); // Backwards block pointer of the third volume block
- kblk3.w16l(0x02, 0x0005); // Forwards block pointer of the third volume block
- kblk4.w16l(0x00, 0x0004); // Backwards block pointer of the fourth volume block
- kblk4.w16l(0x02, 0x0000); // Forwards block pointer of the fourth volume block (null)
+ kblk1->w16l(0x00, 0x0000); // Backwards key block pointer (null)
+ kblk1->w16l(0x02, 0x0003); // Forwards key block pointer
+ kblk1->w8 (0x04, 0xf0 | volume_name.size()); // Block type (f, key block) and name size
+ kblk1->wstr(0x05, volume_name); // Volume name, up to 15 characters
+ kblk1->w32b(0x16, 0x642a250d); // ??? date & time
+ kblk1->w16b(0x1a, 0x80ff); // ???
+ kblk1->w32b(0x1c, 0x642a250d); // Creation date & time
+ kblk1->w8 (0x20, 0x05); // ProDOS version (2gs)
+ kblk1->w8 (0x21, 0x00); // ProDOS minimum version
+ kblk1->w8 (0x22, 0xc3); // Allowed access (destroy, rename, !backup, 3x0, write read)
+ kblk1->w8 (0x23, 0x27); // Directory entry length (fixed)
+ kblk1->w8 (0x24, 0x0d); // Entries per block (fixed)
+ kblk1->w16l(0x25, 0x0000); // Number of file entries in the directory
+ kblk1->w16l(0x27, 0x0006); // Bitmap block pointer
+ kblk1->w16l(0x29, blocks); // Number of blocks
+
+ kblk2->w16l(0x00, 0x0002); // Backwards block pointer of the second volume block
+ kblk2->w16l(0x02, 0x0004); // Forwards block pointer of the second volume block
+ kblk3->w16l(0x00, 0x0003); // Backwards block pointer of the third volume block
+ kblk3->w16l(0x02, 0x0005); // Forwards block pointer of the third volume block
+ kblk4->w16l(0x00, 0x0004); // Backwards block pointer of the fourth volume block
+ kblk4->w16l(0x02, 0x0000); // Forwards block pointer of the fourth volume block (null)
u32 fmap_block_count = (blocks + 4095) / 4096;
u32 first_free_block = 6 + fmap_block_count;
@@ -211,7 +256,7 @@ err_t prodos_impl::format(const meta_data &meta)
// Mark blocks from first_free_block to blocks-1 (the last one) as free
for(u32 i = 0; i != fmap_block_count; i++) {
auto fmap = m_blockdev.get(6 + i);
- u8 *fdata = fmap.data();
+ u8 *fdata = fmap->data();
u32 start = i ? 0 : first_free_block;
u32 end = i != fmap_block_count - 1 ? 4095 : (blocks - 1) & 4095;
end += 1;
@@ -229,7 +274,7 @@ err_t prodos_impl::format(const meta_data &meta)
memset(fdata+sb, 0xff, eb-sb-1);
}
}
- return ERR_OK;
+ return std::error_condition();
}
prodos_impl::prodos_impl(fsblk_t &blockdev) : filesystem_t(blockdev, 512)
@@ -242,8 +287,8 @@ util::arbitrary_datetime prodos_impl::prodos_to_dt(u32 date)
dt.second = 0;
dt.minute = ((date >> 16) & 0x3f);
dt.hour = ((date >> 24) & 0x1f);
- dt.day_of_month = ((date >> 0) & 0x1f);
- dt.month = ((date >> 5) & 0x0f) + 1;
+ dt.day_of_month = ((date >> 0) & 0x1f); // 1-based
+ dt.month = ((date >> 5) & 0x0f); // 1-based
dt.year = ((date >> 9) & 0x7f) + 1900;
if (dt.year <= 1949)
dt.year += 100;
@@ -255,16 +300,16 @@ meta_data prodos_impl::volume_metadata()
{
meta_data res;
auto bdir = m_blockdev.get(2);
- int len = bdir.r8(0x04) & 0xf;
- res.set(meta_name::name, bdir.rstr(0x05, len));
- res.set(meta_name::os_version, bdir.r8(0x20));
- res.set(meta_name::os_minimum_version, bdir.r8(0x21));
- res.set(meta_name::creation_date, prodos_to_dt(bdir.r32l(0x1c)));
- res.set(meta_name::modification_date, prodos_to_dt(bdir.r32l(0x16)));
+ int len = bdir->r8(0x04) & 0xf;
+ res.set(meta_name::name, bdir->rstr(0x05, len));
+ res.set(meta_name::os_version, bdir->r8(0x20));
+ res.set(meta_name::os_minimum_version, bdir->r8(0x21));
+ res.set(meta_name::creation_date, prodos_to_dt(bdir->r32l(0x1c)));
+ res.set(meta_name::modification_date, prodos_to_dt(bdir->r32l(0x16)));
return res;
}
-std::pair<err_t, std::vector<dir_entry>> prodos_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> prodos_impl::directory_contents(const std::vector<std::string> &path)
{
u16 block;
if(path.empty())
@@ -273,62 +318,66 @@ std::pair<err_t, std::vector<dir_entry>> prodos_impl::directory_contents(const s
else {
auto [blk, off, dir] = path_find(path);
if(!off || !dir)
- return std::make_pair(ERR_NOT_FOUND, std::vector<dir_entry>());
- block = blk.r16l(off+0x11);
+ return std::make_pair(error::not_found, std::vector<dir_entry>());
+ block = blk->r16l(off+0x11);
}
std::vector<dir_entry> res;
- u32 off = 39 + 4;
do {
auto blk = m_blockdev.get(block);
- while(off < 511) {
- meta_data meta;
- u8 type = blk.r8(off);
- meta.set(meta_name::name, blk.rstr(off+1, type & 0xf));
- type >>= 4;
-
- if(type == 5) {
- auto rootblk = m_blockdev.get(blk.r16l(off+0x11));
- meta.set(meta_name::length, rootblk.r24l(0x005));
- meta.set(meta_name::rsrc_length, rootblk.r24l(0x105));
-
- } else if(type >= 1 && type <= 3)
- meta.set(meta_name::length, blk.r24l(off + 0x15));
-
- res.emplace_back(dir_entry(type == 0xd ? dir_entry_type::dir : dir_entry_type::file, meta));
- off += 39;
+ for(u32 off = 4; off < 511; off += 39) {
+ u8 type = blk->r8(off);
+ // skip inactive entries and subroutine/volume headers
+ if(type != 0 && type < 0xe0) {
+ meta_data meta;
+ meta.set(meta_name::name, blk->rstr(off+1, type & 0xf));
+ type >>= 4;
+
+ if(type == 5) {
+ auto rootblk = m_blockdev.get(blk->r16l(off+0x11));
+ meta.set(meta_name::length, rootblk->r24l(0x005));
+ meta.set(meta_name::rsrc_length, rootblk->r24l(0x105));
+
+ } else if(type >= 1 && type <= 3) {
+ meta.set(meta_name::length, blk->r24l(off + 0x15));
+ meta.set(meta_name::file_type, file_type_to_string(blk->r8(off + 0x10)));
+ }
+
+ meta.set(meta_name::os_version, blk->r8(off + 0x1c));
+ meta.set(meta_name::os_minimum_version, blk->r8(off + 0x1d));
+ meta.set(meta_name::creation_date, prodos_to_dt(blk->r32l(off + 0x18)));
+ meta.set(meta_name::modification_date, prodos_to_dt(blk->r32l(off + 0x21)));
+
+ res.emplace_back(dir_entry(type == 0xd ? dir_entry_type::dir : dir_entry_type::file, meta));
+ }
}
- block = blk.r16l(2);
+ block = blk->r16l(2);
if(block >= m_blockdev.block_count())
break;
- off = 4;
} while(block);
- return std::make_pair(ERR_OK, res);
+ return std::make_pair(std::error_condition(), res);
}
-std::tuple<fsblk_t::block_t, u32> prodos_impl::path_find_step(const std::string &name, u16 block)
+std::tuple<fsblk_t::block_t::ptr, u32> prodos_impl::path_find_step(const std::string &name, u16 block)
{
- u32 off = 39 + 4;
for(;;) {
auto blk = m_blockdev.get(block);
- while(off < 511) {
- u8 type = blk.r8(off);
- if(name == blk.rstr(off+1, type & 0xf))
+ for(u32 off = 4; off < 511; off += 39) {
+ u8 type = blk->r8(off);
+ if(type != 0 && type < 0xe0 && name == blk->rstr(off+1, type & 0xf))
return std::make_tuple(blk, off);
- off += 39;
}
- block = blk.r16l(2);
+ block = blk->r16l(2);
if(!block || block >= m_blockdev.block_count())
return std::make_tuple(blk, 0U);
- off = 4;
}
}
-std::tuple<fsblk_t::block_t, u32, bool> prodos_impl::path_find(const std::vector<std::string> &path)
+std::tuple<fsblk_t::block_t::ptr, u32, bool> prodos_impl::path_find(const std::vector<std::string> &path)
{
if(path.size() == 0)
- return std::tuple<fsblk_t::block_t, u32, bool>(fsblk_t::block_t(), 0, false);
+ return std::tuple<fsblk_t::block_t::ptr, u32, bool>(fsblk_t::block_t::ptr(), 0, false);
u16 block = 2;
for(u32 pathc = 0;; pathc++) {
@@ -337,27 +386,27 @@ std::tuple<fsblk_t::block_t, u32, bool> prodos_impl::path_find(const std::vector
return std::make_tuple(blk, off, false);
if(pathc + 1 == path.size())
- return std::make_tuple(blk, off, (blk.r8(off) & 0xf0) == 0xd0);
+ return std::make_tuple(blk, off, (blk->r8(off) & 0xf0) == 0xd0);
- if((blk.r8(off) & 0xf0) != 0xd0)
+ if((blk->r8(off) & 0xf0) != 0xd0)
return std::make_tuple(blk, 0U, false);
- block = blk.r16l(off + 0x11);
+ block = blk->r16l(off + 0x11);
}
}
-std::pair<err_t, meta_data> prodos_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> prodos_impl::metadata(const std::vector<std::string> &path)
{
if(path.size() == 0)
- return std::make_pair(ERR_OK, meta_data());
+ return std::make_pair(std::error_condition(), meta_data());
auto [blk, off, dir] = path_find(path);
if(!off)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- const u8 *entry = blk.rodata() + off;
+ const u8 *entry = blk->rodata() + off;
meta_data res;
if(dir) {
@@ -371,23 +420,23 @@ std::pair<err_t, meta_data> prodos_impl::metadata(const std::vector<std::string>
res.set(meta_name::name, name);
if(type == 5) {
auto rootblk = m_blockdev.get(get_u16le(entry+0x11));
- res.set(meta_name::length, rootblk.r24l(0x005));
- res.set(meta_name::rsrc_length, rootblk.r24l(0x105));
+ res.set(meta_name::length, rootblk->r24l(0x005));
+ res.set(meta_name::rsrc_length, rootblk->r24l(0x105));
} else if(type >= 1 && type <= 3)
res.set(meta_name::length, get_u24le(entry + 0x15));
else
- return std::make_pair(ERR_UNSUPPORTED, meta_data());
+ return std::make_pair(error::unsupported, meta_data());
}
- return std::make_pair(ERR_OK, res);
+ return std::make_pair(std::error_condition(), res);
}
-std::pair<err_t, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32 length)
+std::pair<std::error_condition, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32 length)
{
- std::pair<err_t, std::vector<u8>> data;
- data.first = ERR_OK;
+ std::pair<std::error_condition, std::vector<u8>> data;
+ data.first = std::error_condition();
data.second.resize((length + 511) & ~511);
u32 nb = data.second.size()/512;
if(!nb)
@@ -397,15 +446,15 @@ std::pair<err_t, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32
u8 *end = dst + data.second.size();
switch(type) {
case 1:
- memcpy(dst, m_blockdev.get(block).rodata(), 512);
+ m_blockdev.get(block)->read(0, dst, 512);
dst += 512;
break;
case 2: {
auto iblk = m_blockdev.get(block);
for(u32 i=0; i != 256 && dst != end; i++) {
- u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
- memcpy(dst, m_blockdev.get(blk).rodata(), 512);
+ u16 blk = iblk->r8(i) | (iblk->r8(i | 0x100) << 8);
+ m_blockdev.get(blk)->read(0, dst, 512);
dst += 512;
}
break;
@@ -415,10 +464,10 @@ std::pair<err_t, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32
auto mblk = m_blockdev.get(block);
for(u32 j=0; dst != end; j += 256) {
u32 idx = j/256;
- auto iblk = m_blockdev.get(mblk.r8(idx) | (mblk.r8(idx | 0x100) << 8));
+ auto iblk = m_blockdev.get(mblk->r8(idx) | (mblk->r8(idx | 0x100) << 8));
for(u32 i=0; i != 256 && dst != end; i++) {
- u16 blk = iblk.r8(i) | (iblk.r8(i | 0x100) << 8);
- memcpy(dst, m_blockdev.get(blk).rodata(), 512);
+ u16 blk = iblk->r8(i) | (iblk->r8(i | 0x100) << 8);
+ m_blockdev.get(blk)->read(0, dst, 512);
dst += 512;
}
}
@@ -426,7 +475,7 @@ std::pair<err_t, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32
}
default:
- data.first = ERR_UNSUPPORTED;
+ data.first = error::unsupported;
data.second.clear();
return data;
}
@@ -435,13 +484,13 @@ std::pair<err_t, std::vector<u8>> prodos_impl::any_read(u8 type, u16 block, u32
return data;
}
-std::pair<err_t, std::vector<u8>> prodos_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> prodos_impl::file_read(const std::vector<std::string> &path)
{
auto [blk, off, dir] = path_find(path);
if(!off || dir)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
- const u8 *entry = blk.rodata() + off;
+ const u8 *entry = blk->rodata() + off;
u8 type = entry[0] >> 4;
if(type >= 1 && type <= 3)
@@ -449,25 +498,25 @@ std::pair<err_t, std::vector<u8>> prodos_impl::file_read(const std::vector<std::
else if(type == 5) {
auto kblk = m_blockdev.get(get_u16le(entry+0x11));
- return any_read(kblk.r8(0x000), kblk.r16l(0x001), kblk.r24l(0x005));
+ return any_read(kblk->r8(0x000), kblk->r16l(0x001), kblk->r24l(0x005));
} else
- return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
+ return std::make_pair(error::unsupported, std::vector<u8>());
}
-std::pair<err_t, std::vector<u8>> prodos_impl::file_rsrc_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> prodos_impl::file_rsrc_read(const std::vector<std::string> &path)
{
auto [blk, off, dir] = path_find(path);
if(!off || dir)
- return std::make_pair(ERR_NOT_FOUND, std::vector<u8>());
+ return std::make_pair(error::not_found, std::vector<u8>());
- const u8 *entry = blk.rodata() + off;
+ const u8 *entry = blk->rodata() + off;
u8 type = entry[0] >> 4;
if(type == 5) {
auto kblk = m_blockdev.get(get_u16le(entry+0x11));
- return any_read(kblk.r8(0x100), kblk.r16l(0x101), kblk.r24l(0x105));
+ return any_read(kblk->r8(0x100), kblk->r16l(0x101), kblk->r24l(0x105));
} else
- return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
+ return std::make_pair(error::unsupported, std::vector<u8>());
}
diff --git a/src/lib/formats/fs_unformatted.cpp b/src/lib/formats/fs_unformatted.cpp
index df618c6485d..995c2b76148 100644
--- a/src/lib/formats/fs_unformatted.cpp
+++ b/src/lib/formats/fs_unformatted.cpp
@@ -35,11 +35,15 @@ void unformatted_image::enumerate_f(floppy_enumerator &fe) const
u32 best_525 =
form_factor == floppy_image::FF_525 ?
- has_variant(variants, floppy_image::DSHD) ? FSI_525_DSHD :
- has_variant(variants, floppy_image::DSQD) ? FSI_525_DSQD :
- has_variant(variants, floppy_image::DSDD) ? FSI_525_DSDD :
- has_variant(variants, floppy_image::SSQD) ? FSI_525_SSQD :
- has_variant(variants, floppy_image::SSDD) ? FSI_525_SSDD : FSI_525_SSSD
+ has_variant(variants, floppy_image::DSHD) ? FSI_525_DSHD :
+ has_variant(variants, floppy_image::DSQD16) ? FSI_525_DSQD16 :
+ has_variant(variants, floppy_image::DSQD) ? FSI_525_DSQD :
+ has_variant(variants, floppy_image::DSDD16) ? FSI_525_DSDD16 :
+ has_variant(variants, floppy_image::DSDD) ? FSI_525_DSDD :
+ has_variant(variants, floppy_image::SSQD16) ? FSI_525_SSQD16 :
+ has_variant(variants, floppy_image::SSQD) ? FSI_525_SSQD :
+ has_variant(variants, floppy_image::SSDD16) ? FSI_525_SSDD16 :
+ has_variant(variants, floppy_image::SSDD) ? FSI_525_SSDD : FSI_525_SSSD
: FSI_NONE;
u32 best_35 =
@@ -61,14 +65,22 @@ void unformatted_image::enumerate_f(floppy_enumerator &fe) const
if(all || best_525 == FSI_525_DSHD)
fe.add_raw("u525dshd", FSI_525_DSHD, "Unformatted 5\"25 double-sided high-density");
+ if(all || best_525 == FSI_525_DSQD16)
+ fe.add_raw("u525dsqd16", FSI_525_DSQD16, "Unformatted 5\"25 double-sided quad-density 16 hard sectors");
if(all || best_525 == FSI_525_DSQD)
fe.add_raw("u525dsqd", FSI_525_DSQD, "Unformatted 5\"25 double-sided quad-density");
+ if(all || best_525 == FSI_525_DSDD16)
+ fe.add_raw("u525dsdd16", FSI_525_DSDD16, "Unformatted 5\"25 double-sided double-density 16 hard sectors");
if(all || best_525 == FSI_525_DSDD)
fe.add_raw("u525dsdd", FSI_525_DSDD, "Unformatted 5\"25 double-sided double-density");
if(all)
fe.add_raw("u525dssd", FSI_525_DSSD, "Unformatted 5\"25 double-sided single-density");
+ if(all || best_525 == FSI_525_SSQD16)
+ fe.add_raw("u525ssqd16", FSI_525_SSQD16, "Unformatted 5\"25 single-sided quad-density 16 hard sectors");
if(all || best_525 == FSI_525_SSQD)
fe.add_raw("u525ssqd", FSI_525_SSQD, "Unformatted 5\"25 single-sided quad-density");
+ if(all || best_525 == FSI_525_SSDD16)
+ fe.add_raw("u525ssdd16", FSI_525_SSDD16, "Unformatted 5\"25 single-sided double-density 16 hard sectors");
if(all || best_525 == FSI_525_SSDD)
fe.add_raw("u525ssdd", FSI_525_SSDD, "Unformatted 5\"25 single-sided double-density");
if(all || best_525 == FSI_525_SSSD)
@@ -96,13 +108,17 @@ void unformatted_image::format(u32 key, floppy_image *image)
case FSI_8_DSSD: image->set_form_variant(floppy_image::FF_8, floppy_image::DSSD); break;
case FSI_8_SSSD: image->set_form_variant(floppy_image::FF_8, floppy_image::SSSD); break;
- case FSI_525_DSHD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSHD); break;
- case FSI_525_DSQD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSQD); break;
- case FSI_525_DSDD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSDD); break;
- case FSI_525_DSSD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSSD); break;
- case FSI_525_SSQD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSQD); break;
- case FSI_525_SSDD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSDD); break;
- case FSI_525_SSSD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); break;
+ case FSI_525_DSHD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSHD); break;
+ case FSI_525_DSQD16: image->set_form_variant(floppy_image::FF_525, floppy_image::DSQD16); break;
+ case FSI_525_DSQD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSQD); break;
+ case FSI_525_DSDD16: image->set_form_variant(floppy_image::FF_525, floppy_image::DSDD16); break;
+ case FSI_525_DSDD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSDD); break;
+ case FSI_525_DSSD: image->set_form_variant(floppy_image::FF_525, floppy_image::DSSD); break;
+ case FSI_525_SSQD16: image->set_form_variant(floppy_image::FF_525, floppy_image::SSQD16); break;
+ case FSI_525_SSQD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSQD); break;
+ case FSI_525_SSDD16: image->set_form_variant(floppy_image::FF_525, floppy_image::SSDD16); break;
+ case FSI_525_SSDD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSDD); break;
+ case FSI_525_SSSD: image->set_form_variant(floppy_image::FF_525, floppy_image::SSSD); break;
case FSI_35_DSED: image->set_form_variant(floppy_image::FF_35, floppy_image::DSED); break;
case FSI_35_DSHD: image->set_form_variant(floppy_image::FF_35, floppy_image::DSHD); break;
diff --git a/src/lib/formats/fs_unformatted.h b/src/lib/formats/fs_unformatted.h
index 949bb6aae08..fa51049f384 100644
--- a/src/lib/formats/fs_unformatted.h
+++ b/src/lib/formats/fs_unformatted.h
@@ -25,10 +25,14 @@ public:
FSI_525_SSSD,
FSI_525_SSDD,
+ FSI_525_SSDD16,
FSI_525_SSQD,
+ FSI_525_SSQD16,
FSI_525_DSSD,
FSI_525_DSDD,
+ FSI_525_DSDD16,
FSI_525_DSQD,
+ FSI_525_DSQD16,
FSI_525_DSHD,
FSI_35_SSDD,
diff --git a/src/lib/formats/fs_vtech.cpp b/src/lib/formats/fs_vtech.cpp
index 27e7f93a056..163b2ae6d53 100644
--- a/src/lib/formats/fs_vtech.cpp
+++ b/src/lib/formats/fs_vtech.cpp
@@ -19,7 +19,7 @@ namespace fs { const vtech_image VTECH; }
// Filesystem has no subdirectories.
//
// Track 0 sectors 0-14 have the file names. 16 bytes/entry
-// offset 0 : File type 'T' (basic) or 'B' (binary)
+// offset 0 : File type 'T' (basic), 'B' (binary), or some other letter (application-specific)
// offset 1 : 0x3a
// offset 2-9: File name
// offset a : Track number of first file sector
@@ -38,24 +38,24 @@ public:
virtual ~vtech_impl() = default;
virtual meta_data volume_metadata() override;
- virtual err_t volume_metadata_change(const meta_data &info) override;
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path) override;
- virtual err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition volume_metadata_change(const meta_data &info) override;
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path) override;
+ virtual std::error_condition metadata_change(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
- virtual err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath) override;
- virtual err_t remove(const std::vector<std::string> &path) override;
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path) override;
+ virtual std::error_condition rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath) override;
+ virtual std::error_condition remove(const std::vector<std::string> &path) override;
- virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta) override;
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta) override;
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
- virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path) override;
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data) override;
- virtual err_t format(const meta_data &meta) override;
+ virtual std::error_condition format(const meta_data &meta) override;
private:
meta_data file_metadata(const u8 *entry);
- std::tuple<fsblk_t::block_t, u32> file_find(std::string_view name);
+ std::tuple<fsblk_t::block_t::ptr, u32> file_find(std::string_view name);
std::vector<std::pair<u8, u8>> allocate_blocks(u32 count);
void free_blocks(const std::vector<std::pair<u8, u8>> &blocks);
u32 free_block_count();
@@ -114,7 +114,9 @@ std::vector<meta_description> vtech_image::file_meta_description() const
res.emplace_back(meta_description(meta_name::name, "", false, [](const meta_value &m) { return m.as_string().size() <= 8; }, "File name, 8 chars"));
res.emplace_back(meta_description(meta_name::loading_address, 0x7ae9, false, [](const meta_value &m) { return m.as_number() < 0x10000; }, "Loading address of the file"));
res.emplace_back(meta_description(meta_name::length, 0, true, nullptr, "Size of the file in bytes"));
- res.emplace_back(meta_description(meta_name::basic, true, true, nullptr, "Basic file"));
+ res.emplace_back(meta_description(meta_name::file_type, "T", true,
+ [](const meta_value &m) { return m.as_string().size() == 1 && m.as_string()[0] >= 'A' && m.as_string()[0] <= 'Z'; },
+ "File type (e.g. T = text, B = binary)"));
return res;
}
@@ -122,10 +124,10 @@ vtech_impl::vtech_impl(fsblk_t &blockdev) : filesystem_t(blockdev, 128)
{
}
-err_t vtech_impl::format(const meta_data &meta)
+std::error_condition vtech_impl::format(const meta_data &meta)
{
- m_blockdev.fill(0);
- return ERR_OK;
+ m_blockdev.fill_all(0);
+ return std::error_condition();
}
meta_data vtech_impl::volume_metadata()
@@ -133,9 +135,9 @@ meta_data vtech_impl::volume_metadata()
return meta_data();
}
-err_t vtech_impl::volume_metadata_change(const meta_data &meta)
+std::error_condition vtech_impl::volume_metadata_change(const meta_data &meta)
{
- return ERR_OK;
+ return std::error_condition();
}
meta_data vtech_impl::file_metadata(const u8 *entry)
@@ -143,56 +145,56 @@ meta_data vtech_impl::file_metadata(const u8 *entry)
meta_data res;
res.set(meta_name::name, trim_end_spaces(rstr(entry+2, 8)));
- res.set(meta_name::basic, entry[0] == 'T');
+ res.set(meta_name::file_type, std::string{ char(entry[0]) });
res.set(meta_name::loading_address, get_u16le(entry + 0xc));
- res.set(meta_name::length, ((get_u16le(entry + 0xe) - get_u16le(entry + 0xc) + 1) & 0xffff));
+ res.set(meta_name::length, (get_u16le(entry + 0xe) - get_u16le(entry + 0xc)) & 0xffff);
return res;
}
-std::tuple<fsblk_t::block_t, u32> vtech_impl::file_find(std::string_view name)
+std::tuple<fsblk_t::block_t::ptr, u32> vtech_impl::file_find(std::string_view name)
{
for(int sect = 0; sect != 14; sect++) {
auto bdir = m_blockdev.get(sect);
for(u32 i = 0; i != 8; i ++) {
u32 off = i*16;
- u8 type = bdir.r8(off);
- if(type != 'T' && type != 'B')
+ u8 type = bdir->r8(off);
+ if(type < 'A' || type > 'Z')
continue;
- if(bdir.r8(off+1) != ':')
+ if(bdir->r8(off+1) != ':')
continue;
- if(trim_end_spaces(bdir.rstr(off+2, 8)) == name) {
- return std::make_tuple(bdir, i);
+ if(trim_end_spaces(bdir->rstr(off+2, 8)) == name) {
+ return std::make_tuple(bdir, off);
}
}
}
- return std::make_tuple(fsblk_t::block_t(), 0xffffffff);
+ return std::make_tuple(fsblk_t::block_t::ptr(), 0xffffffff);
}
-std::pair<err_t, meta_data> vtech_impl::metadata(const std::vector<std::string> &path)
+std::pair<std::error_condition, meta_data> vtech_impl::metadata(const std::vector<std::string> &path)
{
if(path.size() != 1)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
auto [bdir, off] = file_find(path[0]);
if(off == 0xffffffff)
- return std::make_pair(ERR_NOT_FOUND, meta_data());
+ return std::make_pair(error::not_found, meta_data());
- return std::make_pair(ERR_OK, file_metadata(bdir.rodata() + off));
+ return std::make_pair(std::error_condition(), file_metadata(bdir->rodata() + off));
}
-err_t vtech_impl::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition vtech_impl::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
{
if(path.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off] = file_find(path[0]);
- if(!off)
- return ERR_NOT_FOUND;
+ if(off == 0xffffffff)
+ return error::not_found;
- u8 *entry = bdir.data() + off;
- if(meta.has(meta_name::basic))
- entry[0x0] = meta.get_flag(meta_name::basic) ? 'T' : 'B';
+ u8 *entry = bdir->data() + off;
+ if(meta.has(meta_name::file_type))
+ entry[0x0] = meta.get_string(meta_name::file_type)[0];
if(meta.has(meta_name::name)) {
std::string name = meta.get_string(meta_name::name);
name.resize(8, ' ');
@@ -205,103 +207,103 @@ err_t vtech_impl::metadata_change(const std::vector<std::string> &path, const me
put_u16le(entry + 0xe, new_end);
}
- return ERR_OK;
+ return std::error_condition();
}
-std::pair<err_t, std::vector<dir_entry>> vtech_impl::directory_contents(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<dir_entry>> vtech_impl::directory_contents(const std::vector<std::string> &path)
{
- std::pair<err_t, std::vector<dir_entry>> res;
+ std::pair<std::error_condition, std::vector<dir_entry>> res;
if(path.size() != 0) {
- res.first = ERR_NOT_FOUND;
+ res.first = error::not_found;
return res;
}
- res.first = ERR_OK;
+ res.first = std::error_condition();
for(int sect = 0; sect != 14; sect++) {
auto bdir = m_blockdev.get(sect);
for(u32 i = 0; i != 8; i ++) {
u32 off = i*16;
- u8 type = bdir.r8(off);
- if(type != 'T' && type != 'B')
+ u8 type = bdir->r8(off);
+ if(type < 'A' || type > 'Z')
continue;
- if(bdir.r8(off+1) != ':')
+ if(bdir->r8(off+1) != ':')
continue;
- meta_data meta = file_metadata(bdir.rodata()+off);
+ meta_data meta = file_metadata(bdir->rodata()+off);
res.second.emplace_back(dir_entry(dir_entry_type::file, meta));
}
}
return res;
}
-err_t vtech_impl::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
+std::error_condition vtech_impl::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
{
if(opath.size() != 1 || npath.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off] = file_find(opath[0]);
- if(!off)
- return ERR_NOT_FOUND;
+ if(off == 0xffffffff)
+ return error::not_found;
std::string name = npath[0];
name.resize(8, ' ');
- wstr(bdir.data() + off + 2, name);
+ wstr(bdir->data() + off + 2, name);
- return ERR_OK;
+ return std::error_condition();
}
-err_t vtech_impl::remove(const std::vector<std::string> &path)
+std::error_condition vtech_impl::remove(const std::vector<std::string> &path)
{
- return ERR_NOT_FOUND;
+ return error::unsupported;
}
-err_t vtech_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition vtech_impl::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
if(path.size() != 0)
- return ERR_NOT_FOUND;
+ return error::not_found;
// Find the key for the next unused entry
for(int sect = 0; sect != 14; sect++) {
auto bdir = m_blockdev.get(sect);
for(u32 i = 0; i != 16; i ++) {
u32 off = i*16;
- u8 type = bdir.r8(off);
+ u8 type = bdir->r8(off);
if(type != 'T' && type != 'B') {
std::string fname = meta.get_string(meta_name::name, "");
fname.resize(8, ' ');
- bdir.w8 (off+0x0, meta.get_flag(meta_name::basic, true) ? 'T' : 'B');
- bdir.w8 (off+0x1, ':');
- bdir.wstr(off+0x2, fname);
- bdir.w8 (off+0xa, 0x00);
- bdir.w8 (off+0xb, 0x00);
- bdir.w16l(off+0xc, meta.get_number(meta_name::loading_address, 0x7ae9));
- bdir.w16l(off+0xe, bdir.r16l(off+0xc) - 1); // Size 0 initially
- return ERR_OK;
+ bdir->w8 (off+0x0, meta.get_string(meta_name::file_type, "T")[0]);
+ bdir->w8 (off+0x1, ':');
+ bdir->wstr(off+0x2, fname);
+ bdir->w8 (off+0xa, 0x00);
+ bdir->w8 (off+0xb, 0x00);
+ bdir->w16l(off+0xc, meta.get_number(meta_name::loading_address, 0x7ae9));
+ bdir->w16l(off+0xe, bdir->r16l(off+0xc)); // Size 0 initially
+ return std::error_condition();
}
}
}
- return ERR_NO_SPACE;
+ return error::no_space;
}
-std::pair<err_t, std::vector<u8>> vtech_impl::file_read(const std::vector<std::string> &path)
+std::pair<std::error_condition, std::vector<u8>> vtech_impl::file_read(const std::vector<std::string> &path)
{
std::vector<u8> data;
if(path.size() != 1)
- return std::make_pair(ERR_NOT_FOUND, data);
+ return std::make_pair(error::not_found, data);
auto [bdir, off] = file_find(path[0]);
if(off == 0xffffffff)
- return std::make_pair(ERR_NOT_FOUND, data);
+ return std::make_pair(error::not_found, data);
- const u8 *entry = bdir.rodata() + off;
+ const u8 *entry = bdir->rodata() + off;
u8 track = entry[0xa];
u8 sector = entry[0xb];
- int len = ((get_u16le(entry + 0xe) - get_u16le(entry + 0xc)) & 0xffff) + 1;
+ int len = (get_u16le(entry + 0xe) - get_u16le(entry + 0xc)) & 0xffff;
data.resize(len, 0);
int pos = 0;
@@ -312,26 +314,26 @@ std::pair<err_t, std::vector<u8>> vtech_impl::file_read(const std::vector<std::s
int size = len - pos;
if(size > 126)
size = 126;
- memcpy(data.data() + pos, dblk.data(), size);
+ dblk->read(0, data.data() + pos, size);
pos += size;
- track = dblk.r8(126);
- sector = dblk.r8(127);
+ track = dblk->r8(126);
+ sector = dblk->r8(127);
}
- return std::make_pair(ERR_OK, data);
+ return std::make_pair(std::error_condition(), data);
}
-err_t vtech_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::error_condition vtech_impl::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
if(path.size() != 1)
- return ERR_NOT_FOUND;
+ return error::not_found;
auto [bdir, off] = file_find(path[0]);
if(off == 0xffffffff)
- return ERR_NOT_FOUND;
+ return error::not_found;
- u8 *entry = bdir.data() + off;
+ u8 *entry = bdir->data() + off;
- u32 cur_len = ((get_u16le(entry + 0xe) - get_u16le(entry + 0xc) + 1) & 0xffff);
+ u32 cur_len = (get_u16le(entry + 0xe) - get_u16le(entry + 0xc)) & 0xffff;
u32 new_len = data.size();
if(new_len > 65535)
new_len = 65535;
@@ -340,7 +342,7 @@ err_t vtech_impl::file_write(const std::vector<std::string> &path, const std::ve
// Enough space?
if(cur_ns < need_ns && free_block_count() < need_ns - cur_ns)
- return ERR_NO_SPACE;
+ return error::no_space;
u8 track = entry[0xa];
u8 sector = entry[0xb];
@@ -348,8 +350,8 @@ err_t vtech_impl::file_write(const std::vector<std::string> &path, const std::ve
for(u32 i = 0; i != cur_ns; i++) {
tofree.emplace_back(std::make_pair(track, sector));
auto dblk = m_blockdev.get(track*16 + sector);
- track = dblk.r8(126);
- sector = dblk.r8(127);
+ track = dblk->r8(126);
+ sector = dblk->r8(127);
}
free_blocks(tofree);
@@ -361,16 +363,16 @@ err_t vtech_impl::file_write(const std::vector<std::string> &path, const std::ve
if(len > 126)
len = 126;
else if(len < 126)
- dblk.fill(0x00);
- memcpy(dblk.data(), data.data() + 126*i, len);
+ dblk->fill(0x00);
+ dblk->write(0, data.data() + 126*i, len);
if(i < need_ns) {
- dblk.w8(126, blocks[i+1].first);
- dblk.w8(127, blocks[i+1].second);
+ dblk->w8(126, blocks[i+1].first);
+ dblk->w8(127, blocks[i+1].second);
} else
- dblk.w16l(126, 0);
+ dblk->w16l(126, 0);
}
- u16 end_address = (get_u16le(entry + 0xc) + data.size() - 1) & 0xffff;
+ u16 end_address = (get_u16le(entry + 0xc) + data.size()) & 0xffff;
put_u16le(entry + 0xe, end_address);
if(need_ns) {
entry[0xa] = blocks[0].first;
@@ -378,7 +380,7 @@ err_t vtech_impl::file_write(const std::vector<std::string> &path, const std::ve
} else
put_u16le(entry + 0xa, 0);
- return ERR_OK;
+ return std::error_condition();
}
std::vector<std::pair<u8, u8>> vtech_impl::allocate_blocks(u32 count)
@@ -392,8 +394,8 @@ std::vector<std::pair<u8, u8>> vtech_impl::allocate_blocks(u32 count)
for(u8 sector = 0; sector != 16; sector++) {
u32 off = (track-1)*2 + (sector / 8);
u32 bit = 1 << (sector & 7);
- if(!(fmap.r8(off) & bit)) {
- fmap.w8(off, fmap.r8(off) | bit);
+ if(!(fmap->r8(off) & bit)) {
+ fmap->w8(off, fmap->r8(off) | bit);
blocks.emplace_back(std::make_pair(track, sector));
if(blocks.size() == count)
return blocks;
@@ -410,7 +412,7 @@ void vtech_impl::free_blocks(const std::vector<std::pair<u8, u8>> &blocks)
u8 sector = ref.second;
u32 off = (track-1)*2 + (sector / 8);
u32 bit = 1 << (sector & 7);
- fmap.w8(off, fmap.r8(off) & ~bit);
+ fmap->w8(off, fmap->r8(off) & ~bit);
}
}
@@ -419,7 +421,7 @@ u32 vtech_impl::free_block_count()
auto fmap = m_blockdev.get(15);
u32 nf = 0;
for(u32 off = 0; off != (40-1)*2; off++) {
- u8 m = fmap.r8(off);
+ u8 m = fmap->r8(off);
// Count 1 bits;
m = ((m & 0xaa) >> 1) | (m & 0x55);
m = ((m & 0xcc) >> 2) | (m & 0x33);
diff --git a/src/lib/formats/fsblk.cpp b/src/lib/formats/fsblk.cpp
index d766e389bee..5e8198d0ce8 100644
--- a/src/lib/formats/fsblk.cpp
+++ b/src/lib/formats/fsblk.cpp
@@ -13,154 +13,124 @@
namespace fs {
-void refcounted_inner::ref()
-{
- m_ref ++;
-}
-
-void refcounted_inner::ref_weak()
-{
- m_weak_ref ++;
-}
-
-bool refcounted_inner::unref()
-{
- m_ref --;
- if(m_ref == 0) {
- if(m_weak_ref)
- drop_weak_references();
- else
- delete this;
- return true;
- }
- return false;
-}
-
-bool refcounted_inner::unref_weak()
-{
- m_weak_ref --;
- if(m_weak_ref == 0 && m_ref == 0) {
- delete this;
- return true;
- }
- return false;
-}
-
-
-
void fsblk_t::set_block_size(u32 block_size)
{
m_block_size = block_size;
}
-u8 *fsblk_t::iblock_t::offset(const char *function, u32 off, u32 size)
+const u8 *fsblk_t::block_t::roffs(const char *function, u32 off, u32 size) const
{
if(off + size > m_size)
- throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
- return data() + off;
+ throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
+ return rodata() + off;
}
-const u8 *fsblk_t::iblock_t::rooffset(const char *function, u32 off, u32 size)
+u8 *fsblk_t::block_t::woffs(const char *function, u32 off, u32 size)
{
if(off + size > m_size)
- throw std::out_of_range(util::string_format("block_t::%s out-of-block read access, offset=%d, size=%d, block size=%d\n", function, off, size, m_size));
- return rodata() + off;
+ throw std::out_of_range(util::string_format("block_t::%s out-of-block access, offset=%d, size=%d, block size=%d", function, off, size, m_size));
+ return data() + off;
}
-void fsblk_t::block_t::copy(u32 offset, const u8 *src, u32 size)
+void fsblk_t::block_t::write(u32 offset, const u8 *src, u32 size)
{
- memcpy(m_object->offset("copy", offset, size), src, size);
+ memcpy(woffs("write", offset, size), src, size);
}
void fsblk_t::block_t::fill(u32 offset, u8 data, u32 size)
{
- memset(m_object->offset("fill", offset, size), data, size);
+ memset(woffs("fill", offset, size), data, size);
}
void fsblk_t::block_t::fill(u8 data)
{
- memset(m_object->data(), data, m_object->size());
+ memset(this->data(), data, size());
}
void fsblk_t::block_t::wstr(u32 offset, std::string_view str)
{
- memcpy(m_object->offset("wstr", offset, str.size()), str.data(), str.size());
+ memcpy(woffs("wstr", offset, str.size()), str.data(), str.size());
}
void fsblk_t::block_t::w8(u32 offset, u8 data)
{
- m_object->offset("w8", offset, 1)[0] = data;
+ woffs("w8", offset, 1)[0] = data;
}
void fsblk_t::block_t::w16b(u32 offset, u16 data)
{
- put_u16be(m_object->offset("w16b", offset, 2), data);
+ put_u16be(woffs("w16b", offset, 2), data);
}
void fsblk_t::block_t::w24b(u32 offset, u32 data)
{
- put_u24be(m_object->offset("w24b", offset, 3), data);
+ put_u24be(woffs("w24b", offset, 3), data);
}
void fsblk_t::block_t::w32b(u32 offset, u32 data)
{
- put_u32be(m_object->offset("w32b", offset, 4), data);
+ put_u32be(woffs("w32b", offset, 4), data);
}
void fsblk_t::block_t::w16l(u32 offset, u16 data)
{
- put_u16le(m_object->offset("w16l", offset, 2), data);
+ put_u16le(woffs("w16l", offset, 2), data);
}
void fsblk_t::block_t::w24l(u32 offset, u32 data)
{
- put_u24le(m_object->offset("w24l", offset, 3), data);
+ put_u24le(woffs("w24l", offset, 3), data);
}
void fsblk_t::block_t::w32l(u32 offset, u32 data)
{
- put_u32le(m_object->offset("w32l", offset, 4), data);
+ put_u32le(woffs("w32l", offset, 4), data);
+}
+
+void fsblk_t::block_t::read(u32 offset, u8 *dst, u32 size) const
+{
+ memcpy(dst, roffs("read", offset, size), size);
}
std::string_view fsblk_t::block_t::rstr(u32 offset, u32 size) const
{
- const u8 *d = m_object->rooffset("rstr", offset, size);
+ const u8 *d = roffs("rstr", offset, size);
return std::string_view(reinterpret_cast<const char *>(d), size);
}
u8 fsblk_t::block_t::r8(u32 offset) const
{
- return m_object->offset("r8", offset, 1)[0];
+ return roffs("r8", offset, 1)[0];
}
u16 fsblk_t::block_t::r16b(u32 offset) const
{
- return get_u16be(m_object->offset("r16b", offset, 2));
+ return get_u16be(roffs("r16b", offset, 2));
}
u32 fsblk_t::block_t::r24b(u32 offset) const
{
- return get_u24be(m_object->offset("r24b", offset, 3));
+ return get_u24be(roffs("r24b", offset, 3));
}
u32 fsblk_t::block_t::r32b(u32 offset) const
{
- return get_u32be(m_object->offset("r32b", offset, 4));
+ return get_u32be(roffs("r32b", offset, 4));
}
u16 fsblk_t::block_t::r16l(u32 offset) const
{
- return get_u16le(m_object->offset("r16l", offset, 2));
+ return get_u16le(roffs("r16l", offset, 2));
}
u32 fsblk_t::block_t::r24l(u32 offset) const
{
- return get_u24le(m_object->offset("r24l", offset, 3));
+ return get_u24le(roffs("r24l", offset, 3));
}
u32 fsblk_t::block_t::r32l(u32 offset) const
{
- return get_u32le(m_object->offset("r32l", offset, 4));
+ return get_u32le(roffs("r32l", offset, 4));
}
@@ -186,69 +156,99 @@ meta_data filesystem_t::volume_metadata()
return meta_data();
}
-err_t filesystem_t::volume_metadata_change(const meta_data &meta)
+std::error_condition filesystem_t::volume_metadata_change(const meta_data &meta)
+{
+ return error::unsupported;
+}
+
+std::pair<std::error_condition, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return std::make_pair(error::unsupported, meta_data());
}
-std::pair<err_t, meta_data> filesystem_t::metadata(const std::vector<std::string> &path)
+std::error_condition filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
{
- return std::make_pair(ERR_UNSUPPORTED, meta_data());
+ return error::unsupported;
}
-err_t filesystem_t::metadata_change(const std::vector<std::string> &path, const meta_data &meta)
+std::pair<std::error_condition, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return std::make_pair(error::unsupported, std::vector<dir_entry>());
}
-std::pair<err_t, std::vector<dir_entry>> filesystem_t::directory_contents(const std::vector<std::string> &path)
+std::error_condition filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
{
- return std::make_pair(ERR_UNSUPPORTED, std::vector<dir_entry>());
+ return error::unsupported;
}
-err_t filesystem_t::rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath)
+std::error_condition filesystem_t::remove(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return error::unsupported;
}
-err_t filesystem_t::remove(const std::vector<std::string> &path)
+std::error_condition filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
{
- return ERR_UNSUPPORTED;
+ return error::unsupported;
}
-err_t filesystem_t::dir_create(const std::vector<std::string> &path, const meta_data &meta)
+std::error_condition filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
{
- return ERR_UNSUPPORTED;
+ return error::unsupported;
}
-err_t filesystem_t::file_create(const std::vector<std::string> &path, const meta_data &meta)
+std::pair<std::error_condition, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return std::make_pair(error::unsupported, std::vector<u8>());
}
-std::pair<err_t, std::vector<u8>> filesystem_t::file_read(const std::vector<std::string> &path)
+std::error_condition filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
- return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
+ return error::unsupported;
}
-err_t filesystem_t::file_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::pair<std::error_condition, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
{
- return ERR_UNSUPPORTED;
+ return std::make_pair(error::unsupported, std::vector<u8>());
}
-std::pair<err_t, std::vector<u8>> filesystem_t::file_rsrc_read(const std::vector<std::string> &path)
+std::error_condition filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
{
- return std::make_pair(ERR_UNSUPPORTED, std::vector<u8>());
+ return error::unsupported;
}
-err_t filesystem_t::file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data)
+std::error_condition filesystem_t::format(const meta_data &meta)
{
- return ERR_UNSUPPORTED;
+ return error::unsupported;
}
-err_t filesystem_t::format(const meta_data &meta)
+std::error_category const &fs_category() noexcept
{
- return ERR_UNSUPPORTED;
+ class fs_category_impl : public std::error_category
+ {
+ public:
+ virtual char const *name() const noexcept override { return "fs"; }
+
+ virtual std::string message(int condition) const override
+ {
+ using namespace std::literals;
+ static std::string_view const s_messages[] = {
+ "No error"sv,
+ "Unsupported operation"sv,
+ "File or directory not found"sv,
+ "No space on volume"sv,
+ "Invalid block number"sv,
+ "Invalid filename or path"sv,
+ "Incorrect file size"sv,
+ "File already exists"sv,
+ };
+ if ((0 <= condition) && (std::size(s_messages) > condition))
+ return std::string(s_messages[condition]);
+ else
+ return "Unknown error"s;
+ }
+ };
+ static fs_category_impl const s_fs_category_instance;
+ return s_fs_category_instance;
}
} // namespace fs
diff --git a/src/lib/formats/fsblk.h b/src/lib/formats/fsblk.h
index 63ed910a507..7f368a7307c 100644
--- a/src/lib/formats/fsblk.h
+++ b/src/lib/formats/fsblk.h
@@ -10,8 +10,10 @@
#include "fsmeta.h"
+#include <memory>
#include <string>
#include <string_view>
+#include <system_error>
#include <utility>
#include <vector>
@@ -22,110 +24,14 @@ using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
-enum err_t {
- ERR_OK = 0,
- ERR_UNSUPPORTED,
- ERR_INVALID,
- ERR_NOT_FOUND,
- ERR_NOT_EMPTY,
- ERR_NO_SPACE,
-};
-
-template<typename T> class refcounted_outer {
-public:
- refcounted_outer(bool weak) : m_object(nullptr), m_is_weak_ref(weak) {}
- refcounted_outer(T *object, bool weak) : m_object(object), m_is_weak_ref(weak) {
- ref();
- }
-
- refcounted_outer(const refcounted_outer &cref) {
- m_object = cref.m_object;
- m_is_weak_ref = cref.m_is_weak_ref;
- ref();
- }
-
- refcounted_outer(refcounted_outer &&cref) {
- m_object = cref.m_object;
- m_is_weak_ref = cref.m_is_weak_ref;
- cref.m_object = nullptr;
- }
-
- ~refcounted_outer() {
- unref();
- }
-
- refcounted_outer<T> &operator =(T *dir) {
- if(m_object != dir) {
- unref();
- m_object = dir;
- ref();
- }
- return *this;
- }
-
- refcounted_outer<T> &operator =(const refcounted_outer<T> &cref) {
- if(m_object != cref.m_object) {
- unref();
- m_object = cref.m_object;
- ref();
- }
- return *this;
- }
-
- refcounted_outer<T> &operator =(refcounted_outer<T> &&cref) {
- if(m_object != cref.m_object) {
- unref();
- m_object = cref.m_object;
- ref();
- } else if(m_is_weak_ref != cref.m_is_weak_ref) {
- ref();
- cref.unref();
- m_object = cref.m_object; // In case the object got deleted (when going from strong ref to weak on the last strong)
- }
- cref.m_object = nullptr;
- return *this;
- }
-
- operator bool() const { return m_object != nullptr; }
-
-protected:
- T *m_object;
- bool m_is_weak_ref;
-
-private:
- void ref() {
- if(m_object) {
- if(m_is_weak_ref)
- m_object->ref_weak();
- else
- m_object->ref();
- }
- }
-
- void unref() {
- if(m_object) {
- bool del = m_is_weak_ref ? m_object->unref_weak() : m_object->unref();
- if(del)
- m_object = nullptr;
- }
- }
-};
-
-
-class refcounted_inner {
-public:
- refcounted_inner() : m_ref(0), m_weak_ref(0) {}
- virtual ~refcounted_inner() = default;
-
- void ref();
- void ref_weak();
- bool unref();
- bool unref_weak();
-
- virtual void drop_weak_references() = 0;
-
-public:
- u32 m_ref, m_weak_ref;
+enum class error : int {
+ unsupported = 1,
+ not_found,
+ no_space,
+ invalid_block,
+ invalid_name,
+ incorrect_size,
+ already_exists,
};
enum class dir_entry_type {
@@ -142,51 +48,32 @@ struct dir_entry {
};
class fsblk_t {
-protected:
- class iblock_t : public refcounted_inner {
- public:
- iblock_t(u32 size) : refcounted_inner(), m_size(size) {}
- virtual ~iblock_t() = default;
-
- u32 size() const { return m_size; }
-
- virtual const u8 *rodata() = 0;
- virtual u8 *data() = 0;
- u8 *offset(const char *function, u32 off, u32 size);
- const u8 *rooffset(const char *function, u32 off, u32 size);
-
- protected:
- u32 m_size;
- };
-
-
public:
- class block_t : public refcounted_outer<iblock_t> {
+ class block_t {
public:
- block_t(bool weak = false) : refcounted_outer<iblock_t>(weak) {}
- block_t(iblock_t *block, bool weak = true) : refcounted_outer(block, weak) {}
- virtual ~block_t() = default;
-
- block_t strong() { return block_t(m_object, false); }
- block_t weak() { return block_t(m_object, true); }
+ using ptr = std::shared_ptr<block_t>;
- u32 size() const { return m_object->size(); }
+ block_t(u32 size) : m_size(size) {}
+ virtual ~block_t() = default;
- const u8 *rodata() const { return m_object->rodata(); }
- u8 *data() { return m_object->data(); }
+ u32 size() const { return m_size; }
- void copy(u32 offset, const u8 *src, u32 size);
- void fill( u8 data);
- void fill(u32 offset, u8 data, u32 size);
- void wstr(u32 offset, std::string_view str);
- void w8( u32 offset, u8 data);
- void w16b(u32 offset, u16 data);
- void w24b(u32 offset, u32 data);
- void w32b(u32 offset, u32 data);
- void w16l(u32 offset, u16 data);
- void w24l(u32 offset, u32 data);
- void w32l(u32 offset, u32 data);
+ virtual const u8 *rodata() const = 0;
+ virtual u8 *data() = 0;
+ void write(u32 offset, const u8 *src, u32 size);
+ void fill( u8 data);
+ void fill( u32 offset, u8 data, u32 size);
+ void wstr( u32 offset, std::string_view str);
+ void w8( u32 offset, u8 data);
+ void w16b( u32 offset, u16 data);
+ void w24b( u32 offset, u32 data);
+ void w32b( u32 offset, u32 data);
+ void w16l( u32 offset, u16 data);
+ void w24l( u32 offset, u32 data);
+ void w32l( u32 offset, u32 data);
+
+ void read(u32 offset, u8 *dst, u32 size) const;
std::string_view rstr(u32 offset, u32 size) const;
u8 r8( u32 offset) const;
u16 r16b(u32 offset) const;
@@ -195,6 +82,13 @@ public:
u16 r16l(u32 offset) const;
u32 r24l(u32 offset) const;
u32 r32l(u32 offset) const;
+
+ protected:
+ u32 m_size;
+
+ private:
+ const u8 *roffs(const char *function, u32 off, u32 size) const;
+ u8 *woffs(const char *function, u32 off, u32 size);
};
fsblk_t() : m_block_size(0) {}
@@ -202,8 +96,8 @@ public:
virtual void set_block_size(u32 block_size);
virtual u32 block_count() const = 0;
- virtual block_t get(u32 id) = 0;
- virtual void fill(u8 data) = 0;
+ virtual block_t::ptr get(u32 id) = 0;
+ virtual void fill_all(u8 data) = 0;
protected:
u32 m_block_size;
@@ -218,44 +112,44 @@ public:
virtual meta_data volume_metadata();
// Change the metadata for the volume
- virtual err_t volume_metadata_change(const meta_data &meta);
+ virtual std::error_condition volume_metadata_change(const meta_data &meta);
// Get the metadata for a file or a directory. Empty path targets the root directory
- virtual std::pair<err_t, meta_data> metadata(const std::vector<std::string> &path);
+ virtual std::pair<std::error_condition, meta_data> metadata(const std::vector<std::string> &path);
// Change the metadata for a file or a directory. Empty path targets the root directory
- virtual err_t metadata_change(const std::vector<std::string> &path, const meta_data &meta);
+ virtual std::error_condition metadata_change(const std::vector<std::string> &path, const meta_data &meta);
// Get the contents of a directory, empty path targets the root directory
- virtual std::pair<err_t, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
+ virtual std::pair<std::error_condition, std::vector<dir_entry>> directory_contents(const std::vector<std::string> &path);
// Rename a file or a directory. In contrast to metadata_change, this can move the object
// between directories
- virtual err_t rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
+ virtual std::error_condition rename(const std::vector<std::string> &opath, const std::vector<std::string> &npath);
// Remove a file or a directory. Directories must be empty (e.g. it's not recursive)
- virtual err_t remove(const std::vector<std::string> &path);
+ virtual std::error_condition remove(const std::vector<std::string> &path);
// Create a directory, path designates where the directory must be, directory name is in meta
- virtual err_t dir_create(const std::vector<std::string> &path, const meta_data &meta);
+ virtual std::error_condition dir_create(const std::vector<std::string> &path, const meta_data &meta);
// Create an empty file, path designates where the file must be, file name is in meta
- virtual err_t file_create(const std::vector<std::string> &path, const meta_data &meta);
+ virtual std::error_condition file_create(const std::vector<std::string> &path, const meta_data &meta);
// Read the contents of a file
- virtual std::pair<err_t, std::vector<u8>> file_read(const std::vector<std::string> &path);
+ virtual std::pair<std::error_condition, std::vector<u8>> file_read(const std::vector<std::string> &path);
// Replace the contents of a file, the file must already exist
- virtual err_t file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+ virtual std::error_condition file_write(const std::vector<std::string> &path, const std::vector<u8> &data);
// Read the resource fork of a file on systems that handle those
- virtual std::pair<err_t, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
+ virtual std::pair<std::error_condition, std::vector<u8>> file_rsrc_read(const std::vector<std::string> &path);
// Replace the resource fork of a file, the file must already exist
- virtual err_t file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
+ virtual std::error_condition file_rsrc_write(const std::vector<std::string> &path, const std::vector<u8> &data);
// Format an image, provide the volume metadata
- virtual err_t format(const meta_data &meta);
+ virtual std::error_condition format(const meta_data &meta);
static void wstr(u8 *p, std::string_view str);
@@ -271,6 +165,17 @@ protected:
fsblk_t &m_blockdev;
};
+// error category for filesystem errors
+std::error_category const &fs_category() noexcept;
+inline std::error_condition make_error_condition(error err) noexcept { return std::error_condition(int(err), fs_category()); }
+
} // namespace fs
+
+namespace std {
+
+template <> struct is_error_condition_enum<fs::error> : public std::true_type { };
+
+} // namespace std
+
#endif
diff --git a/src/lib/formats/fsblk_vec.cpp b/src/lib/formats/fsblk_vec.cpp
index 36f11cc9d89..a04d60c263c 100644
--- a/src/lib/formats/fsblk_vec.cpp
+++ b/src/lib/formats/fsblk_vec.cpp
@@ -12,7 +12,7 @@
namespace fs {
-const u8 *fsblk_vec_t::blk_t::rodata()
+const u8 *fsblk_vec_t::blk_t::rodata() const
{
return m_data;
}
@@ -22,23 +22,19 @@ u8 *fsblk_vec_t::blk_t::data()
return m_data;
}
-void fsblk_vec_t::blk_t::drop_weak_references()
-{
-}
-
u32 fsblk_vec_t::block_count() const
{
return m_data.size() / m_block_size;
}
-fsblk_t::block_t fsblk_vec_t::get(u32 id)
+fsblk_vec_t::block_t::ptr fsblk_vec_t::get(u32 id)
{
if(id >= block_count())
- throw std::out_of_range(util::string_format("Block number overflow: requiring block %d on device of size %d (%d bytes, block size %d)\n", id, block_count(), m_data.size(), m_block_size));
- return block_t(new blk_t(m_data.data() + m_block_size*id, m_block_size));
+ throw std::out_of_range(util::string_format("Block number overflow: requiring block %d on device of size %d (%d bytes, block size %d)", id, block_count(), m_data.size(), m_block_size));
+ return std::make_shared<blk_t>(m_data.data() + m_block_size*id, m_block_size);
}
-void fsblk_vec_t::fill(u8 data)
+void fsblk_vec_t::fill_all(u8 data)
{
std::fill(m_data.begin(), m_data.end(), data);
}
diff --git a/src/lib/formats/fsblk_vec.h b/src/lib/formats/fsblk_vec.h
index 49f7ed3013e..b029bc55c5e 100644
--- a/src/lib/formats/fsblk_vec.h
+++ b/src/lib/formats/fsblk_vec.h
@@ -9,14 +9,13 @@ namespace fs {
class fsblk_vec_t : public fsblk_t {
private:
- class blk_t : public iblock_t {
+ class blk_t : public block_t {
public:
- blk_t(u8 *data, u32 size) : iblock_t(size), m_data(data) {}
+ blk_t(u8 *data, u32 size) : block_t(size), m_data(data) {}
virtual ~blk_t() = default;
- virtual const u8 *rodata() override;
+ virtual const u8 *rodata() const override;
virtual u8 *data() override;
- virtual void drop_weak_references() override;
private:
u8 *m_data;
@@ -27,8 +26,8 @@ public:
virtual ~fsblk_vec_t() = default;
virtual u32 block_count() const override;
- virtual block_t get(u32 id) override;
- virtual void fill(u8 data) override;
+ virtual block_t::ptr get(u32 id) override;
+ virtual void fill_all(u8 data) override;
private:
std::vector<u8> &m_data;
diff --git a/src/lib/formats/fsd_dsk.cpp b/src/lib/formats/fsd_dsk.cpp
index e4909ba37f3..b386dc026c6 100644
--- a/src/lib/formats/fsd_dsk.cpp
+++ b/src/lib/formats/fsd_dsk.cpp
@@ -91,9 +91,11 @@ bool fsd_format::supports_save() const noexcept
int fsd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[3];
-
- size_t actual;
- io.read_at(0, h, 3, actual);
+ auto const [err, actual] = read_at(io, 0, h, 3);
+ if (err || (3 != actual)) {
+ LOG_FORMATS("fsd: read error\n");
+ return 0;
+ }
if (memcmp(h, "FSD", 3) == 0) {
return FIFID_SIGN;
}
@@ -111,9 +113,9 @@ bool fsd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t size;
if(io.length(size))
return false;
- std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [err, img, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
uint64_t pos;
std::string title;
diff --git a/src/lib/formats/fsmeta.cpp b/src/lib/formats/fsmeta.cpp
index f3e91e706a0..3c731f21939 100644
--- a/src/lib/formats/fsmeta.cpp
+++ b/src/lib/formats/fsmeta.cpp
@@ -14,7 +14,6 @@ namespace fs {
const char *meta_data::entry_name(meta_name name)
{
switch(name) {
- case meta_name::basic: return "basic";
case meta_name::creation_date: return "creation_date";
case meta_name::length: return "length";
case meta_name::loading_address: return "loading_address";
diff --git a/src/lib/formats/fsmeta.h b/src/lib/formats/fsmeta.h
index 0f6baf20133..ff0b505ab8b 100644
--- a/src/lib/formats/fsmeta.h
+++ b/src/lib/formats/fsmeta.h
@@ -21,7 +21,6 @@
namespace fs {
enum class meta_name {
- basic,
creation_date,
length,
loading_address,
diff --git a/src/lib/formats/g64_dsk.cpp b/src/lib/formats/g64_dsk.cpp
index 568cc8f5027..177438dc9a6 100644
--- a/src/lib/formats/g64_dsk.cpp
+++ b/src/lib/formats/g64_dsk.cpp
@@ -36,9 +36,10 @@ const uint32_t g64_format::c1541_cell_size[] =
int g64_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
char h[8];
+ auto const [err, actual] = read_at(io, 0, h, 8);
+ if (err || (8 != actual))
+ return 0;
- size_t actual;
- io.read_at(0, h, 8, actual);
if (!memcmp(h, G64_FORMAT_HEADER, 8))
return FIFID_SIGN;
@@ -51,9 +52,9 @@ bool g64_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if (io.length(size))
return false;
- std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [err, img, actual] = read_at(io, 0, size);
+ if (err || (actual != size))
+ return false;
if (img[POS_VERSION])
{
@@ -124,7 +125,6 @@ bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &
{
uint8_t const zerofill[] = { 0x00, 0x00, 0x00, 0x00 };
std::vector<uint8_t> const prefill(TRACK_LENGTH, 0xff);
- size_t actual;
int tracks, heads;
image.get_actual_geometry(tracks, heads);
@@ -132,7 +132,7 @@ bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &
// write header
uint8_t header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, static_cast<uint8_t>(tracks), TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 };
- io.write_at(POS_SIGNATURE, header, sizeof(header), actual);
+ write_at(io, POS_SIGNATURE, header, sizeof(header)); // FIXME: check for errors
// write tracks
for (int head = 0; head < heads; head++) {
@@ -145,8 +145,8 @@ bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &
uint32_t const spos = tpos + (tracks * 4);
uint32_t const dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH);
- io.write_at(tpos, zerofill, 4, actual);
- io.write_at(spos, zerofill, 4, actual);
+ write_at(io, tpos, zerofill, 4); // FIXME: check for errors
+ write_at(io, spos, zerofill, 4); // FIXME: check for errors
if (image.get_buffer(track, head).size() <= 1)
continue;
@@ -178,11 +178,11 @@ bool g64_format::save(util::random_read_write &io, const std::vector<uint32_t> &
put_u32le(speed_offset, speed_zone);
put_u16le(track_length, packed.size());
- io.write_at(tpos, track_offset, 4, actual);
- io.write_at(spos, speed_offset, 4, actual);
- io.write_at(dpos, prefill.data(), TRACK_LENGTH, actual);
- io.write_at(dpos, track_length, 2, actual);
- io.write_at(dpos + 2, packed.data(), packed.size(), actual);
+ write_at(io, tpos, track_offset, 4); // FIXME: check for errors
+ write_at(io, spos, speed_offset, 4); // FIXME: check for errors
+ write_at(io, dpos, prefill.data(), TRACK_LENGTH); // FIXME: check for errors
+ write_at(io, dpos, track_length, 2); // FIXME: check for errors
+ write_at(io, dpos + 2, packed.data(), packed.size()); // FIXME: check for errors
tracks_written++;
}
diff --git a/src/lib/formats/gtp_cas.cpp b/src/lib/formats/gtp_cas.cpp
index 85caa73fd02..dc996aa89db 100644
--- a/src/lib/formats/gtp_cas.cpp
+++ b/src/lib/formats/gtp_cas.cpp
@@ -127,7 +127,7 @@ static int gtp_cas_to_wav_size( const uint8_t *casdata, int caslen ) {
return size;
}
-static int gtp_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int gtp_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i,size,n;
size = 0;
n = 0;
diff --git a/src/lib/formats/h17disk.cpp b/src/lib/formats/h17disk.cpp
new file mode 100644
index 00000000000..9fb211ddb0d
--- /dev/null
+++ b/src/lib/formats/h17disk.cpp
@@ -0,0 +1,253 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/*********************************************************************
+
+Heath H17D disk image format (version 2.0.0)
+
+ Format for Heath hard-sectored 5.25" disk images.
+
+ See https://heathkit.garlanger.com/diskformats/ for more information
+
+ TODO - implement writing to H17D image
+
+*********************************************************************/
+
+#include "h17disk.h"
+
+#include "imageutl.h"
+
+#include "ioprocs.h"
+
+#include <cstring>
+
+
+namespace {
+
+constexpr int TRACK_SIZE = 50'000;
+constexpr int BITCELL_SIZE = 4000;
+
+constexpr int SECTOR_METADATA_SIZE = 16;
+
+constexpr int SECTOR_DATA_SIZE = 256;
+constexpr int SECTORS_PER_TRACK = 10;
+
+struct format {
+ int head_count;
+ int track_count;
+ uint32_t variant;
+};
+
+const format formats[] = {
+ { 1, 40, floppy_image::SSSD10 }, // H-17-1
+ { 2, 40, floppy_image::DSSD10 },
+ { 1, 80, floppy_image::SSQD10 },
+ { 2, 80, floppy_image::DSQD10 }, // H-17-4
+ {}
+};
+
+struct block_header {
+ uint32_t block_name;
+ uint32_t length;
+};
+
+enum {
+ DskF = 0x466b7344, //!< "DskF", Disk Format
+ Parm = 0x6b726150, //!< "Parm", Parameters
+ Date = 0x65746144, //!< "Date", Date
+ Imgr = 0x72676d49, //!< "Imgr", Imager
+
+ Prog = 0x676f7250, //!< "Prog", Program (creation)
+ Padd = 0x64646150, //!< "Padd", Padding
+ H8DB = 0x42443848, //!< "H8DB", H8D data block
+ SecM = 0x4d636553, //!< "SecM", Sector Metadata
+ Labl = 0x6c62614c, //!< "Labl", Label
+ Comm = 0x6d6d6f43, //!< "Comm", Comment
+};
+
+std::pair<std::uint64_t, std::size_t> find_block(util::random_read &io, uint32_t block_id)
+{
+ LOG_FORMATS("find_block: 0x%x\n", block_id);
+
+ // start of file
+ int pos = 0;
+ block_header header = { 0, 0 };
+
+ do
+ {
+ pos += header.length + 8;
+ auto const [err, actual] = read_at(io, pos, (void *) &header, 8);
+ if (err || actual !=8)
+ {
+ return std::make_pair(0, 0);
+ }
+ header.length = swapendian_int32(header.length);
+ }
+ while (header.block_name != block_id);
+
+ // update position to point to data portion of the block
+ return std::make_pair(pos + 8, header.length);
+}
+
+format find_format(util::random_read &io)
+{
+ auto const [pos, length] = find_block(io, DskF);
+ if ((pos == 0) || (length < 2) || (length > 3))
+ {
+ LOG_FORMATS("Can't find valid DskF block %d/%d\n", pos, length);
+
+ return {};
+ }
+
+ uint8_t buf[3];
+
+ auto const [err, actual] = read_at(io, pos, buf, length);
+ if (err || (actual != length))
+ {
+ LOG_FORMATS("read error\n");
+
+ return {};
+ }
+
+ int head_count = buf[0];
+ int track_count = buf[1];
+
+ for (int i = 0; formats[i].head_count; i++)
+ {
+ if ((formats[i].head_count == head_count) && (formats[i].track_count == track_count))
+ {
+ LOG_FORMATS("find_format format found: %d - variant: 0x%x\n", i, formats[i].variant);
+
+ return formats[i];
+ }
+ }
+
+ LOG_FORMATS("Invalid disk format - heads: %d, tracks: %d\n", head_count, track_count);
+ return {};
+}
+
+} // anonymous namespace
+
+
+heath_h17d_format::heath_h17d_format() : floppy_image_format_t()
+{
+}
+
+int heath_h17d_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint8_t h[4];
+ auto const [err, actual] = read_at(io, 0, h, 4);
+
+ if (err || (actual != 4))
+ {
+ return 0;
+ }
+
+ // Verify "H17D" Signature.
+ if ((h[0] == 0x48) && (h[1] == 0x31) && (h[2] == 0x37) && (h[3] == 0x44))
+ {
+ return FIFID_SIGN;
+ }
+
+ return 0;
+}
+
+bool heath_h17d_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
+{
+ const format fmt = find_format(io);
+
+ if (!fmt.head_count)
+ {
+ LOG_FORMATS("invalid format\n");
+
+ return false;
+ }
+
+ image.set_variant(fmt.variant);
+
+ std::vector<uint32_t> buf;
+
+ auto const [secm_pos, secm_length] = find_block(io, SecM);
+
+ uint8_t sector_meta_data[SECTOR_METADATA_SIZE];
+ uint8_t sector_data[SECTOR_DATA_SIZE];
+
+ for (int head = 0; head < fmt.head_count; head++)
+ {
+ for (int track = 0; track < fmt.track_count; track++)
+ {
+ for (int sector = 0; sector < SECTORS_PER_TRACK; sector++)
+ {
+ int sect_meta_pos = (sector + (track * fmt.head_count + head) * SECTORS_PER_TRACK) * SECTOR_METADATA_SIZE + secm_pos;
+
+ auto const [err, actual] = read_at(io, sect_meta_pos, sector_meta_data, SECTOR_METADATA_SIZE);
+
+ if (err || (actual != SECTOR_METADATA_SIZE))
+ {
+ LOG_FORMATS("unable to read sect meta data %d/%d/%d\n", head, track, sector);
+
+ return false;
+ }
+ int data_offset = sector_meta_data[0] << 24 | sector_meta_data[1] << 16 | sector_meta_data[2] << 8 | sector_meta_data[3];
+
+ auto const [err2, actual2] = read_at(io, data_offset, sector_data, SECTOR_DATA_SIZE);
+
+ if (err2 || (actual2 != SECTOR_DATA_SIZE))
+ {
+ LOG_FORMATS("unable to read sect data %d/%d/%d\n", head, track, sector);
+
+ return false;
+ }
+
+ // Inital 15 zero bytes
+ for (int i = 0; i < 15; i++)
+ {
+ fm_reverse_byte_w(buf, 0);
+ }
+
+ // header (sync byte, volume, track, sector, checksum)
+ for (int i = 0; i < 5; i++)
+ {
+ fm_reverse_byte_w(buf, sector_meta_data[5 + i]);
+ }
+
+ // 12 zero bytes
+ for (int i = 0; i < 12; i++)
+ {
+ fm_reverse_byte_w(buf, 0);
+ }
+
+ // data sync byte
+ fm_reverse_byte_w(buf, sector_meta_data[10]);
+
+ // sector data
+ for (int i = 0; i < 256; i++)
+ {
+ fm_reverse_byte_w(buf, sector_data[i]);
+ }
+
+ // sector data checksum
+ fm_reverse_byte_w(buf, sector_meta_data[11]);
+
+ // trailing zero's until the next sector hole usually ~ 30 characters.
+ while (buf.size() < TRACK_SIZE / SECTORS_PER_TRACK * (sector + 1))
+ {
+ fm_reverse_byte_w(buf, 0);
+ }
+ }
+
+ generate_track_from_levels(track, head, buf, 0, image);
+ buf.clear();
+ }
+ }
+
+ return true;
+}
+
+void heath_h17d_format::fm_reverse_byte_w(std::vector<uint32_t> &buffer, uint8_t val) const
+{
+ constexpr unsigned char lookup[16] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
+
+ fm_w(buffer, 8, lookup[val & 0x0f] << 4 | lookup[val >> 4], BITCELL_SIZE);
+}
+
+const heath_h17d_format FLOPPY_H17D_FORMAT;
diff --git a/src/lib/formats/h17disk.h b/src/lib/formats/h17disk.h
new file mode 100644
index 00000000000..19ac0bac052
--- /dev/null
+++ b/src/lib/formats/h17disk.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:Mark Garlanger
+/*********************************************************************
+
+Heath h17disk disk image format
+
+The Heath hard-sectored disk format for the H8 and H89 systems with the
+H17 controller on the H8 and the H-88-1 controller on the H89.
+
+*********************************************************************/
+#ifndef MAME_FORMATS_H17DISK_H
+#define MAME_FORMATS_H17DISK_H
+
+#pragma once
+
+#include "flopimg.h"
+
+class heath_h17d_format : public floppy_image_format_t
+{
+public:
+ heath_h17d_format();
+
+ int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
+
+ const char *name() const noexcept override { return "h17disk"; }
+ const char *description() const noexcept override { return "Heath H17D disk image"; }
+ const char *extensions() const noexcept override { return "h17,h17d,h17disk"; }
+ bool supports_save() const noexcept override { return false; }
+
+protected:
+
+ void fm_reverse_byte_w(std::vector<uint32_t> &buffer, uint8_t val) const;
+};
+
+extern const heath_h17d_format FLOPPY_H17D_FORMAT;
+
+#endif // MAME_FORMATS_H17DISK_H
diff --git a/src/lib/formats/h8_cas.cpp b/src/lib/formats/h8_cas.cpp
index c0d5d6dd925..526e411d5ae 100644
--- a/src/lib/formats/h8_cas.cpp
+++ b/src/lib/formats/h8_cas.cpp
@@ -1,147 +1,96 @@
// license:BSD-3-Clause
-// copyright-holders:Robbbert
+// copyright-holders:Robbbert,Mark Garlanger
/********************************************************************
-Support for Heathkit H8 H8T cassette images
+Support for Heathkit H8/H88 H8T cassette images
Standard Kansas City format (300 baud)
+TODO - investigate 1200 buad support, H8 should support it, but H88 does not.
+
We output a leader, followed by the contents of the H8T file.
********************************************************************/
#include "h8_cas.h"
-#define WAVEENTRY_LOW -32768
-#define WAVEENTRY_HIGH 32767
-
-#define H8_WAV_FREQUENCY 9600
-
-// image size
-static int h8_image_size; // FIXME: global variable prevents multiple instances
-
-static int h8_put_samples(int16_t *buffer, int sample_pos, int count, int level)
-{
- if (buffer)
- {
- for (int i=0; i<count; i++)
- buffer[sample_pos + i] = level;
- }
-
- return count;
-}
-
-static int h8_output_bit(int16_t *buffer, int sample_pos, bool bit)
-{
- int samples = 0;
-
- for (uint8_t i = 0; i < 4; i++)
- {
- if (bit)
- {
- samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
- samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
- samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
- samples += h8_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
- }
- else
- {
- samples += h8_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_LOW);
- samples += h8_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_HIGH);
- }
- }
-
- return samples;
-}
-
-static int h8_output_byte(int16_t *buffer, int sample_pos, uint8_t byte)
-{
- int samples = 0;
- uint8_t i;
+#include "coretmpl.h" // BIT
- // start bit
- samples += h8_output_bit (buffer, sample_pos + samples, 0);
- // data bits
- for (i = 0; i<8; i++)
- samples += h8_output_bit (buffer, sample_pos + samples, (byte >> i) & 1);
+namespace {
- // stop bits
- for (i = 0; i<2; i++)
- samples += h8_output_bit (buffer, sample_pos + samples, 1);
-
- return samples;
-}
+constexpr double ONE_FREQ = 1200.0;
+constexpr double ONE_FREQ_VARIANCE = 300.0;
+constexpr double ZERO_FREQ = 2400.0;
+constexpr double ZERO_FREQ_VARIANCE = 600.0;
-static int h8_handle_cassette(int16_t *buffer, const uint8_t *bytes)
+const cassette_image::Modulation heath_h8t_modulation =
{
- uint32_t sample_count = 0;
- uint32_t byte_count = 0;
- uint32_t i;
-
-
- // leader
- for (i=0; i<2000; i++)
- sample_count += h8_output_bit(buffer, sample_count, 1);
-
- // data
- for (i=byte_count; i<h8_image_size; i++)
- sample_count += h8_output_byte(buffer, sample_count, bytes[i]);
-
- return sample_count;
-}
-
-
-/*******************************************************************
- Generate samples for the tape image
-********************************************************************/
+ cassette_image::MODULATION_SINEWAVE,
+ ONE_FREQ - ONE_FREQ_VARIANCE, ONE_FREQ, ONE_FREQ + ONE_FREQ_VARIANCE,
+ ZERO_FREQ - ZERO_FREQ_VARIANCE, ZERO_FREQ, ZERO_FREQ + ZERO_FREQ_VARIANCE
+};
-static int h8_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+cassette_image::error heath_h8t_identify(cassette_image *cassette, cassette_image::Options *opts)
{
- return h8_handle_cassette(buffer, bytes);
+ return cassette->modulation_identify(heath_h8t_modulation, opts);
}
-/*******************************************************************
- Calculate the number of samples needed for this tape image
-********************************************************************/
-static int h8_cassette_calculate_size_in_samples(const uint8_t *bytes, int length)
+cassette_image::error heath_h8t_load(cassette_image *cassette)
{
- h8_image_size = length;
+ cassette_image::error err = cassette_image::error::SUCCESS;
+ uint64_t image_size = cassette->image_size();
+ double time_index = 0.0;
+ double time_displacement;
+
+ auto const MODULATE =
+ [&cassette, &err, &time_index, &time_displacement] (unsigned value)
+ {
+ for (int i = 0; (i < (value ? 8 : 4)); i++)
+ {
+ err = cassette->put_modulated_data_bit(0, time_index, value, heath_h8t_modulation, &time_displacement);
+ if (cassette_image::error::SUCCESS == err)
+ time_index += time_displacement;
+ else
+ return;
+ }
+ };
+
+ // leader - 1 second
+ while ((cassette_image::error::SUCCESS == err) && (time_index < 1.0))
+ MODULATE(1);
+
+ for (uint64_t image_pos = 0; (cassette_image::error::SUCCESS == err) && (image_pos < image_size); image_pos++)
+ {
+ uint8_t data = cassette->image_read_byte(image_pos);
- return h8_handle_cassette(nullptr, bytes);
-}
+ // start bit
+ MODULATE(0);
-static const cassette_image::LegacyWaveFiller h8_legacy_fill_wave =
-{
- h8_cassette_fill_wave, // fill_wave
- -1, // chunk_size
- 0, // chunk_samples
- h8_cassette_calculate_size_in_samples, // chunk_sample_calc
- H8_WAV_FREQUENCY, // sample_frequency
- 0, // header_samples
- 0 // trailer_samples
-};
+ // data bits
+ for (int bit = 0; (cassette_image::error::SUCCESS == err) && (bit < 8); bit++)
+ MODULATE(util::BIT(data, bit));
-static cassette_image::error h8_cassette_identify(cassette_image *cassette, cassette_image::Options *opts)
-{
- return cassette->legacy_identify(opts, &h8_legacy_fill_wave);
-}
+ // stop bit
+ if (cassette_image::error::SUCCESS == err)
+ MODULATE(1);
+ }
-static cassette_image::error h8_cassette_load(cassette_image *cassette)
-{
- return cassette->legacy_construct(&h8_legacy_fill_wave);
+ return err;
}
-static const cassette_image::Format h8_cassette_image_format =
+const cassette_image::Format heath_h8t_format =
{
"h8t",
- h8_cassette_identify,
- h8_cassette_load,
+ heath_h8t_identify,
+ heath_h8t_load,
nullptr
};
-CASSETTE_FORMATLIST_START(h8_cassette_formats)
- CASSETTE_FORMAT(h8_cassette_image_format)
+}
+
+CASSETTE_FORMATLIST_START( h8_cassette_formats )
+ CASSETTE_FORMAT( heath_h8t_format )
CASSETTE_FORMATLIST_END
diff --git a/src/lib/formats/h8_cas.h b/src/lib/formats/h8_cas.h
index 8ad9f82006a..9c7ea02104a 100644
--- a/src/lib/formats/h8_cas.h
+++ b/src/lib/formats/h8_cas.h
@@ -1,10 +1,10 @@
// license:BSD-3-Clause
-// copyright-holders:Robbbert
+// copyright-holders:Robbbert,Mark Garlanger
/*********************************************************************
h8_cas.h
- Format code for Heathkit H8 H8T cassette images
+ Format code for Heathkit H8/H88 H8T cassette images
*********************************************************************/
#ifndef MAME_FORMATS_H8_CAS_H
diff --git a/src/lib/formats/hect_tap.cpp b/src/lib/formats/hect_tap.cpp
index 867d95cf4b0..cef1a730875 100644
--- a/src/lib/formats/hect_tap.cpp
+++ b/src/lib/formats/hect_tap.cpp
@@ -121,7 +121,7 @@ static int hector_handle_tap(int16_t *buffer, const uint8_t *casdata)
if (data_pos>1)
previous_block = casdata[data_pos-1];
- /* Handle block lenght on tape data */
+ /* Handle block length on tape data */
block_size = casdata[data_pos] ;
if (block_size==0)
block_size=256;
@@ -173,8 +173,8 @@ static int hector_handle_forth_tap(int16_t *buffer, const uint8_t *casdata)
/* Starting a block with 768 cycle of synchro*/
sample_count += hector_tap_synchro( buffer, sample_count, 768 );
- /* Handle block lenght on tape data */
- block_size = 822 ; /* Fixed size for the forth*/
+ /* Handle block length on tape data */
+ block_size = 822 ; /* Fixed size for the forth */
/*block_count=0;*/
@@ -203,7 +203,7 @@ static int hector_handle_forth_tap(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int hector_tap_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int hector_tap_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return hector_handle_tap( buffer, bytes );
}
@@ -222,7 +222,7 @@ static int hector_tap_forth_to_wav_size(const uint8_t *casdata, int caslen)
/*******************************************************************
Generate samples for the tape image FORTH
********************************************************************/
-static int hector_tap_forth_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int hector_tap_forth_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return hector_handle_forth_tap( buffer, bytes ); //forth removed here !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}
diff --git a/src/lib/formats/hp300_dsk.cpp b/src/lib/formats/hp300_dsk.cpp
index de33bf6d310..99c3c20f283 100644
--- a/src/lib/formats/hp300_dsk.cpp
+++ b/src/lib/formats/hp300_dsk.cpp
@@ -30,11 +30,11 @@ const char *hp300_format::extensions() const noexcept
}
const hp300_format::format hp300_format::formats[] = {
+ { floppy_image::FF_35, floppy_image::SSDD, floppy_image::MFM, 2000, 16, 66, 1, 256, {}, 0, {}, 32, 22, 46 }, // FORMAT 4
// HP 9121S, 9121D or 9133A
{ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, 2000, 16, 77, 2, 256, {}, 1, {}, 50, 22, 54 }, // FORMAT 0,1
{ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, 2000, 9, 77, 2, 512, {}, 1, {}, 50, 22, 89 }, // FORMAT 2
{ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, 2000, 5, 77, 2, 1024, {}, 1, {}, 50, 22, 108 }, // FORMAT 3
- { floppy_image::FF_35, floppy_image::DSSD, floppy_image::MFM, 2000, 16, 70, 1, 256, {}, 1, {}, 32, 22, 46 }, // FORMAT 4
{ floppy_image::FF_35, floppy_image::DSDD, floppy_image::MFM, 2000, 9, 80, 2, 512, {}, 1, {}, 146, 22, 81 }, // FORMAT 16
// HP9122C/D, 9123D, 9133D/H/L or 9153A/B
{ floppy_image::FF_35, floppy_image::DSHD, floppy_image::MFM, 2000, 32, 77, 2, 256, {}, 1, {}, 50, 22, 59 }, // FORMAT 0,1,4
diff --git a/src/lib/formats/hpi_dsk.cpp b/src/lib/formats/hpi_dsk.cpp
index 84836207222..952ec0a2709 100644
--- a/src/lib/formats/hpi_dsk.cpp
+++ b/src/lib/formats/hpi_dsk.cpp
@@ -162,9 +162,10 @@ bool hpi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
image.set_variant(heads == 2 ? floppy_image::DSDD : floppy_image::SSDD);
// Suck in the whole image
- std::vector<uint8_t> image_data(size);
- size_t actual;
- io.read_at(0, image_data.data(), size, actual);
+ auto const [err, image_data, actual] = read_at(io, 0, size);
+ if (err || (actual != size)) {
+ return false;
+ }
// Get interleave factor from image
unsigned il = (unsigned)image_data[ IL_OFFSET ] * 256 + image_data[ IL_OFFSET + 1 ];
@@ -209,8 +210,7 @@ bool hpi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
while (get_next_sector(bitstream , pos , track_no , head_no , sector_no , sector_data)) {
if (track_no == cyl && head_no == head && sector_no < HPI_SECTORS) {
unsigned offset_in_image = chs_to_lba(cyl, head, sector_no, heads) * HPI_SECTOR_SIZE;
- size_t actual;
- io.write_at(offset_in_image, sector_data, HPI_SECTOR_SIZE, actual);
+ /*auto const [err, actual] =*/ write_at(io, offset_in_image, sector_data, HPI_SECTOR_SIZE); // FIXME: check for errors
}
}
}
diff --git a/src/lib/formats/hti_tape.cpp b/src/lib/formats/hti_tape.cpp
index f4a5727d591..7d6119860f1 100644
--- a/src/lib/formats/hti_tape.cpp
+++ b/src/lib/formats/hti_tape.cpp
@@ -11,6 +11,8 @@
#include "ioprocs.h"
#include "multibyte.h"
+#include <tuple>
+
static constexpr uint32_t OLD_FILE_MAGIC = 0x5441434f; // Magic value at start of old-format image file: "TACO"
static constexpr uint32_t FILE_MAGIC_DELTA = 0x48544930; // Magic value at start of delta-modulation image file: "HTI0"
@@ -54,10 +56,12 @@ bool hti_format_t::load_tape(util::random_read &io)
return false;
}
- size_t actual;
- uint8_t tmp[ 4 ];
+ uint8_t tmp[4];
+ auto const [err, actual] = read(io, tmp, 4);
+ if (err || (4 != actual)) {
+ return false;
+ }
- io.read(tmp, 4, actual);
auto magic = get_u32be(tmp);
if (((m_img_format == HTI_DELTA_MOD_16_BITS || m_img_format == HTI_DELTA_MOD_17_BITS) && magic != FILE_MAGIC_DELTA && magic != OLD_FILE_MAGIC) ||
(m_img_format == HTI_MANCHESTER_MOD && magic != FILE_MAGIC_MANCHESTER)) {
@@ -65,7 +69,7 @@ bool hti_format_t::load_tape(util::random_read &io)
}
for (unsigned i = 0; i < no_of_tracks(); i++) {
- tape_track_t& track = m_tracks[ i ];
+ tape_track_t &track = m_tracks[i];
if (!load_track(io, track, magic == OLD_FILE_MAGIC)) {
clear_tape();
return false;
@@ -77,17 +81,16 @@ bool hti_format_t::load_tape(util::random_read &io)
void hti_format_t::save_tape(util::random_read_write &io)
{
- io.seek(0, SEEK_SET);
+ io.seek(0, SEEK_SET); // FIXME: check for errors
- size_t actual;
- uint8_t tmp[ 4 ];
+ uint8_t tmp[4];
put_u32be(tmp, m_img_format == HTI_MANCHESTER_MOD ? FILE_MAGIC_MANCHESTER : FILE_MAGIC_DELTA);
- io.write(tmp, 4, actual);
+ write(io, tmp, 4); // FIXME: check for errors
for (unsigned i = 0; i < no_of_tracks(); i++) {
- const tape_track_t& track = m_tracks[ i ];
- tape_pos_t next_pos = (tape_pos_t)-1;
+ const tape_track_t &track = m_tracks[i];
+ tape_pos_t next_pos = tape_pos_t(-1);
unsigned n_words = 0;
tape_track_t::const_iterator it_start;
for (tape_track_t::const_iterator it = track.cbegin(); it != track.cend(); ++it) {
@@ -102,20 +105,20 @@ void hti_format_t::save_tape(util::random_read_write &io)
dump_sequence(io, it_start, n_words);
// End of track
put_u32le(tmp, (uint32_t)-1);
- io.write(tmp, 4, actual);
+ write(io, tmp, 4); // FIXME: check for errors
}
}
void hti_format_t::clear_tape()
{
- for (tape_track_t& track : m_tracks) {
+ for (tape_track_t &track : m_tracks) {
track.clear();
}
}
hti_format_t::tape_pos_t hti_format_t::word_length(tape_word_t w) const
{
- unsigned zeros , ones;
+ unsigned zeros, ones;
// pop count of w
ones = (w & 0x5555) + ((w >> 1) & 0x5555);
@@ -128,7 +131,7 @@ hti_format_t::tape_pos_t hti_format_t::word_length(tape_word_t w) const
return zeros * bit_length(false) + ones * bit_length(true);
}
-hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t& it , bool forward) const
+hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t &it, bool forward) const
{
if (forward) {
return word_end_pos(it);
@@ -137,7 +140,7 @@ hti_format_t::tape_pos_t hti_format_t::farthest_end(const track_iterator_t& it ,
}
}
-bool hti_format_t::pos_offset(tape_pos_t& pos , bool forward , tape_pos_t offset)
+bool hti_format_t::pos_offset(tape_pos_t &pos, bool forward, tape_pos_t offset)
{
if (offset == 0) {
return true;
@@ -161,7 +164,7 @@ bool hti_format_t::pos_offset(tape_pos_t& pos , bool forward , tape_pos_t offset
}
}
-hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward)
+hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos, bool forward)
{
if (forward) {
for (tape_pos_t hole : tape_holes) {
@@ -172,9 +175,9 @@ hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward)
// No more holes: will hit end of tape
return NULL_TAPE_POS;
} else {
- for (int i = (sizeof(tape_holes) / sizeof(tape_holes[ 0 ])) - 1; i >= 0; i--) {
- if (tape_holes[ i ] < pos) {
- return tape_holes[ i ];
+ for (int i = (sizeof(tape_holes) / sizeof(tape_holes[0])) - 1; i >= 0; i--) {
+ if (tape_holes[i] < pos) {
+ return tape_holes[i];
}
}
// No more holes: will hit start of tape
@@ -182,16 +185,16 @@ hti_format_t::tape_pos_t hti_format_t::next_hole(tape_pos_t pos , bool forward)
}
}
-void hti_format_t::write_word(unsigned track_no , tape_pos_t start , tape_word_t word , tape_pos_t& length , bool forward)
+void hti_format_t::write_word(unsigned track_no, tape_pos_t start, tape_word_t word, tape_pos_t &length, bool forward)
{
- tape_track_t& track = m_tracks[ track_no ];
+ tape_track_t &track = m_tracks[track_no];
track_iterator_t it_low = track.lower_bound(start);
- adjust_it(track , it_low , start);
+ adjust_it(track, it_low, start);
length = word_length(word);
tape_pos_t end_pos = start + length;
track_iterator_t it_high = track.lower_bound(end_pos);
- track.erase(it_low , it_high);
+ track.erase(it_low, it_high);
// A 0 word is inserted after the word being written, if space allows.
// This is meant to avoid fragmentation of the slack space at the end of a record
@@ -203,24 +206,24 @@ void hti_format_t::write_word(unsigned track_no , tape_pos_t start , tape_word_t
it_high--;
}
- track.insert(it_high , std::make_pair(start, word));
+ track.insert(it_high, std::make_pair(start, word));
}
-void hti_format_t::write_gap(unsigned track_no , tape_pos_t a , tape_pos_t b)
+void hti_format_t::write_gap(unsigned track_no, tape_pos_t a, tape_pos_t b)
{
- ensure_a_lt_b(a , b);
- tape_track_t& track = m_tracks[ track_no ];
+ ensure_a_lt_b(a, b);
+ tape_track_t &track = m_tracks[track_no];
track_iterator_t it_low = track.lower_bound(a);
- adjust_it(track , it_low , a);
+ adjust_it(track, it_low, a);
track_iterator_t it_high = track.lower_bound(b);
track.erase(it_low, it_high);
}
-bool hti_format_t::just_gap(unsigned track_no , tape_pos_t a , tape_pos_t b)
+bool hti_format_t::just_gap(unsigned track_no, tape_pos_t a, tape_pos_t b)
{
- ensure_a_lt_b(a , b);
- tape_track_t& track = m_tracks[ track_no ];
+ ensure_a_lt_b(a, b);
+ tape_track_t &track = m_tracks[track_no];
track_iterator_t it_low = track.lower_bound(a);
track_iterator_t it_high = track.lower_bound(b);
@@ -229,9 +232,9 @@ bool hti_format_t::just_gap(unsigned track_no , tape_pos_t a , tape_pos_t b)
return it_low == it_high;
}
-bool hti_format_t::next_data(unsigned track_no , tape_pos_t pos , bool forward , bool inclusive , track_iterator_t& it)
+bool hti_format_t::next_data(unsigned track_no, tape_pos_t pos, bool forward, bool inclusive, track_iterator_t &it)
{
- tape_track_t& track = m_tracks[ track_no ];
+ tape_track_t &track = m_tracks[track_no];
it = track.lower_bound(pos);
if (forward) {
if (inclusive) {
@@ -251,9 +254,9 @@ bool hti_format_t::next_data(unsigned track_no , tape_pos_t pos , bool forward ,
}
}
-hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no , bool forward , track_iterator_t& it)
+hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no, bool forward, track_iterator_t &it)
{
- tape_track_t& track = m_tracks[ track_no ];
+ tape_track_t &track = m_tracks[track_no];
if (forward) {
tape_pos_t prev_pos = word_end_pos(it);
++it;
@@ -275,7 +278,7 @@ hti_format_t::adv_res_t hti_format_t::adv_it(unsigned track_no , bool forward ,
}
}
-bool hti_format_t::sync_with_record(unsigned track_no , track_iterator_t& it , unsigned& bit_idx)
+bool hti_format_t::sync_with_record(unsigned track_no, track_iterator_t &it, unsigned &bit_idx)
{
while ((it->second & (1U << bit_idx)) == 0) {
if (bit_idx) {
@@ -296,7 +299,7 @@ bool hti_format_t::sync_with_record(unsigned track_no , track_iterator_t& it , u
return true;
}
-hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no , track_iterator_t& it , unsigned& bit_idx , tape_word_t& word)
+hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no, track_iterator_t &it, unsigned &bit_idx, tape_word_t &word)
{
if (bit_idx == 15) {
auto res = adv_it(track_no, true, it);
@@ -319,13 +322,13 @@ hti_format_t::adv_res_t hti_format_t::next_word(unsigned track_no , track_iterat
}
}
-bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward , tape_pos_t min_gap)
+bool hti_format_t::next_gap(unsigned track_no, tape_pos_t &pos, bool forward, tape_pos_t min_gap)
{
tape_track_t::iterator it;
// First align with next data
- next_data(track_no , pos , forward , true , it);
+ next_data(track_no, pos, forward, true, it);
// Then scan for 1st gap
- tape_track_t& track = m_tracks[ track_no ];
+ tape_track_t &track = m_tracks[track_no];
bool done = false;
track_iterator_t prev_it;
unsigned n_gaps = 1;
@@ -346,7 +349,7 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward ,
adv_res_t adv_res;
do {
prev_it = it;
- adv_res = adv_it(track_no , forward , it);
+ adv_res = adv_it(track_no, forward, it);
} while (adv_res == ADV_CONT_DATA);
pos = word_end_pos(prev_it);
}
@@ -366,32 +369,36 @@ bool hti_format_t::next_gap(unsigned track_no , tape_pos_t& pos , bool forward ,
adv_res_t adv_res;
do {
prev_it = it;
- adv_res = adv_it(track_no , forward , it);
+ adv_res = adv_it(track_no, forward, it);
} while (adv_res == ADV_CONT_DATA);
pos = prev_it->first;
}
}
// Set "pos" where minimum gap size is met
- pos_offset(pos , forward , min_gap);
+ pos_offset(pos, forward, min_gap);
return n_gaps == 0;
}
-bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool old_format)
+bool hti_format_t::load_track(util::random_read &io, tape_track_t &track, bool old_format)
{
- size_t actual;
- uint8_t tmp[ 4 ];
- uint32_t tmp32;
tape_pos_t delta_pos = 0;
tape_pos_t last_word_end = 0;
track.clear();
while (1) {
- // Read no. of words to follow
- io.read(tmp, 4, actual);
+ std::error_condition err;
+ size_t actual;
+ uint8_t tmp[4];
+ uint32_t tmp32;
+ // Read no. of words to follow
+ std::tie(err, actual) = read(io, tmp, 4);
+ if (err || (4 != actual)) {
+ return false;
+ }
tmp32 = get_u32le(tmp);
// Track ends
@@ -402,8 +409,10 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool
unsigned n_words = tmp32;
// Read tape position of block
- io.read(tmp, 4, actual);
-
+ std::tie(err, actual) = read(io, tmp, 4);
+ if (err || (4 != actual)) {
+ return false;
+ }
tmp32 = get_u32le(tmp);
tape_pos_t pos = (tape_pos_t)tmp32 + delta_pos;
@@ -414,11 +423,14 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool
for (unsigned i = 0; i < n_words; i++) {
uint16_t tmp16;
- io.read(tmp, 2, actual);
+ std::tie(err, actual) = read(io, tmp, 2);
+ if (err || (2 != actual)) {
+ return false;
+ }
tmp16 = get_u16le(tmp);
if (!old_format) {
- track.insert(std::make_pair(pos , tmp16));
+ track.insert(std::make_pair(pos, tmp16));
pos += word_length(tmp16);
} else if (m_img_format == HTI_DELTA_MOD_16_BITS) {
// Convert HP9845 & HP85 old format
@@ -471,29 +483,28 @@ bool hti_format_t::load_track(util::random_read &io , tape_track_t& track , bool
}
}
-void hti_format_t::dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words)
+void hti_format_t::dump_sequence(util::random_read_write &io, tape_track_t::const_iterator it_start, unsigned n_words)
{
if (n_words) {
- size_t actual;
- uint8_t tmp[ 8 ];
- put_u32le(&tmp[ 0 ], n_words);
- put_u32le(&tmp[ 4 ], it_start->first);
- io.write(tmp, 8, actual);
+ uint8_t tmp[8];
+ put_u32le(&tmp[0], n_words);
+ put_u32le(&tmp[4], it_start->first);
+ write(io, tmp, 8); // FIXME: check for errors
for (unsigned i = 0; i < n_words; i++) {
put_u16le(tmp, it_start->second);
- io.write(tmp, 2, actual);
+ write(io, tmp, 2); // FIXME: check for errors
++it_start;
}
}
}
-hti_format_t::tape_pos_t hti_format_t::word_end_pos(const track_iterator_t& it) const
+hti_format_t::tape_pos_t hti_format_t::word_end_pos(const track_iterator_t &it) const
{
return it->first + word_length(it->second);
}
-void hti_format_t::adjust_it(tape_track_t& track , track_iterator_t& it , tape_pos_t pos) const
+void hti_format_t::adjust_it(tape_track_t &track, track_iterator_t &it, tape_pos_t pos) const
{
if (it != track.begin()) {
--it;
@@ -503,7 +514,7 @@ void hti_format_t::adjust_it(tape_track_t& track , track_iterator_t& it , tape_p
}
}
-void hti_format_t::ensure_a_lt_b(tape_pos_t& a , tape_pos_t& b)
+void hti_format_t::ensure_a_lt_b(tape_pos_t &a, tape_pos_t &b)
{
if (a > b) {
// Ensure A always comes before B
diff --git a/src/lib/formats/hti_tape.h b/src/lib/formats/hti_tape.h
index 373c971d174..d343133583f 100644
--- a/src/lib/formats/hti_tape.h
+++ b/src/lib/formats/hti_tape.h
@@ -22,8 +22,6 @@
class hti_format_t
{
public:
- hti_format_t();
-
// Tape position, 1 unit = 1 inch / (968 * 1024)
typedef int32_t tape_pos_t;
@@ -55,7 +53,6 @@ public:
// Iterator to access words on tape
typedef tape_track_t::iterator track_iterator_t;
- // Set image format
enum image_format_t {
// Delta modulation, 16 bits per word, 2 tracks per cartridge
// HP 9845 & HP 85
@@ -68,6 +65,16 @@ public:
HTI_MANCHESTER_MOD
};
+ enum adv_res_t
+ {
+ ADV_NO_MORE_DATA,
+ ADV_CONT_DATA,
+ ADV_DISCONT_DATA
+ };
+
+ hti_format_t();
+
+ // Set image format
void set_image_format(image_format_t fmt) { m_img_format = fmt; }
// Return number of tracks
@@ -86,55 +93,48 @@ public:
// Return physical length of a 16-bit word on tape
tape_pos_t word_length(tape_word_t w) const;
- tape_pos_t farthest_end(const track_iterator_t& it , bool forward) const;
+ tape_pos_t farthest_end(const track_iterator_t &it, bool forward) const;
- static bool pos_offset(tape_pos_t& pos , bool forward , tape_pos_t offset);
+ static bool pos_offset(tape_pos_t &pos, bool forward, tape_pos_t offset);
// Position of next hole tape will reach in a given direction
- static tape_pos_t next_hole(tape_pos_t pos , bool forward);
+ static tape_pos_t next_hole(tape_pos_t pos, bool forward);
// Write a data word on tape
- void write_word(unsigned track_no , tape_pos_t start , tape_word_t word , tape_pos_t& length , bool forward = true);
+ void write_word(unsigned track_no, tape_pos_t start, tape_word_t word, tape_pos_t &length, bool forward = true);
// Write a gap on tape
- void write_gap(unsigned track_no , tape_pos_t a , tape_pos_t b);
+ void write_gap(unsigned track_no, tape_pos_t a, tape_pos_t b);
// Check that a section of tape has no data (it's just gap)
- bool just_gap(unsigned track_no , tape_pos_t a , tape_pos_t b);
+ bool just_gap(unsigned track_no, tape_pos_t a, tape_pos_t b);
// Return position of next data word in a given direction
- bool next_data(unsigned track_no , tape_pos_t pos , bool forward , bool inclusive , track_iterator_t& it);
-
- enum adv_res_t
- {
- ADV_NO_MORE_DATA,
- ADV_CONT_DATA,
- ADV_DISCONT_DATA
- };
+ bool next_data(unsigned track_no, tape_pos_t pos, bool forward, bool inclusive, track_iterator_t &it);
// Advance an iterator to next word of data
- adv_res_t adv_it(unsigned track_no , bool forward , track_iterator_t& it);
+ adv_res_t adv_it(unsigned track_no, bool forward, track_iterator_t &it);
// Sync with the preamble of a record
- bool sync_with_record(unsigned track_no , track_iterator_t& it , unsigned& bit_idx);
+ bool sync_with_record(unsigned track_no, track_iterator_t &it, unsigned &bit_idx);
// Get a data word from record, after syncing
- adv_res_t next_word(unsigned track_no , track_iterator_t& it , unsigned& bit_idx , tape_word_t& word);
+ adv_res_t next_word(unsigned track_no, track_iterator_t &it, unsigned &bit_idx, tape_word_t &word);
// Scan for beginning of next gap in a given direction
- bool next_gap(unsigned track_no , tape_pos_t& pos , bool forward , tape_pos_t min_gap);
+ bool next_gap(unsigned track_no, tape_pos_t &pos, bool forward, tape_pos_t min_gap);
private:
// Content of tape tracks
- tape_track_t m_tracks[ 2 ];
+ tape_track_t m_tracks[2];
// Image format
image_format_t m_img_format;
- bool load_track(util::random_read &io , tape_track_t& track , bool old_format);
- static void dump_sequence(util::random_read_write &io , tape_track_t::const_iterator it_start , unsigned n_words);
+ bool load_track(util::random_read &io, tape_track_t &track, bool old_format);
+ static void dump_sequence(util::random_read_write &io, tape_track_t::const_iterator it_start, unsigned n_words);
- tape_pos_t word_end_pos(const track_iterator_t& it) const;
- void adjust_it(tape_track_t& track , track_iterator_t& it , tape_pos_t pos) const;
- static void ensure_a_lt_b(tape_pos_t& a , tape_pos_t& b);
+ tape_pos_t word_end_pos(const track_iterator_t &it) const;
+ void adjust_it(tape_track_t &track, track_iterator_t &it, tape_pos_t pos) const;
+ static void ensure_a_lt_b(tape_pos_t &a, tape_pos_t &b);
};
#endif // MAME_FORMATS_HTI_TAPE_H
diff --git a/src/lib/formats/hxchfe_dsk.cpp b/src/lib/formats/hxchfe_dsk.cpp
index a8cf09feaf2..da8d660bb33 100644
--- a/src/lib/formats/hxchfe_dsk.cpp
+++ b/src/lib/formats/hxchfe_dsk.cpp
@@ -106,6 +106,8 @@
#include "osdcore.h" // osd_printf_*
+#include <tuple>
+
#define HFE_FORMAT_HEADER "HXCPICFE"
@@ -139,10 +141,11 @@ bool hfe_format::supports_save() const noexcept
int hfe_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[8];
-
- size_t actual;
- io.read_at(0, &header, sizeof(header), actual);
- if ( memcmp( header, HFE_FORMAT_HEADER, 8 ) ==0) {
+ auto const [err, actual] = read_at(io, 0, &header, sizeof(header));
+ if (err || (sizeof(header) != actual)) {
+ return 0;
+ }
+ if (!memcmp(header, HFE_FORMAT_HEADER, 8)) {
return FIFID_SIGN;
}
return 0;
@@ -150,16 +153,15 @@ int hfe_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
- uint8_t header[HEADER_LENGTH];
- uint8_t track_table[TRACK_TABLE_LENGTH];
- header_info info;
int drivecyl, driveheads;
image.get_maximal_geometry(drivecyl, driveheads);
// read header
- io.read_at(0, header, HEADER_LENGTH, actual);
+ uint8_t header[HEADER_LENGTH];
+ std::tie(err, actual) = read_at(io, 0, header, HEADER_LENGTH); // FIXME: check for errors and premature EOF
// get values
// Format revision must be 0
@@ -169,6 +171,7 @@ bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return false;
}
+ header_info info;
info.m_cylinders = header[9] & 0xff;
info.m_heads = header[10] & 0xff;
@@ -194,7 +197,7 @@ bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return false;
}
- info.m_track_encoding = (encoding_t)(header[11] & 0xff);
+ info.m_track_encoding = encoding_t(header[11] & 0xff);
if (info.m_track_encoding > EMU_FM_ENCODING)
{
@@ -231,7 +234,8 @@ bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::ve
// read track lookup table (multiple of 512)
int table_offset = get_u16le(&header[18]);
- io.read_at(table_offset<<9, track_table, TRACK_TABLE_LENGTH, actual);
+ uint8_t track_table[TRACK_TABLE_LENGTH];
+ std::tie(err, actual) = read_at(io, table_offset<<9, track_table, TRACK_TABLE_LENGTH); // FIXME: check for errors and premature EOF
for (int i=0; i < info.m_cylinders; i++)
{
@@ -244,10 +248,9 @@ bool hfe_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for(int cyl=0; cyl < info.m_cylinders; cyl++)
{
// actual data read
- // The HFE format defines an interleave of the two sides per cylinder
- // at every 256 bytes
+ // The HFE format defines an interleave of the two sides per cylinder at every 256 bytes
cylinder_buffer.resize(info.m_cyl_length[cyl]);
- io.read_at(info.m_cyl_offset[cyl]<<9, &cylinder_buffer[0], info.m_cyl_length[cyl], actual);
+ std::tie(err, actual) = read_at(io, info.m_cyl_offset[cyl]<<9, &cylinder_buffer[0], info.m_cyl_length[cyl]); // FIXME: check for errors and premature EOF
generate_track_from_hfe_bitstream(cyl, 0, samplelength, &cylinder_buffer[0], info.m_cyl_length[cyl], image);
if (info.m_heads == 2)
diff --git a/src/lib/formats/hxcmfm_dsk.cpp b/src/lib/formats/hxcmfm_dsk.cpp
index 0390b55bca0..d9fda047dea 100644
--- a/src/lib/formats/hxcmfm_dsk.cpp
+++ b/src/lib/formats/hxcmfm_dsk.cpp
@@ -6,6 +6,7 @@
#include "ioprocs.h"
#include <cstring>
+#include <tuple>
#define MFM_FORMAT_HEADER "HXCMFM"
@@ -63,10 +64,11 @@ bool mfm_format::supports_save() const noexcept
int mfm_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t header[7];
-
- size_t actual;
- io.read_at(0, &header, sizeof(header), actual);
- if ( memcmp( header, MFM_FORMAT_HEADER, 6 ) ==0) {
+ auto const [err, actual] = read_at(io, 0, &header, sizeof(header)); // FIXME: does this really need to read 7 bytes? only 6 are checked. also check for premature EOF
+ if (err) {
+ return 0;
+ }
+ if (!memcmp(header, MFM_FORMAT_HEADER, 6)) {
return FIFID_SIGN;
}
return 0;
@@ -74,12 +76,13 @@ int mfm_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool mfm_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
MFMIMG header;
MFMTRACKIMG trackdesc;
// read header
- io.read_at(0, &header, sizeof(header), actual);
+ std::tie(err, actual) = read_at(io, 0, &header, sizeof(header)); // FIXME: check for errors and premature EOF
int drivecyl, driveheads;
image.get_maximal_geometry(drivecyl, driveheads);
@@ -91,12 +94,12 @@ bool mfm_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for(int side=0; side < header.number_of_side; side++) {
if (!skip_odd || track%2 == 0) {
// read location of
- io.read_at((header.mfmtracklistoffset)+( counter *sizeof(trackdesc)), &trackdesc, sizeof(trackdesc), actual);
+ std::tie(err, actual) = read_at(io, header.mfmtracklistoffset + (counter * sizeof(trackdesc)), &trackdesc, sizeof(trackdesc)); // FIXME: check for errors and premature EOF
trackbuf.resize(trackdesc.mfmtracksize);
// actual data read
- io.read_at(trackdesc.mfmtrackoffset, &trackbuf[0], trackdesc.mfmtracksize, actual);
+ std::tie(err, actual) = read_at(io, trackdesc.mfmtrackoffset, &trackbuf[0], trackdesc.mfmtracksize); // FIXME: check for errors and premature EOF
if (skip_odd) {
generate_track_from_bitstream(track/2, side, &trackbuf[0], trackdesc.mfmtracksize*8, image);
@@ -117,7 +120,6 @@ bool mfm_format::load(util::random_read &io, uint32_t form_factor, const std::ve
bool mfm_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
// TODO: HD support
- size_t actual;
MFMIMG header;
int track_count, head_count;
image.get_actual_geometry(track_count, head_count);
@@ -130,7 +132,7 @@ bool mfm_format::save(util::random_read_write &io, const std::vector<uint32_t> &
header.floppyiftype = 4;
header.mfmtracklistoffset = sizeof(MFMIMG);
- io.write_at(0, &header, sizeof(MFMIMG), actual);
+ write_at(io, 0, &header, sizeof(MFMIMG)); // FIXME: check for errors
int tpos = sizeof(MFMIMG);
int dpos = tpos + track_count*head_count*sizeof(MFMTRACKIMG);
@@ -149,8 +151,8 @@ bool mfm_format::save(util::random_read_write &io, const std::vector<uint32_t> &
trackdesc.mfmtracksize = packed.size();
trackdesc.mfmtrackoffset = dpos;
- io.write_at(tpos, &trackdesc, sizeof(MFMTRACKIMG), actual);
- io.write_at(dpos, packed.data(), packed.size(), actual);
+ write_at(io, tpos, &trackdesc, sizeof(MFMTRACKIMG)); // FIXME: check for errors
+ write_at(io, dpos, packed.data(), packed.size()); // FIXME: check for errors
tpos += sizeof(MFMTRACKIMG);
dpos += packed.size();
diff --git a/src/lib/formats/ibmxdf_dsk.cpp b/src/lib/formats/ibmxdf_dsk.cpp
index 5fb1f3da411..c9704361f65 100644
--- a/src/lib/formats/ibmxdf_dsk.cpp
+++ b/src/lib/formats/ibmxdf_dsk.cpp
@@ -186,8 +186,8 @@ bool ibmxdf_format::load(util::random_read &io, uint32_t form_factor, const std:
const format &f = formats[type];
- for(int track=0; track < f.track_count; track++)
- for(int head=0; head < f.head_count; head++) {
+ for(int track = 0; track < f.track_count; track++) {
+ for(int head = 0; head < f.head_count; head++) {
uint8_t sectdata[23 * 2 * 512]; // XXX magic
desc_s sectors[40];
floppy_image_format_t::desc_e *desc;
@@ -213,10 +213,10 @@ bool ibmxdf_format::load(util::random_read &io, uint32_t form_factor, const std:
build_sector_description(tf, sectdata, sectors, track, head);
int const track_size = compute_track_size(f) * 2; // read both sides at once
- size_t actual;
- io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, get_image_offset(f, head, track), sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
+ }
image.set_variant(f.variant);
diff --git a/src/lib/formats/idpart_dsk.cpp b/src/lib/formats/idpart_dsk.cpp
new file mode 100644
index 00000000000..9d4c641fa41
--- /dev/null
+++ b/src/lib/formats/idpart_dsk.cpp
@@ -0,0 +1,53 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*********************************************************************
+
+ formats/idpart_dsk.cpp
+
+ Iskra Delta Partner format
+
+*********************************************************************/
+
+#include "formats/idpart_dsk.h"
+
+idpart_format::idpart_format() : upd765_format(formats)
+{
+}
+
+const char *idpart_format::name() const noexcept
+{
+ return "idpart";
+}
+
+const char *idpart_format::description() const noexcept
+{
+ return "Iskra Delta Partner disk image";
+}
+
+const char *idpart_format::extensions() const noexcept
+{
+ return "img";
+}
+
+// Unverified gap sizes.
+const idpart_format::format idpart_format::formats[] = {
+ {
+ floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM,
+ 2000,
+ 18, 73, 2,
+ 256, {},
+ 1, {},
+ 80, 50, 22
+ },
+ {
+ floppy_image::FF_525, floppy_image::DSQD, floppy_image::MFM,
+ 2000,
+ 18, 77, 2,
+ 256, {},
+ 1, {},
+ 80, 50, 22
+ },
+ {}
+};
+
+const idpart_format FLOPPY_IDPART_FORMAT;
diff --git a/src/lib/formats/idpart_dsk.h b/src/lib/formats/idpart_dsk.h
new file mode 100644
index 00000000000..6f5977a5cfa
--- /dev/null
+++ b/src/lib/formats/idpart_dsk.h
@@ -0,0 +1,32 @@
+// license:BSD-3-Clause
+// copyright-holders:Miodrag Milanovic
+/*********************************************************************
+
+ formats/idpart_dsk.h
+
+ Iskra Delta Partner format
+
+*********************************************************************/
+#ifndef MAME_FORMATS_IDPART_DSK_H
+#define MAME_FORMATS_IDPART_DSK_H
+
+#pragma once
+
+#include "upd765_dsk.h"
+
+class idpart_format : public upd765_format
+{
+public:
+ idpart_format();
+
+ virtual const char *name() const noexcept override;
+ virtual const char *description() const noexcept override;
+ virtual const char *extensions() const noexcept override;
+
+private:
+ static const format formats[];
+};
+
+extern const idpart_format FLOPPY_IDPART_FORMAT;
+
+#endif // MAME_FORMATS_IDPART_DSK_H
diff --git a/src/lib/formats/imd_dsk.cpp b/src/lib/formats/imd_dsk.cpp
index fde013f3113..907440dc922 100644
--- a/src/lib/formats/imd_dsk.cpp
+++ b/src/lib/formats/imd_dsk.cpp
@@ -425,9 +425,10 @@ void imd_format::fixnum(char *start, char *end) const
int imd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
char h[4];
+ auto const [err, actual] = read_at(io, 0, h, 4);
+ if(err || (4 != actual))
+ return 0;
- size_t actual;
- io.read_at(0, h, 4, actual);
if(!memcmp(h, "IMD ", 4))
return FIFID_SIGN;
@@ -451,9 +452,9 @@ bool imd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t size;
if(io.length(size))
return false;
- std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [err, img, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
uint64_t pos, savepos;
for(pos=0; pos < size && img[pos] != 0x1a; pos++) { }
diff --git a/src/lib/formats/img_dsk.cpp b/src/lib/formats/img_dsk.cpp
index fb6f1a3bfb3..66e097c281e 100644
--- a/src/lib/formats/img_dsk.cpp
+++ b/src/lib/formats/img_dsk.cpp
@@ -72,9 +72,10 @@ bool img_format::load(util::random_read &io, uint32_t form_factor, const std::ve
image.set_variant(is_dd ? floppy_image::SSDD : floppy_image::SSSD);
// Suck in the whole image
- std::vector<uint8_t> image_data(size);
- size_t actual;
- io.read_at(0, image_data.data(), size, actual);
+ auto const [err, image_data, actual] = read_at(io, 0, size);
+ if (err || (actual != size)) {
+ return false;
+ }
for (unsigned cyl = 0; cyl < TRACKS; cyl++) {
if (is_dd) {
@@ -134,7 +135,7 @@ bool img_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sects[ sector ].sector = real_sector;
sects[ sector ].bad_crc = false;
sects[ sector ].deleted = false;
- sects[ sector ].data = image_data.data() + offset_in_image;
+ sects[ sector ].data = &image_data[offset_in_image];
}
build_pc_track_fm(cyl, 0, image, 83333, SECTORS_FM, sects, 33, 46, 32, 11);
}
@@ -155,8 +156,7 @@ bool img_format::save(util::random_read_write &io, const std::vector<uint32_t> &
while (get_next_sector(bitstream , pos , track_no , sector_no , sector_data)) {
if (track_no == cyl && sector_no >= 1 && sector_no <= SECTORS) {
unsigned offset_in_image = (cyl * SECTORS + sector_no - 1) * SECTOR_SIZE;
- size_t actual;
- io.write_at(offset_in_image, sector_data, SECTOR_SIZE, actual);
+ /*auto const [err, actual] =*/ write_at(io, offset_in_image, sector_data, SECTOR_SIZE); // FIXME: check for errors
}
}
} else {
@@ -164,8 +164,7 @@ bool img_format::save(util::random_read_write &io, const std::vector<uint32_t> &
auto sects = extract_sectors_from_bitstream_fm_pc(bitstream);
for (unsigned s = 1; s <= SECTORS_FM; s++) {
unsigned offset_in_image = (cyl * SECTORS_FM + s - 1) * SECTOR_SIZE;
- size_t actual;
- io.write_at(offset_in_image, sects[ s ].data(), SECTOR_SIZE, actual);
+ /*auto const [err, actual] =*/ write_at(io, offset_in_image, sects[ s ].data(), SECTOR_SIZE); // FIXME: check for errors and premature EOF
}
}
}
diff --git a/src/lib/formats/ipf_dsk.cpp b/src/lib/formats/ipf_dsk.cpp
index 072dd96c99e..b47eca030f2 100644
--- a/src/lib/formats/ipf_dsk.cpp
+++ b/src/lib/formats/ipf_dsk.cpp
@@ -8,6 +8,72 @@
#include <cstring>
+struct ipf_format::ipf_decode {
+ struct track_info {
+ uint32_t cylinder = 0, head = 0, type = 0;
+ uint32_t sigtype = 0, process = 0, reserved[3] = { 0, 0, 0 };
+ uint32_t size_bytes = 0, size_cells = 0;
+ uint32_t index_bytes = 0, index_cells = 0;
+ uint32_t datasize_cells = 0, gapsize_cells = 0;
+ uint32_t block_count = 0, weak_bits = 0;
+
+ uint32_t data_size_bits = 0;
+
+ bool info_set = false;
+
+ const uint8_t *data = nullptr;
+ uint32_t data_size = 0;
+ };
+
+ std::vector<track_info> tinfos;
+ uint32_t tcount = 0;
+
+ uint32_t type = 0, release = 0, revision = 0;
+ uint32_t encoder_type = 0, encoder_revision = 0, origin = 0;
+ uint32_t min_cylinder = 0, max_cylinder = 0, min_head = 0, max_head = 0;
+ uint32_t credit_day = 0, credit_time = 0;
+ uint32_t platform[4] = {}, extra[5] = {};
+
+ uint32_t crc32r(const uint8_t *data, uint32_t size);
+
+ bool parse_info(const uint8_t *info);
+ bool parse_imge(const uint8_t *imge);
+ bool parse_data(const uint8_t *data, uint32_t &pos, uint32_t max_extra_size);
+
+ bool scan_one_tag(uint8_t *data, size_t size, uint32_t &pos, uint8_t *&tag, uint32_t &tsize);
+ bool scan_all_tags(uint8_t *data, size_t size);
+ static uint32_t rb(const uint8_t *&p, int count);
+
+ track_info *get_index(uint32_t idx);
+
+ void track_write_raw(std::vector<uint32_t>::iterator &tpos, const uint8_t *data, uint32_t cells, bool &context);
+ void track_write_mfm(std::vector<uint32_t>::iterator &tpos, const uint8_t *data, uint32_t start_offset, uint32_t patlen, uint32_t cells, bool &context);
+ void track_write_weak(std::vector<uint32_t>::iterator &tpos, uint32_t cells);
+ bool generate_block_data(const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, std::vector<uint32_t>::iterator tlimit, bool &context);
+
+ bool gap_description_to_reserved_size(const uint8_t *&data, const uint8_t *dlimit, uint32_t &res_size);
+ bool generate_gap_from_description(const uint8_t *&data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, uint32_t size, bool pre, bool &context);
+ bool generate_block_gap_0(uint32_t gap_cells, uint8_t pattern, uint32_t &spos, uint32_t ipos, std::vector<uint32_t>::iterator &tpos, bool &context);
+ bool generate_block_gap_1(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
+ bool generate_block_gap_2(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
+ bool generate_block_gap_3(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
+ bool generate_block_gap(uint32_t gap_type, uint32_t gap_cells, uint8_t pattern, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, bool &context);
+
+ bool generate_block(const track_info &t, uint32_t idx, uint32_t ipos, std::vector<uint32_t> &track, uint32_t &pos, uint32_t &dpos, uint32_t &gpos, uint32_t &spos, bool &context);
+ uint32_t block_compute_real_size(const track_info &t);
+
+ void timing_set(std::vector<uint32_t> &track, uint32_t start, uint32_t end, uint32_t time);
+ bool generate_timings(const track_info &t, std::vector<uint32_t> &track, const std::vector<uint32_t> &data_pos, const std::vector<uint32_t> &gap_pos);
+
+ void rotate(std::vector<uint32_t> &track, uint32_t offset, uint32_t size);
+ void mark_track_splice(std::vector<uint32_t> &track, uint32_t offset, uint32_t size);
+ bool generate_track(track_info &t, floppy_image &image);
+ bool generate_tracks(floppy_image &image);
+
+ bool parse(uint8_t *data, size_t size, floppy_image &image);
+};
+
+
const ipf_format FLOPPY_IPF_FORMAT;
const char *ipf_format::name() const noexcept
@@ -34,8 +100,9 @@ int ipf_format::identify(util::random_read &io, uint32_t form_factor, const std:
{
static const uint8_t refh[12] = { 0x43, 0x41, 0x50, 0x53, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0xd5, 0x73, 0xba };
uint8_t h[12];
- size_t actual;
- io.read_at(0, h, 12, actual);
+ auto const [err, actual] = read_at(io, 0, h, 12);
+ if(err || (12 != actual))
+ return 0;
if(!memcmp(h, refh, 12))
return FIFID_SIGN;
@@ -46,13 +113,13 @@ int ipf_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool ipf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
uint64_t size;
- if (io.length(size))
+ if(io.length(size))
+ return false;
+ auto const [err, data, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
return false;
- std::vector<uint8_t> data(size);
- size_t actual;
- io.read_at(0, &data[0], size, actual);
ipf_decode dec;
- return dec.parse(data, image);
+ return dec.parse(data.get(), size, image);
}
@@ -79,12 +146,12 @@ uint32_t ipf_format::ipf_decode::crc32r(const uint8_t *data, uint32_t size)
return ~crc;
}
-bool ipf_format::ipf_decode::parse(std::vector<uint8_t> &data, floppy_image &image)
+bool ipf_format::ipf_decode::parse(uint8_t *data, size_t size, floppy_image &image)
{
image.set_variant(floppy_image::DSDD); // Not handling anything else yet
tcount = 84*2+1; // Usual max
tinfos.resize(tcount);
- bool res = scan_all_tags(data);
+ bool res = scan_all_tags(data, size);
if(res)
res = generate_tracks(image);
tinfos.clear();
@@ -177,13 +244,13 @@ bool ipf_format::ipf_decode::parse_data(const uint8_t *data, uint32_t &pos, uint
return true;
}
-bool ipf_format::ipf_decode::scan_one_tag(std::vector<uint8_t> &data, uint32_t &pos, uint8_t *&tag, uint32_t &tsize)
+bool ipf_format::ipf_decode::scan_one_tag(uint8_t *data, size_t size, uint32_t &pos, uint8_t *&tag, uint32_t &tsize)
{
- if(data.size()-pos < 12)
+ if(size-pos < 12)
return false;
tag = &data[pos];
tsize = get_u32be(tag+4);
- if(data.size()-pos < tsize)
+ if(size-pos < tsize)
return false;
uint32_t crc = get_u32be(tag+8);
tag[8] = tag[9] = tag[10] = tag[11] = 0;
@@ -193,15 +260,14 @@ bool ipf_format::ipf_decode::scan_one_tag(std::vector<uint8_t> &data, uint32_t &
return true;
}
-bool ipf_format::ipf_decode::scan_all_tags(std::vector<uint8_t> &data)
+bool ipf_format::ipf_decode::scan_all_tags(uint8_t *data, size_t size)
{
uint32_t pos = 0;
- uint32_t size = data.size();
while(pos != size) {
uint8_t *tag;
uint32_t tsize;
- if(!scan_one_tag(data, pos, tag, tsize))
+ if(!scan_one_tag(data, size, pos, tag, tsize))
return false;
switch(get_u32be(tag)) {
diff --git a/src/lib/formats/ipf_dsk.h b/src/lib/formats/ipf_dsk.h
index 9e63b2bff38..a1c36f02f8d 100644
--- a/src/lib/formats/ipf_dsk.h
+++ b/src/lib/formats/ipf_dsk.h
@@ -21,71 +21,7 @@ public:
virtual bool supports_save() const noexcept override;
private:
- struct ipf_decode {
- struct track_info {
- uint32_t cylinder = 0, head = 0, type = 0;
- uint32_t sigtype = 0, process = 0, reserved[3] = { 0, 0, 0 };
- uint32_t size_bytes = 0, size_cells = 0;
- uint32_t index_bytes = 0, index_cells = 0;
- uint32_t datasize_cells = 0, gapsize_cells = 0;
- uint32_t block_count = 0, weak_bits = 0;
-
- uint32_t data_size_bits = 0;
-
- bool info_set = false;
-
- const uint8_t *data = nullptr;
- uint32_t data_size = 0;
- };
-
- std::vector<track_info> tinfos;
- uint32_t tcount = 0;
-
- uint32_t type = 0, release = 0, revision = 0;
- uint32_t encoder_type = 0, encoder_revision = 0, origin = 0;
- uint32_t min_cylinder = 0, max_cylinder = 0, min_head = 0, max_head = 0;
- uint32_t credit_day = 0, credit_time = 0;
- uint32_t platform[4] = {}, extra[5] = {};
-
- uint32_t crc32r(const uint8_t *data, uint32_t size);
-
- bool parse_info(const uint8_t *info);
- bool parse_imge(const uint8_t *imge);
- bool parse_data(const uint8_t *data, uint32_t &pos, uint32_t max_extra_size);
-
- bool scan_one_tag(std::vector<uint8_t> &data, uint32_t &pos, uint8_t *&tag, uint32_t &tsize);
- bool scan_all_tags(std::vector<uint8_t> &data);
- static uint32_t r32(const uint8_t *p);
- static uint32_t rb(const uint8_t *&p, int count);
-
- track_info *get_index(uint32_t idx);
-
- void track_write_raw(std::vector<uint32_t>::iterator &tpos, const uint8_t *data, uint32_t cells, bool &context);
- void track_write_mfm(std::vector<uint32_t>::iterator &tpos, const uint8_t *data, uint32_t start_offset, uint32_t patlen, uint32_t cells, bool &context);
- void track_write_weak(std::vector<uint32_t>::iterator &tpos, uint32_t cells);
- bool generate_block_data(const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, std::vector<uint32_t>::iterator tlimit, bool &context);
-
- bool gap_description_to_reserved_size(const uint8_t *&data, const uint8_t *dlimit, uint32_t &res_size);
- bool generate_gap_from_description(const uint8_t *&data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, uint32_t size, bool pre, bool &context);
- bool generate_block_gap_0(uint32_t gap_cells, uint8_t pattern, uint32_t &spos, uint32_t ipos, std::vector<uint32_t>::iterator &tpos, bool &context);
- bool generate_block_gap_1(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
- bool generate_block_gap_2(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
- bool generate_block_gap_3(uint32_t gap_cells, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator &tpos, bool &context);
- bool generate_block_gap(uint32_t gap_type, uint32_t gap_cells, uint8_t pattern, uint32_t &spos, uint32_t ipos, const uint8_t *data, const uint8_t *dlimit, std::vector<uint32_t>::iterator tpos, bool &context);
-
- bool generate_block(const track_info &t, uint32_t idx, uint32_t ipos, std::vector<uint32_t> &track, uint32_t &pos, uint32_t &dpos, uint32_t &gpos, uint32_t &spos, bool &context);
- uint32_t block_compute_real_size(const track_info &t);
-
- void timing_set(std::vector<uint32_t> &track, uint32_t start, uint32_t end, uint32_t time);
- bool generate_timings(const track_info &t, std::vector<uint32_t> &track, const std::vector<uint32_t> &data_pos, const std::vector<uint32_t> &gap_pos);
-
- void rotate(std::vector<uint32_t> &track, uint32_t offset, uint32_t size);
- void mark_track_splice(std::vector<uint32_t> &track, uint32_t offset, uint32_t size);
- bool generate_track(track_info &t, floppy_image &image);
- bool generate_tracks(floppy_image &image);
-
- bool parse(std::vector<uint8_t> &data, floppy_image &image);
- };
+ struct ipf_decode;
};
extern const ipf_format FLOPPY_IPF_FORMAT;
diff --git a/src/lib/formats/jfd_dsk.cpp b/src/lib/formats/jfd_dsk.cpp
index 813c7192ca9..46e933cedf1 100644
--- a/src/lib/formats/jfd_dsk.cpp
+++ b/src/lib/formats/jfd_dsk.cpp
@@ -197,8 +197,9 @@ int jfd_format::identify(util::random_read &io, uint32_t form_factor, const std:
return 0;
std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [ioerr, actual] = read_at(io, 0, &img[0], size);
+ if (ioerr || (actual != size))
+ return 0;
int err;
std::vector<uint8_t> gz_ptr(4);
@@ -222,7 +223,7 @@ int jfd_format::identify(util::random_read &io, uint32_t form_factor, const std:
err = inflateEnd(&d_stream);
if (err != Z_OK) return 0;
- img = gz_ptr;
+ img = std::move(gz_ptr);
}
if (!memcmp(&img[0], JFD_HEADER, sizeof(JFD_HEADER))) {
@@ -239,8 +240,9 @@ bool jfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return false;
std::vector<uint8_t> img(size);
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [ioerr, actual] = read_at(io, 0, &img[0], size);
+ if (ioerr || (actual != size))
+ return false;
int err;
std::vector<uint8_t> gz_ptr;
@@ -274,7 +276,7 @@ bool jfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
return false;
}
size = inflate_size;
- img = gz_ptr;
+ img = std::move(gz_ptr);
}
osd_printf_verbose("jfd_dsk: loading %s\n", &img[48]);
diff --git a/src/lib/formats/juku_dsk.cpp b/src/lib/formats/juku_dsk.cpp
index 05fdc9b8484..46d448a2c61 100644
--- a/src/lib/formats/juku_dsk.cpp
+++ b/src/lib/formats/juku_dsk.cpp
@@ -1,8 +1,8 @@
// license: BSD-3-Clause
-// copyright-holders: Dirk Best
+// copyright-holders: Dirk Best, Märt Põder
/***************************************************************************
- Juku E5101
+ Juku E5101/E5104
Disk image format
@@ -31,11 +31,11 @@ const char *juku_format::extensions() const noexcept
const juku_format::format juku_format::formats[] =
{
- { // 800k 5 1/4 inch double density single sided - gaps unverified (CP/M)
- floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM,
+ { // 386k 5.25" double density single sided - gaps unverified (CP/M)
+ floppy_image::FF_525, floppy_image::SSDD, floppy_image::MFM,
2000, 10, 80, 1, 512, {}, 1, {}, 32, 22, 35
},
- { // 800k 5 1/4 inch double density double sided - gaps unverified (CP/M)
+ { // 786k 5.25" double density "outout" double sided - gaps unverified (CP/M)
floppy_image::FF_525, floppy_image::DSDD, floppy_image::MFM,
2000, 10, 80, 2, 512, {}, 1, {}, 32, 22, 35
},
diff --git a/src/lib/formats/juku_dsk.h b/src/lib/formats/juku_dsk.h
index 414c351ac76..c78363ece14 100644
--- a/src/lib/formats/juku_dsk.h
+++ b/src/lib/formats/juku_dsk.h
@@ -1,8 +1,8 @@
// license: BSD-3-Clause
-// copyright-holders: Dirk Best
+// copyright-holders: Dirk Best, Märt Põder
/***************************************************************************
- Juku E5101
+ Juku E5101/E5104
Disk image format
diff --git a/src/lib/formats/jvc_dsk.cpp b/src/lib/formats/jvc_dsk.cpp
index ce0083a9deb..fcc5d97a5b5 100644
--- a/src/lib/formats/jvc_dsk.cpp
+++ b/src/lib/formats/jvc_dsk.cpp
@@ -141,11 +141,14 @@ bool jvc_format::parse_header(util::random_read &io, int &header_size, int &trac
uint8_t header[5];
// if we know that this is a header of a bad size, we can fail immediately; otherwise read the header
- size_t actual;
- if (header_size >= sizeof(header))
+ if (header_size >= sizeof(header)) // TODO: wouldn't this make more sense with > than >=? The first case in the following switch statement is unreachable as-is.
return false;
if (header_size > 0)
- io.read_at(0, header, header_size, actual);
+ {
+ auto const [err, actual] = read_at(io, 0, header, header_size);
+ if (err || (actual != header_size))
+ return false;
+ }
// default values
heads = 1;
@@ -241,8 +244,7 @@ bool jvc_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sectors[interleave[i]].bad_crc = false;
sectors[interleave[i]].data = &sector_data[sector_offset];
- size_t actual;
- io.read_at(file_offset, sectors[interleave[i]].data, sector_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, file_offset, sectors[interleave[i]].data, sector_size); // FIXME: check for errors and premature EOF
sector_offset += sector_size;
file_offset += sector_size;
@@ -268,8 +270,7 @@ bool jvc_format::save(util::random_read_write &io, const std::vector<uint32_t> &
uint8_t header[2];
header[0] = 18;
header[1] = 2;
- size_t actual;
- io.write_at(file_offset, header, sizeof(header), actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, header, sizeof(header)); // FIXME: check for errors
file_offset += sizeof(header);
}
@@ -289,8 +290,7 @@ bool jvc_format::save(util::random_read_write &io, const std::vector<uint32_t> &
return false;
}
- size_t actual;
- io.write_at(file_offset, sectors[1 + i].data(), 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, sectors[1 + i].data(), 256); // FIXME: check for errors
file_offset += 256;
}
}
diff --git a/src/lib/formats/kc_cas.cpp b/src/lib/formats/kc_cas.cpp
index 035d18fb4cd..34c52786b9c 100644
--- a/src/lib/formats/kc_cas.cpp
+++ b/src/lib/formats/kc_cas.cpp
@@ -232,7 +232,7 @@ static int kc_handle_sss(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int kc_kcc_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int kc_kcc_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return kc_handle_kcc(buffer, bytes);
}
@@ -243,7 +243,7 @@ static int kc_kcc_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
********************************************************************/
static int kc_kcc_to_wav_size(const uint8_t *casdata, int caslen)
{
- kc_image_size = caslen ;
+ kc_image_size = caslen;
return kc_handle_kcc( nullptr, casdata );
}
@@ -284,7 +284,7 @@ static const cassette_image::Format kc_kcc_format =
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int kc_tap_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int kc_tap_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return kc_handle_tap(buffer, bytes);
}
@@ -295,7 +295,7 @@ static int kc_tap_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
********************************************************************/
static int kc_tap_to_wav_size(const uint8_t *casdata, int caslen)
{
- kc_image_size = caslen ;
+ kc_image_size = caslen;
return kc_handle_tap( nullptr, casdata );
}
@@ -336,7 +336,7 @@ static const cassette_image::Format kc_tap_format =
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int kc_sss_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int kc_sss_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return kc_handle_sss(buffer, bytes);
}
@@ -347,7 +347,7 @@ static int kc_sss_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
********************************************************************/
static int kc_sss_to_wav_size(const uint8_t *casdata, int caslen)
{
- kc_image_size = caslen ;
+ kc_image_size = caslen;
return kc_handle_sss( nullptr, casdata );
}
diff --git a/src/lib/formats/kim1_cas.cpp b/src/lib/formats/kim1_cas.cpp
index 933e8cc3818..de2ee022632 100644
--- a/src/lib/formats/kim1_cas.cpp
+++ b/src/lib/formats/kim1_cas.cpp
@@ -145,7 +145,7 @@ static int kim1_handle_kim(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int kim1_kim_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int kim1_kim_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return kim1_handle_kim( buffer, bytes );
}
diff --git a/src/lib/formats/lviv_lvt.cpp b/src/lib/formats/lviv_lvt.cpp
index c2ffe37d9c9..e37508ab529 100644
--- a/src/lib/formats/lviv_lvt.cpp
+++ b/src/lib/formats/lviv_lvt.cpp
@@ -71,7 +71,7 @@ static int lviv_cassette_calculate_size_in_samples(const uint8_t *bytes, int len
/*************************************************************************************/
-static int lviv_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int lviv_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
int16_t * p = buffer;
diff --git a/src/lib/formats/lw30_dsk.cpp b/src/lib/formats/lw30_dsk.cpp
index dd5eef5da5f..dd1536755d5 100644
--- a/src/lib/formats/lw30_dsk.cpp
+++ b/src/lib/formats/lw30_dsk.cpp
@@ -138,9 +138,11 @@ static constexpr int raw_track_size = 2/*0xaa*/ + 48/*0xaa*/ + SECTORS_PER_TRACK
int lw30_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint64_t size = 0;
- io.length(size);
+ if(io.length(size))
+ return 0;
+
if(size == TRACKS_PER_DISK * SECTORS_PER_TRACK * SECTOR_SIZE)
- return 50; // identified by size
+ return FIFID_SIZE; // identified by size
return 0;
}
@@ -150,9 +152,8 @@ bool lw30_format::load(util::random_read &io, uint32_t form_factor, const std::v
uint8_t trackdata[SECTORS_PER_TRACK * SECTOR_SIZE], rawdata[CELLS_PER_REV / 8];
memset(rawdata, 0xaa, sizeof(rawdata));
for(int track = 0; track < TRACKS_PER_DISK; track++) {
- size_t actual{};
- io.read_at(track * SECTORS_PER_TRACK * SECTOR_SIZE, trackdata, SECTORS_PER_TRACK * SECTOR_SIZE, actual);
- if(actual != SECTORS_PER_TRACK * SECTOR_SIZE)
+ auto const [err, actual] = read_at(io, track * SECTORS_PER_TRACK * SECTOR_SIZE, trackdata, SECTORS_PER_TRACK * SECTOR_SIZE);
+ if(err || (actual != SECTORS_PER_TRACK * SECTOR_SIZE))
return false;
size_t i = 0;
for(int x = 0; x < 2 + 48; x++)
diff --git a/src/lib/formats/m20_dsk.cpp b/src/lib/formats/m20_dsk.cpp
index 10c6cf51cf1..02905ecfa0d 100644
--- a/src/lib/formats/m20_dsk.cpp
+++ b/src/lib/formats/m20_dsk.cpp
@@ -62,8 +62,7 @@ bool m20_format::load(util::random_read &io, uint32_t form_factor, const std::ve
bool mfm = track || head;
desc_pc_sector sects[16];
uint8_t sectdata[16*256];
- size_t actual;
- io.read_at(16*256*(track*2+head), sectdata, 16*256, actual);
+ /*auto const [err, actual] =*/ read_at(io, 16*256*(track*2+head), sectdata, 16*256); // FIXME: check for errors and premature EOF
for (int i = 0; i < 16; i++) {
int j = i/2 + (i & 1 ? 0 : 8);
sects[i].track = track;
@@ -92,17 +91,16 @@ bool m20_format::save(util::random_read_write &io, const std::vector<uint32_t> &
int track_count, head_count;
track_count = 35; head_count = 2; //FIXME: use image.get_actual_geometry(track_count, head_count) instead
- // initial fm track
+ // initial FM track
auto bitstream = generate_bitstream_from_track(0, 0, 4000, image);
auto sectors = extract_sectors_from_bitstream_fm_pc(bitstream);
for (int i = 0; i < 16; i++) {
- size_t actual;
- io.write_at(file_offset, sectors[i + 1].data(), 128, actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, sectors[i + 1].data(), 128); // FIXME: check for errors
file_offset += 256; //128;
}
- // rest are mfm tracks
+ // rest are MFM tracks
for (int track = 0; track < track_count; track++) {
for (int head = 0; head < head_count; head++) {
// skip track 0, head 0
@@ -115,8 +113,7 @@ bool m20_format::save(util::random_read_write &io, const std::vector<uint32_t> &
sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);
for (int i = 0; i < 16; i++) {
- size_t actual;
- io.write_at(file_offset, sectors[i + 1].data(), 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, sectors[i + 1].data(), 256); // FIXME: check for errors
file_offset += 256;
}
}
diff --git a/src/lib/formats/mbee_cas.cpp b/src/lib/formats/mbee_cas.cpp
index cd11f7bb041..f8c42602b2b 100644
--- a/src/lib/formats/mbee_cas.cpp
+++ b/src/lib/formats/mbee_cas.cpp
@@ -209,7 +209,7 @@ static int mbee_handle_tap(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int mbee_tap_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int mbee_tap_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return mbee_handle_tap(buffer, bytes);
}
diff --git a/src/lib/formats/mdos_dsk.cpp b/src/lib/formats/mdos_dsk.cpp
index 765ce1bc63c..a14df309db4 100644
--- a/src/lib/formats/mdos_dsk.cpp
+++ b/src/lib/formats/mdos_dsk.cpp
@@ -55,6 +55,8 @@
#include "ioprocs.h"
#include "multibyte.h"
+#include <tuple>
+
mdos_format::mdos_format() : wd177x_format(formats)
{
@@ -77,10 +79,10 @@ const char *mdos_format::extensions() const noexcept
int mdos_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- int type = find_size(io, form_factor, variants);
+ int const type = find_size(io, form_factor, variants);
if (type != -1)
- return FIFID_SIZE;
+ return FIFID_SIZE | FIFID_STRUCT;
return 0;
}
@@ -115,18 +117,22 @@ int mdos_format::parse_date_field(const uint8_t *str)
int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
+ std::error_condition err;
size_t actual;
+
uint64_t size;
if (io.length(size))
return -1;
+ // Look at the disk ID sector.
disk_id_sector info;
- // Look at the disk id sector.
- io.read_at(0, &info, sizeof(struct disk_id_sector), actual);
+ std::tie(err, actual) = read_at(io, 0, &info, sizeof(disk_id_sector));
+ if (err || (sizeof(disk_id_sector) != actual))
+ return -1;
LOG_FORMATS("MDOS floppy dsk: size %d bytes, %d total sectors, %d remaining bytes, expected form factor %x\n", (uint32_t)size, (uint32_t)size / 128, (uint32_t)size % 128, form_factor);
- // The 'unused' area is not necessarily zero filled and is ignoded
+ // The 'unused' area is not necessarily zero filled and is ignored
// in the identification of a MDOS format image.
// Expect an ASCII id, version, revision, and 'user name' strings.
@@ -146,9 +152,9 @@ int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const st
return -1;
// The date should be the numeric day, month and year.
- int month = parse_date_field(info.date);
- int day = parse_date_field(info.date + 2);
- int year = parse_date_field(info.date + 4);
+ int const month = parse_date_field(info.date);
+ int const day = parse_date_field(info.date + 2);
+ int const year = parse_date_field(info.date + 4);
LOG_FORMATS(" day %d, month %d, year %d\n", day, month, year);
if (day < 1 || day > 32 || month < 1 || month > 12 || year < 0)
@@ -182,8 +188,12 @@ int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const st
// the extent of the disk are free or available.
uint8_t cluster_allocation[128], cluster_available[128];
- io.read_at(1 * 128, &cluster_allocation, sizeof(cluster_allocation), actual);
- io.read_at(2 * 128, &cluster_available, sizeof(cluster_available), actual);
+ std::tie(err, actual) = read_at(io, 1 * 128, &cluster_allocation, sizeof(cluster_allocation));
+ if (err || (sizeof(cluster_allocation) != actual))
+ return -1;
+ std::tie(err, actual) = read_at(io, 2 * 128, &cluster_available, sizeof(cluster_available));
+ if (err || (sizeof(cluster_available) != actual))
+ return -1;
for (int cluster = 0; cluster < sizeof(cluster_allocation) * 8; cluster++) {
if (cluster * 4 * 128 + 4 * 128 > size) {
@@ -202,7 +212,7 @@ int mdos_format::find_size(util::random_read &io, uint32_t form_factor, const st
}
}
- for (int i=0; formats[i].form_factor; i++) {
+ for (int i = 0; formats[i].form_factor; i++) {
const format &f = formats[i];
LOG_FORMATS(" checking format %d with form factor %02x, %d sectors, %d heads\n",
i, f.form_factor, f.sector_count, f.head_count);
diff --git a/src/lib/formats/mfi_dsk.cpp b/src/lib/formats/mfi_dsk.cpp
index e6700f8f18f..eb1e632ec03 100644
--- a/src/lib/formats/mfi_dsk.cpp
+++ b/src/lib/formats/mfi_dsk.cpp
@@ -8,6 +8,7 @@
#include <cstring>
#include <functional>
+#include <tuple>
/*
@@ -41,8 +42,10 @@
- 2, MG_D -> Damaged zone, reads as neutral but cannot be changed by writing
- 3, MG_E -> End of zone
- Tracks data is aligned so that the index pulse is at the start,
- whether the disk is hard-sectored or not.
+ Tracks data is aligned so that the index pulse is at the start for soft-
+ sectored disks. For hard-sectored disks, the sector hole for the first
+ sector is at the start and the index hole is half a sector from the end
+ of the track.
The position is the angular position in units of 1/200,000,000th of
a turn. A size in such units, not coincidentally at all, is also
@@ -58,7 +61,9 @@
if you try to rewrite a physical disk with the data. Some
preservation formats encode that information, it is guessed for
others. The write track function of fdcs should set it. The
- representation is the angular position relative to the index.
+ representation is the angular position relative to the index, for
+ soft-sectored disks, and the first sector hole for hard-sectored
+ disks.
The media type is divided in two parts. The first half
indicate the physical form factor, i.e. all medias with that
@@ -99,38 +104,46 @@ bool mfi_format::supports_save() const noexcept
int mfi_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
header h;
+ auto const [err, actual] = read_at(io, 0, &h, sizeof(header));
+ if (err || (sizeof(header) != actual))
+ return 0;
- size_t actual;
- io.read_at(0, &h, sizeof(header), actual);
- if((memcmp( h.sign, sign, 16) == 0 || memcmp( h.sign, sign_old, 16) == 0) &&
+ if((!memcmp(h.sign, sign, 16) || !memcmp(h.sign, sign_old, 16)) &&
(h.cyl_count & CYLINDER_MASK) <= 84 &&
(h.cyl_count >> RESOLUTION_SHIFT) < 3 &&
h.head_count <= 2 &&
(!form_factor || !h.form_factor || h.form_factor == form_factor))
return FIFID_SIGN|FIFID_STRUCT;
+
return 0;
}
bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
+
header h;
- entry entries[84*2*4];
- io.read_at(0, &h, sizeof(header), actual);
- int resolution = h.cyl_count >> RESOLUTION_SHIFT;
+ std::tie(err, actual) = read_at(io, 0, &h, sizeof(header));
+ if(err || (sizeof(header) != actual))
+ return false;
+ int const resolution = h.cyl_count >> RESOLUTION_SHIFT;
h.cyl_count &= CYLINDER_MASK;
- io.read_at(sizeof(header), &entries, (h.cyl_count << resolution)*h.head_count*sizeof(entry), actual);
-
image.set_form_variant(h.form_factor, h.variant);
if(!h.cyl_count)
return true;
+ entry entries[84*2*4];
+ std::tie(err, actual) = read_at(io, sizeof(header), &entries, (h.cyl_count << resolution)*h.head_count*sizeof(entry));
+ if(err || (((h.cyl_count << resolution)*h.head_count*sizeof(entry)) != actual))
+ return false;
+
std::function<void (const std::vector<uint32_t> &src, std::vector<uint32_t> &track)> converter;
- if(!memcmp( h.sign, sign, 16)) {
- converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
+ if(!memcmp(h.sign, sign, 16)) {
+ converter = [] (const std::vector<uint32_t> &src, std::vector<uint32_t> &track) {
uint32_t ctime = 0;
for(uint32_t mg : src) {
ctime += mg & TIME_MASK;
@@ -139,7 +152,7 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
};
} else {
- converter = [](const std::vector<uint32_t> &src, std::vector<uint32_t> &track) -> void {
+ converter = [] (const std::vector<uint32_t> &src, std::vector<uint32_t> &track) {
unsigned int cell_count = src.size();
uint32_t mg = src[0] & MG_MASK;
uint32_t wmg = src[cell_count - 1] & MG_MASK;
@@ -184,7 +197,7 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
compressed.resize(ent->compressed_size);
uncompressed.resize(cell_count);
- io.read_at(ent->offset, &compressed[0], ent->compressed_size, actual);
+ std::tie(err, actual) = read_at(io, ent->offset, &compressed[0], ent->compressed_size); // FIXME: check for errors and premature EOF
uLongf size = ent->uncompressed_size;
if(uncompress((Bytef *)uncompressed.data(), &size, &compressed[0], ent->compressed_size) != Z_OK) {
@@ -204,7 +217,6 @@ bool mfi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
- size_t actual;
int tracks, heads;
image.get_actual_geometry(tracks, heads);
int resolution = image.get_resolution();
@@ -224,7 +236,7 @@ bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
h.form_factor = image.get_form_factor();
h.variant = image.get_variant();
- io.write_at(0, &h, sizeof(header), actual);
+ write_at(io, 0, &h, sizeof(header)); // FIXME: check for errors
memset(entries, 0, sizeof(entries));
@@ -258,11 +270,11 @@ bool mfi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
entries[epos].write_splice = image.get_write_splice_position(track >> 2, head, track & 3);
epos++;
- io.write_at(pos, postcomp.get(), csize, actual);
+ write_at(io, pos, postcomp.get(), csize); // FIXME: check for errors
pos += csize;
}
- io.write_at(sizeof(header), entries, (tracks << resolution)*heads*sizeof(entry), actual);
+ write_at(io, sizeof(header), entries, (tracks << resolution)*heads*sizeof(entry)); // FIXME: check for errors
return true;
}
diff --git a/src/lib/formats/mfi_dsk.h b/src/lib/formats/mfi_dsk.h
index 89201c6db8a..7241bcfab32 100644
--- a/src/lib/formats/mfi_dsk.h
+++ b/src/lib/formats/mfi_dsk.h
@@ -45,13 +45,13 @@ private:
static const char sign[16];
struct header {
- char sign[16];
- unsigned int cyl_count, head_count;
- unsigned int form_factor, variant;
+ uint8_t sign[16];
+ uint32_t cyl_count, head_count;
+ uint32_t form_factor, variant;
};
struct entry {
- unsigned int offset, compressed_size, uncompressed_size, write_splice;
+ uint32_t offset, compressed_size, uncompressed_size, write_splice;
};
};
diff --git a/src/lib/formats/mz_cas.cpp b/src/lib/formats/mz_cas.cpp
index 6bc82a43bd1..ddc35b62663 100644
--- a/src/lib/formats/mz_cas.cpp
+++ b/src/lib/formats/mz_cas.cpp
@@ -69,7 +69,7 @@ static int fill_wave_b(int16_t *buffer, int offs, int byte)
return count;
}
-static int fill_wave(int16_t *buffer, int length, uint8_t *code)
+static int fill_wave(int16_t *buffer, int length, const uint8_t *code, int)
{
static int16_t *beg;
static uint16_t csum = 0;
diff --git a/src/lib/formats/nabupc_dsk.cpp b/src/lib/formats/nabupc_dsk.cpp
index 79d67a5e25f..00205c1e560 100644
--- a/src/lib/formats/nabupc_dsk.cpp
+++ b/src/lib/formats/nabupc_dsk.cpp
@@ -18,6 +18,7 @@
#include "ioprocs.h"
#include "strformat.h"
+
const nabupc_format::format nabupc_format::formats[] =
{
{ // 200k 40 track single sided double density (nabu)
@@ -167,8 +168,7 @@ bool nabupc_format::load(util::random_read &io, uint32_t form_factor, const std:
for (int head = 0; head < f.head_count; head++) {
desc_pc_sector sects[sector_count];
uint8_t sectdata[sector_count * sector_size];
- size_t actual;
- io.read_at((track * f.head_count + head) * sector_count * sector_size, sectdata, sector_count * sector_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track * f.head_count + head) * sector_count * sector_size, sectdata, sector_count * sector_size); // FIXME: check for errors and premature EOF
for (int i = 0; i < sector_count; i++) {
sects[i].track = track;
sects[i].head = head;
@@ -196,8 +196,7 @@ bool nabupc_format::save(util::random_read_write &io, const std::vector<uint32_t
auto bitstream = generate_bitstream_from_track(track, head, 2000, image);
auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);
for (int i = 0; i < sector_count; i++) {
- size_t actual;
- io.write_at(file_offset, sectors[i + 1].data(), sector_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, file_offset, sectors[i + 1].data(), sector_size); // FIXME: check for errors
file_offset += sector_size;
}
}
diff --git a/src/lib/formats/nfd_dsk.cpp b/src/lib/formats/nfd_dsk.cpp
index 773b35d8aef..a51b461e144 100644
--- a/src/lib/formats/nfd_dsk.cpp
+++ b/src/lib/formats/nfd_dsk.cpp
@@ -108,10 +108,11 @@ const char *nfd_format::extensions() const noexcept
int nfd_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[16];
- size_t actual;
- io.read_at(0, h, 16, actual);
+ auto const [err, actual] = read_at(io, 0, h, 16); // TODO: does it really need 16 bytes? it only looks at 14.
+ if (err || (16 != actual))
+ return 0;
- if (strncmp((const char *)h, "T98FDDIMAGE.R0", 14) == 0 || strncmp((const char *)h, "T98FDDIMAGE.R1", 14) == 0)
+ if (!memcmp(h, "T98FDDIMAGE.R0", 14) || !memcmp(h, "T98FDDIMAGE.R1", 14))
return FIFID_SIGN;
return 0;
@@ -119,13 +120,12 @@ int nfd_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint64_t size;
if (io.length(size))
return false;
uint8_t h[0x120], hsec[0x10];
- io.read_at(0, h, 0x120, actual);
- int format_version = !strncmp((const char *)h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
+ read_at(io, 0, h, 0x120); // FIXME: check for errors and premature EOF
+ int format_version = !memcmp(h, "T98FDDIMAGE.R0", 14) ? 0 : 1;
// sector map (the 164th entry is only used by rev.1 format, loops with track < 163 are correct for rev.0)
uint8_t disk_type = 0;
@@ -149,7 +149,7 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
{
int curr_track_size = 0;
// read sector map absolute location
- io.read_at(pos, hsec, 4, actual);
+ read_at(io, pos, hsec, 4); // FIXME: check for errors and premature EOF
pos += 4;
uint32_t secmap_addr = little_endianize_int32(*(uint32_t *)(hsec));
@@ -158,14 +158,14 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
// read actual sector map for the sectors of this track
// for rev.1 format the first 0x10 are a track summary:
// first WORD is # of sectors, second WORD is # of special data sectors
- io.read_at(secmap_addr, hsec, 0x10, actual);
+ read_at(io, secmap_addr, hsec, 0x10); // FIXME: check for errors and premature EOF
secmap_addr += 0x10;
num_secs[track] = little_endianize_int16(*(uint16_t *)(hsec));
num_specials[track] = little_endianize_int16(*(uint16_t *)(hsec + 0x2));
for (int sect = 0; sect < num_secs[track]; sect++)
{
- io.read_at(secmap_addr, hsec, 0x10, actual);
+ read_at(io, secmap_addr, hsec, 0x10); // FIXME: check for errors and premature EOF
if (track == 0 && sect == 0)
disk_type = hsec[0xb]; // can this change across the disk? I don't think so...
@@ -184,7 +184,7 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
{
for (int sect = 0; sect < num_specials[track]; sect++)
{
- io.read_at(secmap_addr, hsec, 0x10, actual);
+ read_at(io, secmap_addr, hsec, 0x10); // FIXME: check for errors and premature EOF
secmap_addr += 0x10;
curr_track_size += (hsec[9] + 1) * little_endianize_int32(*(uint32_t *)(hsec + 0x0a));
}
@@ -207,7 +207,7 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
{
// read sector map for this sector
// for rev.0 format each sector uses 0x10 bytes
- io.read_at(pos, hsec, 0x10, actual);
+ read_at(io, pos, hsec, 0x10); // FIXME: check for errors and premature EOF
if (track == 0 && sect == 0)
disk_type = hsec[0xa]; // can this change across the disk? I don't think so...
@@ -254,7 +254,7 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for (int track = 0; track < 163 && pos < size; track++)
{
- io.read_at(pos, sect_data, track_sizes[track], actual);
+ read_at(io, pos, sect_data, track_sizes[track]); // FIXME: check for errors and premature EOF
for (int i = 0; i < num_secs[track]; i++)
{
@@ -277,7 +277,7 @@ bool nfd_format::load(util::random_read &io, uint32_t form_factor, const std::ve
if (mfm[track * 26])
build_pc_track_mfm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
else
- build_pc_track_fm(track / 2, track % 2, image, cell_count, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
+ build_pc_track_fm(track / 2, track % 2, image, cell_count / 2, num_secs[track], sects, calc_default_pc_gap3_size(form_factor, (128 << sec_sizes[track * 26])));
}
return true;
diff --git a/src/lib/formats/orao_cas.cpp b/src/lib/formats/orao_cas.cpp
index a580fdef077..8cc77e3bf6f 100644
--- a/src/lib/formats/orao_cas.cpp
+++ b/src/lib/formats/orao_cas.cpp
@@ -62,7 +62,7 @@ static int orao_cas_to_wav_size( const uint8_t *casdata, int caslen ) {
return size;
}
-static int orao_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int orao_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i,j,size,k;
uint8_t b;
size = 0;
diff --git a/src/lib/formats/oric_dsk.cpp b/src/lib/formats/oric_dsk.cpp
index f4d9b78faa9..15bb5ce1455 100644
--- a/src/lib/formats/oric_dsk.cpp
+++ b/src/lib/formats/oric_dsk.cpp
@@ -12,6 +12,7 @@
#include "ioprocs.h"
#include "multibyte.h"
+#include "osdcore.h"
#include <cstring>
@@ -39,8 +40,7 @@ bool oric_dsk_format::supports_save() const noexcept
int oric_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[256];
- size_t actual;
- io.read_at(0, h, 256, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, h, 256); // FIXME: check for errors and premature EOF
if(memcmp(h, "MFM_DISK", 8))
return 0;
@@ -60,19 +60,29 @@ int oric_dsk_format::identify(util::random_read &io, uint32_t form_factor, const
bool oric_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint8_t h[256];
uint8_t t[6250+3];
t[6250] = t[6251] = t[6252] = 0;
- io.read_at(0, h, 256, actual);
+ read_at(io, 0, h, 256); // FIXME: check for errors and premature EOF
int sides = get_u32le(&h[ 8]);
int tracks = get_u32le(&h[12]);
+ int max_tracks, max_sides;
+ image.get_maximal_geometry(max_tracks, max_sides);
+ if (tracks > max_tracks) {
+ osd_printf_error("oric_dsk: Floppy disk has too many tracks for this drive (floppy tracks=%d, drive tracks=%d).\n", tracks, max_tracks);
+ return false;
+ }
+ if (sides > max_sides) {
+ osd_printf_warning("oric_dsk: Floppy disk has excess of heads for this drive that will be discarded (floppy heads=%d, drive heads=%d).\n", sides, max_sides);
+ sides = max_sides;
+ }
+
for(int side=0; side<sides; side++)
for(int track=0; track<tracks; track++) {
- io.read_at(256+6400*(tracks*side + track), t, 6250, actual);
+ read_at(io, 256+6400*(tracks*side + track), t, 6250); // FIXME: check for errors and premature EOF
std::vector<uint32_t> stream;
int sector_size = 128;
for(int i=0; i<6250; i++) {
@@ -157,9 +167,9 @@ bool oric_jasmin_format::load(util::random_read &io, uint32_t form_factor, const
int const heads = size == 41*17*256 ? 1 : 2;
- std::vector<uint8_t> data(size);
- size_t actual;
- io.read_at(0, data.data(), size, actual);
+ auto const [err, data, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
for(int head = 0; head != heads; head++)
for(int track = 0; track != 41; track++) {
@@ -171,7 +181,7 @@ bool oric_jasmin_format::load(util::random_read &io, uint32_t form_factor, const
sdesc[s].sector = sector + 1;
sdesc[s].size = 1;
sdesc[s].actual_size = 256;
- sdesc[s].data = data.data() + 256 * (sector + track*17 + head*17*41);
+ sdesc[s].data = &data[256 * (sector + track*17 + head*17*41)];
sdesc[s].deleted = false;
sdesc[s].bad_crc = false;
}
@@ -203,8 +213,7 @@ bool oric_jasmin_format::save(util::random_read_write &io, const std::vector<uin
auto sectors = extract_sectors_from_bitstream_mfm_pc(generate_bitstream_from_track(track, head, 2000, image));
for(unsigned int sector = 0; sector != 17; sector ++) {
uint8_t const *const data = (sector+1 < sectors.size() && !sectors[sector+1].empty()) ? sectors[sector+1].data() : zero;
- size_t actual;
- io.write_at(256 * (sector + track*17 + head*17*41), data, 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, 256 * (sector + track*17 + head*17*41), data, 256); // FIXME: check for errors
}
}
return true;
diff --git a/src/lib/formats/oric_tap.cpp b/src/lib/formats/oric_tap.cpp
index 7f900808f21..a8b11a5ee7a 100644
--- a/src/lib/formats/oric_tap.cpp
+++ b/src/lib/formats/oric_tap.cpp
@@ -345,139 +345,135 @@ static int oric_cassette_calculate_size_in_samples(const uint8_t *bytes, int len
}
/* length is length of sample buffer to fill! */
-static int oric_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int oric_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
unsigned char header[9];
- uint8_t *data_ptr;
- int16_t *p;
- int i;
- uint8_t data;
-
- p = buffer;
-
+ int16_t *p = buffer;
/* header and trailer act as pauses */
/* the trailer is required so that the via sees the last bit of the last
byte */
- if (bytes == CODE_HEADER) {
- for (i = 0; i < ORIC_WAVESAMPLES_HEADER; i++)
+ if (bytes == CODE_HEADER)
+ {
+ for (int i = 0; i < ORIC_WAVESAMPLES_HEADER; i++)
*(p++) = WAVEENTRY_NULL;
}
- else if (bytes == CODE_TRAILER) {
- for (i = 0; i < ORIC_WAVESAMPLES_TRAILER; i++)
+ else if (bytes == CODE_TRAILER)
+ {
+ for (int i = 0; i < ORIC_WAVESAMPLES_TRAILER; i++)
*(p++) = WAVEENTRY_NULL;
}
else
-{
- /* the length is the number of samples left in the buffer and NOT the number of bytes for the input file */
- length = length - ORIC_WAVESAMPLES_TRAILER;
-
- oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
- data_ptr = bytes;
-
- while ((data_ptr<(bytes + oric.tap_size)) && (p < (buffer+length)) )
{
- data = data_ptr[0];
- data_ptr++;
+ /* the length is the number of samples left in the buffer and NOT the number of bytes for the input file */
+ length = length - ORIC_WAVESAMPLES_TRAILER;
- switch (oric.cassette_state)
+ oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
+ const uint8_t *data_ptr = bytes;
+
+ while ((data_ptr < (bytes + oric.tap_size)) && (p < (buffer+length)) )
{
- case ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE:
- {
- if (data==ORIC_SYNC_BYTE)
- {
- LOG_FORMATS("found sync byte!\n");
- /* found first sync byte */
- oric.cassette_state = ORIC_CASSETTE_GOT_SYNC_BYTE;
- }
- }
- break;
+ const uint8_t data = data_ptr[0];
+ data_ptr++;
- case ORIC_CASSETTE_GOT_SYNC_BYTE:
+ switch (oric.cassette_state)
{
- if (data!=ORIC_SYNC_BYTE)
+ case ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE:
{
- /* 0.25 second pause */
- p = oric_fill_pause(p, oric_seconds_to_samples(0.25));
-
- LOG_FORMATS("found end of sync bytes!\n");
- /* found end of sync bytes */
- for (i=0; i<ORIC_LEADER_LENGTH; i++)
+ if (data == ORIC_SYNC_BYTE)
{
- p = oric_output_byte(p,0x016);
+ LOG_FORMATS("found sync byte!\n");
+ /* found first sync byte */
+ oric.cassette_state = ORIC_CASSETTE_GOT_SYNC_BYTE;
}
+ }
+ break;
- if (data==0x024)
+ case ORIC_CASSETTE_GOT_SYNC_BYTE:
+ {
+ if (data != ORIC_SYNC_BYTE)
{
- //LOG_FORMATS("reading header!\n");
- p = oric_output_byte(p,data);
- oric.cassette_state = ORIC_CASSETTE_READ_HEADER;
- oric.data_count = 0;
- oric.data_length = 9;
+ /* 0.25 second pause */
+ p = oric_fill_pause(p, oric_seconds_to_samples(0.25));
+
+ LOG_FORMATS("found end of sync bytes!\n");
+ /* found end of sync bytes */
+ for (int i = 0; i < ORIC_LEADER_LENGTH; i++)
+ {
+ p = oric_output_byte(p,0x016);
+ }
+
+ if (data == 0x024)
+ {
+ //LOG_FORMATS("reading header!\n");
+ p = oric_output_byte(p, data);
+ oric.cassette_state = ORIC_CASSETTE_READ_HEADER;
+ oric.data_count = 0;
+ oric.data_length = 9;
+ }
}
}
- }
- break;
-
- case ORIC_CASSETTE_READ_HEADER:
- {
- header[oric.data_count] = data;
- p = oric_output_byte(p, data);
- oric.data_count++;
+ break;
- if (oric.data_count==oric.data_length)
+ case ORIC_CASSETTE_READ_HEADER:
{
- //LOG_FORMATS("finished reading header!\n");
- oric.cassette_state = ORIC_CASSETTE_READ_FILENAME;
- }
- }
- break;
+ header[oric.data_count] = data;
+ p = oric_output_byte(p, data);
+ oric.data_count++;
- case ORIC_CASSETTE_READ_FILENAME:
- {
- p = oric_output_byte(p, data);
+ if (oric.data_count==oric.data_length)
+ {
+ //LOG_FORMATS("finished reading header!\n");
+ oric.cassette_state = ORIC_CASSETTE_READ_FILENAME;
+ }
+ }
+ break;
- /* got end of filename? */
- if (data==0)
+ case ORIC_CASSETTE_READ_FILENAME:
{
- uint16_t end, start;
- LOG_FORMATS("got end of filename\n");
+ p = oric_output_byte(p, data);
- /* oric includes a small delay, but I don't see
- it being 1 bits */
- for (i=0; i<100; i++)
+ /* got end of filename? */
+ if (data == 0)
{
- p = oric_output_bit(p,1);
- }
+ uint16_t end, start;
+ LOG_FORMATS("got end of filename\n");
- oric.cassette_state = ORIC_CASSETTE_WRITE_DATA;
- oric.data_count = 0;
+ /* oric includes a small delay, but I don't see
+ it being 1 bits */
+ for (int i = 0; i < 100; i++)
+ {
+ p = oric_output_bit(p,1);
+ }
- end = get_u16be(&header[4]);
- start = get_u16be(&header[6]);
- LOG(("start (from header): %02x\n",start));
- LOG(("end (from header): %02x\n",end));
- oric.data_length = end - start + 1;
- }
- }
- break;
+ oric.cassette_state = ORIC_CASSETTE_WRITE_DATA;
+ oric.data_count = 0;
- case ORIC_CASSETTE_WRITE_DATA:
- {
- p = oric_output_byte(p, data);
- oric.data_count++;
+ end = get_u16be(&header[4]);
+ start = get_u16be(&header[6]);
+ LOG(("start (from header): %02x\n",start));
+ LOG(("end (from header): %02x\n",end));
+ oric.data_length = end - start + 1;
+ }
+ }
+ break;
- if (oric.data_count==oric.data_length)
+ case ORIC_CASSETTE_WRITE_DATA:
{
- LOG_FORMATS("finished writing data!\n");
- oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
+ p = oric_output_byte(p, data);
+ oric.data_count++;
+
+ if (oric.data_count==oric.data_length)
+ {
+ LOG_FORMATS("finished writing data!\n");
+ oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
+ }
}
- }
- break;
+ break;
+ }
}
}
-}
return p - buffer;
}
diff --git a/src/lib/formats/os9_dsk.cpp b/src/lib/formats/os9_dsk.cpp
index f74cd7fb3a6..ca79ced2145 100644
--- a/src/lib/formats/os9_dsk.cpp
+++ b/src/lib/formats/os9_dsk.cpp
@@ -88,8 +88,7 @@ int os9_format::find_size(util::random_read &io, uint32_t form_factor, const std
return -1;
uint8_t os9_header[0x60];
- size_t actual;
- io.read_at(0, os9_header, sizeof(os9_header), actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, os9_header, sizeof(os9_header)); // FIXME: check for errors and premature EOF
int os9_total_sectors = get_u24be(&os9_header[0x00]);
int os9_heads = util::BIT(os9_header[0x10], 0) ? 2 : 1;
diff --git a/src/lib/formats/p6001_cas.cpp b/src/lib/formats/p6001_cas.cpp
index c4689eb9be4..cdb0b922680 100644
--- a/src/lib/formats/p6001_cas.cpp
+++ b/src/lib/formats/p6001_cas.cpp
@@ -53,7 +53,7 @@ static int pc6001_cas_to_wav_size (const uint8_t *casdata, int caslen)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int pc6001_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int pc6001_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return pc6001_handle_cas(buffer,bytes);
}
diff --git a/src/lib/formats/pasti_dsk.cpp b/src/lib/formats/pasti_dsk.cpp
index 1390072b97c..ae82ee7939b 100644
--- a/src/lib/formats/pasti_dsk.cpp
+++ b/src/lib/formats/pasti_dsk.cpp
@@ -45,11 +45,10 @@ bool pasti_format::supports_save() const noexcept
int pasti_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
uint8_t h[16];
- size_t actual;
- io.read_at(0, h, 16, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, h, 16); // FIXME: check for errors and premature EOF
if(!memcmp(h, "RSY\0\3\0", 6) &&
- (1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164)))
+ (1 || (h[10] >= 80 && h[10] <= 82) || (h[10] >= 160 && h[10] <= 164))) // TODO: why is this check disabled?
return FIFID_SIGN;
return 0;
@@ -67,9 +66,8 @@ static void hexdump(const uint8_t *d, int s)
bool pasti_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint8_t fh[16];
- io.read_at(0, fh, 16, actual);
+ read_at(io, 0, fh, 16); // FIXME: check for errors and premature EOF
std::vector<uint8_t> raw_track;
@@ -84,7 +82,7 @@ bool pasti_format::load(util::random_read &io, uint32_t form_factor, const std::
for(int track=0; track < tracks; track++) {
for(int head=0; head < heads; head++) {
uint8_t th[16];
- io.read_at(pos, th, 16, actual);
+ read_at(io, pos, th, 16); // FIXME: check for errors and premature EOF
int entry_len = get_u32le(&th[0]);
int fuzz_len = get_u32le(&th[4]);
int sect = get_u16le(&th[8]);
@@ -95,7 +93,7 @@ bool pasti_format::load(util::random_read &io, uint32_t form_factor, const std::
raw_track.resize(entry_len-16);
- io.read_at(pos+16, &raw_track[0], entry_len-16, actual);
+ read_at(io, pos+16, &raw_track[0], entry_len-16); // FIXME: check for errors and premature EOF
uint8_t *fuzz = fuzz_len ? &raw_track[16*sect] : nullptr;
uint8_t *bdata = fuzz ? fuzz+fuzz_len : &raw_track[16*sect];
diff --git a/src/lib/formats/pc98_dsk.cpp b/src/lib/formats/pc98_dsk.cpp
index 534a5216450..36dac83e2af 100644
--- a/src/lib/formats/pc98_dsk.cpp
+++ b/src/lib/formats/pc98_dsk.cpp
@@ -83,6 +83,10 @@ const pc98_format::format pc98_format::formats[] = {
floppy_image::FF_525, floppy_image::DSHD, floppy_image::MFM,
1200, 8, 77, 2, 1024, {}, 1, {}, 80, 50, 22, 84
},
+ { /* 1MB 5 1/4 inch 256bps n88 basic disk type */
+ floppy_image::FF_525, floppy_image::DSHD, floppy_image::MFM,
+ 1200, 26, 77, 2, 256, {}, 1, {}, 80, 50, 21, 77
+ },
{}
};
diff --git a/src/lib/formats/pc98fdi_dsk.cpp b/src/lib/formats/pc98fdi_dsk.cpp
index b331ad8b521..10822ab316d 100644
--- a/src/lib/formats/pc98fdi_dsk.cpp
+++ b/src/lib/formats/pc98fdi_dsk.cpp
@@ -11,8 +11,9 @@
#include "pc98fdi_dsk.h"
#include "ioprocs.h"
+#include "multibyte.h"
-#include "osdcomm.h" // little_endianize_int32
+#include <tuple>
pc98fdi_format::pc98fdi_format()
@@ -41,15 +42,16 @@ int pc98fdi_format::identify(util::random_read &io, uint32_t form_factor, const
return 0;
uint8_t h[32];
- size_t actual;
- io.read_at(0, h, 32, actual);
-
- uint32_t const hsize = little_endianize_int32(*(uint32_t *) (h + 0x8));
- uint32_t const psize = little_endianize_int32(*(uint32_t *) (h + 0xc));
- uint32_t const ssize = little_endianize_int32(*(uint32_t *) (h + 0x10));
- uint32_t const scnt = little_endianize_int32(*(uint32_t *) (h + 0x14));
- uint32_t const sides = little_endianize_int32(*(uint32_t *) (h + 0x18));
- uint32_t const ntrk = little_endianize_int32(*(uint32_t *) (h + 0x1c));
+ auto const [err, actual] = read_at(io, 0, h, 32);
+ if(err || (32 != actual))
+ return 0;
+
+ uint32_t const hsize = get_u32le(h + 0x8);
+ uint32_t const psize = get_u32le(h + 0xc);
+ uint32_t const ssize = get_u32le(h + 0x10);
+ uint32_t const scnt = get_u32le(h + 0x14);
+ uint32_t const sides = get_u32le(h + 0x18);
+ uint32_t const ntrk = get_u32le(h + 0x1c);
if(size == hsize + psize && psize == ssize*scnt*sides*ntrk)
return FIFID_STRUCT;
@@ -58,16 +60,19 @@ int pc98fdi_format::identify(util::random_read &io, uint32_t form_factor, const
bool pc98fdi_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
uint8_t h[32];
- io.read_at(0, h, 32, actual);
+ std::tie(err, actual) = read_at(io, 0, h, 32);
+ if(err || (32 != actual))
+ return false;
- uint32_t const hsize = little_endianize_int32(*(uint32_t *)(h+0x8));
- uint32_t const sector_size = little_endianize_int32(*(uint32_t *)(h+0x10));
- uint32_t const sector_count = little_endianize_int32(*(uint32_t *)(h+0x14));
- uint32_t const head_count = little_endianize_int32(*(uint32_t *)(h+0x18));
- uint32_t const track_count = little_endianize_int32(*(uint32_t *)(h+0x1c));
+ uint32_t const hsize = get_u32le(h + 0x8);
+ uint32_t const sector_size = get_u32le(h + 0x10);
+ uint32_t const sector_count = get_u32le(h + 0x14);
+ uint32_t const head_count = get_u32le(h + 0x18);
+ uint32_t const track_count = get_u32le(h + 0x1c);
int const cell_count = form_factor == floppy_image::FF_35 ? 200000 : 166666;
@@ -78,9 +83,9 @@ bool pc98fdi_format::load(util::random_read &io, uint32_t form_factor, const std
desc_pc_sector sects[256];
uint8_t sect_data[65536];
- for(int track=0; track < track_count; track++)
+ for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- io.read_at(hsize + sector_size*sector_count*(track*head_count + head), sect_data, sector_size*sector_count, actual);
+ std::tie(err, actual) = read_at(io, hsize + sector_size*sector_count*(track*head_count + head), sect_data, sector_size*sector_count); // FIXME: check for errors and premature EOF
for(int i=0; i<sector_count; i++) {
sects[i].track = track;
@@ -95,6 +100,7 @@ bool pc98fdi_format::load(util::random_read &io, uint32_t form_factor, const std
build_pc_track_mfm(track, head, image, cell_count, sector_count, sects, calc_default_pc_gap3_size(form_factor, sector_size));
}
+ }
return true;
}
diff --git a/src/lib/formats/phc25_cas.cpp b/src/lib/formats/phc25_cas.cpp
index 8294df07628..e6dab7e88e1 100644
--- a/src/lib/formats/phc25_cas.cpp
+++ b/src/lib/formats/phc25_cas.cpp
@@ -129,7 +129,7 @@ static int phc25_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int phc25_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int phc25_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return phc25_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/pmd_cas.cpp b/src/lib/formats/pmd_cas.cpp
index ef4cef7c00a..224a3b0af5b 100644
--- a/src/lib/formats/pmd_cas.cpp
+++ b/src/lib/formats/pmd_cas.cpp
@@ -168,7 +168,7 @@ static int pmd85_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int pmd85_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int pmd85_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return pmd85_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/poly_dsk.cpp b/src/lib/formats/poly_dsk.cpp
index 4a264e293a1..8b8f48780f8 100644
--- a/src/lib/formats/poly_dsk.cpp
+++ b/src/lib/formats/poly_dsk.cpp
@@ -50,9 +50,8 @@ int poly_cpm_format::identify(util::random_read &io, uint32_t form_factor, const
{
// check for Poly CP/M boot sector
uint8_t boot[16];
- size_t actual;
- io.read_at(0, boot, 16, actual);
- if (memcmp(boot, "\x86\xc3\xb7\x00\x00\x8e\x10\xc0\xbf\x00\x01\xbf\xe0\x60\x00\x00", 16) == 0)
+ auto const [err, actual] = read_at(io, 0, boot, 16);
+ if (!err && (16 == actual) && !memcmp(boot, "\x86\xc3\xb7\x00\x00\x8e\x10\xc0\xbf\x00\x01\xbf\xe0\x60\x00\x00", 16))
{
return FIFID_SIZE|FIFID_SIGN;
}
@@ -114,8 +113,7 @@ bool poly_cpm_format::load(util::random_read &io, uint32_t form_factor, const st
sects[i].deleted = false;
sects[i].bad_crc = false;
sects[i].data = &sect_data[sdatapos];
- size_t actual;
- io.read(sects[i].data, bps, actual);
+ /*auto const [err, actual] =*/ read(io, sects[i].data, bps); // FIXME: check for errors and premature EOF
sdatapos += bps;
}
// gap sizes unverified
diff --git a/src/lib/formats/primoptp.cpp b/src/lib/formats/primoptp.cpp
index ccadcb6d70d..81eaf65b65a 100644
--- a/src/lib/formats/primoptp.cpp
+++ b/src/lib/formats/primoptp.cpp
@@ -138,12 +138,12 @@ static int primo_cassette_calculate_size_in_samples(const uint8_t *bytes, int le
return size_in_samples;
}
-static int primo_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int primo_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
int i = 0, j = 0, k;
int16_t *p = buffer;
- uint8_t *b = bytes;
+ const uint8_t *b = bytes;
uint32_t file_size = 0;
uint16_t block_size = 0;
diff --git a/src/lib/formats/rk_cas.cpp b/src/lib/formats/rk_cas.cpp
index 4747ccd50ed..25bbb79eea3 100644
--- a/src/lib/formats/rk_cas.cpp
+++ b/src/lib/formats/rk_cas.cpp
@@ -77,7 +77,7 @@ static int gam_cas_to_wav_size( const uint8_t *casdata, int caslen ) {
return (RK_HEADER_LEN * 8 * 2 + caslen * 8 * 2) * RK_SIZE_20;
}
-static int rk20_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int rk20_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i;
int16_t * p = buffer;
@@ -93,7 +93,7 @@ static int rk20_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
return p - buffer;
}
-static int rk22_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int rk22_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i;
int16_t * p = buffer;
@@ -109,7 +109,7 @@ static int rk22_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
return p - buffer;
}
-static int rk60_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int rk60_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i;
int16_t * p = buffer;
@@ -125,7 +125,7 @@ static int rk60_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
return p - buffer;
}
-static int gam_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) {
+static int gam_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int ) {
int i;
int16_t * p = buffer;
diff --git a/src/lib/formats/rx50_dsk.cpp b/src/lib/formats/rx50_dsk.cpp
index cefc2725209..853caf0dbc1 100644
--- a/src/lib/formats/rx50_dsk.cpp
+++ b/src/lib/formats/rx50_dsk.cpp
@@ -139,7 +139,7 @@ int rx50img_format::identify(util::random_read &io, uint32_t form_factor, const
return 0;
}
- // /* Sectors are numbered 1 to 10 */
+// Sectors are numbered 1 to 10
bool rx50img_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
uint8_t track_count, head_count, sector_count;
@@ -158,8 +158,7 @@ bool rx50img_format::load(util::random_read &io, uint32_t form_factor, const std
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- size_t actual;
- io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(rx50_10_desc, track, head, sectors, sector_count, 102064, image); // 98480
}
}
@@ -205,8 +204,7 @@ bool rx50img_format::save(util::random_read_write &io, const std::vector<uint32_
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- size_t actual;
- io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors
}
}
return true;
diff --git a/src/lib/formats/sap_dsk.cpp b/src/lib/formats/sap_dsk.cpp
new file mode 100644
index 00000000000..ef51cb8b772
--- /dev/null
+++ b/src/lib/formats/sap_dsk.cpp
@@ -0,0 +1,169 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#include "sap_dsk.h"
+
+#include "ioprocs.h"
+#include "multibyte.h"
+
+static constexpr unsigned HEADER_LENGTH = 66;
+static constexpr uint8_t MAGIC_XOR = 0xb3;
+
+const sap_dsk_format FLOPPY_SAP_FORMAT;
+
+inline uint16_t sap_dsk_format::accumulate_crc(uint16_t crc, uint8_t data) noexcept
+{
+ // Almost CRC16-CCITT, but not quite...
+ for (int shift : {0, 4})
+ crc = ((crc >> 4) & 0xfff) ^ 0x1081 * ((crc ^ (data >> shift)) & 0xf);
+ return crc;
+}
+
+const char *sap_dsk_format::name() const noexcept
+{
+ return "sap";
+}
+
+const char *sap_dsk_format::description() const noexcept
+{
+ return "Thomson SAP disk image (Systeme d'Archivage Pukall)";
+}
+
+const char *sap_dsk_format::extensions() const noexcept
+{
+ return "sap";
+}
+
+bool sap_dsk_format::supports_save() const noexcept
+{
+ return false;
+}
+
+int sap_dsk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
+{
+ uint8_t buffer[HEADER_LENGTH];
+ auto [err, actual] = read_at(io, 0, buffer, HEADER_LENGTH);
+ if (err || actual != HEADER_LENGTH)
+ return 0;
+
+ // Check ID string
+ if (memcmp(&buffer[1], "SYSTEME D'ARCHIVAGE PUKALL S.A.P. (c) Alexandre PUKALL Avril 1998", HEADER_LENGTH - 1) != 0)
+ return 0;
+
+ // Check disk format
+ if (form_factor == floppy_image::FF_35)
+ {
+ // 3.5" disks must have 80 double-density tracks
+ if ((buffer[0] & 0x7f) != 0x01)
+ return 0;
+ }
+ else if (form_factor == floppy_image::FF_525)
+ {
+ // 5.25" disks must have 40 tracks
+ if ((buffer[0] & 0x7e) != 0x02)
+ return 0;
+ }
+ else if (form_factor != floppy_image::FF_UNKNOWN)
+ return 0;
+
+ uint32_t expected_size = HEADER_LENGTH + uint32_t((buffer[0] & 0x01) ? 256 + 6 : 128 + 6) * ((buffer[0] & 0x02) ? 40 : 80) * 16 * ((buffer[0] & 0x80) ? 2 : 1);
+ uint64_t actual_size;
+ if (!io.length(actual_size) && expected_size == actual_size)
+ return FIFID_SIGN | FIFID_SIZE;
+ else
+ return FIFID_SIGN;
+}
+
+bool sap_dsk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
+{
+ uint8_t disk_type;
+ if (auto [err, actual] = read_at(io, 0, &disk_type, 1); err || actual != 1)
+ return false;
+
+ int track_count = (disk_type & 0x02) ? 40 : 80;
+ int head_count = (disk_type & 0x80) ? 2 : 1;
+ int max_tracks, max_heads;
+ image.get_maximal_geometry(max_tracks, max_heads);
+ if (max_heads < head_count || max_tracks < track_count)
+ return false;
+
+ switch (disk_type & 0x03)
+ {
+ case 0x01:
+ image.set_form_variant(floppy_image::FF_35, (disk_type & 0x80) ? floppy_image::DSDD : floppy_image::SSDD);
+ break;
+
+ case 0x02:
+ image.set_form_variant(floppy_image::FF_525, (disk_type & 0x80) ? floppy_image::DSSD : floppy_image::SSSD);
+ break;
+
+ case 0x03:
+ image.set_form_variant(floppy_image::FF_525, (disk_type & 0x80) ? floppy_image::DSDD : floppy_image::SSDD);
+ break;
+
+ default:
+ return false;
+ }
+
+ uint8_t sector_buf[16 * 1024];
+ uint8_t sector_header[4];
+ uint8_t sector_crc[2];
+ desc_pc_sector sectors[16];
+
+ size_t read_offset = HEADER_LENGTH;
+ for (int head = 0; head < head_count; head++)
+ {
+ for (int track = 0; track < track_count; track++)
+ {
+ uint8_t *bufptr = &sector_buf[0];
+ uint8_t track_size = 16;
+ int sector_count = 0;
+ bool is_mfm = disk_type & 0x01;
+ while (track_size != 0)
+ {
+ if (auto [err, actual] = read_at(io, read_offset, &sector_header[0], 4); err || actual != 4)
+ return false;
+ if (sector_count == 0 && sector_header[0] == 0x01)
+ is_mfm = false;
+ uint8_t sector_size = (sector_header[0] & 0x02) ? 4 >> (sector_header[0] & 0x01) : 1;
+ if (track_size < sector_size)
+ return false;
+ uint16_t sector_octets = sector_size * (is_mfm ? 256 : 128);
+ if (auto [err, actual] = read_at(io, read_offset + 4, bufptr, sector_octets); err || actual != sector_octets)
+ return false;
+ if (auto [err, actual] = read_at(io, read_offset + 4 + sector_octets, &sector_crc[0], 2); err || actual != 2)
+ return false;
+
+ uint16_t crc = 0xffff;
+ for (uint8_t data : sector_header)
+ crc = accumulate_crc(crc, data);
+ for (uint16_t i = 0; i < sector_octets; i++)
+ {
+ bufptr[i] ^= MAGIC_XOR;
+ crc = accumulate_crc(crc, bufptr[i]);
+ }
+
+ sectors[sector_count].track = sector_header[2];
+ sectors[sector_count].head = head;
+ sectors[sector_count].sector = sector_header[3];
+ sectors[sector_count].size = sector_size;
+ sectors[sector_count].actual_size = sector_octets;
+ sectors[sector_count].data = bufptr;
+ // Teo claims this flag is set for protection with "all the gap bytes set to 0xF7"; actual purpose is a bit unclear
+ sectors[sector_count].deleted = bool(sector_header[0] & 0x04);
+ sectors[sector_count].bad_crc = crc != get_u16be(sector_crc);
+
+ read_offset += sector_octets + 6;
+ bufptr += sector_octets;
+ track_size -= sector_size;
+ sector_count++;
+ }
+ if (is_mfm)
+ build_pc_track_mfm(track, head, image, 100000, sector_count, sectors, calc_default_pc_gap3_size(form_factor, sectors[0].actual_size));
+ else
+ build_pc_track_fm(track, head, image, 100000 / 2, sector_count, sectors, calc_default_pc_gap3_size(form_factor, sectors[0].actual_size));
+ }
+ }
+
+ return true;
+}
diff --git a/src/lib/formats/sap_dsk.h b/src/lib/formats/sap_dsk.h
new file mode 100644
index 00000000000..5bc86a2d6ef
--- /dev/null
+++ b/src/lib/formats/sap_dsk.h
@@ -0,0 +1,30 @@
+// license:BSD-3-Clause
+// copyright-holders:AJR
+
+#ifndef MAME_FORMATS_SAP_DSK_H
+#define MAME_FORMATS_SAP_DSK_H
+
+#pragma once
+
+#include "flopimg.h"
+
+class sap_dsk_format : public floppy_image_format_t
+{
+public:
+ sap_dsk_format() = default;
+
+ virtual const char *name() const noexcept override;
+ virtual const char *description() const noexcept override;
+ virtual const char *extensions() const noexcept override;
+ virtual bool supports_save() const noexcept override;
+
+ virtual int identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const override;
+ virtual bool load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const override;
+
+private:
+ static inline uint16_t accumulate_crc(uint16_t crc, uint8_t data) noexcept;
+};
+
+extern const sap_dsk_format FLOPPY_SAP_FORMAT;
+
+#endif // MAME_FORMATS_SAP_DSK_H
diff --git a/src/lib/formats/sdf_dsk.cpp b/src/lib/formats/sdf_dsk.cpp
index 6e3f1147167..92a6b9fb653 100644
--- a/src/lib/formats/sdf_dsk.cpp
+++ b/src/lib/formats/sdf_dsk.cpp
@@ -50,8 +50,11 @@ int sdf_format::identify(util::random_read &io, uint32_t form_factor, const std:
return 0;
}
- size_t actual;
- io.read_at(0, header, HEADER_SIZE, actual);
+ auto const [err, actual] = read_at(io, 0, header, HEADER_SIZE);
+ if (err || (HEADER_SIZE != actual))
+ {
+ return 0;
+ }
int tracks = header[4];
int heads = header[5];
@@ -79,12 +82,11 @@ int sdf_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool sdf_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
uint8_t header[HEADER_SIZE];
std::vector<uint8_t> track_data(TOTAL_TRACK_SIZE);
std::vector<uint32_t> raw_track_data;
- io.read_at(0, header, HEADER_SIZE, actual);
+ read_at(io, 0, header, HEADER_SIZE); // FIXME: check for errors and premature EOF
const int tracks = header[4];
const int heads = header[5];
@@ -108,7 +110,7 @@ bool sdf_format::load(util::random_read &io, uint32_t form_factor, const std::ve
raw_track_data.clear();
// Read track
- io.read_at(HEADER_SIZE + (heads * track + head) * TOTAL_TRACK_SIZE, &track_data[0], TOTAL_TRACK_SIZE, actual);
+ read_at(io, HEADER_SIZE + (heads * track + head) * TOTAL_TRACK_SIZE, &track_data[0], TOTAL_TRACK_SIZE); // FIXME: check for errors and premature EOF
int sector_count = track_data[0];
diff --git a/src/lib/formats/sol_cas.cpp b/src/lib/formats/sol_cas.cpp
index 8c05a756042..1a793fb26a8 100644
--- a/src/lib/formats/sol_cas.cpp
+++ b/src/lib/formats/sol_cas.cpp
@@ -335,7 +335,7 @@ static int sol20_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int sol20_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int sol20_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return sol20_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/sorc_cas.cpp b/src/lib/formats/sorc_cas.cpp
index 78417e80fc0..316fca7eaf4 100644
--- a/src/lib/formats/sorc_cas.cpp
+++ b/src/lib/formats/sorc_cas.cpp
@@ -107,7 +107,7 @@ static int sorcerer_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int sorcerer_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int sorcerer_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return sorcerer_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/spc1000_cas.cpp b/src/lib/formats/spc1000_cas.cpp
index e6b3959e2e7..a3830c4a679 100644
--- a/src/lib/formats/spc1000_cas.cpp
+++ b/src/lib/formats/spc1000_cas.cpp
@@ -89,12 +89,12 @@ static int spc1000_handle_cas(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int spc1000_tap_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int spc1000_tap_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return spc1000_handle_tap(buffer, bytes);
}
-static int spc1000_cas_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int spc1000_cas_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return spc1000_handle_cas(buffer, bytes);
}
diff --git a/src/lib/formats/st_dsk.cpp b/src/lib/formats/st_dsk.cpp
index 17e0d9efc17..fc105de6fcb 100644
--- a/src/lib/formats/st_dsk.cpp
+++ b/src/lib/formats/st_dsk.cpp
@@ -79,8 +79,7 @@ bool st_format::load(util::random_read &io, uint32_t form_factor, const std::vec
int track_size = sector_count*512;
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
- size_t actual;
- io.read_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(atari_st_fcp_get_desc(track, head, head_count, sector_count),
track, head, sectors, sector_count, 100000, image);
}
@@ -116,8 +115,7 @@ bool st_format::save(util::random_read_write &io, const std::vector<uint32_t> &v
for(int track=0; track < track_count; track++) {
for(int head=0; head < head_count; head++) {
get_track_data_mfm_pc(track, head, image, 2000, 512, sector_count, sectdata);
- size_t actual;
- io.write_at((track*head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors
}
}
@@ -152,8 +150,7 @@ bool msa_format::supports_save() const noexcept
void msa_format::read_header(util::random_read &io, uint16_t &sign, uint16_t &sect, uint16_t &head, uint16_t &strack, uint16_t &etrack)
{
uint8_t h[10];
- size_t actual;
- io.read_at(0, h, 10, actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, h, 10); // FIXME: check for errors and premature EOF
sign = get_u16be(&h[0]);
sect = get_u16be(&h[2]);
head = get_u16be(&h[4]);
@@ -247,12 +244,11 @@ bool msa_format::load(util::random_read &io, uint32_t form_factor, const std::ve
for(int track=strack; track <= etrack; track++) {
for(int head=0; head <= heads; head++) {
- size_t actual;
uint8_t th[2];
- io.read_at(pos, th, 2, actual);
+ read_at(io, pos, th, 2); // FIXME: check for errors and premature EOF
pos += 2;
int tsize = get_u16be(th);
- io.read_at(pos, sectdata, tsize, actual);
+ read_at(io, pos, sectdata, tsize); // FIXME: check for errors and premature EOF
pos += tsize;
if(tsize < track_size) {
if(!uncompress(sectdata, tsize, track_size))
@@ -301,8 +297,7 @@ bool msa_format::save(util::random_read_write &io, const std::vector<uint32_t> &
if(io.seek(0, SEEK_SET))
return false;
- size_t actual;
- io.write(header, 10, actual);
+ write(io, header, 10); // FIXME: check for errors
uint8_t sectdata[11*512];
uint8_t compdata[11*512];
@@ -315,13 +310,13 @@ bool msa_format::save(util::random_read_write &io, const std::vector<uint32_t> &
if(compress(sectdata, track_size, compdata, csize)) {
uint8_t th[2];
put_u16be(th, csize);
- io.write(th, 2, actual);
- io.write(compdata, csize, actual);
+ write(io, th, 2); // FIXME: check for errors
+ write(io, compdata, csize); // FIXME: check for errors
} else {
uint8_t th[2];
put_u16be(th, track_size);
- io.write(th, 2, actual);
- io.write(sectdata, track_size, actual);
+ write(io, th, 2); // FIXME: check for errors
+ write(io, sectdata, track_size); // FIXME: check for errors
}
}
}
diff --git a/src/lib/formats/svi_cas.cpp b/src/lib/formats/svi_cas.cpp
index 137eaa27a52..6e9a59e6ae9 100644
--- a/src/lib/formats/svi_cas.cpp
+++ b/src/lib/formats/svi_cas.cpp
@@ -24,7 +24,7 @@ static int cas_size; // FIXME: global variable prevents multiple instances
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int svi_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int svi_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
int cas_pos, samples_pos, n, i;
diff --git a/src/lib/formats/svi_dsk.cpp b/src/lib/formats/svi_dsk.cpp
index a60491fb20d..4d326542ad5 100644
--- a/src/lib/formats/svi_dsk.cpp
+++ b/src/lib/formats/svi_dsk.cpp
@@ -83,8 +83,7 @@ bool svi_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sectors[i].bad_crc = false;
sectors[i].data = &sector_data[sector_offset];
- size_t actual;
- io.read(sectors[i].data, sector_size, actual);
+ /*auto const [err, actual] =*/ read(io, sectors[i].data, sector_size); // FIXME: check for errors and premature EOF
sector_offset += sector_size;
}
@@ -113,8 +112,7 @@ bool svi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
for (int i = 0; i < 18; i++)
{
- size_t actual;
- io.write(sectors[i + 1].data(), 128, actual);
+ /*auto const [err, actual] =*/ write(io, sectors[i + 1].data(), 128); // FIXME: check for errors
}
// rest are mfm tracks
@@ -130,8 +128,7 @@ bool svi_format::save(util::random_read_write &io, const std::vector<uint32_t> &
for (int i = 0; i < 17; i++)
{
- size_t actual;
- io.write(sectors[i + 1].data(), 256, actual);
+ /*auto const [err, actual] =*/ write(io, sectors[i + 1].data(), 256); // FIXME: check for errors
}
}
}
diff --git a/src/lib/formats/td0_dsk.cpp b/src/lib/formats/td0_dsk.cpp
index a9ba54022a0..956bbd002c7 100644
--- a/src/lib/formats/td0_dsk.cpp
+++ b/src/lib/formats/td0_dsk.cpp
@@ -20,6 +20,7 @@
#include "multibyte.h"
#include <cstring>
+#include <tuple>
#define BUFSZ 512 // new input buffer
@@ -330,8 +331,7 @@ int td0dsk_t::data_read(uint8_t *buf, uint16_t size)
if (size > image_size - floppy_file_offset) {
size = image_size - floppy_file_offset;
}
- size_t actual;
- floppy_file.read_at(floppy_file_offset, buf, size, actual);
+ /*auto const [err, actual] =*/ read_at(floppy_file, floppy_file_offset, buf, size); // FIXME: check for errors and premature EOF
floppy_file_offset += size;
return size;
}
@@ -810,10 +810,13 @@ const char *td0_format::extensions() const noexcept
int td0_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- size_t actual;
uint8_t h[7];
+ auto const [err, actual] = read_at(io, 0, h, 7); // FIXME: does this need to read 7 bytes? it only check 2 bytes. Also check for premature EOF.
+ if(err)
+ {
+ return 0;
+ }
- io.read_at(0, h, 7, actual);
if(((h[0] == 'T') && (h[1] == 'D')) || ((h[0] == 't') && (h[1] == 'd')))
{
return FIFID_SIGN;
@@ -823,6 +826,7 @@ int td0_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool td0_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
+ std::error_condition err;
size_t actual;
int track_count = 0;
int head_count = 0;
@@ -830,9 +834,10 @@ bool td0_format::load(util::random_read &io, uint32_t form_factor, const std::ve
int offset = 0;
const int max_size = 4*1024*1024; // 4MB ought to be large enough for any floppy
std::vector<uint8_t> imagebuf(max_size);
- uint8_t header[12];
- if(io.read_at(0, header, 12, actual) || actual != 12)
+ uint8_t header[12];
+ std::tie(err, actual) = read_at(io, 0, header, 12);
+ if(err || (actual != 12))
return false;
head_count = header[9];
@@ -849,7 +854,8 @@ bool td0_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t image_size;
if(io.length(image_size))
return false;
- if(io.read_at(12, &imagebuf[0], image_size - 12, actual) || actual != (image_size - 12))
+ std::tie(err, actual) = read_at(io, 12, &imagebuf[0], image_size - 12);
+ if(err || (actual != (image_size - 12)))
return false;
}
diff --git a/src/lib/formats/thom_cas.cpp b/src/lib/formats/thom_cas.cpp
index 02bab6217fe..f6f9e317d4f 100644
--- a/src/lib/formats/thom_cas.cpp
+++ b/src/lib/formats/thom_cas.cpp
@@ -58,6 +58,8 @@ static uint8_t* to7_k7_bits;
and so, is used by emulators that bypass the BIOS routine.
It is generally hacked from the raw image more or less by hand
(in particular, to by-pass special loaders and copy-protection schemes).
+ Many of these hacks use emulator-exclusive 6809 instructions and will
+ not work in MAME.
As we run the original BIOS routine, we need to hack back the k7 file
into the original stream.
@@ -462,7 +464,8 @@ static cassette_image::error mo5_k5_load( cassette_image *cass )
size_t size = cass->image_size( ), pos = 0;
int i, sz, sz2, hbit = 0;
uint8_t typ, block[264], sum;
- int invalid = 0, hbitsize = 0, dcmoto = 0;
+ int invalid = 0, hbitsize = 0;
+ bool dcmoto = false, dcmoto_old = false;
LOG (( "mo5_k5_load: start conversion, size=%li\n", (long)size ));
PRINT (( "mo5_k5_load: open cassette, length: %li bytes\n", (long) size ));
@@ -553,7 +556,9 @@ static cassette_image::error mo5_k5_load( cassette_image *cass )
cass->image_read( block, pos, 6 );
if ( ! memcmp( block, "DCMOTO", 6 ) || ! memcmp( block, "DCMO5", 5 ) || ! memcmp( block, "DCMO6", 5 ) )
- dcmoto = 1;
+ dcmoto = true;
+ if ( block[0] == 0xdc && block[1] == 0x01 )
+ dcmoto_old = true;
/* loop over regular blocks */
while ( pos < size )
@@ -574,6 +579,12 @@ static cassette_image::error mo5_k5_load( cassette_image *cass )
pos += 5;
}
}
+ else if ( dcmoto_old )
+ {
+ cass->image_read( block, pos, 1 );
+ if ( block[0] == 0xdc )
+ pos++;
+ }
/* skip 0x01 filler */
for ( sz = 0; pos < size; pos++, sz++ )
@@ -693,7 +704,12 @@ static cassette_image::error mo5_k5_load( cassette_image *cass )
pos -= sz;
goto rebounce;
}
- if ( invalid < 10 && sz > 6 && ( (in == 0x3c && in2 == 0x5a) || (in == 0xc3 && in2 == 0x5a) || (in == 0xc3 && in2 == 0x3c) || (in == 0x87 && in2 == 0x4a) ) )
+ if ( invalid < 10 && sz > 6 &&
+ ( (in == 0x3c && in2 == 0x5a) ||
+ (in == 0xc3 && in2 == 0x5a) ||
+ (in == 0xc3 && in2 == 0x3c) ||
+ (in == 0x87 && in2 == 0x4a) ||
+ (in == 0x3c && in2 == 0x55) ) ) // Androïdes
{
/* special block found */
K5_FILL_0( 1200 );
diff --git a/src/lib/formats/thom_dsk.cpp b/src/lib/formats/thom_dsk.cpp
index ad2e4495ca2..3399a1aa487 100644
--- a/src/lib/formats/thom_dsk.cpp
+++ b/src/lib/formats/thom_dsk.cpp
@@ -50,6 +50,12 @@ const thomson_525_format::format thomson_525_format::formats[] = {
{}
};
+int thomson_525_format::get_image_offset(const format &f, int head, int track) const
+{
+ return (track + (head ? f.track_count : 0)) * compute_track_size(f);
+}
+
+
thomson_35_format::thomson_35_format() : wd177x_format(formats)
{
@@ -70,6 +76,8 @@ const char *thomson_35_format::extensions() const noexcept
return "fd";
}
+// 1280K .fd images exist but are not supported. They represent a notional type
+// of 4-sided disk that can be inserted into 2 drives at once.
const thomson_35_format::format thomson_35_format::formats[] = {
{
floppy_image::FF_35, floppy_image::SSDD, floppy_image::MFM,
@@ -90,5 +98,10 @@ const thomson_35_format::format thomson_35_format::formats[] = {
{}
};
+int thomson_35_format::get_image_offset(const format &f, int head, int track) const
+{
+ return (track + (head ? f.track_count : 0)) * compute_track_size(f);
+}
+
const thomson_525_format FLOPPY_THOMSON_525_FORMAT;
const thomson_35_format FLOPPY_THOMSON_35_FORMAT;
diff --git a/src/lib/formats/thom_dsk.h b/src/lib/formats/thom_dsk.h
index 52927f15de8..09ea1cbec0c 100644
--- a/src/lib/formats/thom_dsk.h
+++ b/src/lib/formats/thom_dsk.h
@@ -16,6 +16,8 @@ public:
virtual const char *description() const noexcept override;
virtual const char *extensions() const noexcept override;
+ int get_image_offset(const format &f, int head, int track) const override;
+
private:
static const format formats[];
};
@@ -29,6 +31,8 @@ public:
virtual const char *description() const noexcept override;
virtual const char *extensions() const noexcept override;
+ int get_image_offset(const format &f, int head, int track) const override;
+
private:
static const format formats[];
};
diff --git a/src/lib/formats/ti99_dsk.cpp b/src/lib/formats/ti99_dsk.cpp
index 64b8d81aa67..4cca5bdb996 100644
--- a/src/lib/formats/ti99_dsk.cpp
+++ b/src/lib/formats/ti99_dsk.cpp
@@ -954,8 +954,7 @@ int ti99_sdf_format::identify(util::random_read &io, uint32_t form_factor, const
{
// Read first sector (Volume Information Block)
ti99vib vib;
- size_t actual;
- io.read_at(0, &vib, sizeof(ti99vib), actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, &vib, sizeof(ti99vib)); // FIXME: check for errors and premature EOF
// Check from contents
if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K'))
@@ -993,8 +992,7 @@ void ti99_sdf_format::determine_sizes(util::random_read &io, int& cell_size, int
// Read first sector
ti99vib vib;
- size_t actual;
- io.read_at(0, &vib, sizeof(ti99vib), actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, &vib, sizeof(ti99vib)); // FIXME: check for errors and premature EOF
// Check from contents
if ((vib.id[0]=='D')&&(vib.id[1]=='S')&&(vib.id[2]=='K'))
@@ -1079,8 +1077,7 @@ void ti99_sdf_format::load_track(util::random_read &io, uint8_t *sectordata, int
int logicaltrack = (head==0)? track : (2*trackcount - track - 1);
int position = logicaltrack * get_track_size(sectorcount);
- size_t actual;
- io.read_at(position, sectordata, sectorcount*SECTOR_SIZE, actual);
+ /*auto const [err, actual] =*/ read_at(io, position, sectordata, sectorcount*SECTOR_SIZE); // FIXME: check for errors and premature EOF
// Interleave and skew
int interleave = 7;
@@ -1158,8 +1155,7 @@ void ti99_sdf_format::write_track(util::random_read_write &io, uint8_t *sectorda
{
uint8_t const *const buf = sectordata + i * SECTOR_SIZE;
LOGMASKED(LOG_DETAIL, "[ti99_dsk] Writing sector %d (offset %06x)\n", sector[i], sector[i] * SECTOR_SIZE);
- size_t actual;
- io.write_at(trackoffset + sector[i] * SECTOR_SIZE, buf, SECTOR_SIZE, actual);
+ /*auto const [err, actual] =*/ write_at(io, trackoffset + sector[i] * SECTOR_SIZE, buf, SECTOR_SIZE); // FIXME: check for errors
}
}
@@ -1246,8 +1242,7 @@ int ti99_tdf_format::identify(util::random_read &io, uint32_t form_factor, const
LOGMASKED(LOG_INFO, "[ti99_dsk] Image file length matches TDF\n");
// Fetch track 0
- size_t actual;
- io.read_at(0, fulltrack, get_track_size(sector_count), actual);
+ /*auto const [err, actual] =*/ read_at(io, 0, fulltrack, get_track_size(sector_count)); // FIXME: check for errors and premature EOF
if (sector_count == 9)
{
@@ -1358,12 +1353,11 @@ void ti99_tdf_format::determine_sizes(util::random_read &io, int& cell_size, int
*/
void ti99_tdf_format::load_track(util::random_read &io, uint8_t *sectordata, int *sector, int *secoffset, int head, int track, int sectorcount, int trackcount) const
{
- size_t actual;
uint8_t fulltrack[12544]; // space for a full TDF track
// Read beginning of track 0. We need this to get the first gap, according
// to the format
- io.read_at(0, fulltrack, 100, actual);
+ read_at(io, 0, fulltrack, 100); // FIXME: check for errors and premature EOF
int offset = 0;
int tracksize = get_track_size(sectorcount);
@@ -1404,7 +1398,7 @@ void ti99_tdf_format::load_track(util::random_read &io, uint8_t *sectordata, int
int base = (head * trackcount + track) * tracksize;
int position = 0;
- io.read_at(base, fulltrack, tracksize, actual);
+ read_at(io, base, fulltrack, tracksize); // FIXME: check for errors and premature EOF
for (int i=0; i < sectorcount; i++)
{
@@ -1506,8 +1500,7 @@ void ti99_tdf_format::write_track(util::random_read_write &io, uint8_t *sectorda
for (int i=0; i < param[WGAP3]; i++) trackdata[pos++] = param[WGAPBYTE];
}
for (int i=0; i < param[WGAP4]; i++) trackdata[pos++] = param[WGAPBYTE];
- size_t actual;
- io.write_at(offset, trackdata, get_track_size(sector_count), actual);
+ /*auto const [err, actual] =*/ write_at(io, offset, trackdata, get_track_size(sector_count)); // FIXME: check for errors
}
int ti99_tdf_format::get_track_size(int sector_count) const
diff --git a/src/lib/formats/trd_dsk.cpp b/src/lib/formats/trd_dsk.cpp
index 4ec6d4a962a..cf1a7f00445 100644
--- a/src/lib/formats/trd_dsk.cpp
+++ b/src/lib/formats/trd_dsk.cpp
@@ -12,6 +12,8 @@
#include "ioprocs.h"
+#include <tuple>
+
trd_format::trd_format() : wd177x_format(formats)
{
@@ -51,16 +53,19 @@ int trd_format::find_size(util::random_read &io, uint32_t form_factor, const std
{
index = i; // at least size match, save it for the case if there will be no exact matches
+ std::error_condition err;
size_t actual;
uint8_t sectdata[0x100];
if (f.encoding == floppy_image::MFM)
- io.read_at(0x800, sectdata, 0x100, actual);
+ std::tie(err, actual) = read_at(io, 0x800, sectdata, 0x100);
else
{
- io.read_at(0x100, sectdata, 0x100, actual);
+ std::tie(err, actual) = read_at(io, 0x100, sectdata, 0x100);
for (int i = 0; i < 0x100; i++)
sectdata[i] ^= 0xff;
}
+ if (err || (0x100 != actual))
+ continue;
uint8_t disktype = sectdata[0xe3]; // 16 - DS80, 17 - DS40, 18 - SS80, 19 - SS40
if (disktype < 0x16 || disktype > 0x19)
diff --git a/src/lib/formats/trs80_dsk.cpp b/src/lib/formats/trs80_dsk.cpp
index 511d9fdfbf1..f670273a5af 100644
--- a/src/lib/formats/trs80_dsk.cpp
+++ b/src/lib/formats/trs80_dsk.cpp
@@ -146,9 +146,9 @@ int jv3_format::identify(util::random_read &io, uint32_t form_factor, const std:
if (image_size < 0x2200)
return 0; // too small, silent return
- std::vector<uint8_t> data(image_size);
- size_t actual;
- io.read_at(0, data.data(), image_size, actual);
+ auto const [err, data, actual] = read_at(io, 0, image_size);
+ if (err || (actual != image_size))
+ return 0;
const uint32_t entries = 2901;
const uint32_t header_size = entries *3 +1;
@@ -238,9 +238,9 @@ bool jv3_format::load(util::random_read &io, uint32_t form_factor, const std::ve
uint64_t image_size;
if (io.length(image_size))
return false;
- std::vector<uint8_t> data(image_size);
- size_t actual;
- io.read_at(0, data.data(), data.size(), actual);
+ auto const [err, data, actual] = read_at(io, 0, image_size);
+ if (err || (actual != image_size))
+ return 0;
const uint32_t entries = 2901;
const uint32_t header_size = entries *3 +1;
bool is_dd = false, is_ds = false;
@@ -365,13 +365,14 @@ bool jv3_format::save(util::random_read_write &io, const std::vector<uint32_t> &
{
// If the disk already exists, find out if it's writable
uint64_t image_size;
- if (!io.length(image_size))
+ if (!io.length(image_size) && (image_size >= 0x2200))
{
- std::vector<uint8_t> data(image_size);
- size_t actual;
- io.read_at(0, data.data(), data.size(), actual);
- if ((data.size() >= 0x2200) && (data[0x21ff] == 0))
- return false; // disk is readonly
+ uint8_t flag;
+ auto const [err, actual] = read_at(io, 0x21ff, &flag, 1);
+ if (err || (1 != actual)) // TODO: should we save over the top if we couldn’t read the read-only flag?
+ return false;
+ if (flag == 0)
+ return false; // disk is read-only
}
}
@@ -413,8 +414,7 @@ bool jv3_format::save(util::random_read_write &io, const std::vector<uint32_t> &
header[sect_ptr++] = track;
header[sect_ptr++] = i;
header[sect_ptr++] = head ? 0x10 : 0;
- size_t actual;
- io.write_at(data_ptr, &dummy[0], 256, actual);
+ /*auto const [err, actual] =*/ write_at(io, data_ptr, &dummy[0], 256); // FIXME: check for errors
data_ptr += 256;
}
}
@@ -435,16 +435,14 @@ bool jv3_format::save(util::random_read_write &io, const std::vector<uint32_t> &
flags |= (sectors[i].size() >> 8) ^1;
flags |= head ? 0x10 : 0;
header[sect_ptr++] = flags;
- size_t actual;
- io.write_at(data_ptr, sectors[i].data(), sectors[i].size(), actual);
+ /*auto const [err, actual] =*/ write_at(io, data_ptr, sectors[i].data(), sectors[i].size()); // FIXME: check for errors
data_ptr += sectors[i].size();
}
}
}
}
// Save the header
- size_t actual;
- io.write_at(0, header, 0x2200, actual);
+ /*auto const [err, actual] =*/ write_at(io, 0, header, 0x2200); // FIXME: check for errors
return true;
}
diff --git a/src/lib/formats/trs_cas.cpp b/src/lib/formats/trs_cas.cpp
index 8b1ede7ec81..2648c536320 100644
--- a/src/lib/formats/trs_cas.cpp
+++ b/src/lib/formats/trs_cas.cpp
@@ -174,7 +174,7 @@ static int trs80m3_handle_cas(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int trs80_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int trs80_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
if (cas_size && (bytes[0] == 0x55))
return trs80m3_handle_cas( buffer, bytes );
diff --git a/src/lib/formats/tzx_cas.cpp b/src/lib/formats/tzx_cas.cpp
index 4d14e567453..f758c1b31e6 100644
--- a/src/lib/formats/tzx_cas.cpp
+++ b/src/lib/formats/tzx_cas.cpp
@@ -72,7 +72,7 @@ static void toggle_wave_data(void)
static void tzx_cas_get_blocks( const uint8_t *casdata, int caslen )
{
- int pos = sizeof(TZX_HEADER) + 2;
+ uint32_t pos = sizeof(TZX_HEADER) + 2;
int max_block_count = INITIAL_MAX_BLOCK_COUNT;
int loopcount = 0, loopoffset = 0;
blocks = (uint8_t**)malloc(max_block_count * sizeof(uint8_t*));
@@ -192,7 +192,14 @@ static void tzx_cas_get_blocks( const uint8_t *casdata, int caslen )
break;
}
- block_count++;
+ if (pos > caslen)
+ {
+ LOG_FORMATS("Block %d(ID=%d) with wrong length discarded\n", block_count, blocktype);
+ }
+ else
+ {
+ block_count++;
+ }
}
}
@@ -779,7 +786,7 @@ cleanup:
return -1;
}
-static int tzx_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
+static int tzx_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int )
{
int16_t *p = buffer;
int size = 0;
@@ -788,7 +795,7 @@ static int tzx_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
return size;
}
-static int cdt_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
+static int cdt_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int )
{
int16_t *p = buffer;
int size = 0;
@@ -797,72 +804,114 @@ static int cdt_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
return size;
}
-static int tap_cas_to_wav_size( const uint8_t *casdata, int caslen )
+static int tap_cas_to_wav_size(const uint8_t *casdata, int caslen)
{
+ /*
+ TAP Header:
+ | 0 | W | Length of Data Block (N) | -+
+ | 2 | B | Flag Byte | -+
+ | 3 | B*(N-2) | Data | | Data Block
+ | N+1 | B | XOR Checksum of [2..N] | -+
+ */
+
int size = 0;
const uint8_t *p = casdata;
- while (p < casdata + caslen)
+ while (caslen > 2)
{
int data_size = get_u16le(&p[0]);
- int pilot_length = (p[2] == 0x00) ? 8063 : 3223;
- LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size);
p += 2;
+ caslen -= 2;
+ if (caslen < data_size)
+ {
+ LOG_FORMATS("tap_cas_to_wav_size: Requested 0x%X bytes but only 0x%X available.\n", data_size, caslen);
+ data_size = caslen;
+ }
+ caslen -= data_size;
+
+ // Data Block
+ LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size);
+ const int pilot_length = (p[0] == 0x00) ? 8063 : 3223;
size += tzx_cas_handle_block(nullptr, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
- LOG_FORMATS(", total size is now: %d\n", size);
+ LOG_FORMATS(", total size is now: %d", size);
+
+ // Validate Checksum
+ const uint8_t checksum = p[data_size - 1];
+ LOG_FORMATS(", checksum 0x%X\n", checksum);
+ uint8_t check = 0x00;
+ for(int i = 0; i < (data_size - 1); i++)
+ {
+ check ^= p[i];
+ }
+ if (check != checksum)
+ {
+ osd_printf_warning("tap_cas_to_wav_size: wrong checksum 0x%X\n", check);
+ }
+
p += data_size;
}
return size;
}
-static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
+static int tap_cas_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int bytes_length)
{
int16_t *p = buffer;
int size = 0;
- while (size < length)
+ int block = 0;
+ while (bytes_length > 2)
{
int data_size = get_u16le(&bytes[0]);
- int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223;
- LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size);
bytes += 2;
+ bytes_length -= 2;
+
+ LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size);
+ if (bytes_length < data_size)
+ {
+ osd_printf_warning("BAD Image: block #%d required %d byte(s), but only %d available\n", block, data_size, bytes_length);
+ data_size = bytes_length; // Take as much as we can.
+ }
+ bytes_length -= data_size;
+
+ int pilot_length = (bytes[0] == 0x00) ? 8063 : 3223;
size += tzx_cas_handle_block(&p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
bytes += data_size;
+ ++block;
}
return size;
}
static const cassette_image::LegacyWaveFiller tzx_legacy_fill_wave =
{
- tzx_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tzx_cas_to_wav_size, /* chunk_sample_calc */
- TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ tzx_cas_fill_wave, // fill_wave
+ -1, // chunk_size
+ 0, // chunk_samples
+ tzx_cas_to_wav_size, // chunk_sample_calc
+ TZX_WAV_FREQUENCY, // sample_frequency
+ 0, // header_samples
+ 0, // trailer_samples
};
static const cassette_image::LegacyWaveFiller tap_legacy_fill_wave =
{
- tap_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tap_cas_to_wav_size, /* chunk_sample_calc */
- TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ tap_cas_fill_wave, // fill_wave
+ -1, // chunk_size
+ 0, // chunk_samples
+ tap_cas_to_wav_size, // chunk_sample_calc
+ TZX_WAV_FREQUENCY, // sample_frequency
+ 0, // header_samples
+ 0 // trailer_samples
};
static const cassette_image::LegacyWaveFiller cdt_legacy_fill_wave =
{
- cdt_cas_fill_wave, /* fill_wave */
- -1, /* chunk_size */
- 0, /* chunk_samples */
- tzx_cas_to_wav_size, /* chunk_sample_calc */
- TZX_WAV_FREQUENCY, /* sample_frequency */
- 0, /* header_samples */
- 0 /* trailer_samples */
+ cdt_cas_fill_wave, // fill_wave
+ -1, // chunk_size
+ 0, // chunk_samples
+ tzx_cas_to_wav_size, // chunk_sample_calc
+ TZX_WAV_FREQUENCY, // sample_frequency
+ 0, // header_samples
+ 0 // trailer_samples
};
static cassette_image::error tzx_cassette_identify( cassette_image *cassette, cassette_image::Options *opts )
diff --git a/src/lib/formats/uef_cas.cpp b/src/lib/formats/uef_cas.cpp
index f284af43035..02f150915a7 100644
--- a/src/lib/formats/uef_cas.cpp
+++ b/src/lib/formats/uef_cas.cpp
@@ -247,7 +247,7 @@ static int16_t* uef_cas_fill_bit( uint8_t loops, int16_t *buffer, bool bit )
return buffer;
}
-static int uef_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
+static int uef_cas_fill_wave( int16_t *buffer, int length, const uint8_t *bytes, int )
{
if ( bytes[0] == 0x1f && bytes[1] == 0x8b ) {
if ( gz_ptr == nullptr ) {
@@ -264,16 +264,16 @@ static int uef_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
int chunk_type = get_u16le( &bytes[pos] );
int chunk_length = get_u32le( &bytes[pos+2] );
- uint32_t baud_length, j;
- uint8_t i, *c;
+ uint32_t baud_length;
+ const uint8_t *c;
pos += 6;
switch( chunk_type ) {
case 0x0100: /* implicit start/stop bit data block */
case 0x0104: // used by atom dumps, looks like normal data
- for( j = 0; j < chunk_length; j++ ) {
+ for( uint32_t j = 0; j < chunk_length; j++ ) {
uint8_t byte = bytes[pos+j];
p = uef_cas_fill_bit( loops, p, 0 );
- for( i = 0; i < 8; i++ ) {
+ for( uint8_t i = 0; i < 8; i++ ) {
p = uef_cas_fill_bit( loops, p, (byte >> i) & 1 );
}
p = uef_cas_fill_bit( loops, p, 1 );
@@ -285,11 +285,10 @@ static int uef_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
LOG_FORMATS( "Unsupported chunk type: %04x\n", chunk_type );
break;
case 0x0102: /* explicit tape data block */
- j = ( chunk_length * 10 ) - bytes[pos];
c = bytes + pos;
- while( j ) {
+ for( uint32_t j = ( chunk_length * 10 ) - bytes[pos]; j; ) {
uint8_t byte = *c;
- for( i = 0; i < 8 && i < j; i++ ) {
+ for( uint8_t i = 0; i < 8 && i < j; i++ ) {
p = uef_cas_fill_bit( loops, p, (byte >> i) & 1 );
j--;
}
@@ -311,7 +310,7 @@ static int uef_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
}
break;
case 0x0116: /* floating point gap */
- for( baud_length = (get_uef_float(bytes+pos)*UEF_WAV_FREQUENCY); baud_length; baud_length-- ) {
+ for( baud_length = (get_uef_float(bytes + pos)*UEF_WAV_FREQUENCY); baud_length; baud_length-- ) {
*p = WAVE_NULL; p++;
length -= 1;
}
diff --git a/src/lib/formats/uniflex_dsk.cpp b/src/lib/formats/uniflex_dsk.cpp
index 0143bf8cf0e..063d3c877f9 100644
--- a/src/lib/formats/uniflex_dsk.cpp
+++ b/src/lib/formats/uniflex_dsk.cpp
@@ -53,8 +53,9 @@ int uniflex_format::find_size(util::random_read &io, uint32_t form_factor, const
// Look at the SIR sector, the second sector.
uint8_t sir[192];
- size_t actual;
- io.read_at(1 * 512, sir, sizeof(sir), actual);
+ auto const [err, actual] = read_at(io, 1 * 512, sir, sizeof(sir)); // FIXME: check for premature EOF
+ if (err)
+ return -1;
uint16_t fdn_block_count = get_u16be(&sir[0x10]);
uint32_t last_block_number = get_u24be(&sir[0x12]);
diff --git a/src/lib/formats/upd765_dsk.cpp b/src/lib/formats/upd765_dsk.cpp
index f3f08f37b4e..589ab1e1666 100644
--- a/src/lib/formats/upd765_dsk.cpp
+++ b/src/lib/formats/upd765_dsk.cpp
@@ -231,8 +231,7 @@ bool upd765_format::load(util::random_read &io, uint32_t form_factor, const std:
for(int track=0; track < f.track_count; track++)
for(int head=0; head < f.head_count; head++) {
build_sector_description(f, sectdata, sectors, track, head);
- size_t actual;
- io.read_at((track*f.head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, (track*f.head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(desc, track, head, sectors, f.sector_count, total_size, image);
}
@@ -345,20 +344,19 @@ bool upd765_format::save(util::random_read_write &io, const std::vector<uint32_t
if(chosen_candidate == -1)
chosen_candidate = 0;
-
const format &f = formats[chosen_candidate];
int track_size = compute_track_size(f);
uint8_t sectdata[40*512];
desc_s sectors[40];
- for(int track=0; track < f.track_count; track++)
+ for(int track=0; track < f.track_count; track++) {
for(int head=0; head < f.head_count; head++) {
build_sector_description(f, sectdata, sectors, track, head);
extract_sectors(image, f, sectors, track, head);
- size_t actual;
- io.write_at((track*f.head_count + head)*track_size, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, (track*f.head_count + head)*track_size, sectdata, track_size); // FIXME: check for errors
}
+ }
return true;
}
diff --git a/src/lib/formats/vdk_dsk.cpp b/src/lib/formats/vdk_dsk.cpp
index e47d3502981..02e25ec5df9 100644
--- a/src/lib/formats/vdk_dsk.cpp
+++ b/src/lib/formats/vdk_dsk.cpp
@@ -36,9 +36,10 @@ const char *vdk_format::extensions() const noexcept
int vdk_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
- size_t actual;
uint8_t id[2];
- io.read_at(0, id, 2, actual);
+ auto const [err, actual] = read_at(io, 0, id, 2);
+ if (err || (2 != actual))
+ return 0;
if (id[0] == 'd' && id[1] == 'k')
return FIFID_SIGN;
@@ -48,12 +49,11 @@ int vdk_format::identify(util::random_read &io, uint32_t form_factor, const std:
bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
- size_t actual;
if (io.seek(0, SEEK_SET))
return false;
uint8_t header[0x100];
- io.read(header, 0x100, actual);
+ read(io, header, 0x100); // FIXME: check for errors and premature EOF
int const header_size = header[3] * 0x100 + header[2];
int const track_count = header[8];
@@ -81,7 +81,7 @@ bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
sectors[i].bad_crc = false;
sectors[i].data = &sector_data[sector_offset];
- io.read(sectors[i].data, SECTOR_SIZE, actual);
+ read(io, sectors[i].data, SECTOR_SIZE); // FIXME: check for errors and premature EOF
sector_offset += SECTOR_SIZE;
}
@@ -95,7 +95,6 @@ bool vdk_format::load(util::random_read &io, uint32_t form_factor, const std::ve
bool vdk_format::save(util::random_read_write &io, const std::vector<uint32_t> &variants, const floppy_image &image) const
{
- size_t actual;
if (io.seek(0, SEEK_SET))
return false;
@@ -118,7 +117,7 @@ bool vdk_format::save(util::random_read_write &io, const std::vector<uint32_t> &
header[10] = 0;
header[11] = 0;
- io.write(header, sizeof(header), actual);
+ write(io, header, sizeof(header)); // FIXME: check for errors
// write disk data
for (int track = 0; track < track_count; track++)
@@ -129,7 +128,7 @@ bool vdk_format::save(util::random_read_write &io, const std::vector<uint32_t> &
auto sectors = extract_sectors_from_bitstream_mfm_pc(bitstream);
for (int i = 0; i < SECTOR_COUNT; i++)
- io.write(sectors[FIRST_SECTOR_ID + i].data(), SECTOR_SIZE, actual);
+ write(io, sectors[FIRST_SECTOR_ID + i].data(), SECTOR_SIZE); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/vg5k_cas.cpp b/src/lib/formats/vg5k_cas.cpp
index fcdb9ba7f02..724a4889229 100644
--- a/src/lib/formats/vg5k_cas.cpp
+++ b/src/lib/formats/vg5k_cas.cpp
@@ -184,7 +184,7 @@ static int vg5k_handle_tap(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int vg5k_k7_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int vg5k_k7_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return vg5k_handle_tap(buffer, bytes);
}
diff --git a/src/lib/formats/vgi_dsk.cpp b/src/lib/formats/vgi_dsk.cpp
index ae6cd53018e..a86ffdefb75 100644
--- a/src/lib/formats/vgi_dsk.cpp
+++ b/src/lib/formats/vgi_dsk.cpp
@@ -18,8 +18,8 @@ http://www.bitsavers.org/pdf/micropolis/metafloppy/1084-01_1040_1050_Users_Manua
#include <cstring>
-static const int track_size = 100'000;
-static const int half_bitcell_size = 2000;
+static constexpr int TRACK_SIZE = 100'000;
+static constexpr int HALF_BITCELL_SIZE = 2000;
micropolis_vgi_format::micropolis_vgi_format() : floppy_image_format_t()
{
@@ -32,10 +32,10 @@ struct format {
};
static const format formats[] = {
- {1, 35, floppy_image::SSDD}, // MOD-I
- {2, 35, floppy_image::DSDD},
- {1, 77, floppy_image::SSQD}, // MOD-II
- {2, 77, floppy_image::DSQD},
+ {1, 35, floppy_image::SSDD16}, // MOD-I
+ {2, 35, floppy_image::DSDD16},
+ {1, 77, floppy_image::SSQD16}, // MOD-II
+ {2, 77, floppy_image::DSQD16},
{}
};
@@ -76,14 +76,14 @@ bool micropolis_vgi_format::load(util::random_read &io, uint32_t form_factor, co
for (int track = 0; track < fmt.track_count; track++) {
for (int sector = 0; sector < 16; sector++) {
for (int i = 0; i < 40; i++)
- mfm_w(buf, 8, 0, half_bitcell_size);
- std::size_t actual;
- if (io.read(sector_bytes, std::size(sector_bytes), actual))
+ mfm_w(buf, 8, 0, HALF_BITCELL_SIZE);
+ auto const [err, actual] = read(io, sector_bytes, std::size(sector_bytes));
+ if (err || (actual != std::size(sector_bytes)))
return false;
for (int i = 0; i < std::size(sector_bytes); i++)
- mfm_w(buf, 8, sector_bytes[i], half_bitcell_size);
- while (buf.size() < track_size/16 * (sector+1))
- mfm_w(buf, 8, 0, half_bitcell_size);
+ mfm_w(buf, 8, sector_bytes[i], HALF_BITCELL_SIZE);
+ while (buf.size() < TRACK_SIZE/16 * (sector+1))
+ mfm_w(buf, 8, 0, HALF_BITCELL_SIZE);
}
generate_track_from_levels(track, head, buf, 0, image);
buf.clear();
@@ -116,9 +116,9 @@ bool micropolis_vgi_format::save(util::random_read_write &io, const std::vector<
uint8_t sector_bytes[275];
for (int head = 0; head < fmt.head_count; head++) {
for (int track = 0; track < fmt.track_count; track++) {
- std::vector<bool> bitstream = generate_bitstream_from_track(track, head, half_bitcell_size, image);
+ std::vector<bool> bitstream = generate_bitstream_from_track(track, head, HALF_BITCELL_SIZE, image);
for (int sector = 0; sector < 16; sector++) {
- int sector_start = track_size/16 * sector;
+ int sector_start = TRACK_SIZE/16 * sector;
uint32_t pos = sector_start + 512 - 16;
uint16_t shift_reg = 0;
while (pos < sector_start + 60*16 && pos < bitstream.size()) {
@@ -134,8 +134,8 @@ bool micropolis_vgi_format::save(util::random_read_write &io, const std::vector<
memset(sector_bytes, 0, std::size(sector_bytes));
}
- std::size_t actual;
- if (io.write(sector_bytes, std::size(sector_bytes), actual))
+ auto const [err, actual] = write(io, sector_bytes, std::size(sector_bytes));
+ if (err)
return false;
}
}
diff --git a/src/lib/formats/victor9k_dsk.cpp b/src/lib/formats/victor9k_dsk.cpp
index a0fdaedab5a..803c75303d8 100644
--- a/src/lib/formats/victor9k_dsk.cpp
+++ b/src/lib/formats/victor9k_dsk.cpp
@@ -136,12 +136,12 @@ const char *victor9k_format::extensions() const noexcept
int victor9k_format::find_size(util::random_read &io)
{
uint64_t size;
- if(io.length(size))
+ if (io.length(size))
return -1;
- for(int i=0; formats[i].sector_count; i++) {
+ for (int i = 0; formats[i].sector_count; i++) {
const format &f = formats[i];
- if(size == (uint32_t) f.sector_count*f.sector_base_size)
+ if(size == uint32_t(f.sector_count*f.sector_base_size))
return i;
}
@@ -155,7 +155,7 @@ int victor9k_format::find_size(util::random_read &io, uint32_t form_factor)
int victor9k_format::identify(const floppy_image &image)
{
- for(int i=0; formats[i].form_factor; i++) {
+ for (int i = 0; formats[i].form_factor; i++) {
const format &f = formats[i];
if(f.variant == image.get_variant())
return i;
@@ -291,7 +291,7 @@ void victor9k_format::build_sector_description(const format &f, uint8_t *sectdat
bool victor9k_format::load(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants, floppy_image &image) const
{
int const type = find_size(io, form_factor);
- if(type == -1)
+ if (type == -1)
return false;
const format &f = formats[type];
@@ -300,15 +300,12 @@ bool victor9k_format::load(util::random_read &io, uint32_t form_factor, const st
f.head_count, f.sector_count);
uint64_t size;
- if(io.length(size))
+ if (io.length(size))
return false;
- std::vector<uint8_t> img;
- try { img.resize(size); }
- catch (...) { return false; }
-
- size_t actual;
- io.read_at(0, &img[0], size, actual);
+ auto const [err, img, actual] = read_at(io, 0, size);
+ if (err || (actual != size))
+ return false;
log_boot_sector(&img[0]);
@@ -449,17 +446,17 @@ bool victor9k_format::save(util::random_read_write &io, const std::vector<uint32
{
int type = victor9k_format::identify(image);
uint64_t size;
- io.length(size);
+ io.length(size); // FIXME: check for errors
osd_printf_verbose("save type: %01d, size: %d\n", type, size);
- if(type == -1)
+ if (type == -1)
return false;
const format &f = formats[type];
osd_printf_verbose("save Heads: %01d Tracks: %02d Sectors/track head[1]track[1]: %02d\n ",
f.head_count, f.track_count, sectors_per_track[1][1]);
- for(int head=0; head < f.head_count; head++) {
+ for (int head = 0; head < f.head_count; head++) {
for(int track=0; track < f.track_count; track++) {
int sector_count = sectors_per_track[head][track];
int track_size = compute_track_size(f, head, track);
@@ -471,8 +468,7 @@ bool victor9k_format::save(util::random_read_write &io, const std::vector<uint32
build_sector_description(f, sectdata, 0, sectors, sector_count);
extract_sectors(image, f, sectors, track, head, sector_count);
- size_t actual;
- io.write_at(offset, sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, offset, sectdata, track_size); // FIXME: check for errors
}
}
@@ -481,7 +477,6 @@ bool victor9k_format::save(util::random_read_write &io, const std::vector<uint32
void victor9k_format::extract_sectors(const floppy_image &image, const format &f, desc_s *sdesc, int track, int head, int sector_count)
{
-
// Extract the sectors
auto bitstream = generate_bitstream_from_track(track, head, cell_size[speed_zone[head][track]], image);
auto sectors = extract_sectors_from_bitstream_victor_gcr5(bitstream);
@@ -493,14 +488,14 @@ void victor9k_format::extract_sectors(const floppy_image &image, const format &f
}
}
- for(int i=0; i<sector_count; i++) {
+ for (int i = 0; i<sector_count; i++) {
desc_s &ds = sdesc[i];
const auto &data = sectors[ds.sector_id];
osd_printf_verbose("Head: %01d TracK: %02d Total Sectors: %02d Current Sector: %02d ",
head, track, sector_count, i);
- if(data.empty()) {
+ if (data.empty()) {
memset((uint8_t *)ds.data, 0, ds.size);
- } else if(data.size() < ds.size) {
+ } else if (data.size() < ds.size) {
memcpy((uint8_t *)ds.data, data.data(), data.size() - 1);
memset((uint8_t *)ds.data + data.size() - 1, 0, data.size() - ds.size);
osd_printf_verbose("data.size(): %01d\n", data.size());
diff --git a/src/lib/formats/vt_cas.cpp b/src/lib/formats/vt_cas.cpp
index 046e97880d8..2052647bfd8 100644
--- a/src/lib/formats/vt_cas.cpp
+++ b/src/lib/formats/vt_cas.cpp
@@ -8,7 +8,7 @@
#define SILENCE 8000
-static int generic_fill_wave(int16_t *buffer, int length, uint8_t *code, int bitsamples, int bytesamples, int lo, int16_t *(*fill_wave_byte)(int16_t *buffer, int byte))
+static int generic_fill_wave(int16_t *buffer, int length, const uint8_t *code, int bitsamples, int bytesamples, int lo, int16_t *(*fill_wave_byte)(int16_t *buffer, int byte))
{
static int nullbyte;
@@ -90,7 +90,7 @@ static int16_t *vtech1_fill_wave_byte(int16_t *buffer, int byte)
return buffer;
}
-static int vtech1_cassette_fill_wave(int16_t *buffer, int length, uint8_t *code)
+static int vtech1_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *code, int)
{
return generic_fill_wave(buffer, length, code, V1_BITSAMPLES, V1_BYTESAMPLES, V1_LO, vtech1_fill_wave_byte);
}
@@ -185,7 +185,7 @@ static int16_t *vtech2_fill_wave_byte(int16_t *buffer, int byte)
return buffer;
}
-static int vtech2_cassette_fill_wave(int16_t *buffer, int length, uint8_t *code)
+static int vtech2_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *code, int)
{
return generic_fill_wave(buffer, length, code, VT2_BITSAMPLES, VT2_BYTESAMPLES, VT2_LO, vtech2_fill_wave_byte);
}
diff --git a/src/lib/formats/vt_dsk.cpp b/src/lib/formats/vt_dsk.cpp
index 202ec784187..da7e450b673 100644
--- a/src/lib/formats/vt_dsk.cpp
+++ b/src/lib/formats/vt_dsk.cpp
@@ -21,6 +21,7 @@
void vtech_common_format::wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit)
{
+ buffer.push_back(pos | floppy_image::MG_F);
if(bit) {
pos += 2237;
buffer.push_back(pos | floppy_image::MG_F);
@@ -35,13 +36,13 @@ void vtech_common_format::wbyte(std::vector<uint32_t> &buffer, uint32_t &pos, ui
wbit(buffer, pos, (byte >> i) & 1);
}
-void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, floppy_image &image)
+void vtech_common_format::image_to_flux(const uint8_t *bdata, size_t size, floppy_image &image)
{
static const uint8_t sector_map[16] = {
0x0, 0xb, 0x6, 0x1, 0xc, 0x7, 0x2, 0xd, 0x8, 0x3, 0xe, 0x9, 0x4, 0xf, 0xa, 0x5
};
- for(int track = 0; track != 40; track ++) {
+ for(int track = 0; track != 40; track++) {
uint32_t pos = 0;
std::vector<uint32_t> &buffer = image.get_buffer(track, 0);
buffer.clear();
@@ -49,7 +50,7 @@ void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, flopp
// One window of pad at the start to avoid problems with the write splice
wbit(buffer, pos, 0);
- for(int sector = 0; sector != 16; sector ++) {
+ for(int sector = 0; sector != 16; sector++) {
uint8_t sid = sector_map[sector];
for(int i=0; i != 7; i++)
wbyte(buffer, pos, 0x80);
@@ -69,7 +70,7 @@ void vtech_common_format::image_to_flux(const std::vector<uint8_t> &bdata, flopp
wbyte(buffer, pos, 0xe7);
wbyte(buffer, pos, 0xfe);
uint16_t chk = 0;
- const uint8_t *src = bdata.data() + 16*128*track + 128*sid;
+ const uint8_t *src = &bdata[16*128*track + 128*sid];
for(int i=0; i != 128; i++) {
chk += src[i];
wbyte(buffer, pos, src[i]);
@@ -106,7 +107,7 @@ std::vector<uint8_t> vtech_common_format::flux_to_image(const floppy_image &imag
for(;;) {
int npos = cpos;
for(;;) {
- npos ++;
+ npos++;
if(npos == sz)
npos = 0;
if((buffer[npos] & floppy_image::MG_MASK) == floppy_image::MG_F)
@@ -115,7 +116,11 @@ std::vector<uint8_t> vtech_common_format::flux_to_image(const floppy_image &imag
int dt = (buffer[npos] & floppy_image::TIME_MASK) - (buffer[cpos] & floppy_image::TIME_MASK);
if(dt < 0)
cpos += 200000000;
- bitstream.push_back(dt < 9187 - 143);
+ int t = dt >= 9187 - 143 ? 0 :
+ dt >= 2237 - 143 && dt <= 2237 + 143 ? 1 :
+ 2;
+ if(t <= 1)
+ bitstream.push_back(t);
if(npos <= cpos)
break;
cpos = npos;
@@ -135,7 +140,7 @@ std::vector<uint8_t> vtech_common_format::flux_to_image(const floppy_image &imag
buf = (buf << 1) | bitstream[sz-64+i];
for(;;) {
buf = (buf << 1) | bitstream[pos];
- count ++;
+ count++;
switch(mode) {
case 0: // idle
if(buf == 0x80808000fee718c3)
@@ -219,7 +224,7 @@ const char *vtech_dsk_format::description() const noexcept
const char *vtech_dsk_format::extensions() const noexcept
{
- return "dsk";
+ return "dsk,dvz";
}
int vtech_bin_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
@@ -243,15 +248,15 @@ int vtech_dsk_format::identify(util::random_read &io, uint32_t form_factor, cons
if(size < 256)
return 0;
- std::vector<uint8_t> bdata(size);
- size_t actual;
- io.read_at(0, bdata.data(), size, actual);
+ auto const [err, bdata, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return 0;
// Structurally validate the presence of sector headers and data
int count_sh = 0, count_sd = 0;
uint64_t buf = 0;
- for(uint8_t b : bdata) {
- buf = (buf << 8) | b;
+ for(size_t i = 0; size > i; ++i) {
+ buf = (buf << 8) | bdata[i];
if(buf == 0x80808000fee718c3)
count_sh++;
else if(buf == 0x80808000c318e7fe)
@@ -267,11 +272,11 @@ bool vtech_bin_format::load(util::random_read &io, uint32_t form_factor, const s
if(io.length(size) || (size != 40*16*256))
return false;
- std::vector<uint8_t> bdata(size);
- size_t actual;
- io.read_at(0, bdata.data(), size, actual);
+ auto const [err, bdata, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
- image_to_flux(bdata, image);
+ image_to_flux(bdata.get(), size, image);
image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
return true;
}
@@ -281,9 +286,9 @@ bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const s
uint64_t size;
if(io.length(size))
return false;
- std::vector<uint8_t> bdata(size);
- size_t actual;
- io.read_at(0, bdata.data(), size, actual);
+ auto const [err, bdata, actual] = read_at(io, 0, size);
+ if(err || (actual != size))
+ return false;
std::vector<uint8_t> bdatax(128*16*40, 0);
@@ -293,9 +298,9 @@ bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const s
uint64_t buf = 0;
uint8_t *dest = nullptr;
- for(uint8_t b : bdata) {
- buf = (buf << 8) | b;
- count ++;
+ for(size_t i = 0; size > i; ++i) {
+ buf = (buf << 8) | bdata[i];
+ count++;
switch(mode) {
case 0: // idle
if(buf == 0x80808000fee718c3)
@@ -305,14 +310,14 @@ bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const s
case 1: // sector header
if(count == 3) {
- uint8_t trk = buf >> 16;
- uint8_t sector = buf >> 8;
- uint8_t chk = buf;
+ const uint8_t trk = buf >> 16;
+ const uint8_t sector = buf >> 8;
+ const uint8_t chk = buf;
if(chk != sector + trk) {
mode = 0;
break;
}
- dest = bdatax.data() + 128*16*trk + sector*128;
+ dest = &bdatax[128*16*trk + sector*128];
checksum = 0;
mode = 2;
}
@@ -328,7 +333,7 @@ bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const s
case 3: // sector data
if(count <= 128) {
- uint8_t byte = buf;
+ const uint8_t byte = buf;
checksum += byte;
*dest++ = byte;
@@ -341,7 +346,7 @@ bool vtech_dsk_format::load(util::random_read &io, uint32_t form_factor, const s
}
}
- image_to_flux(bdatax, image);
+ image_to_flux(bdatax.data(), bdatax.size(), image);
image.set_form_variant(floppy_image::FF_525, floppy_image::SSSD);
return true;
}
@@ -354,8 +359,7 @@ bool vtech_bin_format::save(util::random_read_write &io, const std::vector<uint3
return false;
auto bdata = flux_to_image(image);
- size_t actual;
- io.write_at(0, bdata.data(), bdata.size(), actual);
+ /*auto const [err, actual] =*/ write_at(io, 0, bdata.data(), bdata.size()); // FIXME: check for errors
return true;
}
@@ -376,8 +380,8 @@ bool vtech_dsk_format::save(util::random_read_write &io, const std::vector<uint3
};
int pos = 0;
- for(int track = 0; track != 40; track ++) {
- for(int sector = 0; sector != 16; sector ++) {
+ for(int track = 0; track != 40; track++) {
+ for(int sector = 0; sector != 16; sector++) {
uint8_t sid = sector_map[sector];
for(int i=0; i != 7; i++)
bdatax[pos++] = 0x80;
@@ -407,8 +411,7 @@ bool vtech_dsk_format::save(util::random_read_write &io, const std::vector<uint3
}
}
- size_t actual;
- io.write_at(0, bdatax.data(), bdatax.size(), actual);
+ /*auto const [err, actual] =*/ write_at(io, 0, bdatax.data(), bdatax.size()); // FIXME: check for errors
return true;
}
diff --git a/src/lib/formats/vt_dsk.h b/src/lib/formats/vt_dsk.h
index db2687d4108..1348f9dbd4d 100644
--- a/src/lib/formats/vt_dsk.h
+++ b/src/lib/formats/vt_dsk.h
@@ -19,7 +19,7 @@ public:
virtual bool supports_save() const noexcept override { return true; }
protected:
- static void image_to_flux(const std::vector<uint8_t> &bdata, floppy_image &image);
+ static void image_to_flux(const uint8_t *bdata, size_t size, floppy_image &image);
static std::vector<uint8_t> flux_to_image(const floppy_image &image);
static void wbit(std::vector<uint32_t> &buffer, uint32_t &pos, bool bit);
diff --git a/src/lib/formats/wavfile.cpp b/src/lib/formats/wavfile.cpp
index e410c7f9ff9..6cce494f1c8 100644
--- a/src/lib/formats/wavfile.cpp
+++ b/src/lib/formats/wavfile.cpp
@@ -170,7 +170,6 @@ static cassette_image::error wavfile_identify(cassette_image *cassette, cassette
static cassette_image::error wavfile_load(cassette_image *cassette)
{
cassette_image::Options opts;
- memset(&opts, 0, sizeof(opts));
return wavfile_process(cassette, &opts, true);
}
diff --git a/src/lib/formats/wd177x_dsk.cpp b/src/lib/formats/wd177x_dsk.cpp
index c3bba8f7724..e5b02f02e32 100644
--- a/src/lib/formats/wd177x_dsk.cpp
+++ b/src/lib/formats/wd177x_dsk.cpp
@@ -262,8 +262,7 @@ bool wd177x_format::load(util::random_read &io, uint32_t form_factor, const std:
build_sector_description(tf, sectdata, sectors, track, head);
int track_size = compute_track_size(tf);
- size_t actual;
- io.read_at(get_image_offset(f, head, track), sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ read_at(io, get_image_offset(f, head, track), sectdata, track_size); // FIXME: check for errors and premature EOF
generate_track(desc, track, head, sectors, tf.sector_count, total_size, image);
}
@@ -389,8 +388,7 @@ bool wd177x_format::save(util::random_read_write &io, const std::vector<uint32_t
build_sector_description(tf, sectdata, sectors, track, head);
extract_sectors(image, tf, sectors, track, head);
int track_size = compute_track_size(tf);
- size_t actual;
- io.write_at(get_image_offset(f, head, track), sectdata, track_size, actual);
+ /*auto const [err, actual] =*/ write_at(io, get_image_offset(f, head, track), sectdata, track_size); // FIXME: check for errors
}
}
diff --git a/src/lib/formats/x07_cas.cpp b/src/lib/formats/x07_cas.cpp
index 71e8b304efc..945e1ee5c1a 100644
--- a/src/lib/formats/x07_cas.cpp
+++ b/src/lib/formats/x07_cas.cpp
@@ -122,7 +122,7 @@ static int x07_handle_cassette(int16_t *buffer, const uint8_t *bytes)
Generate samples for the tape image
********************************************************************/
-static int x07_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int x07_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
return x07_handle_cassette(buffer, bytes);
}
diff --git a/src/lib/formats/x1_tap.cpp b/src/lib/formats/x1_tap.cpp
index 1a60bb18330..f730fe9fb21 100644
--- a/src/lib/formats/x1_tap.cpp
+++ b/src/lib/formats/x1_tap.cpp
@@ -101,7 +101,7 @@ static int x1_cas_to_wav_size (const uint8_t *casdata, int caslen)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int x1_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int x1_cas_fill_wave(int16_t *buffer, int sample_count, const uint8_t *bytes, int)
{
return x1_handle_tap(buffer,bytes);
}
diff --git a/src/lib/formats/zx81_p.cpp b/src/lib/formats/zx81_p.cpp
index e31b5f58933..515f5b78581 100644
--- a/src/lib/formats/zx81_p.cpp
+++ b/src/lib/formats/zx81_p.cpp
@@ -173,7 +173,7 @@ static int zx81_cassette_calculate_size_in_samples(const uint8_t *bytes, int len
return (number_of_0_data+number_of_0_name)*ZX81_LOW_BIT_LENGTH + (number_of_1_data+number_of_1_name)*ZX81_HIGH_BIT_LENGTH + ZX81_PILOT_LENGTH;
}
-static int zx81_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int zx81_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
int16_t * p = buffer;
int i;
@@ -250,7 +250,7 @@ static int zx80_cassette_calculate_size_in_samples(const uint8_t *bytes, int len
return number_of_0_data*ZX81_LOW_BIT_LENGTH + number_of_1_data*ZX81_HIGH_BIT_LENGTH + ZX81_PILOT_LENGTH;
}
-static int zx80_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
+static int zx80_cassette_fill_wave(int16_t *buffer, int length, const uint8_t *bytes, int)
{
int16_t * p = buffer;
int i;
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 077b72b028f..2a63e816c0a 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -146,13 +146,12 @@ OBJDIRS = $(OBJ) \
$(OBJ)/solver \
$(OBJ)/devices \
$(OBJ)/plib \
- $(OBJ)/devices \
$(OBJ)/macro \
$(OBJ)/macro/modules \
$(OBJ)/tests \
$(OBJ)/tools \
$(OBJ)/prg \
- $(OBJ)/generated \
+ $(OBJ)/generated
MODULESOURCES += $(wildcard $(SRC)/macro/modules/*.cpp)
DEVSOURCES = $(SRC)/solver/nld_solver.cpp
@@ -171,7 +170,7 @@ CORESOURCES := \
$(SRC)/nl_setup.cpp \
$(SRC)/nl_factory.cpp \
$(SRC)/tools/nl_convert.cpp \
- $(SRC)/generated/static_solvers.cpp \
+ $(SRC)/generated/static_solvers.cpp
MAINSOURCES = $(SRC)/prg/nltool.cpp $(SRC)/prg/nlwav.cpp
@@ -196,7 +195,7 @@ PSOURCES := \
$(PSRC)/ppmf.cpp \
$(PSRC)/ppreprocessor.cpp \
$(PSRC)/ptokenizer.cpp \
- $(PSRC)/putil.cpp \
+ $(PSRC)/putil.cpp
NLOBJS = $(patsubst $(SRC)%, $(OBJ)%, $(CORESOURCES:.cpp=.o))
NLDEVOBJS = $(patsubst $(SRC)%, $(OBJ)%, $(DEVSOURCES:.cpp=.o))
@@ -213,7 +212,7 @@ VSFILES = \
$(VSBUILD)/nltool.vcxproj.filters \
$(VSBUILD)/nlwav.vcxproj \
$(VSBUILD)/nlwav.vcxproj.filters \
- $(VSBUILD)/netlist.sln \
+ $(VSBUILD)/netlist.sln
OTHERFILES = makefile
@@ -223,7 +222,7 @@ DOCS = \
$(DOC)/mainpage.dox.h \
$(DOC)/primer_1.dox.h \
$(DOC)/structure.dox.h \
- $(DOC)/test1-50r.svg \
+ $(DOC)/test1-50r.svg
ALL_OBJS = $(OBJS) $(MAINOBJS)
diff --git a/src/lib/netlist/generated/static_solvers.cpp b/src/lib/netlist/generated/static_solvers.cpp
index ff615be2670..8f01960ce72 100644
--- a/src/lib/netlist/generated/static_solvers.cpp
+++ b/src/lib/netlist/generated/static_solvers.cpp
@@ -542,2340 +542,6 @@ static void nl_gcr_90_double_double_ce766957cb26ff3e(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// 280zzzap,sspeedr
-static void nl_gcr_113_double_double_ab9144d965a37e4(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- double m_A13(0.0);
- double m_A14(0.0);
- double m_A15(0.0);
- double m_A16(0.0);
- double m_A17(0.0);
- double m_A18(0.0);
- double m_A19(0.0);
- double m_A20(0.0);
- double m_A21(0.0);
- double m_A22(0.0);
- double m_A23(0.0);
- double m_A24(0.0);
- double m_A25(0.0);
- double m_A26(0.0);
- double m_A27(0.0);
- double m_A28(0.0);
- double m_A29(0.0);
- double m_A30(0.0);
- double m_A31(0.0);
- double m_A32(0.0);
- double m_A33(0.0);
- double m_A34(0.0);
- double m_A35(0.0);
- double m_A36(0.0);
- double m_A37(0.0);
- double m_A38(0.0);
- double m_A39(0.0);
- double m_A40(0.0);
- double m_A41(0.0);
- double m_A42(0.0);
- double m_A43(0.0);
- double m_A44(0.0);
- double m_A45(0.0);
- double m_A46(0.0);
- double m_A47(0.0);
- double m_A48(0.0);
- double m_A49(0.0);
- double m_A50(0.0);
- double m_A51(0.0);
- double m_A52(0.0);
- double m_A53(0.0);
- double m_A54(0.0);
- double m_A55(0.0);
- double m_A56(0.0);
- double m_A57(0.0);
- double m_A58(0.0);
- double m_A59(0.0);
- double m_A60(0.0);
- double m_A61(0.0);
- double m_A62(0.0);
- double m_A63(0.0);
- double m_A64(0.0);
- double m_A65(0.0);
- double m_A66(0.0);
- double m_A67(0.0);
- double m_A68(0.0);
- double m_A69(0.0);
- double m_A70(0.0);
- double m_A71(0.0);
- double m_A72(0.0);
- double m_A73(0.0);
- double m_A74(0.0);
- double m_A75(0.0);
- double m_A76(0.0);
- double m_A77(0.0);
- double m_A78(0.0);
- double m_A79(0.0);
- double m_A80(0.0);
- double m_A81(0.0);
- double m_A82(0.0);
- double m_A83(0.0);
- double m_A84(0.0);
- double m_A85(0.0);
- double m_A86(0.0);
- double m_A87(0.0);
- double m_A88(0.0);
- double m_A89(0.0);
- double m_A90(0.0);
- double m_A91(0.0);
- double m_A92(0.0);
- double m_A93(0.0);
- double m_A94(0.0);
- double m_A95(0.0);
- double m_A96(0.0);
- double m_A97(0.0);
- double m_A98(0.0);
- double m_A99(0.0);
- double m_A100(0.0);
- double m_A101(0.0);
- double m_A102(0.0);
- double m_A103(0.0);
- double m_A104(0.0);
- double m_A105(0.0);
- double m_A106(0.0);
- double m_A107(0.0);
- double m_A108(0.0);
- double m_A109(0.0);
- double m_A110(0.0);
- double m_A111(0.0);
- double m_A112(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A2 += gt[5];
- m_A5 += go[2];
- m_A4 += go[3];
- m_A3 += go[4];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 += Idr[4];
- RHS1 += Idr[5];
- RHS1 -= go[5] * *cnV[5];
- m_A6 += gt[6];
- m_A6 += gt[7];
- m_A7 += go[6];
- double RHS2 = Idr[6];
- RHS2 += Idr[7];
- RHS2 -= go[7] * *cnV[7];
- m_A8 += gt[8];
- m_A8 += gt[9];
- m_A9 += go[8];
- double RHS3 = Idr[8];
- RHS3 += Idr[9];
- RHS3 -= go[9] * *cnV[9];
- m_A10 += gt[10];
- m_A10 += gt[11];
- m_A10 += gt[12];
- m_A11 += go[10];
- m_A12 += go[11];
- double RHS4 = Idr[10];
- RHS4 += Idr[11];
- RHS4 += Idr[12];
- RHS4 -= go[12] * *cnV[12];
- m_A13 += gt[13];
- m_A13 += gt[14];
- m_A14 += go[13];
- double RHS5 = Idr[13];
- RHS5 += Idr[14];
- RHS5 -= go[14] * *cnV[14];
- m_A15 += gt[15];
- m_A15 += gt[16];
- m_A15 += gt[17];
- m_A15 += gt[18];
- m_A15 += gt[19];
- m_A15 += gt[20];
- m_A15 += gt[21];
- m_A18 += go[15];
- m_A19 += go[16];
- m_A17 += go[17];
- m_A16 += go[18];
- double RHS6 = Idr[15];
- RHS6 += Idr[16];
- RHS6 += Idr[17];
- RHS6 += Idr[18];
- RHS6 += Idr[19];
- RHS6 += Idr[20];
- RHS6 += Idr[21];
- RHS6 -= go[19] * *cnV[19];
- RHS6 -= go[20] * *cnV[20];
- RHS6 -= go[21] * *cnV[21];
- m_A20 += gt[22];
- m_A20 += gt[23];
- m_A20 += gt[24];
- m_A20 += gt[25];
- m_A20 += gt[26];
- m_A20 += gt[27];
- m_A20 += gt[28];
- m_A23 += go[22];
- m_A24 += go[23];
- m_A22 += go[24];
- m_A21 += go[25];
- double RHS7 = Idr[22];
- RHS7 += Idr[23];
- RHS7 += Idr[24];
- RHS7 += Idr[25];
- RHS7 += Idr[26];
- RHS7 += Idr[27];
- RHS7 += Idr[28];
- RHS7 -= go[26] * *cnV[26];
- RHS7 -= go[27] * *cnV[27];
- RHS7 -= go[28] * *cnV[28];
- m_A25 += gt[29];
- m_A25 += gt[30];
- m_A25 += gt[31];
- m_A26 += go[29];
- m_A27 += go[30];
- double RHS8 = Idr[29];
- RHS8 += Idr[30];
- RHS8 += Idr[31];
- RHS8 -= go[31] * *cnV[31];
- m_A28 += gt[32];
- m_A28 += gt[33];
- m_A29 += go[32];
- double RHS9 = Idr[32];
- RHS9 += Idr[33];
- RHS9 -= go[33] * *cnV[33];
- m_A30 += gt[34];
- m_A30 += gt[35];
- m_A30 += gt[36];
- m_A30 += gt[37];
- m_A31 += go[34];
- double RHS10 = Idr[34];
- RHS10 += Idr[35];
- RHS10 += Idr[36];
- RHS10 += Idr[37];
- RHS10 -= go[35] * *cnV[35];
- RHS10 -= go[36] * *cnV[36];
- RHS10 -= go[37] * *cnV[37];
- m_A32 += gt[38];
- m_A32 += gt[39];
- m_A33 += go[38];
- double RHS11 = Idr[38];
- RHS11 += Idr[39];
- RHS11 -= go[39] * *cnV[39];
- m_A36 += gt[40];
- m_A36 += gt[41];
- m_A36 += gt[42];
- m_A36 += gt[43];
- m_A35 += go[40];
- m_A34 += go[41];
- double RHS12 = Idr[40];
- RHS12 += Idr[41];
- RHS12 += Idr[42];
- RHS12 += Idr[43];
- RHS12 -= go[42] * *cnV[42];
- RHS12 -= go[43] * *cnV[43];
- m_A42 += gt[44];
- m_A42 += gt[45];
- m_A42 += gt[46];
- m_A42 += gt[47];
- m_A40 += go[44];
- m_A39 += go[45];
- double RHS13 = Idr[44];
- RHS13 += Idr[45];
- RHS13 += Idr[46];
- RHS13 += Idr[47];
- RHS13 -= go[46] * *cnV[46];
- RHS13 -= go[47] * *cnV[47];
- m_A51 += gt[48];
- m_A51 += gt[49];
- m_A51 += gt[50];
- m_A51 += gt[51];
- m_A53 += go[48];
- m_A48 += go[49];
- m_A47 += go[50];
- double RHS14 = Idr[48];
- RHS14 += Idr[49];
- RHS14 += Idr[50];
- RHS14 += Idr[51];
- RHS14 -= go[51] * *cnV[51];
- m_A57 += gt[52];
- m_A57 += gt[53];
- m_A57 += gt[54];
- m_A56 += go[52];
- m_A58 += go[53];
- double RHS15 = Idr[52];
- RHS15 += Idr[53];
- RHS15 += Idr[54];
- RHS15 -= go[54] * *cnV[54];
- m_A60 += gt[55];
- m_A60 += gt[56];
- m_A60 += gt[57];
- m_A60 += gt[58];
- m_A59 += go[55];
- m_A61 += go[56];
- double RHS16 = Idr[55];
- RHS16 += Idr[56];
- RHS16 += Idr[57];
- RHS16 += Idr[58];
- RHS16 -= go[57] * *cnV[57];
- RHS16 -= go[58] * *cnV[58];
- m_A67 += gt[59];
- m_A67 += gt[60];
- m_A67 += gt[61];
- m_A67 += gt[62];
- m_A67 += gt[63];
- m_A67 += gt[64];
- m_A70 += go[59];
- m_A64 += go[60];
- m_A63 += go[61];
- m_A62 += go[62];
- m_A69 += go[63];
- double RHS17 = Idr[59];
- RHS17 += Idr[60];
- RHS17 += Idr[61];
- RHS17 += Idr[62];
- RHS17 += Idr[63];
- RHS17 += Idr[64];
- RHS17 -= go[64] * *cnV[64];
- m_A74 += gt[65];
- m_A74 += gt[66];
- m_A74 += gt[67];
- m_A74 += gt[68];
- m_A73 += go[65];
- m_A72 += go[66];
- m_A75 += go[67];
- double RHS18 = Idr[65];
- RHS18 += Idr[66];
- RHS18 += Idr[67];
- RHS18 += Idr[68];
- RHS18 -= go[68] * *cnV[68];
- m_A80 += gt[69];
- m_A80 += gt[70];
- m_A80 += gt[71];
- m_A80 += gt[72];
- m_A80 += gt[73];
- m_A77 += go[69];
- m_A78 += go[70];
- m_A76 += go[71];
- double RHS19 = Idr[69];
- RHS19 += Idr[70];
- RHS19 += Idr[71];
- RHS19 += Idr[72];
- RHS19 += Idr[73];
- RHS19 -= go[72] * *cnV[72];
- RHS19 -= go[73] * *cnV[73];
- m_A89 += gt[74];
- m_A89 += gt[75];
- m_A89 += gt[76];
- m_A89 += gt[77];
- m_A84 += go[74];
- m_A85 += go[75];
- m_A87 += go[76];
- m_A86 += go[77];
- double RHS20 = Idr[74];
- RHS20 += Idr[75];
- RHS20 += Idr[76];
- RHS20 += Idr[77];
- m_A100 += gt[78];
- m_A100 += gt[79];
- m_A100 += gt[80];
- m_A100 += gt[81];
- m_A100 += gt[82];
- m_A100 += gt[83];
- m_A100 += gt[84];
- m_A96 += go[78];
- m_A93 += go[79];
- m_A101 += go[80];
- m_A92 += go[81];
- m_A97 += go[82];
- double RHS21 = Idr[78];
- RHS21 += Idr[79];
- RHS21 += Idr[80];
- RHS21 += Idr[81];
- RHS21 += Idr[82];
- RHS21 += Idr[83];
- RHS21 += Idr[84];
- RHS21 -= go[83] * *cnV[83];
- RHS21 -= go[84] * *cnV[84];
- m_A112 += gt[85];
- m_A112 += gt[86];
- m_A112 += gt[87];
- m_A112 += gt[88];
- m_A112 += gt[89];
- m_A112 += gt[90];
- m_A108 += go[85];
- m_A111 += go[86];
- m_A103 += go[87];
- m_A104 += go[88];
- m_A102 += go[89];
- double RHS22 = Idr[85];
- RHS22 += Idr[86];
- RHS22 += Idr[87];
- RHS22 += Idr[88];
- RHS22 += Idr[89];
- RHS22 += Idr[90];
- RHS22 -= go[90] * *cnV[90];
- const double f0 = 1.0 / m_A0;
- const double f0_12 = -f0 * m_A34;
- m_A36 += m_A1 * f0_12;
- RHS12 += f0_12 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_12 = -f1 * m_A35;
- m_A36 += m_A3 * f1_12;
- m_A37 += m_A4 * f1_12;
- m_A38 += m_A5 * f1_12;
- RHS12 += f1_12 * RHS1;
- const double f1_13 = -f1 * m_A39;
- m_A41 += m_A3 * f1_13;
- m_A42 += m_A4 * f1_13;
- m_A43 += m_A5 * f1_13;
- RHS13 += f1_13 * RHS1;
- const double f1_14 = -f1 * m_A47;
- m_A49 += m_A3 * f1_14;
- m_A50 += m_A4 * f1_14;
- m_A51 += m_A5 * f1_14;
- RHS14 += f1_14 * RHS1;
- const double f2 = 1.0 / m_A6;
- const double f2_15 = -f2 * m_A56;
- m_A57 += m_A7 * f2_15;
- RHS15 += f2_15 * RHS2;
- const double f3 = 1.0 / m_A8;
- const double f3_20 = -f3 * m_A84;
- m_A89 += m_A9 * f3_20;
- RHS20 += f3_20 * RHS3;
- const double f4 = 1.0 / m_A10;
- const double f4_17 = -f4 * m_A62;
- m_A67 += m_A11 * f4_17;
- m_A69 += m_A12 * f4_17;
- RHS17 += f4_17 * RHS4;
- const double f4_20 = -f4 * m_A85;
- m_A87 += m_A11 * f4_20;
- m_A89 += m_A12 * f4_20;
- RHS20 += f4_20 * RHS4;
- const double f5 = 1.0 / m_A13;
- const double f5_16 = -f5 * m_A59;
- m_A60 += m_A14 * f5_16;
- RHS16 += f5_16 * RHS5;
- const double f6 = 1.0 / m_A15;
- const double f6_13 = -f6 * m_A40;
- m_A42 += m_A16 * f6_13;
- m_A44 += m_A17 * f6_13;
- m_A45 += m_A18 * f6_13;
- m_A46 += m_A19 * f6_13;
- RHS13 += f6_13 * RHS6;
- const double f6_17 = -f6 * m_A63;
- m_A65 += m_A16 * f6_17;
- m_A67 += m_A17 * f6_17;
- m_A70 += m_A18 * f6_17;
- m_A71 += m_A19 * f6_17;
- RHS17 += f6_17 * RHS6;
- const double f6_21 = -f6 * m_A92;
- m_A94 += m_A16 * f6_21;
- m_A97 += m_A17 * f6_21;
- m_A100 += m_A18 * f6_21;
- m_A101 += m_A19 * f6_21;
- RHS21 += f6_21 * RHS6;
- const double f6_22 = -f6 * m_A102;
- m_A105 += m_A16 * f6_22;
- m_A107 += m_A17 * f6_22;
- m_A111 += m_A18 * f6_22;
- m_A112 += m_A19 * f6_22;
- RHS22 += f6_22 * RHS6;
- const double f7 = 1.0 / m_A20;
- const double f7_14 = -f7 * m_A48;
- m_A51 += m_A21 * f7_14;
- m_A52 += m_A22 * f7_14;
- m_A54 += m_A23 * f7_14;
- m_A55 += m_A24 * f7_14;
- RHS14 += f7_14 * RHS7;
- const double f7_17 = -f7 * m_A64;
- m_A66 += m_A21 * f7_17;
- m_A67 += m_A22 * f7_17;
- m_A70 += m_A23 * f7_17;
- m_A71 += m_A24 * f7_17;
- RHS17 += f7_17 * RHS7;
- const double f7_21 = -f7 * m_A93;
- m_A95 += m_A21 * f7_21;
- m_A97 += m_A22 * f7_21;
- m_A100 += m_A23 * f7_21;
- m_A101 += m_A24 * f7_21;
- RHS21 += f7_21 * RHS7;
- const double f7_22 = -f7 * m_A103;
- m_A106 += m_A21 * f7_22;
- m_A107 += m_A22 * f7_22;
- m_A111 += m_A23 * f7_22;
- m_A112 += m_A24 * f7_22;
- RHS22 += f7_22 * RHS7;
- const double f8 = 1.0 / m_A25;
- const double f8_18 = -f8 * m_A72;
- m_A74 += m_A26 * f8_18;
- m_A75 += m_A27 * f8_18;
- RHS18 += f8_18 * RHS8;
- const double f8_22 = -f8 * m_A104;
- m_A108 += m_A26 * f8_22;
- m_A112 += m_A27 * f8_22;
- RHS22 += f8_22 * RHS8;
- const double f9 = 1.0 / m_A28;
- const double f9_18 = -f9 * m_A73;
- m_A74 += m_A29 * f9_18;
- RHS18 += f9_18 * RHS9;
- const double f10 = 1.0 / m_A30;
- const double f10_19 = -f10 * m_A76;
- m_A80 += m_A31 * f10_19;
- RHS19 += f10_19 * RHS10;
- const double f11 = 1.0 / m_A32;
- const double f11_19 = -f11 * m_A77;
- m_A80 += m_A33 * f11_19;
- RHS19 += f11_19 * RHS11;
- const double f12 = 1.0 / m_A36;
- const double f12_13 = -f12 * m_A41;
- m_A42 += m_A37 * f12_13;
- m_A43 += m_A38 * f12_13;
- RHS13 += f12_13 * RHS12;
- const double f12_14 = -f12 * m_A49;
- m_A50 += m_A37 * f12_14;
- m_A51 += m_A38 * f12_14;
- RHS14 += f12_14 * RHS12;
- const double f13 = 1.0 / m_A42;
- const double f13_14 = -f13 * m_A50;
- m_A51 += m_A43 * f13_14;
- m_A52 += m_A44 * f13_14;
- m_A54 += m_A45 * f13_14;
- m_A55 += m_A46 * f13_14;
- RHS14 += f13_14 * RHS13;
- const double f13_17 = -f13 * m_A65;
- m_A66 += m_A43 * f13_17;
- m_A67 += m_A44 * f13_17;
- m_A70 += m_A45 * f13_17;
- m_A71 += m_A46 * f13_17;
- RHS17 += f13_17 * RHS13;
- const double f13_21 = -f13 * m_A94;
- m_A95 += m_A43 * f13_21;
- m_A97 += m_A44 * f13_21;
- m_A100 += m_A45 * f13_21;
- m_A101 += m_A46 * f13_21;
- RHS21 += f13_21 * RHS13;
- const double f13_22 = -f13 * m_A105;
- m_A106 += m_A43 * f13_22;
- m_A107 += m_A44 * f13_22;
- m_A111 += m_A45 * f13_22;
- m_A112 += m_A46 * f13_22;
- RHS22 += f13_22 * RHS13;
- const double f14 = 1.0 / m_A51;
- const double f14_17 = -f14 * m_A66;
- m_A67 += m_A52 * f14_17;
- m_A68 += m_A53 * f14_17;
- m_A70 += m_A54 * f14_17;
- m_A71 += m_A55 * f14_17;
- RHS17 += f14_17 * RHS14;
- const double f14_19 = -f14 * m_A78;
- m_A79 += m_A52 * f14_19;
- m_A80 += m_A53 * f14_19;
- m_A82 += m_A54 * f14_19;
- m_A83 += m_A55 * f14_19;
- RHS19 += f14_19 * RHS14;
- const double f14_21 = -f14 * m_A95;
- m_A97 += m_A52 * f14_21;
- m_A98 += m_A53 * f14_21;
- m_A100 += m_A54 * f14_21;
- m_A101 += m_A55 * f14_21;
- RHS21 += f14_21 * RHS14;
- const double f14_22 = -f14 * m_A106;
- m_A107 += m_A52 * f14_22;
- m_A109 += m_A53 * f14_22;
- m_A111 += m_A54 * f14_22;
- m_A112 += m_A55 * f14_22;
- RHS22 += f14_22 * RHS14;
- const double f15 = 1.0 / m_A57;
- const double f15_20 = -f15 * m_A86;
- m_A89 += m_A58 * f15_20;
- RHS20 += f15_20 * RHS15;
- const double f16 = 1.0 / m_A60;
- const double f16_21 = -f16 * m_A96;
- m_A100 += m_A61 * f16_21;
- RHS21 += f16_21 * RHS16;
- const double f17 = 1.0 / m_A67;
- const double f17_19 = -f17 * m_A79;
- m_A80 += m_A68 * f17_19;
- m_A81 += m_A69 * f17_19;
- m_A82 += m_A70 * f17_19;
- m_A83 += m_A71 * f17_19;
- RHS19 += f17_19 * RHS17;
- const double f17_20 = -f17 * m_A87;
- m_A88 += m_A68 * f17_20;
- m_A89 += m_A69 * f17_20;
- m_A90 += m_A70 * f17_20;
- m_A91 += m_A71 * f17_20;
- RHS20 += f17_20 * RHS17;
- const double f17_21 = -f17 * m_A97;
- m_A98 += m_A68 * f17_21;
- m_A99 += m_A69 * f17_21;
- m_A100 += m_A70 * f17_21;
- m_A101 += m_A71 * f17_21;
- RHS21 += f17_21 * RHS17;
- const double f17_22 = -f17 * m_A107;
- m_A109 += m_A68 * f17_22;
- m_A110 += m_A69 * f17_22;
- m_A111 += m_A70 * f17_22;
- m_A112 += m_A71 * f17_22;
- RHS22 += f17_22 * RHS17;
- const double f18 = 1.0 / m_A74;
- const double f18_22 = -f18 * m_A108;
- m_A112 += m_A75 * f18_22;
- RHS22 += f18_22 * RHS18;
- const double f19 = 1.0 / m_A80;
- const double f19_20 = -f19 * m_A88;
- m_A89 += m_A81 * f19_20;
- m_A90 += m_A82 * f19_20;
- m_A91 += m_A83 * f19_20;
- RHS20 += f19_20 * RHS19;
- const double f19_21 = -f19 * m_A98;
- m_A99 += m_A81 * f19_21;
- m_A100 += m_A82 * f19_21;
- m_A101 += m_A83 * f19_21;
- RHS21 += f19_21 * RHS19;
- const double f19_22 = -f19 * m_A109;
- m_A110 += m_A81 * f19_22;
- m_A111 += m_A82 * f19_22;
- m_A112 += m_A83 * f19_22;
- RHS22 += f19_22 * RHS19;
- const double f20 = 1.0 / m_A89;
- const double f20_21 = -f20 * m_A99;
- m_A100 += m_A90 * f20_21;
- m_A101 += m_A91 * f20_21;
- RHS21 += f20_21 * RHS20;
- const double f20_22 = -f20 * m_A110;
- m_A111 += m_A90 * f20_22;
- m_A112 += m_A91 * f20_22;
- RHS22 += f20_22 * RHS20;
- const double f21 = 1.0 / m_A100;
- const double f21_22 = -f21 * m_A111;
- m_A112 += m_A101 * f21_22;
- RHS22 += f21_22 * RHS21;
- V[22] = RHS22 / m_A112;
- double tmp21 = 0.0;
- tmp21 += m_A101 * V[22];
- V[21] = (RHS21 - tmp21) / m_A100;
- double tmp20 = 0.0;
- tmp20 += m_A90 * V[21];
- tmp20 += m_A91 * V[22];
- V[20] = (RHS20 - tmp20) / m_A89;
- double tmp19 = 0.0;
- tmp19 += m_A81 * V[20];
- tmp19 += m_A82 * V[21];
- tmp19 += m_A83 * V[22];
- V[19] = (RHS19 - tmp19) / m_A80;
- double tmp18 = 0.0;
- tmp18 += m_A75 * V[22];
- V[18] = (RHS18 - tmp18) / m_A74;
- double tmp17 = 0.0;
- tmp17 += m_A68 * V[19];
- tmp17 += m_A69 * V[20];
- tmp17 += m_A70 * V[21];
- tmp17 += m_A71 * V[22];
- V[17] = (RHS17 - tmp17) / m_A67;
- double tmp16 = 0.0;
- tmp16 += m_A61 * V[21];
- V[16] = (RHS16 - tmp16) / m_A60;
- double tmp15 = 0.0;
- tmp15 += m_A58 * V[20];
- V[15] = (RHS15 - tmp15) / m_A57;
- double tmp14 = 0.0;
- tmp14 += m_A52 * V[17];
- tmp14 += m_A53 * V[19];
- tmp14 += m_A54 * V[21];
- tmp14 += m_A55 * V[22];
- V[14] = (RHS14 - tmp14) / m_A51;
- double tmp13 = 0.0;
- tmp13 += m_A43 * V[14];
- tmp13 += m_A44 * V[17];
- tmp13 += m_A45 * V[21];
- tmp13 += m_A46 * V[22];
- V[13] = (RHS13 - tmp13) / m_A42;
- double tmp12 = 0.0;
- tmp12 += m_A37 * V[13];
- tmp12 += m_A38 * V[14];
- V[12] = (RHS12 - tmp12) / m_A36;
- double tmp11 = 0.0;
- tmp11 += m_A33 * V[19];
- V[11] = (RHS11 - tmp11) / m_A32;
- double tmp10 = 0.0;
- tmp10 += m_A31 * V[19];
- V[10] = (RHS10 - tmp10) / m_A30;
- double tmp9 = 0.0;
- tmp9 += m_A29 * V[18];
- V[9] = (RHS9 - tmp9) / m_A28;
- double tmp8 = 0.0;
- tmp8 += m_A26 * V[18];
- tmp8 += m_A27 * V[22];
- V[8] = (RHS8 - tmp8) / m_A25;
- double tmp7 = 0.0;
- tmp7 += m_A21 * V[14];
- tmp7 += m_A22 * V[17];
- tmp7 += m_A23 * V[21];
- tmp7 += m_A24 * V[22];
- V[7] = (RHS7 - tmp7) / m_A20;
- double tmp6 = 0.0;
- tmp6 += m_A16 * V[13];
- tmp6 += m_A17 * V[17];
- tmp6 += m_A18 * V[21];
- tmp6 += m_A19 * V[22];
- V[6] = (RHS6 - tmp6) / m_A15;
- double tmp5 = 0.0;
- tmp5 += m_A14 * V[16];
- V[5] = (RHS5 - tmp5) / m_A13;
- double tmp4 = 0.0;
- tmp4 += m_A11 * V[17];
- tmp4 += m_A12 * V[20];
- V[4] = (RHS4 - tmp4) / m_A10;
- double tmp3 = 0.0;
- tmp3 += m_A9 * V[20];
- V[3] = (RHS3 - tmp3) / m_A8;
- double tmp2 = 0.0;
- tmp2 += m_A7 * V[15];
- V[2] = (RHS2 - tmp2) / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[12];
- tmp1 += m_A4 * V[13];
- tmp1 += m_A5 * V[14];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[12];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
-// 280zzzap,sspeedr
-static void nl_gcr_122_double_double_42c57d523cac30d0(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- double m_A13(0.0);
- double m_A14(0.0);
- double m_A15(0.0);
- double m_A16(0.0);
- double m_A17(0.0);
- double m_A18(0.0);
- double m_A19(0.0);
- double m_A20(0.0);
- double m_A21(0.0);
- double m_A22(0.0);
- double m_A23(0.0);
- double m_A24(0.0);
- double m_A25(0.0);
- double m_A26(0.0);
- double m_A27(0.0);
- double m_A28(0.0);
- double m_A29(0.0);
- double m_A30(0.0);
- double m_A31(0.0);
- double m_A32(0.0);
- double m_A33(0.0);
- double m_A34(0.0);
- double m_A35(0.0);
- double m_A36(0.0);
- double m_A37(0.0);
- double m_A38(0.0);
- double m_A39(0.0);
- double m_A40(0.0);
- double m_A41(0.0);
- double m_A42(0.0);
- double m_A43(0.0);
- double m_A44(0.0);
- double m_A45(0.0);
- double m_A46(0.0);
- double m_A47(0.0);
- double m_A48(0.0);
- double m_A49(0.0);
- double m_A50(0.0);
- double m_A51(0.0);
- double m_A52(0.0);
- double m_A53(0.0);
- double m_A54(0.0);
- double m_A55(0.0);
- double m_A56(0.0);
- double m_A57(0.0);
- double m_A58(0.0);
- double m_A59(0.0);
- double m_A60(0.0);
- double m_A61(0.0);
- double m_A62(0.0);
- double m_A63(0.0);
- double m_A64(0.0);
- double m_A65(0.0);
- double m_A66(0.0);
- double m_A67(0.0);
- double m_A68(0.0);
- double m_A69(0.0);
- double m_A70(0.0);
- double m_A71(0.0);
- double m_A72(0.0);
- double m_A73(0.0);
- double m_A74(0.0);
- double m_A75(0.0);
- double m_A76(0.0);
- double m_A77(0.0);
- double m_A78(0.0);
- double m_A79(0.0);
- double m_A80(0.0);
- double m_A81(0.0);
- double m_A82(0.0);
- double m_A83(0.0);
- double m_A84(0.0);
- double m_A85(0.0);
- double m_A86(0.0);
- double m_A87(0.0);
- double m_A88(0.0);
- double m_A89(0.0);
- double m_A90(0.0);
- double m_A91(0.0);
- double m_A92(0.0);
- double m_A93(0.0);
- double m_A94(0.0);
- double m_A95(0.0);
- double m_A96(0.0);
- double m_A97(0.0);
- double m_A98(0.0);
- double m_A99(0.0);
- double m_A100(0.0);
- double m_A101(0.0);
- double m_A102(0.0);
- double m_A103(0.0);
- double m_A104(0.0);
- double m_A105(0.0);
- double m_A106(0.0);
- double m_A107(0.0);
- double m_A108(0.0);
- double m_A109(0.0);
- double m_A110(0.0);
- double m_A111(0.0);
- double m_A112(0.0);
- double m_A113(0.0);
- double m_A114(0.0);
- double m_A115(0.0);
- double m_A116(0.0);
- double m_A117(0.0);
- double m_A118(0.0);
- double m_A119(0.0);
- double m_A120(0.0);
- double m_A121(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A3 += go[2];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 -= go[3] * *cnV[3];
- m_A4 += gt[4];
- m_A4 += gt[5];
- m_A4 += gt[6];
- m_A5 += go[4];
- double RHS2 = Idr[4];
- RHS2 += Idr[5];
- RHS2 += Idr[6];
- RHS2 -= go[5] * *cnV[5];
- RHS2 -= go[6] * *cnV[6];
- m_A6 += gt[7];
- m_A6 += gt[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A6 += gt[11];
- m_A6 += gt[12];
- m_A6 += gt[13];
- m_A7 += go[7];
- double RHS3 = Idr[7];
- RHS3 += Idr[8];
- RHS3 += Idr[9];
- RHS3 += Idr[10];
- RHS3 += Idr[11];
- RHS3 += Idr[12];
- RHS3 += Idr[13];
- RHS3 -= go[8] * *cnV[8];
- RHS3 -= go[9] * *cnV[9];
- RHS3 -= go[10] * *cnV[10];
- RHS3 -= go[11] * *cnV[11];
- RHS3 -= go[12] * *cnV[12];
- RHS3 -= go[13] * *cnV[13];
- m_A8 += gt[14];
- m_A8 += gt[15];
- m_A9 += go[14];
- double RHS4 = Idr[14];
- RHS4 += Idr[15];
- RHS4 -= go[15] * *cnV[15];
- m_A10 += gt[16];
- m_A10 += gt[17];
- m_A10 += gt[18];
- m_A10 += gt[19];
- m_A12 += go[16];
- m_A13 += go[17];
- m_A11 += go[18];
- double RHS5 = Idr[16];
- RHS5 += Idr[17];
- RHS5 += Idr[18];
- RHS5 += Idr[19];
- RHS5 -= go[19] * *cnV[19];
- m_A14 += gt[20];
- m_A14 += gt[21];
- m_A14 += gt[22];
- m_A14 += gt[23];
- m_A14 += gt[24];
- m_A14 += gt[25];
- m_A14 += gt[26];
- m_A15 += go[20];
- double RHS6 = Idr[20];
- RHS6 += Idr[21];
- RHS6 += Idr[22];
- RHS6 += Idr[23];
- RHS6 += Idr[24];
- RHS6 += Idr[25];
- RHS6 += Idr[26];
- RHS6 -= go[21] * *cnV[21];
- RHS6 -= go[22] * *cnV[22];
- RHS6 -= go[23] * *cnV[23];
- RHS6 -= go[24] * *cnV[24];
- RHS6 -= go[25] * *cnV[25];
- RHS6 -= go[26] * *cnV[26];
- m_A16 += gt[27];
- m_A16 += gt[28];
- m_A18 += go[27];
- m_A17 += go[28];
- double RHS7 = Idr[27];
- RHS7 += Idr[28];
- m_A19 += gt[29];
- m_A19 += gt[30];
- m_A19 += gt[31];
- m_A20 += go[29];
- double RHS8 = Idr[29];
- RHS8 += Idr[30];
- RHS8 += Idr[31];
- RHS8 -= go[30] * *cnV[30];
- RHS8 -= go[31] * *cnV[31];
- m_A21 += gt[32];
- m_A21 += gt[33];
- m_A22 += go[32];
- double RHS9 = Idr[32];
- RHS9 += Idr[33];
- RHS9 -= go[33] * *cnV[33];
- m_A23 += gt[34];
- m_A23 += gt[35];
- m_A23 += gt[36];
- m_A24 += go[34];
- m_A25 += go[35];
- m_A25 += go[36];
- double RHS10 = Idr[34];
- RHS10 += Idr[35];
- RHS10 += Idr[36];
- m_A26 += gt[37];
- m_A26 += gt[38];
- m_A26 += gt[39];
- m_A26 += gt[40];
- m_A26 += gt[41];
- m_A26 += gt[42];
- m_A26 += gt[43];
- m_A27 += go[37];
- double RHS11 = Idr[37];
- RHS11 += Idr[38];
- RHS11 += Idr[39];
- RHS11 += Idr[40];
- RHS11 += Idr[41];
- RHS11 += Idr[42];
- RHS11 += Idr[43];
- RHS11 -= go[38] * *cnV[38];
- RHS11 -= go[39] * *cnV[39];
- RHS11 -= go[40] * *cnV[40];
- RHS11 -= go[41] * *cnV[41];
- RHS11 -= go[42] * *cnV[42];
- RHS11 -= go[43] * *cnV[43];
- m_A28 += gt[44];
- m_A28 += gt[45];
- m_A28 += gt[46];
- m_A29 += go[44];
- double RHS12 = Idr[44];
- RHS12 += Idr[45];
- RHS12 += Idr[46];
- RHS12 -= go[45] * *cnV[45];
- RHS12 -= go[46] * *cnV[46];
- m_A30 += gt[47];
- m_A30 += gt[48];
- m_A30 += gt[49];
- m_A30 += gt[50];
- m_A32 += go[47];
- m_A31 += go[48];
- m_A33 += go[49];
- double RHS13 = Idr[47];
- RHS13 += Idr[48];
- RHS13 += Idr[49];
- RHS13 += Idr[50];
- RHS13 -= go[50] * *cnV[50];
- m_A35 += gt[51];
- m_A35 += gt[52];
- m_A34 += go[51];
- double RHS14 = Idr[51];
- RHS14 += Idr[52];
- RHS14 -= go[52] * *cnV[52];
- m_A37 += gt[53];
- m_A37 += gt[54];
- m_A37 += gt[55];
- m_A37 += gt[56];
- m_A36 += go[53];
- m_A38 += go[54];
- double RHS15 = Idr[53];
- RHS15 += Idr[54];
- RHS15 += Idr[55];
- RHS15 += Idr[56];
- RHS15 -= go[55] * *cnV[55];
- RHS15 -= go[56] * *cnV[56];
- m_A40 += gt[57];
- m_A40 += gt[58];
- m_A39 += go[57];
- double RHS16 = Idr[57];
- RHS16 += Idr[58];
- RHS16 -= go[58] * *cnV[58];
- m_A43 += gt[59];
- m_A43 += gt[60];
- m_A41 += go[59];
- m_A42 += go[60];
- double RHS17 = Idr[59];
- RHS17 += Idr[60];
- m_A47 += gt[61];
- m_A47 += gt[62];
- m_A47 += gt[63];
- m_A47 += gt[64];
- m_A47 += gt[65];
- m_A46 += go[61];
- m_A49 += go[62];
- m_A50 += go[63];
- double RHS18 = Idr[61];
- RHS18 += Idr[62];
- RHS18 += Idr[63];
- RHS18 += Idr[64];
- RHS18 += Idr[65];
- RHS18 -= go[64] * *cnV[64];
- RHS18 -= go[65] * *cnV[65];
- m_A52 += gt[66];
- m_A52 += gt[67];
- m_A51 += go[66];
- double RHS19 = Idr[66];
- RHS19 += Idr[67];
- RHS19 -= go[67] * *cnV[67];
- m_A55 += gt[68];
- m_A55 += gt[69];
- m_A54 += go[68];
- m_A53 += go[69];
- double RHS20 = Idr[68];
- RHS20 += Idr[69];
- m_A60 += gt[70];
- m_A60 += gt[71];
- m_A60 += gt[72];
- m_A60 += gt[73];
- m_A59 += go[70];
- m_A61 += go[71];
- double RHS21 = Idr[70];
- RHS21 += Idr[71];
- RHS21 += Idr[72];
- RHS21 += Idr[73];
- RHS21 -= go[72] * *cnV[72];
- RHS21 -= go[73] * *cnV[73];
- m_A69 += gt[74];
- m_A69 += gt[75];
- m_A69 += gt[76];
- m_A69 += gt[77];
- m_A69 += gt[78];
- m_A69 += gt[79];
- m_A69 += gt[80];
- m_A69 += gt[81];
- m_A69 += gt[82];
- m_A62 += go[74];
- m_A65 += go[75];
- m_A65 += go[76];
- m_A64 += go[77];
- m_A63 += go[78];
- m_A71 += go[79];
- double RHS22 = Idr[74];
- RHS22 += Idr[75];
- RHS22 += Idr[76];
- RHS22 += Idr[77];
- RHS22 += Idr[78];
- RHS22 += Idr[79];
- RHS22 += Idr[80];
- RHS22 += Idr[81];
- RHS22 += Idr[82];
- RHS22 -= go[80] * *cnV[80];
- RHS22 -= go[81] * *cnV[81];
- RHS22 -= go[82] * *cnV[82];
- m_A75 += gt[83];
- m_A75 += gt[84];
- m_A75 += gt[85];
- m_A75 += gt[86];
- m_A74 += go[83];
- m_A76 += go[84];
- double RHS23 = Idr[83];
- RHS23 += Idr[84];
- RHS23 += Idr[85];
- RHS23 += Idr[86];
- RHS23 -= go[85] * *cnV[85];
- RHS23 -= go[86] * *cnV[86];
- m_A82 += gt[87];
- m_A82 += gt[88];
- m_A82 += gt[89];
- m_A82 += gt[90];
- m_A82 += gt[91];
- m_A82 += gt[92];
- m_A77 += go[87];
- m_A78 += go[88];
- m_A84 += go[89];
- double RHS24 = Idr[87];
- RHS24 += Idr[88];
- RHS24 += Idr[89];
- RHS24 += Idr[90];
- RHS24 += Idr[91];
- RHS24 += Idr[92];
- RHS24 -= go[90] * *cnV[90];
- RHS24 -= go[91] * *cnV[91];
- RHS24 -= go[92] * *cnV[92];
- m_A93 += gt[93];
- m_A93 += gt[94];
- m_A93 += gt[95];
- m_A93 += gt[96];
- m_A93 += gt[97];
- m_A91 += go[93];
- m_A89 += go[94];
- m_A88 += go[95];
- m_A87 += go[96];
- m_A86 += go[97];
- double RHS25 = Idr[93];
- RHS25 += Idr[94];
- RHS25 += Idr[95];
- RHS25 += Idr[96];
- RHS25 += Idr[97];
- m_A104 += gt[98];
- m_A104 += gt[99];
- m_A104 += gt[100];
- m_A104 += gt[101];
- m_A104 += gt[102];
- m_A102 += go[98];
- m_A99 += go[99];
- m_A98 += go[100];
- m_A97 += go[101];
- m_A96 += go[102];
- double RHS26 = Idr[98];
- RHS26 += Idr[99];
- RHS26 += Idr[100];
- RHS26 += Idr[101];
- RHS26 += Idr[102];
- m_A113 += gt[103];
- m_A113 += gt[104];
- m_A113 += gt[105];
- m_A113 += gt[106];
- m_A107 += go[103];
- m_A106 += go[104];
- m_A114 += go[105];
- double RHS27 = Idr[103];
- RHS27 += Idr[104];
- RHS27 += Idr[105];
- RHS27 += Idr[106];
- RHS27 -= go[106] * *cnV[106];
- m_A121 += gt[107];
- m_A121 += gt[108];
- m_A121 += gt[109];
- m_A121 += gt[110];
- m_A121 += gt[111];
- m_A118 += go[107];
- m_A117 += go[108];
- m_A120 += go[109];
- m_A116 += go[110];
- m_A115 += go[111];
- double RHS28 = Idr[107];
- RHS28 += Idr[108];
- RHS28 += Idr[109];
- RHS28 += Idr[110];
- RHS28 += Idr[111];
- const double f0 = 1.0 / m_A0;
- const double f0_17 = -f0 * m_A41;
- m_A43 += m_A1 * f0_17;
- RHS17 += f0_17 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_14 = -f1 * m_A34;
- m_A35 += m_A3 * f1_14;
- RHS14 += f1_14 * RHS1;
- const double f1_25 = -f1 * m_A86;
- m_A89 += m_A3 * f1_25;
- RHS25 += f1_25 * RHS1;
- const double f2 = 1.0 / m_A4;
- const double f2_15 = -f2 * m_A36;
- m_A38 += m_A5 * f2_15;
- RHS15 += f2_15 * RHS2;
- const double f2_25 = -f2 * m_A87;
- m_A93 += m_A5 * f2_25;
- RHS25 += f2_25 * RHS2;
- const double f3 = 1.0 / m_A6;
- const double f3_22 = -f3 * m_A62;
- m_A66 += m_A7 * f3_22;
- RHS22 += f3_22 * RHS3;
- const double f4 = 1.0 / m_A8;
- const double f4_16 = -f4 * m_A39;
- m_A40 += m_A9 * f4_16;
- RHS16 += f4_16 * RHS4;
- const double f4_28 = -f4 * m_A115;
- m_A117 += m_A9 * f4_28;
- RHS28 += f4_28 * RHS4;
- const double f5 = 1.0 / m_A10;
- const double f5_17 = -f5 * m_A42;
- m_A43 += m_A11 * f5_17;
- m_A44 += m_A12 * f5_17;
- m_A45 += m_A13 * f5_17;
- RHS17 += f5_17 * RHS5;
- const double f5_22 = -f5 * m_A63;
- m_A67 += m_A11 * f5_22;
- m_A69 += m_A12 * f5_22;
- m_A71 += m_A13 * f5_22;
- RHS22 += f5_22 * RHS5;
- const double f5_25 = -f5 * m_A88;
- m_A90 += m_A11 * f5_25;
- m_A91 += m_A12 * f5_25;
- m_A93 += m_A13 * f5_25;
- RHS25 += f5_25 * RHS5;
- const double f6 = 1.0 / m_A14;
- const double f6_18 = -f6 * m_A46;
- m_A48 += m_A15 * f6_18;
- RHS18 += f6_18 * RHS6;
- const double f7 = 1.0 / m_A16;
- const double f7_22 = -f7 * m_A64;
- m_A69 += m_A17 * f7_22;
- m_A73 += m_A18 * f7_22;
- RHS22 += f7_22 * RHS7;
- const double f7_27 = -f7 * m_A106;
- m_A109 += m_A17 * f7_27;
- m_A113 += m_A18 * f7_27;
- RHS27 += f7_27 * RHS7;
- const double f8 = 1.0 / m_A19;
- const double f8_21 = -f8 * m_A59;
- m_A61 += m_A20 * f8_21;
- RHS21 += f8_21 * RHS8;
- const double f8_28 = -f8 * m_A116;
- m_A121 += m_A20 * f8_28;
- RHS28 += f8_28 * RHS8;
- const double f9 = 1.0 / m_A21;
- const double f9_19 = -f9 * m_A51;
- m_A52 += m_A22 * f9_19;
- RHS19 += f9_19 * RHS9;
- const double f9_26 = -f9 * m_A96;
- m_A99 += m_A22 * f9_26;
- RHS26 += f9_26 * RHS9;
- const double f10 = 1.0 / m_A23;
- const double f10_20 = -f10 * m_A53;
- m_A55 += m_A24 * f10_20;
- m_A56 += m_A25 * f10_20;
- RHS20 += f10_20 * RHS10;
- const double f10_22 = -f10 * m_A65;
- m_A68 += m_A24 * f10_22;
- m_A69 += m_A25 * f10_22;
- RHS22 += f10_22 * RHS10;
- const double f11 = 1.0 / m_A26;
- const double f11_24 = -f11 * m_A77;
- m_A81 += m_A27 * f11_24;
- RHS24 += f11_24 * RHS11;
- const double f12 = 1.0 / m_A28;
- const double f12_23 = -f12 * m_A74;
- m_A76 += m_A29 * f12_23;
- RHS23 += f12_23 * RHS12;
- const double f12_26 = -f12 * m_A97;
- m_A104 += m_A29 * f12_26;
- RHS26 += f12_26 * RHS12;
- const double f13 = 1.0 / m_A30;
- const double f13_20 = -f13 * m_A54;
- m_A55 += m_A31 * f13_20;
- m_A57 += m_A32 * f13_20;
- m_A58 += m_A33 * f13_20;
- RHS20 += f13_20 * RHS13;
- const double f13_24 = -f13 * m_A78;
- m_A79 += m_A31 * f13_24;
- m_A82 += m_A32 * f13_24;
- m_A84 += m_A33 * f13_24;
- RHS24 += f13_24 * RHS13;
- const double f13_26 = -f13 * m_A98;
- m_A100 += m_A31 * f13_26;
- m_A102 += m_A32 * f13_26;
- m_A104 += m_A33 * f13_26;
- RHS26 += f13_26 * RHS13;
- const double f14 = 1.0 / m_A35;
- const double f14_25 = -f14 * m_A89;
- RHS25 += f14_25 * RHS14;
- const double f15 = 1.0 / m_A37;
- const double f15_22 = -f15 * m_A66;
- m_A71 += m_A38 * f15_22;
- RHS22 += f15_22 * RHS15;
- const double f16 = 1.0 / m_A40;
- const double f16_28 = -f16 * m_A117;
- RHS28 += f16_28 * RHS16;
- const double f17 = 1.0 / m_A43;
- const double f17_22 = -f17 * m_A67;
- m_A69 += m_A44 * f17_22;
- m_A71 += m_A45 * f17_22;
- RHS22 += f17_22 * RHS17;
- const double f17_25 = -f17 * m_A90;
- m_A91 += m_A44 * f17_25;
- m_A93 += m_A45 * f17_25;
- RHS25 += f17_25 * RHS17;
- const double f18 = 1.0 / m_A47;
- const double f18_27 = -f18 * m_A107;
- m_A108 += m_A48 * f18_27;
- m_A113 += m_A49 * f18_27;
- m_A114 += m_A50 * f18_27;
- RHS27 += f18_27 * RHS18;
- const double f18_28 = -f18 * m_A118;
- m_A119 += m_A48 * f18_28;
- m_A120 += m_A49 * f18_28;
- m_A121 += m_A50 * f18_28;
- RHS28 += f18_28 * RHS18;
- const double f19 = 1.0 / m_A52;
- const double f19_26 = -f19 * m_A99;
- RHS26 += f19_26 * RHS19;
- const double f20 = 1.0 / m_A55;
- const double f20_22 = -f20 * m_A68;
- m_A69 += m_A56 * f20_22;
- m_A70 += m_A57 * f20_22;
- m_A72 += m_A58 * f20_22;
- RHS22 += f20_22 * RHS20;
- const double f20_24 = -f20 * m_A79;
- m_A80 += m_A56 * f20_24;
- m_A82 += m_A57 * f20_24;
- m_A84 += m_A58 * f20_24;
- RHS24 += f20_24 * RHS20;
- const double f20_26 = -f20 * m_A100;
- m_A101 += m_A56 * f20_26;
- m_A102 += m_A57 * f20_26;
- m_A104 += m_A58 * f20_26;
- RHS26 += f20_26 * RHS20;
- const double f21 = 1.0 / m_A60;
- const double f21_27 = -f21 * m_A108;
- m_A114 += m_A61 * f21_27;
- RHS27 += f21_27 * RHS21;
- const double f21_28 = -f21 * m_A119;
- m_A121 += m_A61 * f21_28;
- RHS28 += f21_28 * RHS21;
- const double f22 = 1.0 / m_A69;
- const double f22_24 = -f22 * m_A80;
- m_A82 += m_A70 * f22_24;
- m_A83 += m_A71 * f22_24;
- m_A84 += m_A72 * f22_24;
- m_A85 += m_A73 * f22_24;
- RHS24 += f22_24 * RHS22;
- const double f22_25 = -f22 * m_A91;
- m_A92 += m_A70 * f22_25;
- m_A93 += m_A71 * f22_25;
- m_A94 += m_A72 * f22_25;
- m_A95 += m_A73 * f22_25;
- RHS25 += f22_25 * RHS22;
- const double f22_26 = -f22 * m_A101;
- m_A102 += m_A70 * f22_26;
- m_A103 += m_A71 * f22_26;
- m_A104 += m_A72 * f22_26;
- m_A105 += m_A73 * f22_26;
- RHS26 += f22_26 * RHS22;
- const double f22_27 = -f22 * m_A109;
- m_A110 += m_A70 * f22_27;
- m_A111 += m_A71 * f22_27;
- m_A112 += m_A72 * f22_27;
- m_A113 += m_A73 * f22_27;
- RHS27 += f22_27 * RHS22;
- const double f23 = 1.0 / m_A75;
- const double f23_24 = -f23 * m_A81;
- m_A84 += m_A76 * f23_24;
- RHS24 += f23_24 * RHS23;
- const double f24 = 1.0 / m_A82;
- const double f24_25 = -f24 * m_A92;
- m_A93 += m_A83 * f24_25;
- m_A94 += m_A84 * f24_25;
- m_A95 += m_A85 * f24_25;
- RHS25 += f24_25 * RHS24;
- const double f24_26 = -f24 * m_A102;
- m_A103 += m_A83 * f24_26;
- m_A104 += m_A84 * f24_26;
- m_A105 += m_A85 * f24_26;
- RHS26 += f24_26 * RHS24;
- const double f24_27 = -f24 * m_A110;
- m_A111 += m_A83 * f24_27;
- m_A112 += m_A84 * f24_27;
- m_A113 += m_A85 * f24_27;
- RHS27 += f24_27 * RHS24;
- const double f25 = 1.0 / m_A93;
- const double f25_26 = -f25 * m_A103;
- m_A104 += m_A94 * f25_26;
- m_A105 += m_A95 * f25_26;
- RHS26 += f25_26 * RHS25;
- const double f25_27 = -f25 * m_A111;
- m_A112 += m_A94 * f25_27;
- m_A113 += m_A95 * f25_27;
- RHS27 += f25_27 * RHS25;
- const double f26 = 1.0 / m_A104;
- const double f26_27 = -f26 * m_A112;
- m_A113 += m_A105 * f26_27;
- RHS27 += f26_27 * RHS26;
- const double f27 = 1.0 / m_A113;
- const double f27_28 = -f27 * m_A120;
- m_A121 += m_A114 * f27_28;
- RHS28 += f27_28 * RHS27;
- V[28] = RHS28 / m_A121;
- double tmp27 = 0.0;
- tmp27 += m_A114 * V[28];
- V[27] = (RHS27 - tmp27) / m_A113;
- double tmp26 = 0.0;
- tmp26 += m_A105 * V[27];
- V[26] = (RHS26 - tmp26) / m_A104;
- double tmp25 = 0.0;
- tmp25 += m_A94 * V[26];
- tmp25 += m_A95 * V[27];
- V[25] = (RHS25 - tmp25) / m_A93;
- double tmp24 = 0.0;
- tmp24 += m_A83 * V[25];
- tmp24 += m_A84 * V[26];
- tmp24 += m_A85 * V[27];
- V[24] = (RHS24 - tmp24) / m_A82;
- double tmp23 = 0.0;
- tmp23 += m_A76 * V[26];
- V[23] = (RHS23 - tmp23) / m_A75;
- double tmp22 = 0.0;
- tmp22 += m_A70 * V[24];
- tmp22 += m_A71 * V[25];
- tmp22 += m_A72 * V[26];
- tmp22 += m_A73 * V[27];
- V[22] = (RHS22 - tmp22) / m_A69;
- double tmp21 = 0.0;
- tmp21 += m_A61 * V[28];
- V[21] = (RHS21 - tmp21) / m_A60;
- double tmp20 = 0.0;
- tmp20 += m_A56 * V[22];
- tmp20 += m_A57 * V[24];
- tmp20 += m_A58 * V[26];
- V[20] = (RHS20 - tmp20) / m_A55;
- double tmp19 = 0.0;
- V[19] = (RHS19 - tmp19) / m_A52;
- double tmp18 = 0.0;
- tmp18 += m_A48 * V[21];
- tmp18 += m_A49 * V[27];
- tmp18 += m_A50 * V[28];
- V[18] = (RHS18 - tmp18) / m_A47;
- double tmp17 = 0.0;
- tmp17 += m_A44 * V[22];
- tmp17 += m_A45 * V[25];
- V[17] = (RHS17 - tmp17) / m_A43;
- double tmp16 = 0.0;
- V[16] = (RHS16 - tmp16) / m_A40;
- double tmp15 = 0.0;
- tmp15 += m_A38 * V[25];
- V[15] = (RHS15 - tmp15) / m_A37;
- double tmp14 = 0.0;
- V[14] = (RHS14 - tmp14) / m_A35;
- double tmp13 = 0.0;
- tmp13 += m_A31 * V[20];
- tmp13 += m_A32 * V[24];
- tmp13 += m_A33 * V[26];
- V[13] = (RHS13 - tmp13) / m_A30;
- double tmp12 = 0.0;
- tmp12 += m_A29 * V[26];
- V[12] = (RHS12 - tmp12) / m_A28;
- double tmp11 = 0.0;
- tmp11 += m_A27 * V[23];
- V[11] = (RHS11 - tmp11) / m_A26;
- double tmp10 = 0.0;
- tmp10 += m_A24 * V[20];
- tmp10 += m_A25 * V[22];
- V[10] = (RHS10 - tmp10) / m_A23;
- double tmp9 = 0.0;
- tmp9 += m_A22 * V[19];
- V[9] = (RHS9 - tmp9) / m_A21;
- double tmp8 = 0.0;
- tmp8 += m_A20 * V[28];
- V[8] = (RHS8 - tmp8) / m_A19;
- double tmp7 = 0.0;
- tmp7 += m_A17 * V[22];
- tmp7 += m_A18 * V[27];
- V[7] = (RHS7 - tmp7) / m_A16;
- double tmp6 = 0.0;
- tmp6 += m_A15 * V[21];
- V[6] = (RHS6 - tmp6) / m_A14;
- double tmp5 = 0.0;
- tmp5 += m_A11 * V[17];
- tmp5 += m_A12 * V[22];
- tmp5 += m_A13 * V[25];
- V[5] = (RHS5 - tmp5) / m_A10;
- double tmp4 = 0.0;
- tmp4 += m_A9 * V[16];
- V[4] = (RHS4 - tmp4) / m_A8;
- double tmp3 = 0.0;
- tmp3 += m_A7 * V[15];
- V[3] = (RHS3 - tmp3) / m_A6;
- double tmp2 = 0.0;
- tmp2 += m_A5 * V[25];
- V[2] = (RHS2 - tmp2) / m_A4;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[14];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[17];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
-// 280zzzap,sspeedr
-static void nl_gcr_123_double_double_864a61c57bac9c38(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- double m_A13(0.0);
- double m_A14(0.0);
- double m_A15(0.0);
- double m_A16(0.0);
- double m_A17(0.0);
- double m_A18(0.0);
- double m_A19(0.0);
- double m_A20(0.0);
- double m_A21(0.0);
- double m_A22(0.0);
- double m_A23(0.0);
- double m_A24(0.0);
- double m_A25(0.0);
- double m_A26(0.0);
- double m_A27(0.0);
- double m_A28(0.0);
- double m_A29(0.0);
- double m_A30(0.0);
- double m_A31(0.0);
- double m_A32(0.0);
- double m_A33(0.0);
- double m_A34(0.0);
- double m_A35(0.0);
- double m_A36(0.0);
- double m_A37(0.0);
- double m_A38(0.0);
- double m_A39(0.0);
- double m_A40(0.0);
- double m_A41(0.0);
- double m_A42(0.0);
- double m_A43(0.0);
- double m_A44(0.0);
- double m_A45(0.0);
- double m_A46(0.0);
- double m_A47(0.0);
- double m_A48(0.0);
- double m_A49(0.0);
- double m_A50(0.0);
- double m_A51(0.0);
- double m_A52(0.0);
- double m_A53(0.0);
- double m_A54(0.0);
- double m_A55(0.0);
- double m_A56(0.0);
- double m_A57(0.0);
- double m_A58(0.0);
- double m_A59(0.0);
- double m_A60(0.0);
- double m_A61(0.0);
- double m_A62(0.0);
- double m_A63(0.0);
- double m_A64(0.0);
- double m_A65(0.0);
- double m_A66(0.0);
- double m_A67(0.0);
- double m_A68(0.0);
- double m_A69(0.0);
- double m_A70(0.0);
- double m_A71(0.0);
- double m_A72(0.0);
- double m_A73(0.0);
- double m_A74(0.0);
- double m_A75(0.0);
- double m_A76(0.0);
- double m_A77(0.0);
- double m_A78(0.0);
- double m_A79(0.0);
- double m_A80(0.0);
- double m_A81(0.0);
- double m_A82(0.0);
- double m_A83(0.0);
- double m_A84(0.0);
- double m_A85(0.0);
- double m_A86(0.0);
- double m_A87(0.0);
- double m_A88(0.0);
- double m_A89(0.0);
- double m_A90(0.0);
- double m_A91(0.0);
- double m_A92(0.0);
- double m_A93(0.0);
- double m_A94(0.0);
- double m_A95(0.0);
- double m_A96(0.0);
- double m_A97(0.0);
- double m_A98(0.0);
- double m_A99(0.0);
- double m_A100(0.0);
- double m_A101(0.0);
- double m_A102(0.0);
- double m_A103(0.0);
- double m_A104(0.0);
- double m_A105(0.0);
- double m_A106(0.0);
- double m_A107(0.0);
- double m_A108(0.0);
- double m_A109(0.0);
- double m_A110(0.0);
- double m_A111(0.0);
- double m_A112(0.0);
- double m_A113(0.0);
- double m_A114(0.0);
- double m_A115(0.0);
- double m_A116(0.0);
- double m_A117(0.0);
- double m_A118(0.0);
- double m_A119(0.0);
- double m_A120(0.0);
- double m_A121(0.0);
- double m_A122(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A0 += gt[2];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 += Idr[2];
- RHS0 -= go[1] * *cnV[1];
- RHS0 -= go[2] * *cnV[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A3 += go[3];
- double RHS1 = Idr[3];
- RHS1 += Idr[4];
- RHS1 -= go[4] * *cnV[4];
- m_A4 += gt[5];
- m_A4 += gt[6];
- m_A4 += gt[7];
- m_A4 += gt[8];
- m_A4 += gt[9];
- m_A4 += gt[10];
- m_A4 += gt[11];
- m_A5 += go[5];
- double RHS2 = Idr[5];
- RHS2 += Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 += Idr[9];
- RHS2 += Idr[10];
- RHS2 += Idr[11];
- RHS2 -= go[6] * *cnV[6];
- RHS2 -= go[7] * *cnV[7];
- RHS2 -= go[8] * *cnV[8];
- RHS2 -= go[9] * *cnV[9];
- RHS2 -= go[10] * *cnV[10];
- RHS2 -= go[11] * *cnV[11];
- m_A6 += gt[12];
- m_A6 += gt[13];
- m_A6 += gt[14];
- m_A7 += go[12];
- double RHS3 = Idr[12];
- RHS3 += Idr[13];
- RHS3 += Idr[14];
- RHS3 -= go[13] * *cnV[13];
- RHS3 -= go[14] * *cnV[14];
- m_A8 += gt[15];
- m_A8 += gt[16];
- m_A8 += gt[17];
- m_A8 += gt[18];
- m_A8 += gt[19];
- m_A8 += gt[20];
- m_A8 += gt[21];
- m_A9 += go[15];
- double RHS4 = Idr[15];
- RHS4 += Idr[16];
- RHS4 += Idr[17];
- RHS4 += Idr[18];
- RHS4 += Idr[19];
- RHS4 += Idr[20];
- RHS4 += Idr[21];
- RHS4 -= go[16] * *cnV[16];
- RHS4 -= go[17] * *cnV[17];
- RHS4 -= go[18] * *cnV[18];
- RHS4 -= go[19] * *cnV[19];
- RHS4 -= go[20] * *cnV[20];
- RHS4 -= go[21] * *cnV[21];
- m_A10 += gt[22];
- m_A10 += gt[23];
- m_A11 += go[22];
- double RHS5 = Idr[22];
- RHS5 += Idr[23];
- RHS5 -= go[23] * *cnV[23];
- m_A12 += gt[24];
- m_A12 += gt[25];
- m_A14 += go[24];
- m_A13 += go[25];
- double RHS6 = Idr[24];
- RHS6 += Idr[25];
- m_A15 += gt[26];
- m_A15 += gt[27];
- m_A16 += go[26];
- double RHS7 = Idr[26];
- RHS7 += Idr[27];
- RHS7 -= go[27] * *cnV[27];
- m_A17 += gt[28];
- m_A17 += gt[29];
- m_A18 += go[28];
- double RHS8 = Idr[28];
- RHS8 += Idr[29];
- RHS8 -= go[29] * *cnV[29];
- m_A19 += gt[30];
- m_A19 += gt[31];
- m_A19 += gt[32];
- m_A19 += gt[33];
- m_A19 += gt[34];
- m_A19 += gt[35];
- m_A19 += gt[36];
- m_A20 += go[30];
- double RHS9 = Idr[30];
- RHS9 += Idr[31];
- RHS9 += Idr[32];
- RHS9 += Idr[33];
- RHS9 += Idr[34];
- RHS9 += Idr[35];
- RHS9 += Idr[36];
- RHS9 -= go[31] * *cnV[31];
- RHS9 -= go[32] * *cnV[32];
- RHS9 -= go[33] * *cnV[33];
- RHS9 -= go[34] * *cnV[34];
- RHS9 -= go[35] * *cnV[35];
- RHS9 -= go[36] * *cnV[36];
- m_A21 += gt[37];
- m_A21 += gt[38];
- m_A21 += gt[39];
- m_A22 += go[37];
- double RHS10 = Idr[37];
- RHS10 += Idr[38];
- RHS10 += Idr[39];
- RHS10 -= go[38] * *cnV[38];
- RHS10 -= go[39] * *cnV[39];
- m_A23 += gt[40];
- m_A23 += gt[41];
- m_A23 += gt[42];
- m_A23 += gt[43];
- m_A24 += go[40];
- double RHS11 = Idr[40];
- RHS11 += Idr[41];
- RHS11 += Idr[42];
- RHS11 += Idr[43];
- RHS11 -= go[41] * *cnV[41];
- RHS11 -= go[42] * *cnV[42];
- RHS11 -= go[43] * *cnV[43];
- m_A25 += gt[44];
- m_A25 += gt[45];
- m_A25 += gt[46];
- m_A25 += gt[47];
- m_A25 += gt[48];
- m_A25 += gt[49];
- m_A25 += gt[50];
- m_A26 += go[44];
- double RHS12 = Idr[44];
- RHS12 += Idr[45];
- RHS12 += Idr[46];
- RHS12 += Idr[47];
- RHS12 += Idr[48];
- RHS12 += Idr[49];
- RHS12 += Idr[50];
- RHS12 -= go[45] * *cnV[45];
- RHS12 -= go[46] * *cnV[46];
- RHS12 -= go[47] * *cnV[47];
- RHS12 -= go[48] * *cnV[48];
- RHS12 -= go[49] * *cnV[49];
- RHS12 -= go[50] * *cnV[50];
- m_A27 += gt[51];
- m_A27 += gt[52];
- m_A28 += go[51];
- double RHS13 = Idr[51];
- RHS13 += Idr[52];
- RHS13 -= go[52] * *cnV[52];
- m_A29 += gt[53];
- m_A29 += gt[54];
- m_A30 += go[53];
- double RHS14 = Idr[53];
- RHS14 += Idr[54];
- RHS14 -= go[54] * *cnV[54];
- m_A31 += gt[55];
- m_A31 += gt[56];
- m_A32 += go[55];
- double RHS15 = Idr[55];
- RHS15 += Idr[56];
- RHS15 -= go[56] * *cnV[56];
- m_A33 += gt[57];
- m_A33 += gt[58];
- m_A33 += gt[59];
- m_A33 += gt[60];
- m_A35 += go[57];
- m_A34 += go[58];
- double RHS16 = Idr[57];
- RHS16 += Idr[58];
- RHS16 += Idr[59];
- RHS16 += Idr[60];
- RHS16 -= go[59] * *cnV[59];
- RHS16 -= go[60] * *cnV[60];
- m_A36 += gt[61];
- m_A36 += gt[62];
- m_A36 += gt[63];
- m_A37 += go[61];
- double RHS17 = Idr[61];
- RHS17 += Idr[62];
- RHS17 += Idr[63];
- RHS17 -= go[62] * *cnV[62];
- RHS17 -= go[63] * *cnV[63];
- m_A38 += gt[64];
- m_A38 += gt[65];
- m_A39 += go[64];
- double RHS18 = Idr[64];
- RHS18 += Idr[65];
- RHS18 -= go[65] * *cnV[65];
- m_A40 += gt[66];
- m_A40 += gt[67];
- m_A41 += go[66];
- double RHS19 = Idr[66];
- RHS19 += Idr[67];
- RHS19 -= go[67] * *cnV[67];
- m_A43 += gt[68];
- m_A43 += gt[69];
- m_A43 += gt[70];
- m_A43 += gt[71];
- m_A42 += go[68];
- double RHS20 = Idr[68];
- RHS20 += Idr[69];
- RHS20 += Idr[70];
- RHS20 += Idr[71];
- RHS20 -= go[69] * *cnV[69];
- RHS20 -= go[70] * *cnV[70];
- RHS20 -= go[71] * *cnV[71];
- m_A47 += gt[72];
- m_A47 += gt[73];
- m_A46 += go[72];
- m_A45 += go[73];
- double RHS21 = Idr[72];
- RHS21 += Idr[73];
- m_A51 += gt[74];
- m_A51 += gt[75];
- m_A49 += go[74];
- double RHS22 = Idr[74];
- RHS22 += Idr[75];
- RHS22 -= go[75] * *cnV[75];
- m_A54 += gt[76];
- m_A54 += gt[77];
- m_A54 += gt[78];
- m_A53 += go[76];
- m_A52 += go[77];
- double RHS23 = Idr[76];
- RHS23 += Idr[77];
- RHS23 += Idr[78];
- RHS23 -= go[78] * *cnV[78];
- m_A56 += gt[79];
- m_A56 += gt[80];
- m_A56 += gt[81];
- m_A56 += gt[82];
- m_A55 += go[79];
- m_A57 += go[80];
- double RHS24 = Idr[79];
- RHS24 += Idr[80];
- RHS24 += Idr[81];
- RHS24 += Idr[82];
- RHS24 -= go[81] * *cnV[81];
- RHS24 -= go[82] * *cnV[82];
- m_A59 += gt[83];
- m_A59 += gt[84];
- m_A59 += gt[85];
- m_A59 += gt[86];
- m_A58 += go[83];
- m_A60 += go[84];
- double RHS25 = Idr[83];
- RHS25 += Idr[84];
- RHS25 += Idr[85];
- RHS25 += Idr[86];
- RHS25 -= go[85] * *cnV[85];
- RHS25 -= go[86] * *cnV[86];
- m_A62 += gt[87];
- m_A62 += gt[88];
- m_A63 += go[87];
- m_A61 += go[88];
- double RHS26 = Idr[87];
- RHS26 += Idr[88];
- m_A67 += gt[89];
- m_A67 += gt[90];
- m_A67 += gt[91];
- m_A67 += gt[92];
- m_A67 += gt[93];
- m_A67 += gt[94];
- m_A64 += go[89];
- m_A65 += go[90];
- m_A69 += go[91];
- m_A68 += go[92];
- double RHS27 = Idr[89];
- RHS27 += Idr[90];
- RHS27 += Idr[91];
- RHS27 += Idr[92];
- RHS27 += Idr[93];
- RHS27 += Idr[94];
- RHS27 -= go[93] * *cnV[93];
- RHS27 -= go[94] * *cnV[94];
- m_A72 += gt[95];
- m_A72 += gt[96];
- m_A72 += gt[97];
- m_A72 += gt[98];
- m_A71 += go[95];
- m_A73 += go[96];
- double RHS28 = Idr[95];
- RHS28 += Idr[96];
- RHS28 += Idr[97];
- RHS28 += Idr[98];
- RHS28 -= go[97] * *cnV[97];
- RHS28 -= go[98] * *cnV[98];
- m_A76 += gt[99];
- m_A76 += gt[100];
- m_A76 += gt[101];
- m_A76 += gt[102];
- m_A77 += go[99];
- m_A78 += go[100];
- m_A74 += go[101];
- m_A75 += go[102];
- double RHS29 = Idr[99];
- RHS29 += Idr[100];
- RHS29 += Idr[101];
- RHS29 += Idr[102];
- m_A81 += gt[103];
- m_A81 += gt[104];
- m_A81 += gt[105];
- m_A80 += go[103];
- m_A79 += go[104];
- double RHS30 = Idr[103];
- RHS30 += Idr[104];
- RHS30 += Idr[105];
- RHS30 -= go[105] * *cnV[105];
- m_A84 += gt[106];
- m_A84 += gt[107];
- m_A82 += go[106];
- m_A83 += go[107];
- double RHS31 = Idr[106];
- RHS31 += Idr[107];
- m_A91 += gt[108];
- m_A91 += gt[109];
- m_A91 += gt[110];
- m_A91 += gt[111];
- m_A91 += gt[112];
- m_A86 += go[108];
- m_A90 += go[109];
- m_A88 += go[110];
- m_A85 += go[111];
- m_A87 += go[112];
- double RHS32 = Idr[108];
- RHS32 += Idr[109];
- RHS32 += Idr[110];
- RHS32 += Idr[111];
- RHS32 += Idr[112];
- m_A99 += gt[113];
- m_A99 += gt[114];
- m_A99 += gt[115];
- m_A99 += gt[116];
- m_A99 += gt[117];
- m_A96 += go[113];
- m_A100 += go[114];
- m_A97 += go[115];
- m_A94 += go[116];
- m_A95 += go[117];
- double RHS33 = Idr[113];
- RHS33 += Idr[114];
- RHS33 += Idr[115];
- RHS33 += Idr[116];
- RHS33 += Idr[117];
- m_A106 += gt[118];
- m_A106 += gt[119];
- m_A106 += gt[120];
- m_A106 += gt[121];
- m_A103 += go[118];
- m_A104 += go[119];
- m_A101 += go[120];
- m_A102 += go[121];
- double RHS34 = Idr[118];
- RHS34 += Idr[119];
- RHS34 += Idr[120];
- RHS34 += Idr[121];
- m_A111 += gt[122];
- m_A111 += gt[123];
- m_A111 += gt[124];
- m_A111 += gt[125];
- m_A108 += go[122];
- m_A109 += go[123];
- double RHS35 = Idr[122];
- RHS35 += Idr[123];
- RHS35 += Idr[124];
- RHS35 += Idr[125];
- RHS35 -= go[124] * *cnV[124];
- RHS35 -= go[125] * *cnV[125];
- m_A122 += gt[126];
- m_A122 += gt[127];
- m_A122 += gt[128];
- m_A122 += gt[129];
- m_A122 += gt[130];
- m_A122 += gt[131];
- m_A113 += go[126];
- m_A117 += go[127];
- m_A120 += go[128];
- m_A114 += go[129];
- double RHS36 = Idr[126];
- RHS36 += Idr[127];
- RHS36 += Idr[128];
- RHS36 += Idr[129];
- RHS36 += Idr[130];
- RHS36 += Idr[131];
- RHS36 -= go[130] * *cnV[130];
- RHS36 -= go[131] * *cnV[131];
- const double f0 = 1.0 / m_A0;
- const double f0_24 = -f0 * m_A55;
- m_A57 += m_A1 * f0_24;
- RHS24 += f0_24 * RHS0;
- const double f0_32 = -f0 * m_A85;
- m_A91 += m_A1 * f0_32;
- RHS32 += f0_32 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_32 = -f1 * m_A86;
- m_A91 += m_A3 * f1_32;
- RHS32 += f1_32 * RHS1;
- const double f2 = 1.0 / m_A4;
- const double f2_27 = -f2 * m_A64;
- m_A66 += m_A5 * f2_27;
- RHS27 += f2_27 * RHS2;
- const double f3 = 1.0 / m_A6;
- const double f3_25 = -f3 * m_A58;
- m_A60 += m_A7 * f3_25;
- RHS25 += f3_25 * RHS3;
- const double f3_34 = -f3 * m_A101;
- m_A106 += m_A7 * f3_34;
- RHS34 += f3_34 * RHS3;
- const double f4 = 1.0 / m_A8;
- const double f4_20 = -f4 * m_A42;
- m_A44 += m_A9 * f4_20;
- RHS20 += f4_20 * RHS4;
- const double f5 = 1.0 / m_A10;
- const double f5_21 = -f5 * m_A45;
- m_A47 += m_A11 * f5_21;
- RHS21 += f5_21 * RHS5;
- const double f5_32 = -f5 * m_A87;
- m_A88 += m_A11 * f5_32;
- RHS32 += f5_32 * RHS5;
- const double f6 = 1.0 / m_A12;
- const double f6_21 = -f6 * m_A46;
- m_A47 += m_A13 * f6_21;
- m_A48 += m_A14 * f6_21;
- RHS21 += f6_21 * RHS6;
- const double f6_22 = -f6 * m_A49;
- m_A50 += m_A13 * f6_22;
- m_A51 += m_A14 * f6_22;
- RHS22 += f6_22 * RHS6;
- const double f7 = 1.0 / m_A15;
- const double f7_23 = -f7 * m_A52;
- m_A54 += m_A16 * f7_23;
- RHS23 += f7_23 * RHS7;
- const double f7_34 = -f7 * m_A102;
- m_A103 += m_A16 * f7_34;
- RHS34 += f7_34 * RHS7;
- const double f8 = 1.0 / m_A17;
- const double f8_23 = -f8 * m_A53;
- m_A54 += m_A18 * f8_23;
- RHS23 += f8_23 * RHS8;
- const double f9 = 1.0 / m_A19;
- const double f9_36 = -f9 * m_A113;
- m_A116 += m_A20 * f9_36;
- RHS36 += f9_36 * RHS9;
- const double f10 = 1.0 / m_A21;
- const double f10_28 = -f10 * m_A71;
- m_A73 += m_A22 * f10_28;
- RHS28 += f10_28 * RHS10;
- const double f10_33 = -f10 * m_A94;
- m_A99 += m_A22 * f10_33;
- RHS33 += f10_33 * RHS10;
- const double f13 = 1.0 / m_A27;
- const double f13_26 = -f13 * m_A61;
- m_A62 += m_A28 * f13_26;
- RHS26 += f13_26 * RHS13;
- const double f13_33 = -f13 * m_A95;
- m_A97 += m_A28 * f13_33;
- RHS33 += f13_33 * RHS13;
- const double f14 = 1.0 / m_A29;
- const double f14_33 = -f14 * m_A96;
- m_A99 += m_A30 * f14_33;
- RHS33 += f14_33 * RHS14;
- const double f15 = 1.0 / m_A31;
- const double f15_31 = -f15 * m_A82;
- m_A84 += m_A32 * f15_31;
- RHS31 += f15_31 * RHS15;
- const double f16 = 1.0 / m_A33;
- const double f16_27 = -f16 * m_A65;
- m_A67 += m_A34 * f16_27;
- m_A70 += m_A35 * f16_27;
- RHS27 += f16_27 * RHS16;
- const double f16_36 = -f16 * m_A114;
- m_A115 += m_A34 * f16_36;
- m_A122 += m_A35 * f16_36;
- RHS36 += f16_36 * RHS16;
- const double f17 = 1.0 / m_A36;
- const double f17_29 = -f17 * m_A74;
- m_A76 += m_A37 * f17_29;
- RHS29 += f17_29 * RHS17;
- const double f17_35 = -f17 * m_A108;
- m_A109 += m_A37 * f17_35;
- RHS35 += f17_35 * RHS17;
- const double f18 = 1.0 / m_A38;
- const double f18_29 = -f18 * m_A75;
- m_A77 += m_A39 * f18_29;
- RHS29 += f18_29 * RHS18;
- const double f18_30 = -f18 * m_A79;
- m_A81 += m_A39 * f18_30;
- RHS30 += f18_30 * RHS18;
- const double f19 = 1.0 / m_A40;
- const double f19_30 = -f19 * m_A80;
- m_A81 += m_A41 * f19_30;
- RHS30 += f19_30 * RHS19;
- const double f21 = 1.0 / m_A47;
- const double f21_22 = -f21 * m_A50;
- m_A51 += m_A48 * f21_22;
- RHS22 += f21_22 * RHS21;
- const double f21_32 = -f21 * m_A88;
- m_A89 += m_A48 * f21_32;
- RHS32 += f21_32 * RHS21;
- const double f22 = 1.0 / m_A51;
- const double f22_32 = -f22 * m_A89;
- RHS32 += f22_32 * RHS22;
- const double f23 = 1.0 / m_A54;
- const double f23_34 = -f23 * m_A103;
- RHS34 += f23_34 * RHS23;
- const double f24 = 1.0 / m_A56;
- const double f24_27 = -f24 * m_A66;
- m_A68 += m_A57 * f24_27;
- RHS27 += f24_27 * RHS24;
- const double f26 = 1.0 / m_A62;
- const double f26_31 = -f26 * m_A83;
- m_A84 += m_A63 * f26_31;
- RHS31 += f26_31 * RHS26;
- const double f26_33 = -f26 * m_A97;
- m_A98 += m_A63 * f26_33;
- RHS33 += f26_33 * RHS26;
- const double f27 = 1.0 / m_A67;
- const double f27_32 = -f27 * m_A90;
- m_A91 += m_A68 * f27_32;
- m_A92 += m_A69 * f27_32;
- m_A93 += m_A70 * f27_32;
- RHS32 += f27_32 * RHS27;
- const double f27_34 = -f27 * m_A104;
- m_A105 += m_A68 * f27_34;
- m_A106 += m_A69 * f27_34;
- m_A107 += m_A70 * f27_34;
- RHS34 += f27_34 * RHS27;
- const double f27_36 = -f27 * m_A115;
- m_A119 += m_A68 * f27_36;
- m_A121 += m_A69 * f27_36;
- m_A122 += m_A70 * f27_36;
- RHS36 += f27_36 * RHS27;
- const double f28 = 1.0 / m_A72;
- const double f28_36 = -f28 * m_A116;
- m_A120 += m_A73 * f28_36;
- RHS36 += f28_36 * RHS28;
- const double f29 = 1.0 / m_A76;
- const double f29_35 = -f29 * m_A109;
- m_A110 += m_A77 * f29_35;
- m_A112 += m_A78 * f29_35;
- RHS35 += f29_35 * RHS29;
- const double f29_36 = -f29 * m_A117;
- m_A118 += m_A77 * f29_36;
- m_A122 += m_A78 * f29_36;
- RHS36 += f29_36 * RHS29;
- const double f30 = 1.0 / m_A81;
- const double f30_35 = -f30 * m_A110;
- RHS35 += f30_35 * RHS30;
- const double f30_36 = -f30 * m_A118;
- RHS36 += f30_36 * RHS30;
- const double f31 = 1.0 / m_A84;
- const double f31_33 = -f31 * m_A98;
- RHS33 += f31_33 * RHS31;
- const double f32 = 1.0 / m_A91;
- const double f32_34 = -f32 * m_A105;
- m_A106 += m_A92 * f32_34;
- m_A107 += m_A93 * f32_34;
- RHS34 += f32_34 * RHS32;
- const double f32_36 = -f32 * m_A119;
- m_A121 += m_A92 * f32_36;
- m_A122 += m_A93 * f32_36;
- RHS36 += f32_36 * RHS32;
- const double f33 = 1.0 / m_A99;
- const double f33_36 = -f33 * m_A120;
- m_A122 += m_A100 * f33_36;
- RHS36 += f33_36 * RHS33;
- const double f34 = 1.0 / m_A106;
- const double f34_36 = -f34 * m_A121;
- m_A122 += m_A107 * f34_36;
- RHS36 += f34_36 * RHS34;
- V[36] = RHS36 / m_A122;
- double tmp35 = 0.0;
- tmp35 += m_A112 * V[36];
- V[35] = (RHS35 - tmp35) / m_A111;
- double tmp34 = 0.0;
- tmp34 += m_A107 * V[36];
- V[34] = (RHS34 - tmp34) / m_A106;
- double tmp33 = 0.0;
- tmp33 += m_A100 * V[36];
- V[33] = (RHS33 - tmp33) / m_A99;
- double tmp32 = 0.0;
- tmp32 += m_A92 * V[34];
- tmp32 += m_A93 * V[36];
- V[32] = (RHS32 - tmp32) / m_A91;
- double tmp31 = 0.0;
- V[31] = (RHS31 - tmp31) / m_A84;
- double tmp30 = 0.0;
- V[30] = (RHS30 - tmp30) / m_A81;
- double tmp29 = 0.0;
- tmp29 += m_A77 * V[30];
- tmp29 += m_A78 * V[36];
- V[29] = (RHS29 - tmp29) / m_A76;
- double tmp28 = 0.0;
- tmp28 += m_A73 * V[33];
- V[28] = (RHS28 - tmp28) / m_A72;
- double tmp27 = 0.0;
- tmp27 += m_A68 * V[32];
- tmp27 += m_A69 * V[34];
- tmp27 += m_A70 * V[36];
- V[27] = (RHS27 - tmp27) / m_A67;
- double tmp26 = 0.0;
- tmp26 += m_A63 * V[31];
- V[26] = (RHS26 - tmp26) / m_A62;
- double tmp25 = 0.0;
- tmp25 += m_A60 * V[34];
- V[25] = (RHS25 - tmp25) / m_A59;
- double tmp24 = 0.0;
- tmp24 += m_A57 * V[32];
- V[24] = (RHS24 - tmp24) / m_A56;
- double tmp23 = 0.0;
- V[23] = (RHS23 - tmp23) / m_A54;
- double tmp22 = 0.0;
- V[22] = (RHS22 - tmp22) / m_A51;
- double tmp21 = 0.0;
- tmp21 += m_A48 * V[22];
- V[21] = (RHS21 - tmp21) / m_A47;
- double tmp20 = 0.0;
- tmp20 += m_A44 * V[25];
- V[20] = (RHS20 - tmp20) / m_A43;
- double tmp19 = 0.0;
- tmp19 += m_A41 * V[30];
- V[19] = (RHS19 - tmp19) / m_A40;
- double tmp18 = 0.0;
- tmp18 += m_A39 * V[30];
- V[18] = (RHS18 - tmp18) / m_A38;
- double tmp17 = 0.0;
- tmp17 += m_A37 * V[29];
- V[17] = (RHS17 - tmp17) / m_A36;
- double tmp16 = 0.0;
- tmp16 += m_A34 * V[27];
- tmp16 += m_A35 * V[36];
- V[16] = (RHS16 - tmp16) / m_A33;
- double tmp15 = 0.0;
- tmp15 += m_A32 * V[31];
- V[15] = (RHS15 - tmp15) / m_A31;
- double tmp14 = 0.0;
- tmp14 += m_A30 * V[33];
- V[14] = (RHS14 - tmp14) / m_A29;
- double tmp13 = 0.0;
- tmp13 += m_A28 * V[26];
- V[13] = (RHS13 - tmp13) / m_A27;
- double tmp12 = 0.0;
- tmp12 += m_A26 * V[35];
- V[12] = (RHS12 - tmp12) / m_A25;
- double tmp11 = 0.0;
- tmp11 += m_A24 * V[12];
- V[11] = (RHS11 - tmp11) / m_A23;
- double tmp10 = 0.0;
- tmp10 += m_A22 * V[33];
- V[10] = (RHS10 - tmp10) / m_A21;
- double tmp9 = 0.0;
- tmp9 += m_A20 * V[28];
- V[9] = (RHS9 - tmp9) / m_A19;
- double tmp8 = 0.0;
- tmp8 += m_A18 * V[23];
- V[8] = (RHS8 - tmp8) / m_A17;
- double tmp7 = 0.0;
- tmp7 += m_A16 * V[23];
- V[7] = (RHS7 - tmp7) / m_A15;
- double tmp6 = 0.0;
- tmp6 += m_A13 * V[21];
- tmp6 += m_A14 * V[22];
- V[6] = (RHS6 - tmp6) / m_A12;
- double tmp5 = 0.0;
- tmp5 += m_A11 * V[21];
- V[5] = (RHS5 - tmp5) / m_A10;
- double tmp4 = 0.0;
- tmp4 += m_A9 * V[25];
- V[4] = (RHS4 - tmp4) / m_A8;
- double tmp3 = 0.0;
- tmp3 += m_A7 * V[34];
- V[3] = (RHS3 - tmp3) / m_A6;
- double tmp2 = 0.0;
- tmp2 += m_A5 * V[24];
- V[2] = (RHS2 - tmp2) / m_A4;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[32];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[32];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// 280zzzap
static void nl_gcr_149_double_double_fc9971724787b82b(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -3844,398 +1510,6 @@ static void nl_gcr_149_double_double_fc9971724787b82b(double * __restrict V, con
V[0] = (RHS0 - tmp0) / m_A0;
}
-// 280zzzap,sspeedr
-static void nl_gcr_57_double_double_bb501e6a23177009(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- double m_A13(0.0);
- double m_A14(0.0);
- double m_A15(0.0);
- double m_A16(0.0);
- double m_A17(0.0);
- double m_A18(0.0);
- double m_A19(0.0);
- double m_A20(0.0);
- double m_A21(0.0);
- double m_A22(0.0);
- double m_A23(0.0);
- double m_A24(0.0);
- double m_A25(0.0);
- double m_A26(0.0);
- double m_A27(0.0);
- double m_A28(0.0);
- double m_A29(0.0);
- double m_A30(0.0);
- double m_A31(0.0);
- double m_A32(0.0);
- double m_A33(0.0);
- double m_A34(0.0);
- double m_A35(0.0);
- double m_A36(0.0);
- double m_A37(0.0);
- double m_A38(0.0);
- double m_A39(0.0);
- double m_A40(0.0);
- double m_A41(0.0);
- double m_A42(0.0);
- double m_A43(0.0);
- double m_A44(0.0);
- double m_A45(0.0);
- double m_A46(0.0);
- double m_A47(0.0);
- double m_A48(0.0);
- double m_A49(0.0);
- double m_A50(0.0);
- double m_A51(0.0);
- double m_A52(0.0);
- double m_A53(0.0);
- double m_A54(0.0);
- double m_A55(0.0);
- double m_A56(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A0 += gt[2];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 += Idr[2];
- RHS0 -= go[1] * *cnV[1];
- RHS0 -= go[2] * *cnV[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A3 += go[3];
- double RHS1 = Idr[3];
- RHS1 += Idr[4];
- RHS1 -= go[4] * *cnV[4];
- m_A4 += gt[5];
- m_A4 += gt[6];
- m_A4 += gt[7];
- m_A4 += gt[8];
- m_A4 += gt[9];
- m_A4 += gt[10];
- m_A4 += gt[11];
- m_A5 += go[5];
- double RHS2 = Idr[5];
- RHS2 += Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 += Idr[9];
- RHS2 += Idr[10];
- RHS2 += Idr[11];
- RHS2 -= go[6] * *cnV[6];
- RHS2 -= go[7] * *cnV[7];
- RHS2 -= go[8] * *cnV[8];
- RHS2 -= go[9] * *cnV[9];
- RHS2 -= go[10] * *cnV[10];
- RHS2 -= go[11] * *cnV[11];
- m_A6 += gt[12];
- m_A6 += gt[13];
- m_A6 += gt[14];
- m_A7 += go[12];
- double RHS3 = Idr[12];
- RHS3 += Idr[13];
- RHS3 += Idr[14];
- RHS3 -= go[13] * *cnV[13];
- RHS3 -= go[14] * *cnV[14];
- m_A8 += gt[15];
- m_A8 += gt[16];
- m_A8 += gt[17];
- m_A8 += gt[18];
- m_A8 += gt[19];
- m_A8 += gt[20];
- m_A8 += gt[21];
- m_A9 += go[15];
- double RHS4 = Idr[15];
- RHS4 += Idr[16];
- RHS4 += Idr[17];
- RHS4 += Idr[18];
- RHS4 += Idr[19];
- RHS4 += Idr[20];
- RHS4 += Idr[21];
- RHS4 -= go[16] * *cnV[16];
- RHS4 -= go[17] * *cnV[17];
- RHS4 -= go[18] * *cnV[18];
- RHS4 -= go[19] * *cnV[19];
- RHS4 -= go[20] * *cnV[20];
- RHS4 -= go[21] * *cnV[21];
- m_A10 += gt[22];
- m_A10 += gt[23];
- m_A11 += go[22];
- double RHS5 = Idr[22];
- RHS5 += Idr[23];
- RHS5 -= go[23] * *cnV[23];
- m_A12 += gt[24];
- m_A12 += gt[25];
- m_A14 += go[24];
- m_A13 += go[25];
- double RHS6 = Idr[24];
- RHS6 += Idr[25];
- m_A15 += gt[26];
- m_A15 += gt[27];
- m_A16 += go[26];
- double RHS7 = Idr[26];
- RHS7 += Idr[27];
- RHS7 -= go[27] * *cnV[27];
- m_A17 += gt[28];
- m_A17 += gt[29];
- m_A18 += go[28];
- double RHS8 = Idr[28];
- RHS8 += Idr[29];
- RHS8 -= go[29] * *cnV[29];
- m_A20 += gt[30];
- m_A20 += gt[31];
- m_A20 += gt[32];
- m_A20 += gt[33];
- m_A19 += go[30];
- double RHS9 = Idr[30];
- RHS9 += Idr[31];
- RHS9 += Idr[32];
- RHS9 += Idr[33];
- RHS9 -= go[31] * *cnV[31];
- RHS9 -= go[32] * *cnV[32];
- RHS9 -= go[33] * *cnV[33];
- m_A24 += gt[34];
- m_A24 += gt[35];
- m_A23 += go[34];
- m_A22 += go[35];
- double RHS10 = Idr[34];
- RHS10 += Idr[35];
- m_A27 += gt[36];
- m_A27 += gt[37];
- m_A27 += gt[38];
- m_A27 += gt[39];
- m_A26 += go[36];
- m_A28 += go[37];
- double RHS11 = Idr[36];
- RHS11 += Idr[37];
- RHS11 += Idr[38];
- RHS11 += Idr[39];
- RHS11 -= go[38] * *cnV[38];
- RHS11 -= go[39] * *cnV[39];
- m_A31 += gt[40];
- m_A31 += gt[41];
- m_A31 += gt[42];
- m_A31 += gt[43];
- m_A31 += gt[44];
- m_A31 += gt[45];
- m_A29 += go[40];
- m_A33 += go[41];
- m_A32 += go[42];
- double RHS12 = Idr[40];
- RHS12 += Idr[41];
- RHS12 += Idr[42];
- RHS12 += Idr[43];
- RHS12 += Idr[44];
- RHS12 += Idr[45];
- RHS12 -= go[43] * *cnV[43];
- RHS12 -= go[44] * *cnV[44];
- RHS12 -= go[45] * *cnV[45];
- m_A36 += gt[46];
- m_A36 += gt[47];
- m_A34 += go[46];
- double RHS13 = Idr[46];
- RHS13 += Idr[47];
- RHS13 -= go[47] * *cnV[47];
- m_A39 += gt[48];
- m_A39 += gt[49];
- m_A39 += gt[50];
- m_A38 += go[48];
- m_A37 += go[49];
- double RHS14 = Idr[48];
- RHS14 += Idr[49];
- RHS14 += Idr[50];
- RHS14 -= go[50] * *cnV[50];
- m_A41 += gt[51];
- m_A41 += gt[52];
- m_A41 += gt[53];
- m_A41 += gt[54];
- m_A40 += go[51];
- m_A42 += go[52];
- double RHS15 = Idr[51];
- RHS15 += Idr[52];
- RHS15 += Idr[53];
- RHS15 += Idr[54];
- RHS15 -= go[53] * *cnV[53];
- RHS15 -= go[54] * *cnV[54];
- m_A49 += gt[55];
- m_A49 += gt[56];
- m_A49 += gt[57];
- m_A49 += gt[58];
- m_A49 += gt[59];
- m_A44 += go[55];
- m_A47 += go[56];
- m_A46 += go[57];
- m_A43 += go[58];
- m_A45 += go[59];
- double RHS16 = Idr[55];
- RHS16 += Idr[56];
- RHS16 += Idr[57];
- RHS16 += Idr[58];
- RHS16 += Idr[59];
- m_A56 += gt[60];
- m_A56 += gt[61];
- m_A56 += gt[62];
- m_A56 += gt[63];
- m_A54 += go[60];
- m_A53 += go[61];
- m_A51 += go[62];
- m_A52 += go[63];
- double RHS17 = Idr[60];
- RHS17 += Idr[61];
- RHS17 += Idr[62];
- RHS17 += Idr[63];
- const double f0 = 1.0 / m_A0;
- const double f0_11 = -f0 * m_A26;
- m_A28 += m_A1 * f0_11;
- RHS11 += f0_11 * RHS0;
- const double f0_16 = -f0 * m_A43;
- m_A49 += m_A1 * f0_16;
- RHS16 += f0_16 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_16 = -f1 * m_A44;
- m_A49 += m_A3 * f1_16;
- RHS16 += f1_16 * RHS1;
- const double f2 = 1.0 / m_A4;
- const double f2_12 = -f2 * m_A29;
- m_A30 += m_A5 * f2_12;
- RHS12 += f2_12 * RHS2;
- const double f3 = 1.0 / m_A6;
- const double f3_15 = -f3 * m_A40;
- m_A42 += m_A7 * f3_15;
- RHS15 += f3_15 * RHS3;
- const double f3_17 = -f3 * m_A51;
- m_A56 += m_A7 * f3_17;
- RHS17 += f3_17 * RHS3;
- const double f4 = 1.0 / m_A8;
- const double f4_9 = -f4 * m_A19;
- m_A21 += m_A9 * f4_9;
- RHS9 += f4_9 * RHS4;
- const double f5 = 1.0 / m_A10;
- const double f5_10 = -f5 * m_A22;
- m_A24 += m_A11 * f5_10;
- RHS10 += f5_10 * RHS5;
- const double f5_16 = -f5 * m_A45;
- m_A46 += m_A11 * f5_16;
- RHS16 += f5_16 * RHS5;
- const double f6 = 1.0 / m_A12;
- const double f6_10 = -f6 * m_A23;
- m_A24 += m_A13 * f6_10;
- m_A25 += m_A14 * f6_10;
- RHS10 += f6_10 * RHS6;
- const double f6_13 = -f6 * m_A34;
- m_A35 += m_A13 * f6_13;
- m_A36 += m_A14 * f6_13;
- RHS13 += f6_13 * RHS6;
- const double f7 = 1.0 / m_A15;
- const double f7_14 = -f7 * m_A37;
- m_A39 += m_A16 * f7_14;
- RHS14 += f7_14 * RHS7;
- const double f7_17 = -f7 * m_A52;
- m_A54 += m_A16 * f7_17;
- RHS17 += f7_17 * RHS7;
- const double f8 = 1.0 / m_A17;
- const double f8_14 = -f8 * m_A38;
- m_A39 += m_A18 * f8_14;
- RHS14 += f8_14 * RHS8;
- const double f10 = 1.0 / m_A24;
- const double f10_13 = -f10 * m_A35;
- m_A36 += m_A25 * f10_13;
- RHS13 += f10_13 * RHS10;
- const double f10_16 = -f10 * m_A46;
- m_A48 += m_A25 * f10_16;
- RHS16 += f10_16 * RHS10;
- const double f11 = 1.0 / m_A27;
- const double f11_12 = -f11 * m_A30;
- m_A32 += m_A28 * f11_12;
- RHS12 += f11_12 * RHS11;
- const double f12 = 1.0 / m_A31;
- const double f12_16 = -f12 * m_A47;
- m_A49 += m_A32 * f12_16;
- m_A50 += m_A33 * f12_16;
- RHS16 += f12_16 * RHS12;
- const double f12_17 = -f12 * m_A53;
- m_A55 += m_A32 * f12_17;
- m_A56 += m_A33 * f12_17;
- RHS17 += f12_17 * RHS12;
- const double f13 = 1.0 / m_A36;
- const double f13_16 = -f13 * m_A48;
- RHS16 += f13_16 * RHS13;
- const double f14 = 1.0 / m_A39;
- const double f14_17 = -f14 * m_A54;
- RHS17 += f14_17 * RHS14;
- const double f16 = 1.0 / m_A49;
- const double f16_17 = -f16 * m_A55;
- m_A56 += m_A50 * f16_17;
- RHS17 += f16_17 * RHS16;
- V[17] = RHS17 / m_A56;
- double tmp16 = 0.0;
- tmp16 += m_A50 * V[17];
- V[16] = (RHS16 - tmp16) / m_A49;
- double tmp15 = 0.0;
- tmp15 += m_A42 * V[17];
- V[15] = (RHS15 - tmp15) / m_A41;
- double tmp14 = 0.0;
- V[14] = (RHS14 - tmp14) / m_A39;
- double tmp13 = 0.0;
- V[13] = (RHS13 - tmp13) / m_A36;
- double tmp12 = 0.0;
- tmp12 += m_A32 * V[16];
- tmp12 += m_A33 * V[17];
- V[12] = (RHS12 - tmp12) / m_A31;
- double tmp11 = 0.0;
- tmp11 += m_A28 * V[16];
- V[11] = (RHS11 - tmp11) / m_A27;
- double tmp10 = 0.0;
- tmp10 += m_A25 * V[13];
- V[10] = (RHS10 - tmp10) / m_A24;
- double tmp9 = 0.0;
- tmp9 += m_A21 * V[15];
- V[9] = (RHS9 - tmp9) / m_A20;
- double tmp8 = 0.0;
- tmp8 += m_A18 * V[14];
- V[8] = (RHS8 - tmp8) / m_A17;
- double tmp7 = 0.0;
- tmp7 += m_A16 * V[14];
- V[7] = (RHS7 - tmp7) / m_A15;
- double tmp6 = 0.0;
- tmp6 += m_A13 * V[10];
- tmp6 += m_A14 * V[13];
- V[6] = (RHS6 - tmp6) / m_A12;
- double tmp5 = 0.0;
- tmp5 += m_A11 * V[10];
- V[5] = (RHS5 - tmp5) / m_A10;
- double tmp4 = 0.0;
- tmp4 += m_A9 * V[15];
- V[4] = (RHS4 - tmp4) / m_A8;
- double tmp3 = 0.0;
- tmp3 += m_A7 * V[17];
- V[3] = (RHS3 - tmp3) / m_A6;
- double tmp2 = 0.0;
- tmp2 += m_A5 * V[11];
- V[2] = (RHS2 - tmp2) / m_A4;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[16];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[16];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// 280zzzap
static void nl_gcr_95_double_double_24643c159711f292(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -6698,107 +3972,6 @@ static void nl_gcr_67_double_double_ee2cacaa15d32491(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// astrob,rebound
-static void nl_gcr_13_double_double_a41a44bd5c424f88(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A0 += gt[2];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 += Idr[2];
- RHS0 -= go[1] * *cnV[1];
- RHS0 -= go[2] * *cnV[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A2 += gt[5];
- m_A3 += go[3];
- double RHS1 = Idr[3];
- RHS1 += Idr[4];
- RHS1 += Idr[5];
- RHS1 -= go[4] * *cnV[4];
- RHS1 -= go[5] * *cnV[5];
- m_A4 += gt[6];
- m_A4 += gt[7];
- m_A4 += gt[8];
- m_A5 += go[6];
- double RHS2 = Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 -= go[7] * *cnV[7];
- RHS2 -= go[8] * *cnV[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A6 += gt[11];
- m_A7 += go[9];
- double RHS3 = Idr[9];
- RHS3 += Idr[10];
- RHS3 += Idr[11];
- RHS3 -= go[10] * *cnV[10];
- RHS3 -= go[11] * *cnV[11];
- m_A12 += gt[12];
- m_A12 += gt[13];
- m_A12 += gt[14];
- m_A12 += gt[15];
- m_A12 += gt[16];
- m_A11 += go[12];
- m_A10 += go[13];
- m_A9 += go[14];
- m_A8 += go[15];
- double RHS4 = Idr[12];
- RHS4 += Idr[13];
- RHS4 += Idr[14];
- RHS4 += Idr[15];
- RHS4 += Idr[16];
- RHS4 -= go[16] * *cnV[16];
- const double f0 = 1.0 / m_A0;
- const double f0_4 = -f0 * m_A8;
- m_A12 += m_A1 * f0_4;
- RHS4 += f0_4 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_4 = -f1 * m_A9;
- m_A12 += m_A3 * f1_4;
- RHS4 += f1_4 * RHS1;
- const double f2 = 1.0 / m_A4;
- const double f2_4 = -f2 * m_A10;
- m_A12 += m_A5 * f2_4;
- RHS4 += f2_4 * RHS2;
- const double f3 = 1.0 / m_A6;
- const double f3_4 = -f3 * m_A11;
- m_A12 += m_A7 * f3_4;
- RHS4 += f3_4 * RHS3;
- V[4] = RHS4 / m_A12;
- double tmp3 = 0.0;
- tmp3 += m_A7 * V[4];
- V[3] = (RHS3 - tmp3) / m_A6;
- double tmp2 = 0.0;
- tmp2 += m_A5 * V[4];
- V[2] = (RHS2 - tmp2) / m_A4;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[4];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[4];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// astrob
static void nl_gcr_154_double_double_13833bf8c127deaa(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -18473,60 +15646,6 @@ static void nl_gcr_77_double_double_437326911721091(double * __restrict V, const
V[0] = (RHS0 - tmp0) / m_A0;
}
-// brdrline,stuntcyc
-static void nl_gcr_7_double_double_59cb6bf7cb9d17dc(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A3 += go[2];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 -= go[3] * *cnV[3];
- m_A6 += gt[4];
- m_A6 += gt[5];
- m_A6 += gt[6];
- m_A6 += gt[7];
- m_A5 += go[4];
- m_A4 += go[5];
- double RHS2 = Idr[4];
- RHS2 += Idr[5];
- RHS2 += Idr[6];
- RHS2 += Idr[7];
- RHS2 -= go[6] * *cnV[6];
- RHS2 -= go[7] * *cnV[7];
- const double f0 = 1.0 / m_A0;
- const double f0_2 = -f0 * m_A4;
- m_A6 += m_A1 * f0_2;
- RHS2 += f0_2 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_2 = -f1 * m_A5;
- m_A6 += m_A3 * f1_2;
- RHS2 += f1_2 * RHS1;
- V[2] = RHS2 / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[2];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[2];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// brdrline
static void nl_gcr_83_double_double_f99b1245e708ec85(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -26154,6 +23273,1582 @@ static void nl_gcr_399_double_double_4334c95878d1be92(double * __restrict V, con
V[0] = (RHS0 - tmp0) / m_A0;
}
+// dribling
+static void nl_gcr_21_double_double_c9b5f1625a51d98f(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A2 += gt[7];
+ m_A2 += gt[8];
+ m_A4 += go[3];
+ m_A3 += go[4];
+ m_A3 += go[5];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 += Idr[7];
+ RHS1 += Idr[8];
+ RHS1 -= go[6] * *cnV[6];
+ RHS1 -= go[7] * *cnV[7];
+ RHS1 -= go[8] * *cnV[8];
+ m_A5 += gt[9];
+ m_A5 += gt[10];
+ m_A5 += gt[11];
+ m_A5 += gt[12];
+ m_A6 += go[9];
+ double RHS2 = Idr[9];
+ RHS2 += Idr[10];
+ RHS2 += Idr[11];
+ RHS2 += Idr[12];
+ RHS2 -= go[10] * *cnV[10];
+ RHS2 -= go[11] * *cnV[11];
+ RHS2 -= go[12] * *cnV[12];
+ m_A7 += gt[13];
+ m_A7 += gt[14];
+ m_A8 += go[13];
+ double RHS3 = Idr[13];
+ RHS3 += Idr[14];
+ RHS3 -= go[14] * *cnV[14];
+ m_A11 += gt[15];
+ m_A11 += gt[16];
+ m_A11 += gt[17];
+ m_A11 += gt[18];
+ m_A11 += gt[19];
+ m_A9 += go[15];
+ m_A10 += go[16];
+ m_A10 += go[17];
+ double RHS4 = Idr[15];
+ RHS4 += Idr[16];
+ RHS4 += Idr[17];
+ RHS4 += Idr[18];
+ RHS4 += Idr[19];
+ RHS4 -= go[18] * *cnV[18];
+ RHS4 -= go[19] * *cnV[19];
+ m_A15 += gt[20];
+ m_A15 += gt[21];
+ m_A16 += go[20];
+ m_A13 += go[21];
+ double RHS5 = Idr[20];
+ RHS5 += Idr[21];
+ m_A20 += gt[22];
+ m_A20 += gt[23];
+ m_A20 += gt[24];
+ m_A20 += gt[25];
+ m_A20 += gt[26];
+ m_A20 += gt[27];
+ m_A18 += go[22];
+ m_A19 += go[23];
+ m_A17 += go[24];
+ double RHS6 = Idr[22];
+ RHS6 += Idr[23];
+ RHS6 += Idr[24];
+ RHS6 += Idr[25];
+ RHS6 += Idr[26];
+ RHS6 += Idr[27];
+ RHS6 -= go[25] * *cnV[25];
+ RHS6 -= go[26] * *cnV[26];
+ RHS6 -= go[27] * *cnV[27];
+ const double f0 = 1.0 / m_A0;
+ const double f0_4 = -f0 * m_A9;
+ m_A11 += m_A1 * f0_4;
+ RHS4 += f0_4 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_4 = -f1 * m_A10;
+ m_A11 += m_A3 * f1_4;
+ m_A12 += m_A4 * f1_4;
+ RHS4 += f1_4 * RHS1;
+ const double f1_5 = -f1 * m_A13;
+ m_A14 += m_A3 * f1_5;
+ m_A15 += m_A4 * f1_5;
+ RHS5 += f1_5 * RHS1;
+ const double f2 = 1.0 / m_A5;
+ const double f2_6 = -f2 * m_A17;
+ m_A20 += m_A6 * f2_6;
+ RHS6 += f2_6 * RHS2;
+ const double f3 = 1.0 / m_A7;
+ const double f3_6 = -f3 * m_A18;
+ m_A20 += m_A8 * f3_6;
+ RHS6 += f3_6 * RHS3;
+ const double f4 = 1.0 / m_A11;
+ const double f4_5 = -f4 * m_A14;
+ m_A15 += m_A12 * f4_5;
+ RHS5 += f4_5 * RHS4;
+ const double f5 = 1.0 / m_A15;
+ const double f5_6 = -f5 * m_A19;
+ m_A20 += m_A16 * f5_6;
+ RHS6 += f5_6 * RHS5;
+ V[6] = RHS6 / m_A20;
+ double tmp5 = 0.0;
+ tmp5 += m_A16 * V[6];
+ V[5] = (RHS5 - tmp5) / m_A15;
+ double tmp4 = 0.0;
+ tmp4 += m_A12 * V[5];
+ V[4] = (RHS4 - tmp4) / m_A11;
+ double tmp3 = 0.0;
+ tmp3 += m_A8 * V[6];
+ V[3] = (RHS3 - tmp3) / m_A7;
+ double tmp2 = 0.0;
+ tmp2 += m_A6 * V[6];
+ V[2] = (RHS2 - tmp2) / m_A5;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[4];
+ tmp1 += m_A4 * V[5];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[4];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// dribling
+static void nl_gcr_28_double_double_99f81817ea8bea2d(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 -= go[4] * *cnV[4];
+ RHS1 -= go[5] * *cnV[5];
+ m_A4 += gt[6];
+ m_A4 += gt[7];
+ m_A4 += gt[8];
+ m_A5 += go[6];
+ double RHS2 = Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 -= go[7] * *cnV[7];
+ RHS2 -= go[8] * *cnV[8];
+ m_A7 += gt[9];
+ m_A7 += gt[10];
+ m_A7 += gt[11];
+ m_A7 += gt[12];
+ m_A7 += gt[13];
+ m_A7 += gt[14];
+ m_A7 += gt[15];
+ m_A6 += go[9];
+ m_A8 += go[10];
+ double RHS3 = Idr[9];
+ RHS3 += Idr[10];
+ RHS3 += Idr[11];
+ RHS3 += Idr[12];
+ RHS3 += Idr[13];
+ RHS3 += Idr[14];
+ RHS3 += Idr[15];
+ RHS3 -= go[11] * *cnV[11];
+ RHS3 -= go[12] * *cnV[12];
+ RHS3 -= go[13] * *cnV[13];
+ RHS3 -= go[14] * *cnV[14];
+ RHS3 -= go[15] * *cnV[15];
+ m_A9 += gt[16];
+ m_A9 += gt[17];
+ m_A9 += gt[18];
+ m_A10 += go[16];
+ double RHS4 = Idr[16];
+ RHS4 += Idr[17];
+ RHS4 += Idr[18];
+ RHS4 -= go[17] * *cnV[17];
+ RHS4 -= go[18] * *cnV[18];
+ m_A11 += gt[19];
+ m_A11 += gt[20];
+ m_A12 += go[19];
+ double RHS5 = Idr[19];
+ RHS5 += Idr[20];
+ RHS5 -= go[20] * *cnV[20];
+ m_A14 += gt[21];
+ m_A14 += gt[22];
+ m_A14 += gt[23];
+ m_A13 += go[21];
+ m_A15 += go[22];
+ m_A16 += go[23];
+ double RHS6 = Idr[21];
+ RHS6 += Idr[22];
+ RHS6 += Idr[23];
+ m_A19 += gt[24];
+ m_A19 += gt[25];
+ m_A19 += gt[26];
+ m_A19 += gt[27];
+ m_A19 += gt[28];
+ m_A19 += gt[29];
+ m_A17 += go[24];
+ m_A18 += go[25];
+ m_A20 += go[26];
+ double RHS7 = Idr[24];
+ RHS7 += Idr[25];
+ RHS7 += Idr[26];
+ RHS7 += Idr[27];
+ RHS7 += Idr[28];
+ RHS7 += Idr[29];
+ RHS7 -= go[27] * *cnV[27];
+ RHS7 -= go[28] * *cnV[28];
+ RHS7 -= go[29] * *cnV[29];
+ m_A27 += gt[30];
+ m_A27 += gt[31];
+ m_A27 += gt[32];
+ m_A27 += gt[33];
+ m_A27 += gt[34];
+ m_A27 += gt[35];
+ m_A27 += gt[36];
+ m_A24 += go[30];
+ m_A25 += go[31];
+ m_A26 += go[32];
+ m_A23 += go[33];
+ m_A22 += go[34];
+ m_A21 += go[35];
+ double RHS8 = Idr[30];
+ RHS8 += Idr[31];
+ RHS8 += Idr[32];
+ RHS8 += Idr[33];
+ RHS8 += Idr[34];
+ RHS8 += Idr[35];
+ RHS8 += Idr[36];
+ RHS8 -= go[36] * *cnV[36];
+ const double f0 = 1.0 / m_A0;
+ const double f0_8 = -f0 * m_A21;
+ m_A27 += m_A1 * f0_8;
+ RHS8 += f0_8 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_8 = -f1 * m_A22;
+ m_A27 += m_A3 * f1_8;
+ RHS8 += f1_8 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_3 = -f2 * m_A6;
+ m_A8 += m_A5 * f2_3;
+ RHS3 += f2_3 * RHS2;
+ const double f2_6 = -f2 * m_A13;
+ m_A14 += m_A5 * f2_6;
+ RHS6 += f2_6 * RHS2;
+ const double f3 = 1.0 / m_A7;
+ const double f3_7 = -f3 * m_A17;
+ m_A18 += m_A8 * f3_7;
+ RHS7 += f3_7 * RHS3;
+ const double f4 = 1.0 / m_A9;
+ const double f4_8 = -f4 * m_A23;
+ m_A27 += m_A10 * f4_8;
+ RHS8 += f4_8 * RHS4;
+ const double f5 = 1.0 / m_A11;
+ const double f5_8 = -f5 * m_A24;
+ m_A27 += m_A12 * f5_8;
+ RHS8 += f5_8 * RHS5;
+ const double f6 = 1.0 / m_A14;
+ const double f6_7 = -f6 * m_A18;
+ m_A19 += m_A15 * f6_7;
+ m_A20 += m_A16 * f6_7;
+ RHS7 += f6_7 * RHS6;
+ const double f6_8 = -f6 * m_A25;
+ m_A26 += m_A15 * f6_8;
+ m_A27 += m_A16 * f6_8;
+ RHS8 += f6_8 * RHS6;
+ const double f7 = 1.0 / m_A19;
+ const double f7_8 = -f7 * m_A26;
+ m_A27 += m_A20 * f7_8;
+ RHS8 += f7_8 * RHS7;
+ V[8] = RHS8 / m_A27;
+ double tmp7 = 0.0;
+ tmp7 += m_A20 * V[8];
+ V[7] = (RHS7 - tmp7) / m_A19;
+ double tmp6 = 0.0;
+ tmp6 += m_A15 * V[7];
+ tmp6 += m_A16 * V[8];
+ V[6] = (RHS6 - tmp6) / m_A14;
+ double tmp5 = 0.0;
+ tmp5 += m_A12 * V[8];
+ V[5] = (RHS5 - tmp5) / m_A11;
+ double tmp4 = 0.0;
+ tmp4 += m_A10 * V[8];
+ V[4] = (RHS4 - tmp4) / m_A9;
+ double tmp3 = 0.0;
+ tmp3 += m_A8 * V[6];
+ V[3] = (RHS3 - tmp3) / m_A7;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[6];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[8];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[8];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// dribling
+static void nl_gcr_29_double_double_1e732268bc2d78b2(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A2 += gt[7];
+ m_A2 += gt[8];
+ m_A4 += go[3];
+ m_A3 += go[4];
+ m_A3 += go[5];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 += Idr[7];
+ RHS1 += Idr[8];
+ RHS1 -= go[6] * *cnV[6];
+ RHS1 -= go[7] * *cnV[7];
+ RHS1 -= go[8] * *cnV[8];
+ m_A5 += gt[9];
+ m_A5 += gt[10];
+ m_A5 += gt[11];
+ m_A5 += gt[12];
+ m_A6 += go[9];
+ double RHS2 = Idr[9];
+ RHS2 += Idr[10];
+ RHS2 += Idr[11];
+ RHS2 += Idr[12];
+ RHS2 -= go[10] * *cnV[10];
+ RHS2 -= go[11] * *cnV[11];
+ RHS2 -= go[12] * *cnV[12];
+ m_A7 += gt[13];
+ m_A7 += gt[14];
+ m_A7 += gt[15];
+ m_A7 += gt[16];
+ m_A8 += go[13];
+ m_A9 += go[14];
+ m_A9 += go[15];
+ double RHS3 = Idr[13];
+ RHS3 += Idr[14];
+ RHS3 += Idr[15];
+ RHS3 += Idr[16];
+ RHS3 -= go[16] * *cnV[16];
+ m_A10 += gt[17];
+ m_A10 += gt[18];
+ m_A11 += go[17];
+ double RHS4 = Idr[17];
+ RHS4 += Idr[18];
+ RHS4 -= go[18] * *cnV[18];
+ m_A14 += gt[19];
+ m_A14 += gt[20];
+ m_A14 += gt[21];
+ m_A14 += gt[22];
+ m_A14 += gt[23];
+ m_A12 += go[19];
+ m_A13 += go[20];
+ m_A13 += go[21];
+ double RHS5 = Idr[19];
+ RHS5 += Idr[20];
+ RHS5 += Idr[21];
+ RHS5 += Idr[22];
+ RHS5 += Idr[23];
+ RHS5 -= go[22] * *cnV[22];
+ RHS5 -= go[23] * *cnV[23];
+ m_A18 += gt[24];
+ m_A18 += gt[25];
+ m_A19 += go[24];
+ m_A16 += go[25];
+ double RHS6 = Idr[24];
+ RHS6 += Idr[25];
+ m_A22 += gt[26];
+ m_A22 += gt[27];
+ m_A21 += go[26];
+ m_A20 += go[27];
+ double RHS7 = Idr[26];
+ RHS7 += Idr[27];
+ m_A28 += gt[28];
+ m_A28 += gt[29];
+ m_A28 += gt[30];
+ m_A28 += gt[31];
+ m_A28 += gt[32];
+ m_A28 += gt[33];
+ m_A28 += gt[34];
+ m_A28 += gt[35];
+ m_A28 += gt[36];
+ m_A28 += gt[37];
+ m_A25 += go[28];
+ m_A25 += go[29];
+ m_A28 += go[30];
+ m_A28 += go[31];
+ m_A28 += go[32];
+ m_A28 += go[33];
+ m_A26 += go[34];
+ m_A24 += go[35];
+ double RHS8 = Idr[28];
+ RHS8 += Idr[29];
+ RHS8 += Idr[30];
+ RHS8 += Idr[31];
+ RHS8 += Idr[32];
+ RHS8 += Idr[33];
+ RHS8 += Idr[34];
+ RHS8 += Idr[35];
+ RHS8 += Idr[36];
+ RHS8 += Idr[37];
+ RHS8 -= go[36] * *cnV[36];
+ RHS8 -= go[37] * *cnV[37];
+ const double f0 = 1.0 / m_A0;
+ const double f0_5 = -f0 * m_A12;
+ m_A14 += m_A1 * f0_5;
+ RHS5 += f0_5 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_5 = -f1 * m_A13;
+ m_A14 += m_A3 * f1_5;
+ m_A15 += m_A4 * f1_5;
+ RHS5 += f1_5 * RHS1;
+ const double f1_6 = -f1 * m_A16;
+ m_A17 += m_A3 * f1_6;
+ m_A18 += m_A4 * f1_6;
+ RHS6 += f1_6 * RHS1;
+ const double f2 = 1.0 / m_A5;
+ const double f2_8 = -f2 * m_A24;
+ m_A28 += m_A6 * f2_8;
+ RHS8 += f2_8 * RHS2;
+ const double f3 = 1.0 / m_A7;
+ const double f3_7 = -f3 * m_A20;
+ m_A22 += m_A8 * f3_7;
+ m_A23 += m_A9 * f3_7;
+ RHS7 += f3_7 * RHS3;
+ const double f3_8 = -f3 * m_A25;
+ m_A27 += m_A8 * f3_8;
+ m_A28 += m_A9 * f3_8;
+ RHS8 += f3_8 * RHS3;
+ const double f4 = 1.0 / m_A10;
+ const double f4_7 = -f4 * m_A21;
+ m_A22 += m_A11 * f4_7;
+ RHS7 += f4_7 * RHS4;
+ const double f5 = 1.0 / m_A14;
+ const double f5_6 = -f5 * m_A17;
+ m_A18 += m_A15 * f5_6;
+ RHS6 += f5_6 * RHS5;
+ const double f6 = 1.0 / m_A18;
+ const double f6_8 = -f6 * m_A26;
+ m_A28 += m_A19 * f6_8;
+ RHS8 += f6_8 * RHS6;
+ const double f7 = 1.0 / m_A22;
+ const double f7_8 = -f7 * m_A27;
+ m_A28 += m_A23 * f7_8;
+ RHS8 += f7_8 * RHS7;
+ V[8] = RHS8 / m_A28;
+ double tmp7 = 0.0;
+ tmp7 += m_A23 * V[8];
+ V[7] = (RHS7 - tmp7) / m_A22;
+ double tmp6 = 0.0;
+ tmp6 += m_A19 * V[8];
+ V[6] = (RHS6 - tmp6) / m_A18;
+ double tmp5 = 0.0;
+ tmp5 += m_A15 * V[6];
+ V[5] = (RHS5 - tmp5) / m_A14;
+ double tmp4 = 0.0;
+ tmp4 += m_A11 * V[7];
+ V[4] = (RHS4 - tmp4) / m_A10;
+ double tmp3 = 0.0;
+ tmp3 += m_A8 * V[7];
+ tmp3 += m_A9 * V[8];
+ V[3] = (RHS3 - tmp3) / m_A7;
+ double tmp2 = 0.0;
+ tmp2 += m_A6 * V[8];
+ V[2] = (RHS2 - tmp2) / m_A5;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[5];
+ tmp1 += m_A4 * V[6];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[5];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// dribling
+static void nl_gcr_54_double_double_a2823a76b83c45a0(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A0 += gt[3];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 += Idr[3];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ RHS0 -= go[3] * *cnV[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A4 += go[4];
+ m_A3 += go[5];
+ double RHS1 = Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 -= go[6] * *cnV[6];
+ m_A5 += gt[7];
+ m_A5 += gt[8];
+ m_A5 += gt[9];
+ m_A5 += gt[10];
+ m_A6 += go[7];
+ m_A7 += go[8];
+ m_A7 += go[9];
+ double RHS2 = Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 -= go[10] * *cnV[10];
+ m_A8 += gt[11];
+ m_A8 += gt[12];
+ m_A10 += go[11];
+ m_A9 += go[12];
+ double RHS3 = Idr[11];
+ RHS3 += Idr[12];
+ m_A11 += gt[13];
+ m_A11 += gt[14];
+ m_A11 += gt[15];
+ m_A11 += gt[16];
+ m_A11 += gt[17];
+ m_A13 += go[13];
+ m_A12 += go[14];
+ m_A12 += go[15];
+ double RHS4 = Idr[13];
+ RHS4 += Idr[14];
+ RHS4 += Idr[15];
+ RHS4 += Idr[16];
+ RHS4 += Idr[17];
+ RHS4 -= go[16] * *cnV[16];
+ RHS4 -= go[17] * *cnV[17];
+ m_A14 += gt[18];
+ m_A14 += gt[19];
+ m_A15 += go[18];
+ double RHS5 = Idr[18];
+ RHS5 += Idr[19];
+ RHS5 -= go[19] * *cnV[19];
+ m_A17 += gt[20];
+ m_A17 += gt[21];
+ m_A17 += gt[22];
+ m_A19 += go[20];
+ m_A18 += go[21];
+ m_A16 += go[22];
+ double RHS6 = Idr[20];
+ RHS6 += Idr[21];
+ RHS6 += Idr[22];
+ m_A22 += gt[23];
+ m_A22 += gt[24];
+ m_A22 += gt[25];
+ m_A22 += gt[26];
+ m_A22 += gt[27];
+ m_A22 += gt[28];
+ m_A22 += gt[29];
+ m_A21 += go[23];
+ m_A20 += go[24];
+ m_A25 += go[25];
+ m_A25 += go[26];
+ m_A25 += go[27];
+ m_A24 += go[28];
+ double RHS7 = Idr[23];
+ RHS7 += Idr[24];
+ RHS7 += Idr[25];
+ RHS7 += Idr[26];
+ RHS7 += Idr[27];
+ RHS7 += Idr[28];
+ RHS7 += Idr[29];
+ RHS7 -= go[29] * *cnV[29];
+ m_A29 += gt[30];
+ m_A29 += gt[31];
+ m_A29 += gt[32];
+ m_A29 += gt[33];
+ m_A29 += gt[34];
+ m_A29 += gt[35];
+ m_A29 += gt[36];
+ m_A32 += go[30];
+ m_A32 += go[31];
+ m_A27 += go[32];
+ m_A27 += go[33];
+ m_A26 += go[34];
+ double RHS8 = Idr[30];
+ RHS8 += Idr[31];
+ RHS8 += Idr[32];
+ RHS8 += Idr[33];
+ RHS8 += Idr[34];
+ RHS8 += Idr[35];
+ RHS8 += Idr[36];
+ RHS8 -= go[35] * *cnV[35];
+ RHS8 -= go[36] * *cnV[36];
+ m_A37 += gt[37];
+ m_A37 += gt[38];
+ m_A37 += gt[39];
+ m_A35 += go[37];
+ m_A33 += go[38];
+ m_A34 += go[39];
+ double RHS9 = Idr[37];
+ RHS9 += Idr[38];
+ RHS9 += Idr[39];
+ m_A46 += gt[40];
+ m_A46 += gt[41];
+ m_A46 += gt[42];
+ m_A46 += gt[43];
+ m_A46 += gt[44];
+ m_A46 += gt[45];
+ m_A46 += gt[46];
+ m_A41 += go[40];
+ m_A41 += go[41];
+ m_A43 += go[42];
+ m_A43 += go[43];
+ m_A43 += go[44];
+ m_A40 += go[45];
+ m_A42 += go[46];
+ double RHS10 = Idr[40];
+ RHS10 += Idr[41];
+ RHS10 += Idr[42];
+ RHS10 += Idr[43];
+ RHS10 += Idr[44];
+ RHS10 += Idr[45];
+ RHS10 += Idr[46];
+ m_A53 += gt[47];
+ m_A53 += gt[48];
+ m_A53 += gt[49];
+ m_A53 += gt[50];
+ m_A53 += gt[51];
+ m_A49 += go[47];
+ m_A48 += go[48];
+ m_A50 += go[49];
+ m_A50 += go[50];
+ double RHS11 = Idr[47];
+ RHS11 += Idr[48];
+ RHS11 += Idr[49];
+ RHS11 += Idr[50];
+ RHS11 += Idr[51];
+ RHS11 -= go[51] * *cnV[51];
+ const double f0 = 1.0 / m_A0;
+ const double f0_6 = -f0 * m_A16;
+ m_A17 += m_A1 * f0_6;
+ RHS6 += f0_6 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_9 = -f1 * m_A33;
+ m_A37 += m_A3 * f1_9;
+ m_A38 += m_A4 * f1_9;
+ RHS9 += f1_9 * RHS1;
+ const double f1_10 = -f1 * m_A40;
+ m_A45 += m_A3 * f1_10;
+ m_A46 += m_A4 * f1_10;
+ RHS10 += f1_10 * RHS1;
+ const double f2 = 1.0 / m_A5;
+ const double f2_7 = -f2 * m_A20;
+ m_A22 += m_A6 * f2_7;
+ m_A25 += m_A7 * f2_7;
+ RHS7 += f2_7 * RHS2;
+ const double f2_10 = -f2 * m_A41;
+ m_A43 += m_A6 * f2_10;
+ m_A46 += m_A7 * f2_10;
+ RHS10 += f2_10 * RHS2;
+ const double f3 = 1.0 / m_A8;
+ const double f3_7 = -f3 * m_A21;
+ m_A22 += m_A9 * f3_7;
+ m_A23 += m_A10 * f3_7;
+ RHS7 += f3_7 * RHS3;
+ const double f3_8 = -f3 * m_A26;
+ m_A28 += m_A9 * f3_8;
+ m_A29 += m_A10 * f3_8;
+ RHS8 += f3_8 * RHS3;
+ const double f4 = 1.0 / m_A11;
+ const double f4_8 = -f4 * m_A27;
+ m_A29 += m_A12 * f4_8;
+ m_A32 += m_A13 * f4_8;
+ RHS8 += f4_8 * RHS4;
+ const double f4_11 = -f4 * m_A48;
+ m_A50 += m_A12 * f4_11;
+ m_A53 += m_A13 * f4_11;
+ RHS11 += f4_11 * RHS4;
+ const double f5 = 1.0 / m_A14;
+ const double f5_11 = -f5 * m_A49;
+ m_A53 += m_A15 * f5_11;
+ RHS11 += f5_11 * RHS5;
+ const double f6 = 1.0 / m_A17;
+ const double f6_9 = -f6 * m_A34;
+ m_A37 += m_A18 * f6_9;
+ m_A38 += m_A19 * f6_9;
+ RHS9 += f6_9 * RHS6;
+ const double f6_10 = -f6 * m_A42;
+ m_A45 += m_A18 * f6_10;
+ m_A46 += m_A19 * f6_10;
+ RHS10 += f6_10 * RHS6;
+ const double f7 = 1.0 / m_A22;
+ const double f7_8 = -f7 * m_A28;
+ m_A29 += m_A23 * f7_8;
+ m_A30 += m_A24 * f7_8;
+ m_A31 += m_A25 * f7_8;
+ RHS8 += f7_8 * RHS7;
+ const double f7_9 = -f7 * m_A35;
+ m_A36 += m_A23 * f7_9;
+ m_A37 += m_A24 * f7_9;
+ m_A38 += m_A25 * f7_9;
+ RHS9 += f7_9 * RHS7;
+ const double f7_10 = -f7 * m_A43;
+ m_A44 += m_A23 * f7_10;
+ m_A45 += m_A24 * f7_10;
+ m_A46 += m_A25 * f7_10;
+ RHS10 += f7_10 * RHS7;
+ const double f8 = 1.0 / m_A29;
+ const double f8_9 = -f8 * m_A36;
+ m_A37 += m_A30 * f8_9;
+ m_A38 += m_A31 * f8_9;
+ m_A39 += m_A32 * f8_9;
+ RHS9 += f8_9 * RHS8;
+ const double f8_10 = -f8 * m_A44;
+ m_A45 += m_A30 * f8_10;
+ m_A46 += m_A31 * f8_10;
+ m_A47 += m_A32 * f8_10;
+ RHS10 += f8_10 * RHS8;
+ const double f8_11 = -f8 * m_A50;
+ m_A51 += m_A30 * f8_11;
+ m_A52 += m_A31 * f8_11;
+ m_A53 += m_A32 * f8_11;
+ RHS11 += f8_11 * RHS8;
+ const double f9 = 1.0 / m_A37;
+ const double f9_10 = -f9 * m_A45;
+ m_A46 += m_A38 * f9_10;
+ m_A47 += m_A39 * f9_10;
+ RHS10 += f9_10 * RHS9;
+ const double f9_11 = -f9 * m_A51;
+ m_A52 += m_A38 * f9_11;
+ m_A53 += m_A39 * f9_11;
+ RHS11 += f9_11 * RHS9;
+ const double f10 = 1.0 / m_A46;
+ const double f10_11 = -f10 * m_A52;
+ m_A53 += m_A47 * f10_11;
+ RHS11 += f10_11 * RHS10;
+ V[11] = RHS11 / m_A53;
+ double tmp10 = 0.0;
+ tmp10 += m_A47 * V[11];
+ V[10] = (RHS10 - tmp10) / m_A46;
+ double tmp9 = 0.0;
+ tmp9 += m_A38 * V[10];
+ tmp9 += m_A39 * V[11];
+ V[9] = (RHS9 - tmp9) / m_A37;
+ double tmp8 = 0.0;
+ tmp8 += m_A30 * V[9];
+ tmp8 += m_A31 * V[10];
+ tmp8 += m_A32 * V[11];
+ V[8] = (RHS8 - tmp8) / m_A29;
+ double tmp7 = 0.0;
+ tmp7 += m_A23 * V[8];
+ tmp7 += m_A24 * V[9];
+ tmp7 += m_A25 * V[10];
+ V[7] = (RHS7 - tmp7) / m_A22;
+ double tmp6 = 0.0;
+ tmp6 += m_A18 * V[9];
+ tmp6 += m_A19 * V[10];
+ V[6] = (RHS6 - tmp6) / m_A17;
+ double tmp5 = 0.0;
+ tmp5 += m_A15 * V[11];
+ V[5] = (RHS5 - tmp5) / m_A14;
+ double tmp4 = 0.0;
+ tmp4 += m_A12 * V[8];
+ tmp4 += m_A13 * V[11];
+ V[4] = (RHS4 - tmp4) / m_A11;
+ double tmp3 = 0.0;
+ tmp3 += m_A9 * V[7];
+ tmp3 += m_A10 * V[8];
+ V[3] = (RHS3 - tmp3) / m_A8;
+ double tmp2 = 0.0;
+ tmp2 += m_A6 * V[7];
+ tmp2 += m_A7 * V[10];
+ V[2] = (RHS2 - tmp2) / m_A5;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[9];
+ tmp1 += m_A4 * V[10];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[6];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// dribling
+static void nl_gcr_7_double_double_a1ecff4d37b54b76(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A0 += gt[3];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 += Idr[3];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ RHS0 -= go[3] * *cnV[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A3 += go[4];
+ double RHS1 = Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 -= go[5] * *cnV[5];
+ RHS1 -= go[6] * *cnV[6];
+ m_A6 += gt[7];
+ m_A6 += gt[8];
+ m_A6 += gt[9];
+ m_A5 += go[7];
+ m_A4 += go[8];
+ double RHS2 = Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 -= go[9] * *cnV[9];
+ const double f0 = 1.0 / m_A0;
+ const double f0_2 = -f0 * m_A4;
+ m_A6 += m_A1 * f0_2;
+ RHS2 += f0_2 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ V[2] = RHS2 / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[2];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// dribling
+static void nl_gcr_95_double_double_a0159c41cfc0b644(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ double m_A54(0.0);
+ double m_A55(0.0);
+ double m_A56(0.0);
+ double m_A57(0.0);
+ double m_A58(0.0);
+ double m_A59(0.0);
+ double m_A60(0.0);
+ double m_A61(0.0);
+ double m_A62(0.0);
+ double m_A63(0.0);
+ double m_A64(0.0);
+ double m_A65(0.0);
+ double m_A66(0.0);
+ double m_A67(0.0);
+ double m_A68(0.0);
+ double m_A69(0.0);
+ double m_A70(0.0);
+ double m_A71(0.0);
+ double m_A72(0.0);
+ double m_A73(0.0);
+ double m_A74(0.0);
+ double m_A75(0.0);
+ double m_A76(0.0);
+ double m_A77(0.0);
+ double m_A78(0.0);
+ double m_A79(0.0);
+ double m_A80(0.0);
+ double m_A81(0.0);
+ double m_A82(0.0);
+ double m_A83(0.0);
+ double m_A84(0.0);
+ double m_A85(0.0);
+ double m_A86(0.0);
+ double m_A87(0.0);
+ double m_A88(0.0);
+ double m_A89(0.0);
+ double m_A90(0.0);
+ double m_A91(0.0);
+ double m_A92(0.0);
+ double m_A93(0.0);
+ double m_A94(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A3 += go[2];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 -= go[3] * *cnV[3];
+ m_A4 += gt[4];
+ m_A4 += gt[5];
+ m_A5 += go[4];
+ double RHS2 = Idr[4];
+ RHS2 += Idr[5];
+ RHS2 -= go[5] * *cnV[5];
+ m_A6 += gt[6];
+ m_A6 += gt[7];
+ m_A7 += go[6];
+ double RHS3 = Idr[6];
+ RHS3 += Idr[7];
+ RHS3 -= go[7] * *cnV[7];
+ m_A8 += gt[8];
+ m_A8 += gt[9];
+ m_A9 += go[8];
+ double RHS4 = Idr[8];
+ RHS4 += Idr[9];
+ RHS4 -= go[9] * *cnV[9];
+ m_A10 += gt[10];
+ m_A10 += gt[11];
+ m_A11 += go[10];
+ double RHS5 = Idr[10];
+ RHS5 += Idr[11];
+ RHS5 -= go[11] * *cnV[11];
+ m_A12 += gt[12];
+ m_A12 += gt[13];
+ m_A12 += gt[14];
+ m_A13 += go[12];
+ double RHS6 = Idr[12];
+ RHS6 += Idr[13];
+ RHS6 += Idr[14];
+ RHS6 -= go[13] * *cnV[13];
+ RHS6 -= go[14] * *cnV[14];
+ m_A14 += gt[15];
+ m_A14 += gt[16];
+ m_A14 += gt[17];
+ m_A14 += gt[18];
+ m_A15 += go[15];
+ double RHS7 = Idr[15];
+ RHS7 += Idr[16];
+ RHS7 += Idr[17];
+ RHS7 += Idr[18];
+ RHS7 -= go[16] * *cnV[16];
+ RHS7 -= go[17] * *cnV[17];
+ RHS7 -= go[18] * *cnV[18];
+ m_A16 += gt[19];
+ m_A16 += gt[20];
+ m_A18 += go[19];
+ m_A17 += go[20];
+ double RHS8 = Idr[19];
+ RHS8 += Idr[20];
+ m_A19 += gt[21];
+ m_A19 += gt[22];
+ m_A21 += go[21];
+ m_A20 += go[22];
+ double RHS9 = Idr[21];
+ RHS9 += Idr[22];
+ m_A22 += gt[23];
+ m_A22 += gt[24];
+ m_A24 += go[23];
+ m_A23 += go[24];
+ double RHS10 = Idr[23];
+ RHS10 += Idr[24];
+ m_A25 += gt[25];
+ m_A25 += gt[26];
+ m_A27 += go[25];
+ m_A26 += go[26];
+ double RHS11 = Idr[25];
+ RHS11 += Idr[26];
+ m_A28 += gt[27];
+ m_A28 += gt[28];
+ m_A28 += gt[29];
+ m_A30 += go[27];
+ m_A29 += go[28];
+ m_A31 += go[29];
+ double RHS12 = Idr[27];
+ RHS12 += Idr[28];
+ RHS12 += Idr[29];
+ m_A32 += gt[30];
+ m_A32 += gt[31];
+ m_A34 += go[30];
+ m_A33 += go[31];
+ double RHS13 = Idr[30];
+ RHS13 += Idr[31];
+ m_A36 += gt[32];
+ m_A36 += gt[33];
+ m_A37 += go[32];
+ m_A35 += go[33];
+ double RHS14 = Idr[32];
+ RHS14 += Idr[33];
+ m_A39 += gt[34];
+ m_A39 += gt[35];
+ m_A40 += go[34];
+ m_A38 += go[35];
+ double RHS15 = Idr[34];
+ RHS15 += Idr[35];
+ m_A43 += gt[36];
+ m_A43 += gt[37];
+ m_A42 += go[36];
+ m_A41 += go[37];
+ double RHS16 = Idr[36];
+ RHS16 += Idr[37];
+ m_A47 += gt[38];
+ m_A47 += gt[39];
+ m_A46 += go[38];
+ m_A45 += go[39];
+ double RHS17 = Idr[38];
+ RHS17 += Idr[39];
+ m_A51 += gt[40];
+ m_A51 += gt[41];
+ m_A50 += go[40];
+ m_A49 += go[41];
+ double RHS18 = Idr[40];
+ RHS18 += Idr[41];
+ m_A55 += gt[42];
+ m_A55 += gt[43];
+ m_A54 += go[42];
+ m_A53 += go[43];
+ double RHS19 = Idr[42];
+ RHS19 += Idr[43];
+ m_A58 += gt[44];
+ m_A58 += gt[45];
+ m_A58 += gt[46];
+ m_A59 += go[44];
+ m_A57 += go[45];
+ double RHS20 = Idr[44];
+ RHS20 += Idr[45];
+ RHS20 += Idr[46];
+ RHS20 -= go[46] * *cnV[46];
+ m_A62 += gt[47];
+ m_A62 += gt[48];
+ m_A62 += gt[49];
+ m_A62 += gt[50];
+ m_A62 += gt[51];
+ m_A63 += go[47];
+ m_A63 += go[48];
+ m_A61 += go[49];
+ double RHS21 = Idr[47];
+ RHS21 += Idr[48];
+ RHS21 += Idr[49];
+ RHS21 += Idr[50];
+ RHS21 += Idr[51];
+ RHS21 -= go[50] * *cnV[50];
+ RHS21 -= go[51] * *cnV[51];
+ m_A66 += gt[52];
+ m_A66 += gt[53];
+ m_A65 += go[52];
+ m_A64 += go[53];
+ double RHS22 = Idr[52];
+ RHS22 += Idr[53];
+ m_A70 += gt[54];
+ m_A70 += gt[55];
+ m_A70 += gt[56];
+ m_A70 += gt[57];
+ m_A70 += gt[58];
+ m_A70 += go[54];
+ m_A69 += go[55];
+ m_A69 += go[56];
+ m_A68 += go[57];
+ double RHS23 = Idr[54];
+ RHS23 += Idr[55];
+ RHS23 += Idr[56];
+ RHS23 += Idr[57];
+ RHS23 += Idr[58];
+ RHS23 -= go[58] * *cnV[58];
+ m_A75 += gt[59];
+ m_A75 += gt[60];
+ m_A75 += gt[61];
+ m_A72 += go[59];
+ m_A76 += go[60];
+ double RHS24 = Idr[59];
+ RHS24 += Idr[60];
+ RHS24 += Idr[61];
+ RHS24 -= go[61] * *cnV[61];
+ m_A78 += gt[62];
+ m_A78 += gt[63];
+ m_A79 += go[62];
+ m_A77 += go[63];
+ double RHS25 = Idr[62];
+ RHS25 += Idr[63];
+ m_A94 += gt[64];
+ m_A94 += gt[65];
+ m_A94 += gt[66];
+ m_A94 += gt[67];
+ m_A94 += gt[68];
+ m_A94 += gt[69];
+ m_A94 += gt[70];
+ m_A94 += gt[71];
+ m_A94 += gt[72];
+ m_A94 += gt[73];
+ m_A94 += gt[74];
+ m_A92 += go[64];
+ m_A90 += go[65];
+ m_A90 += go[66];
+ m_A93 += go[67];
+ m_A84 += go[68];
+ m_A83 += go[69];
+ m_A82 += go[70];
+ m_A81 += go[71];
+ m_A80 += go[72];
+ m_A85 += go[73];
+ double RHS26 = Idr[64];
+ RHS26 += Idr[65];
+ RHS26 += Idr[66];
+ RHS26 += Idr[67];
+ RHS26 += Idr[68];
+ RHS26 += Idr[69];
+ RHS26 += Idr[70];
+ RHS26 += Idr[71];
+ RHS26 += Idr[72];
+ RHS26 += Idr[73];
+ RHS26 += Idr[74];
+ RHS26 -= go[74] * *cnV[74];
+ const double f0 = 1.0 / m_A0;
+ const double f0_16 = -f0 * m_A41;
+ m_A43 += m_A1 * f0_16;
+ RHS16 += f0_16 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_17 = -f1 * m_A45;
+ m_A47 += m_A3 * f1_17;
+ RHS17 += f1_17 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_18 = -f2 * m_A49;
+ m_A51 += m_A5 * f2_18;
+ RHS18 += f2_18 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_19 = -f3 * m_A53;
+ m_A55 += m_A7 * f3_19;
+ RHS19 += f3_19 * RHS3;
+ const double f4 = 1.0 / m_A8;
+ const double f4_22 = -f4 * m_A64;
+ m_A66 += m_A9 * f4_22;
+ RHS22 += f4_22 * RHS4;
+ const double f5 = 1.0 / m_A10;
+ const double f5_14 = -f5 * m_A35;
+ m_A36 += m_A11 * f5_14;
+ RHS14 += f5_14 * RHS5;
+ const double f6 = 1.0 / m_A12;
+ const double f6_15 = -f6 * m_A38;
+ m_A39 += m_A13 * f6_15;
+ RHS15 += f6_15 * RHS6;
+ const double f7 = 1.0 / m_A14;
+ const double f7_21 = -f7 * m_A61;
+ m_A62 += m_A15 * f7_21;
+ RHS21 += f7_21 * RHS7;
+ const double f8 = 1.0 / m_A16;
+ const double f8_16 = -f8 * m_A42;
+ m_A43 += m_A17 * f8_16;
+ m_A44 += m_A18 * f8_16;
+ RHS16 += f8_16 * RHS8;
+ const double f8_26 = -f8 * m_A80;
+ m_A86 += m_A17 * f8_26;
+ m_A94 += m_A18 * f8_26;
+ RHS26 += f8_26 * RHS8;
+ const double f9 = 1.0 / m_A19;
+ const double f9_17 = -f9 * m_A46;
+ m_A47 += m_A20 * f9_17;
+ m_A48 += m_A21 * f9_17;
+ RHS17 += f9_17 * RHS9;
+ const double f9_26 = -f9 * m_A81;
+ m_A87 += m_A20 * f9_26;
+ m_A94 += m_A21 * f9_26;
+ RHS26 += f9_26 * RHS9;
+ const double f10 = 1.0 / m_A22;
+ const double f10_18 = -f10 * m_A50;
+ m_A51 += m_A23 * f10_18;
+ m_A52 += m_A24 * f10_18;
+ RHS18 += f10_18 * RHS10;
+ const double f10_26 = -f10 * m_A82;
+ m_A88 += m_A23 * f10_26;
+ m_A94 += m_A24 * f10_26;
+ RHS26 += f10_26 * RHS10;
+ const double f11 = 1.0 / m_A25;
+ const double f11_19 = -f11 * m_A54;
+ m_A55 += m_A26 * f11_19;
+ m_A56 += m_A27 * f11_19;
+ RHS19 += f11_19 * RHS11;
+ const double f11_26 = -f11 * m_A83;
+ m_A89 += m_A26 * f11_26;
+ m_A94 += m_A27 * f11_26;
+ RHS26 += f11_26 * RHS11;
+ const double f12 = 1.0 / m_A28;
+ const double f12_20 = -f12 * m_A57;
+ m_A58 += m_A29 * f12_20;
+ m_A59 += m_A30 * f12_20;
+ m_A60 += m_A31 * f12_20;
+ RHS20 += f12_20 * RHS12;
+ const double f12_23 = -f12 * m_A68;
+ m_A69 += m_A29 * f12_23;
+ m_A70 += m_A30 * f12_23;
+ m_A71 += m_A31 * f12_23;
+ RHS23 += f12_23 * RHS12;
+ const double f12_24 = -f12 * m_A72;
+ m_A73 += m_A29 * f12_24;
+ m_A74 += m_A30 * f12_24;
+ m_A75 += m_A31 * f12_24;
+ RHS24 += f12_24 * RHS12;
+ const double f13 = 1.0 / m_A32;
+ const double f13_22 = -f13 * m_A65;
+ m_A66 += m_A33 * f13_22;
+ m_A67 += m_A34 * f13_22;
+ RHS22 += f13_22 * RHS13;
+ const double f13_26 = -f13 * m_A84;
+ m_A91 += m_A33 * f13_26;
+ m_A94 += m_A34 * f13_26;
+ RHS26 += f13_26 * RHS13;
+ const double f14 = 1.0 / m_A36;
+ const double f14_25 = -f14 * m_A77;
+ m_A78 += m_A37 * f14_25;
+ RHS25 += f14_25 * RHS14;
+ const double f15 = 1.0 / m_A39;
+ const double f15_26 = -f15 * m_A85;
+ m_A94 += m_A40 * f15_26;
+ RHS26 += f15_26 * RHS15;
+ const double f16 = 1.0 / m_A43;
+ const double f16_26 = -f16 * m_A86;
+ m_A94 += m_A44 * f16_26;
+ RHS26 += f16_26 * RHS16;
+ const double f17 = 1.0 / m_A47;
+ const double f17_26 = -f17 * m_A87;
+ m_A94 += m_A48 * f17_26;
+ RHS26 += f17_26 * RHS17;
+ const double f18 = 1.0 / m_A51;
+ const double f18_26 = -f18 * m_A88;
+ m_A94 += m_A52 * f18_26;
+ RHS26 += f18_26 * RHS18;
+ const double f19 = 1.0 / m_A55;
+ const double f19_26 = -f19 * m_A89;
+ m_A94 += m_A56 * f19_26;
+ RHS26 += f19_26 * RHS19;
+ const double f20 = 1.0 / m_A58;
+ const double f20_23 = -f20 * m_A69;
+ m_A70 += m_A59 * f20_23;
+ m_A71 += m_A60 * f20_23;
+ RHS23 += f20_23 * RHS20;
+ const double f20_24 = -f20 * m_A73;
+ m_A74 += m_A59 * f20_24;
+ m_A75 += m_A60 * f20_24;
+ RHS24 += f20_24 * RHS20;
+ const double f21 = 1.0 / m_A62;
+ const double f21_26 = -f21 * m_A90;
+ m_A94 += m_A63 * f21_26;
+ RHS26 += f21_26 * RHS21;
+ const double f22 = 1.0 / m_A66;
+ const double f22_26 = -f22 * m_A91;
+ m_A94 += m_A67 * f22_26;
+ RHS26 += f22_26 * RHS22;
+ const double f23 = 1.0 / m_A70;
+ const double f23_24 = -f23 * m_A74;
+ m_A75 += m_A71 * f23_24;
+ RHS24 += f23_24 * RHS23;
+ const double f24 = 1.0 / m_A75;
+ const double f24_26 = -f24 * m_A92;
+ m_A94 += m_A76 * f24_26;
+ RHS26 += f24_26 * RHS24;
+ const double f25 = 1.0 / m_A78;
+ const double f25_26 = -f25 * m_A93;
+ m_A94 += m_A79 * f25_26;
+ RHS26 += f25_26 * RHS25;
+ V[26] = RHS26 / m_A94;
+ double tmp25 = 0.0;
+ tmp25 += m_A79 * V[26];
+ V[25] = (RHS25 - tmp25) / m_A78;
+ double tmp24 = 0.0;
+ tmp24 += m_A76 * V[26];
+ V[24] = (RHS24 - tmp24) / m_A75;
+ double tmp23 = 0.0;
+ tmp23 += m_A71 * V[24];
+ V[23] = (RHS23 - tmp23) / m_A70;
+ double tmp22 = 0.0;
+ tmp22 += m_A67 * V[26];
+ V[22] = (RHS22 - tmp22) / m_A66;
+ double tmp21 = 0.0;
+ tmp21 += m_A63 * V[26];
+ V[21] = (RHS21 - tmp21) / m_A62;
+ double tmp20 = 0.0;
+ tmp20 += m_A59 * V[23];
+ tmp20 += m_A60 * V[24];
+ V[20] = (RHS20 - tmp20) / m_A58;
+ double tmp19 = 0.0;
+ tmp19 += m_A56 * V[26];
+ V[19] = (RHS19 - tmp19) / m_A55;
+ double tmp18 = 0.0;
+ tmp18 += m_A52 * V[26];
+ V[18] = (RHS18 - tmp18) / m_A51;
+ double tmp17 = 0.0;
+ tmp17 += m_A48 * V[26];
+ V[17] = (RHS17 - tmp17) / m_A47;
+ double tmp16 = 0.0;
+ tmp16 += m_A44 * V[26];
+ V[16] = (RHS16 - tmp16) / m_A43;
+ double tmp15 = 0.0;
+ tmp15 += m_A40 * V[26];
+ V[15] = (RHS15 - tmp15) / m_A39;
+ double tmp14 = 0.0;
+ tmp14 += m_A37 * V[25];
+ V[14] = (RHS14 - tmp14) / m_A36;
+ double tmp13 = 0.0;
+ tmp13 += m_A33 * V[22];
+ tmp13 += m_A34 * V[26];
+ V[13] = (RHS13 - tmp13) / m_A32;
+ double tmp12 = 0.0;
+ tmp12 += m_A29 * V[20];
+ tmp12 += m_A30 * V[23];
+ tmp12 += m_A31 * V[24];
+ V[12] = (RHS12 - tmp12) / m_A28;
+ double tmp11 = 0.0;
+ tmp11 += m_A26 * V[19];
+ tmp11 += m_A27 * V[26];
+ V[11] = (RHS11 - tmp11) / m_A25;
+ double tmp10 = 0.0;
+ tmp10 += m_A23 * V[18];
+ tmp10 += m_A24 * V[26];
+ V[10] = (RHS10 - tmp10) / m_A22;
+ double tmp9 = 0.0;
+ tmp9 += m_A20 * V[17];
+ tmp9 += m_A21 * V[26];
+ V[9] = (RHS9 - tmp9) / m_A19;
+ double tmp8 = 0.0;
+ tmp8 += m_A17 * V[16];
+ tmp8 += m_A18 * V[26];
+ V[8] = (RHS8 - tmp8) / m_A16;
+ double tmp7 = 0.0;
+ tmp7 += m_A15 * V[21];
+ V[7] = (RHS7 - tmp7) / m_A14;
+ double tmp6 = 0.0;
+ tmp6 += m_A13 * V[15];
+ V[6] = (RHS6 - tmp6) / m_A12;
+ double tmp5 = 0.0;
+ tmp5 += m_A11 * V[14];
+ V[5] = (RHS5 - tmp5) / m_A10;
+ double tmp4 = 0.0;
+ tmp4 += m_A9 * V[22];
+ V[4] = (RHS4 - tmp4) / m_A8;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[19];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[18];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[17];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[16];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// elim,zektor
static void nl_gcr_10_double_double_11c2ae166b240b6e(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -28709,57 +27404,6 @@ static void nl_gcr_45_double_double_28b736fe552777a9(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// elim,zektor
-static void nl_gcr_7_double_double_d190a0e3b8e1f4a7(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A3 += go[2];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 -= go[3] * *cnV[3];
- m_A6 += gt[4];
- m_A6 += gt[5];
- m_A6 += gt[6];
- m_A5 += go[4];
- m_A4 += go[5];
- double RHS2 = Idr[4];
- RHS2 += Idr[5];
- RHS2 += Idr[6];
- RHS2 -= go[6] * *cnV[6];
- const double f0 = 1.0 / m_A0;
- const double f0_2 = -f0 * m_A4;
- m_A6 += m_A1 * f0_2;
- RHS2 += f0_2 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_2 = -f1 * m_A5;
- m_A6 += m_A3 * f1_2;
- RHS2 += f1_2 * RHS1;
- V[2] = RHS2 / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[2];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[2];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// fireone
static void nl_gcr_128_double_double_7aee4423e3fdbfda(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -33183,63 +31827,6 @@ static void nl_gcr_79_double_double_c1d22fe6e895255d(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// fireone,astrob,rebound,speedfrk,cheekyms
-static void nl_gcr_7_double_double_7c86a9bc1c6aef4c(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A0 += gt[2];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 += Idr[2];
- RHS0 -= go[1] * *cnV[1];
- RHS0 -= go[2] * *cnV[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A3 += go[3];
- double RHS1 = Idr[3];
- RHS1 += Idr[4];
- RHS1 -= go[4] * *cnV[4];
- m_A6 += gt[5];
- m_A6 += gt[6];
- m_A6 += gt[7];
- m_A6 += gt[8];
- m_A5 += go[5];
- m_A4 += go[6];
- double RHS2 = Idr[5];
- RHS2 += Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 -= go[7] * *cnV[7];
- RHS2 -= go[8] * *cnV[8];
- const double f0 = 1.0 / m_A0;
- const double f0_2 = -f0 * m_A4;
- m_A6 += m_A1 * f0_2;
- RHS2 += f0_2 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_2 = -f1 * m_A5;
- m_A6 += m_A3 * f1_2;
- RHS2 += f1_2 * RHS1;
- V[2] = RHS2 / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[2];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[2];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// fireone
static void nl_gcr_7_double_double_e7fb484f621b3ab9(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -38153,8 +36740,163 @@ static void nl_gcr_7_double_double_782d79b5cbe953b1(double * __restrict V, const
V[0] = (RHS0 - tmp0) / m_A0;
}
+// gi6809
+static void nl_gcr_13_double_double_9eda6de0d275a3e5(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 -= go[4] * *cnV[4];
+ RHS1 -= go[5] * *cnV[5];
+ RHS1 -= go[6] * *cnV[6];
+ m_A4 += gt[7];
+ m_A4 += gt[8];
+ m_A4 += gt[9];
+ m_A4 += gt[10];
+ m_A5 += go[7];
+ double RHS2 = Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 -= go[8] * *cnV[8];
+ RHS2 -= go[9] * *cnV[9];
+ RHS2 -= go[10] * *cnV[10];
+ m_A6 += gt[11];
+ m_A6 += gt[12];
+ m_A7 += go[11];
+ double RHS3 = Idr[11];
+ RHS3 += Idr[12];
+ RHS3 -= go[12] * *cnV[12];
+ m_A12 += gt[13];
+ m_A12 += gt[14];
+ m_A12 += gt[15];
+ m_A12 += gt[16];
+ m_A12 += gt[17];
+ m_A12 += gt[18];
+ m_A11 += go[13];
+ m_A10 += go[14];
+ m_A9 += go[15];
+ m_A8 += go[16];
+ double RHS4 = Idr[13];
+ RHS4 += Idr[14];
+ RHS4 += Idr[15];
+ RHS4 += Idr[16];
+ RHS4 += Idr[17];
+ RHS4 += Idr[18];
+ RHS4 -= go[17] * *cnV[17];
+ RHS4 -= go[18] * *cnV[18];
+ const double f0 = 1.0 / m_A0;
+ const double f0_4 = -f0 * m_A8;
+ m_A12 += m_A1 * f0_4;
+ RHS4 += f0_4 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_4 = -f1 * m_A9;
+ m_A12 += m_A3 * f1_4;
+ RHS4 += f1_4 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_4 = -f2 * m_A10;
+ m_A12 += m_A5 * f2_4;
+ RHS4 += f2_4 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_4 = -f3 * m_A11;
+ m_A12 += m_A7 * f3_4;
+ RHS4 += f3_4 * RHS3;
+ V[4] = RHS4 / m_A12;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[4];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[4];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[4];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[4];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// gi6809
+static void nl_gcr_7_double_double_8a409a18e77784cb(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A3 += go[2];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 -= go[3] * *cnV[3];
+ m_A6 += gt[4];
+ m_A6 += gt[5];
+ m_A5 += go[4];
+ m_A4 += go[5];
+ double RHS2 = Idr[4];
+ RHS2 += Idr[5];
+ const double f0 = 1.0 / m_A0;
+ const double f0_2 = -f0 * m_A4;
+ m_A6 += m_A1 * f0_2;
+ RHS2 += f0_2 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ V[2] = RHS2 / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[2];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// gtrak10
-static void nl_gcr_43_double_double_4c46fdf7c0037727(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+static void nl_gcr_22_double_double_1f38df4919cdddae(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
{
@@ -38181,27 +36923,6 @@ static void nl_gcr_43_double_double_4c46fdf7c0037727(double * __restrict V, cons
double m_A19(0.0);
double m_A20(0.0);
double m_A21(0.0);
- double m_A22(0.0);
- double m_A23(0.0);
- double m_A24(0.0);
- double m_A25(0.0);
- double m_A26(0.0);
- double m_A27(0.0);
- double m_A28(0.0);
- double m_A29(0.0);
- double m_A30(0.0);
- double m_A31(0.0);
- double m_A32(0.0);
- double m_A33(0.0);
- double m_A34(0.0);
- double m_A35(0.0);
- double m_A36(0.0);
- double m_A37(0.0);
- double m_A38(0.0);
- double m_A39(0.0);
- double m_A40(0.0);
- double m_A41(0.0);
- double m_A42(0.0);
m_A0 += gt[0];
m_A0 += gt[1];
m_A0 += gt[2];
@@ -38221,262 +36942,159 @@ static void nl_gcr_43_double_double_4c46fdf7c0037727(double * __restrict V, cons
RHS1 -= go[4] * *cnV[4];
RHS1 -= go[5] * *cnV[5];
m_A4 += gt[6];
- m_A4 += gt[7];
- m_A4 += gt[8];
m_A5 += go[6];
double RHS2 = Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 -= go[7] * *cnV[7];
- RHS2 -= go[8] * *cnV[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A6 += gt[11];
- m_A7 += go[9];
- double RHS3 = Idr[9];
- RHS3 += Idr[10];
- RHS3 += Idr[11];
- RHS3 -= go[10] * *cnV[10];
- RHS3 -= go[11] * *cnV[11];
- m_A8 += gt[12];
- m_A8 += gt[13];
- m_A8 += gt[14];
- m_A9 += go[12];
- double RHS4 = Idr[12];
- RHS4 += Idr[13];
- RHS4 += Idr[14];
- RHS4 -= go[13] * *cnV[13];
- RHS4 -= go[14] * *cnV[14];
- m_A10 += gt[15];
- m_A10 += gt[16];
- m_A10 += gt[17];
- m_A11 += go[15];
- double RHS5 = Idr[15];
- RHS5 += Idr[16];
- RHS5 += Idr[17];
- RHS5 -= go[16] * *cnV[16];
- RHS5 -= go[17] * *cnV[17];
- m_A12 += gt[18];
- m_A12 += gt[19];
- m_A12 += gt[20];
- m_A13 += go[18];
- double RHS6 = Idr[18];
- RHS6 += Idr[19];
- RHS6 += Idr[20];
- RHS6 -= go[19] * *cnV[19];
- RHS6 -= go[20] * *cnV[20];
- m_A14 += gt[21];
- m_A14 += gt[22];
- m_A14 += gt[23];
- m_A15 += go[21];
- double RHS7 = Idr[21];
+ m_A6 += gt[7];
+ m_A7 += go[7];
+ double RHS3 = Idr[7];
+ m_A8 += gt[8];
+ m_A8 += gt[9];
+ m_A8 += gt[10];
+ m_A9 += go[8];
+ double RHS4 = Idr[8];
+ RHS4 += Idr[9];
+ RHS4 += Idr[10];
+ RHS4 -= go[9] * *cnV[9];
+ RHS4 -= go[10] * *cnV[10];
+ m_A10 += gt[11];
+ m_A10 += gt[12];
+ m_A10 += gt[13];
+ m_A11 += go[11];
+ double RHS5 = Idr[11];
+ RHS5 += Idr[12];
+ RHS5 += Idr[13];
+ RHS5 -= go[12] * *cnV[12];
+ RHS5 -= go[13] * *cnV[13];
+ m_A14 += gt[14];
+ m_A14 += gt[15];
+ m_A14 += gt[16];
+ m_A13 += go[14];
+ m_A12 += go[15];
+ m_A15 += go[16];
+ double RHS6 = Idr[14];
+ RHS6 += Idr[15];
+ RHS6 += Idr[16];
+ m_A21 += gt[17];
+ m_A21 += gt[18];
+ m_A21 += gt[19];
+ m_A21 += gt[20];
+ m_A21 += gt[21];
+ m_A21 += gt[22];
+ m_A21 += gt[23];
+ m_A20 += go[17];
+ m_A19 += go[18];
+ m_A18 += go[19];
+ m_A17 += go[20];
+ m_A16 += go[21];
+ double RHS7 = Idr[17];
+ RHS7 += Idr[18];
+ RHS7 += Idr[19];
+ RHS7 += Idr[20];
+ RHS7 += Idr[21];
RHS7 += Idr[22];
RHS7 += Idr[23];
RHS7 -= go[22] * *cnV[22];
RHS7 -= go[23] * *cnV[23];
- m_A16 += gt[24];
- m_A16 += gt[25];
- m_A16 += gt[26];
- m_A17 += go[24];
- double RHS8 = Idr[24];
- RHS8 += Idr[25];
- RHS8 += Idr[26];
- RHS8 -= go[25] * *cnV[25];
- RHS8 -= go[26] * *cnV[26];
- m_A18 += gt[27];
- m_A18 += gt[28];
- m_A18 += gt[29];
- m_A19 += go[27];
- double RHS9 = Idr[27];
- RHS9 += Idr[28];
- RHS9 += Idr[29];
- RHS9 -= go[28] * *cnV[28];
- RHS9 -= go[29] * *cnV[29];
- m_A20 += gt[30];
- m_A20 += gt[31];
- m_A20 += gt[32];
- m_A21 += go[30];
- double RHS10 = Idr[30];
- RHS10 += Idr[31];
- RHS10 += Idr[32];
- RHS10 -= go[31] * *cnV[31];
- RHS10 -= go[32] * *cnV[32];
- m_A22 += gt[33];
- m_A22 += gt[34];
- m_A22 += gt[35];
- m_A23 += go[33];
- double RHS11 = Idr[33];
- RHS11 += Idr[34];
- RHS11 += Idr[35];
- RHS11 -= go[34] * *cnV[34];
- RHS11 -= go[35] * *cnV[35];
- m_A25 += gt[36];
- m_A25 += gt[37];
- m_A25 += gt[38];
- m_A26 += go[36];
- m_A24 += go[37];
- double RHS12 = Idr[36];
- RHS12 += Idr[37];
- RHS12 += Idr[38];
- RHS12 -= go[38] * *cnV[38];
- m_A30 += gt[39];
- m_A30 += gt[40];
- m_A30 += gt[41];
- m_A30 += gt[42];
- m_A30 += gt[43];
- m_A30 += gt[44];
- m_A30 += gt[45];
- m_A29 += go[39];
- m_A28 += go[40];
- m_A27 += go[41];
- m_A31 += go[42];
- m_A31 += go[43];
- double RHS13 = Idr[39];
- RHS13 += Idr[40];
- RHS13 += Idr[41];
- RHS13 += Idr[42];
- RHS13 += Idr[43];
- RHS13 += Idr[44];
- RHS13 += Idr[45];
- RHS13 -= go[44] * *cnV[44];
- RHS13 -= go[45] * *cnV[45];
- m_A42 += gt[46];
- m_A42 += gt[47];
- m_A42 += gt[48];
- m_A42 += gt[49];
- m_A42 += gt[50];
- m_A42 += gt[51];
- m_A42 += gt[52];
- m_A42 += gt[53];
- m_A42 += gt[54];
- m_A42 += gt[55];
- m_A42 += gt[56];
- m_A42 += gt[57];
- m_A42 += gt[58];
- m_A41 += go[46];
- m_A41 += go[47];
- m_A39 += go[48];
- m_A38 += go[49];
- m_A37 += go[50];
- m_A36 += go[51];
- m_A35 += go[52];
- m_A34 += go[53];
- m_A33 += go[54];
- m_A32 += go[55];
- m_A40 += go[56];
- double RHS14 = Idr[46];
- RHS14 += Idr[47];
- RHS14 += Idr[48];
- RHS14 += Idr[49];
- RHS14 += Idr[50];
- RHS14 += Idr[51];
- RHS14 += Idr[52];
- RHS14 += Idr[53];
- RHS14 += Idr[54];
- RHS14 += Idr[55];
- RHS14 += Idr[56];
- RHS14 += Idr[57];
- RHS14 += Idr[58];
- RHS14 -= go[57] * *cnV[57];
- RHS14 -= go[58] * *cnV[58];
const double f0 = 1.0 / m_A0;
- const double f0_12 = -f0 * m_A24;
- m_A25 += m_A1 * f0_12;
- RHS12 += f0_12 * RHS0;
+ const double f0_7 = -f0 * m_A16;
+ m_A21 += m_A1 * f0_7;
+ RHS7 += f0_7 * RHS0;
const double f1 = 1.0 / m_A2;
- const double f1_14 = -f1 * m_A32;
- m_A42 += m_A3 * f1_14;
- RHS14 += f1_14 * RHS1;
+ const double f1_7 = -f1 * m_A17;
+ m_A21 += m_A3 * f1_7;
+ RHS7 += f1_7 * RHS1;
const double f2 = 1.0 / m_A4;
- const double f2_14 = -f2 * m_A33;
- m_A42 += m_A5 * f2_14;
- RHS14 += f2_14 * RHS2;
+ const double f2_6 = -f2 * m_A12;
+ m_A14 += m_A5 * f2_6;
+ RHS6 += f2_6 * RHS2;
const double f3 = 1.0 / m_A6;
- const double f3_14 = -f3 * m_A34;
- m_A42 += m_A7 * f3_14;
- RHS14 += f3_14 * RHS3;
+ const double f3_6 = -f3 * m_A13;
+ m_A14 += m_A7 * f3_6;
+ RHS6 += f3_6 * RHS3;
const double f4 = 1.0 / m_A8;
- const double f4_14 = -f4 * m_A35;
- m_A42 += m_A9 * f4_14;
- RHS14 += f4_14 * RHS4;
+ const double f4_7 = -f4 * m_A18;
+ m_A21 += m_A9 * f4_7;
+ RHS7 += f4_7 * RHS4;
const double f5 = 1.0 / m_A10;
- const double f5_14 = -f5 * m_A36;
- m_A42 += m_A11 * f5_14;
- RHS14 += f5_14 * RHS5;
- const double f6 = 1.0 / m_A12;
- const double f6_14 = -f6 * m_A37;
- m_A42 += m_A13 * f6_14;
- RHS14 += f6_14 * RHS6;
- const double f7 = 1.0 / m_A14;
- const double f7_14 = -f7 * m_A38;
- m_A42 += m_A15 * f7_14;
- RHS14 += f7_14 * RHS7;
- const double f8 = 1.0 / m_A16;
- const double f8_14 = -f8 * m_A39;
- m_A42 += m_A17 * f8_14;
- RHS14 += f8_14 * RHS8;
- const double f9 = 1.0 / m_A18;
- const double f9_13 = -f9 * m_A27;
- m_A30 += m_A19 * f9_13;
- RHS13 += f9_13 * RHS9;
- const double f10 = 1.0 / m_A20;
- const double f10_13 = -f10 * m_A28;
- m_A30 += m_A21 * f10_13;
- RHS13 += f10_13 * RHS10;
- const double f11 = 1.0 / m_A22;
- const double f11_13 = -f11 * m_A29;
- m_A30 += m_A23 * f11_13;
- RHS13 += f11_13 * RHS11;
- const double f12 = 1.0 / m_A25;
- const double f12_14 = -f12 * m_A40;
- m_A42 += m_A26 * f12_14;
- RHS14 += f12_14 * RHS12;
- const double f13 = 1.0 / m_A30;
- const double f13_14 = -f13 * m_A41;
- m_A42 += m_A31 * f13_14;
- RHS14 += f13_14 * RHS13;
- V[14] = RHS14 / m_A42;
- double tmp13 = 0.0;
- tmp13 += m_A31 * V[14];
- V[13] = (RHS13 - tmp13) / m_A30;
- double tmp12 = 0.0;
- tmp12 += m_A26 * V[14];
- V[12] = (RHS12 - tmp12) / m_A25;
- double tmp11 = 0.0;
- tmp11 += m_A23 * V[13];
- V[11] = (RHS11 - tmp11) / m_A22;
- double tmp10 = 0.0;
- tmp10 += m_A21 * V[13];
- V[10] = (RHS10 - tmp10) / m_A20;
- double tmp9 = 0.0;
- tmp9 += m_A19 * V[13];
- V[9] = (RHS9 - tmp9) / m_A18;
- double tmp8 = 0.0;
- tmp8 += m_A17 * V[14];
- V[8] = (RHS8 - tmp8) / m_A16;
- double tmp7 = 0.0;
- tmp7 += m_A15 * V[14];
- V[7] = (RHS7 - tmp7) / m_A14;
+ const double f5_7 = -f5 * m_A19;
+ m_A21 += m_A11 * f5_7;
+ RHS7 += f5_7 * RHS5;
+ const double f6 = 1.0 / m_A14;
+ const double f6_7 = -f6 * m_A20;
+ m_A21 += m_A15 * f6_7;
+ RHS7 += f6_7 * RHS6;
+ V[7] = RHS7 / m_A21;
double tmp6 = 0.0;
- tmp6 += m_A13 * V[14];
- V[6] = (RHS6 - tmp6) / m_A12;
+ tmp6 += m_A15 * V[7];
+ V[6] = (RHS6 - tmp6) / m_A14;
double tmp5 = 0.0;
- tmp5 += m_A11 * V[14];
+ tmp5 += m_A11 * V[7];
V[5] = (RHS5 - tmp5) / m_A10;
double tmp4 = 0.0;
- tmp4 += m_A9 * V[14];
+ tmp4 += m_A9 * V[7];
V[4] = (RHS4 - tmp4) / m_A8;
double tmp3 = 0.0;
- tmp3 += m_A7 * V[14];
+ tmp3 += m_A7 * V[6];
V[3] = (RHS3 - tmp3) / m_A6;
double tmp2 = 0.0;
- tmp2 += m_A5 * V[14];
+ tmp2 += m_A5 * V[6];
V[2] = (RHS2 - tmp2) / m_A4;
double tmp1 = 0.0;
- tmp1 += m_A3 * V[14];
+ tmp1 += m_A3 * V[7];
V[1] = (RHS1 - tmp1) / m_A2;
double tmp0 = 0.0;
- tmp0 += m_A1 * V[12];
+ tmp0 += m_A1 * V[7];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// gtrak10,elim,zektor
+static void nl_gcr_7_double_double_d190a0e3b8e1f4a7(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A3 += go[2];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 -= go[3] * *cnV[3];
+ m_A6 += gt[4];
+ m_A6 += gt[5];
+ m_A6 += gt[6];
+ m_A5 += go[4];
+ m_A4 += go[5];
+ double RHS2 = Idr[4];
+ RHS2 += Idr[5];
+ RHS2 += Idr[6];
+ RHS2 -= go[6] * *cnV[6];
+ const double f0 = 1.0 / m_A0;
+ const double f0_2 = -f0 * m_A4;
+ m_A6 += m_A1 * f0_2;
+ RHS2 += f0_2 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ V[2] = RHS2 / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[2];
V[0] = (RHS0 - tmp0) / m_A0;
}
@@ -44601,6 +43219,107 @@ static void nl_gcr_50_double_double_c6f25bb06e161d1c(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
+// rebound,astrob
+static void nl_gcr_13_double_double_a41a44bd5c424f88(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 -= go[4] * *cnV[4];
+ RHS1 -= go[5] * *cnV[5];
+ m_A4 += gt[6];
+ m_A4 += gt[7];
+ m_A4 += gt[8];
+ m_A5 += go[6];
+ double RHS2 = Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 -= go[7] * *cnV[7];
+ RHS2 -= go[8] * *cnV[8];
+ m_A6 += gt[9];
+ m_A6 += gt[10];
+ m_A6 += gt[11];
+ m_A7 += go[9];
+ double RHS3 = Idr[9];
+ RHS3 += Idr[10];
+ RHS3 += Idr[11];
+ RHS3 -= go[10] * *cnV[10];
+ RHS3 -= go[11] * *cnV[11];
+ m_A12 += gt[12];
+ m_A12 += gt[13];
+ m_A12 += gt[14];
+ m_A12 += gt[15];
+ m_A12 += gt[16];
+ m_A11 += go[12];
+ m_A10 += go[13];
+ m_A9 += go[14];
+ m_A8 += go[15];
+ double RHS4 = Idr[12];
+ RHS4 += Idr[13];
+ RHS4 += Idr[14];
+ RHS4 += Idr[15];
+ RHS4 += Idr[16];
+ RHS4 -= go[16] * *cnV[16];
+ const double f0 = 1.0 / m_A0;
+ const double f0_4 = -f0 * m_A8;
+ m_A12 += m_A1 * f0_4;
+ RHS4 += f0_4 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_4 = -f1 * m_A9;
+ m_A12 += m_A3 * f1_4;
+ RHS4 += f1_4 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_4 = -f2 * m_A10;
+ m_A12 += m_A5 * f2_4;
+ RHS4 += f2_4 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_4 = -f3 * m_A11;
+ m_A12 += m_A7 * f3_4;
+ RHS4 += f3_4 * RHS3;
+ V[4] = RHS4 / m_A12;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[4];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[4];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[4];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[4];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// rebound
static void nl_gcr_28_double_double_8bec817b324dcc3(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -45050,102 +43769,6 @@ static void nl_gcr_11_double_double_aa07266ef5d420d1(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// ripoff,sundance,warrior
-static void nl_gcr_12_double_double_295cf2e2f3d489bf(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A2 += gt[5];
- m_A4 += go[2];
- m_A3 += go[3];
- m_A3 += go[4];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 += Idr[4];
- RHS1 += Idr[5];
- RHS1 -= go[5] * *cnV[5];
- m_A6 += gt[6];
- m_A6 += gt[7];
- m_A6 += gt[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A7 += go[6];
- m_A7 += go[7];
- m_A5 += go[8];
- m_A5 += go[9];
- double RHS2 = Idr[6];
- RHS2 += Idr[7];
- RHS2 += Idr[8];
- RHS2 += Idr[9];
- RHS2 += Idr[10];
- RHS2 -= go[10] * *cnV[10];
- m_A11 += gt[11];
- m_A11 += gt[12];
- m_A11 += gt[13];
- m_A11 += gt[14];
- m_A11 += gt[15];
- m_A10 += go[11];
- m_A10 += go[12];
- m_A9 += go[13];
- m_A8 += go[14];
- double RHS3 = Idr[11];
- RHS3 += Idr[12];
- RHS3 += Idr[13];
- RHS3 += Idr[14];
- RHS3 += Idr[15];
- RHS3 -= go[15] * *cnV[15];
- const double f0 = 1.0 / m_A0;
- const double f0_3 = -f0 * m_A8;
- m_A11 += m_A1 * f0_3;
- RHS3 += f0_3 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_2 = -f1 * m_A5;
- m_A6 += m_A3 * f1_2;
- m_A7 += m_A4 * f1_2;
- RHS2 += f1_2 * RHS1;
- const double f1_3 = -f1 * m_A9;
- m_A10 += m_A3 * f1_3;
- m_A11 += m_A4 * f1_3;
- RHS3 += f1_3 * RHS1;
- const double f2 = 1.0 / m_A6;
- const double f2_3 = -f2 * m_A10;
- m_A11 += m_A7 * f2_3;
- RHS3 += f2_3 * RHS2;
- V[3] = RHS3 / m_A11;
- double tmp2 = 0.0;
- tmp2 += m_A7 * V[3];
- V[2] = (RHS2 - tmp2) / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[2];
- tmp1 += m_A4 * V[3];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[3];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// ripoff
static void nl_gcr_16_double_double_698d5dd47fb16d5(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -59446,6 +58069,63 @@ static void nl_gcr_37_double_double_e4f2ffbf201a3d0c(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
+// speedfrk,cheekyms,rebound,astrob,fireone
+static void nl_gcr_7_double_double_7c86a9bc1c6aef4c(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 -= go[4] * *cnV[4];
+ m_A6 += gt[5];
+ m_A6 += gt[6];
+ m_A6 += gt[7];
+ m_A6 += gt[8];
+ m_A5 += go[5];
+ m_A4 += go[6];
+ double RHS2 = Idr[5];
+ RHS2 += Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 -= go[7] * *cnV[7];
+ RHS2 -= go[8] * *cnV[8];
+ const double f0 = 1.0 / m_A0;
+ const double f0_2 = -f0 * m_A4;
+ m_A6 += m_A1 * f0_2;
+ RHS2 += f0_2 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ V[2] = RHS2 / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[2];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// speedfrk
static void nl_gcr_7_double_double_e07b5b086812756c(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -59582,6 +58262,2340 @@ static void nl_gcr_10_double_double_ac1e401ddf971e15(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
+// sspeedr,280zzzap
+static void nl_gcr_113_double_double_ab9144d965a37e4(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ double m_A54(0.0);
+ double m_A55(0.0);
+ double m_A56(0.0);
+ double m_A57(0.0);
+ double m_A58(0.0);
+ double m_A59(0.0);
+ double m_A60(0.0);
+ double m_A61(0.0);
+ double m_A62(0.0);
+ double m_A63(0.0);
+ double m_A64(0.0);
+ double m_A65(0.0);
+ double m_A66(0.0);
+ double m_A67(0.0);
+ double m_A68(0.0);
+ double m_A69(0.0);
+ double m_A70(0.0);
+ double m_A71(0.0);
+ double m_A72(0.0);
+ double m_A73(0.0);
+ double m_A74(0.0);
+ double m_A75(0.0);
+ double m_A76(0.0);
+ double m_A77(0.0);
+ double m_A78(0.0);
+ double m_A79(0.0);
+ double m_A80(0.0);
+ double m_A81(0.0);
+ double m_A82(0.0);
+ double m_A83(0.0);
+ double m_A84(0.0);
+ double m_A85(0.0);
+ double m_A86(0.0);
+ double m_A87(0.0);
+ double m_A88(0.0);
+ double m_A89(0.0);
+ double m_A90(0.0);
+ double m_A91(0.0);
+ double m_A92(0.0);
+ double m_A93(0.0);
+ double m_A94(0.0);
+ double m_A95(0.0);
+ double m_A96(0.0);
+ double m_A97(0.0);
+ double m_A98(0.0);
+ double m_A99(0.0);
+ double m_A100(0.0);
+ double m_A101(0.0);
+ double m_A102(0.0);
+ double m_A103(0.0);
+ double m_A104(0.0);
+ double m_A105(0.0);
+ double m_A106(0.0);
+ double m_A107(0.0);
+ double m_A108(0.0);
+ double m_A109(0.0);
+ double m_A110(0.0);
+ double m_A111(0.0);
+ double m_A112(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A5 += go[2];
+ m_A4 += go[3];
+ m_A3 += go[4];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 -= go[5] * *cnV[5];
+ m_A6 += gt[6];
+ m_A6 += gt[7];
+ m_A7 += go[6];
+ double RHS2 = Idr[6];
+ RHS2 += Idr[7];
+ RHS2 -= go[7] * *cnV[7];
+ m_A8 += gt[8];
+ m_A8 += gt[9];
+ m_A9 += go[8];
+ double RHS3 = Idr[8];
+ RHS3 += Idr[9];
+ RHS3 -= go[9] * *cnV[9];
+ m_A10 += gt[10];
+ m_A10 += gt[11];
+ m_A10 += gt[12];
+ m_A11 += go[10];
+ m_A12 += go[11];
+ double RHS4 = Idr[10];
+ RHS4 += Idr[11];
+ RHS4 += Idr[12];
+ RHS4 -= go[12] * *cnV[12];
+ m_A13 += gt[13];
+ m_A13 += gt[14];
+ m_A14 += go[13];
+ double RHS5 = Idr[13];
+ RHS5 += Idr[14];
+ RHS5 -= go[14] * *cnV[14];
+ m_A15 += gt[15];
+ m_A15 += gt[16];
+ m_A15 += gt[17];
+ m_A15 += gt[18];
+ m_A15 += gt[19];
+ m_A15 += gt[20];
+ m_A15 += gt[21];
+ m_A18 += go[15];
+ m_A19 += go[16];
+ m_A17 += go[17];
+ m_A16 += go[18];
+ double RHS6 = Idr[15];
+ RHS6 += Idr[16];
+ RHS6 += Idr[17];
+ RHS6 += Idr[18];
+ RHS6 += Idr[19];
+ RHS6 += Idr[20];
+ RHS6 += Idr[21];
+ RHS6 -= go[19] * *cnV[19];
+ RHS6 -= go[20] * *cnV[20];
+ RHS6 -= go[21] * *cnV[21];
+ m_A20 += gt[22];
+ m_A20 += gt[23];
+ m_A20 += gt[24];
+ m_A20 += gt[25];
+ m_A20 += gt[26];
+ m_A20 += gt[27];
+ m_A20 += gt[28];
+ m_A23 += go[22];
+ m_A24 += go[23];
+ m_A22 += go[24];
+ m_A21 += go[25];
+ double RHS7 = Idr[22];
+ RHS7 += Idr[23];
+ RHS7 += Idr[24];
+ RHS7 += Idr[25];
+ RHS7 += Idr[26];
+ RHS7 += Idr[27];
+ RHS7 += Idr[28];
+ RHS7 -= go[26] * *cnV[26];
+ RHS7 -= go[27] * *cnV[27];
+ RHS7 -= go[28] * *cnV[28];
+ m_A25 += gt[29];
+ m_A25 += gt[30];
+ m_A25 += gt[31];
+ m_A26 += go[29];
+ m_A27 += go[30];
+ double RHS8 = Idr[29];
+ RHS8 += Idr[30];
+ RHS8 += Idr[31];
+ RHS8 -= go[31] * *cnV[31];
+ m_A28 += gt[32];
+ m_A28 += gt[33];
+ m_A29 += go[32];
+ double RHS9 = Idr[32];
+ RHS9 += Idr[33];
+ RHS9 -= go[33] * *cnV[33];
+ m_A30 += gt[34];
+ m_A30 += gt[35];
+ m_A30 += gt[36];
+ m_A30 += gt[37];
+ m_A31 += go[34];
+ double RHS10 = Idr[34];
+ RHS10 += Idr[35];
+ RHS10 += Idr[36];
+ RHS10 += Idr[37];
+ RHS10 -= go[35] * *cnV[35];
+ RHS10 -= go[36] * *cnV[36];
+ RHS10 -= go[37] * *cnV[37];
+ m_A32 += gt[38];
+ m_A32 += gt[39];
+ m_A33 += go[38];
+ double RHS11 = Idr[38];
+ RHS11 += Idr[39];
+ RHS11 -= go[39] * *cnV[39];
+ m_A36 += gt[40];
+ m_A36 += gt[41];
+ m_A36 += gt[42];
+ m_A36 += gt[43];
+ m_A35 += go[40];
+ m_A34 += go[41];
+ double RHS12 = Idr[40];
+ RHS12 += Idr[41];
+ RHS12 += Idr[42];
+ RHS12 += Idr[43];
+ RHS12 -= go[42] * *cnV[42];
+ RHS12 -= go[43] * *cnV[43];
+ m_A42 += gt[44];
+ m_A42 += gt[45];
+ m_A42 += gt[46];
+ m_A42 += gt[47];
+ m_A40 += go[44];
+ m_A39 += go[45];
+ double RHS13 = Idr[44];
+ RHS13 += Idr[45];
+ RHS13 += Idr[46];
+ RHS13 += Idr[47];
+ RHS13 -= go[46] * *cnV[46];
+ RHS13 -= go[47] * *cnV[47];
+ m_A51 += gt[48];
+ m_A51 += gt[49];
+ m_A51 += gt[50];
+ m_A51 += gt[51];
+ m_A53 += go[48];
+ m_A48 += go[49];
+ m_A47 += go[50];
+ double RHS14 = Idr[48];
+ RHS14 += Idr[49];
+ RHS14 += Idr[50];
+ RHS14 += Idr[51];
+ RHS14 -= go[51] * *cnV[51];
+ m_A57 += gt[52];
+ m_A57 += gt[53];
+ m_A57 += gt[54];
+ m_A56 += go[52];
+ m_A58 += go[53];
+ double RHS15 = Idr[52];
+ RHS15 += Idr[53];
+ RHS15 += Idr[54];
+ RHS15 -= go[54] * *cnV[54];
+ m_A60 += gt[55];
+ m_A60 += gt[56];
+ m_A60 += gt[57];
+ m_A60 += gt[58];
+ m_A59 += go[55];
+ m_A61 += go[56];
+ double RHS16 = Idr[55];
+ RHS16 += Idr[56];
+ RHS16 += Idr[57];
+ RHS16 += Idr[58];
+ RHS16 -= go[57] * *cnV[57];
+ RHS16 -= go[58] * *cnV[58];
+ m_A67 += gt[59];
+ m_A67 += gt[60];
+ m_A67 += gt[61];
+ m_A67 += gt[62];
+ m_A67 += gt[63];
+ m_A67 += gt[64];
+ m_A70 += go[59];
+ m_A64 += go[60];
+ m_A63 += go[61];
+ m_A62 += go[62];
+ m_A69 += go[63];
+ double RHS17 = Idr[59];
+ RHS17 += Idr[60];
+ RHS17 += Idr[61];
+ RHS17 += Idr[62];
+ RHS17 += Idr[63];
+ RHS17 += Idr[64];
+ RHS17 -= go[64] * *cnV[64];
+ m_A74 += gt[65];
+ m_A74 += gt[66];
+ m_A74 += gt[67];
+ m_A74 += gt[68];
+ m_A73 += go[65];
+ m_A72 += go[66];
+ m_A75 += go[67];
+ double RHS18 = Idr[65];
+ RHS18 += Idr[66];
+ RHS18 += Idr[67];
+ RHS18 += Idr[68];
+ RHS18 -= go[68] * *cnV[68];
+ m_A80 += gt[69];
+ m_A80 += gt[70];
+ m_A80 += gt[71];
+ m_A80 += gt[72];
+ m_A80 += gt[73];
+ m_A77 += go[69];
+ m_A78 += go[70];
+ m_A76 += go[71];
+ double RHS19 = Idr[69];
+ RHS19 += Idr[70];
+ RHS19 += Idr[71];
+ RHS19 += Idr[72];
+ RHS19 += Idr[73];
+ RHS19 -= go[72] * *cnV[72];
+ RHS19 -= go[73] * *cnV[73];
+ m_A89 += gt[74];
+ m_A89 += gt[75];
+ m_A89 += gt[76];
+ m_A89 += gt[77];
+ m_A84 += go[74];
+ m_A85 += go[75];
+ m_A87 += go[76];
+ m_A86 += go[77];
+ double RHS20 = Idr[74];
+ RHS20 += Idr[75];
+ RHS20 += Idr[76];
+ RHS20 += Idr[77];
+ m_A100 += gt[78];
+ m_A100 += gt[79];
+ m_A100 += gt[80];
+ m_A100 += gt[81];
+ m_A100 += gt[82];
+ m_A100 += gt[83];
+ m_A100 += gt[84];
+ m_A96 += go[78];
+ m_A93 += go[79];
+ m_A101 += go[80];
+ m_A92 += go[81];
+ m_A97 += go[82];
+ double RHS21 = Idr[78];
+ RHS21 += Idr[79];
+ RHS21 += Idr[80];
+ RHS21 += Idr[81];
+ RHS21 += Idr[82];
+ RHS21 += Idr[83];
+ RHS21 += Idr[84];
+ RHS21 -= go[83] * *cnV[83];
+ RHS21 -= go[84] * *cnV[84];
+ m_A112 += gt[85];
+ m_A112 += gt[86];
+ m_A112 += gt[87];
+ m_A112 += gt[88];
+ m_A112 += gt[89];
+ m_A112 += gt[90];
+ m_A108 += go[85];
+ m_A111 += go[86];
+ m_A103 += go[87];
+ m_A104 += go[88];
+ m_A102 += go[89];
+ double RHS22 = Idr[85];
+ RHS22 += Idr[86];
+ RHS22 += Idr[87];
+ RHS22 += Idr[88];
+ RHS22 += Idr[89];
+ RHS22 += Idr[90];
+ RHS22 -= go[90] * *cnV[90];
+ const double f0 = 1.0 / m_A0;
+ const double f0_12 = -f0 * m_A34;
+ m_A36 += m_A1 * f0_12;
+ RHS12 += f0_12 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_12 = -f1 * m_A35;
+ m_A36 += m_A3 * f1_12;
+ m_A37 += m_A4 * f1_12;
+ m_A38 += m_A5 * f1_12;
+ RHS12 += f1_12 * RHS1;
+ const double f1_13 = -f1 * m_A39;
+ m_A41 += m_A3 * f1_13;
+ m_A42 += m_A4 * f1_13;
+ m_A43 += m_A5 * f1_13;
+ RHS13 += f1_13 * RHS1;
+ const double f1_14 = -f1 * m_A47;
+ m_A49 += m_A3 * f1_14;
+ m_A50 += m_A4 * f1_14;
+ m_A51 += m_A5 * f1_14;
+ RHS14 += f1_14 * RHS1;
+ const double f2 = 1.0 / m_A6;
+ const double f2_15 = -f2 * m_A56;
+ m_A57 += m_A7 * f2_15;
+ RHS15 += f2_15 * RHS2;
+ const double f3 = 1.0 / m_A8;
+ const double f3_20 = -f3 * m_A84;
+ m_A89 += m_A9 * f3_20;
+ RHS20 += f3_20 * RHS3;
+ const double f4 = 1.0 / m_A10;
+ const double f4_17 = -f4 * m_A62;
+ m_A67 += m_A11 * f4_17;
+ m_A69 += m_A12 * f4_17;
+ RHS17 += f4_17 * RHS4;
+ const double f4_20 = -f4 * m_A85;
+ m_A87 += m_A11 * f4_20;
+ m_A89 += m_A12 * f4_20;
+ RHS20 += f4_20 * RHS4;
+ const double f5 = 1.0 / m_A13;
+ const double f5_16 = -f5 * m_A59;
+ m_A60 += m_A14 * f5_16;
+ RHS16 += f5_16 * RHS5;
+ const double f6 = 1.0 / m_A15;
+ const double f6_13 = -f6 * m_A40;
+ m_A42 += m_A16 * f6_13;
+ m_A44 += m_A17 * f6_13;
+ m_A45 += m_A18 * f6_13;
+ m_A46 += m_A19 * f6_13;
+ RHS13 += f6_13 * RHS6;
+ const double f6_17 = -f6 * m_A63;
+ m_A65 += m_A16 * f6_17;
+ m_A67 += m_A17 * f6_17;
+ m_A70 += m_A18 * f6_17;
+ m_A71 += m_A19 * f6_17;
+ RHS17 += f6_17 * RHS6;
+ const double f6_21 = -f6 * m_A92;
+ m_A94 += m_A16 * f6_21;
+ m_A97 += m_A17 * f6_21;
+ m_A100 += m_A18 * f6_21;
+ m_A101 += m_A19 * f6_21;
+ RHS21 += f6_21 * RHS6;
+ const double f6_22 = -f6 * m_A102;
+ m_A105 += m_A16 * f6_22;
+ m_A107 += m_A17 * f6_22;
+ m_A111 += m_A18 * f6_22;
+ m_A112 += m_A19 * f6_22;
+ RHS22 += f6_22 * RHS6;
+ const double f7 = 1.0 / m_A20;
+ const double f7_14 = -f7 * m_A48;
+ m_A51 += m_A21 * f7_14;
+ m_A52 += m_A22 * f7_14;
+ m_A54 += m_A23 * f7_14;
+ m_A55 += m_A24 * f7_14;
+ RHS14 += f7_14 * RHS7;
+ const double f7_17 = -f7 * m_A64;
+ m_A66 += m_A21 * f7_17;
+ m_A67 += m_A22 * f7_17;
+ m_A70 += m_A23 * f7_17;
+ m_A71 += m_A24 * f7_17;
+ RHS17 += f7_17 * RHS7;
+ const double f7_21 = -f7 * m_A93;
+ m_A95 += m_A21 * f7_21;
+ m_A97 += m_A22 * f7_21;
+ m_A100 += m_A23 * f7_21;
+ m_A101 += m_A24 * f7_21;
+ RHS21 += f7_21 * RHS7;
+ const double f7_22 = -f7 * m_A103;
+ m_A106 += m_A21 * f7_22;
+ m_A107 += m_A22 * f7_22;
+ m_A111 += m_A23 * f7_22;
+ m_A112 += m_A24 * f7_22;
+ RHS22 += f7_22 * RHS7;
+ const double f8 = 1.0 / m_A25;
+ const double f8_18 = -f8 * m_A72;
+ m_A74 += m_A26 * f8_18;
+ m_A75 += m_A27 * f8_18;
+ RHS18 += f8_18 * RHS8;
+ const double f8_22 = -f8 * m_A104;
+ m_A108 += m_A26 * f8_22;
+ m_A112 += m_A27 * f8_22;
+ RHS22 += f8_22 * RHS8;
+ const double f9 = 1.0 / m_A28;
+ const double f9_18 = -f9 * m_A73;
+ m_A74 += m_A29 * f9_18;
+ RHS18 += f9_18 * RHS9;
+ const double f10 = 1.0 / m_A30;
+ const double f10_19 = -f10 * m_A76;
+ m_A80 += m_A31 * f10_19;
+ RHS19 += f10_19 * RHS10;
+ const double f11 = 1.0 / m_A32;
+ const double f11_19 = -f11 * m_A77;
+ m_A80 += m_A33 * f11_19;
+ RHS19 += f11_19 * RHS11;
+ const double f12 = 1.0 / m_A36;
+ const double f12_13 = -f12 * m_A41;
+ m_A42 += m_A37 * f12_13;
+ m_A43 += m_A38 * f12_13;
+ RHS13 += f12_13 * RHS12;
+ const double f12_14 = -f12 * m_A49;
+ m_A50 += m_A37 * f12_14;
+ m_A51 += m_A38 * f12_14;
+ RHS14 += f12_14 * RHS12;
+ const double f13 = 1.0 / m_A42;
+ const double f13_14 = -f13 * m_A50;
+ m_A51 += m_A43 * f13_14;
+ m_A52 += m_A44 * f13_14;
+ m_A54 += m_A45 * f13_14;
+ m_A55 += m_A46 * f13_14;
+ RHS14 += f13_14 * RHS13;
+ const double f13_17 = -f13 * m_A65;
+ m_A66 += m_A43 * f13_17;
+ m_A67 += m_A44 * f13_17;
+ m_A70 += m_A45 * f13_17;
+ m_A71 += m_A46 * f13_17;
+ RHS17 += f13_17 * RHS13;
+ const double f13_21 = -f13 * m_A94;
+ m_A95 += m_A43 * f13_21;
+ m_A97 += m_A44 * f13_21;
+ m_A100 += m_A45 * f13_21;
+ m_A101 += m_A46 * f13_21;
+ RHS21 += f13_21 * RHS13;
+ const double f13_22 = -f13 * m_A105;
+ m_A106 += m_A43 * f13_22;
+ m_A107 += m_A44 * f13_22;
+ m_A111 += m_A45 * f13_22;
+ m_A112 += m_A46 * f13_22;
+ RHS22 += f13_22 * RHS13;
+ const double f14 = 1.0 / m_A51;
+ const double f14_17 = -f14 * m_A66;
+ m_A67 += m_A52 * f14_17;
+ m_A68 += m_A53 * f14_17;
+ m_A70 += m_A54 * f14_17;
+ m_A71 += m_A55 * f14_17;
+ RHS17 += f14_17 * RHS14;
+ const double f14_19 = -f14 * m_A78;
+ m_A79 += m_A52 * f14_19;
+ m_A80 += m_A53 * f14_19;
+ m_A82 += m_A54 * f14_19;
+ m_A83 += m_A55 * f14_19;
+ RHS19 += f14_19 * RHS14;
+ const double f14_21 = -f14 * m_A95;
+ m_A97 += m_A52 * f14_21;
+ m_A98 += m_A53 * f14_21;
+ m_A100 += m_A54 * f14_21;
+ m_A101 += m_A55 * f14_21;
+ RHS21 += f14_21 * RHS14;
+ const double f14_22 = -f14 * m_A106;
+ m_A107 += m_A52 * f14_22;
+ m_A109 += m_A53 * f14_22;
+ m_A111 += m_A54 * f14_22;
+ m_A112 += m_A55 * f14_22;
+ RHS22 += f14_22 * RHS14;
+ const double f15 = 1.0 / m_A57;
+ const double f15_20 = -f15 * m_A86;
+ m_A89 += m_A58 * f15_20;
+ RHS20 += f15_20 * RHS15;
+ const double f16 = 1.0 / m_A60;
+ const double f16_21 = -f16 * m_A96;
+ m_A100 += m_A61 * f16_21;
+ RHS21 += f16_21 * RHS16;
+ const double f17 = 1.0 / m_A67;
+ const double f17_19 = -f17 * m_A79;
+ m_A80 += m_A68 * f17_19;
+ m_A81 += m_A69 * f17_19;
+ m_A82 += m_A70 * f17_19;
+ m_A83 += m_A71 * f17_19;
+ RHS19 += f17_19 * RHS17;
+ const double f17_20 = -f17 * m_A87;
+ m_A88 += m_A68 * f17_20;
+ m_A89 += m_A69 * f17_20;
+ m_A90 += m_A70 * f17_20;
+ m_A91 += m_A71 * f17_20;
+ RHS20 += f17_20 * RHS17;
+ const double f17_21 = -f17 * m_A97;
+ m_A98 += m_A68 * f17_21;
+ m_A99 += m_A69 * f17_21;
+ m_A100 += m_A70 * f17_21;
+ m_A101 += m_A71 * f17_21;
+ RHS21 += f17_21 * RHS17;
+ const double f17_22 = -f17 * m_A107;
+ m_A109 += m_A68 * f17_22;
+ m_A110 += m_A69 * f17_22;
+ m_A111 += m_A70 * f17_22;
+ m_A112 += m_A71 * f17_22;
+ RHS22 += f17_22 * RHS17;
+ const double f18 = 1.0 / m_A74;
+ const double f18_22 = -f18 * m_A108;
+ m_A112 += m_A75 * f18_22;
+ RHS22 += f18_22 * RHS18;
+ const double f19 = 1.0 / m_A80;
+ const double f19_20 = -f19 * m_A88;
+ m_A89 += m_A81 * f19_20;
+ m_A90 += m_A82 * f19_20;
+ m_A91 += m_A83 * f19_20;
+ RHS20 += f19_20 * RHS19;
+ const double f19_21 = -f19 * m_A98;
+ m_A99 += m_A81 * f19_21;
+ m_A100 += m_A82 * f19_21;
+ m_A101 += m_A83 * f19_21;
+ RHS21 += f19_21 * RHS19;
+ const double f19_22 = -f19 * m_A109;
+ m_A110 += m_A81 * f19_22;
+ m_A111 += m_A82 * f19_22;
+ m_A112 += m_A83 * f19_22;
+ RHS22 += f19_22 * RHS19;
+ const double f20 = 1.0 / m_A89;
+ const double f20_21 = -f20 * m_A99;
+ m_A100 += m_A90 * f20_21;
+ m_A101 += m_A91 * f20_21;
+ RHS21 += f20_21 * RHS20;
+ const double f20_22 = -f20 * m_A110;
+ m_A111 += m_A90 * f20_22;
+ m_A112 += m_A91 * f20_22;
+ RHS22 += f20_22 * RHS20;
+ const double f21 = 1.0 / m_A100;
+ const double f21_22 = -f21 * m_A111;
+ m_A112 += m_A101 * f21_22;
+ RHS22 += f21_22 * RHS21;
+ V[22] = RHS22 / m_A112;
+ double tmp21 = 0.0;
+ tmp21 += m_A101 * V[22];
+ V[21] = (RHS21 - tmp21) / m_A100;
+ double tmp20 = 0.0;
+ tmp20 += m_A90 * V[21];
+ tmp20 += m_A91 * V[22];
+ V[20] = (RHS20 - tmp20) / m_A89;
+ double tmp19 = 0.0;
+ tmp19 += m_A81 * V[20];
+ tmp19 += m_A82 * V[21];
+ tmp19 += m_A83 * V[22];
+ V[19] = (RHS19 - tmp19) / m_A80;
+ double tmp18 = 0.0;
+ tmp18 += m_A75 * V[22];
+ V[18] = (RHS18 - tmp18) / m_A74;
+ double tmp17 = 0.0;
+ tmp17 += m_A68 * V[19];
+ tmp17 += m_A69 * V[20];
+ tmp17 += m_A70 * V[21];
+ tmp17 += m_A71 * V[22];
+ V[17] = (RHS17 - tmp17) / m_A67;
+ double tmp16 = 0.0;
+ tmp16 += m_A61 * V[21];
+ V[16] = (RHS16 - tmp16) / m_A60;
+ double tmp15 = 0.0;
+ tmp15 += m_A58 * V[20];
+ V[15] = (RHS15 - tmp15) / m_A57;
+ double tmp14 = 0.0;
+ tmp14 += m_A52 * V[17];
+ tmp14 += m_A53 * V[19];
+ tmp14 += m_A54 * V[21];
+ tmp14 += m_A55 * V[22];
+ V[14] = (RHS14 - tmp14) / m_A51;
+ double tmp13 = 0.0;
+ tmp13 += m_A43 * V[14];
+ tmp13 += m_A44 * V[17];
+ tmp13 += m_A45 * V[21];
+ tmp13 += m_A46 * V[22];
+ V[13] = (RHS13 - tmp13) / m_A42;
+ double tmp12 = 0.0;
+ tmp12 += m_A37 * V[13];
+ tmp12 += m_A38 * V[14];
+ V[12] = (RHS12 - tmp12) / m_A36;
+ double tmp11 = 0.0;
+ tmp11 += m_A33 * V[19];
+ V[11] = (RHS11 - tmp11) / m_A32;
+ double tmp10 = 0.0;
+ tmp10 += m_A31 * V[19];
+ V[10] = (RHS10 - tmp10) / m_A30;
+ double tmp9 = 0.0;
+ tmp9 += m_A29 * V[18];
+ V[9] = (RHS9 - tmp9) / m_A28;
+ double tmp8 = 0.0;
+ tmp8 += m_A26 * V[18];
+ tmp8 += m_A27 * V[22];
+ V[8] = (RHS8 - tmp8) / m_A25;
+ double tmp7 = 0.0;
+ tmp7 += m_A21 * V[14];
+ tmp7 += m_A22 * V[17];
+ tmp7 += m_A23 * V[21];
+ tmp7 += m_A24 * V[22];
+ V[7] = (RHS7 - tmp7) / m_A20;
+ double tmp6 = 0.0;
+ tmp6 += m_A16 * V[13];
+ tmp6 += m_A17 * V[17];
+ tmp6 += m_A18 * V[21];
+ tmp6 += m_A19 * V[22];
+ V[6] = (RHS6 - tmp6) / m_A15;
+ double tmp5 = 0.0;
+ tmp5 += m_A14 * V[16];
+ V[5] = (RHS5 - tmp5) / m_A13;
+ double tmp4 = 0.0;
+ tmp4 += m_A11 * V[17];
+ tmp4 += m_A12 * V[20];
+ V[4] = (RHS4 - tmp4) / m_A10;
+ double tmp3 = 0.0;
+ tmp3 += m_A9 * V[20];
+ V[3] = (RHS3 - tmp3) / m_A8;
+ double tmp2 = 0.0;
+ tmp2 += m_A7 * V[15];
+ V[2] = (RHS2 - tmp2) / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[12];
+ tmp1 += m_A4 * V[13];
+ tmp1 += m_A5 * V[14];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[12];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// sspeedr,280zzzap
+static void nl_gcr_122_double_double_42c57d523cac30d0(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ double m_A54(0.0);
+ double m_A55(0.0);
+ double m_A56(0.0);
+ double m_A57(0.0);
+ double m_A58(0.0);
+ double m_A59(0.0);
+ double m_A60(0.0);
+ double m_A61(0.0);
+ double m_A62(0.0);
+ double m_A63(0.0);
+ double m_A64(0.0);
+ double m_A65(0.0);
+ double m_A66(0.0);
+ double m_A67(0.0);
+ double m_A68(0.0);
+ double m_A69(0.0);
+ double m_A70(0.0);
+ double m_A71(0.0);
+ double m_A72(0.0);
+ double m_A73(0.0);
+ double m_A74(0.0);
+ double m_A75(0.0);
+ double m_A76(0.0);
+ double m_A77(0.0);
+ double m_A78(0.0);
+ double m_A79(0.0);
+ double m_A80(0.0);
+ double m_A81(0.0);
+ double m_A82(0.0);
+ double m_A83(0.0);
+ double m_A84(0.0);
+ double m_A85(0.0);
+ double m_A86(0.0);
+ double m_A87(0.0);
+ double m_A88(0.0);
+ double m_A89(0.0);
+ double m_A90(0.0);
+ double m_A91(0.0);
+ double m_A92(0.0);
+ double m_A93(0.0);
+ double m_A94(0.0);
+ double m_A95(0.0);
+ double m_A96(0.0);
+ double m_A97(0.0);
+ double m_A98(0.0);
+ double m_A99(0.0);
+ double m_A100(0.0);
+ double m_A101(0.0);
+ double m_A102(0.0);
+ double m_A103(0.0);
+ double m_A104(0.0);
+ double m_A105(0.0);
+ double m_A106(0.0);
+ double m_A107(0.0);
+ double m_A108(0.0);
+ double m_A109(0.0);
+ double m_A110(0.0);
+ double m_A111(0.0);
+ double m_A112(0.0);
+ double m_A113(0.0);
+ double m_A114(0.0);
+ double m_A115(0.0);
+ double m_A116(0.0);
+ double m_A117(0.0);
+ double m_A118(0.0);
+ double m_A119(0.0);
+ double m_A120(0.0);
+ double m_A121(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A3 += go[2];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 -= go[3] * *cnV[3];
+ m_A4 += gt[4];
+ m_A4 += gt[5];
+ m_A4 += gt[6];
+ m_A5 += go[4];
+ double RHS2 = Idr[4];
+ RHS2 += Idr[5];
+ RHS2 += Idr[6];
+ RHS2 -= go[5] * *cnV[5];
+ RHS2 -= go[6] * *cnV[6];
+ m_A6 += gt[7];
+ m_A6 += gt[8];
+ m_A6 += gt[9];
+ m_A6 += gt[10];
+ m_A6 += gt[11];
+ m_A6 += gt[12];
+ m_A6 += gt[13];
+ m_A7 += go[7];
+ double RHS3 = Idr[7];
+ RHS3 += Idr[8];
+ RHS3 += Idr[9];
+ RHS3 += Idr[10];
+ RHS3 += Idr[11];
+ RHS3 += Idr[12];
+ RHS3 += Idr[13];
+ RHS3 -= go[8] * *cnV[8];
+ RHS3 -= go[9] * *cnV[9];
+ RHS3 -= go[10] * *cnV[10];
+ RHS3 -= go[11] * *cnV[11];
+ RHS3 -= go[12] * *cnV[12];
+ RHS3 -= go[13] * *cnV[13];
+ m_A8 += gt[14];
+ m_A8 += gt[15];
+ m_A9 += go[14];
+ double RHS4 = Idr[14];
+ RHS4 += Idr[15];
+ RHS4 -= go[15] * *cnV[15];
+ m_A10 += gt[16];
+ m_A10 += gt[17];
+ m_A10 += gt[18];
+ m_A10 += gt[19];
+ m_A12 += go[16];
+ m_A13 += go[17];
+ m_A11 += go[18];
+ double RHS5 = Idr[16];
+ RHS5 += Idr[17];
+ RHS5 += Idr[18];
+ RHS5 += Idr[19];
+ RHS5 -= go[19] * *cnV[19];
+ m_A14 += gt[20];
+ m_A14 += gt[21];
+ m_A14 += gt[22];
+ m_A14 += gt[23];
+ m_A14 += gt[24];
+ m_A14 += gt[25];
+ m_A14 += gt[26];
+ m_A15 += go[20];
+ double RHS6 = Idr[20];
+ RHS6 += Idr[21];
+ RHS6 += Idr[22];
+ RHS6 += Idr[23];
+ RHS6 += Idr[24];
+ RHS6 += Idr[25];
+ RHS6 += Idr[26];
+ RHS6 -= go[21] * *cnV[21];
+ RHS6 -= go[22] * *cnV[22];
+ RHS6 -= go[23] * *cnV[23];
+ RHS6 -= go[24] * *cnV[24];
+ RHS6 -= go[25] * *cnV[25];
+ RHS6 -= go[26] * *cnV[26];
+ m_A16 += gt[27];
+ m_A16 += gt[28];
+ m_A18 += go[27];
+ m_A17 += go[28];
+ double RHS7 = Idr[27];
+ RHS7 += Idr[28];
+ m_A19 += gt[29];
+ m_A19 += gt[30];
+ m_A19 += gt[31];
+ m_A20 += go[29];
+ double RHS8 = Idr[29];
+ RHS8 += Idr[30];
+ RHS8 += Idr[31];
+ RHS8 -= go[30] * *cnV[30];
+ RHS8 -= go[31] * *cnV[31];
+ m_A21 += gt[32];
+ m_A21 += gt[33];
+ m_A22 += go[32];
+ double RHS9 = Idr[32];
+ RHS9 += Idr[33];
+ RHS9 -= go[33] * *cnV[33];
+ m_A23 += gt[34];
+ m_A23 += gt[35];
+ m_A23 += gt[36];
+ m_A24 += go[34];
+ m_A25 += go[35];
+ m_A25 += go[36];
+ double RHS10 = Idr[34];
+ RHS10 += Idr[35];
+ RHS10 += Idr[36];
+ m_A26 += gt[37];
+ m_A26 += gt[38];
+ m_A26 += gt[39];
+ m_A26 += gt[40];
+ m_A26 += gt[41];
+ m_A26 += gt[42];
+ m_A26 += gt[43];
+ m_A27 += go[37];
+ double RHS11 = Idr[37];
+ RHS11 += Idr[38];
+ RHS11 += Idr[39];
+ RHS11 += Idr[40];
+ RHS11 += Idr[41];
+ RHS11 += Idr[42];
+ RHS11 += Idr[43];
+ RHS11 -= go[38] * *cnV[38];
+ RHS11 -= go[39] * *cnV[39];
+ RHS11 -= go[40] * *cnV[40];
+ RHS11 -= go[41] * *cnV[41];
+ RHS11 -= go[42] * *cnV[42];
+ RHS11 -= go[43] * *cnV[43];
+ m_A28 += gt[44];
+ m_A28 += gt[45];
+ m_A28 += gt[46];
+ m_A29 += go[44];
+ double RHS12 = Idr[44];
+ RHS12 += Idr[45];
+ RHS12 += Idr[46];
+ RHS12 -= go[45] * *cnV[45];
+ RHS12 -= go[46] * *cnV[46];
+ m_A30 += gt[47];
+ m_A30 += gt[48];
+ m_A30 += gt[49];
+ m_A30 += gt[50];
+ m_A32 += go[47];
+ m_A31 += go[48];
+ m_A33 += go[49];
+ double RHS13 = Idr[47];
+ RHS13 += Idr[48];
+ RHS13 += Idr[49];
+ RHS13 += Idr[50];
+ RHS13 -= go[50] * *cnV[50];
+ m_A35 += gt[51];
+ m_A35 += gt[52];
+ m_A34 += go[51];
+ double RHS14 = Idr[51];
+ RHS14 += Idr[52];
+ RHS14 -= go[52] * *cnV[52];
+ m_A37 += gt[53];
+ m_A37 += gt[54];
+ m_A37 += gt[55];
+ m_A37 += gt[56];
+ m_A36 += go[53];
+ m_A38 += go[54];
+ double RHS15 = Idr[53];
+ RHS15 += Idr[54];
+ RHS15 += Idr[55];
+ RHS15 += Idr[56];
+ RHS15 -= go[55] * *cnV[55];
+ RHS15 -= go[56] * *cnV[56];
+ m_A40 += gt[57];
+ m_A40 += gt[58];
+ m_A39 += go[57];
+ double RHS16 = Idr[57];
+ RHS16 += Idr[58];
+ RHS16 -= go[58] * *cnV[58];
+ m_A43 += gt[59];
+ m_A43 += gt[60];
+ m_A41 += go[59];
+ m_A42 += go[60];
+ double RHS17 = Idr[59];
+ RHS17 += Idr[60];
+ m_A47 += gt[61];
+ m_A47 += gt[62];
+ m_A47 += gt[63];
+ m_A47 += gt[64];
+ m_A47 += gt[65];
+ m_A46 += go[61];
+ m_A49 += go[62];
+ m_A50 += go[63];
+ double RHS18 = Idr[61];
+ RHS18 += Idr[62];
+ RHS18 += Idr[63];
+ RHS18 += Idr[64];
+ RHS18 += Idr[65];
+ RHS18 -= go[64] * *cnV[64];
+ RHS18 -= go[65] * *cnV[65];
+ m_A52 += gt[66];
+ m_A52 += gt[67];
+ m_A51 += go[66];
+ double RHS19 = Idr[66];
+ RHS19 += Idr[67];
+ RHS19 -= go[67] * *cnV[67];
+ m_A55 += gt[68];
+ m_A55 += gt[69];
+ m_A54 += go[68];
+ m_A53 += go[69];
+ double RHS20 = Idr[68];
+ RHS20 += Idr[69];
+ m_A60 += gt[70];
+ m_A60 += gt[71];
+ m_A60 += gt[72];
+ m_A60 += gt[73];
+ m_A59 += go[70];
+ m_A61 += go[71];
+ double RHS21 = Idr[70];
+ RHS21 += Idr[71];
+ RHS21 += Idr[72];
+ RHS21 += Idr[73];
+ RHS21 -= go[72] * *cnV[72];
+ RHS21 -= go[73] * *cnV[73];
+ m_A69 += gt[74];
+ m_A69 += gt[75];
+ m_A69 += gt[76];
+ m_A69 += gt[77];
+ m_A69 += gt[78];
+ m_A69 += gt[79];
+ m_A69 += gt[80];
+ m_A69 += gt[81];
+ m_A69 += gt[82];
+ m_A62 += go[74];
+ m_A65 += go[75];
+ m_A65 += go[76];
+ m_A64 += go[77];
+ m_A63 += go[78];
+ m_A71 += go[79];
+ double RHS22 = Idr[74];
+ RHS22 += Idr[75];
+ RHS22 += Idr[76];
+ RHS22 += Idr[77];
+ RHS22 += Idr[78];
+ RHS22 += Idr[79];
+ RHS22 += Idr[80];
+ RHS22 += Idr[81];
+ RHS22 += Idr[82];
+ RHS22 -= go[80] * *cnV[80];
+ RHS22 -= go[81] * *cnV[81];
+ RHS22 -= go[82] * *cnV[82];
+ m_A75 += gt[83];
+ m_A75 += gt[84];
+ m_A75 += gt[85];
+ m_A75 += gt[86];
+ m_A74 += go[83];
+ m_A76 += go[84];
+ double RHS23 = Idr[83];
+ RHS23 += Idr[84];
+ RHS23 += Idr[85];
+ RHS23 += Idr[86];
+ RHS23 -= go[85] * *cnV[85];
+ RHS23 -= go[86] * *cnV[86];
+ m_A82 += gt[87];
+ m_A82 += gt[88];
+ m_A82 += gt[89];
+ m_A82 += gt[90];
+ m_A82 += gt[91];
+ m_A82 += gt[92];
+ m_A77 += go[87];
+ m_A78 += go[88];
+ m_A84 += go[89];
+ double RHS24 = Idr[87];
+ RHS24 += Idr[88];
+ RHS24 += Idr[89];
+ RHS24 += Idr[90];
+ RHS24 += Idr[91];
+ RHS24 += Idr[92];
+ RHS24 -= go[90] * *cnV[90];
+ RHS24 -= go[91] * *cnV[91];
+ RHS24 -= go[92] * *cnV[92];
+ m_A93 += gt[93];
+ m_A93 += gt[94];
+ m_A93 += gt[95];
+ m_A93 += gt[96];
+ m_A93 += gt[97];
+ m_A91 += go[93];
+ m_A89 += go[94];
+ m_A88 += go[95];
+ m_A87 += go[96];
+ m_A86 += go[97];
+ double RHS25 = Idr[93];
+ RHS25 += Idr[94];
+ RHS25 += Idr[95];
+ RHS25 += Idr[96];
+ RHS25 += Idr[97];
+ m_A104 += gt[98];
+ m_A104 += gt[99];
+ m_A104 += gt[100];
+ m_A104 += gt[101];
+ m_A104 += gt[102];
+ m_A102 += go[98];
+ m_A99 += go[99];
+ m_A98 += go[100];
+ m_A97 += go[101];
+ m_A96 += go[102];
+ double RHS26 = Idr[98];
+ RHS26 += Idr[99];
+ RHS26 += Idr[100];
+ RHS26 += Idr[101];
+ RHS26 += Idr[102];
+ m_A113 += gt[103];
+ m_A113 += gt[104];
+ m_A113 += gt[105];
+ m_A113 += gt[106];
+ m_A107 += go[103];
+ m_A106 += go[104];
+ m_A114 += go[105];
+ double RHS27 = Idr[103];
+ RHS27 += Idr[104];
+ RHS27 += Idr[105];
+ RHS27 += Idr[106];
+ RHS27 -= go[106] * *cnV[106];
+ m_A121 += gt[107];
+ m_A121 += gt[108];
+ m_A121 += gt[109];
+ m_A121 += gt[110];
+ m_A121 += gt[111];
+ m_A118 += go[107];
+ m_A117 += go[108];
+ m_A120 += go[109];
+ m_A116 += go[110];
+ m_A115 += go[111];
+ double RHS28 = Idr[107];
+ RHS28 += Idr[108];
+ RHS28 += Idr[109];
+ RHS28 += Idr[110];
+ RHS28 += Idr[111];
+ const double f0 = 1.0 / m_A0;
+ const double f0_17 = -f0 * m_A41;
+ m_A43 += m_A1 * f0_17;
+ RHS17 += f0_17 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_14 = -f1 * m_A34;
+ m_A35 += m_A3 * f1_14;
+ RHS14 += f1_14 * RHS1;
+ const double f1_25 = -f1 * m_A86;
+ m_A89 += m_A3 * f1_25;
+ RHS25 += f1_25 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_15 = -f2 * m_A36;
+ m_A38 += m_A5 * f2_15;
+ RHS15 += f2_15 * RHS2;
+ const double f2_25 = -f2 * m_A87;
+ m_A93 += m_A5 * f2_25;
+ RHS25 += f2_25 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_22 = -f3 * m_A62;
+ m_A66 += m_A7 * f3_22;
+ RHS22 += f3_22 * RHS3;
+ const double f4 = 1.0 / m_A8;
+ const double f4_16 = -f4 * m_A39;
+ m_A40 += m_A9 * f4_16;
+ RHS16 += f4_16 * RHS4;
+ const double f4_28 = -f4 * m_A115;
+ m_A117 += m_A9 * f4_28;
+ RHS28 += f4_28 * RHS4;
+ const double f5 = 1.0 / m_A10;
+ const double f5_17 = -f5 * m_A42;
+ m_A43 += m_A11 * f5_17;
+ m_A44 += m_A12 * f5_17;
+ m_A45 += m_A13 * f5_17;
+ RHS17 += f5_17 * RHS5;
+ const double f5_22 = -f5 * m_A63;
+ m_A67 += m_A11 * f5_22;
+ m_A69 += m_A12 * f5_22;
+ m_A71 += m_A13 * f5_22;
+ RHS22 += f5_22 * RHS5;
+ const double f5_25 = -f5 * m_A88;
+ m_A90 += m_A11 * f5_25;
+ m_A91 += m_A12 * f5_25;
+ m_A93 += m_A13 * f5_25;
+ RHS25 += f5_25 * RHS5;
+ const double f6 = 1.0 / m_A14;
+ const double f6_18 = -f6 * m_A46;
+ m_A48 += m_A15 * f6_18;
+ RHS18 += f6_18 * RHS6;
+ const double f7 = 1.0 / m_A16;
+ const double f7_22 = -f7 * m_A64;
+ m_A69 += m_A17 * f7_22;
+ m_A73 += m_A18 * f7_22;
+ RHS22 += f7_22 * RHS7;
+ const double f7_27 = -f7 * m_A106;
+ m_A109 += m_A17 * f7_27;
+ m_A113 += m_A18 * f7_27;
+ RHS27 += f7_27 * RHS7;
+ const double f8 = 1.0 / m_A19;
+ const double f8_21 = -f8 * m_A59;
+ m_A61 += m_A20 * f8_21;
+ RHS21 += f8_21 * RHS8;
+ const double f8_28 = -f8 * m_A116;
+ m_A121 += m_A20 * f8_28;
+ RHS28 += f8_28 * RHS8;
+ const double f9 = 1.0 / m_A21;
+ const double f9_19 = -f9 * m_A51;
+ m_A52 += m_A22 * f9_19;
+ RHS19 += f9_19 * RHS9;
+ const double f9_26 = -f9 * m_A96;
+ m_A99 += m_A22 * f9_26;
+ RHS26 += f9_26 * RHS9;
+ const double f10 = 1.0 / m_A23;
+ const double f10_20 = -f10 * m_A53;
+ m_A55 += m_A24 * f10_20;
+ m_A56 += m_A25 * f10_20;
+ RHS20 += f10_20 * RHS10;
+ const double f10_22 = -f10 * m_A65;
+ m_A68 += m_A24 * f10_22;
+ m_A69 += m_A25 * f10_22;
+ RHS22 += f10_22 * RHS10;
+ const double f11 = 1.0 / m_A26;
+ const double f11_24 = -f11 * m_A77;
+ m_A81 += m_A27 * f11_24;
+ RHS24 += f11_24 * RHS11;
+ const double f12 = 1.0 / m_A28;
+ const double f12_23 = -f12 * m_A74;
+ m_A76 += m_A29 * f12_23;
+ RHS23 += f12_23 * RHS12;
+ const double f12_26 = -f12 * m_A97;
+ m_A104 += m_A29 * f12_26;
+ RHS26 += f12_26 * RHS12;
+ const double f13 = 1.0 / m_A30;
+ const double f13_20 = -f13 * m_A54;
+ m_A55 += m_A31 * f13_20;
+ m_A57 += m_A32 * f13_20;
+ m_A58 += m_A33 * f13_20;
+ RHS20 += f13_20 * RHS13;
+ const double f13_24 = -f13 * m_A78;
+ m_A79 += m_A31 * f13_24;
+ m_A82 += m_A32 * f13_24;
+ m_A84 += m_A33 * f13_24;
+ RHS24 += f13_24 * RHS13;
+ const double f13_26 = -f13 * m_A98;
+ m_A100 += m_A31 * f13_26;
+ m_A102 += m_A32 * f13_26;
+ m_A104 += m_A33 * f13_26;
+ RHS26 += f13_26 * RHS13;
+ const double f14 = 1.0 / m_A35;
+ const double f14_25 = -f14 * m_A89;
+ RHS25 += f14_25 * RHS14;
+ const double f15 = 1.0 / m_A37;
+ const double f15_22 = -f15 * m_A66;
+ m_A71 += m_A38 * f15_22;
+ RHS22 += f15_22 * RHS15;
+ const double f16 = 1.0 / m_A40;
+ const double f16_28 = -f16 * m_A117;
+ RHS28 += f16_28 * RHS16;
+ const double f17 = 1.0 / m_A43;
+ const double f17_22 = -f17 * m_A67;
+ m_A69 += m_A44 * f17_22;
+ m_A71 += m_A45 * f17_22;
+ RHS22 += f17_22 * RHS17;
+ const double f17_25 = -f17 * m_A90;
+ m_A91 += m_A44 * f17_25;
+ m_A93 += m_A45 * f17_25;
+ RHS25 += f17_25 * RHS17;
+ const double f18 = 1.0 / m_A47;
+ const double f18_27 = -f18 * m_A107;
+ m_A108 += m_A48 * f18_27;
+ m_A113 += m_A49 * f18_27;
+ m_A114 += m_A50 * f18_27;
+ RHS27 += f18_27 * RHS18;
+ const double f18_28 = -f18 * m_A118;
+ m_A119 += m_A48 * f18_28;
+ m_A120 += m_A49 * f18_28;
+ m_A121 += m_A50 * f18_28;
+ RHS28 += f18_28 * RHS18;
+ const double f19 = 1.0 / m_A52;
+ const double f19_26 = -f19 * m_A99;
+ RHS26 += f19_26 * RHS19;
+ const double f20 = 1.0 / m_A55;
+ const double f20_22 = -f20 * m_A68;
+ m_A69 += m_A56 * f20_22;
+ m_A70 += m_A57 * f20_22;
+ m_A72 += m_A58 * f20_22;
+ RHS22 += f20_22 * RHS20;
+ const double f20_24 = -f20 * m_A79;
+ m_A80 += m_A56 * f20_24;
+ m_A82 += m_A57 * f20_24;
+ m_A84 += m_A58 * f20_24;
+ RHS24 += f20_24 * RHS20;
+ const double f20_26 = -f20 * m_A100;
+ m_A101 += m_A56 * f20_26;
+ m_A102 += m_A57 * f20_26;
+ m_A104 += m_A58 * f20_26;
+ RHS26 += f20_26 * RHS20;
+ const double f21 = 1.0 / m_A60;
+ const double f21_27 = -f21 * m_A108;
+ m_A114 += m_A61 * f21_27;
+ RHS27 += f21_27 * RHS21;
+ const double f21_28 = -f21 * m_A119;
+ m_A121 += m_A61 * f21_28;
+ RHS28 += f21_28 * RHS21;
+ const double f22 = 1.0 / m_A69;
+ const double f22_24 = -f22 * m_A80;
+ m_A82 += m_A70 * f22_24;
+ m_A83 += m_A71 * f22_24;
+ m_A84 += m_A72 * f22_24;
+ m_A85 += m_A73 * f22_24;
+ RHS24 += f22_24 * RHS22;
+ const double f22_25 = -f22 * m_A91;
+ m_A92 += m_A70 * f22_25;
+ m_A93 += m_A71 * f22_25;
+ m_A94 += m_A72 * f22_25;
+ m_A95 += m_A73 * f22_25;
+ RHS25 += f22_25 * RHS22;
+ const double f22_26 = -f22 * m_A101;
+ m_A102 += m_A70 * f22_26;
+ m_A103 += m_A71 * f22_26;
+ m_A104 += m_A72 * f22_26;
+ m_A105 += m_A73 * f22_26;
+ RHS26 += f22_26 * RHS22;
+ const double f22_27 = -f22 * m_A109;
+ m_A110 += m_A70 * f22_27;
+ m_A111 += m_A71 * f22_27;
+ m_A112 += m_A72 * f22_27;
+ m_A113 += m_A73 * f22_27;
+ RHS27 += f22_27 * RHS22;
+ const double f23 = 1.0 / m_A75;
+ const double f23_24 = -f23 * m_A81;
+ m_A84 += m_A76 * f23_24;
+ RHS24 += f23_24 * RHS23;
+ const double f24 = 1.0 / m_A82;
+ const double f24_25 = -f24 * m_A92;
+ m_A93 += m_A83 * f24_25;
+ m_A94 += m_A84 * f24_25;
+ m_A95 += m_A85 * f24_25;
+ RHS25 += f24_25 * RHS24;
+ const double f24_26 = -f24 * m_A102;
+ m_A103 += m_A83 * f24_26;
+ m_A104 += m_A84 * f24_26;
+ m_A105 += m_A85 * f24_26;
+ RHS26 += f24_26 * RHS24;
+ const double f24_27 = -f24 * m_A110;
+ m_A111 += m_A83 * f24_27;
+ m_A112 += m_A84 * f24_27;
+ m_A113 += m_A85 * f24_27;
+ RHS27 += f24_27 * RHS24;
+ const double f25 = 1.0 / m_A93;
+ const double f25_26 = -f25 * m_A103;
+ m_A104 += m_A94 * f25_26;
+ m_A105 += m_A95 * f25_26;
+ RHS26 += f25_26 * RHS25;
+ const double f25_27 = -f25 * m_A111;
+ m_A112 += m_A94 * f25_27;
+ m_A113 += m_A95 * f25_27;
+ RHS27 += f25_27 * RHS25;
+ const double f26 = 1.0 / m_A104;
+ const double f26_27 = -f26 * m_A112;
+ m_A113 += m_A105 * f26_27;
+ RHS27 += f26_27 * RHS26;
+ const double f27 = 1.0 / m_A113;
+ const double f27_28 = -f27 * m_A120;
+ m_A121 += m_A114 * f27_28;
+ RHS28 += f27_28 * RHS27;
+ V[28] = RHS28 / m_A121;
+ double tmp27 = 0.0;
+ tmp27 += m_A114 * V[28];
+ V[27] = (RHS27 - tmp27) / m_A113;
+ double tmp26 = 0.0;
+ tmp26 += m_A105 * V[27];
+ V[26] = (RHS26 - tmp26) / m_A104;
+ double tmp25 = 0.0;
+ tmp25 += m_A94 * V[26];
+ tmp25 += m_A95 * V[27];
+ V[25] = (RHS25 - tmp25) / m_A93;
+ double tmp24 = 0.0;
+ tmp24 += m_A83 * V[25];
+ tmp24 += m_A84 * V[26];
+ tmp24 += m_A85 * V[27];
+ V[24] = (RHS24 - tmp24) / m_A82;
+ double tmp23 = 0.0;
+ tmp23 += m_A76 * V[26];
+ V[23] = (RHS23 - tmp23) / m_A75;
+ double tmp22 = 0.0;
+ tmp22 += m_A70 * V[24];
+ tmp22 += m_A71 * V[25];
+ tmp22 += m_A72 * V[26];
+ tmp22 += m_A73 * V[27];
+ V[22] = (RHS22 - tmp22) / m_A69;
+ double tmp21 = 0.0;
+ tmp21 += m_A61 * V[28];
+ V[21] = (RHS21 - tmp21) / m_A60;
+ double tmp20 = 0.0;
+ tmp20 += m_A56 * V[22];
+ tmp20 += m_A57 * V[24];
+ tmp20 += m_A58 * V[26];
+ V[20] = (RHS20 - tmp20) / m_A55;
+ double tmp19 = 0.0;
+ V[19] = (RHS19 - tmp19) / m_A52;
+ double tmp18 = 0.0;
+ tmp18 += m_A48 * V[21];
+ tmp18 += m_A49 * V[27];
+ tmp18 += m_A50 * V[28];
+ V[18] = (RHS18 - tmp18) / m_A47;
+ double tmp17 = 0.0;
+ tmp17 += m_A44 * V[22];
+ tmp17 += m_A45 * V[25];
+ V[17] = (RHS17 - tmp17) / m_A43;
+ double tmp16 = 0.0;
+ V[16] = (RHS16 - tmp16) / m_A40;
+ double tmp15 = 0.0;
+ tmp15 += m_A38 * V[25];
+ V[15] = (RHS15 - tmp15) / m_A37;
+ double tmp14 = 0.0;
+ V[14] = (RHS14 - tmp14) / m_A35;
+ double tmp13 = 0.0;
+ tmp13 += m_A31 * V[20];
+ tmp13 += m_A32 * V[24];
+ tmp13 += m_A33 * V[26];
+ V[13] = (RHS13 - tmp13) / m_A30;
+ double tmp12 = 0.0;
+ tmp12 += m_A29 * V[26];
+ V[12] = (RHS12 - tmp12) / m_A28;
+ double tmp11 = 0.0;
+ tmp11 += m_A27 * V[23];
+ V[11] = (RHS11 - tmp11) / m_A26;
+ double tmp10 = 0.0;
+ tmp10 += m_A24 * V[20];
+ tmp10 += m_A25 * V[22];
+ V[10] = (RHS10 - tmp10) / m_A23;
+ double tmp9 = 0.0;
+ tmp9 += m_A22 * V[19];
+ V[9] = (RHS9 - tmp9) / m_A21;
+ double tmp8 = 0.0;
+ tmp8 += m_A20 * V[28];
+ V[8] = (RHS8 - tmp8) / m_A19;
+ double tmp7 = 0.0;
+ tmp7 += m_A17 * V[22];
+ tmp7 += m_A18 * V[27];
+ V[7] = (RHS7 - tmp7) / m_A16;
+ double tmp6 = 0.0;
+ tmp6 += m_A15 * V[21];
+ V[6] = (RHS6 - tmp6) / m_A14;
+ double tmp5 = 0.0;
+ tmp5 += m_A11 * V[17];
+ tmp5 += m_A12 * V[22];
+ tmp5 += m_A13 * V[25];
+ V[5] = (RHS5 - tmp5) / m_A10;
+ double tmp4 = 0.0;
+ tmp4 += m_A9 * V[16];
+ V[4] = (RHS4 - tmp4) / m_A8;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[15];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[25];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[14];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[17];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
+// sspeedr,280zzzap
+static void nl_gcr_123_double_double_864a61c57bac9c38(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ double m_A54(0.0);
+ double m_A55(0.0);
+ double m_A56(0.0);
+ double m_A57(0.0);
+ double m_A58(0.0);
+ double m_A59(0.0);
+ double m_A60(0.0);
+ double m_A61(0.0);
+ double m_A62(0.0);
+ double m_A63(0.0);
+ double m_A64(0.0);
+ double m_A65(0.0);
+ double m_A66(0.0);
+ double m_A67(0.0);
+ double m_A68(0.0);
+ double m_A69(0.0);
+ double m_A70(0.0);
+ double m_A71(0.0);
+ double m_A72(0.0);
+ double m_A73(0.0);
+ double m_A74(0.0);
+ double m_A75(0.0);
+ double m_A76(0.0);
+ double m_A77(0.0);
+ double m_A78(0.0);
+ double m_A79(0.0);
+ double m_A80(0.0);
+ double m_A81(0.0);
+ double m_A82(0.0);
+ double m_A83(0.0);
+ double m_A84(0.0);
+ double m_A85(0.0);
+ double m_A86(0.0);
+ double m_A87(0.0);
+ double m_A88(0.0);
+ double m_A89(0.0);
+ double m_A90(0.0);
+ double m_A91(0.0);
+ double m_A92(0.0);
+ double m_A93(0.0);
+ double m_A94(0.0);
+ double m_A95(0.0);
+ double m_A96(0.0);
+ double m_A97(0.0);
+ double m_A98(0.0);
+ double m_A99(0.0);
+ double m_A100(0.0);
+ double m_A101(0.0);
+ double m_A102(0.0);
+ double m_A103(0.0);
+ double m_A104(0.0);
+ double m_A105(0.0);
+ double m_A106(0.0);
+ double m_A107(0.0);
+ double m_A108(0.0);
+ double m_A109(0.0);
+ double m_A110(0.0);
+ double m_A111(0.0);
+ double m_A112(0.0);
+ double m_A113(0.0);
+ double m_A114(0.0);
+ double m_A115(0.0);
+ double m_A116(0.0);
+ double m_A117(0.0);
+ double m_A118(0.0);
+ double m_A119(0.0);
+ double m_A120(0.0);
+ double m_A121(0.0);
+ double m_A122(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 -= go[4] * *cnV[4];
+ m_A4 += gt[5];
+ m_A4 += gt[6];
+ m_A4 += gt[7];
+ m_A4 += gt[8];
+ m_A4 += gt[9];
+ m_A4 += gt[10];
+ m_A4 += gt[11];
+ m_A5 += go[5];
+ double RHS2 = Idr[5];
+ RHS2 += Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 += Idr[11];
+ RHS2 -= go[6] * *cnV[6];
+ RHS2 -= go[7] * *cnV[7];
+ RHS2 -= go[8] * *cnV[8];
+ RHS2 -= go[9] * *cnV[9];
+ RHS2 -= go[10] * *cnV[10];
+ RHS2 -= go[11] * *cnV[11];
+ m_A6 += gt[12];
+ m_A6 += gt[13];
+ m_A6 += gt[14];
+ m_A7 += go[12];
+ double RHS3 = Idr[12];
+ RHS3 += Idr[13];
+ RHS3 += Idr[14];
+ RHS3 -= go[13] * *cnV[13];
+ RHS3 -= go[14] * *cnV[14];
+ m_A8 += gt[15];
+ m_A8 += gt[16];
+ m_A8 += gt[17];
+ m_A8 += gt[18];
+ m_A8 += gt[19];
+ m_A8 += gt[20];
+ m_A8 += gt[21];
+ m_A9 += go[15];
+ double RHS4 = Idr[15];
+ RHS4 += Idr[16];
+ RHS4 += Idr[17];
+ RHS4 += Idr[18];
+ RHS4 += Idr[19];
+ RHS4 += Idr[20];
+ RHS4 += Idr[21];
+ RHS4 -= go[16] * *cnV[16];
+ RHS4 -= go[17] * *cnV[17];
+ RHS4 -= go[18] * *cnV[18];
+ RHS4 -= go[19] * *cnV[19];
+ RHS4 -= go[20] * *cnV[20];
+ RHS4 -= go[21] * *cnV[21];
+ m_A10 += gt[22];
+ m_A10 += gt[23];
+ m_A11 += go[22];
+ double RHS5 = Idr[22];
+ RHS5 += Idr[23];
+ RHS5 -= go[23] * *cnV[23];
+ m_A12 += gt[24];
+ m_A12 += gt[25];
+ m_A14 += go[24];
+ m_A13 += go[25];
+ double RHS6 = Idr[24];
+ RHS6 += Idr[25];
+ m_A15 += gt[26];
+ m_A15 += gt[27];
+ m_A16 += go[26];
+ double RHS7 = Idr[26];
+ RHS7 += Idr[27];
+ RHS7 -= go[27] * *cnV[27];
+ m_A17 += gt[28];
+ m_A17 += gt[29];
+ m_A18 += go[28];
+ double RHS8 = Idr[28];
+ RHS8 += Idr[29];
+ RHS8 -= go[29] * *cnV[29];
+ m_A19 += gt[30];
+ m_A19 += gt[31];
+ m_A19 += gt[32];
+ m_A19 += gt[33];
+ m_A19 += gt[34];
+ m_A19 += gt[35];
+ m_A19 += gt[36];
+ m_A20 += go[30];
+ double RHS9 = Idr[30];
+ RHS9 += Idr[31];
+ RHS9 += Idr[32];
+ RHS9 += Idr[33];
+ RHS9 += Idr[34];
+ RHS9 += Idr[35];
+ RHS9 += Idr[36];
+ RHS9 -= go[31] * *cnV[31];
+ RHS9 -= go[32] * *cnV[32];
+ RHS9 -= go[33] * *cnV[33];
+ RHS9 -= go[34] * *cnV[34];
+ RHS9 -= go[35] * *cnV[35];
+ RHS9 -= go[36] * *cnV[36];
+ m_A21 += gt[37];
+ m_A21 += gt[38];
+ m_A21 += gt[39];
+ m_A22 += go[37];
+ double RHS10 = Idr[37];
+ RHS10 += Idr[38];
+ RHS10 += Idr[39];
+ RHS10 -= go[38] * *cnV[38];
+ RHS10 -= go[39] * *cnV[39];
+ m_A23 += gt[40];
+ m_A23 += gt[41];
+ m_A23 += gt[42];
+ m_A23 += gt[43];
+ m_A24 += go[40];
+ double RHS11 = Idr[40];
+ RHS11 += Idr[41];
+ RHS11 += Idr[42];
+ RHS11 += Idr[43];
+ RHS11 -= go[41] * *cnV[41];
+ RHS11 -= go[42] * *cnV[42];
+ RHS11 -= go[43] * *cnV[43];
+ m_A25 += gt[44];
+ m_A25 += gt[45];
+ m_A25 += gt[46];
+ m_A25 += gt[47];
+ m_A25 += gt[48];
+ m_A25 += gt[49];
+ m_A25 += gt[50];
+ m_A26 += go[44];
+ double RHS12 = Idr[44];
+ RHS12 += Idr[45];
+ RHS12 += Idr[46];
+ RHS12 += Idr[47];
+ RHS12 += Idr[48];
+ RHS12 += Idr[49];
+ RHS12 += Idr[50];
+ RHS12 -= go[45] * *cnV[45];
+ RHS12 -= go[46] * *cnV[46];
+ RHS12 -= go[47] * *cnV[47];
+ RHS12 -= go[48] * *cnV[48];
+ RHS12 -= go[49] * *cnV[49];
+ RHS12 -= go[50] * *cnV[50];
+ m_A27 += gt[51];
+ m_A27 += gt[52];
+ m_A28 += go[51];
+ double RHS13 = Idr[51];
+ RHS13 += Idr[52];
+ RHS13 -= go[52] * *cnV[52];
+ m_A29 += gt[53];
+ m_A29 += gt[54];
+ m_A30 += go[53];
+ double RHS14 = Idr[53];
+ RHS14 += Idr[54];
+ RHS14 -= go[54] * *cnV[54];
+ m_A31 += gt[55];
+ m_A31 += gt[56];
+ m_A32 += go[55];
+ double RHS15 = Idr[55];
+ RHS15 += Idr[56];
+ RHS15 -= go[56] * *cnV[56];
+ m_A33 += gt[57];
+ m_A33 += gt[58];
+ m_A33 += gt[59];
+ m_A33 += gt[60];
+ m_A35 += go[57];
+ m_A34 += go[58];
+ double RHS16 = Idr[57];
+ RHS16 += Idr[58];
+ RHS16 += Idr[59];
+ RHS16 += Idr[60];
+ RHS16 -= go[59] * *cnV[59];
+ RHS16 -= go[60] * *cnV[60];
+ m_A36 += gt[61];
+ m_A36 += gt[62];
+ m_A36 += gt[63];
+ m_A37 += go[61];
+ double RHS17 = Idr[61];
+ RHS17 += Idr[62];
+ RHS17 += Idr[63];
+ RHS17 -= go[62] * *cnV[62];
+ RHS17 -= go[63] * *cnV[63];
+ m_A38 += gt[64];
+ m_A38 += gt[65];
+ m_A39 += go[64];
+ double RHS18 = Idr[64];
+ RHS18 += Idr[65];
+ RHS18 -= go[65] * *cnV[65];
+ m_A40 += gt[66];
+ m_A40 += gt[67];
+ m_A41 += go[66];
+ double RHS19 = Idr[66];
+ RHS19 += Idr[67];
+ RHS19 -= go[67] * *cnV[67];
+ m_A43 += gt[68];
+ m_A43 += gt[69];
+ m_A43 += gt[70];
+ m_A43 += gt[71];
+ m_A42 += go[68];
+ double RHS20 = Idr[68];
+ RHS20 += Idr[69];
+ RHS20 += Idr[70];
+ RHS20 += Idr[71];
+ RHS20 -= go[69] * *cnV[69];
+ RHS20 -= go[70] * *cnV[70];
+ RHS20 -= go[71] * *cnV[71];
+ m_A47 += gt[72];
+ m_A47 += gt[73];
+ m_A46 += go[72];
+ m_A45 += go[73];
+ double RHS21 = Idr[72];
+ RHS21 += Idr[73];
+ m_A51 += gt[74];
+ m_A51 += gt[75];
+ m_A49 += go[74];
+ double RHS22 = Idr[74];
+ RHS22 += Idr[75];
+ RHS22 -= go[75] * *cnV[75];
+ m_A54 += gt[76];
+ m_A54 += gt[77];
+ m_A54 += gt[78];
+ m_A53 += go[76];
+ m_A52 += go[77];
+ double RHS23 = Idr[76];
+ RHS23 += Idr[77];
+ RHS23 += Idr[78];
+ RHS23 -= go[78] * *cnV[78];
+ m_A56 += gt[79];
+ m_A56 += gt[80];
+ m_A56 += gt[81];
+ m_A56 += gt[82];
+ m_A55 += go[79];
+ m_A57 += go[80];
+ double RHS24 = Idr[79];
+ RHS24 += Idr[80];
+ RHS24 += Idr[81];
+ RHS24 += Idr[82];
+ RHS24 -= go[81] * *cnV[81];
+ RHS24 -= go[82] * *cnV[82];
+ m_A59 += gt[83];
+ m_A59 += gt[84];
+ m_A59 += gt[85];
+ m_A59 += gt[86];
+ m_A58 += go[83];
+ m_A60 += go[84];
+ double RHS25 = Idr[83];
+ RHS25 += Idr[84];
+ RHS25 += Idr[85];
+ RHS25 += Idr[86];
+ RHS25 -= go[85] * *cnV[85];
+ RHS25 -= go[86] * *cnV[86];
+ m_A62 += gt[87];
+ m_A62 += gt[88];
+ m_A63 += go[87];
+ m_A61 += go[88];
+ double RHS26 = Idr[87];
+ RHS26 += Idr[88];
+ m_A67 += gt[89];
+ m_A67 += gt[90];
+ m_A67 += gt[91];
+ m_A67 += gt[92];
+ m_A67 += gt[93];
+ m_A67 += gt[94];
+ m_A64 += go[89];
+ m_A65 += go[90];
+ m_A69 += go[91];
+ m_A68 += go[92];
+ double RHS27 = Idr[89];
+ RHS27 += Idr[90];
+ RHS27 += Idr[91];
+ RHS27 += Idr[92];
+ RHS27 += Idr[93];
+ RHS27 += Idr[94];
+ RHS27 -= go[93] * *cnV[93];
+ RHS27 -= go[94] * *cnV[94];
+ m_A72 += gt[95];
+ m_A72 += gt[96];
+ m_A72 += gt[97];
+ m_A72 += gt[98];
+ m_A71 += go[95];
+ m_A73 += go[96];
+ double RHS28 = Idr[95];
+ RHS28 += Idr[96];
+ RHS28 += Idr[97];
+ RHS28 += Idr[98];
+ RHS28 -= go[97] * *cnV[97];
+ RHS28 -= go[98] * *cnV[98];
+ m_A76 += gt[99];
+ m_A76 += gt[100];
+ m_A76 += gt[101];
+ m_A76 += gt[102];
+ m_A77 += go[99];
+ m_A78 += go[100];
+ m_A74 += go[101];
+ m_A75 += go[102];
+ double RHS29 = Idr[99];
+ RHS29 += Idr[100];
+ RHS29 += Idr[101];
+ RHS29 += Idr[102];
+ m_A81 += gt[103];
+ m_A81 += gt[104];
+ m_A81 += gt[105];
+ m_A80 += go[103];
+ m_A79 += go[104];
+ double RHS30 = Idr[103];
+ RHS30 += Idr[104];
+ RHS30 += Idr[105];
+ RHS30 -= go[105] * *cnV[105];
+ m_A84 += gt[106];
+ m_A84 += gt[107];
+ m_A82 += go[106];
+ m_A83 += go[107];
+ double RHS31 = Idr[106];
+ RHS31 += Idr[107];
+ m_A91 += gt[108];
+ m_A91 += gt[109];
+ m_A91 += gt[110];
+ m_A91 += gt[111];
+ m_A91 += gt[112];
+ m_A86 += go[108];
+ m_A90 += go[109];
+ m_A88 += go[110];
+ m_A85 += go[111];
+ m_A87 += go[112];
+ double RHS32 = Idr[108];
+ RHS32 += Idr[109];
+ RHS32 += Idr[110];
+ RHS32 += Idr[111];
+ RHS32 += Idr[112];
+ m_A99 += gt[113];
+ m_A99 += gt[114];
+ m_A99 += gt[115];
+ m_A99 += gt[116];
+ m_A99 += gt[117];
+ m_A96 += go[113];
+ m_A100 += go[114];
+ m_A97 += go[115];
+ m_A94 += go[116];
+ m_A95 += go[117];
+ double RHS33 = Idr[113];
+ RHS33 += Idr[114];
+ RHS33 += Idr[115];
+ RHS33 += Idr[116];
+ RHS33 += Idr[117];
+ m_A106 += gt[118];
+ m_A106 += gt[119];
+ m_A106 += gt[120];
+ m_A106 += gt[121];
+ m_A103 += go[118];
+ m_A104 += go[119];
+ m_A101 += go[120];
+ m_A102 += go[121];
+ double RHS34 = Idr[118];
+ RHS34 += Idr[119];
+ RHS34 += Idr[120];
+ RHS34 += Idr[121];
+ m_A111 += gt[122];
+ m_A111 += gt[123];
+ m_A111 += gt[124];
+ m_A111 += gt[125];
+ m_A108 += go[122];
+ m_A109 += go[123];
+ double RHS35 = Idr[122];
+ RHS35 += Idr[123];
+ RHS35 += Idr[124];
+ RHS35 += Idr[125];
+ RHS35 -= go[124] * *cnV[124];
+ RHS35 -= go[125] * *cnV[125];
+ m_A122 += gt[126];
+ m_A122 += gt[127];
+ m_A122 += gt[128];
+ m_A122 += gt[129];
+ m_A122 += gt[130];
+ m_A122 += gt[131];
+ m_A113 += go[126];
+ m_A117 += go[127];
+ m_A120 += go[128];
+ m_A114 += go[129];
+ double RHS36 = Idr[126];
+ RHS36 += Idr[127];
+ RHS36 += Idr[128];
+ RHS36 += Idr[129];
+ RHS36 += Idr[130];
+ RHS36 += Idr[131];
+ RHS36 -= go[130] * *cnV[130];
+ RHS36 -= go[131] * *cnV[131];
+ const double f0 = 1.0 / m_A0;
+ const double f0_24 = -f0 * m_A55;
+ m_A57 += m_A1 * f0_24;
+ RHS24 += f0_24 * RHS0;
+ const double f0_32 = -f0 * m_A85;
+ m_A91 += m_A1 * f0_32;
+ RHS32 += f0_32 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_32 = -f1 * m_A86;
+ m_A91 += m_A3 * f1_32;
+ RHS32 += f1_32 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_27 = -f2 * m_A64;
+ m_A66 += m_A5 * f2_27;
+ RHS27 += f2_27 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_25 = -f3 * m_A58;
+ m_A60 += m_A7 * f3_25;
+ RHS25 += f3_25 * RHS3;
+ const double f3_34 = -f3 * m_A101;
+ m_A106 += m_A7 * f3_34;
+ RHS34 += f3_34 * RHS3;
+ const double f4 = 1.0 / m_A8;
+ const double f4_20 = -f4 * m_A42;
+ m_A44 += m_A9 * f4_20;
+ RHS20 += f4_20 * RHS4;
+ const double f5 = 1.0 / m_A10;
+ const double f5_21 = -f5 * m_A45;
+ m_A47 += m_A11 * f5_21;
+ RHS21 += f5_21 * RHS5;
+ const double f5_32 = -f5 * m_A87;
+ m_A88 += m_A11 * f5_32;
+ RHS32 += f5_32 * RHS5;
+ const double f6 = 1.0 / m_A12;
+ const double f6_21 = -f6 * m_A46;
+ m_A47 += m_A13 * f6_21;
+ m_A48 += m_A14 * f6_21;
+ RHS21 += f6_21 * RHS6;
+ const double f6_22 = -f6 * m_A49;
+ m_A50 += m_A13 * f6_22;
+ m_A51 += m_A14 * f6_22;
+ RHS22 += f6_22 * RHS6;
+ const double f7 = 1.0 / m_A15;
+ const double f7_23 = -f7 * m_A52;
+ m_A54 += m_A16 * f7_23;
+ RHS23 += f7_23 * RHS7;
+ const double f7_34 = -f7 * m_A102;
+ m_A103 += m_A16 * f7_34;
+ RHS34 += f7_34 * RHS7;
+ const double f8 = 1.0 / m_A17;
+ const double f8_23 = -f8 * m_A53;
+ m_A54 += m_A18 * f8_23;
+ RHS23 += f8_23 * RHS8;
+ const double f9 = 1.0 / m_A19;
+ const double f9_36 = -f9 * m_A113;
+ m_A116 += m_A20 * f9_36;
+ RHS36 += f9_36 * RHS9;
+ const double f10 = 1.0 / m_A21;
+ const double f10_28 = -f10 * m_A71;
+ m_A73 += m_A22 * f10_28;
+ RHS28 += f10_28 * RHS10;
+ const double f10_33 = -f10 * m_A94;
+ m_A99 += m_A22 * f10_33;
+ RHS33 += f10_33 * RHS10;
+ const double f13 = 1.0 / m_A27;
+ const double f13_26 = -f13 * m_A61;
+ m_A62 += m_A28 * f13_26;
+ RHS26 += f13_26 * RHS13;
+ const double f13_33 = -f13 * m_A95;
+ m_A97 += m_A28 * f13_33;
+ RHS33 += f13_33 * RHS13;
+ const double f14 = 1.0 / m_A29;
+ const double f14_33 = -f14 * m_A96;
+ m_A99 += m_A30 * f14_33;
+ RHS33 += f14_33 * RHS14;
+ const double f15 = 1.0 / m_A31;
+ const double f15_31 = -f15 * m_A82;
+ m_A84 += m_A32 * f15_31;
+ RHS31 += f15_31 * RHS15;
+ const double f16 = 1.0 / m_A33;
+ const double f16_27 = -f16 * m_A65;
+ m_A67 += m_A34 * f16_27;
+ m_A70 += m_A35 * f16_27;
+ RHS27 += f16_27 * RHS16;
+ const double f16_36 = -f16 * m_A114;
+ m_A115 += m_A34 * f16_36;
+ m_A122 += m_A35 * f16_36;
+ RHS36 += f16_36 * RHS16;
+ const double f17 = 1.0 / m_A36;
+ const double f17_29 = -f17 * m_A74;
+ m_A76 += m_A37 * f17_29;
+ RHS29 += f17_29 * RHS17;
+ const double f17_35 = -f17 * m_A108;
+ m_A109 += m_A37 * f17_35;
+ RHS35 += f17_35 * RHS17;
+ const double f18 = 1.0 / m_A38;
+ const double f18_29 = -f18 * m_A75;
+ m_A77 += m_A39 * f18_29;
+ RHS29 += f18_29 * RHS18;
+ const double f18_30 = -f18 * m_A79;
+ m_A81 += m_A39 * f18_30;
+ RHS30 += f18_30 * RHS18;
+ const double f19 = 1.0 / m_A40;
+ const double f19_30 = -f19 * m_A80;
+ m_A81 += m_A41 * f19_30;
+ RHS30 += f19_30 * RHS19;
+ const double f21 = 1.0 / m_A47;
+ const double f21_22 = -f21 * m_A50;
+ m_A51 += m_A48 * f21_22;
+ RHS22 += f21_22 * RHS21;
+ const double f21_32 = -f21 * m_A88;
+ m_A89 += m_A48 * f21_32;
+ RHS32 += f21_32 * RHS21;
+ const double f22 = 1.0 / m_A51;
+ const double f22_32 = -f22 * m_A89;
+ RHS32 += f22_32 * RHS22;
+ const double f23 = 1.0 / m_A54;
+ const double f23_34 = -f23 * m_A103;
+ RHS34 += f23_34 * RHS23;
+ const double f24 = 1.0 / m_A56;
+ const double f24_27 = -f24 * m_A66;
+ m_A68 += m_A57 * f24_27;
+ RHS27 += f24_27 * RHS24;
+ const double f26 = 1.0 / m_A62;
+ const double f26_31 = -f26 * m_A83;
+ m_A84 += m_A63 * f26_31;
+ RHS31 += f26_31 * RHS26;
+ const double f26_33 = -f26 * m_A97;
+ m_A98 += m_A63 * f26_33;
+ RHS33 += f26_33 * RHS26;
+ const double f27 = 1.0 / m_A67;
+ const double f27_32 = -f27 * m_A90;
+ m_A91 += m_A68 * f27_32;
+ m_A92 += m_A69 * f27_32;
+ m_A93 += m_A70 * f27_32;
+ RHS32 += f27_32 * RHS27;
+ const double f27_34 = -f27 * m_A104;
+ m_A105 += m_A68 * f27_34;
+ m_A106 += m_A69 * f27_34;
+ m_A107 += m_A70 * f27_34;
+ RHS34 += f27_34 * RHS27;
+ const double f27_36 = -f27 * m_A115;
+ m_A119 += m_A68 * f27_36;
+ m_A121 += m_A69 * f27_36;
+ m_A122 += m_A70 * f27_36;
+ RHS36 += f27_36 * RHS27;
+ const double f28 = 1.0 / m_A72;
+ const double f28_36 = -f28 * m_A116;
+ m_A120 += m_A73 * f28_36;
+ RHS36 += f28_36 * RHS28;
+ const double f29 = 1.0 / m_A76;
+ const double f29_35 = -f29 * m_A109;
+ m_A110 += m_A77 * f29_35;
+ m_A112 += m_A78 * f29_35;
+ RHS35 += f29_35 * RHS29;
+ const double f29_36 = -f29 * m_A117;
+ m_A118 += m_A77 * f29_36;
+ m_A122 += m_A78 * f29_36;
+ RHS36 += f29_36 * RHS29;
+ const double f30 = 1.0 / m_A81;
+ const double f30_35 = -f30 * m_A110;
+ RHS35 += f30_35 * RHS30;
+ const double f30_36 = -f30 * m_A118;
+ RHS36 += f30_36 * RHS30;
+ const double f31 = 1.0 / m_A84;
+ const double f31_33 = -f31 * m_A98;
+ RHS33 += f31_33 * RHS31;
+ const double f32 = 1.0 / m_A91;
+ const double f32_34 = -f32 * m_A105;
+ m_A106 += m_A92 * f32_34;
+ m_A107 += m_A93 * f32_34;
+ RHS34 += f32_34 * RHS32;
+ const double f32_36 = -f32 * m_A119;
+ m_A121 += m_A92 * f32_36;
+ m_A122 += m_A93 * f32_36;
+ RHS36 += f32_36 * RHS32;
+ const double f33 = 1.0 / m_A99;
+ const double f33_36 = -f33 * m_A120;
+ m_A122 += m_A100 * f33_36;
+ RHS36 += f33_36 * RHS33;
+ const double f34 = 1.0 / m_A106;
+ const double f34_36 = -f34 * m_A121;
+ m_A122 += m_A107 * f34_36;
+ RHS36 += f34_36 * RHS34;
+ V[36] = RHS36 / m_A122;
+ double tmp35 = 0.0;
+ tmp35 += m_A112 * V[36];
+ V[35] = (RHS35 - tmp35) / m_A111;
+ double tmp34 = 0.0;
+ tmp34 += m_A107 * V[36];
+ V[34] = (RHS34 - tmp34) / m_A106;
+ double tmp33 = 0.0;
+ tmp33 += m_A100 * V[36];
+ V[33] = (RHS33 - tmp33) / m_A99;
+ double tmp32 = 0.0;
+ tmp32 += m_A92 * V[34];
+ tmp32 += m_A93 * V[36];
+ V[32] = (RHS32 - tmp32) / m_A91;
+ double tmp31 = 0.0;
+ V[31] = (RHS31 - tmp31) / m_A84;
+ double tmp30 = 0.0;
+ V[30] = (RHS30 - tmp30) / m_A81;
+ double tmp29 = 0.0;
+ tmp29 += m_A77 * V[30];
+ tmp29 += m_A78 * V[36];
+ V[29] = (RHS29 - tmp29) / m_A76;
+ double tmp28 = 0.0;
+ tmp28 += m_A73 * V[33];
+ V[28] = (RHS28 - tmp28) / m_A72;
+ double tmp27 = 0.0;
+ tmp27 += m_A68 * V[32];
+ tmp27 += m_A69 * V[34];
+ tmp27 += m_A70 * V[36];
+ V[27] = (RHS27 - tmp27) / m_A67;
+ double tmp26 = 0.0;
+ tmp26 += m_A63 * V[31];
+ V[26] = (RHS26 - tmp26) / m_A62;
+ double tmp25 = 0.0;
+ tmp25 += m_A60 * V[34];
+ V[25] = (RHS25 - tmp25) / m_A59;
+ double tmp24 = 0.0;
+ tmp24 += m_A57 * V[32];
+ V[24] = (RHS24 - tmp24) / m_A56;
+ double tmp23 = 0.0;
+ V[23] = (RHS23 - tmp23) / m_A54;
+ double tmp22 = 0.0;
+ V[22] = (RHS22 - tmp22) / m_A51;
+ double tmp21 = 0.0;
+ tmp21 += m_A48 * V[22];
+ V[21] = (RHS21 - tmp21) / m_A47;
+ double tmp20 = 0.0;
+ tmp20 += m_A44 * V[25];
+ V[20] = (RHS20 - tmp20) / m_A43;
+ double tmp19 = 0.0;
+ tmp19 += m_A41 * V[30];
+ V[19] = (RHS19 - tmp19) / m_A40;
+ double tmp18 = 0.0;
+ tmp18 += m_A39 * V[30];
+ V[18] = (RHS18 - tmp18) / m_A38;
+ double tmp17 = 0.0;
+ tmp17 += m_A37 * V[29];
+ V[17] = (RHS17 - tmp17) / m_A36;
+ double tmp16 = 0.0;
+ tmp16 += m_A34 * V[27];
+ tmp16 += m_A35 * V[36];
+ V[16] = (RHS16 - tmp16) / m_A33;
+ double tmp15 = 0.0;
+ tmp15 += m_A32 * V[31];
+ V[15] = (RHS15 - tmp15) / m_A31;
+ double tmp14 = 0.0;
+ tmp14 += m_A30 * V[33];
+ V[14] = (RHS14 - tmp14) / m_A29;
+ double tmp13 = 0.0;
+ tmp13 += m_A28 * V[26];
+ V[13] = (RHS13 - tmp13) / m_A27;
+ double tmp12 = 0.0;
+ tmp12 += m_A26 * V[35];
+ V[12] = (RHS12 - tmp12) / m_A25;
+ double tmp11 = 0.0;
+ tmp11 += m_A24 * V[12];
+ V[11] = (RHS11 - tmp11) / m_A23;
+ double tmp10 = 0.0;
+ tmp10 += m_A22 * V[33];
+ V[10] = (RHS10 - tmp10) / m_A21;
+ double tmp9 = 0.0;
+ tmp9 += m_A20 * V[28];
+ V[9] = (RHS9 - tmp9) / m_A19;
+ double tmp8 = 0.0;
+ tmp8 += m_A18 * V[23];
+ V[8] = (RHS8 - tmp8) / m_A17;
+ double tmp7 = 0.0;
+ tmp7 += m_A16 * V[23];
+ V[7] = (RHS7 - tmp7) / m_A15;
+ double tmp6 = 0.0;
+ tmp6 += m_A13 * V[21];
+ tmp6 += m_A14 * V[22];
+ V[6] = (RHS6 - tmp6) / m_A12;
+ double tmp5 = 0.0;
+ tmp5 += m_A11 * V[21];
+ V[5] = (RHS5 - tmp5) / m_A10;
+ double tmp4 = 0.0;
+ tmp4 += m_A9 * V[25];
+ V[4] = (RHS4 - tmp4) / m_A8;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[34];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[24];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[32];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[32];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// sspeedr
static void nl_gcr_13_double_double_3e833834e5ce5aee(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -60774,6 +61788,398 @@ static void nl_gcr_176_double_double_2294220d3c91e762(double * __restrict V, con
V[0] = (RHS0 - tmp0) / m_A0;
}
+// sspeedr,280zzzap
+static void nl_gcr_57_double_double_bb501e6a23177009(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ double m_A12(0.0);
+ double m_A13(0.0);
+ double m_A14(0.0);
+ double m_A15(0.0);
+ double m_A16(0.0);
+ double m_A17(0.0);
+ double m_A18(0.0);
+ double m_A19(0.0);
+ double m_A20(0.0);
+ double m_A21(0.0);
+ double m_A22(0.0);
+ double m_A23(0.0);
+ double m_A24(0.0);
+ double m_A25(0.0);
+ double m_A26(0.0);
+ double m_A27(0.0);
+ double m_A28(0.0);
+ double m_A29(0.0);
+ double m_A30(0.0);
+ double m_A31(0.0);
+ double m_A32(0.0);
+ double m_A33(0.0);
+ double m_A34(0.0);
+ double m_A35(0.0);
+ double m_A36(0.0);
+ double m_A37(0.0);
+ double m_A38(0.0);
+ double m_A39(0.0);
+ double m_A40(0.0);
+ double m_A41(0.0);
+ double m_A42(0.0);
+ double m_A43(0.0);
+ double m_A44(0.0);
+ double m_A45(0.0);
+ double m_A46(0.0);
+ double m_A47(0.0);
+ double m_A48(0.0);
+ double m_A49(0.0);
+ double m_A50(0.0);
+ double m_A51(0.0);
+ double m_A52(0.0);
+ double m_A53(0.0);
+ double m_A54(0.0);
+ double m_A55(0.0);
+ double m_A56(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A0 += gt[2];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 += Idr[2];
+ RHS0 -= go[1] * *cnV[1];
+ RHS0 -= go[2] * *cnV[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A3 += go[3];
+ double RHS1 = Idr[3];
+ RHS1 += Idr[4];
+ RHS1 -= go[4] * *cnV[4];
+ m_A4 += gt[5];
+ m_A4 += gt[6];
+ m_A4 += gt[7];
+ m_A4 += gt[8];
+ m_A4 += gt[9];
+ m_A4 += gt[10];
+ m_A4 += gt[11];
+ m_A5 += go[5];
+ double RHS2 = Idr[5];
+ RHS2 += Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 += Idr[11];
+ RHS2 -= go[6] * *cnV[6];
+ RHS2 -= go[7] * *cnV[7];
+ RHS2 -= go[8] * *cnV[8];
+ RHS2 -= go[9] * *cnV[9];
+ RHS2 -= go[10] * *cnV[10];
+ RHS2 -= go[11] * *cnV[11];
+ m_A6 += gt[12];
+ m_A6 += gt[13];
+ m_A6 += gt[14];
+ m_A7 += go[12];
+ double RHS3 = Idr[12];
+ RHS3 += Idr[13];
+ RHS3 += Idr[14];
+ RHS3 -= go[13] * *cnV[13];
+ RHS3 -= go[14] * *cnV[14];
+ m_A8 += gt[15];
+ m_A8 += gt[16];
+ m_A8 += gt[17];
+ m_A8 += gt[18];
+ m_A8 += gt[19];
+ m_A8 += gt[20];
+ m_A8 += gt[21];
+ m_A9 += go[15];
+ double RHS4 = Idr[15];
+ RHS4 += Idr[16];
+ RHS4 += Idr[17];
+ RHS4 += Idr[18];
+ RHS4 += Idr[19];
+ RHS4 += Idr[20];
+ RHS4 += Idr[21];
+ RHS4 -= go[16] * *cnV[16];
+ RHS4 -= go[17] * *cnV[17];
+ RHS4 -= go[18] * *cnV[18];
+ RHS4 -= go[19] * *cnV[19];
+ RHS4 -= go[20] * *cnV[20];
+ RHS4 -= go[21] * *cnV[21];
+ m_A10 += gt[22];
+ m_A10 += gt[23];
+ m_A11 += go[22];
+ double RHS5 = Idr[22];
+ RHS5 += Idr[23];
+ RHS5 -= go[23] * *cnV[23];
+ m_A12 += gt[24];
+ m_A12 += gt[25];
+ m_A14 += go[24];
+ m_A13 += go[25];
+ double RHS6 = Idr[24];
+ RHS6 += Idr[25];
+ m_A15 += gt[26];
+ m_A15 += gt[27];
+ m_A16 += go[26];
+ double RHS7 = Idr[26];
+ RHS7 += Idr[27];
+ RHS7 -= go[27] * *cnV[27];
+ m_A17 += gt[28];
+ m_A17 += gt[29];
+ m_A18 += go[28];
+ double RHS8 = Idr[28];
+ RHS8 += Idr[29];
+ RHS8 -= go[29] * *cnV[29];
+ m_A20 += gt[30];
+ m_A20 += gt[31];
+ m_A20 += gt[32];
+ m_A20 += gt[33];
+ m_A19 += go[30];
+ double RHS9 = Idr[30];
+ RHS9 += Idr[31];
+ RHS9 += Idr[32];
+ RHS9 += Idr[33];
+ RHS9 -= go[31] * *cnV[31];
+ RHS9 -= go[32] * *cnV[32];
+ RHS9 -= go[33] * *cnV[33];
+ m_A24 += gt[34];
+ m_A24 += gt[35];
+ m_A23 += go[34];
+ m_A22 += go[35];
+ double RHS10 = Idr[34];
+ RHS10 += Idr[35];
+ m_A27 += gt[36];
+ m_A27 += gt[37];
+ m_A27 += gt[38];
+ m_A27 += gt[39];
+ m_A26 += go[36];
+ m_A28 += go[37];
+ double RHS11 = Idr[36];
+ RHS11 += Idr[37];
+ RHS11 += Idr[38];
+ RHS11 += Idr[39];
+ RHS11 -= go[38] * *cnV[38];
+ RHS11 -= go[39] * *cnV[39];
+ m_A31 += gt[40];
+ m_A31 += gt[41];
+ m_A31 += gt[42];
+ m_A31 += gt[43];
+ m_A31 += gt[44];
+ m_A31 += gt[45];
+ m_A29 += go[40];
+ m_A33 += go[41];
+ m_A32 += go[42];
+ double RHS12 = Idr[40];
+ RHS12 += Idr[41];
+ RHS12 += Idr[42];
+ RHS12 += Idr[43];
+ RHS12 += Idr[44];
+ RHS12 += Idr[45];
+ RHS12 -= go[43] * *cnV[43];
+ RHS12 -= go[44] * *cnV[44];
+ RHS12 -= go[45] * *cnV[45];
+ m_A36 += gt[46];
+ m_A36 += gt[47];
+ m_A34 += go[46];
+ double RHS13 = Idr[46];
+ RHS13 += Idr[47];
+ RHS13 -= go[47] * *cnV[47];
+ m_A39 += gt[48];
+ m_A39 += gt[49];
+ m_A39 += gt[50];
+ m_A38 += go[48];
+ m_A37 += go[49];
+ double RHS14 = Idr[48];
+ RHS14 += Idr[49];
+ RHS14 += Idr[50];
+ RHS14 -= go[50] * *cnV[50];
+ m_A41 += gt[51];
+ m_A41 += gt[52];
+ m_A41 += gt[53];
+ m_A41 += gt[54];
+ m_A40 += go[51];
+ m_A42 += go[52];
+ double RHS15 = Idr[51];
+ RHS15 += Idr[52];
+ RHS15 += Idr[53];
+ RHS15 += Idr[54];
+ RHS15 -= go[53] * *cnV[53];
+ RHS15 -= go[54] * *cnV[54];
+ m_A49 += gt[55];
+ m_A49 += gt[56];
+ m_A49 += gt[57];
+ m_A49 += gt[58];
+ m_A49 += gt[59];
+ m_A44 += go[55];
+ m_A47 += go[56];
+ m_A46 += go[57];
+ m_A43 += go[58];
+ m_A45 += go[59];
+ double RHS16 = Idr[55];
+ RHS16 += Idr[56];
+ RHS16 += Idr[57];
+ RHS16 += Idr[58];
+ RHS16 += Idr[59];
+ m_A56 += gt[60];
+ m_A56 += gt[61];
+ m_A56 += gt[62];
+ m_A56 += gt[63];
+ m_A54 += go[60];
+ m_A53 += go[61];
+ m_A51 += go[62];
+ m_A52 += go[63];
+ double RHS17 = Idr[60];
+ RHS17 += Idr[61];
+ RHS17 += Idr[62];
+ RHS17 += Idr[63];
+ const double f0 = 1.0 / m_A0;
+ const double f0_11 = -f0 * m_A26;
+ m_A28 += m_A1 * f0_11;
+ RHS11 += f0_11 * RHS0;
+ const double f0_16 = -f0 * m_A43;
+ m_A49 += m_A1 * f0_16;
+ RHS16 += f0_16 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_16 = -f1 * m_A44;
+ m_A49 += m_A3 * f1_16;
+ RHS16 += f1_16 * RHS1;
+ const double f2 = 1.0 / m_A4;
+ const double f2_12 = -f2 * m_A29;
+ m_A30 += m_A5 * f2_12;
+ RHS12 += f2_12 * RHS2;
+ const double f3 = 1.0 / m_A6;
+ const double f3_15 = -f3 * m_A40;
+ m_A42 += m_A7 * f3_15;
+ RHS15 += f3_15 * RHS3;
+ const double f3_17 = -f3 * m_A51;
+ m_A56 += m_A7 * f3_17;
+ RHS17 += f3_17 * RHS3;
+ const double f4 = 1.0 / m_A8;
+ const double f4_9 = -f4 * m_A19;
+ m_A21 += m_A9 * f4_9;
+ RHS9 += f4_9 * RHS4;
+ const double f5 = 1.0 / m_A10;
+ const double f5_10 = -f5 * m_A22;
+ m_A24 += m_A11 * f5_10;
+ RHS10 += f5_10 * RHS5;
+ const double f5_16 = -f5 * m_A45;
+ m_A46 += m_A11 * f5_16;
+ RHS16 += f5_16 * RHS5;
+ const double f6 = 1.0 / m_A12;
+ const double f6_10 = -f6 * m_A23;
+ m_A24 += m_A13 * f6_10;
+ m_A25 += m_A14 * f6_10;
+ RHS10 += f6_10 * RHS6;
+ const double f6_13 = -f6 * m_A34;
+ m_A35 += m_A13 * f6_13;
+ m_A36 += m_A14 * f6_13;
+ RHS13 += f6_13 * RHS6;
+ const double f7 = 1.0 / m_A15;
+ const double f7_14 = -f7 * m_A37;
+ m_A39 += m_A16 * f7_14;
+ RHS14 += f7_14 * RHS7;
+ const double f7_17 = -f7 * m_A52;
+ m_A54 += m_A16 * f7_17;
+ RHS17 += f7_17 * RHS7;
+ const double f8 = 1.0 / m_A17;
+ const double f8_14 = -f8 * m_A38;
+ m_A39 += m_A18 * f8_14;
+ RHS14 += f8_14 * RHS8;
+ const double f10 = 1.0 / m_A24;
+ const double f10_13 = -f10 * m_A35;
+ m_A36 += m_A25 * f10_13;
+ RHS13 += f10_13 * RHS10;
+ const double f10_16 = -f10 * m_A46;
+ m_A48 += m_A25 * f10_16;
+ RHS16 += f10_16 * RHS10;
+ const double f11 = 1.0 / m_A27;
+ const double f11_12 = -f11 * m_A30;
+ m_A32 += m_A28 * f11_12;
+ RHS12 += f11_12 * RHS11;
+ const double f12 = 1.0 / m_A31;
+ const double f12_16 = -f12 * m_A47;
+ m_A49 += m_A32 * f12_16;
+ m_A50 += m_A33 * f12_16;
+ RHS16 += f12_16 * RHS12;
+ const double f12_17 = -f12 * m_A53;
+ m_A55 += m_A32 * f12_17;
+ m_A56 += m_A33 * f12_17;
+ RHS17 += f12_17 * RHS12;
+ const double f13 = 1.0 / m_A36;
+ const double f13_16 = -f13 * m_A48;
+ RHS16 += f13_16 * RHS13;
+ const double f14 = 1.0 / m_A39;
+ const double f14_17 = -f14 * m_A54;
+ RHS17 += f14_17 * RHS14;
+ const double f16 = 1.0 / m_A49;
+ const double f16_17 = -f16 * m_A55;
+ m_A56 += m_A50 * f16_17;
+ RHS17 += f16_17 * RHS16;
+ V[17] = RHS17 / m_A56;
+ double tmp16 = 0.0;
+ tmp16 += m_A50 * V[17];
+ V[16] = (RHS16 - tmp16) / m_A49;
+ double tmp15 = 0.0;
+ tmp15 += m_A42 * V[17];
+ V[15] = (RHS15 - tmp15) / m_A41;
+ double tmp14 = 0.0;
+ V[14] = (RHS14 - tmp14) / m_A39;
+ double tmp13 = 0.0;
+ V[13] = (RHS13 - tmp13) / m_A36;
+ double tmp12 = 0.0;
+ tmp12 += m_A32 * V[16];
+ tmp12 += m_A33 * V[17];
+ V[12] = (RHS12 - tmp12) / m_A31;
+ double tmp11 = 0.0;
+ tmp11 += m_A28 * V[16];
+ V[11] = (RHS11 - tmp11) / m_A27;
+ double tmp10 = 0.0;
+ tmp10 += m_A25 * V[13];
+ V[10] = (RHS10 - tmp10) / m_A24;
+ double tmp9 = 0.0;
+ tmp9 += m_A21 * V[15];
+ V[9] = (RHS9 - tmp9) / m_A20;
+ double tmp8 = 0.0;
+ tmp8 += m_A18 * V[14];
+ V[8] = (RHS8 - tmp8) / m_A17;
+ double tmp7 = 0.0;
+ tmp7 += m_A16 * V[14];
+ V[7] = (RHS7 - tmp7) / m_A15;
+ double tmp6 = 0.0;
+ tmp6 += m_A13 * V[10];
+ tmp6 += m_A14 * V[13];
+ V[6] = (RHS6 - tmp6) / m_A12;
+ double tmp5 = 0.0;
+ tmp5 += m_A11 * V[10];
+ V[5] = (RHS5 - tmp5) / m_A10;
+ double tmp4 = 0.0;
+ tmp4 += m_A9 * V[15];
+ V[4] = (RHS4 - tmp4) / m_A8;
+ double tmp3 = 0.0;
+ tmp3 += m_A7 * V[17];
+ V[3] = (RHS3 - tmp3) / m_A6;
+ double tmp2 = 0.0;
+ tmp2 += m_A5 * V[11];
+ V[2] = (RHS2 - tmp2) / m_A4;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[16];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[16];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// sspeedr
static void nl_gcr_95_double_double_4a8e2b707bbac8a6(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -62238,7 +63644,7 @@ static void nl_gcr_12_double_double_88a8ef5f6bd43d48(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// starcas,wotw,solarq,armora
+// starcas,wotw,armora,solarq
static void nl_gcr_22_double_double_1250f340dea396ae(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
{
@@ -70535,8 +71941,8 @@ static void nl_gcr_20_double_double_c924fe5960b1479e(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
-// stuntcyc
-static void nl_gcr_22_double_double_ca68d70bd8f2f62e(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+// stuntcyc,brdrline
+static void nl_gcr_7_double_double_59cb6bf7cb9d17dc(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
{
@@ -70548,140 +71954,44 @@ static void nl_gcr_22_double_double_ca68d70bd8f2f62e(double * __restrict V, cons
double m_A4(0.0);
double m_A5(0.0);
double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- double m_A12(0.0);
- double m_A13(0.0);
- double m_A14(0.0);
- double m_A15(0.0);
- double m_A16(0.0);
- double m_A17(0.0);
- double m_A18(0.0);
- double m_A19(0.0);
- double m_A20(0.0);
- double m_A21(0.0);
m_A0 += gt[0];
m_A0 += gt[1];
- m_A0 += gt[2];
- m_A0 += gt[3];
- m_A2 += go[0];
- m_A2 += go[1];
- m_A1 += go[2];
+ m_A1 += go[0];
double RHS0 = Idr[0];
RHS0 += Idr[1];
- RHS0 += Idr[2];
- RHS0 += Idr[3];
- RHS0 -= go[3] * *cnV[3];
- m_A3 += gt[4];
- m_A3 += gt[5];
- m_A3 += gt[6];
- m_A3 += gt[7];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A3 += go[2];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 -= go[3] * *cnV[3];
+ m_A6 += gt[4];
+ m_A6 += gt[5];
+ m_A6 += gt[6];
+ m_A6 += gt[7];
m_A5 += go[4];
- m_A5 += go[5];
- m_A4 += go[6];
- double RHS1 = Idr[4];
- RHS1 += Idr[5];
- RHS1 += Idr[6];
- RHS1 += Idr[7];
- RHS1 -= go[7] * *cnV[7];
- m_A6 += gt[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A7 += go[8];
- double RHS2 = Idr[8];
- RHS2 += Idr[9];
- RHS2 += Idr[10];
- RHS2 -= go[9] * *cnV[9];
- RHS2 -= go[10] * *cnV[10];
- m_A10 += gt[11];
- m_A10 += gt[12];
- m_A10 += gt[13];
- m_A12 += go[11];
- m_A9 += go[12];
- m_A8 += go[13];
- double RHS3 = Idr[11];
- RHS3 += Idr[12];
- RHS3 += Idr[13];
- m_A16 += gt[14];
- m_A16 += gt[15];
- m_A16 += gt[16];
- m_A16 += gt[17];
- m_A16 += gt[18];
- m_A17 += go[14];
- m_A14 += go[15];
- m_A14 += go[16];
- m_A13 += go[17];
- m_A13 += go[18];
- double RHS4 = Idr[14];
- RHS4 += Idr[15];
- RHS4 += Idr[16];
- RHS4 += Idr[17];
- RHS4 += Idr[18];
- m_A21 += gt[19];
- m_A21 += gt[20];
- m_A21 += gt[21];
- m_A18 += go[19];
- m_A20 += go[20];
- m_A19 += go[21];
- double RHS5 = Idr[19];
- RHS5 += Idr[20];
- RHS5 += Idr[21];
+ m_A4 += go[5];
+ double RHS2 = Idr[4];
+ RHS2 += Idr[5];
+ RHS2 += Idr[6];
+ RHS2 += Idr[7];
+ RHS2 -= go[6] * *cnV[6];
+ RHS2 -= go[7] * *cnV[7];
const double f0 = 1.0 / m_A0;
- const double f0_3 = -f0 * m_A8;
- m_A10 += m_A1 * f0_3;
- m_A11 += m_A2 * f0_3;
- RHS3 += f0_3 * RHS0;
- const double f0_4 = -f0 * m_A13;
- m_A15 += m_A1 * f0_4;
- m_A16 += m_A2 * f0_4;
- RHS4 += f0_4 * RHS0;
- const double f1 = 1.0 / m_A3;
- const double f1_3 = -f1 * m_A9;
- m_A10 += m_A4 * f1_3;
- m_A11 += m_A5 * f1_3;
- RHS3 += f1_3 * RHS1;
- const double f1_4 = -f1 * m_A14;
- m_A15 += m_A4 * f1_4;
- m_A16 += m_A5 * f1_4;
- RHS4 += f1_4 * RHS1;
- const double f2 = 1.0 / m_A6;
- const double f2_5 = -f2 * m_A18;
- m_A21 += m_A7 * f2_5;
- RHS5 += f2_5 * RHS2;
- const double f3 = 1.0 / m_A10;
- const double f3_4 = -f3 * m_A15;
- m_A16 += m_A11 * f3_4;
- m_A17 += m_A12 * f3_4;
- RHS4 += f3_4 * RHS3;
- const double f3_5 = -f3 * m_A19;
- m_A20 += m_A11 * f3_5;
- m_A21 += m_A12 * f3_5;
- RHS5 += f3_5 * RHS3;
- const double f4 = 1.0 / m_A16;
- const double f4_5 = -f4 * m_A20;
- m_A21 += m_A17 * f4_5;
- RHS5 += f4_5 * RHS4;
- V[5] = RHS5 / m_A21;
- double tmp4 = 0.0;
- tmp4 += m_A17 * V[5];
- V[4] = (RHS4 - tmp4) / m_A16;
- double tmp3 = 0.0;
- tmp3 += m_A11 * V[4];
- tmp3 += m_A12 * V[5];
- V[3] = (RHS3 - tmp3) / m_A10;
- double tmp2 = 0.0;
- tmp2 += m_A7 * V[5];
- V[2] = (RHS2 - tmp2) / m_A6;
+ const double f0_2 = -f0 * m_A4;
+ m_A6 += m_A1 * f0_2;
+ RHS2 += f0_2 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ V[2] = RHS2 / m_A6;
double tmp1 = 0.0;
- tmp1 += m_A4 * V[3];
- tmp1 += m_A5 * V[4];
- V[1] = (RHS1 - tmp1) / m_A3;
+ tmp1 += m_A3 * V[2];
+ V[1] = (RHS1 - tmp1) / m_A2;
double tmp0 = 0.0;
- tmp0 += m_A1 * V[3];
- tmp0 += m_A2 * V[4];
+ tmp0 += m_A1 * V[2];
V[0] = (RHS0 - tmp0) / m_A0;
}
@@ -71400,105 +72710,6 @@ static void nl_gcr_100_double_double_e02a162cb515a958(double * __restrict V, con
V[0] = (RHS0 - tmp0) / m_A0;
}
-// sundance,warrior
-static void nl_gcr_12_double_double_ad6dba01ff2425c3(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
-
-{
-
- plib::unused_var(cnV);
- double m_A0(0.0);
- double m_A1(0.0);
- double m_A2(0.0);
- double m_A3(0.0);
- double m_A4(0.0);
- double m_A5(0.0);
- double m_A6(0.0);
- double m_A7(0.0);
- double m_A8(0.0);
- double m_A9(0.0);
- double m_A10(0.0);
- double m_A11(0.0);
- m_A0 += gt[0];
- m_A0 += gt[1];
- m_A1 += go[0];
- double RHS0 = Idr[0];
- RHS0 += Idr[1];
- RHS0 -= go[1] * *cnV[1];
- m_A2 += gt[2];
- m_A2 += gt[3];
- m_A2 += gt[4];
- m_A2 += gt[5];
- m_A2 += gt[6];
- m_A4 += go[2];
- m_A3 += go[3];
- m_A3 += go[4];
- double RHS1 = Idr[2];
- RHS1 += Idr[3];
- RHS1 += Idr[4];
- RHS1 += Idr[5];
- RHS1 += Idr[6];
- RHS1 -= go[5] * *cnV[5];
- RHS1 -= go[6] * *cnV[6];
- m_A6 += gt[7];
- m_A6 += gt[8];
- m_A6 += gt[9];
- m_A6 += gt[10];
- m_A6 += gt[11];
- m_A7 += go[7];
- m_A7 += go[8];
- m_A5 += go[9];
- m_A5 += go[10];
- double RHS2 = Idr[7];
- RHS2 += Idr[8];
- RHS2 += Idr[9];
- RHS2 += Idr[10];
- RHS2 += Idr[11];
- RHS2 -= go[11] * *cnV[11];
- m_A11 += gt[12];
- m_A11 += gt[13];
- m_A11 += gt[14];
- m_A11 += gt[15];
- m_A11 += gt[16];
- m_A10 += go[12];
- m_A10 += go[13];
- m_A9 += go[14];
- m_A8 += go[15];
- double RHS3 = Idr[12];
- RHS3 += Idr[13];
- RHS3 += Idr[14];
- RHS3 += Idr[15];
- RHS3 += Idr[16];
- RHS3 -= go[16] * *cnV[16];
- const double f0 = 1.0 / m_A0;
- const double f0_3 = -f0 * m_A8;
- m_A11 += m_A1 * f0_3;
- RHS3 += f0_3 * RHS0;
- const double f1 = 1.0 / m_A2;
- const double f1_2 = -f1 * m_A5;
- m_A6 += m_A3 * f1_2;
- m_A7 += m_A4 * f1_2;
- RHS2 += f1_2 * RHS1;
- const double f1_3 = -f1 * m_A9;
- m_A10 += m_A3 * f1_3;
- m_A11 += m_A4 * f1_3;
- RHS3 += f1_3 * RHS1;
- const double f2 = 1.0 / m_A6;
- const double f2_3 = -f2 * m_A10;
- m_A11 += m_A7 * f2_3;
- RHS3 += f2_3 * RHS2;
- V[3] = RHS3 / m_A11;
- double tmp2 = 0.0;
- tmp2 += m_A7 * V[3];
- V[2] = (RHS2 - tmp2) / m_A6;
- double tmp1 = 0.0;
- tmp1 += m_A3 * V[2];
- tmp1 += m_A4 * V[3];
- V[1] = (RHS1 - tmp1) / m_A2;
- double tmp0 = 0.0;
- tmp0 += m_A1 * V[3];
- V[0] = (RHS0 - tmp0) / m_A0;
-}
-
// sundance
static void nl_gcr_70_double_double_8446e63d7842f6a6(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -77174,6 +78385,102 @@ static void nl_gcr_10_double_double_8003d4625273fa4d(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
+// warrior,ripoff,sundance
+static void nl_gcr_12_double_double_295cf2e2f3d489bf(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A4 += go[2];
+ m_A3 += go[3];
+ m_A3 += go[4];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 -= go[5] * *cnV[5];
+ m_A6 += gt[6];
+ m_A6 += gt[7];
+ m_A6 += gt[8];
+ m_A6 += gt[9];
+ m_A6 += gt[10];
+ m_A7 += go[6];
+ m_A7 += go[7];
+ m_A5 += go[8];
+ m_A5 += go[9];
+ double RHS2 = Idr[6];
+ RHS2 += Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 -= go[10] * *cnV[10];
+ m_A11 += gt[11];
+ m_A11 += gt[12];
+ m_A11 += gt[13];
+ m_A11 += gt[14];
+ m_A11 += gt[15];
+ m_A10 += go[11];
+ m_A10 += go[12];
+ m_A9 += go[13];
+ m_A8 += go[14];
+ double RHS3 = Idr[11];
+ RHS3 += Idr[12];
+ RHS3 += Idr[13];
+ RHS3 += Idr[14];
+ RHS3 += Idr[15];
+ RHS3 -= go[15] * *cnV[15];
+ const double f0 = 1.0 / m_A0;
+ const double f0_3 = -f0 * m_A8;
+ m_A11 += m_A1 * f0_3;
+ RHS3 += f0_3 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ m_A7 += m_A4 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ const double f1_3 = -f1 * m_A9;
+ m_A10 += m_A3 * f1_3;
+ m_A11 += m_A4 * f1_3;
+ RHS3 += f1_3 * RHS1;
+ const double f2 = 1.0 / m_A6;
+ const double f2_3 = -f2 * m_A10;
+ m_A11 += m_A7 * f2_3;
+ RHS3 += f2_3 * RHS2;
+ V[3] = RHS3 / m_A11;
+ double tmp2 = 0.0;
+ tmp2 += m_A7 * V[3];
+ V[2] = (RHS2 - tmp2) / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ tmp1 += m_A4 * V[3];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[3];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// warrior
static void nl_gcr_12_double_double_42a31ce5c187b308(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -77249,6 +78556,105 @@ static void nl_gcr_12_double_double_42a31ce5c187b308(double * __restrict V, cons
V[0] = (RHS0 - tmp0) / m_A0;
}
+// warrior,sundance
+static void nl_gcr_12_double_double_ad6dba01ff2425c3(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
+
+{
+
+ plib::unused_var(cnV);
+ double m_A0(0.0);
+ double m_A1(0.0);
+ double m_A2(0.0);
+ double m_A3(0.0);
+ double m_A4(0.0);
+ double m_A5(0.0);
+ double m_A6(0.0);
+ double m_A7(0.0);
+ double m_A8(0.0);
+ double m_A9(0.0);
+ double m_A10(0.0);
+ double m_A11(0.0);
+ m_A0 += gt[0];
+ m_A0 += gt[1];
+ m_A1 += go[0];
+ double RHS0 = Idr[0];
+ RHS0 += Idr[1];
+ RHS0 -= go[1] * *cnV[1];
+ m_A2 += gt[2];
+ m_A2 += gt[3];
+ m_A2 += gt[4];
+ m_A2 += gt[5];
+ m_A2 += gt[6];
+ m_A4 += go[2];
+ m_A3 += go[3];
+ m_A3 += go[4];
+ double RHS1 = Idr[2];
+ RHS1 += Idr[3];
+ RHS1 += Idr[4];
+ RHS1 += Idr[5];
+ RHS1 += Idr[6];
+ RHS1 -= go[5] * *cnV[5];
+ RHS1 -= go[6] * *cnV[6];
+ m_A6 += gt[7];
+ m_A6 += gt[8];
+ m_A6 += gt[9];
+ m_A6 += gt[10];
+ m_A6 += gt[11];
+ m_A7 += go[7];
+ m_A7 += go[8];
+ m_A5 += go[9];
+ m_A5 += go[10];
+ double RHS2 = Idr[7];
+ RHS2 += Idr[8];
+ RHS2 += Idr[9];
+ RHS2 += Idr[10];
+ RHS2 += Idr[11];
+ RHS2 -= go[11] * *cnV[11];
+ m_A11 += gt[12];
+ m_A11 += gt[13];
+ m_A11 += gt[14];
+ m_A11 += gt[15];
+ m_A11 += gt[16];
+ m_A10 += go[12];
+ m_A10 += go[13];
+ m_A9 += go[14];
+ m_A8 += go[15];
+ double RHS3 = Idr[12];
+ RHS3 += Idr[13];
+ RHS3 += Idr[14];
+ RHS3 += Idr[15];
+ RHS3 += Idr[16];
+ RHS3 -= go[16] * *cnV[16];
+ const double f0 = 1.0 / m_A0;
+ const double f0_3 = -f0 * m_A8;
+ m_A11 += m_A1 * f0_3;
+ RHS3 += f0_3 * RHS0;
+ const double f1 = 1.0 / m_A2;
+ const double f1_2 = -f1 * m_A5;
+ m_A6 += m_A3 * f1_2;
+ m_A7 += m_A4 * f1_2;
+ RHS2 += f1_2 * RHS1;
+ const double f1_3 = -f1 * m_A9;
+ m_A10 += m_A3 * f1_3;
+ m_A11 += m_A4 * f1_3;
+ RHS3 += f1_3 * RHS1;
+ const double f2 = 1.0 / m_A6;
+ const double f2_3 = -f2 * m_A10;
+ m_A11 += m_A7 * f2_3;
+ RHS3 += f2_3 * RHS2;
+ V[3] = RHS3 / m_A11;
+ double tmp2 = 0.0;
+ tmp2 += m_A7 * V[3];
+ V[2] = (RHS2 - tmp2) / m_A6;
+ double tmp1 = 0.0;
+ tmp1 += m_A3 * V[2];
+ tmp1 += m_A4 * V[3];
+ V[1] = (RHS1 - tmp1) / m_A2;
+ double tmp0 = 0.0;
+ tmp0 += m_A1 * V[3];
+ V[0] = (RHS0 - tmp0) / m_A0;
+}
+
// warrior
static void nl_gcr_27_double_double_da598f43329e823(double * __restrict V, const double * __restrict go, const double * __restrict gt, const double * __restrict Idr, const double * const * __restrict cnV)
@@ -81833,16 +83239,8 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
// 1942
{"nl_gcr_90_double_double_ce766957cb26ff3e", reinterpret_cast<void *>(&nl_gcr_90_double_double_ce766957cb26ff3e)}, // NOLINT
-// 280zzzap,sspeedr
- {"nl_gcr_113_double_double_ab9144d965a37e4", reinterpret_cast<void *>(&nl_gcr_113_double_double_ab9144d965a37e4)}, // NOLINT
-// 280zzzap,sspeedr
- {"nl_gcr_122_double_double_42c57d523cac30d0", reinterpret_cast<void *>(&nl_gcr_122_double_double_42c57d523cac30d0)}, // NOLINT
-// 280zzzap,sspeedr
- {"nl_gcr_123_double_double_864a61c57bac9c38", reinterpret_cast<void *>(&nl_gcr_123_double_double_864a61c57bac9c38)}, // NOLINT
// 280zzzap
{"nl_gcr_149_double_double_fc9971724787b82b", reinterpret_cast<void *>(&nl_gcr_149_double_double_fc9971724787b82b)}, // NOLINT
-// 280zzzap,sspeedr
- {"nl_gcr_57_double_double_bb501e6a23177009", reinterpret_cast<void *>(&nl_gcr_57_double_double_bb501e6a23177009)}, // NOLINT
// 280zzzap
{"nl_gcr_95_double_double_24643c159711f292", reinterpret_cast<void *>(&nl_gcr_95_double_double_24643c159711f292)}, // NOLINT
// armora
@@ -81855,8 +83253,6 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_58_double_double_64e460d8f716cd89", reinterpret_cast<void *>(&nl_gcr_58_double_double_64e460d8f716cd89)}, // NOLINT
// armora
{"nl_gcr_67_double_double_ee2cacaa15d32491", reinterpret_cast<void *>(&nl_gcr_67_double_double_ee2cacaa15d32491)}, // NOLINT
-// astrob,rebound
- {"nl_gcr_13_double_double_a41a44bd5c424f88", reinterpret_cast<void *>(&nl_gcr_13_double_double_a41a44bd5c424f88)}, // NOLINT
// astrob
{"nl_gcr_154_double_double_13833bf8c127deaa", reinterpret_cast<void *>(&nl_gcr_154_double_double_13833bf8c127deaa)}, // NOLINT
// astrob
@@ -81925,8 +83321,6 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_75_double_double_75400df5d559a266", reinterpret_cast<void *>(&nl_gcr_75_double_double_75400df5d559a266)}, // NOLINT
// brdrline
{"nl_gcr_77_double_double_437326911721091", reinterpret_cast<void *>(&nl_gcr_77_double_double_437326911721091)}, // NOLINT
-// brdrline,stuntcyc
- {"nl_gcr_7_double_double_59cb6bf7cb9d17dc", reinterpret_cast<void *>(&nl_gcr_7_double_double_59cb6bf7cb9d17dc)}, // NOLINT
// brdrline
{"nl_gcr_83_double_double_f99b1245e708ec85", reinterpret_cast<void *>(&nl_gcr_83_double_double_f99b1245e708ec85)}, // NOLINT
// brdrline
@@ -81965,6 +83359,18 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_16_double_double_8c0f7f2284333de5", reinterpret_cast<void *>(&nl_gcr_16_double_double_8c0f7f2284333de5)}, // NOLINT
// destroyr
{"nl_gcr_399_double_double_4334c95878d1be92", reinterpret_cast<void *>(&nl_gcr_399_double_double_4334c95878d1be92)}, // NOLINT
+// dribling
+ {"nl_gcr_21_double_double_c9b5f1625a51d98f", reinterpret_cast<void *>(&nl_gcr_21_double_double_c9b5f1625a51d98f)}, // NOLINT
+// dribling
+ {"nl_gcr_28_double_double_99f81817ea8bea2d", reinterpret_cast<void *>(&nl_gcr_28_double_double_99f81817ea8bea2d)}, // NOLINT
+// dribling
+ {"nl_gcr_29_double_double_1e732268bc2d78b2", reinterpret_cast<void *>(&nl_gcr_29_double_double_1e732268bc2d78b2)}, // NOLINT
+// dribling
+ {"nl_gcr_54_double_double_a2823a76b83c45a0", reinterpret_cast<void *>(&nl_gcr_54_double_double_a2823a76b83c45a0)}, // NOLINT
+// dribling
+ {"nl_gcr_7_double_double_a1ecff4d37b54b76", reinterpret_cast<void *>(&nl_gcr_7_double_double_a1ecff4d37b54b76)}, // NOLINT
+// dribling
+ {"nl_gcr_95_double_double_a0159c41cfc0b644", reinterpret_cast<void *>(&nl_gcr_95_double_double_a0159c41cfc0b644)}, // NOLINT
// elim,zektor
{"nl_gcr_10_double_double_11c2ae166b240b6e", reinterpret_cast<void *>(&nl_gcr_10_double_double_11c2ae166b240b6e)}, // NOLINT
// elim,zektor
@@ -81989,8 +83395,6 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_36_double_double_e76692c10e79997e", reinterpret_cast<void *>(&nl_gcr_36_double_double_e76692c10e79997e)}, // NOLINT
// elim,zektor
{"nl_gcr_45_double_double_28b736fe552777a9", reinterpret_cast<void *>(&nl_gcr_45_double_double_28b736fe552777a9)}, // NOLINT
-// elim,zektor
- {"nl_gcr_7_double_double_d190a0e3b8e1f4a7", reinterpret_cast<void *>(&nl_gcr_7_double_double_d190a0e3b8e1f4a7)}, // NOLINT
// fireone
{"nl_gcr_128_double_double_7aee4423e3fdbfda", reinterpret_cast<void *>(&nl_gcr_128_double_double_7aee4423e3fdbfda)}, // NOLINT
// fireone
@@ -82009,8 +83413,6 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_73_double_double_643133e86b2b1628", reinterpret_cast<void *>(&nl_gcr_73_double_double_643133e86b2b1628)}, // NOLINT
// fireone
{"nl_gcr_79_double_double_c1d22fe6e895255d", reinterpret_cast<void *>(&nl_gcr_79_double_double_c1d22fe6e895255d)}, // NOLINT
-// fireone,astrob,rebound,speedfrk,cheekyms
- {"nl_gcr_7_double_double_7c86a9bc1c6aef4c", reinterpret_cast<void *>(&nl_gcr_7_double_double_7c86a9bc1c6aef4c)}, // NOLINT
// fireone
{"nl_gcr_7_double_double_e7fb484f621b3ab9", reinterpret_cast<void *>(&nl_gcr_7_double_double_e7fb484f621b3ab9)}, // NOLINT
// fireone
@@ -82043,8 +83445,14 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_10_double_double_934712b55bb3b2b2", reinterpret_cast<void *>(&nl_gcr_10_double_double_934712b55bb3b2b2)}, // NOLINT
// gamemachine
{"nl_gcr_7_double_double_782d79b5cbe953b1", reinterpret_cast<void *>(&nl_gcr_7_double_double_782d79b5cbe953b1)}, // NOLINT
+// gi6809
+ {"nl_gcr_13_double_double_9eda6de0d275a3e5", reinterpret_cast<void *>(&nl_gcr_13_double_double_9eda6de0d275a3e5)}, // NOLINT
+// gi6809
+ {"nl_gcr_7_double_double_8a409a18e77784cb", reinterpret_cast<void *>(&nl_gcr_7_double_double_8a409a18e77784cb)}, // NOLINT
// gtrak10
- {"nl_gcr_43_double_double_4c46fdf7c0037727", reinterpret_cast<void *>(&nl_gcr_43_double_double_4c46fdf7c0037727)}, // NOLINT
+ {"nl_gcr_22_double_double_1f38df4919cdddae", reinterpret_cast<void *>(&nl_gcr_22_double_double_1f38df4919cdddae)}, // NOLINT
+// gtrak10,elim,zektor
+ {"nl_gcr_7_double_double_d190a0e3b8e1f4a7", reinterpret_cast<void *>(&nl_gcr_7_double_double_d190a0e3b8e1f4a7)}, // NOLINT
// gunfight
{"nl_gcr_112_double_double_743595e64cee0a5e", reinterpret_cast<void *>(&nl_gcr_112_double_double_743595e64cee0a5e)}, // NOLINT
// gunfight
@@ -82081,6 +83489,8 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_7_double_double_e51b463cd890ef6d", reinterpret_cast<void *>(&nl_gcr_7_double_double_e51b463cd890ef6d)}, // NOLINT
// popeye
{"nl_gcr_50_double_double_c6f25bb06e161d1c", reinterpret_cast<void *>(&nl_gcr_50_double_double_c6f25bb06e161d1c)}, // NOLINT
+// rebound,astrob
+ {"nl_gcr_13_double_double_a41a44bd5c424f88", reinterpret_cast<void *>(&nl_gcr_13_double_double_a41a44bd5c424f88)}, // NOLINT
// rebound
{"nl_gcr_28_double_double_8bec817b324dcc3", reinterpret_cast<void *>(&nl_gcr_28_double_double_8bec817b324dcc3)}, // NOLINT
// rebound
@@ -82089,8 +83499,6 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_10_double_double_43188bf576854ae0", reinterpret_cast<void *>(&nl_gcr_10_double_double_43188bf576854ae0)}, // NOLINT
// ripoff
{"nl_gcr_11_double_double_aa07266ef5d420d1", reinterpret_cast<void *>(&nl_gcr_11_double_double_aa07266ef5d420d1)}, // NOLINT
-// ripoff,sundance,warrior
- {"nl_gcr_12_double_double_295cf2e2f3d489bf", reinterpret_cast<void *>(&nl_gcr_12_double_double_295cf2e2f3d489bf)}, // NOLINT
// ripoff
{"nl_gcr_16_double_double_698d5dd47fb16d5", reinterpret_cast<void *>(&nl_gcr_16_double_double_698d5dd47fb16d5)}, // NOLINT
// ripoff
@@ -82157,21 +83565,31 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_91_double_double_b7b209d222c0a9a6", reinterpret_cast<void *>(&nl_gcr_91_double_double_b7b209d222c0a9a6)}, // NOLINT
// speedfrk
{"nl_gcr_37_double_double_e4f2ffbf201a3d0c", reinterpret_cast<void *>(&nl_gcr_37_double_double_e4f2ffbf201a3d0c)}, // NOLINT
+// speedfrk,cheekyms,rebound,astrob,fireone
+ {"nl_gcr_7_double_double_7c86a9bc1c6aef4c", reinterpret_cast<void *>(&nl_gcr_7_double_double_7c86a9bc1c6aef4c)}, // NOLINT
// speedfrk
{"nl_gcr_7_double_double_e07b5b086812756c", reinterpret_cast<void *>(&nl_gcr_7_double_double_e07b5b086812756c)}, // NOLINT
// sspeedr
{"nl_gcr_10_double_double_ac1e401ddf971e15", reinterpret_cast<void *>(&nl_gcr_10_double_double_ac1e401ddf971e15)}, // NOLINT
+// sspeedr,280zzzap
+ {"nl_gcr_113_double_double_ab9144d965a37e4", reinterpret_cast<void *>(&nl_gcr_113_double_double_ab9144d965a37e4)}, // NOLINT
+// sspeedr,280zzzap
+ {"nl_gcr_122_double_double_42c57d523cac30d0", reinterpret_cast<void *>(&nl_gcr_122_double_double_42c57d523cac30d0)}, // NOLINT
+// sspeedr,280zzzap
+ {"nl_gcr_123_double_double_864a61c57bac9c38", reinterpret_cast<void *>(&nl_gcr_123_double_double_864a61c57bac9c38)}, // NOLINT
// sspeedr
{"nl_gcr_13_double_double_3e833834e5ce5aee", reinterpret_cast<void *>(&nl_gcr_13_double_double_3e833834e5ce5aee)}, // NOLINT
// sspeedr
{"nl_gcr_176_double_double_2294220d3c91e762", reinterpret_cast<void *>(&nl_gcr_176_double_double_2294220d3c91e762)}, // NOLINT
+// sspeedr,280zzzap
+ {"nl_gcr_57_double_double_bb501e6a23177009", reinterpret_cast<void *>(&nl_gcr_57_double_double_bb501e6a23177009)}, // NOLINT
// sspeedr
{"nl_gcr_95_double_double_4a8e2b707bbac8a6", reinterpret_cast<void *>(&nl_gcr_95_double_double_4a8e2b707bbac8a6)}, // NOLINT
// starcas,wotw
{"nl_gcr_109_double_double_5d550fc7441617a2", reinterpret_cast<void *>(&nl_gcr_109_double_double_5d550fc7441617a2)}, // NOLINT
// starcas,wotw
{"nl_gcr_12_double_double_88a8ef5f6bd43d48", reinterpret_cast<void *>(&nl_gcr_12_double_double_88a8ef5f6bd43d48)}, // NOLINT
-// starcas,wotw,solarq,armora
+// starcas,wotw,armora,solarq
{"nl_gcr_22_double_double_1250f340dea396ae", reinterpret_cast<void *>(&nl_gcr_22_double_double_1250f340dea396ae)}, // NOLINT
// starcas,wotw,boxingb
{"nl_gcr_23_double_double_ea2b6e3a05e6ef0b", reinterpret_cast<void *>(&nl_gcr_23_double_double_ea2b6e3a05e6ef0b)}, // NOLINT
@@ -82215,12 +83633,10 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_10_double_double_85652d3e3ada285a", reinterpret_cast<void *>(&nl_gcr_10_double_double_85652d3e3ada285a)}, // NOLINT
// stuntcyc
{"nl_gcr_20_double_double_c924fe5960b1479e", reinterpret_cast<void *>(&nl_gcr_20_double_double_c924fe5960b1479e)}, // NOLINT
-// stuntcyc
- {"nl_gcr_22_double_double_ca68d70bd8f2f62e", reinterpret_cast<void *>(&nl_gcr_22_double_double_ca68d70bd8f2f62e)}, // NOLINT
+// stuntcyc,brdrline
+ {"nl_gcr_7_double_double_59cb6bf7cb9d17dc", reinterpret_cast<void *>(&nl_gcr_7_double_double_59cb6bf7cb9d17dc)}, // NOLINT
// sundance
{"nl_gcr_100_double_double_e02a162cb515a958", reinterpret_cast<void *>(&nl_gcr_100_double_double_e02a162cb515a958)}, // NOLINT
-// sundance,warrior
- {"nl_gcr_12_double_double_ad6dba01ff2425c3", reinterpret_cast<void *>(&nl_gcr_12_double_double_ad6dba01ff2425c3)}, // NOLINT
// sundance
{"nl_gcr_70_double_double_8446e63d7842f6a6", reinterpret_cast<void *>(&nl_gcr_70_double_double_8446e63d7842f6a6)}, // NOLINT
// sundance
@@ -82253,8 +83669,12 @@ const plib::static_library::symbol nl_static_solver_syms[] = {
{"nl_gcr_7_double_double_74349e9889a2630b", reinterpret_cast<void *>(&nl_gcr_7_double_double_74349e9889a2630b)}, // NOLINT
// warrior
{"nl_gcr_10_double_double_8003d4625273fa4d", reinterpret_cast<void *>(&nl_gcr_10_double_double_8003d4625273fa4d)}, // NOLINT
+// warrior,ripoff,sundance
+ {"nl_gcr_12_double_double_295cf2e2f3d489bf", reinterpret_cast<void *>(&nl_gcr_12_double_double_295cf2e2f3d489bf)}, // NOLINT
// warrior
{"nl_gcr_12_double_double_42a31ce5c187b308", reinterpret_cast<void *>(&nl_gcr_12_double_double_42a31ce5c187b308)}, // NOLINT
+// warrior,sundance
+ {"nl_gcr_12_double_double_ad6dba01ff2425c3", reinterpret_cast<void *>(&nl_gcr_12_double_double_ad6dba01ff2425c3)}, // NOLINT
// warrior
{"nl_gcr_27_double_double_da598f43329e823", reinterpret_cast<void *>(&nl_gcr_27_double_double_da598f43329e823)}, // NOLINT
// warrior
diff --git a/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp b/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp
index 4e668766c04..2a1d844d512 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx_lib.cpp
@@ -1046,7 +1046,7 @@ static NETLIST_START(TTL_7474_DIP)
//- Package: DIP
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
//- FunctionTable:
-//- https://ia800608.us.archive.org/5/items/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
+//- https://archive.org/download/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
//-
//- +---+---++---+----+
//- | D | G || Q | QQ |
@@ -1088,7 +1088,7 @@ static NETLIST_START(TTL_7475_DIP)
//- Package: DIP
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
//- FunctionTable:
-//- https://ia800608.us.archive.org/5/items/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
+//- https://archive.org/download/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
//-
//- +---+---++---+----+
//- | D | G || Q | QQ |
@@ -2831,7 +2831,7 @@ static NETLIST_START(SN74LS629_DIP)
//- Package: DIP
//- NamingConvention: Naming conventions follow National Semiconductor datasheet
//- FunctionTable:
-//- https://ia800608.us.archive.org/5/items/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
+//- https://archive.org/download/bitsavers_nationaldaTTLDatabook_40452765/1976_National_TTL_Databook.pdf
//-
static NETLIST_START(TTL_9310_DIP)
{
diff --git a/src/lib/netlist/nl_create_mame_solvers.sh b/src/lib/netlist/nl_create_mame_solvers.sh
index 25826efaed3..4786e11eaed 100644..100755
--- a/src/lib/netlist/nl_create_mame_solvers.sh
+++ b/src/lib/netlist/nl_create_mame_solvers.sh
@@ -16,7 +16,7 @@ mkdir ${OUTDIR}
#--dir src/lib/netlist/generated/static --static-include
-if ${NLTOOL} --cmd static --output=${GENERATED}.tmp --include=src/mame/audio ${FILES} ; then
+if ${NLTOOL} --cmd static --output=${GENERATED}.tmp --include=src/mame/shared ${FILES} ; then
mv -f ${GENERATED}.tmp ${GENERATED}
echo Created ${GENERATED} file
else
diff --git a/src/lib/netlist/nl_dice_compat.h b/src/lib/netlist/nl_dice_compat.h
index 3088829b5f9..aff1ac4da6f 100644
--- a/src/lib/netlist/nl_dice_compat.h
+++ b/src/lib/netlist/nl_dice_compat.h
@@ -16,7 +16,7 @@ sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/ma
| sed -e 's/) RES(/)\n RES(/g' \
| sed -e 's/) CAP(/)\n CAP(/g' \
| sed -e 's/) NET_C(/)\n NET_C(/g' \
-| sed -e 's/NL_EMPTY//' \
+| sed -e 's/NL_EMPTY//'
*
*/
diff --git a/src/lib/netlist/plib/pexception.cpp b/src/lib/netlist/plib/pexception.cpp
index 168cb172473..b358f3ad6ba 100644
--- a/src/lib/netlist/plib/pexception.cpp
+++ b/src/lib/netlist/plib/pexception.cpp
@@ -8,7 +8,7 @@
#include <cfloat>
#include <iostream>
-#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
+#if (defined(__x86_64__) || defined(__i386__)) && defined(__GLIBC__)
#define HAS_FEENABLE_EXCEPT (1)
#else
#define HAS_FEENABLE_EXCEPT (0)
diff --git a/src/lib/netlist/plib/ppreprocessor.cpp b/src/lib/netlist/plib/ppreprocessor.cpp
index fd545bc7879..0c3858862f6 100644
--- a/src/lib/netlist/plib/ppreprocessor.cpp
+++ b/src/lib/netlist/plib/ppreprocessor.cpp
@@ -146,7 +146,7 @@ namespace plib {
sexpr.next(); \
const auto v2 = prepro_expr(sexpr, (p_prio)); \
val = (val p_op v2); \
- } \
+ }
// Operator precedence see https://en.cppreference.com/w/cpp/language/operator_precedence
diff --git a/src/lib/netlist/plib/ptests.h b/src/lib/netlist/plib/ptests.h
index cc05b120b96..4e65de7f978 100644
--- a/src/lib/netlist/plib/ptests.h
+++ b/src/lib/netlist/plib/ptests.h
@@ -47,7 +47,7 @@
#define PINT_REGISTER(name, desc) \
extern const plib::testing::reg_entry<PINT_TESTNAME(name, desc)> PINT_TESTNAME(name, desc ## _reg); \
- const plib::testing::reg_entry<PINT_TESTNAME(name, desc)> PINT_TESTNAME(name, desc ## _reg)(#name, #desc, PINT_LOCATION()); \
+ const plib::testing::reg_entry<PINT_TESTNAME(name, desc)> PINT_TESTNAME(name, desc ## _reg)(#name, #desc, PINT_LOCATION());
#define PINT_TEST_F(name, desc, base) \
class PINT_TESTNAME(name, desc) : public base \
@@ -296,7 +296,7 @@ namespace plib::testing
static const char * opstr() { return #op ; } \
template <typename T1, typename T2> \
bool operator()(const T1 &v1, const T2 &v2) { return v1 op v2; } \
- }; \
+ };
DEF_COMP(eq, ==)
DEF_COMP(ne, !=)
diff --git a/src/lib/netlist/tests/test_penum.cpp b/src/lib/netlist/tests/test_penum.cpp
index 8e90c8537e1..6347a41d027 100644
--- a/src/lib/netlist/tests/test_penum.cpp
+++ b/src/lib/netlist/tests/test_penum.cpp
@@ -91,7 +91,7 @@ namespace plib
return;
}
}
- constexpr operator const char * () const noexcept { return staticf::m_str[static_cast<std::size_t>(m_v)]; } \
+ constexpr operator const char * () const noexcept { return staticf::m_str[static_cast<std::size_t>(m_v)]; }
constexpr operator E () const noexcept { return m_v; }
protected:
E m_v;
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 8fe3b19eca8..2859034c166 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -340,7 +340,7 @@ void nl_convert_spice_t::convert_block(const str_list &contents)
{
process_line(line);
}
- catch (const plib::pexception &e)
+ catch ([[maybe_unused]] const plib::pexception &e)
{
fprintf(stderr, "Error on line: <%d>\n", linenumber);
throw;
diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp
index 40ce6ebe689..7b5e8d00d87 100644
--- a/src/lib/util/aviio.cpp
+++ b/src/lib/util/aviio.cpp
@@ -48,7 +48,7 @@ static constexpr std::uint64_t FOUR_GB = std::uint64_t(1) << 32;
* @brief A constant that defines maximum sound channels.
*/
-static constexpr unsigned MAX_SOUND_CHANNELS = 2;
+static constexpr unsigned MAX_SOUND_CHANNELS = 16;
/**
* @def SOUND_BUFFER_MSEC
diff --git a/src/lib/util/bitstream.h b/src/lib/util/bitstream.h
index 4f3817afe6f..eb8b2005329 100644
--- a/src/lib/util/bitstream.h
+++ b/src/lib/util/bitstream.h
@@ -40,10 +40,11 @@ public:
private:
// internal state
uint32_t m_buffer; // current bit accumulator
- int m_bits; // number of bits in the accumulator
+ int m_bits; // number of bits in the accumulator
const uint8_t * m_read; // read pointer
uint32_t m_doffset; // byte offset within the data
uint32_t m_dlength; // length of the data
+ int m_dbitoffs; // bit offset within current read pointer
};
@@ -64,7 +65,7 @@ public:
private:
// internal state
uint32_t m_buffer; // current bit accumulator
- int m_bits; // number of bits in the accumulator
+ int m_bits; // number of bits in the accumulator
uint8_t * m_write; // write pointer
uint32_t m_doffset; // byte offset within the data
uint32_t m_dlength; // length of the data
@@ -85,7 +86,8 @@ inline bitstream_in::bitstream_in(const void *src, uint32_t srclength)
m_bits(0),
m_read(reinterpret_cast<const uint8_t *>(src)),
m_doffset(0),
- m_dlength(srclength)
+ m_dlength(srclength),
+ m_dbitoffs(0)
{
}
@@ -103,12 +105,31 @@ inline uint32_t bitstream_in::peek(int numbits)
// fetch data if we need more
if (numbits > m_bits)
{
- while (m_bits <= 24)
+ while (m_bits < 32)
{
+ uint32_t newbits = 0;
+
if (m_doffset < m_dlength)
- m_buffer |= m_read[m_doffset] << (24 - m_bits);
- m_doffset++;
- m_bits += 8;
+ {
+ // adjust current data to discard any previously read partial bits
+ newbits = (m_read[m_doffset] << m_dbitoffs) & 0xff;
+ }
+
+ if (m_bits + 8 > 32)
+ {
+ // take only what can be used to fill out the rest of the buffer
+ m_dbitoffs = 32 - m_bits;
+ newbits >>= 8 - m_dbitoffs;
+ m_buffer |= newbits;
+ m_bits += m_dbitoffs;
+ }
+ else
+ {
+ m_buffer |= newbits << (24 - m_bits);
+ m_bits += 8 - m_dbitoffs;
+ m_dbitoffs = 0;
+ m_doffset++;
+ }
}
}
@@ -154,6 +175,10 @@ inline uint32_t bitstream_in::read_offset() const
result--;
bits -= 8;
}
+
+ if (m_dbitoffs > bits)
+ result++;
+
return result;
}
@@ -169,7 +194,11 @@ inline uint32_t bitstream_in::flush()
m_doffset--;
m_bits -= 8;
}
- m_bits = m_buffer = 0;
+
+ if (m_dbitoffs > m_bits)
+ m_doffset++;
+
+ m_bits = m_buffer = m_dbitoffs = 0;
return m_doffset;
}
@@ -196,8 +225,11 @@ inline bitstream_out::bitstream_out(void *dest, uint32_t destlength)
inline void bitstream_out::write(uint32_t newbits, int numbits)
{
+ newbits <<= 32 - numbits;
+
// flush the buffer if we're going to overflow it
- if (m_bits + numbits > 32)
+ while (m_bits + numbits >= 32 && numbits > 0)
+ {
while (m_bits >= 8)
{
if (m_doffset < m_dlength)
@@ -207,11 +239,19 @@ inline void bitstream_out::write(uint32_t newbits, int numbits)
m_bits -= 8;
}
- // shift the bits to the top
- if (numbits == 0)
- newbits = 0;
- else
- newbits <<= 32 - numbits;
+ // offload more bits if it'll still overflow the buffer
+ if (m_bits + numbits >= 32)
+ {
+ const int rem = std::min(32 - m_bits, numbits);
+ m_buffer |= newbits >> m_bits;
+ m_bits += rem;
+ newbits <<= rem;
+ numbits -= rem;
+ }
+ }
+
+ if (numbits <= 0)
+ return;
// now shift it down to account for the number of bits we already have and OR them in
m_buffer |= newbits >> m_bits;
diff --git a/src/lib/util/cdrom.cpp b/src/lib/util/cdrom.cpp
index 36a51104d3c..ab227dce1eb 100644
--- a/src/lib/util/cdrom.cpp
+++ b/src/lib/util/cdrom.cpp
@@ -21,10 +21,12 @@
#include "corestr.h"
#include "multibyte.h"
#include "osdfile.h"
+#include "path.h"
#include "strformat.h"
#include <cassert>
#include <cstdlib>
+#include <tuple>
/***************************************************************************
@@ -34,7 +36,6 @@
/** @brief The verbose. */
#define VERBOSE (0)
#define EXTRA_VERBOSE (0)
-#if VERBOSE
/**
* @def LOG(x) do
@@ -44,31 +45,7 @@
* @param x The void to process.
*/
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
-
-/**
- * @fn void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
- *
- * @brief Logerrors the given text.
- *
- * @param text The text.
- *
- * @return A CLIB_DECL.
- */
-
-void CLIB_DECL logerror(const char *text, ...) ATTR_PRINTF(1,2);
-#else
-
-/**
- * @def LOG(x);
- *
- * @brief A macro that defines log.
- *
- * @param x The void to process.
- */
-
-#define LOG(x)
-#endif
+#define LOG(x) do { if (VERBOSE) { osd_printf_info x; } } while (0)
@@ -159,7 +136,7 @@ cdrom_file::cdrom_file(std::string_view inputfile)
std::error_condition err = parse_toc(inputfile, cdtoc, cdtrack_info);
if (err)
{
- fprintf(stderr, "Error reading input file: %s\n", err.message().c_str());
+ osd_printf_error("Error reading input file: %s\n", err.message());
throw nullptr;
}
@@ -175,13 +152,13 @@ cdrom_file::cdrom_file(std::string_view inputfile)
std::error_condition const filerr = osd_file::open(cdtrack_info.track[i].fname, OPEN_FLAG_READ, file, length);
if (filerr)
{
- fprintf(stderr, "Unable to open file: %s\n", cdtrack_info.track[i].fname.c_str());
+ osd_printf_error("Unable to open file: %s\n", cdtrack_info.track[i].fname);
throw nullptr;
}
fhandle[i] = util::osd_file_read(std::move(file));
if (!fhandle[i])
{
- fprintf(stderr, "Unable to open file: %s\n", cdtrack_info.track[i].fname.c_str());
+ osd_printf_error("Unable to open file: %s\n", cdtrack_info.track[i].fname);
throw nullptr;
}
}
@@ -204,6 +181,9 @@ cdrom_file::cdrom_file(std::string_view inputfile)
track.logframeofs = track.pregap;
}
+ if ((cdtoc.flags & CD_FLAG_MULTISESSION) && (cdtrack_info.track[i].leadin != -1))
+ logofs += cdtrack_info.track[i].leadin;
+
track.physframeofs = physofs;
track.chdframeofs = 0;
track.logframeofs += logofs;
@@ -215,22 +195,30 @@ cdrom_file::cdrom_file(std::string_view inputfile)
physofs += track.frames;
logofs += track.frames;
+ if ((cdtoc.flags & CD_FLAG_MULTISESSION) && cdtrack_info.track[i].leadout != -1)
+ logofs += cdtrack_info.track[i].leadout;
+
if (EXTRA_VERBOSE)
- printf("Track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d pregap %d pgmode %d presize %d postgap %d logofs %d physofs %d chdofs %d logframes %d\n", i+1,
- track.trktype,
- track.subtype,
- track.datasize,
- track.subsize,
- track.frames,
- track.extraframes,
- track.pregap,
- track.pgtype,
- track.pgdatasize,
- track.postgap,
- track.logframeofs,
- track.physframeofs,
- track.chdframeofs,
- track.logframes);
+ {
+ osd_printf_verbose("session %d track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d pregap %d pgmode %d presize %d postgap %d logofs %d physofs %d chdofs %d logframes %d pad %d\n",
+ track.session + 1,
+ i + 1,
+ track.trktype,
+ track.subtype,
+ track.datasize,
+ track.subsize,
+ track.frames,
+ track.extraframes,
+ track.pregap,
+ track.pgtype,
+ track.pgdatasize,
+ track.postgap,
+ track.logframeofs,
+ track.physframeofs,
+ track.chdframeofs,
+ track.logframes,
+ track.padframes);
+ }
}
// fill out dummy entries for the last track to help our search
@@ -313,21 +301,26 @@ cdrom_file::cdrom_file(chd_file *_chd)
logofs += track.frames;
if (EXTRA_VERBOSE)
- printf("Track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d pregap %d pgmode %d presize %d postgap %d logofs %d physofs %d chdofs %d logframes %d\n", i+1,
- track.trktype,
- track.subtype,
- track.datasize,
- track.subsize,
- track.frames,
- track.extraframes,
- track.pregap,
- track.pgtype,
- track.pgdatasize,
- track.postgap,
- track.logframeofs,
- track.physframeofs,
- track.chdframeofs,
- track.logframes);
+ {
+ osd_printf_verbose("session %d track %02d is format %d subtype %d datasize %d subsize %d frames %d extraframes %d pregap %d pgmode %d presize %d postgap %d logofs %d physofs %d chdofs %d logframes %d pad %d\n",
+ track.session + 1,
+ i + 1,
+ track.trktype,
+ track.subtype,
+ track.datasize,
+ track.subsize,
+ track.frames,
+ track.extraframes,
+ track.pregap,
+ track.pgtype,
+ track.pgdatasize,
+ track.postgap,
+ track.logframeofs,
+ track.physframeofs,
+ track.chdframeofs,
+ track.logframes,
+ track.padframes);
+ }
}
// fill out dummy entries for the last track to help our search
@@ -387,7 +380,7 @@ std::error_condition cdrom_file::read_partial_sector(void *dest, uint32_t lbasec
if ((cdtoc.tracks[tracknum].pgdatasize == 0) && (lbasector < cdtoc.tracks[tracknum].logframeofs))
{
if (EXTRA_VERBOSE)
- printf("PG missing sector: LBA %d, trklog %d\n", lbasector, cdtoc.tracks[tracknum].logframeofs);
+ osd_printf_verbose("PG missing sector: LBA %d, trklog %d\n", lbasector, cdtoc.tracks[tracknum].logframeofs);
memset(dest, 0, length);
return result;
}
@@ -423,13 +416,13 @@ std::error_condition cdrom_file::read_partial_sector(void *dest, uint32_t lbasec
sourcefileoffset += chdsector * bytespersector + startoffs;
if (EXTRA_VERBOSE)
- printf("Reading %u bytes from sector %d from track %d at offset %lu\n", (unsigned)length, chdsector, tracknum + 1, (unsigned long)sourcefileoffset);
+ osd_printf_verbose("Reading %u bytes from sector %d from track %d at offset %lu\n", (unsigned)length, chdsector, tracknum + 1, (unsigned long)sourcefileoffset);
- size_t actual;
result = srcfile.seek(sourcefileoffset, SEEK_SET);
+ size_t actual;
if (!result)
- result = srcfile.read(dest, length, actual);
- // FIXME: if (actual < length) report error
+ std::tie(result, actual) = read(srcfile, dest, length);
+ // FIXME: if (!result && (actual < length)) report error
needswap = cdtrack_info.track[tracknum].swap;
}
@@ -437,9 +430,10 @@ std::error_condition cdrom_file::read_partial_sector(void *dest, uint32_t lbasec
if (needswap)
{
uint8_t *buffer = (uint8_t *)dest - startoffs;
- for (int swapindex = startoffs; swapindex < 2352; swapindex += 2 )
+ for (int swapindex = startoffs; swapindex < 2352; swapindex += 2)
{
- std::swap(buffer[ swapindex ], buffer[ swapindex + 1 ]);
+ using std::swap;
+ swap(buffer[ swapindex ], buffer[ swapindex + 1 ]);
}
}
return result;
@@ -604,6 +598,27 @@ uint32_t cdrom_file::get_track(uint32_t frame) const
return track;
}
+uint32_t cdrom_file::get_track_index(uint32_t frame) const
+{
+ const uint32_t track = get_track(frame);
+ const uint32_t track_start = get_track_start(track);
+ const uint32_t index_offset = frame - track_start;
+ int index = 0;
+
+ for (int i = 0; i < std::size(cdtrack_info.track[track].idx); i++)
+ {
+ if (index_offset >= cdtrack_info.track[track].idx[i])
+ index = i;
+ else
+ break;
+ }
+
+ if (cdtrack_info.track[track].idx[index] == -1)
+ index = 1; // valid index not found, default to index 1
+
+ return index;
+}
+
/***************************************************************************
EXTRA UTILITIES
@@ -682,11 +697,6 @@ void cdrom_file::get_info_from_type_string(const char *typestring, uint32_t *trk
*trktype = CD_TRACK_MODE2_FORM_MIX;
*datasize = 2336;
}
- else if (!strcmp(typestring, "MODE2/2336"))
- {
- *trktype = CD_TRACK_MODE2_FORM_MIX;
- *datasize = 2336;
- }
else if (!strcmp(typestring, "MODE2_RAW"))
{
*trktype = CD_TRACK_MODE2_RAW;
@@ -891,91 +901,78 @@ std::error_condition cdrom_file::parse_metadata(chd_file *chd, toc &toc)
std::string metadata;
std::error_condition err;
- toc.flags = 0;
+ /* clear structures */
+ memset(&toc, 0, sizeof(toc));
+
+ toc.numsessions = 1;
/* start with no tracks */
for (toc.numtrks = 0; toc.numtrks < MAX_TRACKS; toc.numtrks++)
{
- int tracknum = -1, frames = 0, pregap, postgap, padframes;
+ int tracknum, frames, pregap, postgap, padframes;
char type[16], subtype[16], pgtype[16], pgsub[16];
track_info *track;
- pregap = postgap = padframes = 0;
+ tracknum = -1;
+ frames = pregap = postgap = padframes = 0;
+ std::fill(std::begin(type), std::end(type), 0);
+ std::fill(std::begin(subtype), std::end(subtype), 0);
+ std::fill(std::begin(pgtype), std::end(pgtype), 0);
+ std::fill(std::begin(pgsub), std::end(pgsub), 0);
- /* fetch the metadata for this track */
- err = chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc.numtrks, metadata);
- if (!err)
+ // fetch the metadata for this track
+ if (!chd->read_metadata(CDROM_TRACK_METADATA_TAG, toc.numtrks, metadata))
{
- /* parse the metadata */
- type[0] = subtype[0] = 0;
- pgtype[0] = pgsub[0] = 0;
if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames) != 4)
return chd_file::error::INVALID_DATA;
- if (tracknum == 0 || tracknum > MAX_TRACKS)
+ }
+ else if (!chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc.numtrks, metadata))
+ {
+ if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8)
return chd_file::error::INVALID_DATA;
- track = &toc.tracks[tracknum - 1];
}
else
{
- err = chd->read_metadata(CDROM_TRACK_METADATA2_TAG, toc.numtrks, metadata);
+ // fall through to GD-ROM detection
+ err = chd->read_metadata(GDROM_OLD_METADATA_TAG, toc.numtrks, metadata);
if (!err)
- {
- /* parse the metadata */
- type[0] = subtype[0] = 0;
- pregap = postgap = 0;
- if (sscanf(metadata.c_str(), CDROM_TRACK_METADATA2_FORMAT, &tracknum, type, subtype, &frames, &pregap, pgtype, pgsub, &postgap) != 8)
- return chd_file::error::INVALID_DATA;
- if (tracknum == 0 || tracknum > MAX_TRACKS)
- return chd_file::error::INVALID_DATA;
- track = &toc.tracks[tracknum - 1];
- }
+ toc.flags |= CD_FLAG_GDROMLE; // legacy GDROM track was detected
else
- {
- err = chd->read_metadata(GDROM_OLD_METADATA_TAG, toc.numtrks, metadata);
- if (!err)
- /* legacy GDROM track was detected */
- toc.flags |= CD_FLAG_GDROMLE;
- else
- err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc.numtrks, metadata);
+ err = chd->read_metadata(GDROM_TRACK_METADATA_TAG, toc.numtrks, metadata);
- if (!err)
- {
- /* parse the metadata */
- type[0] = subtype[0] = 0;
- pregap = postgap = 0;
- if (sscanf(metadata.c_str(), GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9)
- return chd_file::error::INVALID_DATA;
- if (tracknum == 0 || tracknum > MAX_TRACKS)
- return chd_file::error::INVALID_DATA;
- track = &toc.tracks[tracknum - 1];
- toc.flags |= CD_FLAG_GDROM;
- }
- else
- {
- break;
- }
- }
+ if (err)
+ break;
+
+ if (sscanf(metadata.c_str(), GDROM_TRACK_METADATA_FORMAT, &tracknum, type, subtype, &frames, &padframes, &pregap, pgtype, pgsub, &postgap) != 9)
+ return chd_file::error::INVALID_DATA;
+
+ toc.flags |= CD_FLAG_GDROM;
}
- /* extract the track type and determine the data size */
+ if (tracknum == 0 || tracknum > MAX_TRACKS)
+ return chd_file::error::INVALID_DATA;
+
+ track = &toc.tracks[tracknum - 1];
+
+ // extract the track type and determine the data size
track->trktype = CD_TRACK_MODE1;
track->datasize = 0;
convert_type_string_to_track_info(type, track);
if (track->datasize == 0)
return chd_file::error::INVALID_DATA;
- /* extract the subtype and determine the subcode data size */
+ // extract the subtype and determine the subcode data size
track->subtype = CD_SUB_NONE;
track->subsize = 0;
convert_subtype_string_to_track_info(subtype, track);
- /* set the frames and extra frames data */
+ // set the frames and extra frames data
track->frames = frames;
track->padframes = padframes;
int padded = (frames + TRACK_PADDING - 1) / TRACK_PADDING;
track->extraframes = padded * TRACK_PADDING - frames;
- /* set the pregap info */
+ // set the pregap info
track->pregap = pregap;
track->pgtype = CD_TRACK_MODE1;
track->pgsub = CD_SUB_NONE;
@@ -999,7 +996,7 @@ std::error_condition cdrom_file::parse_metadata(chd_file *chd, toc &toc)
if (toc.numtrks > 0)
return std::error_condition();
- printf("toc.numtrks = %u?!\n", toc.numtrks);
+ osd_printf_info("toc.numtrks = %u?!\n", toc.numtrks);
/* look for old-style metadata */
std::vector<uint8_t> oldmetadata;
@@ -1011,8 +1008,11 @@ std::error_condition cdrom_file::parse_metadata(chd_file *chd, toc &toc)
auto *mrp = reinterpret_cast<uint32_t *>(&oldmetadata[0]);
toc.numtrks = *mrp++;
+ toc.numsessions = 1;
+
for (int i = 0; i < MAX_TRACKS; i++)
{
+ toc.tracks[i].session = 0;
toc.tracks[i].trktype = *mrp++;
toc.tracks[i].subtype = *mrp++;
toc.tracks[i].datasize = *mrp++;
@@ -1070,7 +1070,16 @@ std::error_condition cdrom_file::write_metadata(chd_file *chd, const toc &toc)
for (int i = 0; i < toc.numtrks; i++)
{
std::string metadata;
- if (!(toc.flags & CD_FLAG_GDROM))
+ if (toc.flags & CD_FLAG_GDROM)
+ {
+ metadata = util::string_format(GDROM_TRACK_METADATA_FORMAT, i + 1, get_type_string(toc.tracks[i].trktype),
+ get_subtype_string(toc.tracks[i].subtype), toc.tracks[i].frames, toc.tracks[i].padframes,
+ toc.tracks[i].pregap, get_type_string(toc.tracks[i].pgtype),
+ get_subtype_string(toc.tracks[i].pgsub), toc.tracks[i].postgap);
+
+ err = chd->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata);
+ }
+ else
{
char submode[32];
@@ -1090,15 +1099,6 @@ std::error_condition cdrom_file::write_metadata(chd_file *chd, const toc &toc)
toc.tracks[i].postgap);
err = chd->write_metadata(CDROM_TRACK_METADATA2_TAG, i, metadata);
}
- else
- {
- metadata = util::string_format(GDROM_TRACK_METADATA_FORMAT, i + 1, get_type_string(toc.tracks[i].trktype),
- get_subtype_string(toc.tracks[i].subtype), toc.tracks[i].frames, toc.tracks[i].padframes,
- toc.tracks[i].pregap, get_type_string(toc.tracks[i].pgtype),
- get_subtype_string(toc.tracks[i].pgsub), toc.tracks[i].postgap);
-
- err = chd->write_metadata(GDROM_TRACK_METADATA_TAG, i, metadata);
- }
if (err)
return err;
}
@@ -1440,14 +1440,14 @@ void cdrom_file::ecc_clear(uint8_t *sector)
*
* @brief A macro that defines tokenize.
*
- * @param linebuffer The linebuffer.
- * @param i Zero-based index of the.
- * @param sizeof(linebuffer) The sizeof(linebuffer)
- * @param token The token.
- * @param sizeof(token) The sizeof(token)
+ * @param linebuffer The linebuffer.
+ * @param i Zero-based index of the.
+ * @param std::size(linebuffer) The std::size(linebuffer)
+ * @param token The token.
+ * @param std::size(token) The std::size(token)
*/
-#define TOKENIZE i = tokenize( linebuffer, i, sizeof(linebuffer), token, sizeof(token) );
+#define TOKENIZE i = tokenize( linebuffer, i, std::size(linebuffer), token, std::size(token) );
/***************************************************************************
@@ -1467,9 +1467,12 @@ void cdrom_file::ecc_clear(uint8_t *sector)
std::string cdrom_file::get_file_path(std::string &path)
{
int pos = path.find_last_of('\\');
- if (pos!=-1) {
+ if (pos!=-1)
+ {
path = path.substr(0,pos+1);
- } else {
+ }
+ else
+ {
pos = path.find_last_of('/');
path = path.substr(0,pos+1);
}
@@ -1518,20 +1521,20 @@ uint64_t cdrom_file::get_file_size(std::string_view filename)
* @return An int.
*/
-int cdrom_file::tokenize( const char *linebuffer, int i, int linebuffersize, char *token, int tokensize )
+int cdrom_file::tokenize(const char *linebuffer, int i, int linebuffersize, char *token, int tokensize)
{
int j = 0;
- int singlequote = 0;
- int doublequote = 0;
+ bool singlequote = false;
+ bool doublequote = false;
while ((i < linebuffersize) && isspace((uint8_t)linebuffer[i]))
{
i++;
}
- while ((i < linebuffersize) && (j < tokensize))
+ while ((i < linebuffersize) && (j < tokensize) && (linebuffer[i] != '\0'))
{
- if (!singlequote && linebuffer[i] == '"' )
+ if (!singlequote && linebuffer[i] == '"')
{
doublequote = !doublequote;
}
@@ -1572,19 +1575,19 @@ int cdrom_file::tokenize( const char *linebuffer, int i, int linebuffersize, cha
* @return An int.
*/
-int cdrom_file::msf_to_frames( char *token )
+int cdrom_file::msf_to_frames(const char *token)
{
int m = 0;
int s = 0;
int f = 0;
- if( sscanf( token, "%d:%d:%d", &m, &s, &f ) == 1 )
+ if (sscanf(token, "%d:%d:%d", &m, &s, &f) == 1)
{
f = m;
}
else
{
- /* convert to just frames */
+ // convert to just frames
s += (m * 60);
f += (s * 75);
}
@@ -1624,7 +1627,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
std::error_condition const filerr = osd_file::open(fname, OPEN_FLAG_READ, file, fsize);
if (filerr)
{
- printf("ERROR: could not open (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: could not open (%s)\n", fname);
return 0;
}
@@ -1633,12 +1636,12 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
offset += actual;
if (offset < 4)
{
- printf("ERROR: unexpected RIFF offset %lu (%s)\n", offset, fname.c_str());
+ osd_printf_error("ERROR: unexpected RIFF offset %lu (%s)\n", offset, fname);
return 0;
}
if (memcmp(&buf[0], "RIFF", 4) != 0)
{
- printf("ERROR: could not find RIFF header (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: could not find RIFF header (%s)\n", fname);
return 0;
}
@@ -1647,7 +1650,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
offset += actual;
if (offset < 8)
{
- printf("ERROR: unexpected size offset %lu (%s)\n", offset, fname.c_str());
+ osd_printf_error("ERROR: unexpected size offset %lu (%s)\n", offset, fname);
return 0;
}
filesize = little_endianize_int32(filesize);
@@ -1657,12 +1660,12 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
offset += actual;
if (offset < 12)
{
- printf("ERROR: unexpected WAVE offset %lu (%s)\n", offset, fname.c_str());
+ osd_printf_error("ERROR: unexpected WAVE offset %lu (%s)\n", offset, fname);
return 0;
}
if (memcmp(&buf[0], "WAVE", 4) != 0)
{
- printf("ERROR: could not find WAVE header (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: could not find WAVE header (%s)\n", fname);
return 0;
}
@@ -1681,7 +1684,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
offset += length;
if (offset >= filesize)
{
- printf("ERROR: could not find fmt tag (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: could not find fmt tag (%s)\n", fname);
return 0;
}
}
@@ -1692,7 +1695,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
temp16 = little_endianize_int16(temp16);
if (temp16 != 1)
{
- printf("ERROR: unsupported format %u - only PCM is supported (%s)\n", temp16, fname.c_str());
+ osd_printf_error("ERROR: unsupported format %u - only PCM is supported (%s)\n", temp16, fname);
return 0;
}
@@ -1702,7 +1705,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
temp16 = little_endianize_int16(temp16);
if (temp16 != 2)
{
- printf("ERROR: unsupported number of channels %u - only stereo is supported (%s)\n", temp16, fname.c_str());
+ osd_printf_error("ERROR: unsupported number of channels %u - only stereo is supported (%s)\n", temp16, fname);
return 0;
}
@@ -1712,7 +1715,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
rate = little_endianize_int32(rate);
if (rate != 44100)
{
- printf("ERROR: unsupported samplerate %u - only 44100 is supported (%s)\n", rate, fname.c_str());
+ osd_printf_error("ERROR: unsupported samplerate %u - only 44100 is supported (%s)\n", rate, fname);
return 0;
}
@@ -1726,7 +1729,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
bits = little_endianize_int16(bits);
if (bits != 16)
{
- printf("ERROR: unsupported bits/sample %u - only 16 is supported (%s)\n", bits, fname.c_str());
+ osd_printf_error("ERROR: unsupported bits/sample %u - only 16 is supported (%s)\n", bits, fname);
return 0;
}
@@ -1748,7 +1751,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
offset += length;
if (offset >= filesize)
{
- printf("ERROR: could not find data tag (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: could not find data tag (%s)\n", fname);
return 0;
}
}
@@ -1756,7 +1759,7 @@ uint32_t cdrom_file::parse_wav_sample(std::string_view filename, uint32_t *datao
/* if there was a 0 length data block, we're done */
if (length == 0)
{
- printf("ERROR: empty data block (%s)\n", fname.c_str());
+ osd_printf_error("ERROR: empty data block (%s)\n", fname);
return 0;
}
@@ -1858,13 +1861,15 @@ std::error_condition cdrom_file::parse_nero(std::string_view tocfname, toc &outt
memset(&outtoc, 0, sizeof(outtoc));
outinfo.reset();
+ outtoc.numsessions = 1;
+
// seek to 12 bytes before the end
fseek(infile, -12, SEEK_END);
fread(buffer, 12, 1, infile);
if (memcmp(buffer, "NER5", 4))
{
- printf("ERROR: Not a Nero 5.5 or later image!\n");
+ osd_printf_error("ERROR: Not a Nero 5.5 or later image!\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
}
@@ -1873,7 +1878,7 @@ std::error_condition cdrom_file::parse_nero(std::string_view tocfname, toc &outt
if ((buffer[7] != 0) || (buffer[6] != 0) || (buffer[5] != 0) || (buffer[4] != 0))
{
- printf("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it.");
+ osd_printf_error("ERROR: File size is > 4GB, this version of CHDMAN cannot handle it.");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
}
@@ -1920,8 +1925,7 @@ std::error_condition cdrom_file::parse_nero(std::string_view tocfname, toc &outt
// printf("Track %d: sector size %d mode %x index0 %llx index1 %llx track_end %llx (pregap %d sectors, length %d sectors)\n", track, size, mode, index0, index1, track_end, (uint32_t)(index1-index0)/size, (uint32_t)(track_end-index1)/size);
outinfo.track[track-1].fname.assign(tocfname);
outinfo.track[track-1].offset = offset + (uint32_t)(index1-index0);
- outinfo.track[track-1].idx0offs = 0;
- outinfo.track[track-1].idx1offs = 0;
+ outinfo.track[track-1].idx[0] = outinfo.track[track-1].idx[1] = 0;
switch (mode)
{
@@ -1931,12 +1935,12 @@ std::error_condition cdrom_file::parse_nero(std::string_view tocfname, toc &outt
break;
case 0x0300: // Mode 2 Form 1
- printf("ERROR: Mode 2 Form 1 tracks not supported\n");
+ osd_printf_error("ERROR: Mode 2 Form 1 tracks not supported\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
case 0x0500: // raw data
- printf("ERROR: Raw data tracks not supported\n");
+ osd_printf_error("ERROR: Raw data tracks not supported\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
@@ -1951,22 +1955,22 @@ std::error_condition cdrom_file::parse_nero(std::string_view tocfname, toc &outt
break;
case 0x0f00: // raw data with sub-channel
- printf("ERROR: Raw data tracks with sub-channel not supported\n");
+ osd_printf_error("ERROR: Raw data tracks with sub-channel not supported\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
case 0x1000: // audio with sub-channel
- printf("ERROR: Audio tracks with sub-channel not supported\n");
+ osd_printf_error("ERROR: Audio tracks with sub-channel not supported\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
case 0x1100: // raw Mode 2 Form 1 with sub-channel
- printf("ERROR: Raw Mode 2 Form 1 tracks with sub-channel not supported\n");
+ osd_printf_error("ERROR: Raw Mode 2 Form 1 tracks with sub-channel not supported\n");
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
default:
- printf("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode);
+ osd_printf_error("ERROR: Unknown track type %x, contact MAMEDEV!\n", mode);
fclose(infile);
return chd_file::error::UNSUPPORTED_FORMAT;
}
@@ -2041,31 +2045,38 @@ std::error_condition cdrom_file::parse_iso(std::string_view tocfname, toc &outto
outtoc.numtrks = 1;
+ outtoc.numsessions = 1;
outinfo.track[0].fname = tocfname;
outinfo.track[0].offset = 0;
- outinfo.track[0].idx0offs = 0;
- outinfo.track[0].idx1offs = 0;
+ outinfo.track[0].idx[0] = outinfo.track[0].idx[1] = 0;
- if ((size % 2048)==0 ) {
+ if ((size % 2048) == 0)
+ {
outtoc.tracks[0].trktype = CD_TRACK_MODE1;
outtoc.tracks[0].frames = size / 2048;
outtoc.tracks[0].datasize = 2048;
outinfo.track[0].swap = false;
- } else if ((size % 2336)==0 ) {
+ }
+ else if ((size % 2336) == 0)
+ {
// 2352 byte mode 2
outtoc.tracks[0].trktype = CD_TRACK_MODE2;
outtoc.tracks[0].frames = size / 2336;
outtoc.tracks[0].datasize = 2336;
outinfo.track[0].swap = false;
- } else if ((size % 2352)==0 ) {
+ }
+ else if ((size % 2352) == 0)
+ {
// 2352 byte mode 2 raw
outtoc.tracks[0].trktype = CD_TRACK_MODE2_RAW;
outtoc.tracks[0].frames = size / 2352;
outtoc.tracks[0].datasize = 2352;
outinfo.track[0].swap = false;
- } else {
- printf("ERROR: Unrecognized track type\n");
+ }
+ else
+ {
+ osd_printf_error("ERROR: Unrecognized track type\n");
return chd_file::error::UNSUPPORTED_FORMAT;
}
@@ -2103,7 +2114,9 @@ std::error_condition cdrom_file::parse_iso(std::string_view tocfname, toc &outto
std::error_condition cdrom_file::parse_gdi(std::string_view tocfname, toc &outtoc, track_input_info &outinfo)
{
- int i, numtracks;
+ char token[512];
+ int i = 0;
+ int trackcnt = 0;
std::string path = std::string(tocfname);
@@ -2122,89 +2135,172 @@ std::error_condition cdrom_file::parse_gdi(std::string_view tocfname, toc &outto
outtoc.flags = CD_FLAG_GDROM;
char linebuffer[512];
- fgets(linebuffer,511,infile);
- numtracks=atoi(linebuffer);
+ memset(linebuffer, 0, sizeof(linebuffer));
+
+ if (!fgets(linebuffer,511,infile))
+ {
+ osd_printf_error("GDI doesn't have track count (blank file?)\n");
+ return chd_file::error::INVALID_DATA;
+ }
+
+ i = 0;
+ TOKENIZE
+
+ const int numtracks = atoi(token);
+
+ if (numtracks > 0 && numtracks - 1 > std::size(outinfo.track))
+ {
+ osd_printf_error("GDI expects too many tracks. Expected %d tracks but only up to %zu tracks allowed\n", numtracks, std::size(outinfo.track) + 1);
+ return chd_file::error::INVALID_DATA;
+ }
- for(i=0;i<numtracks;++i)
+ if (numtracks == 0)
{
- char *tok;
- int trknum;
- int trksize,trktype;
- int sz;
+ osd_printf_error("GDI header specifies no tracks\n");
+ return chd_file::error::INVALID_DATA;
+ }
- fgets(linebuffer,511,infile);
+ while (!feof(infile))
+ {
+ int paramcnt = 0;
- tok=strtok(linebuffer," ");
+ if (!fgets(linebuffer,511,infile))
+ break;
- trknum=atoi(tok)-1;
+ i = 0;
+ TOKENIZE
- outinfo.track[trknum].swap=false;
- outinfo.track[trknum].offset=0;
+ // Ignore empty lines so they're not countered toward the total track count
+ if (!token[0])
+ continue;
+
+ paramcnt++;
+ const int trknum = atoi(token) - 1;
+
+ if (trknum < 0 || trknum > std::size(outinfo.track) || trknum + 1 > numtracks)
+ {
+ osd_printf_error("Track %d is out of expected range of 1 to %d\n", trknum + 1, numtracks);
+ return chd_file::error::INVALID_DATA;
+ }
+
+ if (outtoc.tracks[trknum].datasize != 0)
+ osd_printf_warning("Track %d defined multiple times?\n", trknum + 1);
+ else
+ trackcnt++;
+
+ outinfo.track[trknum].swap = false;
+ outinfo.track[trknum].offset = 0;
outtoc.tracks[trknum].datasize = 0;
outtoc.tracks[trknum].subtype = CD_SUB_NONE;
outtoc.tracks[trknum].subsize = 0;
outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
- tok=strtok(nullptr," ");
- outtoc.tracks[trknum].physframeofs=atoi(tok);
+ TOKENIZE
+ if (token[0])
+ paramcnt++;
+ outtoc.tracks[trknum].physframeofs = atoi(token);
- tok=strtok(nullptr," ");
- trktype=atoi(tok);
+ TOKENIZE
+ if (token[0])
+ paramcnt++;
+ const int trktype = atoi(token);
- tok=strtok(nullptr," ");
- trksize=atoi(tok);
+ TOKENIZE
+ if (token[0])
+ paramcnt++;
+ const int trksize = atoi(token);
- if(trktype==4 && trksize==2352)
+ if (trktype == 4 && trksize == 2352)
{
- outtoc.tracks[trknum].trktype=CD_TRACK_MODE1_RAW;
- outtoc.tracks[trknum].datasize=2352;
+ outtoc.tracks[trknum].trktype = CD_TRACK_MODE1_RAW;
+ outtoc.tracks[trknum].datasize = 2352;
}
- if(trktype==4 && trksize==2048)
+ else if (trktype == 4 && trksize == 2048)
{
- outtoc.tracks[trknum].trktype=CD_TRACK_MODE1;
- outtoc.tracks[trknum].datasize=2048;
+ outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
+ outtoc.tracks[trknum].datasize = 2048;
}
- if(trktype==0)
+ else if (trktype == 0)
{
- outtoc.tracks[trknum].trktype=CD_TRACK_AUDIO;
- outtoc.tracks[trknum].datasize=2352;
+ outtoc.tracks[trknum].trktype = CD_TRACK_AUDIO;
+ outtoc.tracks[trknum].datasize = 2352;
outinfo.track[trknum].swap = true;
}
+ else
+ {
+ osd_printf_error("Unknown track type %d and track size %d combination encountered\n", trktype, trksize);
+ return chd_file::error::INVALID_DATA;
+ }
- std::string name;
+ // skip to start of next token
+ int pi = i;
+ while (pi < std::size(linebuffer) && isspace((uint8_t)linebuffer[pi]))
+ pi++;
- tok=strtok(nullptr," ");
- name = tok;
- if (tok[0]=='"') {
- do {
- tok=strtok(nullptr," ");
- if (tok!=nullptr) {
- name += " ";
- name += tok;
- }
- } while(tok!=nullptr && (strrchr(tok,'"')-tok !=(strlen(tok)-1)));
- strdelchr(name,'"');
+ if (linebuffer[pi] == '"' && strchr(linebuffer + pi + 1, '"') == nullptr)
+ {
+ osd_printf_error("Track %d filename does not having closing quotation mark: '%s'\n", trknum + 1, linebuffer + pi);
+ return chd_file::error::INVALID_DATA;
}
- outinfo.track[trknum].fname.assign(path).append(name);
- sz = get_file_size(outinfo.track[trknum].fname);
+ TOKENIZE
+ if (token[0])
+ paramcnt++;
+
+ outinfo.track[trknum].fname.assign(path).append(token);
- outtoc.tracks[trknum].frames = sz/trksize;
+ const uint64_t sz = get_file_size(outinfo.track[trknum].fname);
+ outtoc.tracks[trknum].frames = sz / trksize;
outtoc.tracks[trknum].padframes = 0;
if (trknum != 0)
{
- int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
+ const int dif = outtoc.tracks[trknum].physframeofs - (outtoc.tracks[trknum-1].frames + outtoc.tracks[trknum-1].physframeofs);
outtoc.tracks[trknum-1].frames += dif;
outtoc.tracks[trknum-1].padframes = dif;
}
+
+ TOKENIZE
+ // offset parameter, not used
+ if (token[0])
+ paramcnt++;
+
+ // check if there are any extra parameters that shouldn't be there
+ while (token[0])
+ {
+ TOKENIZE
+ if (token[0])
+ paramcnt++;
+ }
+
+ if (paramcnt != 6)
+ {
+ osd_printf_error("GDI track entry should have 6 parameters, found %d\n", paramcnt);
+ return chd_file::error::INVALID_DATA;
+ }
+ }
+
+ bool missing_tracks = trackcnt != numtracks;
+ for (int i = 0; i < numtracks; i++)
+ {
+ if (outtoc.tracks[i].datasize == 0)
+ {
+ osd_printf_warning("Could not find track %d\n", i + 1);
+ missing_tracks = true;
+ }
+ }
+
+ if (missing_tracks)
+ {
+ osd_printf_error("GDI is missing tracks\n");
+ return chd_file::error::INVALID_DATA;
}
if (EXTRA_VERBOSE)
- for(i=0; i < numtracks; i++)
+ for (int i = 0; i < numtracks; i++)
{
- printf("%s %d %d %d (true %d)\n", outinfo.track[i].fname.c_str(), outtoc.tracks[i].frames, outtoc.tracks[i].padframes, outtoc.tracks[i].physframeofs, outtoc.tracks[i].frames - outtoc.tracks[i].padframes);
+ osd_printf_verbose("'%s' %d %d %d (true %d)\n", outinfo.track[i].fname, outtoc.tracks[i].frames, outtoc.tracks[i].padframes, outtoc.tracks[i].physframeofs, outtoc.tracks[i].frames - outtoc.tracks[i].padframes);
}
/* close the input TOC */
@@ -2212,12 +2308,13 @@ std::error_condition cdrom_file::parse_gdi(std::string_view tocfname, toc &outto
/* store the number of tracks found */
outtoc.numtrks = numtracks;
+ outtoc.numsessions = 1;
return std::error_condition();
}
/*-------------------------------------------------
- parse_cue - parse a CDRWin format CUE file
+ parse_cue - parse a .CUE file
-------------------------------------------------*/
/**
@@ -2230,15 +2327,23 @@ std::error_condition cdrom_file::parse_gdi(std::string_view tocfname, toc &outto
* @param [in,out] outinfo The outinfo.
*
* @return A std::error_condition.
+ *
+ * Redump multi-CUE for Dreamcast GDI:
+ * Dreamcast discs have two images on a single disc. The first image is SINGLE-DENSITY and the second image
+ * is HIGH-DENSITY. The SINGLE-DENSITY area starts 0 LBA and HIGH-DENSITY area starts 45000 LBA.
*/
std::error_condition cdrom_file::parse_cue(std::string_view tocfname, toc &outtoc, track_input_info &outinfo)
{
- int i, trknum;
- static char token[512];
+ int i, trknum, sessionnum, session_pregap;
+ char token[512];
std::string lastfname;
uint32_t wavlen, wavoffs;
std::string path = std::string(tocfname);
+ const bool is_gdrom = is_gdicue(tocfname);
+ enum gdi_area current_area = SINGLE_DENSITY;
+ bool is_multibin = false;
+ int leadin = -1;
FILE *infile = fopen(path.c_str(), "rt");
if (!infile)
@@ -2254,554 +2359,289 @@ std::error_condition cdrom_file::parse_cue(std::string_view tocfname, toc &outto
trknum = -1;
wavoffs = wavlen = 0;
+ sessionnum = 0;
+ session_pregap = 0;
+
+ if (is_gdrom)
+ {
+ outtoc.flags = CD_FLAG_GDROM;
+ }
char linebuffer[512];
+ memset(linebuffer, 0, sizeof(linebuffer));
+
while (!feof(infile))
{
/* get the next line */
- fgets(linebuffer, 511, infile);
+ if (!fgets(linebuffer, 511, infile))
+ break;
- /* if EOF didn't hit, keep going */
- if (!feof(infile))
- {
- i = 0;
+ i = 0;
- TOKENIZE
+ TOKENIZE
+
+ if (!strcmp(token, "REM"))
+ {
+ /* skip to actual data of REM command */
+ while (i < std::size(linebuffer) && isspace((uint8_t)linebuffer[i]))
+ i++;
- if (!strcmp(token, "FILE"))
+ if (!strncmp(linebuffer+i, "SESSION", 7))
{
- /* found the data file for a track */
+ /* IsoBuster extension */
TOKENIZE
- /* keep the filename */
- lastfname.assign(path).append(token);
-
- /* get the file type */
+ /* get the session number */
TOKENIZE
- if (!strcmp(token, "BINARY"))
- {
- outinfo.track[trknum+1].swap = false;
- }
- else if (!strcmp(token, "MOTOROLA"))
- {
- outinfo.track[trknum+1].swap = true;
- }
- else if (!strcmp(token, "WAVE"))
- {
- wavlen = parse_wav_sample(lastfname, &wavoffs);
- if (!wavlen)
- {
- fclose(infile);
- printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str());
- return chd_file::error::INVALID_DATA;
- }
- }
- else
- {
- fclose(infile);
- printf("ERROR: Unhandled track type %s\n", token);
- return chd_file::error::UNSUPPORTED_FORMAT;
- }
+ sessionnum = strtoul(token, nullptr, 10) - 1;
+
+ if (sessionnum >= 1) /* don't consider it a multisession CD unless there's actually more than 1 session */
+ outtoc.flags |= CD_FLAG_MULTISESSION;
}
- else if (!strcmp(token, "TRACK"))
+ else if ((outtoc.flags & CD_FLAG_MULTISESSION) && !strncmp(linebuffer+i, "PREGAP", 6))
{
- /* get the track number */
- TOKENIZE
- trknum = strtoul(token, nullptr, 10) - 1;
+ /*
+ Redump extension? PREGAP associated with the session instead of the track
- /* next token on the line is the track type */
+ DiscImageCreator - Older versions would write a bogus value here (and maybe session lead-in and lead-out).
+ These should be considered bad dumps and will not be supported.
+ */
TOKENIZE
- if (wavlen != 0)
- {
- outtoc.tracks[trknum].trktype = CD_TRACK_AUDIO;
- outtoc.tracks[trknum].frames = wavlen/2352;
- outinfo.track[trknum].offset = wavoffs;
- wavoffs = wavlen = 0;
- }
- else
- {
- outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
- outtoc.tracks[trknum].datasize = 0;
- outinfo.track[trknum].offset = 0;
- }
- outtoc.tracks[trknum].subtype = CD_SUB_NONE;
- outtoc.tracks[trknum].subsize = 0;
- outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
- outtoc.tracks[trknum].pregap = 0;
- outtoc.tracks[trknum].padframes = 0;
- outinfo.track[trknum].idx0offs = -1;
- outinfo.track[trknum].idx1offs = 0;
-
- outinfo.track[trknum].fname.assign(lastfname); // default filename to the last one
-
-// printf("trk %d: fname %s offset %d\n", trknum, outinfo.track[trknum].fname.c_str(), outinfo.track[trknum].offset);
-
- convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
- if (outtoc.tracks[trknum].datasize == 0)
- {
- fclose(infile);
- printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return chd_file::error::UNSUPPORTED_FORMAT;
- }
-
- /* next (optional) token on the line is the subcode type */
+ /* get pregap time */
TOKENIZE
-
- convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]);
+ session_pregap = msf_to_frames(token);
}
- else if (!strcmp(token, "INDEX")) /* only in bin/cue files */
+ else if (!strncmp(linebuffer+i, "LEAD-OUT", 8))
{
- int idx, frames;
+ /*
+ IsoBuster and ImgBurn (single bin file) - Lead-out time is the start of the lead-out
+ lead-out time - MSF of last track of session = size of last track
- /* get index number */
+ Redump and DiscImageCreator (multiple bins) - Lead-out time is the duration of just the lead-out
+ */
TOKENIZE
- idx = strtoul(token, nullptr, 10);
- /* get index */
+ /* get lead-out time */
TOKENIZE
- frames = msf_to_frames( token );
-
- if (idx == 0)
- {
- outinfo.track[trknum].idx0offs = frames;
- }
- else if (idx == 1)
- {
- outinfo.track[trknum].idx1offs = frames;
- if ((outtoc.tracks[trknum].pregap == 0) && (outinfo.track[trknum].idx0offs != -1))
- {
- outtoc.tracks[trknum].pregap = frames - outinfo.track[trknum].idx0offs;
- outtoc.tracks[trknum].pgtype = outtoc.tracks[trknum].trktype;
- switch (outtoc.tracks[trknum].pgtype)
- {
- case CD_TRACK_MODE1:
- case CD_TRACK_MODE2_FORM1:
- outtoc.tracks[trknum].pgdatasize = 2048;
- break;
-
- case CD_TRACK_MODE1_RAW:
- case CD_TRACK_MODE2_RAW:
- case CD_TRACK_AUDIO:
- outtoc.tracks[trknum].pgdatasize = 2352;
- break;
-
- case CD_TRACK_MODE2:
- case CD_TRACK_MODE2_FORM_MIX:
- outtoc.tracks[trknum].pgdatasize = 2336;
- break;
-
- case CD_TRACK_MODE2_FORM2:
- outtoc.tracks[trknum].pgdatasize = 2324;
- break;
- }
- }
- else // pregap sectors not in file, but we're always using idx0ofs for track length calc now
- {
- outinfo.track[trknum].idx0offs = frames;
- }
- }
+ int leadout_offset = msf_to_frames(token);
+ outinfo.track[trknum].leadout = leadout_offset;
}
- else if (!strcmp(token, "PREGAP"))
+ else if (!strncmp(linebuffer+i, "LEAD-IN", 7))
{
- int frames;
-
- /* get index */
+ /*
+ IsoBuster and ImgBurn (single bin file) - Not used?
+ Redump and DiscImageCreator (multiple bins) - Lead-in time is the duration of just the lead-in
+ */
TOKENIZE
- frames = msf_to_frames( token );
- outtoc.tracks[trknum].pregap = frames;
+ /* get lead-in time */
+ TOKENIZE
+ leadin = msf_to_frames(token);
}
- else if (!strcmp(token, "POSTGAP"))
+ else if (is_gdrom && !strncmp(linebuffer+i, "SINGLE-DENSITY AREA", 19))
{
- int frames;
-
- /* get index */
- TOKENIZE
- frames = msf_to_frames( token );
-
- outtoc.tracks[trknum].postgap = frames;
+ /* single-density area starts LBA = 0 */
+ current_area = SINGLE_DENSITY;
+ }
+ else if (is_gdrom && !strncmp(linebuffer+i, "HIGH-DENSITY AREA", 17))
+ {
+ /* high-density area starts LBA = 45000 */
+ current_area = HIGH_DENSITY;
}
}
- }
-
- /* close the input CUE */
- fclose(infile);
-
- /* store the number of tracks found */
- outtoc.numtrks = trknum + 1;
-
- /* now go over the files again and set the lengths */
- for (trknum = 0; trknum < outtoc.numtrks; trknum++)
- {
- uint64_t tlen = 0;
-
- // this is true for cue/bin and cue/iso, and we need it for cue/wav since .WAV is little-endian
- if (outtoc.tracks[trknum].trktype == CD_TRACK_AUDIO)
+ else if (!strcmp(token, "FILE"))
{
- outinfo.track[trknum].swap = true;
- }
+ /* found the data file for a track */
+ TOKENIZE
- // don't do this for .WAV tracks, we already have their length and offset filled out
- if (outinfo.track[trknum].offset == 0)
- {
- // is this the last track?
- if (trknum == (outtoc.numtrks-1))
+ /* keep the filename */
+ if (!is_multibin)
{
- /* if we have the same filename as the last track, do it that way */
- if (trknum != 0 && (outinfo.track[trknum].fname.compare(outinfo.track[trknum-1].fname)==0))
- {
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
- {
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return std::errc::no_such_file_or_directory;
- }
- outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
- outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- }
- else /* data files are different */
- {
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
- {
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return std::errc::no_such_file_or_directory;
- }
- tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outtoc.tracks[trknum].frames = tlen;
- outinfo.track[trknum].offset = 0;
- }
+ std::string prevfname(std::move(lastfname));
+ lastfname.assign(path).append(token);
+ is_multibin = !prevfname.empty() && lastfname != prevfname;
}
else
{
- /* if we have the same filename as the next track, do it that way */
- if (outinfo.track[trknum].fname.compare(outinfo.track[trknum+1].fname)==0)
- {
- outtoc.tracks[trknum].frames = outinfo.track[trknum+1].idx0offs - outinfo.track[trknum].idx0offs;
+ lastfname.assign(path).append(token);
+ }
- if (trknum == 0) // track 0 offset is 0
- {
- outinfo.track[trknum].offset = 0;
- }
- else
- {
- outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
- }
+ /* get the file type */
+ TOKENIZE
- if (!outtoc.tracks[trknum].frames)
- {
- printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
- return chd_file::error::INVALID_DATA;
- }
- }
- else /* data files are different */
+ if (!strcmp(token, "BINARY"))
+ {
+ outinfo.track[trknum+1].swap = false;
+ }
+ else if (!strcmp(token, "MOTOROLA"))
+ {
+ outinfo.track[trknum+1].swap = true;
+ }
+ else if (!strcmp(token, "WAVE"))
+ {
+ wavlen = parse_wav_sample(lastfname, &wavoffs);
+ if (!wavlen)
{
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
- {
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str());
- return std::errc::no_such_file_or_directory;
- }
- tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outtoc.tracks[trknum].frames = tlen;
- outinfo.track[trknum].offset = 0;
+ fclose(infile);
+ osd_printf_error("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname);
+ return chd_file::error::INVALID_DATA;
}
}
+ else
+ {
+ fclose(infile);
+ osd_printf_error("ERROR: Unhandled track type %s\n", token);
+ return chd_file::error::UNSUPPORTED_FORMAT;
+ }
}
- //printf("trk %d: %d frames @ offset %d\n", trknum+1, outtoc.tracks[trknum].frames, outinfo.track[trknum].offset);
- }
-
- return std::error_condition();
-}
-
-/*---------------------------------------------------------------------------------------
- is_gdicue - determine if CUE contains Redump multi-CUE format for Dreamcast GDI
-----------------------------------------------------------------------------------------*/
-
-/**
- * Dreamcast GDI has two images on one disc, SINGLE-DENSITY and HIGH-DENSITY.
- *
- * Redump stores both images in a single .cue with a REM comment separating the images.
- * This multi-cue format replaces the old flawed .gdi format.
- *
- * http://forum.redump.org/topic/19969/done-sega-dreamcast-multicue-gdi/
- *
- * This function looks for strings "REM SINGLE-DENSITY AREA" & "REM HIGH-DENSITY AREA"
- * indicating the Redump multi-cue format and therefore a Dreamcast GDI disc.
- */
-
-bool cdrom_file::is_gdicue(std::string_view tocfname)
-{
- bool has_rem_singledensity = false;
- bool has_rem_highdensity = false;
- std::string path = std::string(tocfname);
-
- FILE *infile = fopen(path.c_str(), "rt");
- if (!infile)
- {
- return false;
- }
-
- path = get_file_path(path);
-
- char linebuffer[512];
- while (!feof(infile))
- {
- fgets(linebuffer, 511, infile);
-
- /* if EOF didn't hit, keep going */
- if (!feof(infile))
+ else if (!strcmp(token, "TRACK"))
{
- has_rem_singledensity = has_rem_singledensity || !strncmp(linebuffer, "REM SINGLE-DENSITY AREA", 23);
- has_rem_highdensity = has_rem_highdensity || !strncmp(linebuffer, "REM HIGH-DENSITY AREA", 21);
- }
- }
-
- fclose(infile);
-
- return has_rem_singledensity && has_rem_highdensity;
-}
-
-/*-----------------------------------------------------------------
- parse_gdicue - parse a Redump multi-CUE for Dreamcast GDI
-------------------------------------------------------------------*/
-
-/**
- * @fn std::error_condition parse_gdicue(std::string_view tocfname, toc &outtoc, track_input_info &outinfo)
- *
- * @brief Chdcd parse cue.
- *
- * @param tocfname The tocfname.
- * @param [in,out] outtoc The outtoc.
- * @param [in,out] outinfo The outinfo.
- *
- * @return A std::error_condition.
- *
- * Dreamcast discs have two images on a single disc. The first image is SINGLE-DENSITY and the second image
- * is HIGH-DENSITY. The SINGLE-DENSITY area starts 0 LBA and HIGH-DENSITY area starts 45000 LBA.
- *
- * There are three Dreamcast disc patterns.
- *
- * Pattern I - (SD) DATA + AUDIO, (HD) DATA
- * Pattern II - (SD) DATA + AUDIO, (HD) DATA + ... + AUDIO
- * Pattern III - (SD) DATA + AUDIO, (HD) DATA + ... + DATA
- *
- * TOSEC layout is preferred and this code adjusts the TOC and INFO generated by a Redump .cue to match the
- * layout from a TOSEC .gdi.
- */
-
-std::error_condition cdrom_file::parse_gdicue(std::string_view tocfname, toc &outtoc, track_input_info &outinfo)
-{
- int i, trknum;
- static char token[512];
- std::string lastfname;
- uint32_t wavlen, wavoffs;
- std::string path = std::string(tocfname);
- enum gdi_area current_area = SINGLE_DENSITY;
- enum gdi_pattern disc_pattern = TYPE_UNKNOWN;
-
- FILE *infile = fopen(path.c_str(), "rt");
- if (!infile)
- {
- return std::error_condition(errno, std::generic_category());
- }
-
- path = get_file_path(path);
-
- /* clear structures */
- memset(&outtoc, 0, sizeof(outtoc));
- outinfo.reset();
-
- trknum = -1;
- wavoffs = wavlen = 0;
-
- outtoc.flags = CD_FLAG_GDROM;
+ /* get the track number */
+ TOKENIZE
+ trknum = strtoul(token, nullptr, 10) - 1;
- char linebuffer[512];
- while (!feof(infile))
- {
- /* get the next line */
- fgets(linebuffer, 511, infile);
+ /* next token on the line is the track type */
+ TOKENIZE
- /* if EOF didn't hit, keep going */
- if (!feof(infile))
- {
- /* single-density area starts LBA = 0 */
- if (!strncmp(linebuffer, "REM SINGLE-DENSITY AREA", 23))
+ outtoc.tracks[trknum].session = sessionnum;
+ outtoc.tracks[trknum].subtype = CD_SUB_NONE;
+ outtoc.tracks[trknum].subsize = 0;
+ outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
+ outtoc.tracks[trknum].pregap = 0;
+ outtoc.tracks[trknum].padframes = 0;
+ outtoc.tracks[trknum].datasize = 0;
+ outtoc.tracks[trknum].multicuearea = is_gdrom ? current_area : 0;
+ outinfo.track[trknum].offset = 0;
+ std::fill(std::begin(outinfo.track[trknum].idx), std::end(outinfo.track[trknum].idx), -1);
+
+ outinfo.track[trknum].leadout = -1;
+ outinfo.track[trknum].leadin = leadin; /* use previously saved lead-in value */
+ leadin = -1;
+
+ if (session_pregap != 0)
{
- current_area = SINGLE_DENSITY;
- continue;
+ /*
+ associated the pregap from the session transition with the lead-in to simplify things for now.
+ setting it as the proper pregap for the track causes logframeofs of the last dummy entry in the TOC
+ to become 2s later than it should. this might be an issue with how pgdatasize = 0 pregaps are handled.
+ */
+ if (outinfo.track[trknum].leadin == -1)
+ outinfo.track[trknum].leadin = session_pregap;
+ else
+ outinfo.track[trknum].leadin += session_pregap;
+ session_pregap = 0;
}
- /* high-density area starts LBA = 45000 */
- if (!strncmp(linebuffer, "REM HIGH-DENSITY AREA", 21))
+ if (wavlen != 0)
{
- current_area = HIGH_DENSITY;
- continue;
+ outtoc.tracks[trknum].frames = wavlen/2352;
+ outinfo.track[trknum].offset = wavoffs;
+ wavoffs = wavlen = 0;
}
- i = 0;
-
- TOKENIZE
+ outinfo.track[trknum].fname.assign(lastfname); /* default filename to the last one */
- if (!strcmp(token, "FILE"))
+ if (EXTRA_VERBOSE)
{
- /* found the data file for a track */
- TOKENIZE
-
- /* keep the filename */
- lastfname.assign(path).append(token);
-
- /* get the file type */
- TOKENIZE
-
- if (!strcmp(token, "BINARY"))
- {
- outinfo.track[trknum+1].swap = false;
- }
- else if (!strcmp(token, "MOTOROLA"))
+ if (is_gdrom)
{
- outinfo.track[trknum+1].swap = true;
- }
- else if (!strcmp(token, "WAVE"))
- {
- wavlen = parse_wav_sample(lastfname, &wavoffs);
- if (!wavlen)
- {
- fclose(infile);
- printf("ERROR: couldn't read [%s] or not a valid .WAV\n", lastfname.c_str());
- return chd_file::error::INVALID_DATA;
- }
+ osd_printf_verbose("trk %d: fname %s offset %d area %d\n", trknum, outinfo.track[trknum].fname, outinfo.track[trknum].offset, outtoc.tracks[trknum].multicuearea);
}
else
{
- fclose(infile);
- printf("ERROR: Unhandled track type %s\n", token);
- return chd_file::error::UNSUPPORTED_FORMAT;
+ osd_printf_verbose("trk %d: fname %s offset %d\n", trknum, outinfo.track[trknum].fname, outinfo.track[trknum].offset);
}
}
- else if (!strcmp(token, "TRACK"))
+
+ convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
+ if (outtoc.tracks[trknum].datasize == 0)
{
- /* get the track number */
- TOKENIZE
- trknum = strtoul(token, nullptr, 10) - 1;
+ fclose(infile);
+ osd_printf_error("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
+ return chd_file::error::UNSUPPORTED_FORMAT;
+ }
- /* next token on the line is the track type */
- TOKENIZE
+ /* next (optional) token on the line is the subcode type */
+ TOKENIZE
- if (wavlen != 0)
- {
- outtoc.tracks[trknum].trktype = CD_TRACK_AUDIO;
- outtoc.tracks[trknum].frames = wavlen/2352;
- outinfo.track[trknum].offset = wavoffs;
- wavoffs = wavlen = 0;
- }
- else
- {
- outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
- outtoc.tracks[trknum].datasize = 0;
- outinfo.track[trknum].offset = 0;
- }
- outtoc.tracks[trknum].subtype = CD_SUB_NONE;
- outtoc.tracks[trknum].subsize = 0;
- outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
- outtoc.tracks[trknum].pregap = 0;
- outtoc.tracks[trknum].padframes = 0;
- outtoc.tracks[trknum].multicuearea = current_area;
- outinfo.track[trknum].idx0offs = -1;
- outinfo.track[trknum].idx1offs = 0;
-
- outinfo.track[trknum].fname.assign(lastfname); // default filename to the last one
-
- if (EXTRA_VERBOSE)
- printf("trk %d: fname %s offset %d area %d\n", trknum, outinfo.track[trknum].fname.c_str(), outinfo.track[trknum].offset, outtoc.tracks[trknum].multicuearea);
-
- convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
- if (outtoc.tracks[trknum].datasize == 0)
- {
- fclose(infile);
- printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return chd_file::error::UNSUPPORTED_FORMAT;
- }
+ convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]);
+ }
+ else if (!strcmp(token, "INDEX"))
+ {
+ int idx, frames;
- /* next (optional) token on the line is the subcode type */
- TOKENIZE
+ /* get index number */
+ TOKENIZE
+ idx = strtoul(token, nullptr, 10);
- convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]);
- }
- else if (!strcmp(token, "INDEX")) /* only in bin/cue files */
- {
- int idx, frames;
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames(token);
- /* get index number */
- TOKENIZE
- idx = strtoul(token, nullptr, 10);
+ if (idx < 0 || idx > MAX_INDEX)
+ {
+ osd_printf_error("ERROR: encountered invalid index %d\n", idx);
+ return chd_file::error::INVALID_DATA;
+ }
- /* get index */
- TOKENIZE
- frames = msf_to_frames( token );
+ outinfo.track[trknum].idx[idx] = frames;
- if (idx == 0)
+ if (idx == 1)
+ {
+ if (outtoc.tracks[trknum].pregap == 0 && outinfo.track[trknum].idx[0] != -1)
{
- outinfo.track[trknum].idx0offs = frames;
+ outtoc.tracks[trknum].pregap = frames - outinfo.track[trknum].idx[0];
+ outtoc.tracks[trknum].pgtype = outtoc.tracks[trknum].trktype;
+ outtoc.tracks[trknum].pgdatasize = outtoc.tracks[trknum].datasize;
}
- else if (idx == 1)
+ else if (outinfo.track[trknum].idx[0] == -1) /* pregap sectors not in file, but we're always using idx 0 for track length calc now */
{
- outinfo.track[trknum].idx1offs = frames;
- if ((outtoc.tracks[trknum].pregap == 0) && (outinfo.track[trknum].idx0offs != -1))
- {
- outtoc.tracks[trknum].pregap = frames - outinfo.track[trknum].idx0offs;
- outtoc.tracks[trknum].pgtype = outtoc.tracks[trknum].trktype;
- switch (outtoc.tracks[trknum].pgtype)
- {
- case CD_TRACK_MODE1:
- case CD_TRACK_MODE2_FORM1:
- outtoc.tracks[trknum].pgdatasize = 2048;
- break;
-
- case CD_TRACK_MODE1_RAW:
- case CD_TRACK_MODE2_RAW:
- case CD_TRACK_AUDIO:
- outtoc.tracks[trknum].pgdatasize = 2352;
- break;
-
- case CD_TRACK_MODE2:
- case CD_TRACK_MODE2_FORM_MIX:
- outtoc.tracks[trknum].pgdatasize = 2336;
- break;
-
- case CD_TRACK_MODE2_FORM2:
- outtoc.tracks[trknum].pgdatasize = 2324;
- break;
- }
- }
- else // pregap sectors not in file, but we're always using idx0ofs for track length calc now
- {
- outinfo.track[trknum].idx0offs = frames;
- }
+ outinfo.track[trknum].idx[0] = frames;
}
}
- else if (!strcmp(token, "PREGAP"))
- {
- int frames;
+ }
+ else if (!strcmp(token, "PREGAP"))
+ {
+ int frames;
- /* get index */
- TOKENIZE
- frames = msf_to_frames( token );
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames(token);
- outtoc.tracks[trknum].pregap = frames;
- }
- else if (!strcmp(token, "POSTGAP"))
+ outtoc.tracks[trknum].pregap = frames;
+ }
+ else if (!strcmp(token, "POSTGAP"))
+ {
+ int frames;
+
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames(token);
+
+ outtoc.tracks[trknum].postgap = frames;
+ }
+ else if (!strcmp(token, "FLAGS"))
+ {
+ outtoc.tracks[trknum].control_flags = 0;
+
+ /* keep looping over remaining tokens in FLAGS line until there's no more to read */
+ while (i < std::size(linebuffer))
{
- int frames;
+ int last_idx = i;
- /* get index */
TOKENIZE
- frames = msf_to_frames( token );
- outtoc.tracks[trknum].postgap = frames;
+ if (i == last_idx)
+ break;
+
+ if (!strcmp(token, "DCP"))
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_DIGITAL_COPY_PERMITTED;
+ else if (!strcmp(token, "4CH"))
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_4CH;
+ else if (!strcmp(token, "PRE"))
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_PREEMPHASIS;
}
}
}
@@ -2811,164 +2651,255 @@ std::error_condition cdrom_file::parse_gdicue(std::string_view tocfname, toc &ou
/* store the number of tracks found */
outtoc.numtrks = trknum + 1;
+ outtoc.numsessions = sessionnum + 1;
/* now go over the files again and set the lengths */
for (trknum = 0; trknum < outtoc.numtrks; trknum++)
{
uint64_t tlen = 0;
- // this is true for cue/bin and cue/iso, and we need it for cue/wav since .WAV is little-endian
+ if (outinfo.track[trknum].idx[1] == -1)
+ {
+ /* index 1 should always be set */
+ osd_printf_error("ERROR: track %d is missing INDEX 01 marker\n", trknum+1);
+ return chd_file::error::INVALID_DATA;
+ }
+
+ /* this is true for cue/bin and cue/iso, and we need it for cue/wav since .WAV is little-endian */
if (outtoc.tracks[trknum].trktype == CD_TRACK_AUDIO)
{
outinfo.track[trknum].swap = true;
}
- // don't do this for .WAV tracks, we already have their length and offset filled out
- if (outinfo.track[trknum].offset == 0)
+ /* don't do this for .WAV tracks, we already have their length and offset filled out */
+ if (outinfo.track[trknum].offset != 0)
+ continue;
+
+ if (trknum+1 >= outtoc.numtrks && trknum > 0 && (outinfo.track[trknum].fname.compare(outinfo.track[trknum-1].fname) == 0))
+ {
+ /* if the last track's filename is the same as the previous track */
+ tlen = get_file_size(outinfo.track[trknum].fname);
+ if (tlen == 0)
+ {
+ osd_printf_error("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname);
+ return std::errc::no_such_file_or_directory;
+ }
+
+ outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
+ outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ }
+ else if (trknum+1 < outtoc.numtrks && outinfo.track[trknum].fname.compare(outinfo.track[trknum+1].fname) == 0)
{
- // is this the last track?
- if (trknum == (outtoc.numtrks-1))
+ /* if the current filename is the same as the next track */
+ outtoc.tracks[trknum].frames = outinfo.track[trknum+1].idx[0] - outinfo.track[trknum].idx[0];
+
+ if (outtoc.tracks[trknum].frames == 0)
{
- /* if we have the same filename as the last track, do it that way */
- if (trknum != 0 && (outinfo.track[trknum].fname.compare(outinfo.track[trknum-1].fname)==0))
+ osd_printf_error("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
+ return chd_file::error::INVALID_DATA;
+ }
+
+ if (trknum > 0)
+ {
+ const uint32_t previous_track_raw_size = outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
+ outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + previous_track_raw_size;
+ }
+ }
+ else if (outtoc.tracks[trknum].frames == 0)
+ {
+ /* if the filenames between tracks are different */
+ tlen = get_file_size(outinfo.track[trknum].fname);
+ if (tlen == 0)
+ {
+ osd_printf_error("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname);
+ return std::errc::no_such_file_or_directory;
+ }
+
+ outtoc.tracks[trknum].frames = tlen / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ outinfo.track[trknum].offset = 0;
+ }
+
+ if (outtoc.flags & CD_FLAG_MULTISESSION)
+ {
+ if (is_multibin)
+ {
+ if (outinfo.track[trknum].leadout == -1 && trknum + 1 < outtoc.numtrks && outtoc.tracks[trknum].session != outtoc.tracks[trknum+1].session)
{
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
- {
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return std::errc::no_such_file_or_directory;
- }
- outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
- outtoc.tracks[trknum].frames = (tlen - outinfo.track[trknum].offset) / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ /* add a standard lead-out to the last track before changing sessions */
+ outinfo.track[trknum].leadout = outtoc.tracks[trknum].session == 0 ? 6750 : 2250; /* first session lead-out (1m30s0f) is longer than the rest (0m30s0f) */
}
- else /* data files are different */
+
+ if (outinfo.track[trknum].leadin == -1 && trknum > 0 && outtoc.tracks[trknum].session != outtoc.tracks[trknum-1].session)
{
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
- {
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum-1].fname.c_str());
- return std::errc::no_such_file_or_directory;
- }
- tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outtoc.tracks[trknum].frames = tlen;
- outinfo.track[trknum].offset = 0;
+ /* add a standard lead-in to the first track of a new session */
+ outinfo.track[trknum].leadin = 4500; /* lead-in (1m0s0f) */
}
}
else
{
- /* if we have the same filename as the next track, do it that way */
- if (outinfo.track[trknum].fname.compare(outinfo.track[trknum+1].fname)==0)
+ if (outinfo.track[trknum].leadout != -1)
{
- outtoc.tracks[trknum].frames = outinfo.track[trknum+1].idx0offs - outinfo.track[trknum].idx0offs;
-
- if (trknum == 0) // track 0 offset is 0
+ /*
+ if a lead-out time is specified in a multisession CD then the size of the previous track needs to be trimmed
+ to use the lead-out time instead of the idx 0 of the next track
+ */
+ const int endframes = outinfo.track[trknum].leadout - outinfo.track[trknum].idx[0];
+ if (outtoc.tracks[trknum].frames >= endframes)
{
- outinfo.track[trknum].offset = 0;
- }
- else
- {
- outinfo.track[trknum].offset = outinfo.track[trknum-1].offset + outtoc.tracks[trknum-1].frames * (outtoc.tracks[trknum-1].datasize + outtoc.tracks[trknum-1].subsize);
- }
+ outtoc.tracks[trknum].frames = endframes; /* trim track length */
- if (!outtoc.tracks[trknum].frames)
- {
- printf("ERROR: unable to determine size of track %d, missing INDEX 01 markers?\n", trknum+1);
- return chd_file::error::INVALID_DATA;
+ if (trknum + 1 < outtoc.numtrks)
+ {
+ /* lead-out value becomes just the duration between the lead-out to the pre-gap of the next track */
+ outinfo.track[trknum].leadout = outinfo.track[trknum+1].idx[0] - outinfo.track[trknum].leadout;
+ }
}
}
- else /* data files are different */
+
+ if (trknum > 0 && outinfo.track[trknum-1].leadout != -1)
{
- tlen = get_file_size(outinfo.track[trknum].fname);
- if (tlen == 0)
+ /*
+ ImgBurn bin/cue have dummy data to pad between the lead-out and the start of the next track.
+ DiscImageCreator img/cue does not have any data between the lead-out and the start of the next track.
+
+ Detecting by extension is an awful way to handle this but there's no other way to determine what format
+ the data will be in since we don't know the exact length of the last track just from the cue.
+ */
+ if (!core_filename_ends_with(outinfo.track[trknum-1].fname, ".img"))
{
- printf("ERROR: couldn't find bin file [%s]\n", outinfo.track[trknum].fname.c_str());
- return std::errc::no_such_file_or_directory;
+ outtoc.tracks[trknum-1].padframes += outinfo.track[trknum-1].leadout;
+ outtoc.tracks[trknum].frames -= outinfo.track[trknum-1].leadout;
+ outinfo.track[trknum].offset += outinfo.track[trknum-1].leadout * (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
}
- tlen /= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outtoc.tracks[trknum].frames = tlen;
- outinfo.track[trknum].offset = 0;
}
}
}
}
- /*
- * Dreamcast patterns are identified by track types and number of tracks
- */
- if (outtoc.numtrks > 4 && outtoc.tracks[outtoc.numtrks-1].pgtype == CD_TRACK_MODE1_RAW)
+ if (is_gdrom)
{
- if (outtoc.tracks[outtoc.numtrks-2].pgtype == CD_TRACK_AUDIO)
- disc_pattern = TYPE_III_SPLIT;
- else
- disc_pattern = TYPE_III;
+ /*
+ * Strip pregaps from Redump tracks and adjust the LBA offset to match TOSEC layout
+ */
+ for (trknum = 1; trknum < outtoc.numtrks; trknum++)
+ {
+ uint32_t this_pregap = outtoc.tracks[trknum].pregap;
+ uint32_t this_offset = this_pregap * (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+
+ outtoc.tracks[trknum-1].frames += this_pregap;
+ outtoc.tracks[trknum-1].splitframes += this_pregap;
+
+ outinfo.track[trknum].offset += this_offset;
+ outtoc.tracks[trknum].frames -= this_pregap;
+ outinfo.track[trknum].idx[1] -= this_pregap;
+
+ outtoc.tracks[trknum].pregap = 0;
+ outtoc.tracks[trknum].pgtype = 0;
+ }
+
+ /*
+ * TOC now matches TOSEC layout, set LBA for every track with HIGH-DENSITY area @ LBA 45000
+ */
+ for (trknum = 1; trknum < outtoc.numtrks; trknum++)
+ {
+ if (outtoc.tracks[trknum].multicuearea == HIGH_DENSITY && outtoc.tracks[trknum-1].multicuearea == SINGLE_DENSITY)
+ {
+ outtoc.tracks[trknum].physframeofs = 45000;
+ int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
+ outtoc.tracks[trknum-1].frames += dif;
+ outtoc.tracks[trknum-1].padframes = dif;
+ }
+ else
+ {
+ outtoc.tracks[trknum].physframeofs = outtoc.tracks[trknum-1].physframeofs + outtoc.tracks[trknum-1].frames;
+ }
+ }
}
- else if (outtoc.numtrks > 3)
+
+ if (EXTRA_VERBOSE)
{
- if (outtoc.tracks[outtoc.numtrks-1].pgtype == CD_TRACK_AUDIO)
- disc_pattern = TYPE_II;
- else
- disc_pattern = TYPE_III;
+ for (trknum = 0; trknum < outtoc.numtrks; trknum++)
+ {
+ osd_printf_verbose("session %d trk %d: %d frames @ offset %d, pad=%d, split=%d, area=%d, phys=%d, pregap=%d, pgtype=%d, pgdatasize=%d, idx0=%d, idx1=%d, dataframes=%d\n",
+ outtoc.tracks[trknum].session + 1,
+ trknum + 1,
+ outtoc.tracks[trknum].frames,
+ outinfo.track[trknum].offset,
+ outtoc.tracks[trknum].padframes,
+ outtoc.tracks[trknum].splitframes,
+ outtoc.tracks[trknum].multicuearea,
+ outtoc.tracks[trknum].physframeofs,
+ outtoc.tracks[trknum].pregap,
+ outtoc.tracks[trknum].pgtype,
+ outtoc.tracks[trknum].pgdatasize,
+ outinfo.track[trknum].idx[0],
+ outinfo.track[trknum].idx[1],
+ outtoc.tracks[trknum].frames - outtoc.tracks[trknum].padframes);
+ }
}
- else if (outtoc.numtrks == 3)
+
+ return std::error_condition();
+}
+
+/*---------------------------------------------------------------------------------------
+ is_gdicue - determine if CUE contains Redump multi-CUE format for Dreamcast GDI
+----------------------------------------------------------------------------------------*/
+
+/**
+ * Dreamcast GDI has two images on one disc, SINGLE-DENSITY and HIGH-DENSITY.
+ *
+ * Redump stores both images in a single .cue with a REM comment separating the images.
+ * This multi-cue format replaces the old flawed .gdi format.
+ *
+ * http://forum.redump.org/topic/19969/done-sega-dreamcast-multicue-gdi/
+ *
+ * This function looks for strings "REM SINGLE-DENSITY AREA" & "REM HIGH-DENSITY AREA"
+ * indicating the Redump multi-cue format and therefore a Dreamcast GDI disc.
+ */
+
+bool cdrom_file::is_gdicue(std::string_view tocfname)
+{
+ char token[512];
+ bool has_rem_singledensity = false;
+ bool has_rem_highdensity = false;
+ std::string path = std::string(tocfname);
+
+ FILE *infile = fopen(path.c_str(), "rt");
+ if (!infile)
{
- disc_pattern = TYPE_I;
+ return false;
}
- /*
- * Special handling for TYPE_III_SPLIT, pregap in last track contains 75 frames audio and 150 frames data
- */
- if (disc_pattern == TYPE_III_SPLIT)
+ path = get_file_path(path);
+
+ char linebuffer[512];
+ memset(linebuffer, 0, sizeof(linebuffer));
+
+ while (!feof(infile))
{
- assert(outtoc.tracks[outtoc.numtrks-1].pregap == 225);
+ if (!fgets(linebuffer, 511, infile))
+ break;
- // grow the AUDIO track into DATA track by 75 frames as per Pattern III
- outtoc.tracks[outtoc.numtrks-2].frames += 225;
- outtoc.tracks[outtoc.numtrks-2].padframes += 150;
- outinfo.track[outtoc.numtrks-2].offset = 150 * (outtoc.tracks[outtoc.numtrks-2].datasize+outtoc.tracks[outtoc.numtrks-2].subsize);
- outtoc.tracks[outtoc.numtrks-2].splitframes = 75;
+ int i = 0;
- // skip the pregap when reading the DATA track
- outtoc.tracks[outtoc.numtrks-1].frames -= 225;
- outinfo.track[outtoc.numtrks-1].offset += 225 * (outtoc.tracks[outtoc.numtrks-1].datasize+outtoc.tracks[outtoc.numtrks-1].subsize);
- }
+ TOKENIZE
- /*
- * Set LBA for every track with HIGH-DENSITY area @ LBA 45000
- */
- for (trknum = 1; trknum < outtoc.numtrks; trknum++)
- {
- if (outtoc.tracks[trknum].multicuearea == HIGH_DENSITY && outtoc.tracks[trknum-1].multicuearea == SINGLE_DENSITY)
+ if (!strcmp(token, "REM"))
{
- outtoc.tracks[trknum].physframeofs = 45000;
- int dif=outtoc.tracks[trknum].physframeofs-(outtoc.tracks[trknum-1].frames+outtoc.tracks[trknum-1].physframeofs);
- outtoc.tracks[trknum-1].frames += dif;
- outtoc.tracks[trknum-1].padframes = dif;
- }
- else
- {
- outtoc.tracks[trknum].physframeofs = outtoc.tracks[trknum-1].physframeofs + outtoc.tracks[trknum-1].frames;
+ /* skip to actual data of REM command */
+ while (i < std::size(linebuffer) && isspace((uint8_t)linebuffer[i]))
+ i++;
+
+ if (!strncmp(linebuffer+i, "SINGLE-DENSITY AREA", 19))
+ has_rem_singledensity = true;
+ else if (!strncmp(linebuffer+i, "HIGH-DENSITY AREA", 17))
+ has_rem_highdensity = true;
}
}
- if (EXTRA_VERBOSE)
- for (trknum = 0; trknum < outtoc.numtrks; trknum++)
- {
- printf("trk %d: %d frames @ offset %d, pad=%d, split=%d, area=%d, phys=%d, pregap=%d, pgtype=%d, idx0=%d, idx1=%d, (true %d)\n",
- trknum+1,
- outtoc.tracks[trknum].frames,
- outinfo.track[trknum].offset,
- outtoc.tracks[trknum].padframes,
- outtoc.tracks[trknum].splitframes,
- outtoc.tracks[trknum].multicuearea,
- outtoc.tracks[trknum].physframeofs,
- outtoc.tracks[trknum].pregap,
- outtoc.tracks[trknum].pgtype,
- outinfo.track[trknum].idx0offs,
- outinfo.track[trknum].idx1offs,
- outtoc.tracks[trknum].frames - outtoc.tracks[trknum].padframes);
- }
+ fclose(infile);
- return std::error_condition();
+ return has_rem_singledensity && has_rem_highdensity;
}
/*-------------------------------------------------
@@ -2989,7 +2920,7 @@ std::error_condition cdrom_file::parse_gdicue(std::string_view tocfname, toc &ou
std::error_condition cdrom_file::parse_toc(std::string_view tocfname, toc &outtoc, track_input_info &outinfo)
{
- static char token[512];
+ char token[512];
auto pos = tocfname.rfind('.');
std::string tocfext = pos == std::string_view::npos ? std::string() : strmakelower(tocfname.substr(pos + 1));
@@ -3001,10 +2932,7 @@ std::error_condition cdrom_file::parse_toc(std::string_view tocfname, toc &outto
if (tocfext == "cue")
{
- if (is_gdicue(tocfname))
- return parse_gdicue(tocfname, outtoc, outinfo);
- else
- return parse_cue(tocfname, outtoc, outinfo);
+ return parse_cue(tocfname, outtoc, outinfo);
}
if (tocfext == "nrg")
@@ -3034,132 +2962,167 @@ std::error_condition cdrom_file::parse_toc(std::string_view tocfname, toc &outto
int trknum = -1;
char linebuffer[512];
+ memset(linebuffer, 0, sizeof(linebuffer));
+
while (!feof(infile))
{
/* get the next line */
- fgets(linebuffer, 511, infile);
+ if (!fgets(linebuffer, 511, infile))
+ break;
- /* if EOF didn't hit, keep going */
- if (!feof(infile))
- {
- int i = 0;
+ int i = 0;
+ TOKENIZE
+
+ /*
+ Samples: https://github.com/cdrdao/cdrdao/tree/master/testtocs
+
+ Unimplemented:
+ CD_TEXT
+ SILENCE
+ ZERO
+ FIFO
+ PREGAP
+ CATALOG
+ ISRC
+ */
+ if (!strcmp(token, "NO"))
+ {
TOKENIZE
+ if (!strcmp(token, "COPY"))
+ outtoc.tracks[trknum].control_flags &= ~CD_FLAG_CONTROL_DIGITAL_COPY_PERMITTED;
+ else if (!strcmp(token, "PRE_EMPHASIS"))
+ outtoc.tracks[trknum].control_flags &= ~CD_FLAG_CONTROL_PREEMPHASIS;
+ }
+ else if (!strcmp(token, "COPY"))
+ {
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_DIGITAL_COPY_PERMITTED;
+ }
+ else if (!strcmp(token, "PRE_EMPHASIS"))
+ {
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_PREEMPHASIS;
+ }
+ else if (!strcmp(token, "TWO_CHANNEL_AUDIO"))
+ {
+ outtoc.tracks[trknum].control_flags &= ~CD_FLAG_CONTROL_4CH;
+ }
+ else if (!strcmp(token, "FOUR_CHANNEL_AUDIO"))
+ {
+ outtoc.tracks[trknum].control_flags |= CD_FLAG_CONTROL_4CH;
+ }
+ else if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE")))
+ {
+ int f;
- if ((!strcmp(token, "DATAFILE")) || (!strcmp(token, "AUDIOFILE")) || (!strcmp(token, "FILE")))
- {
- int f;
+ /* found the data file for a track */
+ TOKENIZE
- /* found the data file for a track */
- TOKENIZE
+ /* keep the filename */
+ outinfo.track[trknum].fname.assign(path).append(token);
- /* keep the filename */
- outinfo.track[trknum].fname.assign(path).append(token);
+ /* get either the offset or the length */
+ TOKENIZE
- /* get either the offset or the length */
+ if (!strcmp(token, "SWAP"))
+ {
TOKENIZE
- if (!strcmp(token, "SWAP"))
- {
- TOKENIZE
+ outinfo.track[trknum].swap = true;
+ }
+ else
+ {
+ outinfo.track[trknum].swap = false;
+ }
- outinfo.track[trknum].swap = true;
- }
- else
- {
- outinfo.track[trknum].swap = false;
- }
+ if (token[0] == '#')
+ {
+ /* it's a decimal offset, use it */
+ f = strtoul(&token[1], nullptr, 10);
+ }
+ else if (isdigit((uint8_t)token[0]))
+ {
+ /* convert the time to an offset */
+ f = msf_to_frames(token);
- if (token[0] == '#')
- {
- /* it's a decimal offset, use it */
- f = strtoul(&token[1], nullptr, 10);
- }
- else if (isdigit((uint8_t)token[0]))
- {
- /* convert the time to an offset */
- f = msf_to_frames( token );
+ f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ }
+ else
+ {
+ f = 0;
+ }
- f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- }
- else
- {
- f = 0;
- }
+ outinfo.track[trknum].offset = f;
- outinfo.track[trknum].offset = f;
+ TOKENIZE
+
+ if (isdigit((uint8_t)token[0]))
+ {
+ // this could be the length or an offset from the previous field.
+ f = msf_to_frames(token);
TOKENIZE
if (isdigit((uint8_t)token[0]))
{
- // this could be the length or an offset from the previous field.
- f = msf_to_frames( token );
-
- TOKENIZE
-
- if (isdigit((uint8_t)token[0]))
- {
- // it was an offset.
- f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ // it was an offset.
+ f *= (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outinfo.track[trknum].offset += f;
+ outinfo.track[trknum].offset += f;
- // this is the length.
- f = msf_to_frames( token );
- }
- }
- else if( trknum == 0 && outinfo.track[trknum].offset != 0 )
- {
- /* the 1st track might have a length with no offset */
- f = outinfo.track[trknum].offset / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
- outinfo.track[trknum].offset = 0;
+ // this is the length.
+ f = msf_to_frames(token);
}
- else
- {
- /* guesstimate the track length? */
- f = 0;
- }
-
- outtoc.tracks[trknum].frames = f;
}
- else if (!strcmp(token, "TRACK"))
+ else if (trknum == 0 && outinfo.track[trknum].offset != 0)
{
- trknum++;
-
- /* next token on the line is the track type */
- TOKENIZE
+ /* the 1st track might have a length with no offset */
+ f = outinfo.track[trknum].offset / (outtoc.tracks[trknum].datasize + outtoc.tracks[trknum].subsize);
+ outinfo.track[trknum].offset = 0;
+ }
+ else
+ {
+ /* guesstimate the track length? */
+ f = 0;
+ }
- outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
- outtoc.tracks[trknum].datasize = 0;
- outtoc.tracks[trknum].subtype = CD_SUB_NONE;
- outtoc.tracks[trknum].subsize = 0;
- outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
- outtoc.tracks[trknum].padframes = 0;
+ outtoc.tracks[trknum].frames = f;
+ }
+ else if (!strcmp(token, "TRACK"))
+ {
+ trknum++;
- convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
- if (outtoc.tracks[trknum].datasize == 0)
- {
- fclose(infile);
- printf("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
- return chd_file::error::UNSUPPORTED_FORMAT;
- }
+ /* next token on the line is the track type */
+ TOKENIZE
- /* next (optional) token on the line is the subcode type */
- TOKENIZE
+ outtoc.tracks[trknum].trktype = CD_TRACK_MODE1;
+ outtoc.tracks[trknum].datasize = 0;
+ outtoc.tracks[trknum].subtype = CD_SUB_NONE;
+ outtoc.tracks[trknum].subsize = 0;
+ outtoc.tracks[trknum].pgsub = CD_SUB_NONE;
+ outtoc.tracks[trknum].padframes = 0;
- convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]);
- }
- else if (!strcmp(token, "START"))
+ convert_type_string_to_track_info(token, &outtoc.tracks[trknum]);
+ if (outtoc.tracks[trknum].datasize == 0)
{
- int frames;
+ fclose(infile);
+ osd_printf_error("ERROR: Unknown track type [%s]. Contact MAMEDEV.\n", token);
+ return chd_file::error::UNSUPPORTED_FORMAT;
+ }
- /* get index */
- TOKENIZE
- frames = msf_to_frames( token );
+ /* next (optional) token on the line is the subcode type */
+ TOKENIZE
- outtoc.tracks[trknum].pregap = frames;
- }
+ convert_subtype_string_to_track_info(token, &outtoc.tracks[trknum]);
+ }
+ else if (!strcmp(token, "START"))
+ {
+ int frames;
+
+ /* get index */
+ TOKENIZE
+ frames = msf_to_frames(token);
+
+ outtoc.tracks[trknum].pregap = frames;
}
}
@@ -3168,6 +3131,7 @@ std::error_condition cdrom_file::parse_toc(std::string_view tocfname, toc &outto
/* store the number of tracks found */
outtoc.numtrks = trknum + 1;
+ outtoc.numsessions = 1;
return std::error_condition();
}
diff --git a/src/lib/util/cdrom.h b/src/lib/util/cdrom.h
index 214a7ed39d6..b11ecb5b3ba 100644
--- a/src/lib/util/cdrom.h
+++ b/src/lib/util/cdrom.h
@@ -16,6 +16,12 @@
#include "ioprocs.h"
#include "osdcore.h"
+#include <algorithm>
+#include <string>
+#include <string_view>
+#include <system_error>
+
+
class cdrom_file {
public:
// tracks are padded to a multiple of this many frames
@@ -24,6 +30,7 @@ public:
static constexpr uint32_t MAX_TRACKS = 99; /* AFAIK the theoretical limit */
static constexpr uint32_t MAX_SECTOR_DATA = 2352;
static constexpr uint32_t MAX_SUBCODE_DATA = 96;
+ static constexpr uint32_t MAX_INDEX = 99;
static constexpr uint32_t FRAME_SIZE = MAX_SECTOR_DATA + MAX_SUBCODE_DATA;
static constexpr uint32_t FRAMES_PER_HUNK = 8;
@@ -53,29 +60,47 @@ public:
enum
{
- CD_FLAG_GDROM = 0x00000001, // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
- CD_FLAG_GDROMLE = 0x00000002 // legacy GD-ROM, with little-endian CDDA data
+ CD_FLAG_GDROM = 0x00000001, // disc is a GD-ROM, all tracks should be stored with GD-ROM metadata
+ CD_FLAG_GDROMLE = 0x00000002, // legacy GD-ROM, with little-endian CDDA data
+ CD_FLAG_MULTISESSION = 0x00000004, // multisession CD-ROM
+ };
+
+ enum
+ {
+ CD_FLAG_CONTROL_PREEMPHASIS = 1,
+ CD_FLAG_CONTROL_DIGITAL_COPY_PERMITTED = 2,
+ CD_FLAG_CONTROL_DATA_TRACK = 4,
+ CD_FLAG_CONTROL_4CH = 8,
+ };
+
+ enum
+ {
+ CD_FLAG_ADR_START_TIME = 1,
+ CD_FLAG_ADR_CATALOG_CODE,
+ CD_FLAG_ADR_ISRC_CODE,
};
struct track_info
{
/* fields used by CHDMAN and in MAME */
- uint32_t trktype; /* track type */
- uint32_t subtype; /* subcode data type */
- uint32_t datasize; /* size of data in each sector of this track */
- uint32_t subsize; /* size of subchannel data in each sector of this track */
- uint32_t frames; /* number of frames in this track */
- uint32_t extraframes; /* number of "spillage" frames in this track */
- uint32_t pregap; /* number of pregap frames */
- uint32_t postgap; /* number of postgap frames */
- uint32_t pgtype; /* type of sectors in pregap */
- uint32_t pgsub; /* type of subchannel data in pregap */
- uint32_t pgdatasize; /* size of data in each sector of the pregap */
- uint32_t pgsubsize; /* size of subchannel data in each sector of the pregap */
+ uint32_t trktype; /* track type */
+ uint32_t subtype; /* subcode data type */
+ uint32_t datasize; /* size of data in each sector of this track */
+ uint32_t subsize; /* size of subchannel data in each sector of this track */
+ uint32_t frames; /* number of frames in this track */
+ uint32_t extraframes; /* number of "spillage" frames in this track */
+ uint32_t pregap; /* number of pregap frames */
+ uint32_t postgap; /* number of postgap frames */
+ uint32_t pgtype; /* type of sectors in pregap */
+ uint32_t pgsub; /* type of subchannel data in pregap */
+ uint32_t pgdatasize; /* size of data in each sector of the pregap */
+ uint32_t pgsubsize; /* size of subchannel data in each sector of the pregap */
+ uint32_t control_flags; /* metadata flags associated with each track */
+ uint32_t session; /* session number */
/* fields used in CHDMAN only */
uint32_t padframes; /* number of frames of padding to add to the end of the track; needed for GDI */
- uint32_t splitframes; /* number of frames to read from the next file; needed for Redump split-bin GDI */
+ uint32_t splitframes; /* number of frames from the next file to add to the end of the current track after padding; needed for Redump split-bin GDI */
/* fields used in MAME/MESS only */
uint32_t logframeofs; /* logical frame of actual track data - offset by pregap size if pregap not physically present */
@@ -91,20 +116,21 @@ public:
struct toc
{
uint32_t numtrks; /* number of tracks */
+ uint32_t numsessions; /* number of sessions */
uint32_t flags; /* see FLAG_ above */
- track_info tracks[MAX_TRACKS];
+ track_info tracks[MAX_TRACKS + 1];
};
struct track_input_entry
{
track_input_entry() { reset(); }
- void reset() { fname.clear(); offset = idx0offs = idx1offs = 0; swap = false; }
+ void reset() { fname.clear(); offset = 0; leadin = leadout = -1; swap = false; std::fill(std::begin(idx), std::end(idx), -1); }
std::string fname; // filename for each track
uint32_t offset; // offset in the data file for each track
bool swap; // data needs to be byte swapped
- uint32_t idx0offs;
- uint32_t idx1offs;
+ int32_t idx[MAX_INDEX + 1];
+ int32_t leadin, leadout; // TODO: these should probably be their own tracks entirely
};
struct track_input_info
@@ -128,6 +154,7 @@ public:
uint32_t get_track(uint32_t frame) const;
uint32_t get_track_start(uint32_t track) const {return cdtoc.tracks[track == 0xaa ? cdtoc.numtrks : track].logframeofs; }
uint32_t get_track_start_phys(uint32_t track) const { return cdtoc.tracks[track == 0xaa ? cdtoc.numtrks : track].physframeofs; }
+ uint32_t get_track_index(uint32_t frame) const;
/* TOC utilities */
static std::error_condition parse_nero(std::string_view tocfname, toc &outtoc, track_input_info &outinfo);
@@ -135,10 +162,18 @@ public:
static std::error_condition parse_gdi(std::string_view tocfname, toc &outtoc, track_input_info &outinfo);
static std::error_condition parse_cue(std::string_view tocfname, toc &outtoc, track_input_info &outinfo);
static bool is_gdicue(std::string_view tocfname);
- static std::error_condition parse_gdicue(std::string_view tocfname, toc &outtoc, track_input_info &outinfo);
static std::error_condition parse_toc(std::string_view tocfname, toc &outtoc, track_input_info &outinfo);
+ int get_last_session() const { return cdtoc.numsessions ? cdtoc.numsessions : 1; }
int get_last_track() const { return cdtoc.numtrks; }
- int get_adr_control(int track) const { return track == 0xaa || cdtoc.tracks[track].trktype == CD_TRACK_AUDIO ? 0x10 : 0x14; }
+ int get_adr_control(int track) const
+ {
+ if (track == 0xaa)
+ track = get_last_track() - 1; // use last track's flags
+ int adrctl = (CD_FLAG_ADR_START_TIME << 4) | (cdtoc.tracks[track].control_flags & 0x0f);
+ if (cdtoc.tracks[track].trktype != CD_TRACK_AUDIO)
+ adrctl |= CD_FLAG_CONTROL_DATA_TRACK;
+ return adrctl;
+ }
int get_track_type(int track) const { return cdtoc.tracks[track].trktype; }
const toc &get_toc() const { return cdtoc; }
@@ -254,8 +289,8 @@ private:
static std::string get_file_path(std::string &path);
static uint64_t get_file_size(std::string_view filename);
- static int tokenize( const char *linebuffer, int i, int linebuffersize, char *token, int tokensize );
- static int msf_to_frames( char *token );
+ static int tokenize(const char *linebuffer, int i, int linebuffersize, char *token, int tokensize);
+ static int msf_to_frames(const char *token);
static uint32_t parse_wav_sample(std::string_view filename, uint32_t *dataoffs);
static uint16_t read_uint16(FILE *infile);
static uint32_t read_uint32(FILE *infile);
diff --git a/src/lib/util/chd.cpp b/src/lib/util/chd.cpp
index 194884bfd9a..c05977a84eb 100644
--- a/src/lib/util/chd.cpp
+++ b/src/lib/util/chd.cpp
@@ -2,8 +2,6 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- chd.c
-
MAME Compressed Hunks of Data file format
***************************************************************************/
@@ -22,11 +20,13 @@
#include <zlib.h>
+#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdlib>
#include <ctime>
#include <new>
+#include <tuple>
//**************************************************************************
@@ -134,7 +134,7 @@ struct chd_file::metadata_hash
// stream in bigendian order
//-------------------------------------------------
-inline util::sha1_t chd_file::be_read_sha1(const uint8_t *base)const
+inline util::sha1_t chd_file::be_read_sha1(const uint8_t *base) const noexcept
{
util::sha1_t result;
memcpy(&result.m_raw[0], base, sizeof(result.m_raw));
@@ -147,7 +147,7 @@ inline util::sha1_t chd_file::be_read_sha1(const uint8_t *base)const
// stream in bigendian order
//-------------------------------------------------
-inline void chd_file::be_write_sha1(uint8_t *base, util::sha1_t value)
+inline void chd_file::be_write_sha1(uint8_t *base, util::sha1_t value) noexcept
{
memcpy(base, &value.m_raw[0], sizeof(value.m_raw));
}
@@ -155,45 +155,45 @@ inline void chd_file::be_write_sha1(uint8_t *base, util::sha1_t value)
//-------------------------------------------------
// file_read - read from the file at the given
-// offset; on failure throw an error
+// offset.
//-------------------------------------------------
-inline void chd_file::file_read(uint64_t offset, void *dest, uint32_t length) const
+inline std::error_condition chd_file::file_read(uint64_t offset, void *dest, uint32_t length) const noexcept
{
// no file = failure
- if (!m_file)
- throw std::error_condition(error::NOT_OPEN);
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
// seek and read
- m_file->seek(offset, SEEK_SET);
+ std::error_condition err;
+ err = m_file->seek(offset, SEEK_SET);
+ if (UNEXPECTED(err))
+ return err;
size_t count;
- std::error_condition err = m_file->read(dest, length, count);
- if (err)
- throw err;
- else if (count != length)
- throw std::error_condition(std::errc::io_error); // TODO: revisit this error code (happens if file is cut off)
+ std::tie(err, count) = read(*m_file, dest, length);
+ if (UNEXPECTED(!err && (count != length)))
+ return std::error_condition(std::errc::io_error); // TODO: revisit this error code (happens if file is truncated)
+ return err;
}
//-------------------------------------------------
// file_write - write to the file at the given
-// offset; on failure throw an error
+// offset.
//-------------------------------------------------
-inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t length)
+inline std::error_condition chd_file::file_write(uint64_t offset, const void *source, uint32_t length) noexcept
{
// no file = failure
- if (!m_file)
- throw std::error_condition(error::NOT_OPEN);
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
// seek and write
- m_file->seek(offset, SEEK_SET);
- size_t count;
- std::error_condition err = m_file->write(source, length, count);
- if (err)
- throw err;
- else if (count != length)
- throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is inuterrupted by a signal
+ std::error_condition err;
+ err = m_file->seek(offset, SEEK_SET);
+ if (UNEXPECTED(err))
+ return err;
+ return write(*m_file, source, length).first;
}
@@ -205,21 +205,20 @@ inline void chd_file::file_write(uint64_t offset, const void *source, uint32_t l
inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint32_t alignment)
{
- std::error_condition err;
-
// no file = failure
- if (!m_file)
+ if (UNEXPECTED(!m_file))
throw std::error_condition(error::NOT_OPEN);
// seek to the end and align if necessary
+ std::error_condition err;
err = m_file->seek(0, SEEK_END);
- if (err)
+ if (UNEXPECTED(err))
throw err;
if (alignment != 0)
{
uint64_t offset;
err = m_file->tell(offset);
- if (err)
+ if (UNEXPECTED(err))
throw err;
uint32_t delta = offset % alignment;
if (delta != 0)
@@ -232,8 +231,8 @@ inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint3
{
uint32_t bytes_to_write = std::min<std::size_t>(sizeof(buffer), delta);
size_t count;
- err = m_file->write(buffer, bytes_to_write, count);
- if (err)
+ std::tie(err, count) = write(*m_file, buffer, bytes_to_write);
+ if (UNEXPECTED(err))
throw err;
delta -= count;
}
@@ -243,14 +242,11 @@ inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint3
// write the real data
uint64_t offset;
err = m_file->tell(offset);
- if (err)
+ if (UNEXPECTED(err))
throw err;
- size_t count;
- err = m_file->write(source, length, count);
- if (err)
+ std::tie(err, std::ignore) = write(*m_file, source, length);
+ if (UNEXPECTED(err))
throw err;
- else if (count != length)
- throw std::error_condition(std::errc::interrupted); // can theoretically happen if write is interrupted by a signal
return offset;
}
@@ -260,11 +256,14 @@ inline uint64_t chd_file::file_append(const void *source, uint32_t length, uint3
// necessary to represent all numbers 0..value
//-------------------------------------------------
-inline uint8_t chd_file::bits_for_value(uint64_t value)
+inline uint8_t chd_file::bits_for_value(uint64_t value) noexcept
{
uint8_t result = 0;
while (value != 0)
- value >>= 1, result++;
+ {
+ value >>= 1;
+ result++;
+ }
return result;
}
@@ -338,20 +337,14 @@ bool chd_file::parent_missing() const noexcept
* @return A sha1_t.
*/
-util::sha1_t chd_file::sha1()
+util::sha1_t chd_file::sha1() const noexcept
{
- try
- {
- // read the big-endian version
- uint8_t rawbuf[sizeof(util::sha1_t)];
- file_read(m_sha1_offset, rawbuf, sizeof(rawbuf));
- return be_read_sha1(rawbuf);
- }
- catch (std::error_condition const &)
- {
- // on failure, return nullptr
- return util::sha1_t::null;
- }
+ // read the big-endian version
+ uint8_t rawbuf[sizeof(util::sha1_t)];
+ std::error_condition err = file_read(m_sha1_offset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(err))
+ return util::sha1_t::null; // on failure, return null
+ return be_read_sha1(rawbuf);
}
/**
@@ -367,22 +360,24 @@ util::sha1_t chd_file::sha1()
* @return A sha1_t.
*/
-util::sha1_t chd_file::raw_sha1()
+util::sha1_t chd_file::raw_sha1() const noexcept
{
try
{
// determine offset within the file for data-only
- if (!m_rawsha1_offset)
+ if (UNEXPECTED(!m_rawsha1_offset))
throw std::error_condition(error::UNSUPPORTED_VERSION);
// read the big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
- file_read(m_rawsha1_offset, rawbuf, sizeof(rawbuf));
+ std::error_condition err = file_read(m_rawsha1_offset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(err))
+ throw err;
return be_read_sha1(rawbuf);
}
catch (std::error_condition const &)
{
- // on failure, return nullptr
+ // on failure, return null
return util::sha1_t::null;
}
}
@@ -400,17 +395,19 @@ util::sha1_t chd_file::raw_sha1()
* @return A sha1_t.
*/
-util::sha1_t chd_file::parent_sha1()
+util::sha1_t chd_file::parent_sha1() const noexcept
{
try
{
// determine offset within the file
- if (!m_parentsha1_offset)
+ if (UNEXPECTED(!m_parentsha1_offset))
throw std::error_condition(error::UNSUPPORTED_VERSION);
// read the big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
- file_read(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
+ std::error_condition err = file_read(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(err))
+ throw err;
return be_read_sha1(rawbuf);
}
catch (std::error_condition const &)
@@ -441,49 +438,51 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
return std::error_condition(error::HUNK_OUT_OF_RANGE);
// get the map pointer
- uint8_t *rawmap;
switch (m_version)
{
- // v3/v4 map entries
- case 3:
- case 4:
- rawmap = &m_rawmap[16 * hunknum];
+ // v3/v4 map entries
+ case 3:
+ case 4:
+ {
+ uint8_t const *const rawmap = &m_rawmap[16 * hunknum];
switch (rawmap[15] & V34_MAP_ENTRY_FLAG_TYPE_MASK)
{
- case V34_MAP_ENTRY_TYPE_COMPRESSED:
- compressor = CHD_CODEC_ZLIB;
- compbytes = get_u16be(&rawmap[12]) + (rawmap[14] << 16);
- break;
+ case V34_MAP_ENTRY_TYPE_COMPRESSED:
+ compressor = CHD_CODEC_ZLIB;
+ compbytes = get_u16be(&rawmap[12]) + (rawmap[14] << 16);
+ break;
- case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
- compressor = CHD_CODEC_NONE;
- compbytes = m_hunkbytes;
- break;
+ case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
+ compressor = CHD_CODEC_NONE;
+ compbytes = m_hunkbytes;
+ break;
- case V34_MAP_ENTRY_TYPE_MINI:
- compressor = CHD_CODEC_MINI;
- compbytes = 0;
- break;
+ case V34_MAP_ENTRY_TYPE_MINI:
+ compressor = CHD_CODEC_MINI;
+ compbytes = 0;
+ break;
- case V34_MAP_ENTRY_TYPE_SELF_HUNK:
- compressor = CHD_CODEC_SELF;
- compbytes = 0;
- break;
+ case V34_MAP_ENTRY_TYPE_SELF_HUNK:
+ compressor = CHD_CODEC_SELF;
+ compbytes = 0;
+ break;
- case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
- compressor = CHD_CODEC_PARENT;
- compbytes = 0;
- break;
+ case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
+ compressor = CHD_CODEC_PARENT;
+ compbytes = 0;
+ break;
}
- break;
+ }
+ break;
- // v5 map entries
- case 5:
- rawmap = &m_rawmap[m_mapentrybytes * hunknum];
+ // v5 map entries
+ case 5:
+ {
+ uint8_t const *const rawmap = &m_rawmap[m_mapentrybytes * hunknum];
- // uncompressed case
if (!compressed())
{
+ // uncompressed case
if (get_u32be(&rawmap[0]) == 0)
{
compressor = CHD_CODEC_PARENT;
@@ -494,12 +493,12 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
compressor = CHD_CODEC_NONE;
compbytes = m_hunkbytes;
}
- break;
}
-
- // compressed case
- switch (rawmap[0])
+ else
{
+ // compressed case
+ switch (rawmap[0])
+ {
case COMPRESSION_TYPE_0:
case COMPRESSION_TYPE_1:
case COMPRESSION_TYPE_2:
@@ -525,9 +524,12 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
default:
return error::UNKNOWN_COMPRESSION;
+ }
}
- break;
+ }
+ break;
}
+
return std::error_condition();
}
@@ -541,20 +543,36 @@ std::error_condition chd_file::hunk_info(uint32_t hunknum, chd_codec_type &compr
* @param rawdata The rawdata.
*/
-void chd_file::set_raw_sha1(util::sha1_t rawdata)
+std::error_condition chd_file::set_raw_sha1(util::sha1_t rawdata) noexcept
{
+ uint64_t const offset = (m_rawsha1_offset != 0) ? m_rawsha1_offset : m_sha1_offset;
+ assert(offset != 0);
+
// create a big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
be_write_sha1(rawbuf, rawdata);
// write to the header
- uint64_t offset = (m_rawsha1_offset != 0) ? m_rawsha1_offset : m_sha1_offset;
- assert(offset != 0);
- file_write(offset, rawbuf, sizeof(rawbuf));
+ std::error_condition err = file_write(offset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(err))
+ return err;
- // if we have a separate rawsha1_offset, update the full sha1 as well
- if (m_rawsha1_offset != 0)
- metadata_update_hash();
+ try
+ {
+ // if we have a separate rawsha1_offset, update the full sha1 as well
+ if (m_rawsha1_offset != 0)
+ metadata_update_hash();
+ }
+ catch (std::error_condition const &err)
+ {
+ return err;
+ }
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
+
+ return std::error_condition();
}
/**
@@ -569,23 +587,24 @@ void chd_file::set_raw_sha1(util::sha1_t rawdata)
* @param parent The parent.
*/
-void chd_file::set_parent_sha1(util::sha1_t parent)
+std::error_condition chd_file::set_parent_sha1(util::sha1_t parent) noexcept
{
// if no file, fail
- if (!m_file)
- throw std::error_condition(error::INVALID_FILE);
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::INVALID_FILE);
+
+ assert(m_parentsha1_offset != 0);
// create a big-endian version
uint8_t rawbuf[sizeof(util::sha1_t)];
be_write_sha1(rawbuf, parent);
// write to the header
- assert(m_parentsha1_offset != 0);
- file_write(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
+ return file_write(m_parentsha1_offset, rawbuf, sizeof(rawbuf));
}
/**
- * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+ * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, const chd_codec_type (&compression)[4])
*
* @brief -------------------------------------------------
* create - create a new file with no parent using an existing opened file handle
@@ -605,12 +624,12 @@ std::error_condition chd_file::create(
uint64_t logicalbytes,
uint32_t hunkbytes,
uint32_t unitbytes,
- chd_codec_type compression[4])
+ const chd_codec_type (&compression)[4])
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
- else if (!file)
+ else if (UNEXPECTED(!file))
return std::errc::invalid_argument;
// set the header parameters
@@ -626,7 +645,7 @@ std::error_condition chd_file::create(
}
/**
- * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+ * @fn std::error_condition chd_file::create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, const chd_codec_type (&compression)[4], chd_file &parent)
*
* @brief -------------------------------------------------
* create - create a new file with a parent using an existing opened file handle
@@ -645,13 +664,13 @@ std::error_condition chd_file::create(
util::random_read_write::ptr &&file,
uint64_t logicalbytes,
uint32_t hunkbytes,
- chd_codec_type compression[4],
+ const chd_codec_type (&compression)[4],
chd_file &parent)
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
- else if (!file)
+ else if (UNEXPECTED(!file))
return std::errc::invalid_argument;
// set the header parameters
@@ -667,7 +686,7 @@ std::error_condition chd_file::create(
}
/**
- * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4])
+ * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, const chd_codec_type (&compression)[4])
*
* @brief -------------------------------------------------
* create - create a new file with no parent using a filename
@@ -687,23 +706,23 @@ std::error_condition chd_file::create(
uint64_t logicalbytes,
uint32_t hunkbytes,
uint32_t unitbytes,
- chd_codec_type compression[4])
+ const chd_codec_type (&compression)[4])
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
// create the new file
util::core_file::ptr file;
std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr)
+ if (UNEXPECTED(filerr))
return filerr;
// create the file normally, then claim the file
std::error_condition chderr = create(std::move(file), logicalbytes, hunkbytes, unitbytes, compression);
// if an error happened, close and delete the file
- if (chderr)
+ if (UNEXPECTED(chderr))
{
file.reset();
osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view
@@ -712,7 +731,7 @@ std::error_condition chd_file::create(
}
/**
- * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent)
+ * @fn std::error_condition chd_file::create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, const chd_codec_type (&compression)[4], chd_file &parent)
*
* @brief -------------------------------------------------
* create - create a new file with a parent using a filename
@@ -731,24 +750,24 @@ std::error_condition chd_file::create(
std::string_view filename,
uint64_t logicalbytes,
uint32_t hunkbytes,
- chd_codec_type compression[4],
+ const chd_codec_type (&compression)[4],
chd_file &parent)
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
// create the new file
util::core_file::ptr file;
std::error_condition filerr = util::core_file::open(filename, OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE, file);
- if (filerr)
+ if (UNEXPECTED(filerr))
return filerr;
// create the file normally, then claim the file
std::error_condition chderr = create(std::move(file), logicalbytes, hunkbytes, compression, parent);
// if an error happened, close and delete the file
- if (chderr)
+ if (UNEXPECTED(chderr))
{
file.reset();
osd_file::remove(std::string(filename)); // FIXME: allow osd_file to use std::string_view
@@ -777,14 +796,14 @@ std::error_condition chd_file::open(
const open_parent_func &open_parent)
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
// open the file
const uint32_t openflags = writeable ? (OPEN_FLAG_READ | OPEN_FLAG_WRITE) : OPEN_FLAG_READ;
util::core_file::ptr file;
std::error_condition filerr = util::core_file::open(filename, openflags, file);
- if (filerr)
+ if (UNEXPECTED(filerr))
return filerr;
// now open the CHD
@@ -812,9 +831,9 @@ std::error_condition chd_file::open(
const open_parent_func &open_parent)
{
// make sure we don't already have a file open
- if (m_file)
+ if (UNEXPECTED(m_file))
return error::ALREADY_OPEN;
- else if (!file)
+ else if (UNEXPECTED(!file))
return std::errc::invalid_argument;
// open the file
@@ -848,7 +867,7 @@ void chd_file::close()
m_hunkcount = 0;
m_unitbytes = 0;
m_unitcount = 0;
- memset(m_compression, 0, sizeof(m_compression));
+ std::fill(std::begin(m_compression), std::end(m_compression), 0);
m_parent.reset();
m_parent_missing = false;
@@ -873,6 +892,105 @@ void chd_file::close()
m_cachehunk = ~0;
}
+std::error_condition chd_file::codec_process_hunk(uint32_t hunknum)
+{
+ // punt if no file
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
+
+ // return an error if out of range
+ if (UNEXPECTED(hunknum >= m_hunkcount))
+ return std::error_condition(error::HUNK_OUT_OF_RANGE);
+
+ // wrap this for clean reporting
+ try
+ {
+ // get a pointer to the map entry
+ switch (m_version)
+ {
+ // v3/v4 map entries
+ case 3:
+ case 4:
+ {
+ uint8_t const *const rawmap = &m_rawmap[16 * hunknum];
+ uint64_t const blockoffs = get_u64be(&rawmap[0]);
+ switch (rawmap[15] & V34_MAP_ENTRY_FLAG_TYPE_MASK)
+ {
+ case V34_MAP_ENTRY_TYPE_COMPRESSED:
+ {
+ uint32_t const blocklen = get_u16be(&rawmap[12]) | (uint32_t(rawmap[14]) << 16);
+ std::error_condition err = file_read(blockoffs, &m_compressed[0], blocklen);
+ if (UNEXPECTED(err))
+ return err;
+ m_decompressor[0]->process(&m_compressed[0], blocklen);
+ return std::error_condition();
+ }
+
+ case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
+ case V34_MAP_ENTRY_TYPE_MINI:
+ return std::error_condition(error::UNSUPPORTED_FORMAT);
+
+ case V34_MAP_ENTRY_TYPE_SELF_HUNK:
+ return codec_process_hunk(blockoffs);
+
+ case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
+ if (UNEXPECTED(m_parent_missing))
+ return std::error_condition(error::REQUIRES_PARENT);
+ return m_parent->codec_process_hunk(blockoffs);
+ }
+ }
+ break;
+
+ // v5 map entries
+ case 5:
+ {
+ if (UNEXPECTED(!compressed()))
+ return std::error_condition(error::UNSUPPORTED_FORMAT);
+
+ // compressed case
+ uint8_t const *const rawmap = &m_rawmap[m_mapentrybytes * hunknum];
+ uint32_t const blocklen = get_u24be(&rawmap[1]);
+ uint64_t const blockoffs = get_u48be(&rawmap[4]);
+ switch (rawmap[0])
+ {
+ case COMPRESSION_TYPE_0:
+ case COMPRESSION_TYPE_1:
+ case COMPRESSION_TYPE_2:
+ case COMPRESSION_TYPE_3:
+ {
+ std::error_condition err = file_read(blockoffs, &m_compressed[0], blocklen);
+ if (UNEXPECTED(err))
+ return err;
+ auto &decompressor = *m_decompressor[rawmap[0]];
+ decompressor.process(&m_compressed[0], blocklen);
+ return std::error_condition();
+ }
+
+ case COMPRESSION_NONE:
+ return std::error_condition(error::UNSUPPORTED_FORMAT);
+
+ case COMPRESSION_SELF:
+ return codec_process_hunk(blockoffs);
+
+ case COMPRESSION_PARENT:
+ if (UNEXPECTED(m_parent_missing))
+ return std::error_condition(error::REQUIRES_PARENT);
+ return m_parent->codec_process_hunk(blockoffs / (m_parent->hunk_bytes() / m_parent->unit_bytes()));
+ }
+ break;
+ }
+ }
+
+ // if we get here, the map contained an unsupported block type
+ return std::error_condition(error::INVALID_DATA);
+ }
+ catch (std::error_condition const &err)
+ {
+ // just return errors
+ return err;
+ }
+}
+
/**
* @fn std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
*
@@ -893,126 +1011,148 @@ void chd_file::close()
* @param hunknum The hunknum.
* @param [in,out] buffer If non-null, the buffer.
*
- * @return The hunk.
+ * @return An error condition.
*/
std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
{
+ // punt if no file
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
+
+ // return an error if out of range
+ if (UNEXPECTED(hunknum >= m_hunkcount))
+ return std::error_condition(error::HUNK_OUT_OF_RANGE);
+
+ auto *const dest = reinterpret_cast<uint8_t *>(buffer);
+
// wrap this for clean reporting
try
{
- // punt if no file
- if (!m_file)
- throw std::error_condition(error::NOT_OPEN);
-
- // return an error if out of range
- if (hunknum >= m_hunkcount)
- throw std::error_condition(error::HUNK_OUT_OF_RANGE);
-
// get a pointer to the map entry
- uint64_t blockoffs;
- uint32_t blocklen;
- util::crc32_t blockcrc;
- uint8_t *rawmap;
- auto *dest = reinterpret_cast<uint8_t *>(buffer);
switch (m_version)
{
- // v3/v4 map entries
- case 3:
- case 4:
- rawmap = &m_rawmap[16 * hunknum];
- blockoffs = get_u64be(&rawmap[0]);
- blockcrc = get_u32be(&rawmap[8]);
+ // v3/v4 map entries
+ case 3:
+ case 4:
+ {
+ uint8_t const *const rawmap = &m_rawmap[16 * hunknum];
+ uint64_t const blockoffs = get_u64be(&rawmap[0]);
+ util::crc32_t const blockcrc = get_u32be(&rawmap[8]);
+ bool const nocrc = rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC;
switch (rawmap[15] & V34_MAP_ENTRY_FLAG_TYPE_MASK)
{
- case V34_MAP_ENTRY_TYPE_COMPRESSED:
- blocklen = get_u16be(&rawmap[12]) + (rawmap[14] << 16);
- file_read(blockoffs, &m_compressed[0], blocklen);
+ case V34_MAP_ENTRY_TYPE_COMPRESSED:
+ {
+ uint32_t const blocklen = get_u16be(&rawmap[12]) | (uint32_t(rawmap[14]) << 16);
+ std::error_condition err = file_read(blockoffs, &m_compressed[0], blocklen);
+ if (UNEXPECTED(err))
+ return err;
m_decompressor[0]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != nullptr && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
+ if (UNEXPECTED(!nocrc && (util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)))
+ return std::error_condition(error::DECOMPRESSION_ERROR);
return std::error_condition();
+ }
- case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
- file_read(blockoffs, dest, m_hunkbytes);
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
+ case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
+ {
+ std::error_condition err = file_read(blockoffs, dest, m_hunkbytes);
+ if (UNEXPECTED(err))
+ return err;
+ if (UNEXPECTED(!nocrc && (util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)))
+ return std::error_condition(error::DECOMPRESSION_ERROR);
return std::error_condition();
+ }
- case V34_MAP_ENTRY_TYPE_MINI:
- put_u64be(dest, blockoffs);
- for (uint32_t bytes = 8; bytes < m_hunkbytes; bytes++)
- dest[bytes] = dest[bytes - 8];
- if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
- return std::error_condition();
+ case V34_MAP_ENTRY_TYPE_MINI:
+ put_u64be(dest, blockoffs);
+ for (uint32_t bytes = 8; bytes < m_hunkbytes; bytes++)
+ dest[bytes] = dest[bytes - 8];
+ if (UNEXPECTED(!nocrc && (util::crc32_creator::simple(dest, m_hunkbytes) != blockcrc)))
+ return std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
- case V34_MAP_ENTRY_TYPE_SELF_HUNK:
- return read_hunk(blockoffs, dest);
+ case V34_MAP_ENTRY_TYPE_SELF_HUNK:
+ return read_hunk(blockoffs, dest);
- case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
- if (m_parent_missing)
- throw std::error_condition(error::REQUIRES_PARENT);
- return m_parent->read_hunk(blockoffs, dest);
+ case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
+ if (UNEXPECTED(m_parent_missing))
+ return std::error_condition(error::REQUIRES_PARENT);
+ return m_parent->read_hunk(blockoffs, dest);
}
- break;
+ }
+ break;
- // v5 map entries
- case 5:
- rawmap = &m_rawmap[m_mapentrybytes * hunknum];
+ // v5 map entries
+ case 5:
+ {
+ uint8_t const *const rawmap = &m_rawmap[m_mapentrybytes * hunknum];
- // uncompressed case
if (!compressed())
{
- blockoffs = mulu_32x32(get_u32be(rawmap), m_hunkbytes);
+ // uncompressed case
+ uint64_t const blockoffs = mulu_32x32(get_u32be(rawmap), m_hunkbytes);
if (blockoffs != 0)
- file_read(blockoffs, dest, m_hunkbytes);
- else if (m_parent_missing)
- throw std::error_condition(error::REQUIRES_PARENT);
+ return file_read(blockoffs, dest, m_hunkbytes);
+ else if (UNEXPECTED(m_parent_missing))
+ return std::error_condition(error::REQUIRES_PARENT);
else if (m_parent)
- m_parent->read_hunk(hunknum, dest);
+ return m_parent->read_hunk(hunknum, dest);
else
memset(dest, 0, m_hunkbytes);
return std::error_condition();
}
-
- // compressed case
- blocklen = get_u24be(&rawmap[1]);
- blockoffs = get_u48be(&rawmap[4]);
- blockcrc = get_u16be(&rawmap[10]);
- switch (rawmap[0])
+ else
{
+ // compressed case
+ uint32_t const blocklen = get_u24be(&rawmap[1]);
+ uint64_t const blockoffs = get_u48be(&rawmap[4]);
+ util::crc16_t const blockcrc = get_u16be(&rawmap[10]);
+ switch (rawmap[0])
+ {
case COMPRESSION_TYPE_0:
case COMPRESSION_TYPE_1:
case COMPRESSION_TYPE_2:
case COMPRESSION_TYPE_3:
- file_read(blockoffs, &m_compressed[0], blocklen);
- m_decompressor[rawmap[0]]->decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
- if (!m_decompressor[rawmap[0]]->lossy() && dest != nullptr && util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
- if (m_decompressor[rawmap[0]]->lossy() && util::crc16_creator::simple(&m_compressed[0], blocklen) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
- return std::error_condition();
+ {
+ std::error_condition err = file_read(blockoffs, &m_compressed[0], blocklen);
+ if (UNEXPECTED(err))
+ return err;
+ auto &decompressor = *m_decompressor[rawmap[0]];
+ decompressor.decompress(&m_compressed[0], blocklen, dest, m_hunkbytes);
+ util::crc16_t const calculated = !decompressor.lossy()
+ ? util::crc16_creator::simple(dest, m_hunkbytes)
+ : util::crc16_creator::simple(&m_compressed[0], blocklen);
+ if (UNEXPECTED(calculated != blockcrc))
+ return std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
+ }
case COMPRESSION_NONE:
- file_read(blockoffs, dest, m_hunkbytes);
- if (util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
- throw std::error_condition(error::DECOMPRESSION_ERROR);
- return std::error_condition();
+ {
+ std::error_condition err = file_read(blockoffs, dest, m_hunkbytes);
+ if (UNEXPECTED(err))
+ return err;
+ if (UNEXPECTED(util::crc16_creator::simple(dest, m_hunkbytes) != blockcrc))
+ return std::error_condition(error::DECOMPRESSION_ERROR);
+ return std::error_condition();
+ }
case COMPRESSION_SELF:
return read_hunk(blockoffs, dest);
case COMPRESSION_PARENT:
- if (m_parent_missing)
- throw std::error_condition(error::REQUIRES_PARENT);
- return m_parent->read_bytes(uint64_t(blockoffs) * uint64_t(m_parent->unit_bytes()), dest, m_hunkbytes);
+ if (UNEXPECTED(m_parent_missing))
+ return std::error_condition(error::REQUIRES_PARENT);
+ return m_parent->read_bytes(blockoffs * m_parent->unit_bytes(), dest, m_hunkbytes);
+ }
}
break;
+ }
}
- // if we get here, something was wrong
- throw std::error_condition(std::errc::io_error);
+ // if we get here, the map contained an unsupported block type
+ return std::error_condition(error::INVALID_DATA);
}
catch (std::error_condition const &err)
{
@@ -1042,68 +1182,73 @@ std::error_condition chd_file::read_hunk(uint32_t hunknum, void *buffer)
std::error_condition chd_file::write_hunk(uint32_t hunknum, const void *buffer)
{
- // wrap this for clean reporting
- try
- {
- // punt if no file
- if (!m_file)
- throw std::error_condition(error::NOT_OPEN);
+ // punt if no file
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
- // return an error if out of range
- if (hunknum >= m_hunkcount)
- throw std::error_condition(error::HUNK_OUT_OF_RANGE);
+ // return an error if out of range
+ if (UNEXPECTED(hunknum >= m_hunkcount))
+ return std::error_condition(error::HUNK_OUT_OF_RANGE);
- // if not writeable, fail
- if (!m_allow_writes)
- throw std::error_condition(error::FILE_NOT_WRITEABLE);
+ // if not writeable, fail
+ if (UNEXPECTED(!m_allow_writes))
+ return std::error_condition(error::FILE_NOT_WRITEABLE);
- // uncompressed writes only via this interface
- if (compressed())
- throw std::error_condition(error::FILE_NOT_WRITEABLE);
+ // uncompressed writes only via this interface
+ if (UNEXPECTED(compressed()))
+ return std::error_condition(error::FILE_NOT_WRITEABLE);
- // see if we have allocated the space on disk for this hunk
- uint8_t *rawmap = &m_rawmap[hunknum * 4];
- uint32_t rawentry = get_u32be(rawmap);
+ // see if we have allocated the space on disk for this hunk
+ uint8_t *const rawmap = &m_rawmap[hunknum * 4];
+ uint32_t rawentry = get_u32be(rawmap);
- // if not, allocate one now
- if (rawentry == 0)
+ // if not, allocate one now
+ if (rawentry == 0)
+ {
+ // first make sure we need to allocate it
+ bool all_zeros = true;
+ const auto *scan = reinterpret_cast<const uint32_t *>(buffer);
+ for (uint32_t index = 0; index < m_hunkbytes / 4; index++)
{
- // first make sure we need to allocate it
- bool all_zeros = true;
- const auto *scan = reinterpret_cast<const uint32_t *>(buffer);
- for (uint32_t index = 0; index < m_hunkbytes / 4; index++)
- if (scan[index] != 0)
- {
- all_zeros = false;
- break;
- }
+ if (scan[index] != 0)
+ {
+ all_zeros = false;
+ break;
+ }
+ }
- // if it's all zeros, do nothing more
- if (all_zeros)
- return std::error_condition();
+ // if it's all zeros, do nothing more
+ if (all_zeros)
+ return std::error_condition();
+ // wrap this for clean reporting
+ try
+ {
// append new data to the end of the file, aligning the first chunk
rawentry = file_append(buffer, m_hunkbytes, m_hunkbytes) / m_hunkbytes;
-
- // write the map entry back
- put_u32be(rawmap, rawentry);
- file_write(m_mapoffset + hunknum * 4, rawmap, 4);
-
- // update the cached hunk if we just wrote it
- if (hunknum == m_cachehunk && buffer != &m_cache[0])
- memcpy(&m_cache[0], buffer, m_hunkbytes);
}
- else
+ catch (std::error_condition const &err)
{
- // otherwise, just overwrite
- file_write(uint64_t(rawentry) * uint64_t(m_hunkbytes), buffer, m_hunkbytes);
+ // just return errors
+ return err;
}
+
+ // write the map entry back
+ put_u32be(rawmap, rawentry);
+ std::error_condition err = file_write(m_mapoffset + hunknum * 4, rawmap, 4);
+ if (UNEXPECTED(err))
+ return err;
+
+ // update the cached hunk if we just wrote it
+ if (hunknum == m_cachehunk && buffer != &m_cache[0])
+ memcpy(&m_cache[0], buffer, m_hunkbytes);
+
return std::error_condition();
}
- catch (std::error_condition const &err)
+ else
{
- // just return errors
- return err;
+ // otherwise, just overwrite
+ return file_write(uint64_t(rawentry) * uint64_t(m_hunkbytes), buffer, m_hunkbytes);
}
}
@@ -1163,36 +1308,36 @@ std::error_condition chd_file::write_units(uint64_t unitnum, const void *buffer,
std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_t bytes)
{
// iterate over hunks
- uint32_t first_hunk = offset / m_hunkbytes;
- uint32_t last_hunk = (offset + bytes - 1) / m_hunkbytes;
+ uint32_t const first_hunk = offset / m_hunkbytes;
+ uint32_t const last_hunk = (offset + bytes - 1) / m_hunkbytes;
auto *dest = reinterpret_cast<uint8_t *>(buffer);
for (uint32_t curhunk = first_hunk; curhunk <= last_hunk; curhunk++)
{
// determine start/end boundaries
- uint32_t startoffs = (curhunk == first_hunk) ? (offset % m_hunkbytes) : 0;
- uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
-
- // if it's a full block, just read directly from disk unless it's the cached hunk
- std::error_condition err;
- if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk)
- err = read_hunk(curhunk, dest);
+ uint32_t const startoffs = (curhunk == first_hunk) ? (offset % m_hunkbytes) : 0;
+ uint32_t const endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
- // otherwise, read from the cache
+ if ((startoffs == 0) && (endoffs == m_hunkbytes - 1) && (curhunk != m_cachehunk))
+ {
+ // if it's a full block, just read directly from disk unless it's the cached hunk
+ std::error_condition err = read_hunk(curhunk, dest);
+ if (UNEXPECTED(err))
+ return err;
+ }
else
{
+ // otherwise, read from the cache
if (curhunk != m_cachehunk)
{
- err = read_hunk(curhunk, &m_cache[0]);
- if (err)
+ std::error_condition err = read_hunk(curhunk, &m_cache[0]);
+ if (UNEXPECTED(err))
return err;
m_cachehunk = curhunk;
}
memcpy(dest, &m_cache[startoffs], endoffs + 1 - startoffs);
}
- // handle errors and advance
- if (err)
- return err;
+ // advance
dest += endoffs + 1 - startoffs;
}
return std::error_condition();
@@ -1216,27 +1361,28 @@ std::error_condition chd_file::read_bytes(uint64_t offset, void *buffer, uint32_
std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer, uint32_t bytes)
{
// iterate over hunks
- uint32_t first_hunk = offset / m_hunkbytes;
- uint32_t last_hunk = (offset + bytes - 1) / m_hunkbytes;
- const auto *source = reinterpret_cast<const uint8_t *>(buffer);
+ uint32_t const first_hunk = offset / m_hunkbytes;
+ uint32_t const last_hunk = (offset + bytes - 1) / m_hunkbytes;
+ auto const *source = reinterpret_cast<uint8_t const *>(buffer);
for (uint32_t curhunk = first_hunk; curhunk <= last_hunk; curhunk++)
{
// determine start/end boundaries
- uint32_t startoffs = (curhunk == first_hunk) ? (offset % m_hunkbytes) : 0;
- uint32_t endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
+ uint32_t const startoffs = (curhunk == first_hunk) ? (offset % m_hunkbytes) : 0;
+ uint32_t const endoffs = (curhunk == last_hunk) ? ((offset + bytes - 1) % m_hunkbytes) : (m_hunkbytes - 1);
- // if it's a full block, just write directly to disk unless it's the cached hunk
std::error_condition err;
- if (startoffs == 0 && endoffs == m_hunkbytes - 1 && curhunk != m_cachehunk)
+ if ((startoffs == 0) && (endoffs == m_hunkbytes - 1) && (curhunk != m_cachehunk))
+ {
+ // if it's a full block, just write directly to disk unless it's the cached hunk
err = write_hunk(curhunk, source);
-
- // otherwise, write from the cache
+ }
else
{
+ // otherwise, write from the cache
if (curhunk != m_cachehunk)
{
err = read_hunk(curhunk, &m_cache[0]);
- if (err)
+ if (UNEXPECTED(err))
return err;
m_cachehunk = curhunk;
}
@@ -1245,7 +1391,7 @@ std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer,
}
// handle errors and advance
- if (err)
+ if (UNEXPECTED(err))
return err;
source += endoffs + 1 - startoffs;
}
@@ -1266,29 +1412,20 @@ std::error_condition chd_file::write_bytes(uint64_t offset, const void *buffer,
* @param searchindex The searchindex.
* @param [in,out] output The output.
*
- * @return The metadata.
+ * @return An error condition.
*/
std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::string &output)
{
- // wrap this for clean reporting
- try
- {
- // if we didn't find it, just return
- metadata_entry metaentry;
- if (!metadata_find(searchtag, searchindex, metaentry))
- return std::error_condition(error::METADATA_NOT_FOUND);
-
- // read the metadata
- output.assign(metaentry.length, '\0');
- file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
- return std::error_condition();
- }
- catch (std::error_condition const &err)
- {
- // just return errors
+ // if we didn't find it, just return
+ metadata_entry metaentry;
+ if (std::error_condition err = metadata_find(searchtag, searchindex, metaentry))
return err;
- }
+
+ // read the metadata
+ try { output.assign(metaentry.length, '\0'); }
+ catch (std::bad_alloc const &) { return std::errc::not_enough_memory; }
+ return file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
}
/**
@@ -1303,29 +1440,20 @@ std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_
* @param searchindex The searchindex.
* @param [in,out] output The output.
*
- * @return The metadata.
+ * @return An error condition.
*/
std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output)
{
- // wrap this for clean reporting
- try
- {
- // if we didn't find it, just return
- metadata_entry metaentry;
- if (!metadata_find(searchtag, searchindex, metaentry))
- throw std::error_condition(error::METADATA_NOT_FOUND);
-
- // read the metadata
- output.resize(metaentry.length);
- file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
- return std::error_condition();
- }
- catch (std::error_condition const &err)
- {
- // just return errors
+ // if we didn't find it, just return
+ metadata_entry metaentry;
+ if (std::error_condition err = metadata_find(searchtag, searchindex, metaentry))
return err;
- }
+
+ // read the metadata
+ try { output.resize(metaentry.length); }
+ catch (std::bad_alloc const &) { return std::errc::not_enough_memory; }
+ return file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
}
/**
@@ -1342,29 +1470,19 @@ std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_
* @param outputlen The outputlen.
* @param [in,out] resultlen The resultlen.
*
- * @return The metadata.
+ * @return An error condition.
*/
std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, void *output, uint32_t outputlen, uint32_t &resultlen)
{
- // wrap this for clean reporting
- try
- {
- // if we didn't find it, just return
- metadata_entry metaentry;
- if (!metadata_find(searchtag, searchindex, metaentry))
- throw std::error_condition(error::METADATA_NOT_FOUND);
-
- // read the metadata
- resultlen = metaentry.length;
- file_read(metaentry.offset + METADATA_HEADER_SIZE, output, std::min(outputlen, resultlen));
- return std::error_condition();
- }
- catch (std::error_condition const &err)
- {
- // just return errors
+ // if we didn't find it, just return
+ metadata_entry metaentry;
+ if (std::error_condition err = metadata_find(searchtag, searchindex, metaentry))
return err;
- }
+
+ // read the metadata
+ resultlen = metaentry.length;
+ return file_read(metaentry.offset + METADATA_HEADER_SIZE, output, std::min(outputlen, resultlen));
}
/**
@@ -1381,31 +1499,28 @@ std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_
* @param [in,out] resulttag The resulttag.
* @param [in,out] resultflags The resultflags.
*
- * @return The metadata.
+ * @return An error condition.
*/
std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_t searchindex, std::vector<uint8_t> &output, chd_metadata_tag &resulttag, uint8_t &resultflags)
{
- // wrap this for clean reporting
- try
- {
- // if we didn't find it, just return
- metadata_entry metaentry;
- if (!metadata_find(searchtag, searchindex, metaentry))
- throw std::error_condition(error::METADATA_NOT_FOUND);
-
- // read the metadata
- output.resize(metaentry.length);
- file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
- resulttag = metaentry.metatag;
- resultflags = metaentry.flags;
- return std::error_condition();
- }
- catch (std::error_condition const &err)
- {
- // just return errors
+ std::error_condition err;
+
+ // if we didn't find it, just return
+ metadata_entry metaentry;
+ err = metadata_find(searchtag, searchindex, metaentry);
+ if (err)
return err;
- }
+
+ // read the metadata
+ try { output.resize(metaentry.length); }
+ catch (std::bad_alloc const &) { return std::errc::not_enough_memory; }
+ err = file_read(metaentry.offset + METADATA_HEADER_SIZE, &output[0], metaentry.length);
+ if (UNEXPECTED(err))
+ return err;
+ resulttag = metaentry.metatag;
+ resultflags = metaentry.flags;
+ return std::error_condition();
}
/**
@@ -1426,40 +1541,52 @@ std::error_condition chd_file::read_metadata(chd_metadata_tag searchtag, uint32_
std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t metaindex, const void *inputbuf, uint32_t inputlen, uint8_t flags)
{
- // wrap this for clean reporting
- try
+ // must write at least 1 byte and no more than 16MB
+ if (UNEXPECTED((inputlen < 1) || (inputlen >= 16 * 1024 * 1024)))
+ return std::error_condition(std::errc::invalid_argument);
+
+ // find the entry if it already exists
+ metadata_entry metaentry;
+ bool finished = false;
+ std::error_condition err = metadata_find(metatag, metaindex, metaentry);
+ if (!err)
{
- // must write at least 1 byte and no more than 16MB
- if (inputlen < 1 || inputlen >= 16 * 1024 * 1024)
- return std::error_condition(std::errc::invalid_argument);
-
- // find the entry if it already exists
- metadata_entry metaentry;
- bool finished = false;
- if (metadata_find(metatag, metaindex, metaentry))
+ if (inputlen <= metaentry.length)
{
// if the new data fits over the old data, just overwrite
- if (inputlen <= metaentry.length)
- {
- file_write(metaentry.offset + METADATA_HEADER_SIZE, inputbuf, inputlen);
-
- // if the lengths don't match, we need to update the length in our header
- if (inputlen != metaentry.length)
- {
- uint8_t length[3];
- put_u24be(length, inputlen);
- file_write(metaentry.offset + 5, length, sizeof(length));
- }
+ err = file_write(metaentry.offset + METADATA_HEADER_SIZE, inputbuf, inputlen);
+ if (UNEXPECTED(err))
+ return err;
- // indicate we did everything
- finished = true;
+ // if the lengths don't match, we need to update the length in our header
+ if (inputlen != metaentry.length)
+ {
+ uint8_t length[3];
+ put_u24be(length, inputlen);
+ err = file_write(metaentry.offset + 5, length, sizeof(length));
+ if (UNEXPECTED(err))
+ return err;
}
+ // indicate we did everything
+ finished = true;
+ }
+ else
+ {
// if it doesn't fit, unlink the current entry
- else
- metadata_set_previous_next(metaentry.prev, metaentry.next);
+ err = metadata_set_previous_next(metaentry.prev, metaentry.next);
+ if (UNEXPECTED(err))
+ return err;
}
+ }
+ else if (UNEXPECTED(err != error::METADATA_NOT_FOUND))
+ {
+ return err;
+ }
+ // wrap this for clean reporting
+ try
+ {
// if not yet done, create a new entry and append
if (!finished)
{
@@ -1475,7 +1602,9 @@ std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t
file_append(inputbuf, inputlen);
// set the previous entry to point to us
- metadata_set_previous_next(metaentry.prev, offset);
+ err = metadata_set_previous_next(metaentry.prev, offset);
+ if (UNEXPECTED(err))
+ return err;
}
// update the hash
@@ -1487,6 +1616,10 @@ std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t
// return any errors
return err;
}
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
}
/**
@@ -1507,23 +1640,13 @@ std::error_condition chd_file::write_metadata(chd_metadata_tag metatag, uint32_t
std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_t metaindex)
{
- // wrap this for clean reporting
- try
- {
- // find the entry
- metadata_entry metaentry;
- if (!metadata_find(metatag, metaindex, metaentry))
- throw std::error_condition(error::METADATA_NOT_FOUND);
-
- // point the previous to the next, unlinking us
- metadata_set_previous_next(metaentry.prev, metaentry.next);
- return std::error_condition();
- }
- catch (std::error_condition const &err)
- {
- // return any errors
+ // find the entry
+ metadata_entry metaentry;
+ if (std::error_condition err = metadata_find(metatag, metaindex, metaentry))
return err;
- }
+
+ // point the previous to the next, unlinking us
+ return metadata_set_previous_next(metaentry.prev, metaentry.next);
}
/**
@@ -1542,34 +1665,32 @@ std::error_condition chd_file::delete_metadata(chd_metadata_tag metatag, uint32_
std::error_condition chd_file::clone_all_metadata(chd_file &source)
{
- // wrap this for clean reporting
- try
+ // iterate over metadata entries in the source
+ std::vector<uint8_t> filedata;
+ metadata_entry metaentry;
+ metaentry.metatag = 0;
+ metaentry.length = 0;
+ metaentry.next = 0;
+ metaentry.flags = 0;
+ std::error_condition err;
+ for (err = source.metadata_find(CHDMETATAG_WILDCARD, 0, metaentry); !err; err = source.metadata_find(CHDMETATAG_WILDCARD, 0, metaentry, true))
{
- // iterate over metadata entries in the source
- std::vector<uint8_t> filedata;
- metadata_entry metaentry;
- metaentry.metatag = 0;
- metaentry.length = 0;
- metaentry.next = 0;
- metaentry.flags = 0;
- for (bool has_data = source.metadata_find(CHDMETATAG_WILDCARD, 0, metaentry); has_data; has_data = source.metadata_find(CHDMETATAG_WILDCARD, 0, metaentry, true))
- {
- // read the metadata item
- filedata.resize(metaentry.length);
- source.file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length);
-
- // write it to the destination
- std::error_condition err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags);
- if (err)
- throw err;
- }
- return std::error_condition();
+ // read the metadata item
+ try { filedata.resize(metaentry.length); }
+ catch (std::bad_alloc const &) { return std::errc::not_enough_memory; }
+ err = source.file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length);
+ if (UNEXPECTED(err))
+ return err;
+
+ // write it to the destination
+ err = write_metadata(metaentry.metatag, (uint32_t)-1, &filedata[0], metaentry.length, metaentry.flags);
+ if (UNEXPECTED(err))
+ return err;
}
- catch (std::error_condition const &err)
- {
- // return any errors
+ if (err == error::METADATA_NOT_FOUND)
+ return std::error_condition();
+ else
return err;
- }
}
/**
@@ -1595,15 +1716,18 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
std::vector<uint8_t> filedata;
std::vector<metadata_hash> hasharray;
metadata_entry metaentry;
- for (bool has_data = metadata_find(CHDMETATAG_WILDCARD, 0, metaentry); has_data; has_data = metadata_find(CHDMETATAG_WILDCARD, 0, metaentry, true))
+ std::error_condition err;
+ for (err = metadata_find(CHDMETATAG_WILDCARD, 0, metaentry); !err; err = metadata_find(CHDMETATAG_WILDCARD, 0, metaentry, true))
{
// if not checksumming, continue
- if ((metaentry.flags & CHD_MDFLAGS_CHECKSUM) == 0)
+ if (!(metaentry.flags & CHD_MDFLAGS_CHECKSUM))
continue;
// allocate memory and read the data
filedata.resize(metaentry.length);
- file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length);
+ err = file_read(metaentry.offset + METADATA_HEADER_SIZE, &filedata[0], metaentry.length);
+ if (UNEXPECTED(err))
+ throw err;
// create an entry for this metadata and add it
metadata_hash hashentry;
@@ -1611,6 +1735,8 @@ util::sha1_t chd_file::compute_overall_sha1(util::sha1_t rawsha1)
hashentry.sha1 = util::sha1_creator::simple(&filedata[0], metaentry.length);
hasharray.push_back(hashentry);
}
+ if (err != error::METADATA_NOT_FOUND)
+ throw err;
// sort the array
if (!hasharray.empty())
@@ -1772,7 +1898,7 @@ uint32_t chd_file::guess_unitbytes()
void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
- if (get_u32be(&rawheader[8]) != V3_HEADER_SIZE)
+ if (UNEXPECTED(get_u32be(&rawheader[8]) != V3_HEADER_SIZE))
throw std::error_condition(error::INVALID_FILE);
// extract core info
@@ -1835,7 +1961,7 @@ void chd_file::parse_v3_header(uint8_t *rawheader, util::sha1_t &parentsha1)
void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
- if (get_u32be(&rawheader[8]) != V4_HEADER_SIZE)
+ if (UNEXPECTED(get_u32be(&rawheader[8]) != V4_HEADER_SIZE))
throw std::error_condition(error::INVALID_FILE);
// extract core info
@@ -1895,7 +2021,7 @@ void chd_file::parse_v4_header(uint8_t *rawheader, util::sha1_t &parentsha1)
void chd_file::parse_v5_header(uint8_t *rawheader, util::sha1_t &parentsha1)
{
// verify header length
- if (get_u32be(&rawheader[8]) != V5_HEADER_SIZE)
+ if (UNEXPECTED(get_u32be(&rawheader[8]) != V5_HEADER_SIZE))
throw std::error_condition(error::INVALID_FILE);
// extract core info
@@ -1969,9 +2095,9 @@ std::error_condition chd_file::compress_v5_map()
{
uint8_t curcomp = m_rawmap[hunknum * 12 + 0];
- // promote self block references to more compact forms
if (curcomp == COMPRESSION_SELF)
{
+ // promote self block references to more compact forms
uint32_t refhunk = get_u48be(&m_rawmap[hunknum * 12 + 4]);
if (refhunk == last_self)
curcomp = COMPRESSION_SELF_0;
@@ -1981,10 +2107,9 @@ std::error_condition chd_file::compress_v5_map()
max_self = std::max(max_self, refhunk);
last_self = refhunk;
}
-
- // promote parent block references to more compact forms
else if (curcomp == COMPRESSION_PARENT)
{
+ // promote parent block references to more compact forms
uint32_t refunit = get_u48be(&m_rawmap[hunknum * 12 + 4]);
if (refunit == mulu_32x32(hunknum, m_hunkbytes) / m_unitbytes)
curcomp = COMPRESSION_PARENT_SELF;
@@ -2032,26 +2157,37 @@ std::error_condition chd_file::compress_v5_map()
}
}
- // compute a tree and export it to the buffer
- std::vector<uint8_t> compressed(m_hunkcount * 6);
+ // determine the number of bits we need to hold the a length and a hunk index
+ const uint8_t lengthbits = bits_for_value(max_complen);
+ const uint8_t selfbits = bits_for_value(max_self);
+ const uint8_t parentbits = bits_for_value(max_parent);
+
+ // determine the needed size of the output buffer
+ // 16 bytes is required for the header
+ // max len per entry given to huffman encoder at instantiation is 8 bits
+ // this corresponds to worst-case max 12 bits per entry when RLE encoded.
+ // max additional bits per entry after RLE encoded tree is
+ // for COMPRESSION_TYPE_0-3: lengthbits+16
+ // for COMPRESSION_NONE: 16
+ // for COMPRESSION_SELF: selfbits
+ // for COMPRESSION_PARENT: parentbits
+ // the overall size is clamped later with bitbuf.flush()
+ int nbits_needed = (8*16) + (12 + std::max<int>({lengthbits+16, selfbits, parentbits}))*m_hunkcount;
+ std::vector<uint8_t> compressed(nbits_needed / 8 + 1);
bitstream_out bitbuf(&compressed[16], compressed.size() - 16);
+
+ // compute a tree and export it to the buffer
huffman_error err = encoder.compute_tree_from_histo();
- if (err != HUFFERR_NONE)
+ if (UNEXPECTED(err != HUFFERR_NONE))
throw std::error_condition(error::COMPRESSION_ERROR);
err = encoder.export_tree_rle(bitbuf);
- if (err != HUFFERR_NONE)
+ if (UNEXPECTED(err != HUFFERR_NONE))
throw std::error_condition(error::COMPRESSION_ERROR);
// encode the data
for (uint8_t *src = &compression_rle[0]; src < dest; src++)
encoder.encode_one(bitbuf, *src);
- // determine the number of bits we need to hold the a length
- // and a hunk index
- uint8_t lengthbits = bits_for_value(max_complen);
- uint8_t selfbits = bits_for_value(max_self);
- uint8_t parentbits = bits_for_value(max_parent);
-
// for each compression type, output the relevant data
lastcomp = 0;
count = 0;
@@ -2134,13 +2270,16 @@ std::error_condition chd_file::compress_v5_map()
// then write the map offset
uint8_t rawbuf[sizeof(uint64_t)];
put_u64be(rawbuf, m_mapoffset);
- file_write(m_mapoffset_offset, rawbuf, sizeof(rawbuf));
- return std::error_condition();
+ return file_write(m_mapoffset_offset, rawbuf, sizeof(rawbuf));
}
catch (std::error_condition const &err)
{
return err;
}
+ catch (std::bad_alloc const &)
+ {
+ return std::errc::not_enough_memory;
+ }
}
/**
@@ -2165,7 +2304,10 @@ void chd_file::decompress_v5_map()
// read the reader
uint8_t rawbuf[16];
- file_read(m_mapoffset, rawbuf, sizeof(rawbuf));
+ std::error_condition ioerr;
+ ioerr = file_read(m_mapoffset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(ioerr))
+ throw ioerr;
uint32_t const mapbytes = get_u32be(&rawbuf[0]);
uint64_t const firstoffs = get_u48be(&rawbuf[4]);
util::crc16_t const mapcrc = get_u16be(&rawbuf[10]);
@@ -2175,13 +2317,15 @@ void chd_file::decompress_v5_map()
// now read the map
std::vector<uint8_t> compressed(mapbytes);
- file_read(m_mapoffset + 16, &compressed[0], mapbytes);
+ ioerr = file_read(m_mapoffset + 16, &compressed[0], mapbytes);
+ if (UNEXPECTED(ioerr))
+ throw ioerr;
bitstream_in bitbuf(&compressed[0], compressed.size());
// first decode the compression types
huffman_decoder<16, 8> decoder;
- huffman_error err = decoder.import_tree_rle(bitbuf);
- if (err != HUFFERR_NONE)
+ huffman_error const huferr = decoder.import_tree_rle(bitbuf);
+ if (UNEXPECTED(huferr != HUFFERR_NONE))
throw std::error_condition(error::DECOMPRESSION_ERROR);
uint8_t lastcomp = 0;
int repcount = 0;
@@ -2265,7 +2409,7 @@ void chd_file::decompress_v5_map()
}
// verify the final CRC
- if (util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc)
+ if (UNEXPECTED(util::crc16_creator::simple(&m_rawmap[0], m_hunkcount * 12) != mapcrc))
throw std::error_condition(error::DECOMPRESSION_ERROR);
}
@@ -2295,13 +2439,13 @@ std::error_condition chd_file::create_common()
m_metaoffset = 0;
// if we have a parent, it must be V3 or later
- if (m_parent && m_parent->version() < 3)
+ if (UNEXPECTED(m_parent && m_parent->version() < 3))
throw std::error_condition(error::UNSUPPORTED_VERSION);
// must be an even number of units per hunk
- if (m_hunkbytes % m_unitbytes != 0)
+ if (UNEXPECTED(m_hunkbytes % m_unitbytes != 0))
throw std::error_condition(std::errc::invalid_argument);
- if (m_parent && m_unitbytes != m_parent->unit_bytes())
+ if (UNEXPECTED(m_parent && m_unitbytes != m_parent->unit_bytes()))
throw std::error_condition(std::errc::invalid_argument);
// verify the compression types
@@ -2336,7 +2480,9 @@ std::error_condition chd_file::create_common()
be_write_sha1(&rawheader[104], m_parent ? m_parent->sha1() : util::sha1_t::null);
// write the resulting header
- file_write(0, rawheader, sizeof(rawheader));
+ std::error_condition err = file_write(0, rawheader, sizeof(rawheader));
+ if (UNEXPECTED(err))
+ throw err;
// parse it back out to set up fields appropriately
util::sha1_t parentsha1;
@@ -2354,8 +2500,10 @@ std::error_condition chd_file::create_common()
uint64_t offset = m_mapoffset;
while (mapsize != 0)
{
- uint32_t bytes_to_write = (std::min<size_t>)(mapsize, sizeof(buffer));
- file_write(offset, buffer, bytes_to_write);
+ uint32_t const bytes_to_write = std::min<size_t>(mapsize, sizeof(buffer));
+ err = file_write(offset, buffer, bytes_to_write);
+ if (UNEXPECTED(err))
+ throw err;
offset += bytes_to_write;
mapsize -= bytes_to_write;
}
@@ -2411,10 +2559,12 @@ std::error_condition chd_file::open_common(bool writeable, const open_parent_fun
// read the raw header
uint8_t rawheader[MAX_HEADER_SIZE];
- file_read(0, rawheader, sizeof(rawheader));
+ std::error_condition err = file_read(0, rawheader, sizeof(rawheader));
+ if (UNEXPECTED(err))
+ throw err;
// verify the signature
- if (memcmp(rawheader, "MComprHD", 8) != 0)
+ if (UNEXPECTED(memcmp(rawheader, "MComprHD", 8) != 0))
throw std::error_condition(error::INVALID_FILE);
m_version = get_u32be(&rawheader[12]);
@@ -2433,7 +2583,7 @@ std::error_condition chd_file::open_common(bool writeable, const open_parent_fun
if (m_version < HEADER_VERSION)
m_allow_writes = false;
- if (writeable && !m_allow_writes)
+ if (UNEXPECTED(writeable && !m_allow_writes))
throw std::error_condition(error::FILE_NOT_WRITEABLE);
// make sure we have a parent if we need one (and don't if we don't)
@@ -2447,7 +2597,7 @@ std::error_condition chd_file::open_common(bool writeable, const open_parent_fun
else if (m_parent->sha1() != parentsha1)
throw std::error_condition(error::INVALID_PARENT);
}
- else if (m_parent)
+ else if (UNEXPECTED(m_parent))
{
throw std::error_condition(std::errc::invalid_argument);
}
@@ -2481,16 +2631,22 @@ void chd_file::create_open_common()
for (int decompnum = 0; decompnum < std::size(m_compression); decompnum++)
{
m_decompressor[decompnum] = chd_codec_list::new_decompressor(m_compression[decompnum], *this);
- if (m_decompressor[decompnum] == nullptr && m_compression[decompnum] != 0)
+ if (UNEXPECTED(!m_decompressor[decompnum] && (m_compression[decompnum] != 0)))
throw std::error_condition(error::UNKNOWN_COMPRESSION);
}
// read the map; v5+ compressed drives need to read and decompress their map
m_rawmap.resize(m_hunkcount * m_mapentrybytes);
if (m_version >= 5 && compressed())
+ {
decompress_v5_map();
+ }
else
- file_read(m_mapoffset, &m_rawmap[0], m_rawmap.size());
+ {
+ std::error_condition err = file_read(m_mapoffset, &m_rawmap[0], m_rawmap.size());
+ if (UNEXPECTED(err))
+ throw err;
+ }
// allocate the temporary compressed buffer and a buffer for caching
m_compressed.resize(m_hunkbytes);
@@ -2505,44 +2661,37 @@ void chd_file::create_open_common()
* for appending to a compressed CHD
* -------------------------------------------------.
*
- * @exception CHDERR_NOT_OPEN Thrown when a chderr not open error condition occurs.
- * @exception CHDERR_HUNK_OUT_OF_RANGE Thrown when a chderr hunk out of range error
- * condition occurs.
- * @exception CHDERR_FILE_NOT_WRITEABLE Thrown when a chderr file not writeable error
- * condition occurs.
- * @exception CHDERR_COMPRESSION_ERROR Thrown when a chderr compression error error
- * condition occurs.
- *
* @param hunknum The hunknum.
*/
-void chd_file::verify_proper_compression_append(uint32_t hunknum)
+std::error_condition chd_file::verify_proper_compression_append(uint32_t hunknum) const noexcept
{
// punt if no file
- if (!m_file)
- throw std::error_condition(error::NOT_OPEN);
+ if (UNEXPECTED(!m_file))
+ return std::error_condition(error::NOT_OPEN);
// return an error if out of range
- if (hunknum >= m_hunkcount)
- throw std::error_condition(error::HUNK_OUT_OF_RANGE);
+ if (UNEXPECTED(hunknum >= m_hunkcount))
+ return std::error_condition(error::HUNK_OUT_OF_RANGE);
// if not writeable, fail
- if (!m_allow_writes)
- throw std::error_condition(error::FILE_NOT_WRITEABLE);
+ if (UNEXPECTED(!m_allow_writes))
+ return std::error_condition(error::FILE_NOT_WRITEABLE);
// compressed writes only via this interface
- if (!compressed())
- throw std::error_condition(error::FILE_NOT_WRITEABLE);
+ if (UNEXPECTED(!compressed()))
+ return std::error_condition(error::FILE_NOT_WRITEABLE);
// only permitted to write new blocks
- uint8_t *rawmap = &m_rawmap[hunknum * 12];
- if (rawmap[0] != 0xff)
- throw std::error_condition(error::COMPRESSION_ERROR);
+ uint8_t const *const rawmap = &m_rawmap[hunknum * 12];
+ if (UNEXPECTED(rawmap[0] != 0xff))
+ return std::error_condition(error::COMPRESSION_ERROR);
+
+ // if this isn't the first block, only permitted to write immediately after the previous one
+ if (UNEXPECTED((hunknum != 0) && (rawmap[-12] == 0xff)))
+ return std::error_condition(error::COMPRESSION_ERROR);
- // if this isn't the first block, only permitted to write immediately
- // after the previous one
- if (hunknum != 0 && rawmap[-12] == 0xff)
- throw std::error_condition(error::COMPRESSION_ERROR);
+ return std::error_condition();
}
/**
@@ -2563,7 +2712,9 @@ void chd_file::verify_proper_compression_append(uint32_t hunknum)
void chd_file::hunk_write_compressed(uint32_t hunknum, int8_t compression, const uint8_t *compressed, uint32_t complength, util::crc16_t crc16)
{
// verify that we are appending properly to a compressed file
- verify_proper_compression_append(hunknum);
+ std::error_condition err = verify_proper_compression_append(hunknum);
+ if (UNEXPECTED(err))
+ throw err;
// write the final result
uint64_t offset = file_append(compressed, complength);
@@ -2593,11 +2744,13 @@ void chd_file::hunk_write_compressed(uint32_t hunknum, int8_t compression, const
void chd_file::hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk)
{
// verify that we are appending properly to a compressed file
- verify_proper_compression_append(hunknum);
+ std::error_condition err = verify_proper_compression_append(hunknum);
+ if (UNEXPECTED(err))
+ throw err;
// only permitted to reference prior hunks
- if (otherhunk >= hunknum)
- throw std::error_condition(std::errc::invalid_argument);
+ if (UNEXPECTED(otherhunk >= hunknum))
+ throw std::error_condition(error::HUNK_OUT_OF_RANGE);
// update the map entry
uint8_t *rawmap = &m_rawmap[hunknum * 12];
@@ -2621,10 +2774,12 @@ void chd_file::hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk)
void chd_file::hunk_copy_from_parent(uint32_t hunknum, uint64_t parentunit)
{
// verify that we are appending properly to a compressed file
- verify_proper_compression_append(hunknum);
+ std::error_condition err = verify_proper_compression_append(hunknum);
+ if (UNEXPECTED(err))
+ throw err;
// update the map entry
- uint8_t *rawmap = &m_rawmap[hunknum * 12];
+ uint8_t *const rawmap = &m_rawmap[hunknum * 12];
rawmap[0] = COMPRESSION_PARENT;
put_u24be(&rawmap[1], 0);
put_u48be(&rawmap[4], parentunit);
@@ -2632,7 +2787,7 @@ void chd_file::hunk_copy_from_parent(uint32_t hunknum, uint64_t parentunit)
}
/**
- * @fn bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume)
+ * @fn std::error_condition chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume)
*
* @brief -------------------------------------------------
* metadata_find - find a metadata entry
@@ -2643,10 +2798,10 @@ void chd_file::hunk_copy_from_parent(uint32_t hunknum, uint64_t parentunit)
* @param [in,out] metaentry The metaentry.
* @param resume true to resume.
*
- * @return true if it succeeds, false if it fails.
+ * @return A std::error_condition (error::METADATA_NOT_FOUND if the search fails).
*/
-bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume) const
+std::error_condition chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume) const noexcept
{
// start at the beginning unless we're resuming a previous search
if (!resume)
@@ -2665,7 +2820,9 @@ bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metada
{
// read the raw header
uint8_t raw_meta_header[METADATA_HEADER_SIZE];
- file_read(metaentry.offset, raw_meta_header, sizeof(raw_meta_header));
+ std::error_condition err = file_read(metaentry.offset, raw_meta_header, sizeof(raw_meta_header));
+ if (UNEXPECTED(err))
+ return err;
// extract the data
metaentry.metatag = get_u32be(&raw_meta_header[0]);
@@ -2676,7 +2833,7 @@ bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metada
// if we got a match, proceed
if (metatag == CHDMETATAG_WILDCARD || metaentry.metatag == metatag)
if (metaindex-- == 0)
- return true;
+ return std::error_condition();
// no match, fetch the next link
metaentry.prev = metaentry.offset;
@@ -2684,7 +2841,7 @@ bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metada
}
// if we get here, we didn't find it
- return false;
+ return error::METADATA_NOT_FOUND;
}
/**
@@ -2698,27 +2855,28 @@ bool chd_file::metadata_find(chd_metadata_tag metatag, int32_t metaindex, metada
* @param nextoffset The nextoffset.
*/
-void chd_file::metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffset)
+std::error_condition chd_file::metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffset) noexcept
{
uint64_t offset = 0;
- // if we were the first entry, make the next entry the first
if (prevoffset == 0)
{
+ // if we were the first entry, make the next entry the first
offset = m_metaoffset_offset;
m_metaoffset = nextoffset;
}
-
- // otherwise, update the link in the previous header
else
+ {
+ // otherwise, update the link in the previous header
offset = prevoffset + 8;
+ }
// create a big-endian version
uint8_t rawbuf[sizeof(uint64_t)];
put_u64be(rawbuf, nextoffset);
// write to the header and update our local copy
- file_write(offset, rawbuf, sizeof(rawbuf));
+ return file_write(offset, rawbuf, sizeof(rawbuf));
}
/**
@@ -2732,7 +2890,7 @@ void chd_file::metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffs
void chd_file::metadata_update_hash()
{
// only works for V4 and above, and only for compressed CHDs
- if (m_version < 4 || !compressed())
+ if ((m_version < 4) || !compressed())
return;
// compute the new overall hash
@@ -2743,7 +2901,9 @@ void chd_file::metadata_update_hash()
be_write_sha1(&rawbuf[0], fullsha1);
// write to the header
- file_write(m_sha1_offset, rawbuf, sizeof(rawbuf));
+ std::error_condition err = file_write(m_sha1_offset, rawbuf, sizeof(rawbuf));
+ if (UNEXPECTED(err))
+ throw err;
}
/**
@@ -2778,19 +2938,18 @@ int CLIB_DECL chd_file::metadata_hash_compare(const void *elem1, const void *ele
* -------------------------------------------------.
*/
-chd_file_compressor::chd_file_compressor()
- : m_walking_parent(false),
- m_total_in(0),
- m_total_out(0),
- m_read_queue(nullptr),
- m_read_queue_offset(0),
- m_read_done_offset(0),
- m_read_error(false),
- m_work_queue(nullptr),
- m_write_hunk(0)
+chd_file_compressor::chd_file_compressor() :
+ m_walking_parent(false),
+ m_total_in(0),
+ m_total_out(0),
+ m_read_queue(nullptr),
+ m_read_queue_offset(0),
+ m_read_done_offset(0),
+ m_work_queue(nullptr),
+ m_write_hunk(0)
{
// zap arrays
- memset(m_codecs, 0, sizeof(m_codecs));
+ std::fill(std::begin(m_codecs), std::end(m_codecs), nullptr);
// allocate work queues
m_read_queue = osd_work_queue_alloc(WORK_QUEUE_FLAG_IO);
@@ -2839,7 +2998,7 @@ void chd_file_compressor::compress_begin()
// reset read state
m_read_queue_offset = 0;
m_read_done_offset = 0;
- m_read_error = false;
+ m_read_error.clear();
// reset work item state
m_work_buffer.resize(hunk_bytes() * (WORK_BUFFER_HUNKS + 1));
@@ -2880,20 +3039,19 @@ void chd_file_compressor::compress_begin()
std::error_condition chd_file_compressor::compress_continue(double &progress, double &ratio)
{
- // if we got an error, return an error
- if (m_read_error)
- return std::errc::io_error;
+ // if we got an error, return the error
+ if (UNEXPECTED(m_read_error))
+ return m_read_error;
// if done reading, queue some more
while (m_read_queue_offset < m_logicalbytes && osd_work_queue_items(m_read_queue) < 2)
{
// see if we have enough free work items to read the next half of a buffer
- uint32_t startitem = m_read_queue_offset / hunk_bytes();
- uint32_t enditem = startitem + WORK_BUFFER_HUNKS / 2;
- uint32_t curitem;
- for (curitem = startitem; curitem < enditem; curitem++)
- if (m_work_item[curitem % WORK_BUFFER_HUNKS].m_status != WS_READY)
- break;
+ uint32_t const startitem = m_read_queue_offset / hunk_bytes();
+ uint32_t const enditem = startitem + WORK_BUFFER_HUNKS / 2;
+ uint32_t curitem = startitem;
+ while ((curitem < enditem) && (m_work_item[curitem % WORK_BUFFER_HUNKS].m_status == WS_READY))
+ ++curitem;
// if it's not all clear, defer
if (curitem != enditem)
@@ -2917,64 +3075,60 @@ std::error_condition chd_file_compressor::compress_continue(double &progress, do
work_item &item = m_work_item[m_write_hunk % WORK_BUFFER_HUNKS];
// free any OSD work item
- if (item.m_osd != nullptr)
+ if (item.m_osd)
+ {
osd_work_item_release(item.m_osd);
- item.m_osd = nullptr;
+ item.m_osd = nullptr;
+ }
- // for parent walking, just add to the hashmap
if (m_walking_parent)
{
- uint32_t uph = hunk_bytes() / unit_bytes();
+ // for parent walking, just add to the hashmap
+ uint32_t const uph = hunk_bytes() / unit_bytes();
uint32_t units = uph;
if (item.m_hunknum == hunk_count() - 1 || !compressed())
units = 1;
for (uint32_t unit = 0; unit < units; unit++)
+ {
if (m_parent_map.find(item.m_hash[unit].m_crc16, item.m_hash[unit].m_sha1) == hashmap::NOT_FOUND)
m_parent_map.add(item.m_hunknum * uph + unit, item.m_hash[unit].m_crc16, item.m_hash[unit].m_sha1);
+ }
}
-
- // if we're uncompressed, use regular writes
else if (!compressed())
{
+ // if we're uncompressed, use regular writes
std::error_condition err = write_hunk(item.m_hunknum, item.m_data);
- if (err)
+ if (UNEXPECTED(err))
return err;
// writes of all-0 data don't actually take space, so see if we count this
chd_codec_type codec = CHD_CODEC_NONE;
uint32_t complen;
- hunk_info(item.m_hunknum, codec, complen);
- if (codec == CHD_CODEC_NONE)
+ err = hunk_info(item.m_hunknum, codec, complen);
+ if (!err && codec == CHD_CODEC_NONE) // TODO: report error?
m_total_out += m_hunkbytes;
}
-
- // for compressing, process the result
- else do
+ else if (uint64_t const selfhunk = m_current_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1); selfhunk != hashmap::NOT_FOUND)
+ {
+ // the hunk is in the self map
+ hunk_copy_from_self(item.m_hunknum, selfhunk);
+ }
+ else
{
- // first see if the hunk is in the parent or self maps
- uint64_t selfhunk = m_current_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1);
- if (selfhunk != hashmap::NOT_FOUND)
+ // if not, see if it's in the parent map
+ uint64_t const parentunit = m_parent ? m_parent_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1) : hashmap::NOT_FOUND;
+ if (parentunit != hashmap::NOT_FOUND)
{
- hunk_copy_from_self(item.m_hunknum, selfhunk);
- break;
+ hunk_copy_from_parent(item.m_hunknum, parentunit);
}
-
- // if not, see if it's in the parent map
- if (m_parent)
+ else
{
- uint64_t parentunit = m_parent_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1);
- if (parentunit != hashmap::NOT_FOUND)
- {
- hunk_copy_from_parent(item.m_hunknum, parentunit);
- break;
- }
+ // otherwise, append it compressed and add to the self map
+ hunk_write_compressed(item.m_hunknum, item.m_compression, item.m_compressed, item.m_complen, item.m_hash[0].m_crc16);
+ m_total_out += item.m_complen;
+ m_current_map.add(item.m_hunknum, item.m_hash[0].m_crc16, item.m_hash[0].m_sha1);
}
-
- // otherwise, append it compressed and add to the self map
- hunk_write_compressed(item.m_hunknum, item.m_compression, item.m_compressed, item.m_complen, item.m_hash[0].m_crc16);
- m_total_out += item.m_complen;
- m_current_map.add(item.m_hunknum, item.m_hash[0].m_crc16, item.m_hash[0].m_sha1);
- } while (false);
+ }
// reset the item and advance
item.m_status = WS_READY;
@@ -2983,23 +3137,24 @@ std::error_condition chd_file_compressor::compress_continue(double &progress, do
// if we hit the end, finalize
if (m_write_hunk == m_hunkcount)
{
- // if this is just walking the parent, reset and get ready for compression
if (m_walking_parent)
{
+ // if this is just walking the parent, reset and get ready for compression
m_walking_parent = false;
m_read_queue_offset = m_read_done_offset = 0;
m_write_hunk = 0;
- for (auto & elem : m_work_item)
+ for (auto &elem : m_work_item)
elem.m_status = WS_READY;
}
-
- // wait for all reads to finish and if we're compressed, write the final SHA1 and map
else
{
+ // wait for all reads to finish and if we're compressed, write the final SHA1 and map
osd_work_queue_wait(m_read_queue, 30 * osd_ticks_per_second());
if (!compressed())
return std::error_condition();
- set_raw_sha1(m_compsha1.finish());
+ std::error_condition err = set_raw_sha1(m_compsha1.finish());
+ if (UNEXPECTED(err))
+ return err;
return compress_v5_map();
}
}
@@ -3014,9 +3169,9 @@ std::error_condition chd_file_compressor::compress_continue(double &progress, do
// if we're waiting for work, wait
// sometimes code can get here with .m_status == WS_READY and .m_osd != nullptr, TODO find out why this happens
- while (m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_status != WS_READY &&
- m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_status != WS_COMPLETE &&
- m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd != nullptr)
+ while ((m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_status != WS_READY) &&
+ (m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_status != WS_COMPLETE) &&
+ m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd)
osd_work_item_wait(m_work_item[m_write_hunk % WORK_BUFFER_HUNKS].m_osd, osd_ticks_per_second());
return m_walking_parent ? error::WALKING_PARENT : error::COMPRESSING;
@@ -3037,7 +3192,7 @@ std::error_condition chd_file_compressor::compress_continue(double &progress, do
void *chd_file_compressor::async_walk_parent_static(void *param, int threadid)
{
- auto *item = reinterpret_cast<work_item *>(param);
+ auto *const item = reinterpret_cast<work_item *>(param);
item->m_compressor->async_walk_parent(*item);
return nullptr;
}
@@ -3079,7 +3234,7 @@ void chd_file_compressor::async_walk_parent(work_item &item)
void *chd_file_compressor::async_compress_hunk_static(void *param, int threadid)
{
- auto *item = reinterpret_cast<work_item *>(param);
+ auto *const item = reinterpret_cast<work_item *>(param);
item->m_compressor->async_compress_hunk(*item, threadid);
return nullptr;
}
@@ -3106,8 +3261,8 @@ void chd_file_compressor::async_compress_hunk(work_item &item, int threadid)
// find the best compression scheme, unless we already have a self or parent match
// (note we may miss a self match from blocks not yet added, but this just results in extra work)
// TODO: data race
- if (m_current_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1) == hashmap::NOT_FOUND &&
- m_parent_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1) == hashmap::NOT_FOUND)
+ if ((m_current_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1) == hashmap::NOT_FOUND) &&
+ (m_parent_map.find(item.m_hash[0].m_crc16, item.m_hash[0].m_sha1) == hashmap::NOT_FOUND))
item.m_compression = item.m_codecs->find_best_compressor(item.m_data, item.m_compressed, item.m_complen);
// mark us complete
@@ -3142,37 +3297,45 @@ void *chd_file_compressor::async_read_static(void *param, int threadid)
void chd_file_compressor::async_read()
{
// if in the error or complete state, stop
- if (m_read_error)
+ if (UNEXPECTED(m_read_error))
return;
// determine parameters for the read
- uint32_t work_buffer_bytes = WORK_BUFFER_HUNKS * hunk_bytes();
+ uint32_t const work_buffer_bytes = WORK_BUFFER_HUNKS * hunk_bytes();
uint32_t numbytes = work_buffer_bytes / 2;
- if (m_read_done_offset + numbytes > logical_bytes())
+ if ((m_read_done_offset + numbytes) > logical_bytes())
numbytes = logical_bytes() - m_read_done_offset;
+ uint8_t *const dest = &m_work_buffer[0] + (m_read_done_offset % work_buffer_bytes);
+ assert((&m_work_buffer[0] == dest) || (&m_work_buffer[work_buffer_bytes / 2] == dest));
+ assert(!(m_read_done_offset % hunk_bytes()));
+ uint64_t const end_offset = m_read_done_offset + numbytes;
+
// catch any exceptions coming out of here
try
{
// do the read
- uint8_t *dest = &m_work_buffer[0] + (m_read_done_offset % work_buffer_bytes);
- assert(dest == &m_work_buffer[0] || dest == &m_work_buffer[work_buffer_bytes/2]);
- uint64_t end_offset = m_read_done_offset + numbytes;
-
- // if walking the parent, read in hunks from the parent CHD
if (m_walking_parent)
{
+ // if walking the parent, read in hunks from the parent CHD
+ uint64_t curoffs = m_read_done_offset;
uint8_t *curdest = dest;
- for (uint64_t curoffs = m_read_done_offset; curoffs < end_offset + 1; curoffs += hunk_bytes())
+ uint32_t curhunk = m_read_done_offset / hunk_bytes();
+ while (curoffs < end_offset + 1)
{
- m_parent->read_hunk(curoffs / hunk_bytes(), curdest);
+ std::error_condition err = m_parent->read_hunk(curhunk, curdest);
+ if (err && (error::HUNK_OUT_OF_RANGE != err)) // FIXME: fix the code so it doesn't depend on trying to read past the end of the parent CHD
+ throw err;
+ curoffs += hunk_bytes();
curdest += hunk_bytes();
+ ++curhunk;
}
}
-
- // otherwise, call the virtual function
else
+ {
+ // otherwise, call the virtual function
read_data(dest, m_read_done_offset, numbytes);
+ }
// spawn off work for each hunk
for (uint64_t curoffs = m_read_done_offset; curoffs < end_offset; curoffs += hunk_bytes())
@@ -3199,12 +3362,12 @@ void chd_file_compressor::async_read()
catch (std::error_condition const &err)
{
fprintf(stderr, "CHD error occurred: %s\n", err.message().c_str());
- m_read_error = true;
+ m_read_error = err;
}
catch (std::exception const &ex)
{
fprintf(stderr, "exception occurred: %s\n", ex.what());
- m_read_error = true;
+ m_read_error = std::errc::io_error; // TODO: revisit this error code
}
}
@@ -3222,8 +3385,8 @@ void chd_file_compressor::async_read()
* -------------------------------------------------.
*/
-chd_file_compressor::hashmap::hashmap()
- : m_block_list(new entry_block(nullptr))
+chd_file_compressor::hashmap::hashmap() :
+ m_block_list(new entry_block(nullptr))
{
// initialize the map to empty
memset(m_map, 0, sizeof(m_map));
@@ -3279,10 +3442,10 @@ void chd_file_compressor::hashmap::reset()
* @return An uint64_t.
*/
-uint64_t chd_file_compressor::hashmap::find(util::crc16_t crc16, util::sha1_t sha1)
+uint64_t chd_file_compressor::hashmap::find(util::crc16_t crc16, util::sha1_t sha1) const noexcept
{
// look up the entry in the map
- for (entry_t *entry = m_map[crc16]; entry != nullptr; entry = entry->m_next)
+ for (entry_t *entry = m_map[crc16]; entry; entry = entry->m_next)
if (entry->m_sha1 == sha1)
return entry->m_itemnum;
return NOT_FOUND;
@@ -3312,36 +3475,40 @@ void chd_file_compressor::hashmap::add(uint64_t itemnum, util::crc16_t crc16, ut
m_map[crc16] = entry;
}
-bool chd_file::is_hd() const
+std::error_condition chd_file::check_is_hd() const noexcept
{
metadata_entry metaentry;
return metadata_find(HARD_DISK_METADATA_TAG, 0, metaentry);
}
-bool chd_file::is_cd() const
+std::error_condition chd_file::check_is_cd() const noexcept
{
metadata_entry metaentry;
- return metadata_find(CDROM_OLD_METADATA_TAG, 0, metaentry)
- || metadata_find(CDROM_TRACK_METADATA_TAG, 0, metaentry)
- || metadata_find(CDROM_TRACK_METADATA2_TAG, 0, metaentry);
+ std::error_condition err = metadata_find(CDROM_OLD_METADATA_TAG, 0, metaentry);
+ if (err == error::METADATA_NOT_FOUND)
+ err = metadata_find(CDROM_TRACK_METADATA_TAG, 0, metaentry);
+ if (err == error::METADATA_NOT_FOUND)
+ err = metadata_find(CDROM_TRACK_METADATA2_TAG, 0, metaentry);
+ return err;
}
-bool chd_file::is_gd() const
+std::error_condition chd_file::check_is_gd() const noexcept
{
metadata_entry metaentry;
- return metadata_find(GDROM_OLD_METADATA_TAG, 0, metaentry)
- || metadata_find(GDROM_TRACK_METADATA_TAG, 0, metaentry);
+ std::error_condition err = metadata_find(GDROM_OLD_METADATA_TAG, 0, metaentry);
+ if (err == error::METADATA_NOT_FOUND)
+ err = metadata_find(GDROM_TRACK_METADATA_TAG, 0, metaentry);
+ return err;
}
-bool chd_file::is_dvd() const
+std::error_condition chd_file::check_is_dvd() const noexcept
{
metadata_entry metaentry;
return metadata_find(DVD_METADATA_TAG, 0, metaentry);
}
-bool chd_file::is_av() const
+std::error_condition chd_file::check_is_av() const noexcept
{
metadata_entry metaentry;
return metadata_find(AV_METADATA_TAG, 0, metaentry);
}
-
diff --git a/src/lib/util/chd.h b/src/lib/util/chd.h
index 3e52cab4f9b..671f4bdbd01 100644
--- a/src/lib/util/chd.h
+++ b/src/lib/util/chd.h
@@ -2,8 +2,6 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- chd.h
-
MAME Compressed Hunks of Data file format
***************************************************************************/
@@ -309,24 +307,24 @@ public:
uint32_t hunk_count() const noexcept { return m_hunkcount; }
uint32_t unit_bytes() const noexcept { return m_unitbytes; }
uint64_t unit_count() const noexcept { return m_unitcount; }
- bool compressed() const { return (m_compression[0] != CHD_CODEC_NONE); }
+ bool compressed() const noexcept { return (m_compression[0] != CHD_CODEC_NONE); }
chd_codec_type compression(int index) const noexcept { return m_compression[index]; }
chd_file *parent() const noexcept { return m_parent.get(); }
bool parent_missing() const noexcept;
- util::sha1_t sha1();
- util::sha1_t raw_sha1();
- util::sha1_t parent_sha1();
+ util::sha1_t sha1() const noexcept;
+ util::sha1_t raw_sha1() const noexcept;
+ util::sha1_t parent_sha1() const noexcept;
std::error_condition hunk_info(uint32_t hunknum, chd_codec_type &compressor, uint32_t &compbytes);
// setters
- void set_raw_sha1(util::sha1_t rawdata);
- void set_parent_sha1(util::sha1_t parent);
+ std::error_condition set_raw_sha1(util::sha1_t rawdata) noexcept;
+ std::error_condition set_parent_sha1(util::sha1_t parent) noexcept;
// file create
- std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, chd_codec_type compression[4]);
- std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
- std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, chd_codec_type compression[4], chd_file &parent);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, const chd_codec_type (&compression)[4]);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, uint32_t unitbytes, const chd_codec_type (&compression)[4]);
+ std::error_condition create(std::string_view filename, uint64_t logicalbytes, uint32_t hunkbytes, const chd_codec_type (&compression)[4], chd_file &parent);
+ std::error_condition create(util::random_read_write::ptr &&file, uint64_t logicalbytes, uint32_t hunkbytes, const chd_codec_type (&compression)[4], chd_file &parent);
// file open
std::error_condition open(std::string_view filename, bool writeable = false, chd_file *parent = nullptr, const open_parent_func &open_parent = nullptr);
@@ -336,6 +334,7 @@ public:
void close();
// read/write
+ std::error_condition codec_process_hunk(uint32_t hunknum);
std::error_condition read_hunk(uint32_t hunknum, void *buffer);
std::error_condition write_hunk(uint32_t hunknum, const void *buffer);
std::error_condition read_units(uint64_t unitnum, void *buffer, uint32_t count = 1);
@@ -361,23 +360,23 @@ public:
std::error_condition codec_configure(chd_codec_type codec, int param, void *config);
// typing
- bool is_hd() const;
- bool is_cd() const;
- bool is_gd() const;
- bool is_dvd() const;
- bool is_av() const;
+ std::error_condition check_is_hd() const noexcept;
+ std::error_condition check_is_cd() const noexcept;
+ std::error_condition check_is_gd() const noexcept;
+ std::error_condition check_is_dvd() const noexcept;
+ std::error_condition check_is_av() const noexcept;
private:
struct metadata_entry;
struct metadata_hash;
// inline helpers
- util::sha1_t be_read_sha1(const uint8_t *base) const;
- void be_write_sha1(uint8_t *base, util::sha1_t value);
- void file_read(uint64_t offset, void *dest, uint32_t length) const;
- void file_write(uint64_t offset, const void *source, uint32_t length);
+ util::sha1_t be_read_sha1(const uint8_t *base) const noexcept;
+ void be_write_sha1(uint8_t *base, util::sha1_t value) noexcept;
+ std::error_condition file_read(uint64_t offset, void *dest, uint32_t length) const noexcept;
+ std::error_condition file_write(uint64_t offset, const void *source, uint32_t length) noexcept;
uint64_t file_append(const void *source, uint32_t length, uint32_t alignment = 0);
- uint8_t bits_for_value(uint64_t value);
+ static uint8_t bits_for_value(uint64_t value) noexcept;
// internal helpers
uint32_t guess_unitbytes();
@@ -389,12 +388,12 @@ private:
std::error_condition create_common();
std::error_condition open_common(bool writeable, const open_parent_func &open_parent);
void create_open_common();
- void verify_proper_compression_append(uint32_t hunknum);
+ std::error_condition verify_proper_compression_append(uint32_t hunknum) const noexcept;
void hunk_write_compressed(uint32_t hunknum, int8_t compression, const uint8_t *compressed, uint32_t complength, util::crc16_t crc16);
void hunk_copy_from_self(uint32_t hunknum, uint32_t otherhunk);
void hunk_copy_from_parent(uint32_t hunknum, uint64_t parentunit);
- bool metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume = false) const;
- void metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffset);
+ std::error_condition metadata_find(chd_metadata_tag metatag, int32_t metaindex, metadata_entry &metaentry, bool resume = false) const noexcept;
+ std::error_condition metadata_set_previous_next(uint64_t prevoffset, uint64_t nextoffset) noexcept;
void metadata_update_hash();
static int CLIB_DECL metadata_hash_compare(const void *elem1, const void *elem2);
@@ -466,7 +465,7 @@ private:
// operations
void reset();
- uint64_t find(util::crc16_t crc16, util::sha1_t sha1);
+ uint64_t find(util::crc16_t crc16, util::sha1_t sha1) const noexcept;
void add(uint64_t itemnum, util::crc16_t crc16, util::sha1_t sha1);
// constants
@@ -563,7 +562,7 @@ private:
osd_work_queue * m_read_queue; // work queue for reading
uint64_t m_read_queue_offset;// next offset to enqueue
uint64_t m_read_done_offset; // next offset that will complete
- bool m_read_error; // error during reading?
+ std::error_condition m_read_error; // error during reading, if any
// work item thread
static constexpr int WORK_BUFFER_HUNKS = 256;
diff --git a/src/lib/util/chdcodec.cpp b/src/lib/util/chdcodec.cpp
index c59d880374c..c8a1f573bd0 100644
--- a/src/lib/util/chdcodec.cpp
+++ b/src/lib/util/chdcodec.cpp
@@ -2,8 +2,6 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- chdcodec.c
-
Codecs used by the CHD format
***************************************************************************/
@@ -333,16 +331,16 @@ private:
// ======================> chd_cd_compressor
-template<class BaseCompressor, class SubcodeCompressor>
+template <class BaseCompressor, class SubcodeCompressor>
class chd_cd_compressor : public chd_compressor
{
public:
// construction/destruction
chd_cd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_base_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy),
- m_subcode_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy),
- m_buffer(hunkbytes + (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_base_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy)
+ , m_subcode_compressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy)
+ , m_buffer(hunkbytes + (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA)
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
@@ -402,16 +400,16 @@ private:
// ======================> chd_cd_decompressor
-template<class BaseDecompressor, class SubcodeDecompressor>
+template <class BaseDecompressor, class SubcodeDecompressor>
class chd_cd_decompressor : public chd_decompressor
{
public:
// construction/destruction
chd_cd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_decompressor(chd, hunkbytes, lossy),
- m_base_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy),
- m_subcode_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy),
- m_buffer(hunkbytes)
+ : chd_decompressor(chd, hunkbytes, lossy)
+ , m_base_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SECTOR_DATA, lossy)
+ , m_subcode_decompressor(chd, (hunkbytes / cdrom_file::FRAME_SIZE) * cdrom_file::MAX_SUBCODE_DATA, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
@@ -490,6 +488,7 @@ public:
chd_avhuff_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy);
// core functionality
+ virtual void process(const uint8_t *src, uint32_t complen) override;
virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) override;
virtual void configure(int param, void *config) override;
@@ -553,7 +552,7 @@ const codec_entry f_codec_list[] =
// instance of the given type
//-------------------------------------------------
-const codec_entry *find_in_list(chd_codec_type type)
+const codec_entry *find_in_list(chd_codec_type type) noexcept
{
// find in the list and construct the class
for (auto & elem : f_codec_list)
@@ -575,9 +574,9 @@ const codec_entry *find_in_list(chd_codec_type type)
//-------------------------------------------------
chd_codec::chd_codec(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : m_chd(chd),
- m_hunkbytes(hunkbytes),
- m_lossy(lossy)
+ : m_chd(chd)
+ , m_hunkbytes(hunkbytes)
+ , m_lossy(lossy)
{
}
@@ -607,10 +606,6 @@ void chd_codec::configure(int param, void *config)
// CHD COMPRESSOR
//**************************************************************************
-//-------------------------------------------------
-// chd_compressor - constructor
-//-------------------------------------------------
-
chd_compressor::chd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
: chd_codec(chd, hunkbytes, lossy)
{
@@ -622,15 +617,16 @@ chd_compressor::chd_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
// CHD DECOMPRESSOR
//**************************************************************************
-//-------------------------------------------------
-// chd_decompressor - constructor
-//-------------------------------------------------
-
chd_decompressor::chd_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
: chd_codec(chd, hunkbytes, lossy)
{
}
+void chd_decompressor::process(const uint8_t *src, uint32_t complen)
+{
+ throw std::error_condition(chd_file::error::UNSUPPORTED_FORMAT);
+}
+
//**************************************************************************
@@ -668,7 +664,7 @@ chd_decompressor::ptr chd_codec_list::new_decompressor(chd_codec_type type, chd_
// corresponds to a supported codec
//-------------------------------------------------
-bool chd_codec_list::codec_exists(chd_codec_type type)
+bool chd_codec_list::codec_exists(chd_codec_type type) noexcept
{
// find in the list and construct the class
return bool(find_in_list(type));
@@ -680,7 +676,7 @@ bool chd_codec_list::codec_exists(chd_codec_type type)
// codec
//-------------------------------------------------
-const char *chd_codec_list::codec_name(chd_codec_type type)
+const char *chd_codec_list::codec_name(chd_codec_type type) noexcept
{
// find in the list and construct the class
const codec_entry *entry = find_in_list(type);
@@ -1588,8 +1584,8 @@ void chd_flac_decompressor::decompress(const uint8_t *src, uint32_t complen, uin
//-------------------------------------------------
chd_cd_flac_compressor::chd_cd_flac_compressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_compressor(chd, hunkbytes, lossy),
- m_buffer(hunkbytes)
+ : chd_compressor(chd, hunkbytes, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
@@ -1717,8 +1713,8 @@ uint32_t chd_cd_flac_compressor::blocksize(uint32_t bytes)
*/
chd_cd_flac_decompressor::chd_cd_flac_decompressor(chd_file &chd, uint32_t hunkbytes, bool lossy)
- : chd_decompressor(chd, hunkbytes, lossy),
- m_buffer(hunkbytes)
+ : chd_decompressor(chd, hunkbytes, lossy)
+ , m_buffer(hunkbytes)
{
// make sure the CHD's hunk size is an even multiple of the frame size
if (hunkbytes % cdrom_file::FRAME_SIZE != 0)
@@ -1943,21 +1939,13 @@ chd_avhuff_decompressor::chd_avhuff_decompressor(chd_file &chd, uint32_t hunkbyt
{
}
-/**
- * @fn void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
- *
- * @brief -------------------------------------------------
- * decompress - decompress data using the A/V codec
- * -------------------------------------------------.
- *
- * @exception CHDERR_DECOMPRESSION_ERROR Thrown when a chderr decompression error error
- * condition occurs.
- *
- * @param src Source for the.
- * @param complen The complen.
- * @param [in,out] dest If non-null, destination for the.
- * @param destlen The destlen.
- */
+void chd_avhuff_decompressor::process(const uint8_t *src, uint32_t complen)
+{
+ // decode the audio and video
+ avhuff_error averr = m_decoder.decode_data(src, complen, nullptr);
+ if (averr != AVHERR_NONE)
+ throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
+}
void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen)
{
@@ -1967,12 +1955,9 @@ void chd_avhuff_decompressor::decompress(const uint8_t *src, uint32_t complen, u
throw std::error_condition(chd_file::error::DECOMPRESSION_ERROR);
// pad short frames with 0
- if (dest != nullptr)
- {
- int size = avhuff_encoder::raw_data_size(dest);
- if (size < destlen)
- memset(dest + size, 0, destlen - size);
- }
+ auto const size = avhuff_encoder::raw_data_size(dest);
+ if (size < destlen)
+ memset(dest + size, 0, destlen - size);
}
/**
diff --git a/src/lib/util/chdcodec.h b/src/lib/util/chdcodec.h
index c3234ea600d..c477333544f 100644
--- a/src/lib/util/chdcodec.h
+++ b/src/lib/util/chdcodec.h
@@ -2,8 +2,6 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- chdcodec.h
-
Codecs used by the CHD format
***************************************************************************/
@@ -89,6 +87,7 @@ public:
using ptr = std::unique_ptr<chd_decompressor>;
// implementation
+ virtual void process(const uint8_t *src, uint32_t complen);
virtual void decompress(const uint8_t *src, uint32_t complen, uint8_t *dest, uint32_t destlen) = 0;
};
@@ -104,8 +103,8 @@ public:
static chd_decompressor::ptr new_decompressor(chd_codec_type type, chd_file &file);
// utilities
- static bool codec_exists(chd_codec_type type);
- static const char *codec_name(chd_codec_type type);
+ static bool codec_exists(chd_codec_type type) noexcept;
+ static const char *codec_name(chd_codec_type type) noexcept;
};
diff --git a/src/lib/util/corefile.cpp b/src/lib/util/corefile.cpp
index 3d5c705ab86..74a742b0306 100644
--- a/src/lib/util/corefile.cpp
+++ b/src/lib/util/corefile.cpp
@@ -48,13 +48,13 @@ public:
virtual std::error_condition tell(std::uint64_t &result) noexcept override { return m_file.tell(result); }
virtual std::error_condition length(std::uint64_t &result) noexcept override { return m_file.length(result); }
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.read(buffer, length, actual); }
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.read_at(offset, buffer, length, actual); }
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.read_some(buffer, length, actual); }
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.read_some_at(offset, buffer, length, actual); }
virtual std::error_condition finalize() noexcept override { return m_file.finalize(); }
virtual std::error_condition flush() noexcept override { return m_file.flush(); }
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.write(buffer, length, actual); }
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.write_at(offset, buffer, length, actual); }
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.write_some(buffer, length, actual); }
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override { return m_file.write_some_at(offset, buffer, length, actual); }
virtual bool eof() const override { return m_file.eof(); }
@@ -167,13 +167,13 @@ public:
~core_in_memory_file() override { purge(); }
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override;
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override;
virtual std::error_condition finalize() noexcept override { return std::error_condition(); }
virtual std::error_condition flush() noexcept override { clear_putback(); return std::error_condition(); }
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override { actual = 0; return std::errc::bad_file_descriptor; }
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override { actual = 0; return std::errc::bad_file_descriptor; }
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override { actual = 0; return std::errc::bad_file_descriptor; }
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override { actual = 0; return std::errc::bad_file_descriptor; }
void const *buffer() const { return m_data; }
@@ -217,13 +217,13 @@ public:
}
~core_osd_file() override;
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override;
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override;
virtual std::error_condition finalize() noexcept override;
virtual std::error_condition flush() noexcept override;
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override;
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override;
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override;
virtual std::error_condition truncate(std::uint64_t offset) override;
@@ -260,9 +260,8 @@ int core_text_file::getc()
{
if (!pos)
{
- std::size_t readlen;
std::uint8_t bom[4];
- read(bom, 4, readlen);
+ auto const [err, readlen] = read(*this, bom, 4); // FIXME: check for errors
if (readlen == 4)
{
if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf)
@@ -303,15 +302,14 @@ int core_text_file::getc()
// fetch the next character
// FIXME: all of this plays fast and loose with error checking and seeks backwards far too frequently
char16_t utf16_buffer[UTF16_CHAR_MAX];
- auto uchar = char32_t(~0);
+ char32_t uchar = ~char32_t(0);
switch (m_text_type)
{
default:
case text_file_type::OSD:
{
char default_buffer[16];
- std::size_t readlen;
- read(default_buffer, sizeof(default_buffer), readlen);
+ auto const [err, readlen] = read(*this, default_buffer, sizeof(default_buffer));
if (readlen > 0)
{
auto const charlen = osd_uchar_from_osdchar(&uchar, default_buffer, readlen / sizeof(default_buffer[0]));
@@ -323,8 +321,7 @@ int core_text_file::getc()
case text_file_type::UTF8:
{
char utf8_buffer[UTF8_CHAR_MAX];
- std::size_t readlen;
- read(utf8_buffer, sizeof(utf8_buffer), readlen);
+ auto const [err, readlen] = read(*this, utf8_buffer, sizeof(utf8_buffer));
if (readlen > 0)
{
auto const charlen = uchar_from_utf8(&uchar, utf8_buffer, readlen / sizeof(utf8_buffer[0]));
@@ -335,8 +332,7 @@ int core_text_file::getc()
case text_file_type::UTF16BE:
{
- std::size_t readlen;
- read(utf16_buffer, sizeof(utf16_buffer), readlen);
+ auto const [err, readlen] = read(*this, utf16_buffer, sizeof(utf16_buffer));
if (readlen > 0)
{
auto const charlen = uchar_from_utf16be(&uchar, utf16_buffer, readlen / sizeof(utf16_buffer[0]));
@@ -347,8 +343,7 @@ int core_text_file::getc()
case text_file_type::UTF16LE:
{
- std::size_t readlen;
- read(utf16_buffer, sizeof(utf16_buffer), readlen);
+ auto const [err, readlen] = read(*this, utf16_buffer, sizeof(utf16_buffer));
if (readlen > 0)
{
auto const charlen = uchar_from_utf16le(&uchar, utf16_buffer, readlen / sizeof(utf16_buffer[0]));
@@ -360,8 +355,7 @@ int core_text_file::getc()
case text_file_type::UTF32BE:
{
// FIXME: deal with read returning short
- std::size_t readlen;
- read(&uchar, sizeof(uchar), readlen);
+ auto const [err, readlen] = read(*this, &uchar, sizeof(uchar));
if (sizeof(uchar) == readlen)
uchar = big_endianize_int32(uchar);
}
@@ -370,8 +364,7 @@ int core_text_file::getc()
case text_file_type::UTF32LE:
{
// FIXME: deal with read returning short
- std::size_t readlen;
- read(&uchar, sizeof(uchar), readlen);
+ auto const [err, readlen] = read(*this, &uchar, sizeof(uchar));
if (sizeof(uchar) == readlen)
uchar = little_endianize_int32(uchar);
}
@@ -467,7 +460,7 @@ char *core_text_file::gets(char *s, int n)
int core_text_file::puts(std::string_view s)
{
- // TODO: what to do about write errors or short writes (interrupted)?
+ // TODO: what to do about write errors?
// The API doesn't lend itself to reporting the error as the return
// value includes extra bytes inserted like the UTF-8 marker and
// carriage returns.
@@ -511,8 +504,7 @@ int core_text_file::puts(std::string_view s)
// if we overflow, break into chunks
if (pconvbuf >= convbuf + std::size(convbuf) - 10)
{
- std::size_t written;
- write(convbuf, pconvbuf - convbuf, written); // FIXME: error ignored here
+ auto const [err, written] = write(*this, convbuf, pconvbuf - convbuf); // FIXME: error ignored here
count += written;
pconvbuf = convbuf;
}
@@ -521,8 +513,7 @@ int core_text_file::puts(std::string_view s)
// final flush
if (pconvbuf != convbuf)
{
- std::size_t written;
- write(convbuf, pconvbuf - convbuf, written); // FIXME: error ignored here
+ auto const [err, written] = write(*this, convbuf, pconvbuf - convbuf); // FIXME: error ignored here
count += written;
}
@@ -646,7 +637,7 @@ std::size_t core_basic_file::safe_buffer_copy(
// read - read from a file
//-------------------------------------------------
-std::error_condition core_in_memory_file::read(void *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_in_memory_file::read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept
{
clear_putback();
@@ -659,7 +650,7 @@ std::error_condition core_in_memory_file::read(void *buffer, std::size_t length,
return std::error_condition();
}
-std::error_condition core_in_memory_file::read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_in_memory_file::read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept
{
clear_putback();
@@ -705,17 +696,17 @@ core_osd_file::~core_osd_file()
// read - read from a file
//-------------------------------------------------
-std::error_condition core_osd_file::read(void *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_osd_file::read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept
{
// since osd_file works like pread/pwrite, implement in terms of read_at
// core_osd_file is declared final, so a derived class can't interfere
- std::error_condition err = read_at(index(), buffer, length, actual);
+ std::error_condition err = read_some_at(index(), buffer, length, actual);
add_offset(actual);
return err;
}
-std::error_condition core_osd_file::read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_osd_file::read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept
{
if (!m_file)
{
@@ -750,18 +741,12 @@ std::error_condition core_osd_file::read_at(std::uint64_t offset, void *buffer,
}
else
{
- // read the remainder directly from the file
- do
- {
- // may need to split into chunks if size_t is larger than 32 bits
- std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length - actual);
- std::uint32_t bytes_read;
- err = m_file->read(reinterpret_cast<std::uint8_t *>(buffer) + actual, offset + actual, chunk, bytes_read);
- if (err || !bytes_read)
- break;
+ // read the remainder directly from the file - may need to return short if size_t is larger than 32 bits
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length - actual);
+ std::uint32_t bytes_read;
+ err = m_file->read(reinterpret_cast<std::uint8_t *>(buffer) + actual, offset + actual, chunk, bytes_read);
+ if (!err)
actual += bytes_read;
- }
- while (actual < length);
}
}
@@ -774,17 +759,17 @@ std::error_condition core_osd_file::read_at(std::uint64_t offset, void *buffer,
// write - write to a file
//-------------------------------------------------
-std::error_condition core_osd_file::write(void const *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_osd_file::write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept
{
// since osd_file works like pread/pwrite, implement in terms of write_at
// core_osd_file is declared final, so a derived class can't interfere
- std::error_condition err = write_at(index(), buffer, length, actual);
+ std::error_condition err = write_some_at(index(), buffer, length, actual);
add_offset(actual);
return err;
}
-std::error_condition core_osd_file::write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept
+std::error_condition core_osd_file::write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept
{
// flush any buffered char
clear_putback();
@@ -792,24 +777,23 @@ std::error_condition core_osd_file::write_at(std::uint64_t offset, void const *b
// invalidate any buffered data
m_bufferbytes = 0U;
- // do the write - may need to split into chunks if size_t is larger than 32 bits
- actual = 0U;
- while (length)
+ // do the write - may need to return short if size_t is larger than 32 bits
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t bytes_written;
+ std::error_condition err = m_file->write(buffer, offset, chunk, bytes_written);
+ if (err)
{
// bytes written not valid on error
- std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
- std::uint32_t bytes_written;
- std::error_condition err = m_file->write(buffer, offset, chunk, bytes_written);
- if (err)
- return err;
+ actual = 0U;
+ }
+ else
+ {
assert(chunk >= bytes_written);
offset += bytes_written;
- buffer = reinterpret_cast<std::uint8_t const *>(buffer) + bytes_written;
- length -= bytes_written;
- actual += bytes_written;
+ actual = bytes_written;
set_size((std::max)(size(), offset));
}
- return std::error_condition();
+ return err;
}
@@ -968,7 +952,7 @@ core_file::~core_file()
// pointer
//-------------------------------------------------
-std::error_condition core_file::load(std::string_view filename, void **data, std::uint32_t &length) noexcept
+std::error_condition core_file::load(std::string_view filename, void **data, std::size_t &length) noexcept
{
std::error_condition err;
@@ -983,20 +967,20 @@ std::error_condition core_file::load(std::string_view filename, void **data, std
err = file->length(size);
if (err)
return err;
- else if (std::uint32_t(size) != size) // TODO: change interface to use size_t rather than uint32_t for output size
+ else if (std::size_t(size) != size)
return std::errc::file_too_large;
// allocate memory
*data = std::malloc(std::size_t(size));
if (!*data)
return std::errc::not_enough_memory;
- length = std::uint32_t(size);
+ length = std::size_t(size);
// read the data
if (size)
{
std::size_t actual;
- err = file->read(*data, std::size_t(size), actual);
+ std::tie(err, actual) = read(*file, *data, std::size_t(size));
if (err || (size != actual))
{
std::free(*data);
@@ -1004,7 +988,7 @@ std::error_condition core_file::load(std::string_view filename, void **data, std
if (err)
return err;
else
- return std::errc::io_error; // TODO: revisit this error code - either interrupted by an async signal or file truncated out from under us
+ return std::errc::io_error; // TODO: revisit this error code - file truncated out from under us
}
}
@@ -1038,14 +1022,14 @@ std::error_condition core_file::load(std::string_view filename, std::vector<uint
if (size)
{
std::size_t actual;
- err = file->read(&data[0], std::size_t(size), actual);
+ std::tie(err, actual) = read(*file, &data[0], std::size_t(size));
if (err || (size != actual))
{
data.clear();
if (err)
return err;
else
- return std::errc::io_error; // TODO: revisit this error code - either interrupted by an async signal or file truncated out from under us
+ return std::errc::io_error; // TODO: revisit this error code - file truncated out from under us
}
}
diff --git a/src/lib/util/corefile.h b/src/lib/util/corefile.h
index 315645d4e2c..fda5015d8ba 100644
--- a/src/lib/util/corefile.h
+++ b/src/lib/util/corefile.h
@@ -77,7 +77,7 @@ public:
virtual char *gets(char *s, int n) = 0;
// open a file with the specified filename, read it into memory, and return a pointer
- static std::error_condition load(std::string_view filename, void **data, std::uint32_t &length) noexcept;
+ static std::error_condition load(std::string_view filename, void **data, std::size_t &length) noexcept;
static std::error_condition load(std::string_view filename, std::vector<uint8_t> &data) noexcept;
diff --git a/src/lib/util/corestr.cpp b/src/lib/util/corestr.cpp
index 586f56c1aa3..9fa0a3990a2 100644
--- a/src/lib/util/corestr.cpp
+++ b/src/lib/util/corestr.cpp
@@ -15,6 +15,7 @@
#include <memory>
#include <cctype>
+#include <cstdint>
#include <cstdlib>
diff --git a/src/lib/util/coretmpl.h b/src/lib/util/coretmpl.h
index 55313a4a0f5..87f8cfbf09e 100644
--- a/src/lib/util/coretmpl.h
+++ b/src/lib/util/coretmpl.h
@@ -654,7 +654,7 @@ template <typename T, typename U, typename... V> constexpr T bitswap(T val, U b,
/// bit of the input. Specify bits in the order they should appear in
/// the output field, from most significant to least significant.
/// \return The extracted bits packed into a right-aligned field.
-template <unsigned B, typename T, typename... U> T bitswap(T val, U... b) noexcept
+template <unsigned B, typename T, typename... U> constexpr T bitswap(T val, U... b) noexcept
{
static_assert(sizeof...(b) == B, "wrong number of bits");
static_assert((sizeof(std::remove_reference_t<T>) * 8) >= B, "return type too small for result");
diff --git a/src/lib/util/coreutil.cpp b/src/lib/util/coreutil.cpp
index 94ec6dec273..cebbceb037e 100644
--- a/src/lib/util/coreutil.cpp
+++ b/src/lib/util/coreutil.cpp
@@ -10,7 +10,6 @@
#include "coreutil.h"
#include <cassert>
-#include <zlib.h>
/***************************************************************************
@@ -55,14 +54,3 @@ uint32_t bcd_2_dec(uint32_t a)
}
return result;
}
-
-
-
-/***************************************************************************
- MISC
-***************************************************************************/
-
-uint32_t core_crc32(uint32_t crc, const uint8_t *buf, uint32_t len)
-{
- return crc32(crc, buf, len);
-}
diff --git a/src/lib/util/coreutil.h b/src/lib/util/coreutil.h
index 1f487232619..813deb27a83 100644
--- a/src/lib/util/coreutil.h
+++ b/src/lib/util/coreutil.h
@@ -72,11 +72,4 @@ inline int gregorian_days_in_month(int month, int year)
return result;
}
-
-/***************************************************************************
- MISC
-***************************************************************************/
-
-uint32_t core_crc32(uint32_t crc, const uint8_t *buf, uint32_t len);
-
#endif // MAME_UTIL_COREUTIL_H
diff --git a/src/lib/util/delegate.cpp b/src/lib/util/delegate.cpp
index 8949f90f146..fb2fd4e2091 100644
--- a/src/lib/util/delegate.cpp
+++ b/src/lib/util/delegate.cpp
@@ -10,6 +10,8 @@
#include "delegate.h"
+#include "mfpresolve.h"
+
#include <cstdio>
#include <sstream>
@@ -70,31 +72,9 @@ const delegate_mfp_compatible::raw_mfp_data delegate_mfp_compatible::s_null_mfp
delegate_generic_function delegate_mfp_itanium::convert_to_generic(delegate_generic_class *&object) const
{
- // apply the "this" delta to the object first - the value is shifted to the left one bit position for the ARM-like variant
- LOG("Input this=%p ptr=%p adj=%ld ", reinterpret_cast<void const *>(object), reinterpret_cast<void const *>(m_function), long(m_this_delta));
- object = reinterpret_cast<delegate_generic_class *>(
- reinterpret_cast<std::uint8_t *>(object) + (m_this_delta >> ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 1 : 0)));
- LOG("Calculated this=%p ", reinterpret_cast<void const *>(object));
-
- // test the virtual member function flag - it's the low bit of either the ptr or adj field, depending on the variant
- if ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? !(m_this_delta & 1) : !(m_function & 1))
- {
- // conventional function pointer
- LOG("ptr=%p\n", reinterpret_cast<void const *>(m_function));
- return reinterpret_cast<delegate_generic_function>(m_function);
- }
- else
- {
- // byte index into the vtable to the function
- std::uint8_t const *const vtable_ptr = *reinterpret_cast<std::uint8_t const *const *>(object) + m_function - ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 0 : 1);
- delegate_generic_function result;
- if (MAME_ABI_CXX_VTABLE_FNDESC)
- result = reinterpret_cast<delegate_generic_function>(uintptr_t(vtable_ptr));
- else
- result = *reinterpret_cast<delegate_generic_function const *>(vtable_ptr);
- LOG("ptr=%p (vtable)\n", reinterpret_cast<void const *>(result));
- return result;
- }
+ auto const [entrypoint, adjusted] = resolve_member_function_itanium(m_function, m_this_delta, object);
+ object = reinterpret_cast<delegate_generic_class *>(adjusted);
+ return reinterpret_cast<delegate_generic_function>(entrypoint);
}
@@ -107,181 +87,9 @@ delegate_generic_function delegate_mfp_itanium::convert_to_generic(delegate_gene
delegate_generic_function delegate_mfp_msvc::adjust_this_pointer(delegate_generic_class *&object) const
{
- LOG("Input this=%p ", reinterpret_cast<void const *>(object));
- if (sizeof(single_base_equiv) < m_size)
- LOG("thisdelta=%d ", m_this_delta);
- if (sizeof(unknown_base_equiv) == m_size)
- LOG("vptrdelta=%d vindex=%d ", m_vptr_offs, m_vt_index);
- std::uint8_t *byteptr = reinterpret_cast<std::uint8_t *>(object);
-
- // test for pointer to member function cast across virtual inheritance relationship
- if ((sizeof(unknown_base_equiv) == m_size) && m_vt_index)
- {
- // add offset from "this" pointer to location of vptr, and add offset to virtual base from vtable
- byteptr += m_vptr_offs;
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(byteptr);
- byteptr += *reinterpret_cast<int const *>(vptr + m_vt_index);
- }
-
- // add "this" pointer displacement if present in the pointer to member function
- if (sizeof(single_base_equiv) < m_size)
- byteptr += m_this_delta;
- LOG("Calculated this=%p\n", reinterpret_cast<void const *>(byteptr));
- object = reinterpret_cast<delegate_generic_class *>(byteptr);
-
- // walk past recognisable thunks
-#if defined(__x86_64__) || defined(_M_X64)
- std::uint8_t const *func = reinterpret_cast<std::uint8_t const *>(m_function);
- while (true)
- {
- // Assumes Windows calling convention, and doesn't consider that
- // the "this" pointer could be in RDX if RCX is a pointer to
- // space for an oversize scalar result. Since the result area
- // is uninitialised on entry, you won't see something that looks
- // like a vtable dispatch through RCX in this case - it won't
- // behave badly, it just won't bypass virtual call thunks in the
- // rare situations where the return type is an oversize scalar.
- if (0xe9 == func[0])
- {
- // relative jump with 32-bit displacement (typically a resolved PLT entry)
- LOG("Found relative jump at %p ", func);
- func += std::ptrdiff_t(5) + *reinterpret_cast<std::int32_t const *>(func + 1);
- LOG("redirecting to %p\n", func);
- continue;
- }
- else if ((0x48 == func[0]) && (0x8b == func[1]) && (0x01 == func[2]))
- {
- if ((0xff == func[3]) && ((0x20 == func[4]) || (0x60 == func[4]) || (0xa0 == func[4])))
- {
- // MSVC virtual function call thunk - mov rax,QWORD PTR [rcx] ; jmp QWORD PTR [rax+...]
- LOG("Found virtual member function thunk at %p ", func);
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
- if (0x20 == func[4]) // no displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
- else if (0x60 == func[4]) // 8-bit displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 5));
- else // 32-bit displacement
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 5));
- LOG("redirecting to %p\n", func);
- continue;
- }
- else if ((0x48 == func[3]) && (0x8b == func[4]))
- {
- // clang virtual function call thunk - mov rax,QWORD PTR [rcx] ; mov rax,QWORD PTR [rax+...] ; jmp rax
- if ((0x00 == func[5]) && (0x48 == func[6]) && (0xff == func[7]) && (0xe0 == func[8]))
- {
- // no displacement
- LOG("Found virtual member function thunk at %p ", func);
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
- LOG("redirecting to %p\n", func);
- continue;
- }
- else if ((0x40 == func[5]) && (0x48 == func[7]) && (0xff == func[8]) && (0xe0 == func[9]))
- {
- // 8-bit displacement
- LOG("Found virtual member function thunk at %p ", func);
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 6));
- LOG("redirecting to %p\n", func);
- continue;
- }
- else if ((0x80 == func[5]) && (0x48 == func[10]) && (0xff == func[11]) && (0xe0 == func[12]))
- {
- // 32-bit displacement
- LOG("Found virtual member function thunk at %p ", func);
- std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
- func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 6));
- LOG("redirecting to %p\n", func);
- continue;
- }
- }
- }
-
- // clang uses unoptimised thunks if optimisation is disabled
- // Without optimisation, clang produces thunks like:
- // 50 push rax
- // 48 89 0c 24 mov QWORD PTR [rsp],rcx
- // 48 8b 0c 24 mov rcx,QWORD PTR [rsp]
- // 48 8b 01 mov rax,QWORD PTR [rcx]
- // 48 8b 80 xx xx xx xx mov rax,QWORD PTR [rax+...]
- // 41 5a pop r10
- // 48 ff e0 jmp rax
- // Trying to decode these thunks likely isn't worth the effort.
- // Chasing performance in unoptimised builds isn't very useful,
- // and the format of these thunks may be fragile.
-
- // not something we can easily bypass
- break;
- }
- return reinterpret_cast<delegate_generic_function>(std::uintptr_t(func));
-#elif defined(__aarch64__) || defined(_M_ARM64)
- std::uint32_t const *func = reinterpret_cast<std::uint32_t const *>(m_function);
- while (true)
- {
- // Assumes little Endian mode. Instructions are always stored
- // in little Endian format on AArch64, so if big Endian mode is
- // to be supported, the values need to be swapped.
- if ((0x90000010 == (func[0] & 0x9f00001f)) && (0x91000210 == (func[1] & 0xffc003ff)) && (0xd61f0200 == func[2]))
- {
- // page-relative jump with +/-4GB reach - adrp xip0,... ; add xip0,xip0,#... ; br xip0
- LOG("Found page-relative jump at %p ", func);
- std::int64_t const page =
- (std::uint64_t(func[0] & 0x60000000) >> 17) |
- (std::uint64_t(func[0] & 0x00ffffe0) << 9) |
- ((func[0] & 0x00800000) ? (~std::uint64_t(0) << 33) : 0);
- std::uint32_t const offset = (func[1] & 0x003ffc00) >> 10;
- func = reinterpret_cast<std::uint32_t const *>(((std::uintptr_t(func) + page) & (~std::uintptr_t(0) << 12)) + offset);
- LOG("redirecting to %p\n", func);
- }
- else if ((0xf9400010 == func[0]) && (0xf9400210 == (func[1] & 0xffc003ff)) && (0xd61f0200 == func[2]))
- {
- // virtual function call thunk - ldr xip0,[x0] ; ldr xip0,[x0,#...] ; br xip0
- LOG("Found virtual member function thunk at %p ", func);
- std::uint32_t const *const *const vptr = *reinterpret_cast<std::uint32_t const *const *const *>(object);
- func = vptr[(func[1] & 0x003ffc00) >> 10];
- LOG("redirecting to %p\n", func);
- }
- else
- {
- // not something we can easily bypass
- break;
- }
-
- // clang uses horribly sub-optimal thunks for AArch64
- // Without optimisation, clang produces thunks like:
- // d10143ff sub sp,sp,#80
- // f90027e7 str x7,[sp,#72]
- // f90023e6 str x6,[sp,#64]
- // f9001fe5 str x5,[sp,#56]
- // f9001be4 str x4,[sp,#48]
- // f90017e3 str x3,[sp,#40]
- // f90013e2 str x2,[sp,#32]
- // f9000fe1 str x1,[sp,#24]
- // f90007e0 str x0,[sp,#8]
- // f94007e0 ldr x0,[sp,#8]
- // f9400009 ldr x9,[x0]
- // f9400129 ldr x9,[x9,#...]
- // 910143ff add sp,sp,#80
- // d61f0120 br x9
- // With optimisation, clang produces thunks like:
- // d10103ff sub sp,sp,#64
- // a9008be1 stp x1,x2,[sp,#8]
- // a90193e3 stp x3,x4,[sp,#24]
- // a9029be5 stp x5,x6,[sp,#40]
- // f9001fe7 str x7,[sp,#56]
- // f9400009 ldr x9,[x0]
- // f9400129 ldr x9,[x9,#...]
- // 910103ff add sp,sp,#64
- // d61f0120 br x9
- // It's more effort than it's worth to try decoding these
- // thunks.
-
- }
- return reinterpret_cast<delegate_generic_function>(std::uintptr_t(func));
-#else
- return reinterpret_cast<delegate_generic_function>(m_function);
-#endif
+ auto const [entrypoint, adjusted] = resolve_member_function_msvc(&m_function, m_size, object);
+ object = reinterpret_cast<delegate_generic_class *>(adjusted);
+ return reinterpret_cast<delegate_generic_function>(entrypoint);
}
} // namespace util::detail
diff --git a/src/lib/util/dvdrom.cpp b/src/lib/util/dvdrom.cpp
index 36dc29e7215..0b2379ef7e6 100644
--- a/src/lib/util/dvdrom.cpp
+++ b/src/lib/util/dvdrom.cpp
@@ -58,8 +58,8 @@ dvdrom_file::dvdrom_file(chd_file *_chd)
throw nullptr;
/* check it's actually a DVD-ROM */
- if (!chd->is_dvd())
- throw nullptr;
+ if (std::error_condition err = chd->check_is_dvd())
+ throw err;
sector_count = chd->unit_count();
}
diff --git a/src/lib/util/flac.cpp b/src/lib/util/flac.cpp
index 4d6a3bca81b..d3110ca0d38 100644
--- a/src/lib/util/flac.cpp
+++ b/src/lib/util/flac.cpp
@@ -18,6 +18,7 @@
#include <cstring>
#include <iterator>
#include <new>
+#include <tuple>
//**************************************************************************
@@ -84,6 +85,8 @@ bool flac_encoder::reset()
FLAC__stream_encoder_set_blocksize(m_encoder, m_block_size);
// re-start processing
+ if (m_file)
+ return (FLAC__stream_encoder_init_stream(m_encoder, write_callback_static, seek_callback_static, tell_callback_static, nullptr, this) == FLAC__STREAM_ENCODER_INIT_STATUS_OK);
return (FLAC__stream_encoder_init_stream(m_encoder, write_callback_static, nullptr, nullptr, nullptr, this) == FLAC__STREAM_ENCODER_INIT_STATUS_OK);
}
@@ -266,8 +269,7 @@ FLAC__StreamEncoderWriteStatus flac_encoder::write_callback(const FLAC__byte buf
int count = bytes - offset;
if (m_file)
{
- size_t actual;
- m_file->write(buffer, count, actual); // TODO: check for errors
+ /*auto const [err, actual] =*/ write(*m_file, buffer, count); // FIXME: check for errors
}
else
{
@@ -281,6 +283,38 @@ FLAC__StreamEncoderWriteStatus flac_encoder::write_callback(const FLAC__byte buf
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
+FLAC__StreamEncoderSeekStatus flac_encoder::seek_callback_static(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
+{
+ return reinterpret_cast<flac_encoder *>(client_data)->seek_callback(absolute_byte_offset);
+}
+
+FLAC__StreamEncoderSeekStatus flac_encoder::seek_callback(FLAC__uint64 absolute_byte_offset)
+{
+ if (m_file)
+ {
+ if (!m_file->seek(absolute_byte_offset, SEEK_SET))
+ return FLAC__STREAM_ENCODER_SEEK_STATUS_OK;
+ return FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR;
+ }
+ return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
+}
+
+FLAC__StreamEncoderTellStatus flac_encoder::tell_callback_static(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
+{
+ return reinterpret_cast<flac_encoder *>(client_data)->tell_callback(absolute_byte_offset);
+}
+
+FLAC__StreamEncoderTellStatus flac_encoder::tell_callback(FLAC__uint64 *absolute_byte_offset)
+{
+ if (m_file)
+ {
+ if (!m_file->tell(*absolute_byte_offset))
+ return FLAC__STREAM_ENCODER_TELL_STATUS_OK;
+ return FLAC__STREAM_ENCODER_TELL_STATUS_ERROR;
+ }
+ return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
+}
+
//**************************************************************************
@@ -537,7 +571,8 @@ FLAC__StreamDecoderReadStatus flac_decoder::read_callback(FLAC__byte buffer[], s
if (m_file) // if a file, just read
{
- m_file->read(buffer, expected, *bytes); // TODO: check for errors
+ std::error_condition err;
+ std::tie(err, *bytes) = read(*m_file, buffer, expected); // FIXME: check for errors
}
else // otherwise, copy from memory
{
@@ -601,12 +636,12 @@ FLAC__StreamDecoderTellStatus flac_decoder::tell_callback_static(const FLAC__Str
// stream
//-------------------------------------------------
-FLAC__StreamDecoderWriteStatus flac_decoder::write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
+FLAC__StreamDecoderWriteStatus flac_decoder::write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
{
return reinterpret_cast<flac_decoder *>(client_data)->write_callback(frame, buffer);
}
-FLAC__StreamDecoderWriteStatus flac_decoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+FLAC__StreamDecoderWriteStatus flac_decoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[])
{
assert(frame->header.channels == channels());
@@ -633,7 +668,7 @@ FLAC__StreamDecoderWriteStatus flac_decoder::write_callback(const ::FLAC__Frame
}
}
-template <flac_decoder::DECODE_MODE Mode, bool SwapEndian> FLAC__StreamDecoderWriteStatus flac_decoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[])
+template <flac_decoder::DECODE_MODE Mode, bool SwapEndian> FLAC__StreamDecoderWriteStatus flac_decoder::write_callback(const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[])
{
const int blocksize = frame->header.blocksize;
const int shift = (Mode == SCALE_DOWN) ? frame->header.bits_per_sample - m_bits_per_sample : (Mode == SCALE_UP) ? m_bits_per_sample - frame->header.bits_per_sample : 0;
diff --git a/src/lib/util/flac.h b/src/lib/util/flac.h
index c3fee4b574b..be3a0a8ac96 100644
--- a/src/lib/util/flac.h
+++ b/src/lib/util/flac.h
@@ -62,6 +62,10 @@ private:
void init_common();
static FLAC__StreamEncoderWriteStatus write_callback_static(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);
+ static FLAC__StreamEncoderSeekStatus seek_callback_static(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
+ FLAC__StreamEncoderSeekStatus seek_callback(FLAC__uint64 absolute_byte_offset);
+ static FLAC__StreamEncoderTellStatus tell_callback_static(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
+ FLAC__StreamEncoderTellStatus tell_callback(FLAC__uint64 *absolute_byte_offset);
// internal state
FLAC__StreamEncoder * m_encoder; // actual encoder
@@ -123,9 +127,9 @@ private:
FLAC__StreamDecoderReadStatus read_callback(FLAC__byte buffer[], size_t *bytes);
static void metadata_callback_static(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static FLAC__StreamDecoderTellStatus tell_callback_static(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
- static FLAC__StreamDecoderWriteStatus write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
- FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
- template <DECODE_MODE Mode, bool SwapEndian> FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 * const buffer[]);
+ static FLAC__StreamDecoderWriteStatus write_callback_static(const FLAC__StreamDecoder *decoder, const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data);
+ FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[]);
+ template <DECODE_MODE Mode, bool SwapEndian> FLAC__StreamDecoderWriteStatus write_callback(const ::FLAC__Frame *frame, const FLAC__int32 *const buffer[]);
static void error_callback_static(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
// output state
diff --git a/src/lib/util/harddisk.cpp b/src/lib/util/harddisk.cpp
index 6eb12b38091..266e5d25a2b 100644
--- a/src/lib/util/harddisk.cpp
+++ b/src/lib/util/harddisk.cpp
@@ -16,6 +16,7 @@
#include "osdcore.h"
#include <cstdlib>
+#include <tuple>
/*-------------------------------------------------
@@ -118,7 +119,7 @@ bool hard_disk_file::read(uint32_t lbasector, void *buffer)
size_t actual = 0;
std::error_condition err = fhandle->seek(fileoffset + (lbasector * hdinfo.sectorbytes), SEEK_SET);
if (!err)
- err = fhandle->read(buffer, hdinfo.sectorbytes, actual);
+ std::tie(err, actual) = util::read(*fhandle, buffer, hdinfo.sectorbytes);
return !err && (actual == hdinfo.sectorbytes);
}
}
@@ -151,8 +152,8 @@ bool hard_disk_file::write(uint32_t lbasector, const void *buffer)
size_t actual = 0;
std::error_condition err = fhandle->seek(fileoffset + (lbasector * hdinfo.sectorbytes), SEEK_SET);
if (!err)
- err = fhandle->write(buffer, hdinfo.sectorbytes, actual);
- return !err && (actual == hdinfo.sectorbytes);
+ std::tie(err, actual) = util::write(*fhandle, buffer, hdinfo.sectorbytes);
+ return !err;
}
}
diff --git a/src/lib/util/hash.cpp b/src/lib/util/hash.cpp
index 9100ff6abde..f2c528e9b22 100644
--- a/src/lib/util/hash.cpp
+++ b/src/lib/util/hash.cpp
@@ -410,14 +410,13 @@ std::error_condition hash_collection::compute(random_read &stream, uint64_t offs
unsigned const chunk_length = std::min(length, sizeof(buffer));
// read one chunk
- std::size_t bytes_read;
- std::error_condition err = stream.read_at(offset, buffer, chunk_length, bytes_read);
+ auto const [err, bytes_read] = read_at(stream, offset, buffer, chunk_length);
if (err)
return err;
if (!bytes_read) // EOF?
break;
offset += bytes_read;
- length -= chunk_length;
+ length -= bytes_read;
// append the chunk
creator->append(buffer, bytes_read);
diff --git a/src/lib/util/ioprocs.cpp b/src/lib/util/ioprocs.cpp
index 0477f1efae1..687968f85ee 100644
--- a/src/lib/util/ioprocs.cpp
+++ b/src/lib/util/ioprocs.cpp
@@ -20,6 +20,7 @@
#include <cstring>
#include <iterator>
#include <limits>
+#include <new>
#include <type_traits>
@@ -120,14 +121,14 @@ public:
{
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
do_read(this->m_pointer, buffer, length, actual);
this->m_pointer += actual;
return std::error_condition();
}
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
do_read(offset, buffer, length, actual);
return std::error_condition();
@@ -239,7 +240,7 @@ public:
{
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
if (m_dangling_write)
{
@@ -270,7 +271,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
actual = 0U;
@@ -338,7 +339,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
if (m_dangling_read)
{
@@ -361,7 +362,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
actual = 0U;
@@ -409,7 +410,7 @@ public:
set_filler(fill);
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
actual = 0U;
@@ -473,7 +474,7 @@ public:
return std::error_condition();
}
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
actual = 0U;
@@ -634,18 +635,12 @@ public:
{
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
- if (std::numeric_limits<std::uint32_t>::max() < length)
- {
- actual = 0U;
- return std::errc::invalid_argument;
- }
-
// actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
std::uint32_t count;
- std::error_condition err = file().read(buffer, m_pointer, std::uint32_t(length), count);
+ std::error_condition err = file().read(buffer, m_pointer, chunk, count);
if (!err)
{
m_pointer += count;
@@ -658,18 +653,12 @@ public:
return err;
}
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- // TODO: should the client have to deal with reading less than expected even if EOF isn't hit?
- if (std::numeric_limits<std::uint32_t>::max() < length)
- {
- actual = 0U;
- return std::errc::invalid_argument;
- }
-
// actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
std::uint32_t count;
- std::error_condition err = file().read(buffer, offset, std::uint32_t(length), count);
+ std::error_condition err = file().read(buffer, offset, chunk, count);
if (!err)
actual = std::size_t(count);
else
@@ -696,48 +685,148 @@ public:
return file().flush();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- actual = 0U;
- while (length)
+ // actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t count;
+ std::error_condition err = file().write(buffer, m_pointer, chunk, count);
+ if (!err)
{
- // actual length not valid on error
- std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
- std::uint32_t written;
- std::error_condition err = file().write(buffer, m_pointer, chunk, written);
- if (err)
- return err;
- m_pointer += written;
- buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
- length -= written;
- actual += written;
+ actual = std::size_t(count);
+ m_pointer += count;
}
- return std::error_condition();
+ else
+ {
+ actual = 0U;
+ }
+ return err;
}
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- actual = 0U;
- while (length)
- {
- // actual length not valid on error
- std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
- std::uint32_t written;
- std::error_condition err = file().write(buffer, offset, chunk, written);
- if (err)
- return err;
- offset += written;
- buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
- length -= written;
- actual += written;
- }
- return std::error_condition();
+ // actual length not valid on error
+ std::uint32_t const chunk = std::min<std::common_type_t<std::uint32_t, std::size_t> >(std::numeric_limits<std::uint32_t>::max(), length);
+ std::uint32_t count;
+ std::error_condition err = file().write(buffer, offset, chunk, count);
+ if (!err)
+ actual = std::size_t(count);
+ else
+ actual = 0U;
+ return err;
}
};
} // anonymous namespace
+// helper functions for common patterns
+
+std::pair<std::error_condition, std::size_t> read(read_stream &stream, void *buffer, std::size_t length) noexcept
+{
+ std::size_t actual = 0;
+ do
+ {
+ std::size_t count;
+ std::error_condition err = stream.read_some(buffer, length, count);
+ actual += count;
+ if (!err)
+ {
+ if (!count)
+ break;
+ }
+ else if (std::errc::interrupted != err)
+ {
+ return std::make_pair(err, actual);
+ }
+ buffer = reinterpret_cast<std::uint8_t *>(buffer) + count;
+ length -= count;
+ }
+ while (length);
+ return std::make_pair(std::error_condition(), actual);
+}
+
+std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read(read_stream &stream, std::size_t length) noexcept
+{
+ std::unique_ptr<std::uint8_t []> buffer(new (std::nothrow) std::uint8_t [length]);
+ if (!buffer)
+ return std::make_tuple(std::errc::not_enough_memory, std::move(buffer), std::size_t(0));
+ auto [err, actual] = read(stream, buffer.get(), length);
+ return std::make_tuple(err, std::move(buffer), actual);
+}
+
+std::pair<std::error_condition, std::size_t> read_at(random_read &stream, std::uint64_t offset, void *buffer, std::size_t length) noexcept
+{
+ std::size_t actual = 0;
+ do
+ {
+ std::size_t count;
+ std::error_condition err = stream.read_some_at(offset, buffer, length, count);
+ actual += count;
+ if (!err)
+ {
+ if (!count)
+ break;
+ }
+ else if (std::errc::interrupted != err)
+ {
+ return std::make_pair(err, actual);
+ }
+ offset += count;
+ buffer = reinterpret_cast<std::uint8_t *>(buffer) + count;
+ length -= count;
+ }
+ while (length);
+ return std::make_pair(std::error_condition(), actual);
+}
+
+std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read_at(random_read &stream, std::uint64_t offset, std::size_t length) noexcept
+{
+ std::unique_ptr<std::uint8_t []> buffer(new (std::nothrow) std::uint8_t [length]);
+ if (!buffer)
+ return std::make_tuple(std::errc::not_enough_memory, std::move(buffer), std::size_t(0));
+ auto [err, actual] = read_at(stream, offset, buffer.get(), length);
+ return std::make_tuple(err, std::move(buffer), actual);
+}
+
+std::pair<std::error_condition, std::size_t> write(write_stream &stream, void const *buffer, std::size_t length) noexcept
+{
+ std::size_t actual = 0;
+ do
+ {
+ std::size_t written;
+ std::error_condition const err = stream.write_some(buffer, length, written);
+ assert(written || err || !length);
+ actual += written;
+ if (err && (std::errc::interrupted != err))
+ return std::make_pair(err, actual);
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ }
+ while (length);
+ return std::make_pair(std::error_condition(), actual);
+}
+
+std::pair<std::error_condition, std::size_t> write_at(random_write &stream, std::uint64_t offset, void const *buffer, std::size_t length) noexcept
+{
+ std::size_t actual = 0;
+ do
+ {
+ std::size_t written;
+ std::error_condition const err = stream.write_some_at(offset, buffer, length, written);
+ assert(written || err || !length);
+ actual += written;
+ if (err && (std::errc::interrupted != err))
+ return std::make_pair(err, actual);
+ offset += written;
+ buffer = reinterpret_cast<std::uint8_t const *>(buffer) + written;
+ length -= written;
+ }
+ while (length);
+ return std::make_pair(std::error_condition(), actual);
+}
+
+
// creating RAM read adapters
random_read::ptr ram_read(void const *data, std::size_t size) noexcept
diff --git a/src/lib/util/ioprocs.h b/src/lib/util/ioprocs.h
index efe0a231a11..9e2c29d2a14 100644
--- a/src/lib/util/ioprocs.h
+++ b/src/lib/util/ioprocs.h
@@ -19,6 +19,8 @@
#include <cstdlib>
#include <memory>
#include <system_error>
+#include <tuple>
+#include <utility>
// FIXME: make a proper place for OSD forward declarations
@@ -56,7 +58,7 @@ public:
/// \param [out] actual Number of bytes actually read. Will always
/// be less than or equal to the requested length.
/// \return An error condition if reading stopped due to an error.
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};
@@ -100,7 +102,7 @@ public:
/// \param [out] actual Number of bytes actually written. Will
/// always be less than or equal to the requested length.
/// \return An error condition if writing stopped due to an error.
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};
@@ -184,7 +186,7 @@ public:
/// be less than or equal to the requested length.
/// \return An error condition if seeking failed or reading stopped
/// due to an error.
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};
@@ -214,7 +216,7 @@ public:
/// always be less than or equal to the requested length.
/// \return An error condition if seeking failed or writing stopped
/// due to an error.
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept = 0;
};
@@ -229,6 +231,123 @@ public:
using ptr = std::unique_ptr<random_read_write>;
};
+
+/// \brief Read from the current position in the stream
+///
+/// Reads up to the specified number of bytes from the stream into the
+/// supplied buffer, continuing if interrupted by asynchronous signals.
+/// May read less than the requested number of bytes if the end of the
+/// stream is reached or an error occurs. If the stream supports
+/// seeking, reading starts at the current position in the stream, and
+/// the current position is incremented by the number of bytes read.
+/// The operation may not be atomic if it is interrupted before the
+/// requested number of bytes is read.
+/// \param [in] stream The stream to read from.
+/// \param [out] buffer Destination buffer. Must be large enough to
+/// hold the requested number of bytes.
+/// \param [in] length Maximum number of bytes to read.
+/// \return A pair containing an error condition if reading stopped due
+/// to an error, and the actual number of bytes read.
+std::pair<std::error_condition, std::size_t> read(read_stream &stream, void *buffer, std::size_t length) noexcept;
+
+/// \brief Allocate memory and read from the current position in the
+/// stream
+///
+/// Allocates the specified number of bytes and then reads up to that
+/// number of bytes from the stream into the newly allocated buffer,
+/// continuing if interrupted by asynchronous signals. May read less
+/// than the requested number of bytes if the end of the stream is
+/// reached or an error occurs. If the stream supports seeking,
+/// reading starts at the current position in the stream, and the
+/// current position is incremented by the number of bytes read. The
+/// operation may not be atomic if it is interrupted before the
+/// requested number of bytes is read. No data will be read if
+/// allocation fails.
+/// \param [in] stream The stream to read from.
+/// hold the requested number of bytes.
+/// \param [in] length Maximum number of bytes to read.
+/// \return A tuple containing an error condition if allocation failed
+/// or reading stopped due to an error, the allocated buffer, and the
+/// actual number of bytes read.
+std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read(read_stream &stream, std::size_t length) noexcept;
+
+/// \brief Read from the specified position
+///
+/// Reads up to the specified number of bytes from the stream into the
+/// supplied buffer, continuing if interrupted by asynchronous signals.
+/// May read less than the requested number of bytes if the end of the
+/// stream is reached or an error occurs. If seeking is supported,
+/// reading starts at the specified position and the current position is
+/// unaffected. The operation may not be atomic if it is interrupted
+/// before the requested number of bytes is read.
+/// \param [in] stream The stream to read from.
+/// \param [in] offset The position to start reading from, specified as
+/// a number of bytes from the beginning of the stream.
+/// \param [out] buffer Destination buffer. Must be large enough to
+/// hold the requested number of bytes.
+/// \param [in] length Maximum number of bytes to read.
+/// \return A pair containing an error condition if reading stopped due
+/// to an error, and the actual number of bytes read.
+std::pair<std::error_condition, std::size_t> read_at(random_read &stream, std::uint64_t offset, void *buffer, std::size_t length) noexcept;
+
+/// \brief Allocate memory and read from the specified position
+///
+/// Allocates the specified number of bytes and then reads up to that
+/// number of bytes from the stream into the newly allocated buffer,
+/// continuing if interrupted by asynchronous signals. May read less
+/// than the requested number of bytes if the end of the stream is
+/// reached or an error occurs. If seeking is supported, reading
+/// starts at the specified position and the current position is
+/// unaffected. The operation may not be atomic if it is interrupted
+/// before the requested number of bytes is read. No data will be read
+/// if allocation fails.
+/// \param [in] stream The stream to read from.
+/// \param [in] offset The position to start reading from, specified as
+/// a number of bytes from the beginning of the stream.
+/// \param [out] buffer Destination buffer. Must be large enough to
+/// hold the requested number of bytes.
+/// \param [in] length Maximum number of bytes to read.
+/// \return A tuple containing an error condition if allocation failed
+/// or reading stopped due to an error, the allocated buffer, and the
+/// actual number of bytes read.
+std::tuple<std::error_condition, std::unique_ptr<std::uint8_t []>, std::size_t> read_at(random_read &stream, std::uint64_t offset, std::size_t length) noexcept;
+
+/// \brief Write at the current position in the stream
+///
+/// Writes up to the specified number of bytes from the supplied
+/// buffer to the stream, continuing if interrupted by asynchronous
+/// signals. May write less than the requested number of bytes if an
+/// error occurs. If the stream supports seeking, writing starts at the
+/// current position in the stream, and the current position is
+/// incremented by the number of bytes written. The operation may not
+/// be atomic if it is interrupted before the requested number of bytes
+/// is written.
+/// \param [in] stream The stream to write to.
+/// \param [in] buffer Buffer containing the data to write. Must
+/// contain at least the specified number of bytes.
+/// \param [in] length Number of bytes to write.
+/// \return A pair containing an error condition if writing stopped due
+/// to an error, and the actual number of bytes written.
+std::pair<std::error_condition, std::size_t> write(write_stream &stream, void const *buffer, std::size_t length) noexcept;
+
+/// \brief Write at specified position
+///
+/// Writes up to the specified number of bytes from the supplied buffer,
+/// continuing if interrupted by asynchronous signals. If seeking is
+/// supported, writing starts at the specified position and the current
+/// position is unaffected. May write less than the requested number
+/// of bytes if an error occurs. The operation may not be atomic if it
+/// is interrupted before the requested number of bytes is written.
+/// \param [in] stream The stream to write to.
+/// \param [in] offset The position to start writing at, specified as a
+/// number of bytes from the beginning of the stream.
+/// \param [in] buffer Buffer containing the data to write. Must
+/// contain at least the specified number of bytes.
+/// \param [in] length Number of bytes to write.
+/// \return A pair containing an error condition if writing stopped due
+/// to an error, and the actual number of bytes written.
+std::pair<std::error_condition, std::size_t> write_at(random_write &stream, std::uint64_t offset, void const *buffer, std::size_t length) noexcept;
+
/// \}
diff --git a/src/lib/util/ioprocsfill.h b/src/lib/util/ioprocsfill.h
index e49b10687f0..7179d61852c 100644
--- a/src/lib/util/ioprocsfill.h
+++ b/src/lib/util/ioprocsfill.h
@@ -45,9 +45,21 @@ class read_stream_fill_wrapper : public Base, public virtual fill_wrapper_base<D
public:
using Base::Base;
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- std::error_condition err = Base::read(buffer, length, actual);
+ // not atomic with respect to other read/write calls
+ actual = 0U;
+ std::error_condition err;
+ std::size_t chunk;
+ do
+ {
+ err = Base::read_some(
+ reinterpret_cast<std::uint8_t *>(buffer) + actual,
+ length - actual,
+ chunk);
+ actual += chunk;
+ }
+ while ((length > actual) && ((!err && chunk) || (std::errc::interrupted == err)));
assert(length >= actual);
std::fill(
reinterpret_cast<std::uint8_t *>(buffer) + actual,
@@ -64,9 +76,23 @@ class random_read_fill_wrapper : public read_stream_fill_wrapper<Base, DefaultFi
public:
using read_stream_fill_wrapper<Base, DefaultFiller>::read_stream_fill_wrapper;
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- std::error_condition err = Base::read_at(offset, buffer, length, actual);
+ // not atomic with respect to other read/write calls
+ actual = 0U;
+ std::error_condition err;
+ std::size_t chunk;
+ do
+ {
+ err = Base::read_some_at(
+ offset,
+ reinterpret_cast<std::uint8_t *>(buffer) + actual,
+ length - actual,
+ chunk);
+ offset += chunk;
+ actual += chunk;
+ }
+ while ((length > actual) && ((!err && chunk) || (std::errc::interrupted == err)));
assert(length >= actual);
std::fill(
reinterpret_cast<std::uint8_t *>(buffer) + actual,
@@ -83,8 +109,9 @@ class random_write_fill_wrapper : public Base, public virtual fill_wrapper_base<
public:
using Base::Base;
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
+ // not atomic with respect to other read/write calls
std::error_condition err;
actual = 0U;
@@ -108,23 +135,22 @@ public:
do
{
std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled);
- err = Base::write_at(current, fill_buffer, chunk, actual);
- if (err)
- {
- actual = 0U;
+ std::size_t filled;
+ err = Base::write_some_at(current, fill_buffer, chunk, filled);
+ current += filled;
+ unfilled -= filled;
+ if (err && (std::errc::interrupted != err))
return err;
- }
- current += chunk;
- unfilled -= chunk;
}
while (unfilled);
}
- return Base::write(buffer, length, actual);
+ return Base::write_some(buffer, length, actual);
}
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
+ // not atomic with respect to other read/write calls
std::error_condition err;
std::uint64_t current;
err = Base::length(current);
@@ -139,18 +165,19 @@ public:
do
{
std::size_t const chunk = std::min<std::common_type_t<std::size_t, std::uint64_t> >(FillBlock, unfilled);
- err = Base::write_at(current, fill_buffer, chunk, actual);
- current += chunk;
- unfilled -= chunk;
+ std::size_t filled;
+ err = Base::write_some_at(current, fill_buffer, chunk, filled);
+ current += filled;
+ unfilled -= filled;
}
- while (unfilled && !err);
+ while (unfilled && (!err || (std::errc::interrupted == err)));
}
if (err)
{
actual = 0U;
return err;
}
- return Base::write_at(offset, buffer, length, actual);
+ return Base::write_some_at(offset, buffer, length, actual);
}
};
diff --git a/src/lib/util/ioprocsfilter.cpp b/src/lib/util/ioprocsfilter.cpp
index 68b9c90d018..b8d4cc3e786 100644
--- a/src/lib/util/ioprocsfilter.cpp
+++ b/src/lib/util/ioprocsfilter.cpp
@@ -21,6 +21,7 @@
#include <cstdint>
#include <limits>
#include <system_error>
+#include <tuple>
#include <type_traits>
#include <utility>
@@ -372,9 +373,9 @@ class read_stream_proxy : public virtual read_stream, public T
public:
using T::T;
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- return this->object().read(buffer, length, actual);
+ return this->object().read_some(buffer, length, actual);
}
};
@@ -397,9 +398,9 @@ public:
return this->object().flush();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- return this->object().write(buffer, length, actual);
+ return this->object().write_some(buffer, length, actual);
}
};
@@ -437,9 +438,9 @@ class random_read_proxy : public virtual random_read, public read_stream_proxy<T
public:
using read_stream_proxy<T>::read_stream_proxy;
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- return this->object().read_at(offset, buffer, length, actual);
+ return this->object().read_some_at(offset, buffer, length, actual);
}
};
@@ -452,9 +453,9 @@ class random_write_proxy : public virtual random_write, public write_stream_prox
public:
using write_stream_proxy<T>::write_stream_proxy;
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
- return this->object().write_at(offset, buffer, length, actual);
+ return this->object().write_some_at(offset, buffer, length, actual);
}
};
@@ -487,7 +488,7 @@ public:
{
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
std::error_condition err;
actual = 0U;
@@ -504,7 +505,7 @@ public:
{
auto const space = get_unfilled_input();
std::size_t filled;
- err = this->object().read(space.first, space.second, filled);
+ std::tie(err, filled) = read(this->object(), space.first, space.second);
add_input(filled);
short_input = space.second > filled;
}
@@ -598,8 +599,7 @@ public:
auto const output = get_output();
if (output.second)
{
- std::size_t written;
- std::error_condition err = object().write(output.first, output.second, written);
+ auto const [err, written] = write(object(), output.first, output.second);
consume_output(written);
if (err)
{
@@ -611,7 +611,7 @@ public:
return object().flush();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
std::error_condition err;
actual = 0U;
@@ -651,7 +651,7 @@ private:
{
auto const output = get_output();
std::size_t written;
- std::error_condition err = object().write(output.first, output.second, written);
+ std::error_condition const err = object().write_some(output.first, output.second, written);
consume_output(written);
return err;
}
diff --git a/src/lib/util/ioprocsvec.h b/src/lib/util/ioprocsvec.h
index d3c1c7fe01b..e66000b5729 100644
--- a/src/lib/util/ioprocsvec.h
+++ b/src/lib/util/ioprocsvec.h
@@ -90,14 +90,14 @@ public:
return std::error_condition();
}
- virtual std::error_condition read(void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some(void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
do_read(m_pointer, buffer, length, actual);
m_pointer += actual;
return std::error_condition();
}
- virtual std::error_condition read_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition read_some_at(std::uint64_t offset, void *buffer, std::size_t length, std::size_t &actual) noexcept override
{
do_read(offset, buffer, length, actual);
return std::error_condition();
@@ -113,14 +113,14 @@ public:
return std::error_condition();
}
- virtual std::error_condition write(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some(void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
std::error_condition result = do_write(m_pointer, buffer, length, actual);
m_pointer += actual;
return result;
}
- virtual std::error_condition write_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
+ virtual std::error_condition write_some_at(std::uint64_t offset, void const *buffer, std::size_t length, std::size_t &actual) noexcept override
{
return do_write(offset, buffer, length, actual);
}
diff --git a/src/lib/util/jedparse.cpp b/src/lib/util/jedparse.cpp
index 5915886b1a6..b347a2dd2b5 100644
--- a/src/lib/util/jedparse.cpp
+++ b/src/lib/util/jedparse.cpp
@@ -24,6 +24,7 @@
#include <cstdlib>
#include <cstring>
#include <cctype>
+#include <tuple>
@@ -194,7 +195,6 @@ static void process_field(jed_data *data, const uint8_t *cursrc, const uint8_t *
int jed_parse(util::random_read &src, jed_data *result)
{
jed_parse_info pinfo;
- int i;
std::size_t actual;
std::error_condition err;
@@ -206,7 +206,7 @@ int jed_parse(util::random_read &src, jed_data *result)
uint8_t ch;
do
{
- err = src.read(&ch, 1, actual);
+ std::tie(err, actual) = read(src, &ch, 1);
if (err)
{
if (LOG_PARSE) printf("Read error searching for JED start marker\n");
@@ -225,7 +225,7 @@ int jed_parse(util::random_read &src, jed_data *result)
uint16_t checksum = ch;
do
{
- err = src.read(&ch, 1, actual);
+ std::tie(err, actual) = read(src, &ch, 1);
if (err)
{
if (LOG_PARSE) printf("Read error searching for JED end marker\n");
@@ -261,7 +261,8 @@ int jed_parse(util::random_read &src, jed_data *result)
/* see if there is a transmission checksum at the end */
uint8_t sumbuf[4];
- if (!src.read(&sumbuf[0], 4, actual) && actual == 4 && ishex(sumbuf[0]) && ishex(sumbuf[1]) && ishex(sumbuf[2]) && ishex(sumbuf[3]))
+ std::tie(err, actual) = read(src, &sumbuf[0], 4);
+ if (!err && (actual == 4) && ishex(sumbuf[0]) && ishex(sumbuf[1]) && ishex(sumbuf[2]) && ishex(sumbuf[3]))
{
uint16_t dessum = (hexval(sumbuf[0]) << 12) | (hexval(sumbuf[1]) << 8) | (hexval(sumbuf[2]) << 4) | hexval(sumbuf[3] << 0);
if (dessum != 0 && dessum != checksum)
@@ -281,7 +282,8 @@ int jed_parse(util::random_read &src, jed_data *result)
}
}
auto srcdata = std::make_unique<uint8_t[]>(endpos - startpos);
- if (src.read(&srcdata[0], endpos - startpos, actual) || actual != endpos - startpos)
+ std::tie(err, actual) = read(src, &srcdata[0], endpos - startpos);
+ if (err || ((endpos - startpos) != actual))
{
if (LOG_PARSE) printf("Error reading JED data\n");
return JEDERR_INVALID_DATA;
@@ -325,7 +327,7 @@ int jed_parse(util::random_read &src, jed_data *result)
/* validate the checksum */
checksum = 0;
- for (i = 0; i < (result->numfuses + 7) / 8; i++)
+ for (int i = 0; i < ((result->numfuses + 7) / 8); i++)
checksum += result->fusemap[i];
if (pinfo.checksum != 0 && checksum != pinfo.checksum)
{
@@ -441,13 +443,16 @@ size_t jed_output(const jed_data *data, void *result, size_t length)
int jedbin_parse(util::read_stream &src, jed_data *result)
{
+ std::error_condition err;
+ std::size_t actual;
+
/* initialize the output */
memset(result, 0, sizeof(*result));
/* need at least 4 bytes */
uint8_t buf[4];
- std::size_t actual;
- if (src.read(&buf[0], 4, actual) || actual != 4)
+ std::tie(err, actual) = read(src, &buf[0], 4);
+ if (err || (4 != actual))
return JEDERR_INVALID_DATA;
/* first unpack the number of fuses */
@@ -457,7 +462,8 @@ int jedbin_parse(util::read_stream &src, jed_data *result)
/* now make sure we have enough data in the source */
/* copy in the data */
- if (src.read(result->fusemap, (result->numfuses + 7) / 8, actual) || actual != (result->numfuses + 7) / 8)
+ std::tie(err, actual) = read(src, result->fusemap, (result->numfuses + 7) / 8);
+ if (err || (((result->numfuses + 7) / 8) != actual))
return JEDERR_INVALID_DATA;
return JEDERR_NONE;
}
diff --git a/src/lib/util/language.cpp b/src/lib/util/language.cpp
index 3a00fe80ad7..50b518acd1b 100644
--- a/src/lib/util/language.cpp
+++ b/src/lib/util/language.cpp
@@ -61,11 +61,10 @@ void load_translation(random_read &file)
return;
}
- std::size_t read;
- file.read(translation_data.get(), size, read);
- if (read != size)
+ auto const [err, actual] = read(file, translation_data.get(), size);
+ if (err || (actual != size))
{
- osd_printf_error("Error reading translation file: requested %u bytes but got %u bytes\n", size, read);
+ osd_printf_error("Error reading translation file: requested %u bytes but got %u bytes\n", size, actual);
translation_data.reset();
return;
}
diff --git a/src/lib/util/mfpresolve.cpp b/src/lib/util/mfpresolve.cpp
new file mode 100644
index 00000000000..c7b9c58fde2
--- /dev/null
+++ b/src/lib/util/mfpresolve.cpp
@@ -0,0 +1,431 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ mfpresolve.h
+
+ Helpers for resolving member function pointers to entry points.
+
+***************************************************************************/
+
+#include "mfpresolve.h"
+
+#include "osdcomm.h"
+
+#include <cstdio>
+
+
+//**************************************************************************
+// MACROS
+//**************************************************************************
+
+#if defined(MAME_DELEGATE_LOG_ADJ)
+ #define LOG(...) printf(__VA_ARGS__)
+#else
+ #define LOG(...) do { if (false) printf(__VA_ARGS__); } while (false)
+#endif
+
+
+
+namespace util::detail {
+
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_itanium(
+ std::uintptr_t function,
+ std::ptrdiff_t delta,
+ void const *object) noexcept
+{
+ // apply the "this" delta to the object first - the value is shifted to the left one bit position for the ARM-like variant
+ LOG("Input this=%p ptr=%p adj=%ld ", object, reinterpret_cast<void const *>(function), long(delta));
+ constexpr int deltashift = (MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 1 : 0;
+ object = reinterpret_cast<std::uint8_t const *>(object) + (delta >> deltashift);
+ LOG("Calculated this=%p ", object);
+
+ // test the virtual member function flag - it's the low bit of either the ptr or adj field, depending on the variant
+ if ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? !(delta & 1) : !(function & 1))
+ {
+ // conventional function pointer
+ LOG("ptr=%p\n", reinterpret_cast<void const *>(function));
+ return std::make_pair(function, std::uintptr_t(object));
+ }
+ else
+ {
+ // byte index into the vtable to the function
+ auto const vtable_ptr = *reinterpret_cast<std::uint8_t const *const *>(object) + function - ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 0 : 1);
+ std::uintptr_t result;
+ if (MAME_ABI_CXX_VTABLE_FNDESC)
+ result = std::uintptr_t(vtable_ptr);
+ else
+ result = *reinterpret_cast<std::uintptr_t const *>(vtable_ptr);
+ LOG("ptr=%p (vtable)\n", reinterpret_cast<void const *>(result));
+ return std::make_pair(result, std::uintptr_t(object));
+ }
+}
+
+
+std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_itanium(
+ std::uintptr_t function,
+ std::ptrdiff_t delta) noexcept
+{
+ constexpr uintptr_t funcmask = ~uintptr_t((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 0 : 1);
+ constexpr int deltashift = (MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 1 : 0;
+ return std::make_tuple(
+ function & funcmask,
+ delta >> deltashift,
+ (MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? (delta & 1) : (function & 1));
+}
+
+
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_msvc(
+ void const *funcptr,
+ std::size_t size,
+ void const *object) noexcept
+{
+ mfp_msvc_unknown_equiv const *unknown;
+ assert(sizeof(*unknown) >= size);
+ unknown = reinterpret_cast<mfp_msvc_unknown_equiv const *>(funcptr);
+
+ LOG("Input this=%p ", object);
+ if (sizeof(mfp_msvc_single_equiv) < size)
+ LOG("thisdelta=%d ", unknown->delta);
+ if (sizeof(mfp_msvc_unknown_equiv) == size)
+ LOG("vptrdelta=%d vindex=%d ", unknown->voffset, unknown->vindex);
+ auto byteptr = reinterpret_cast<std::uint8_t const *>(object);
+
+ // test for pointer to member function cast across virtual inheritance relationship
+ if ((sizeof(mfp_msvc_unknown_equiv) == size) && unknown->vindex)
+ {
+ // add offset from "this" pointer to location of vptr, and add offset to virtual base from vtable
+ byteptr += unknown->voffset;
+ auto const vptr = *reinterpret_cast<std::uint8_t const *const *>(byteptr);
+ byteptr += *reinterpret_cast<int const *>(vptr + unknown->vindex);
+ }
+
+ // add "this" pointer displacement if present in the pointer to member function
+ if (sizeof(mfp_msvc_single_equiv) < size)
+ byteptr += unknown->delta;
+ LOG("Calculated this=%p\n", reinterpret_cast<void const *>(byteptr));
+
+ // walk past recognisable thunks
+ return std::make_pair(bypass_member_function_thunks(unknown->entrypoint, byteptr), std::uintptr_t(byteptr));
+}
+
+
+std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_msvc(
+ void const *funcptr,
+ std::size_t size) noexcept
+{
+ mfp_msvc_unknown_equiv const *unknown;
+ assert(sizeof(*unknown) >= size);
+ unknown = reinterpret_cast<mfp_msvc_unknown_equiv const *>(funcptr);
+
+ // no way to represent pointer to member function cast across virtual inheritance relationship
+ if ((sizeof(mfp_msvc_unknown_equiv) == size) && unknown->vindex)
+ return std::make_tuple(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::ptrdiff_t(0), false);
+
+ auto const [function, is_virtual] = bypass_member_function_thunks(unknown->entrypoint);
+ return std::make_tuple(
+ function,
+ (sizeof(mfp_msvc_single_equiv) < size) ? unknown->delta : 0,
+ is_virtual);
+}
+
+
+std::uintptr_t bypass_member_function_thunks(
+ std::uintptr_t entrypoint,
+ void const *object) noexcept
+{
+#if defined(__x86_64__) || defined(_M_X64)
+ std::uint8_t const *func = reinterpret_cast<std::uint8_t const *>(entrypoint);
+ while (true)
+ {
+ // Assumes Windows calling convention, and doesn't consider that
+ // the "this" pointer could be in RDX if RCX is a pointer to
+ // space for an oversize scalar result. Since the result area
+ // is uninitialised on entry, you won't see something that looks
+ // like a vtable dispatch through RCX in this case - it won't
+ // behave badly, it just won't bypass virtual call thunks in the
+ // rare situations where the return type is an oversize scalar.
+ if (0xe9 == func[0])
+ {
+ // relative jump with 32-bit displacement (typically a resolved PLT entry)
+ LOG("Found relative jump at %p ", func);
+ func += std::ptrdiff_t(5) + *reinterpret_cast<std::int32_t const *>(func + 1);
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if (object && (0x48 == func[0]) && (0x8b == func[1]) && (0x01 == func[2]))
+ {
+ if ((0xff == func[3]) && ((0x20 == func[4]) || (0x60 == func[4]) || (0xa0 == func[4])))
+ {
+ // MSVC virtual function call thunk - mov rax,QWORD PTR [rcx] ; jmp QWORD PTR [rax+...]
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ if (0x20 == func[4]) // no displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
+ else if (0x60 == func[4]) // 8-bit displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 5));
+ else // 32-bit displacement
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 5));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x48 == func[3]) && (0x8b == func[4]))
+ {
+ // clang virtual function call thunk - mov rax,QWORD PTR [rcx] ; mov rax,QWORD PTR [rax+...] ; jmp rax
+ if ((0x00 == func[5]) && (0x48 == func[6]) && (0xff == func[7]) && (0xe0 == func[8]))
+ {
+ // no displacement
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr);
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x40 == func[5]) && (0x48 == func[7]) && (0xff == func[8]) && (0xe0 == func[9]))
+ {
+ // 8-bit displacement
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int8_t const *>(func + 6));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x80 == func[5]) && (0x48 == func[10]) && (0xff == func[11]) && (0xe0 == func[12]))
+ {
+ // 32-bit displacement
+ LOG("Found virtual member function thunk at %p ", func);
+ std::uint8_t const *const vptr = *reinterpret_cast<std::uint8_t const *const *>(object);
+ func = *reinterpret_cast<std::uint8_t const *const *>(vptr + *reinterpret_cast<std::int32_t const *>(func + 6));
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ }
+ }
+
+ // clang uses unoptimised thunks if optimisation is disabled
+ // Without optimisation, clang produces thunks like:
+ // 50 push rax
+ // 48 89 0c 24 mov QWORD PTR [rsp],rcx
+ // 48 8b 0c 24 mov rcx,QWORD PTR [rsp]
+ // 48 8b 01 mov rax,QWORD PTR [rcx]
+ // 48 8b 80 xx xx xx xx mov rax,QWORD PTR [rax+...]
+ // 41 5a pop r10
+ // 48 ff e0 jmp rax
+ // Trying to decode these thunks likely isn't worth the effort.
+ // Chasing performance in unoptimised builds isn't very useful,
+ // and the format of these thunks may be fragile.
+
+ // not something we can easily bypass
+ break;
+ }
+ return std::uintptr_t(func);
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ std::uint32_t const *func = reinterpret_cast<std::uint32_t const *>(entrypoint);
+ auto const fetch = [&func] (auto offset) { return little_endianize_int32(func[offset]); };
+ while (true)
+ {
+ if ((0x90000010 == (fetch(0) & 0x9f00001f)) && (0x91000210 == (fetch(1) & 0xffc003ff)) && (0xd61f0200 == fetch(2)))
+ {
+ // page-relative jump with +/-4GB reach - adrp xip0,... ; add xip0,xip0,#... ; br xip0
+ LOG("Found page-relative jump at %p ", func);
+ std::int64_t const page =
+ (std::uint64_t(fetch(0) & 0x60000000) >> 17) |
+ (std::uint64_t(fetch(0) & 0x00ffffe0) << 9) |
+ ((fetch(0) & 0x00800000) ? (~std::uint64_t(0) << 33) : 0);
+ std::uint32_t const offset = (fetch(1) & 0x003ffc00) >> 10;
+ func = reinterpret_cast<std::uint32_t const *>(((std::uintptr_t(func) + page) & (~std::uintptr_t(0) << 12)) + offset);
+ LOG("redirecting to %p\n", func);
+ }
+ else if (object && (0xf9400010 == fetch(0)) && (0xf9400210 == (fetch(1) & 0xffc003ff)) && (0xd61f0200 == fetch(2)))
+ {
+ // virtual function call thunk - ldr xip0,[x0] ; ldr xip0,[x0,#...] ; br xip0
+ LOG("Found virtual member function thunk at %p ", func);
+ auto const vptr = *reinterpret_cast<std::uint32_t const *const *const *>(object);
+ func = vptr[(fetch(1) & 0x003ffc00) >> 10];
+ LOG("redirecting to %p\n", func);
+ }
+ else
+ {
+ // not something we can easily bypass
+ break;
+ }
+
+ // clang uses horribly sub-optimal thunks for AArch64
+ // Without optimisation, clang produces thunks like:
+ // d10143ff sub sp,sp,#80
+ // f90027e7 str x7,[sp,#72]
+ // f90023e6 str x6,[sp,#64]
+ // f9001fe5 str x5,[sp,#56]
+ // f9001be4 str x4,[sp,#48]
+ // f90017e3 str x3,[sp,#40]
+ // f90013e2 str x2,[sp,#32]
+ // f9000fe1 str x1,[sp,#24]
+ // f90007e0 str x0,[sp,#8]
+ // f94007e0 ldr x0,[sp,#8]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910143ff add sp,sp,#80
+ // d61f0120 br x9
+ // With optimisation, clang produces thunks like:
+ // d10103ff sub sp,sp,#64
+ // a9008be1 stp x1,x2,[sp,#8]
+ // a90193e3 stp x3,x4,[sp,#24]
+ // a9029be5 stp x5,x6,[sp,#40]
+ // f9001fe7 str x7,[sp,#56]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910103ff add sp,sp,#64
+ // d61f0120 br x9
+ // It's more effort than it's worth to try decoding these
+ // thunks.
+
+ }
+ return std::uintptr_t(func);
+#else
+ return entrypoint;
+#endif
+}
+
+
+std::pair<std::uintptr_t, bool> bypass_member_function_thunks(
+ std::uintptr_t entrypoint) noexcept
+{
+#if defined(__x86_64__) || defined(_M_X64)
+ std::uint8_t const *func = reinterpret_cast<std::uint8_t const *>(entrypoint);
+ while (true)
+ {
+ // Assumes Windows calling convention, and doesn't consider that
+ // the "this" pointer could be in RDX if RCX is a pointer to
+ // space for an oversize scalar result. Since the result area
+ // is uninitialised on entry, you won't see something that looks
+ // like a vtable dispatch through RCX in this case - it won't
+ // behave badly, it just won't bypass virtual call thunks in the
+ // rare situations where the return type is an oversize scalar.
+ if (0xe9 == func[0])
+ {
+ // relative jump with 32-bit displacement (typically a resolved PLT entry)
+ LOG("Found relative jump at %p ", func);
+ func += std::ptrdiff_t(5) + *reinterpret_cast<std::int32_t const *>(func + 1);
+ LOG("redirecting to %p\n", func);
+ continue;
+ }
+ else if ((0x48 == func[0]) && (0x8b == func[1]) && (0x01 == func[2]))
+ {
+ if ((0xff == func[3]) && ((0x20 == func[4]) || (0x60 == func[4]) || (0xa0 == func[4])))
+ {
+ // MSVC virtual function call thunk - mov rax,QWORD PTR [rcx] ; jmp QWORD PTR [rax+...]
+ LOG("Found virtual member function thunk at %p\n", func);
+ if (0x20 == func[4]) // no displacement
+ return std::make_pair(std::uintptr_t(0), true);
+ else if (0x60 == func[4]) // 8-bit displacement
+ return std::make_pair(std::uintptr_t(*reinterpret_cast<std::int8_t const *>(func + 5)), true);
+ else // 32-bit displacement
+ return std::make_pair(std::uintptr_t(*reinterpret_cast<std::int32_t const *>(func + 5)), true);
+ }
+ else if ((0x48 == func[3]) && (0x8b == func[4]))
+ {
+ // clang virtual function call thunk - mov rax,QWORD PTR [rcx] ; mov rax,QWORD PTR [rax+...] ; jmp rax
+ if ((0x00 == func[5]) && (0x48 == func[6]) && (0xff == func[7]) && (0xe0 == func[8]))
+ {
+ // no displacement
+ LOG("Found virtual member function thunk at %p\n", func);
+ return std::make_pair(std::uintptr_t(0), true);
+ }
+ else if ((0x40 == func[5]) && (0x48 == func[7]) && (0xff == func[8]) && (0xe0 == func[9]))
+ {
+ // 8-bit displacement
+ LOG("Found virtual member function thunk at %p\n", func);
+ return std::make_pair(std::uintptr_t(*reinterpret_cast<std::int8_t const *>(func + 6)), true);
+ }
+ else if ((0x80 == func[5]) && (0x48 == func[10]) && (0xff == func[11]) && (0xe0 == func[12]))
+ {
+ // 32-bit displacement
+ LOG("Found virtual member function thunk at %p\n", func);
+ return std::make_pair(std::uintptr_t(*reinterpret_cast<std::int32_t const *>(func + 6)), true);
+ }
+ }
+ }
+
+ // clang uses unoptimised thunks if optimisation is disabled
+ // Without optimisation, clang produces thunks like:
+ // 50 push rax
+ // 48 89 0c 24 mov QWORD PTR [rsp],rcx
+ // 48 8b 0c 24 mov rcx,QWORD PTR [rsp]
+ // 48 8b 01 mov rax,QWORD PTR [rcx]
+ // 48 8b 80 xx xx xx xx mov rax,QWORD PTR [rax+...]
+ // 41 5a pop r10
+ // 48 ff e0 jmp rax
+ // Trying to decode these thunks likely isn't worth the effort.
+ // Chasing performance in unoptimised builds isn't very useful,
+ // and the format of these thunks may be fragile.
+
+ // not something we can easily bypass
+ break;
+ }
+ return std::make_pair(std::uintptr_t(func), false);
+#elif defined(__aarch64__) || defined(_M_ARM64)
+ std::uint32_t const *func = reinterpret_cast<std::uint32_t const *>(entrypoint);
+ auto const fetch = [&func] (auto offset) { return little_endianize_int32(func[offset]); };
+ while (true)
+ {
+ if ((0x90000010 == (fetch(0) & 0x9f00001f)) && (0x91000210 == (fetch(1) & 0xffc003ff)) && (0xd61f0200 == fetch(2)))
+ {
+ // page-relative jump with +/-4GB reach - adrp xip0,... ; add xip0,xip0,#... ; br xip0
+ LOG("Found page-relative jump at %p ", func);
+ std::int64_t const page =
+ (std::uint64_t(fetch(0) & 0x60000000) >> 17) |
+ (std::uint64_t(fetch(0) & 0x00ffffe0) << 9) |
+ ((fetch(0) & 0x00800000) ? (~std::uint64_t(0) << 33) : 0);
+ std::uint32_t const offset = (fetch(1) & 0x003ffc00) >> 10;
+ func = reinterpret_cast<std::uint32_t const *>(((std::uintptr_t(func) + page) & (~std::uintptr_t(0) << 12)) + offset);
+ LOG("redirecting to %p\n", func);
+ }
+ else if ((0xf9400010 == fetch(0)) && (0xf9400210 == (fetch(1) & 0xffc003ff)) && (0xd61f0200 == fetch(2)))
+ {
+ // virtual function call thunk - ldr xip0,[x0] ; ldr xip0,[x0,#...] ; br xip0
+ LOG("Found virtual member function thunk at %p\n", func);
+ return std::make_pair(std::uintptr_t((fetch(1) & 0x003ffc00) >> (10 - 3)), true);
+ }
+ else
+ {
+ // not something we can easily bypass
+ break;
+ }
+
+ // clang uses horribly sub-optimal thunks for AArch64
+ // Without optimisation, clang produces thunks like:
+ // d10143ff sub sp,sp,#80
+ // f90027e7 str x7,[sp,#72]
+ // f90023e6 str x6,[sp,#64]
+ // f9001fe5 str x5,[sp,#56]
+ // f9001be4 str x4,[sp,#48]
+ // f90017e3 str x3,[sp,#40]
+ // f90013e2 str x2,[sp,#32]
+ // f9000fe1 str x1,[sp,#24]
+ // f90007e0 str x0,[sp,#8]
+ // f94007e0 ldr x0,[sp,#8]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910143ff add sp,sp,#80
+ // d61f0120 br x9
+ // With optimisation, clang produces thunks like:
+ // d10103ff sub sp,sp,#64
+ // a9008be1 stp x1,x2,[sp,#8]
+ // a90193e3 stp x3,x4,[sp,#24]
+ // a9029be5 stp x5,x6,[sp,#40]
+ // f9001fe7 str x7,[sp,#56]
+ // f9400009 ldr x9,[x0]
+ // f9400129 ldr x9,[x9,#...]
+ // 910103ff add sp,sp,#64
+ // d61f0120 br x9
+ // It's more effort than it's worth to try decoding these
+ // thunks.
+
+ }
+ return std::make_pair(std::uintptr_t(func), false);
+#else
+ return std::make_pair(entrypoint, false);
+#endif
+}
+
+} // namespace util::detail
diff --git a/src/lib/util/mfpresolve.h b/src/lib/util/mfpresolve.h
new file mode 100644
index 00000000000..eb3fba2b85d
--- /dev/null
+++ b/src/lib/util/mfpresolve.h
@@ -0,0 +1,151 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/***************************************************************************
+
+ mfpresolve.h
+
+ Helpers for resolving member function pointers to entry points.
+
+***************************************************************************/
+#ifndef MAME_LIB_UTIL_MFPRESOLVE_H
+#define MAME_LIB_UTIL_MFPRESOLVE_H
+
+#pragma once
+
+#include "abi.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <tuple>
+#include <utility>
+
+
+namespace util {
+
+namespace detail {
+
+struct mfp_itanium_equiv
+{
+ std::uintptr_t function;
+ std::ptrdiff_t delta;
+
+ constexpr std::ptrdiff_t this_delta() const noexcept { return delta >> ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? 1 : 0); }
+ constexpr bool is_virtual() const noexcept { return ((MAME_ABI_CXX_ITANIUM_MFP_TYPE == MAME_ABI_CXX_ITANIUM_MFP_ARM) ? delta : function) & 1; }
+};
+
+struct mfp_msvc_single_equiv { std::uintptr_t entrypoint; };
+struct mfp_msvc_multi_equiv { std::uintptr_t entrypoint; int delta; };
+struct mfp_msvc_virtual_equiv { std::uintptr_t entrypoint; int delta; int vindex; };
+struct mfp_msvc_unknown_equiv { std::uintptr_t entrypoint; int delta; int voffset; int vindex; };
+
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_itanium(std::uintptr_t function, std::ptrdiff_t delta, void const *object) noexcept;
+std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_itanium(std::uintptr_t function, std::ptrdiff_t delta) noexcept;
+std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function_msvc(void const *funcptr, std::size_t size, void const *object) noexcept;
+std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function_msvc(void const *funcptr, std::size_t size) noexcept;
+std::uintptr_t bypass_member_function_thunks(std::uintptr_t entrypoint, void const *object) noexcept;
+std::pair<std::uintptr_t, bool> bypass_member_function_thunks(std::uintptr_t entrypoint) noexcept;
+
+} // namespace detail
+
+
+template <typename T, typename U>
+inline T bypass_member_function_thunks(T entrypoint, U const *object) noexcept
+{
+ return reinterpret_cast<T>(
+ detail::bypass_member_function_thunks(
+ reinterpret_cast<std::uintptr_t>(entrypoint),
+ reinterpret_cast<void const *>(object)));
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T::*function)(Params...), T &object) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ detail::mfp_itanium_equiv equiv;
+ assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.function, equiv.delta, &object);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function), &object);
+ }
+ else
+ {
+ return std::make_pair(
+ std::uintptr_t(static_cast<void (*)()>(nullptr)),
+ std::uintptr_t(static_cast<void *>(nullptr)));
+ }
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::pair<std::uintptr_t, std::uintptr_t> resolve_member_function(Ret (T::*function)(Params...) const, T const &object) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ detail::mfp_itanium_equiv equiv;
+ assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.function, equiv.delta, &object);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function), &object);
+ }
+ else
+ {
+ return std::make_pair(
+ std::uintptr_t(static_cast<void (*)()>(nullptr)),
+ std::uintptr_t(static_cast<void *>(nullptr)));
+ }
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function(Ret (T::*function)(Params...)) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ detail::mfp_itanium_equiv equiv;
+ assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.function, equiv.delta);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function));
+ }
+ else
+ {
+ return std::make_tuple(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::ptrdiff_t(0), false);
+ }
+}
+
+
+template <typename T, typename Ret, typename... Params>
+inline std::tuple<std::uintptr_t, std::ptrdiff_t, bool> resolve_member_function(Ret (T::*function)(Params...) const) noexcept
+{
+ if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_ITANIUM)
+ {
+ detail::mfp_itanium_equiv equiv;
+ assert(sizeof(function) == sizeof(equiv));
+ *reinterpret_cast<decltype(function) *>(&equiv) = function;
+ return detail::resolve_member_function_itanium(equiv.function, equiv.delta);
+ }
+ else if (MAME_ABI_CXX_TYPE == MAME_ABI_CXX_MSVC)
+ {
+ return detail::resolve_member_function_msvc(&function, sizeof(function));
+ }
+ else
+ {
+ return std::make_tuple(std::uintptr_t(static_cast<void (*)()>(nullptr)), std::ptrdiff_t(0), false);
+ }
+}
+
+} // namespace util
+
+#endif // MAME_LIB_UTIL_MFPRESOLVE_H
diff --git a/src/lib/util/msdib.cpp b/src/lib/util/msdib.cpp
index e70ba1b592a..bf33991f116 100644
--- a/src/lib/util/msdib.cpp
+++ b/src/lib/util/msdib.cpp
@@ -20,6 +20,7 @@
#include <cassert>
#include <cstdlib>
#include <cstring>
+#include <tuple>
#define LOG_GENERAL (1U << 0)
@@ -127,11 +128,10 @@ std::uint8_t dib_splat_sample(std::uint8_t val, unsigned bits) noexcept
msdib_error dib_read_file_header(read_stream &fp, std::uint32_t &filelen) noexcept
{
- std::size_t actual;
-
// the bitmap file header doesn't use natural alignment
bitmap_file_header file_header;
- if (fp.read(file_header, sizeof(file_header), actual) || (sizeof(file_header) != actual))
+ auto const [err, actual] = read(fp, file_header, sizeof(file_header));
+ if (err || (sizeof(file_header) != actual))
{
LOG("Error reading DIB file header\n");
return msdib_error::FILE_TRUNCATED;
@@ -167,6 +167,7 @@ msdib_error dib_read_bitmap_header(
std::size_t &row_bytes,
std::uint32_t length) noexcept
{
+ std::error_condition err;
std::size_t actual;
// check that these things haven't been padded somehow
@@ -178,7 +179,8 @@ msdib_error dib_read_bitmap_header(
if (sizeof(header.core) > length)
return msdib_error::FILE_TRUNCATED;
std::memset(&header, 0, sizeof(header));
- if (fp.read(&header.core.size, sizeof(header.core.size), actual) || (sizeof(header.core.size) != actual))
+ std::tie(err, actual) = read(fp, &header.core.size, sizeof(header.core.size));
+ if (err || (sizeof(header.core.size) != actual))
{
LOG("Error reading DIB header size (length %u)\n", length);
return msdib_error::FILE_TRUNCATED;
@@ -208,7 +210,8 @@ msdib_error dib_read_bitmap_header(
{
palette_bytes = 3U;
std::uint32_t const header_read(std::min<std::uint32_t>(header.core.size, sizeof(header.core)) - sizeof(header.core.size));
- if (fp.read(&header.core.width, header_read, actual) || (header_read != actual))
+ std::tie(err, actual) = read(fp, &header.core.width, header_read);
+ if (err || (header_read != actual))
{
LOG("Error reading DIB core header from image data (%u bytes)\n", length);
return msdib_error::FILE_TRUNCATED;
@@ -261,7 +264,8 @@ msdib_error dib_read_bitmap_header(
{
palette_bytes = 4U;
std::uint32_t const header_read(std::min<std::uint32_t>(header.info.size, sizeof(header.info)) - sizeof(header.info.size));
- if (fp.read(&header.info.width, header_read, actual) || (header_read != actual))
+ std::tie(err, actual) = read(fp, &header.info.width, header_read);
+ if (err || (header_read != actual))
{
LOG("Error reading DIB info header from image data (%u bytes)\n", length);
return msdib_error::FILE_TRUNCATED;
@@ -445,7 +449,6 @@ msdib_error msdib_read_bitmap(random_read &fp, bitmap_argb32 &bitmap) noexcept
msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::uint32_t length, std::uint32_t dirheight) noexcept
{
// read the bitmap header
- std::size_t actual;
bitmap_headers header;
unsigned palette_bytes;
bool indexed;
@@ -492,7 +495,8 @@ msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::
std::unique_ptr<std::uint8_t []> palette_data(new (std::nothrow) std::uint8_t [palette_size]);
if (!palette_data)
return msdib_error::OUT_OF_MEMORY;
- if (fp.read(palette_data.get(), palette_size, actual) || (palette_size != actual))
+ auto const [err, actual] = read(fp, palette_data.get(), palette_size);
+ if (err || (palette_size != actual))
{
LOG("Error reading palette from DIB image data (%u bytes)\n", length);
return msdib_error::FILE_TRUNCATED;
@@ -575,7 +579,8 @@ msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::
int const y_inc(top_down ? 1 : -1);
for (std::int32_t i = 0, y = top_down ? 0 : (header.info.height - 1); header.info.height > i; ++i, y += y_inc)
{
- if (fp.read(row_data.get(), row_bytes, actual) || (row_bytes != actual))
+ auto const [err, actual] = read(fp, row_data.get(), row_bytes);
+ if (err || (row_bytes != actual))
{
LOG("Error reading DIB row %d data from image data\n", i);
return msdib_error::FILE_TRUNCATED;
@@ -638,7 +643,8 @@ msdib_error msdib_read_bitmap_data(random_read &fp, bitmap_argb32 &bitmap, std::
{
for (std::int32_t i = 0, y = top_down ? 0 : (header.info.height - 1); header.info.height > i; ++i, y += y_inc)
{
- if (fp.read(row_data.get(), mask_row_bytes, actual) || (mask_row_bytes != actual))
+ auto const [err, actual] = read(fp, row_data.get(), mask_row_bytes);
+ if (err || (mask_row_bytes != actual))
{
LOG("Error reading DIB mask row %d data from image data\n", i);
return msdib_error::FILE_TRUNCATED;
diff --git a/src/lib/util/options.h b/src/lib/util/options.h
index 99db519a5e5..8b85b9f58e6 100644
--- a/src/lib/util/options.h
+++ b/src/lib/util/options.h
@@ -12,6 +12,7 @@
#define MAME_LIB_UTIL_OPTIONS_H
#include "strformat.h"
+#include "utilfwd.h"
#include <algorithm>
#include <exception>
@@ -43,7 +44,6 @@ const int OPTION_PRIORITY_MAXIMUM = 255; // maximum priority
//**************************************************************************
struct options_entry;
-namespace util { class core_file; }
// exception thrown by core_options when an illegal request is made
class options_exception : public std::exception
diff --git a/src/lib/util/plaparse.cpp b/src/lib/util/plaparse.cpp
index 423939b41a8..9f4d1c0bc14 100644
--- a/src/lib/util/plaparse.cpp
+++ b/src/lib/util/plaparse.cpp
@@ -68,11 +68,14 @@ static uint32_t suck_number(util::random_read &src)
uint32_t value = 0;
// find first digit
- uint8_t ch;
- std::size_t actual;
bool found = false;
- while (!src.read(&ch, 1, actual) && actual == 1)
+ while (true)
{
+ uint8_t ch;
+ auto const [err, actual] = read(src, &ch, 1);
+ if (err || (1 != actual))
+ break;
+
// loop over and accumulate digits
if (isdigit(ch))
{
@@ -189,8 +192,8 @@ static bool process_terms(jed_data *data, util::random_read &src, uint8_t ch, pa
curoutput = 0;
}
- std::size_t actual;
- if (src.read(&ch, 1, actual))
+ auto const [err, actual] = read(src, &ch, 1);
+ if (err)
return false;
if (actual != 1)
return true;
@@ -227,9 +230,11 @@ static bool process_field(jed_data *data, util::random_read &src, parse_info *pi
int destptr = 0;
uint8_t seek;
- std::size_t actual;
- while (!src.read(&seek, 1, actual) && actual == 1 && isalpha(seek))
+ while (true)
{
+ auto const [err, actual] = read(src, &seek, 1);
+ if (err || (actual != 1) || !isalpha(seek))
+ break;
dest[destptr++] = tolower(seek);
if (destptr == sizeof(dest))
break;
@@ -275,8 +280,11 @@ static bool process_field(jed_data *data, util::random_read &src, parse_info *pi
// output polarity (optional)
case KW_PHASE:
if (LOG_PARSE) printf("Phase...\n");
- while (!src.read(&seek, 1, actual) && actual == 1 && !iscrlf(seek) && pinfo->xorptr < (JED_MAX_FUSES/2))
+ while (true)
{
+ auto const [err, actual] = read(src, &seek, 1);
+ if (err || (actual != 1) || iscrlf(seek) || (pinfo->xorptr >= (JED_MAX_FUSES / 2)))
+ break;
if (seek == '0' || seek == '1')
{
// 0 is negative
@@ -322,19 +330,23 @@ int pla_parse(util::random_read &src, jed_data *result)
result->numfuses = 0;
memset(result->fusemap, 0, sizeof(result->fusemap));
- uint8_t ch;
- std::size_t actual;
- while (!src.read(&ch, 1, actual) && actual == 1)
+ while (true)
{
+ std::error_condition err;
+ size_t actual;
+ uint8_t ch;
+ std::tie(err, actual) = read(src, &ch, 1);
+ if (err || (actual != 1))
+ break;
switch (ch)
{
// comment line
case '#':
- while (!src.read(&ch, 1, actual) && actual == 1)
+ do
{
- if (iscrlf(ch))
- break;
+ std::tie(err, actual) = read(src, &ch, 1);
}
+ while (!err && (actual == 1) && !iscrlf(ch));
break;
// keyword
diff --git a/src/lib/util/png.cpp b/src/lib/util/png.cpp
index 8e077f92114..ce28a866604 100644
--- a/src/lib/util/png.cpp
+++ b/src/lib/util/png.cpp
@@ -24,6 +24,7 @@
#include <cstdlib>
#include <cstring>
#include <new>
+#include <tuple>
namespace util {
@@ -452,7 +453,7 @@ private:
std::uint8_t tempbuff[4];
// fetch the length of this chunk
- err = fp.read(tempbuff, 4, actual);
+ std::tie(err, actual) = read(fp, tempbuff, 4);
if (err)
return err;
else if (4 != actual)
@@ -460,7 +461,7 @@ private:
length = fetch_32bit(tempbuff);
// fetch the type of this chunk
- err = fp.read(tempbuff, 4, actual);
+ std::tie(err, actual) = read(fp, tempbuff, 4);
if (err)
return err;
else if (4 != actual)
@@ -477,13 +478,8 @@ private:
// read the chunk itself into an allocated memory buffer
if (length)
{
- // allocate memory for this chunk
- data.reset(new (std::nothrow) std::uint8_t [length]);
- if (!data)
- return std::errc::not_enough_memory;
-
- // read the data from the file
- err = fp.read(data.get(), length, actual);
+ // allocate memory and read the data from the file
+ std::tie(err, data, actual) = read(fp, length);
if (err)
{
data.reset();
@@ -500,7 +496,7 @@ private:
}
// read the CRC
- err = fp.read(tempbuff, 4, actual);
+ std::tie(err, actual) = read(fp, tempbuff, 4);
if (err)
{
data.reset();
@@ -789,8 +785,7 @@ public:
std::uint8_t signature[sizeof(PNG_SIGNATURE)];
// read 8 bytes
- std::size_t actual;
- std::error_condition err = fp.read(signature, sizeof(signature), actual);
+ auto const [err, actual] = read(fp, signature, sizeof(signature));
if (err)
return err;
else if (sizeof(signature) != actual)
@@ -941,7 +936,6 @@ std::error_condition png_info::add_text(std::string_view keyword, std::string_vi
static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, uint32_t type, uint32_t length) noexcept
{
std::error_condition err;
- std::size_t written;
std::uint8_t tempbuff[8];
std::uint32_t crc;
@@ -951,30 +945,24 @@ static std::error_condition write_chunk(write_stream &fp, const uint8_t *data, u
crc = crc32(0, tempbuff + 4, 4);
// write that data
- err = fp.write(tempbuff, 8, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, 8);
if (err)
return err;
- else if (8 != written)
- return std::errc::io_error;
// append the actual data
if (length > 0)
{
- err = fp.write(data, length, written);
+ std::tie(err, std::ignore) = write(fp, data, length);
if (err)
return err;
- else if (length != written)
- return std::errc::io_error;
crc = crc32(crc, data, length);
}
// write the CRC
put_32bit(tempbuff, crc);
- err = fp.write(tempbuff, 4, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, 4);
if (err)
return err;
- else if (4 != written)
- return std::errc::io_error;
return std::error_condition();
}
@@ -993,7 +981,6 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data
if (err)
return err;
- std::size_t written;
std::uint8_t tempbuff[8192];
std::uint32_t zlength = 0;
z_stream stream;
@@ -1006,11 +993,9 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data
crc = crc32(0, tempbuff + 4, 4);
// write that data
- err = fp.write(tempbuff, 8, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, 8);
if (err)
return err;
- else if (8 != written)
- return std::errc::io_error;
// initialize the stream
memset(&stream, 0, sizeof(stream));
@@ -1036,17 +1021,12 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data
if (stream.avail_out < sizeof(tempbuff))
{
int bytes = sizeof(tempbuff) - stream.avail_out;
- err = fp.write(tempbuff, bytes, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, bytes);
if (err)
{
deflateEnd(&stream);
return err;
}
- else if (bytes != written)
- {
- deflateEnd(&stream);
- return std::errc::io_error;
- }
crc = crc32(crc, tempbuff, bytes);
zlength += bytes;
}
@@ -1079,22 +1059,18 @@ static std::error_condition write_deflated_chunk(random_write &fp, uint8_t *data
// write the CRC
put_32bit(tempbuff, crc);
- err = fp.write(tempbuff, 4, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, 4);
if (err)
return err;
- else if (4 != written)
- return std::errc::io_error;
// seek back and update the length
err = fp.seek(lengthpos, SEEK_SET);
if (err)
return err;
put_32bit(tempbuff + 0, zlength);
- err = fp.write(tempbuff, 4, written);
+ std::tie(err, std::ignore) = write(fp, tempbuff, 4);
if (err)
return err;
- else if (4 != written)
- return std::errc::io_error;
// return to the end
return fp.seek(lengthpos + 8 + zlength + 4, SEEK_SET);
@@ -1326,12 +1302,9 @@ std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t
info = &pnginfo;
// write the PNG signature
- std::size_t written;
- std::error_condition err = fp.write(PNG_SIGNATURE, sizeof(PNG_SIGNATURE), written);
+ auto const [err, written] = write(fp, PNG_SIGNATURE, sizeof(PNG_SIGNATURE));
if (err)
return err;
- else if (sizeof(PNG_SIGNATURE) != written)
- return std::errc::io_error;
// write the rest of the PNG data
return write_png_stream(fp, *info, bitmap, palette_length, palette);
@@ -1347,12 +1320,9 @@ std::error_condition png_write_bitmap(random_write &fp, png_info *info, bitmap_t
std::error_condition mng_capture_start(random_write &fp, bitmap_t const &bitmap, unsigned rate) noexcept
{
- std::size_t written;
- std::error_condition err = fp.write(MNG_Signature, 8, written);
+ auto const [err, written] = write(fp, MNG_Signature, 8);
if (err)
return err;
- else if (8 != written)
- return std::errc::io_error;
uint8_t mhdr[28];
memset(mhdr, 0, 28);
diff --git a/src/lib/util/server_http_impl.hpp b/src/lib/util/server_http_impl.hpp
index e949e6b2483..7de440bce2c 100644
--- a/src/lib/util/server_http_impl.hpp
+++ b/src/lib/util/server_http_impl.hpp
@@ -63,10 +63,10 @@ namespace webpp {
}
}
public:
- virtual Response& status(int number) { m_ostream << statusToString(number); return *this; }
- virtual void type(std::string str) { m_header << "Content-Type: "<< str << "\r\n"; }
- virtual void send(std::string str) { m_ostream << m_header.str() << "Content-Length: " << str.length() << "\r\n\r\n" << str; }
- virtual size_t size() const { return m_streambuf.size(); }
+ virtual Response& status(int number) override { m_ostream << statusToString(number); return *this; }
+ virtual void type(std::string str) override { m_header << "Content-Type: "<< str << "\r\n"; }
+ virtual void send(std::string str) override { m_ostream << m_header.str() << "Content-Length: " << str.length() << "\r\n\r\n" << str; }
+ virtual size_t size() const override { return m_streambuf.size(); }
std::shared_ptr<socket_type> socket() { return m_socket; }
/// If true, force server to close the connection after the response have been sent.
diff --git a/src/lib/util/simh_tape_file.cpp b/src/lib/util/simh_tape_file.cpp
index 4fe1af5ae88..ffd6a48aeb3 100644
--- a/src/lib/util/simh_tape_file.cpp
+++ b/src/lib/util/simh_tape_file.cpp
@@ -119,16 +119,14 @@ void simh_tape_file::raw_seek(const osd::u64 pos) const
void simh_tape_file::raw_read(osd::u8 *const buf, const osd::u32 len) const
{
- size_t actual_len;
- std::error_condition err = m_file.read(buf, len, actual_len);
+ auto const [err, actual_len] = read(m_file, buf, len);
if (err || actual_len != len) // error: we failed to read expected number of bytes
throw std::runtime_error(std::string("failed read: ") + (err ? err.message() : std::string("unexpected length")));
}
void simh_tape_file::raw_write(const osd::u8 *const buf, const osd::u32 len) const
{
- size_t actual_len;
- std::error_condition err = m_file.write(buf, len, actual_len);
+ auto const [err, actual_len] = write(m_file, buf, len);
if (err || actual_len != len) // error: we failed to write expected number of bytes
throw std::runtime_error(std::string("failed write: ") + (err ? err.message() : std::string("unexpected length")));
}
diff --git a/src/lib/util/un7z.cpp b/src/lib/util/un7z.cpp
index 362c95ee235..5ee97d62777 100644
--- a/src/lib/util/un7z.cpp
+++ b/src/lib/util/un7z.cpp
@@ -71,8 +71,7 @@ private:
if (!size)
return SZ_OK;
- std::size_t read_length(0);
- std::error_condition const err = file->read_at(currfpos, data, size, read_length);
+ auto const [err, read_length] = read_at(*file, currfpos, data, size);
size = read_length;
currfpos += read_length;
diff --git a/src/lib/util/unzip.cpp b/src/lib/util/unzip.cpp
index c1df469fed4..2ca8e722d25 100644
--- a/src/lib/util/unzip.cpp
+++ b/src/lib/util/unzip.cpp
@@ -154,8 +154,7 @@ public:
while (cd_remaining)
{
std::size_t const chunk(std::size_t(std::min<std::uint64_t>(std::numeric_limits<std::size_t>::max(), cd_remaining)));
- std::size_t read_length(0);
- std::error_condition const filerr = m_file->read_at(m_ecd.cd_start_disk_offset + cd_offs, &m_cd[cd_offs], chunk, read_length);
+ auto const [filerr, read_length] = read_at(*m_file, m_ecd.cd_start_disk_offset + cd_offs, &m_cd[cd_offs], chunk);
if (filerr)
{
osd_printf_error(
@@ -914,7 +913,7 @@ std::error_condition zip_file_impl::decompress(void *buffer, std::size_t length)
}
// get the compressed data offset
- std::uint64_t offset;
+ std::uint64_t offset = 0;
auto const ziperr = get_compressed_data_offset(offset);
if (ziperr)
return ziperr;
@@ -979,7 +978,7 @@ std::error_condition zip_file_impl::read_ecd() noexcept
}
// read in one buffers' worth of data
- filerr = m_file->read_at(m_length - buflen, &buffer[0], buflen, read_length);
+ std::tie(filerr, read_length) = read_at(*m_file, m_length - buflen, &buffer[0], buflen);
if (filerr)
{
osd_printf_error(
@@ -1024,11 +1023,11 @@ std::error_condition zip_file_impl::read_ecd() noexcept
}
// try to read the ZIP64 ECD locator
- filerr = m_file->read_at(
+ std::tie(filerr, read_length) = read_at(
+ *m_file,
m_length - buflen + offset - ecd64_locator_reader::minimum_length(),
&buffer[0],
- ecd64_locator_reader::minimum_length(),
- read_length);
+ ecd64_locator_reader::minimum_length());
if (filerr)
{
osd_printf_error(
@@ -1058,7 +1057,7 @@ std::error_condition zip_file_impl::read_ecd() noexcept
}
// try to read the ZIP64 ECD
- filerr = m_file->read_at(ecd64_loc_rd.ecd64_offset(), &buffer[0], ecd64_reader::minimum_length(), read_length);
+ std::tie(filerr, read_length) = read_at(*m_file, ecd64_loc_rd.ecd64_offset(), &buffer[0], ecd64_reader::minimum_length());
if (filerr)
{
osd_printf_error(
@@ -1160,8 +1159,7 @@ std::error_condition zip_file_impl::get_compressed_data_offset(std::uint64_t &of
return ziperr;
// now go read the fixed-sized part of the local file header
- std::size_t read_length;
- std::error_condition const filerr = m_file->read_at(m_header.local_header_offset, &m_buffer[0], local_file_header_reader::minimum_length(), read_length);
+ auto const [filerr, read_length] = read_at(*m_file, m_header.local_header_offset, &m_buffer[0], local_file_header_reader::minimum_length());
if (filerr)
{
osd_printf_error(
@@ -1205,8 +1203,7 @@ std::error_condition zip_file_impl::get_compressed_data_offset(std::uint64_t &of
std::error_condition zip_file_impl::decompress_data_type_0(std::uint64_t offset, void *buffer, std::size_t length) noexcept
{
// the data is uncompressed; just read it
- std::size_t read_length(0);
- std::error_condition const filerr = m_file->read_at(offset, buffer, m_header.compressed_length, read_length);
+ auto const [filerr, read_length] = read_at(*m_file, offset, buffer, m_header.compressed_length);
if (filerr)
{
osd_printf_error(
@@ -1277,12 +1274,11 @@ std::error_condition zip_file_impl::decompress_data_type_8(std::uint64_t offset,
while (true)
{
// read in the next chunk of data
- std::size_t read_length(0);
- auto const filerr = m_file->read_at(
+ auto const [filerr, read_length] = read_at(
+ *m_file,
offset,
&m_buffer[0],
- std::size_t(std::min<std::uint64_t>(input_remaining, m_buffer.size())),
- read_length);
+ std::size_t(std::min<std::uint64_t>(input_remaining, m_buffer.size())));
if (filerr)
{
osd_printf_error(
@@ -1393,7 +1389,7 @@ std::error_condition zip_file_impl::decompress_data_type_14(std::uint64_t offset
m_header.file_name, m_filename);
return archive_file::error::DECOMPRESS_ERROR;
}
- filerr = m_file->read_at(offset, &m_buffer[0], 4, read_length);
+ std::tie(filerr, read_length) = read_at(*m_file, offset, &m_buffer[0], 4);
if (filerr)
{
osd_printf_error(
@@ -1425,7 +1421,7 @@ std::error_condition zip_file_impl::decompress_data_type_14(std::uint64_t offset
m_header.file_name, m_filename);
return archive_file::error::DECOMPRESS_ERROR;
}
- filerr = m_file->read_at(offset, &m_buffer[0], props_size, read_length);
+ std::tie(filerr, read_length) = read_at(*m_file, offset, &m_buffer[0], props_size);
if (filerr)
{
osd_printf_error(
@@ -1472,11 +1468,11 @@ std::error_condition zip_file_impl::decompress_data_type_14(std::uint64_t offset
while (0 < input_remaining)
{
// read in the next chunk of data
- filerr = m_file->read_at(
+ std::tie(filerr, read_length) = read_at(
+ *m_file,
offset,
&m_buffer[0],
- std::size_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())),
- read_length);
+ std::size_t((std::min<std::uint64_t>)(input_remaining, m_buffer.size())));
if (filerr)
{
osd_printf_error(
@@ -1569,12 +1565,11 @@ std::error_condition zip_file_impl::decompress_data_type_93(std::uint64_t offset
while (input_remaining && length)
{
// read in the next chunk of data
- std::size_t read_length(0);
- auto const filerr = m_file->read_at(
+ auto const [filerr, read_length] = read_at(
+ *m_file,
offset,
&m_buffer[0],
- std::size_t(std::min<std::uint64_t>(input_remaining, m_buffer.size())),
- read_length);
+ std::size_t(std::min<std::uint64_t>(input_remaining, m_buffer.size())));
if (filerr)
{
osd_printf_error(
diff --git a/src/lib/util/xmlfile.cpp b/src/lib/util/xmlfile.cpp
index 39604a29a87..db8d87930e2 100644
--- a/src/lib/util/xmlfile.cpp
+++ b/src/lib/util/xmlfile.cpp
@@ -41,14 +41,14 @@ constexpr unsigned TEMP_BUFFER_SIZE(4096U);
void write_escaped(core_file &file, std::string const &str)
{
+ // FIXME: check for errors
std::string::size_type pos = 0;
while ((str.size() > pos) && (std::string::npos != pos))
{
std::string::size_type const found = str.find_first_of("\"&<>", pos);
if (found != std::string::npos)
{
- std::size_t written;
- file.write(&str[pos], found - pos, written);
+ write(file, &str[pos], found - pos);
switch (str[found])
{
case '"': file.puts("&quot;"); pos = found + 1; break;
@@ -60,8 +60,7 @@ void write_escaped(core_file &file, std::string const &str)
}
else
{
- std::size_t written;
- file.write(&str[pos], str.size() - pos, written);
+ write(file, &str[pos], str.size() - pos);
pos = found;
}
}
@@ -77,10 +76,12 @@ void write_escaped(core_file &file, std::string const &str)
struct parse_info
{
+ parse_info() { memset(&parser, 0, sizeof(parser)); }
+
XML_Parser parser;
file::ptr rootnode;
- data_node * curnode;
- uint32_t flags;
+ data_node * curnode = nullptr;
+ uint32_t flags = 0;
};
@@ -134,8 +135,7 @@ file::ptr file::read(read_stream &file, parse_options const *opts)
char tempbuf[TEMP_BUFFER_SIZE];
// read as much as we can
- size_t bytes;
- file.read(tempbuf, sizeof(tempbuf), bytes); // TODO: better error handling
+ auto const [err, bytes] = util::read(file, tempbuf, sizeof(tempbuf)); // FIXME: better error handling
done = !bytes;
// parse the data
@@ -815,7 +815,7 @@ std::string normalize_string(std::string_view string)
static bool expat_setup_parser(parse_info &info, parse_options const *opts)
{
// setup info structure
- memset(&info, 0, sizeof(info));
+ info = parse_info();
if (opts != nullptr)
{
info.flags = opts->flags;