mirror of
https://github.com/holub/mame
synced 2025-04-26 10:13:37 +03:00
archimedes: Added JFD floppy format as used by JASPP (Archimedes Software Preservation Project)
This commit is contained in:
parent
d0d342d76c
commit
f224898523
@ -941,6 +941,18 @@ if (FORMATS["JVC_DSK"]~=null or _OPTIONS["with-tools"]) then
|
||||
}
|
||||
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
|
||||
|
@ -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
|
||||
|
365
src/lib/formats/jfd_dsk.cpp
Normal file
365
src/lib/formats/jfd_dsk.cpp
Normal file
@ -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>;
|
31
src/lib/formats/jfd_dsk.h
Normal file
31
src/lib/formats/jfd_dsk.h
Normal file
@ -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
|
@ -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 )
|
||||
|
Loading…
Reference in New Issue
Block a user