summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/lib/formats/apridisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/lib/formats/apridisk.c')
-rw-r--r--trunk/src/lib/formats/apridisk.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/trunk/src/lib/formats/apridisk.c b/trunk/src/lib/formats/apridisk.c
new file mode 100644
index 00000000000..1998a72acfc
--- /dev/null
+++ b/trunk/src/lib/formats/apridisk.c
@@ -0,0 +1,226 @@
+/***************************************************************************
+
+ APRIDISK disk image format
+
+***************************************************************************/
+
+#include "apridisk.h"
+#include "imageutl.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define APR_HEADER_SIZE 128
+
+/* sector types */
+#define APR_DELETED 0xe31d0000
+#define APR_MAGIC 0xe31d0001
+#define APR_COMMENT 0xe31d0002
+#define APR_CREATOR 0xe31d0003
+
+/* compression type */
+#define APR_UNCOMPRESSED 0x9e90
+#define APR_COMPRESSED 0x3e5a
+
+static const char *apr_magic = "ACT Apricot disk image\x1a\x04";
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+struct apr_sector
+{
+ int head;
+ int track;
+ int sector;
+ UINT8 data[512];
+};
+
+struct apr_tag
+{
+ int heads;
+ int tracks;
+ int sectors_per_track;
+ struct apr_sector sectors[2880];
+ char *comment;
+};
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+/* sector format:
+ *
+ * 00-03: sector type
+ * 04-05: compression type
+ * 06-07: header size
+ * 08-11: data size
+ * 12-13: track
+ * 14: head
+ * 15: sector
+ */
+
+static floperr_t apr_read_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen)
+{
+ struct apr_tag *tag = (apr_tag *)floppy_tag(floppy);
+// printf("apr_read_sector %d %d %d\n", head, track, sector);
+ memcpy(buffer, tag->sectors[head * track * sector].data, buflen);
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+static floperr_t apr_read_indexed_sector(floppy_image_legacy *floppy, int head, int track, int sector, void *buffer, size_t buflen)
+{
+ struct apr_tag *tag = (apr_tag *)floppy_tag(floppy);
+// printf("apr_read_indexed_sector %d %d %d\n", head, track, sector);
+ memcpy(buffer, tag->sectors[head * track * sector].data, buflen);
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+/* sector length is always 512 byte */
+static floperr_t apr_get_sector_length(floppy_image_legacy *floppy, int head, int track, int sector, UINT32 *sector_length)
+{
+ *sector_length = 512;
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+static int apr_get_heads_per_disk(floppy_image_legacy *floppy)
+{
+ struct apr_tag *tag = (apr_tag *)floppy_tag(floppy);
+ return tag->heads;
+}
+
+static int apr_get_tracks_per_disk(floppy_image_legacy *floppy)
+{
+ struct apr_tag *tag = (apr_tag *)floppy_tag(floppy);
+ return tag->tracks;
+}
+
+static floperr_t apr_get_indexed_sector_info(floppy_image_legacy *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
+{
+ struct apr_tag *tag = (apr_tag *)floppy_tag(floppy);
+
+// printf("apr_get_indexed_sector_info %d %d %d\n", head, track, sector_index);
+
+ /* sanity checks */
+ if (head < 0 || head > (tag->heads - 1)) return FLOPPY_ERROR_SEEKERROR;
+ if (track < 0 || track > (tag->tracks - 1)) return FLOPPY_ERROR_SEEKERROR;
+ if (sector_index < 0 || sector_index > (tag->sectors_per_track - 1)) return FLOPPY_ERROR_SEEKERROR;
+
+ if (cylinder) *cylinder = tag->sectors[head * track * sector_index].track;
+ if (side) *side = tag->sectors[head * track * sector_index].head;
+ if (sector) *sector = tag->sectors[head * track * sector_index].sector;
+ if (sector_length) *sector_length = 512;
+
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+FLOPPY_IDENTIFY( apridisk_identify )
+{
+ UINT8 header[APR_HEADER_SIZE];
+
+ /* get header */
+ floppy_image_read(floppy, &header, 0, sizeof(header));
+
+ /* look for the magic string */
+ if (memcmp(header, apr_magic, sizeof(*apr_magic)) == 0)
+ *vote = 100;
+ else
+ *vote = 0;
+
+ return FLOPPY_ERROR_SUCCESS;
+}
+
+FLOPPY_CONSTRUCT( apridisk_construct )
+{
+ struct FloppyCallbacks *callbacks;
+ struct apr_tag *tag;
+
+ int cur_sector = 0;
+ UINT8 sector_header[16];
+ UINT64 pos = 128;
+ UINT32 type;
+
+ tag = (apr_tag *)floppy_create_tag(floppy, sizeof(struct apr_tag));
+
+ if (!tag)
+ return FLOPPY_ERROR_OUTOFMEMORY;
+
+ tag->heads = 0;
+ tag->tracks = 0;
+ tag->sectors_per_track = 0;
+
+ floppy_image_read(floppy, &sector_header, pos, 16);
+ type = pick_integer_le(&sector_header, 0, 4);
+
+ while (type == APR_DELETED || type == APR_MAGIC || type == APR_COMMENT || type == APR_CREATOR)
+ {
+ UINT16 compression = pick_integer_le(&sector_header, 4, 2);
+ UINT16 header_size = pick_integer_le(&sector_header, 6, 2);
+ UINT32 data_size = pick_integer_le(&sector_header, 8, 4);
+
+ tag->sectors[cur_sector].head = pick_integer_le(&sector_header, 12, 1);
+ tag->sectors[cur_sector].sector = pick_integer_le(&sector_header, 13, 1);
+ tag->sectors[cur_sector].track = pick_integer_le(&sector_header, 14, 1);
+
+ pos += header_size;
+
+ if (type == APR_MAGIC)
+ {
+ if (compression == APR_UNCOMPRESSED)
+ {
+ floppy_image_read(floppy, &tag->sectors[cur_sector].data, pos, data_size);
+
+ }
+ else if (compression == APR_COMPRESSED)
+ {
+ UINT8 *buffer = (UINT8 *)osd_malloc(data_size * sizeof(UINT8));
+ UINT16 length;
+ UINT8 value;
+
+ floppy_image_read(floppy, buffer, pos, data_size);
+
+ length = pick_integer_le(buffer, 0, 2);
+ value = pick_integer_le(buffer, 2, 1);
+
+ osd_free(buffer);
+
+ /* not sure if this is possible */
+ if (length != 512) {
+ printf("Compression unsupported");
+ exit(-1);
+ }
+
+ memset(&tag->sectors[cur_sector].data, value, length);
+ }
+ else
+ return FLOPPY_ERROR_INVALIDIMAGE;
+
+ tag->heads = MAX(tag->sectors[cur_sector].head, tag->heads);
+ tag->tracks = MAX(tag->sectors[cur_sector].track, tag->tracks);
+ tag->sectors_per_track = MAX(tag->sectors[cur_sector].sector, tag->sectors_per_track);
+ }
+
+ /* seek to next sector */
+ pos += data_size;
+ cur_sector++;
+
+ floppy_image_read(floppy, &sector_header, pos, 16);
+ type = pick_integer_le(&sector_header, 0, 4);
+ }
+
+ tag->heads++;
+ tag->tracks++;
+
+ callbacks = floppy_callbacks(floppy);
+ callbacks->read_sector = apr_read_sector;
+ callbacks->read_indexed_sector = apr_read_indexed_sector;
+ callbacks->get_sector_length = apr_get_sector_length;
+ callbacks->get_heads_per_disk = apr_get_heads_per_disk;
+ callbacks->get_tracks_per_disk = apr_get_tracks_per_disk;
+ callbacks->get_indexed_sector_info = apr_get_indexed_sector_info;
+
+ return FLOPPY_ERROR_SUCCESS;
+}