summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Nigel Barnes <Pernod70@users.noreply.github.com>2017-03-23 18:59:43 +0000
committer Nigel Barnes <Pernod70@users.noreply.github.com>2017-03-23 20:47:26 +0000
commitf2248985239ceb1325d25e8df218ced1556156b2 (patch)
tree03ab749e7afc0db40aaaf5de1803bc707f9b57ea
parentd0d342d76c53b992f3717d5a800c1d9fd62cd0cc (diff)
archimedes: Added JFD floppy format as used by JASPP (Archimedes Software Preservation Project)
-rw-r--r--scripts/src/formats.lua12
-rw-r--r--scripts/target/mame/mess.lua1
-rw-r--r--src/lib/formats/jfd_dsk.cpp365
-rw-r--r--src/lib/formats/jfd_dsk.h31
-rw-r--r--src/mame/drivers/aa310.cpp4
5 files changed, 412 insertions, 1 deletions
diff --git a/scripts/src/formats.lua b/scripts/src/formats.lua
index 81ab80f32be..ba20df392a0 100644
--- a/scripts/src/formats.lua
+++ b/scripts/src/formats.lua
@@ -943,6 +943,18 @@ end
--------------------------------------------------
--
+--@src/lib/formats/jfd_dsk.h,FORMATS["JFD_DSK"] = true
+--------------------------------------------------
+
+if (FORMATS["JFD_DSK"]~=null or _OPTIONS["with-tools"]) then
+ files {
+ MAME_DIR.. "src/lib/formats/jfd_dsk.cpp",
+ MAME_DIR.. "src/lib/formats/jfd_dsk.h",
+ }
+end
+
+--------------------------------------------------
+--
--@src/lib/formats/kaypro_dsk.h,FORMATS["KAYPRO_DSK"] = true
--------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 8541d09070f..9abd10c5439 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -802,6 +802,7 @@ FORMATS["HECT_TAP"] = true
FORMATS["HP_IPC_DSK"] = true
FORMATS["IQ151_DSK"] = true
FORMATS["ITT3030_DSK"] = true
+FORMATS["JFD_DSK"] = true
FORMATS["JVC_DSK"] = true
FORMATS["KAYPRO_DSK"] = true
FORMATS["KC85_DSK"] = true
diff --git a/src/lib/formats/jfd_dsk.cpp b/src/lib/formats/jfd_dsk.cpp
new file mode 100644
index 00000000000..d0d55bb0c68
--- /dev/null
+++ b/src/lib/formats/jfd_dsk.cpp
@@ -0,0 +1,365 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*********************************************************************
+
+ formats/jfd_dsk.c
+
+ JASPP Floppy Disk image format
+
+ JFD file structure
+ ------------------
+
+ A JFD file is a gzip compressed version of the original JFD
+ file.
+
+ Official files should be named "[optional text name] Fxxxxxnn"
+ (see below for xxxx / nn explanation) eg "Fire & Ice (1995)
+ (Warner Interactive Entertainment) F1015401" or shortened to
+ "F1015401" on an Arc that doesn't support long file names.
+
+ Compressed file always starts:
+ 1F 8B 08 00 00 00 00 00 00 0B EC BD
+ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
+ | | | | | | | | | |
+ | | | | | | | | | +- OS
+ | | | | | | | | +---- xfl
+ | | | | +--+--+--+------- time
+ | | | +------------------- gzip flags
+ | | +---------------------- gzip compression*
+ | |
+ +--+------------------------- gzip header
+
+ * Compression method: 8 is the only supported format
+
+
+ Original JFD file structure:
+
+ +0 "JFDI" identifier
+ +4 Min. version of ADFFS required to handle file * 100
+ eg 1.25 would be 125
+ +8 Memory allocation required to load file in bytes
+ ie uncompressed file size
+ +12 Disc sequence number - SSSSnnnn
+ Where:
+ SSSS is the number of discs in this set
+ nnnn is the number of this disc
+ +16 Game ID number (xxxxx) - official release ID of this
+ floppy set. Unofficial releases should be an ID of zero
+ +20 Image version number: VVVwwwww
+ Where:
+ VVV - major release version, 0 being initial release
+ wwwww - minor version, reset to 0 on a major release
+ and is incremented on each flush / save as
+ +24 Offset to Track Table, the end of which is denoted by
+ the start of the Sector Table
+ +28 Offset to Sector Table, end of which is denoted by
+ the start of the Data Table
+ +32 Offset to Data Table
+ +36 Offset to optional Delta Track Table. Changes to the
+ Track table are written here post initial release
+ 0 denotes not present
+ +40 Offset to optional Delta Sector Table. Changes to the
+ Sector table are written here post initial release
+ 0 denotes not present
+ +44 Offset to optional Delta Data Table. Changes to the
+ Data table are written here post initial release
+ 0 denotes not present
+ +48 Disc title. eg "Fire & Ice (1995) (Warner Interactive
+ Entertainment) disc 1 of 2", zero terminated.
+ +304 ... future expansion space (additions in 2.04+)
+
+ +304 Bit flags:
+ 0 - Disk write protected
+ 1 - Disk is RW, write delta changes back to JFD
+ 2 - Protect CMOS required
+ 3 - Protect Modules required
+ 4 - Hide Hourglass
+ 5 - Requires Shift-Break to load
+ 6 - Remap video memory to 1FFFFFF downwards
+
+ 8 - ARM3 compatible
+ 9 - ARM250 compatible
+ 10 - ARM610/710 compatible
+ 11 - ARM7500 compatible
+ 12 - StrongArm compatible
+ 13 = ARMv5/v5/v7 compatible
+
+ 16 - RiscOS 2 compatible
+ 17 - RiscOS 3.1 compatible
+ 18 - RiscOS 3.5 compatible
+ 19 - RiscOS 3.7 compatible
+ 20 - RiscOS 3.8 / 4.x compatible
+ 21 - RiscOS 5.x compatible
+ 22 - RiscOS 6.x compatible
+ +308 FPS of the original game * 2 (eg for 12.5 FPS use 25)
+ +309 - 311 reserved
+ +312 Length of Obey file in bytes
+ +316 ... future expansion space (currently 0 bytes)
+
+ [Track Table]
+ +0 Track 0 offset within Sector Table
+ +4 Track 1 offset within Sector Table
+ ...
+ +n*4 Track n offset within Sector Table
+ n can be any value, although to allow writes should be at
+ least 160. For reference, APD's are 166
+ A blank track is denoted by FFFFFFFF
+
+ [Sector Table]
+ +0 ttBdnnCs - Sector Header description (see below)
+ +4 Offset within Data Table of sector data, if this value is
+ FFFFFFFF no data is associated with the sector. In the
+ case of a sector with a CRC flag set in C set, the sector
+ is a stub to produce a specific error.
+
+ .. repeats for all sectors in track, two doubles (ie 8 bytes) per
+ sector
+
+ +n FFFFFFFF - end of track marker
+
+ The above repeats for all tracks containing sector data.
+
+
+ [Data Table]
+ ... X bytes of sector data in native byte format.
+ Not necessarily in disc order, as sectors are located
+ individually during reads.
+
+ [Obey file]
+ ... Obey file used to boot the floppy
+
+
+ Sector Header description: ttBdnnCs
+ Where:
+
+ tt - time of sector from start of index marker in milliseconds
+ max being 200 (optional, required for duplicate sectors)
+ B - Option bits
+ bit 0 - sector data contains DiscOp 3 data for the track
+ bit 1 - reserved
+ bit 2 - reserved
+ bit 3 - reserved
+ d - Density value, where:
+ 1 - single
+ 2 - double
+ 4 - quad
+ 8 - octal
+ nn - Sector number
+ C - CRC bits, where:
+ bit 0 - ID CRC invalid
+ bit 1 - Data CRC invalid
+ bit 2 - reserved
+ bit 3 - Slow sector (read at normal floppy speed)
+ s - 1772 sector size, where:
+ 0 - 128 bytes
+ 1 - 256 bytes
+ 2 - 512 bytes
+ 3 - 1024 bytes
+
+*********************************************************************/
+
+#include <zlib.h>
+#include "formats/jfd_dsk.h"
+
+static const uint8_t JFD_HEADER[4] = { 'J', 'F', 'D', 'I' };
+static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b };
+
+jfd_format::jfd_format()
+{
+}
+
+const char *jfd_format::name() const
+{
+ return "jfd";
+}
+
+const char *jfd_format::description() const
+{
+ return "JASPP Floppy Disk image";
+}
+
+const char *jfd_format::extensions() const
+{
+ return "jfd";
+}
+
+int jfd_format::identify(io_generic *io, uint32_t form_factor)
+{
+ uint64_t size = io_generic_size(io);
+ std::vector<uint8_t> img(size);
+ io_generic_read(io, &img[0], 0, size);
+
+ int err;
+ std::vector<uint8_t> gz_ptr(4);
+ z_stream d_stream;
+
+ if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) {
+ d_stream.zalloc = nullptr;
+ d_stream.zfree = nullptr;
+ d_stream.opaque = nullptr;
+ d_stream.next_in = &img[0];
+ d_stream.avail_in = size;
+ d_stream.next_out = &gz_ptr[0];
+ d_stream.avail_out = 4;
+
+ err = inflateInit2(&d_stream, MAX_WBITS | 16);
+ if (err != Z_OK) return 0;
+
+ err = inflate(&d_stream, Z_SYNC_FLUSH);
+ if (err != Z_OK) return 0;
+
+ err = inflateEnd(&d_stream);
+ if (err != Z_OK) return 0;
+
+ img = gz_ptr;
+ }
+
+ if (!memcmp(&img[0], JFD_HEADER, sizeof(JFD_HEADER))) {
+ return 100;
+ }
+
+ return 0;
+}
+
+bool jfd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+{
+ uint64_t size = io_generic_size(io);
+ std::vector<uint8_t> img(size);
+ io_generic_read(io, &img[0], 0, size);
+
+ int err;
+ std::vector<uint8_t> gz_ptr;
+ z_stream d_stream;
+ int inflate_size = (img[size - 1] << 24) | (img[size - 2] << 16) | (img[size - 3] << 8) | img[size - 4];
+
+ if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) {
+ gz_ptr.resize(inflate_size);
+
+ d_stream.zalloc = nullptr;
+ d_stream.zfree = nullptr;
+ d_stream.opaque = nullptr;
+ d_stream.next_in = &img[0];
+ d_stream.avail_in = size;
+ d_stream.next_out = &gz_ptr[0];
+ d_stream.avail_out = inflate_size;
+
+ err = inflateInit2(&d_stream, MAX_WBITS | 16);
+ if (err != Z_OK) {
+ osd_printf_error("inflateInit2 error: %d\n", err);
+ return false;
+ }
+ err = inflate(&d_stream, Z_FINISH);
+ if (err != Z_STREAM_END && err != Z_OK) {
+ osd_printf_error("inflate error: %d\n", err);
+ return false;
+ }
+ err = inflateEnd(&d_stream);
+ if (err != Z_OK) {
+ osd_printf_error("inflateEnd error: %d\n", err);
+ return false;
+ }
+ size = inflate_size;
+ img = gz_ptr;
+ }
+
+ osd_printf_verbose("jfd_dsk: loading %s\n", &img[48]);
+
+ uint32_t offset_track = little_endianize_int32(*(uint32_t *)(&img[24])); /* Track Table */
+ uint32_t offset_sector = little_endianize_int32(*(uint32_t *)(&img[28])); /* Sector Table */
+ uint32_t offset_data = little_endianize_int32(*(uint32_t *)(&img[32])); /* Data Table */
+
+ desc_pc_sector sects[256];
+ uint8_t den[256];
+ uint8_t spt, ssize;
+ uint32_t header, discop3;
+ std::vector<uint32_t> track_data;
+
+ int track_count = (offset_sector - offset_track) / 4;
+
+ for (int track = 0; track < track_count; track++) {
+ uint32_t track_offset = little_endianize_int32(*(uint32_t *)(&img[offset_track + (track * 4)]));
+ spt = 0;
+ discop3 = 0;
+
+ if (track_offset == 0xffffffff) /* unformatted track */
+ {
+ den[0] = 2;
+ sects[0].track = track / 2;
+ sects[0].head = track % 2;
+ sects[0].sector = 0;
+ sects[0].size = 0;
+ }
+ else
+ {
+ for (int i = 0; i < 256; i++) {
+ header = little_endianize_int32(*(uint32_t *)(&img[offset_sector + track_offset + (i * 8)])); /* Sector Header */
+ if (header == 0xffffffff)
+ break;
+
+ uint32_t data_offset = little_endianize_int32(*(uint32_t *)(&img[offset_sector + track_offset + (i * 8) + 4]));
+
+ den[i] = (header >> 16) & 0x0f; /* sector density */
+ if (den[i] != 2)
+ {
+ osd_printf_warning("jfd_dsk: track %d sector %d is %s density, not supported\n", track, i, den[0] == 1 ? "single" : "quad");
+ }
+ if (((header >> 20) & 0x0f) == 0x01) /* DiscOp3 data */
+ {
+ discop3 = little_endianize_int32(*(uint32_t *)(&img[offset_data + data_offset]));
+ for (int i = 0; i < discop3; i++)
+ {
+ mfm_w(track_data, 8, img[offset_data + data_offset + 4 + i]);
+ }
+ osd_printf_warning("jfd_dsk: track %d contains DiscOp3 data (@%x), not supported\n", track, offset_data + data_offset);
+ break;
+ }
+ else
+ {
+ spt = i + 1;
+ sects[i].track = track / 2;
+ sects[i].head = track % 2;
+ sects[i].sector = (header >> 8) & 0xff;
+ sects[i].bad_crc = (header >> 4) & 0x02;
+ sects[i].deleted = false;
+ ssize = header & 0x03;
+ sects[i].size = ssize;
+ if (data_offset != 0xffffffff)
+ {
+ sects[i].actual_size = 128 << ssize;
+ sects[i].data = &img[offset_data + data_offset];
+ }
+ else
+ {
+ sects[i].actual_size = 0;
+ }
+ if (((header >> 24) & 0xff) != 0xff) /* Sector in sector */
+ {
+ osd_printf_warning("jfd_dsk: track %d sector %d specifies time of sector from start of index marker, not supported\n", track, i);
+ }
+ }
+ }
+ }
+
+ if (discop3)
+ {
+ generate_track_from_levels(track / 2, track % 2, track_data, 0, image);
+ }
+ else
+ {
+ if (den[0] == 1)
+ build_wd_track_fm(track / 2, track % 2, image, 50000, spt, sects, 10, 40, 10);
+ else
+ build_wd_track_mfm(track / 2, track % 2, image, den[0] * 50000, spt, sects, 90, 32, 22);
+ }
+ }
+ image->set_variant(floppy_image::DSDD);
+
+ return true;
+}
+
+bool jfd_format::supports_save() const
+{
+ return false;
+}
+
+const floppy_format_type FLOPPY_JFD_FORMAT = &floppy_image_format_creator<jfd_format>;
diff --git a/src/lib/formats/jfd_dsk.h b/src/lib/formats/jfd_dsk.h
new file mode 100644
index 00000000000..38374bfb97c
--- /dev/null
+++ b/src/lib/formats/jfd_dsk.h
@@ -0,0 +1,31 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/*********************************************************************
+
+ formats/jfd_dsk.h
+
+ JASPP Floppy Disk image format
+
+*********************************************************************/
+
+#ifndef JFD_DSK_H_
+#define JFD_DSK_H_
+
+#include "flopimg.h"
+
+class jfd_format : public floppy_image_format_t {
+public:
+ jfd_format();
+
+ virtual const char *name() const override;
+ virtual const char *description() const override;
+ virtual const char *extensions() const override;
+
+ virtual int identify(io_generic *io, uint32_t form_factor) override;
+ virtual bool load(io_generic *io, uint32_t form_factor, floppy_image *image) override;
+ virtual bool supports_save() const override;
+};
+
+extern const floppy_format_type FLOPPY_JFD_FORMAT;
+
+#endif
diff --git a/src/mame/drivers/aa310.cpp b/src/mame/drivers/aa310.cpp
index 69e29745673..de81fa4514a 100644
--- a/src/mame/drivers/aa310.cpp
+++ b/src/mame/drivers/aa310.cpp
@@ -89,6 +89,7 @@
#include "cpu/arm/arm.h"
#include "formats/acorn_dsk.h"
#include "formats/apd_dsk.h"
+#include "formats/jfd_dsk.h"
#include "machine/i2cmem.h"
#include "machine/ram.h"
#include "machine/wd_fdc.h"
@@ -355,7 +356,8 @@ INPUT_PORTS_END
FLOPPY_FORMATS_MEMBER( aa310_state::floppy_formats )
FLOPPY_ACORN_ADFS_NEW_FORMAT,
FLOPPY_ACORN_ADFS_OLD_FORMAT,
- FLOPPY_APD_FORMAT
+ FLOPPY_APD_FORMAT,
+ FLOPPY_JFD_FORMAT
FLOPPY_FORMATS_END
static SLOT_INTERFACE_START( aa310_floppies )