summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/td0_dsk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/td0_dsk.cpp')
-rw-r--r--src/lib/formats/td0_dsk.cpp208
1 files changed, 114 insertions, 94 deletions
diff --git a/src/lib/formats/td0_dsk.cpp b/src/lib/formats/td0_dsk.cpp
index 4dc3ed53cbf..956bbd002c7 100644
--- a/src/lib/formats/td0_dsk.cpp
+++ b/src/lib/formats/td0_dsk.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Miodrag Milanovic
/*********************************************************************
- formats/td0_dsk.c
+ formats/td0_dsk.cpp
TD0 disk images
@@ -14,10 +14,14 @@
* Edited and translated to English by Kenji RIKITAKE
*/
+#include "flopimg_legacy.h"
+
+#include "ioprocs.h"
+#include "multibyte.h"
+
#include <cstring>
-#include <cassert>
-#include "pool.h"
-#include "flopimg.h"
+#include <tuple>
+
#define BUFSZ 512 // new input buffer
@@ -49,17 +53,26 @@ struct td0dsk_tag
};
struct tdlzhuf {
- uint16_t r,
- bufcnt,bufndx,bufpos, // string buffer
+ uint16_t r = 0,
+ bufcnt = 0, bufndx = 0, bufpos = 0, // string buffer
// the following to allow block reads from input in next_word()
- ibufcnt,ibufndx; // input buffer counters
- uint8_t inbuf[BUFSZ]; // input buffer
+ ibufcnt = 0, ibufndx = 0; // input buffer counters
+ uint8_t inbuf[BUFSZ]{}; // input buffer
};
struct td0dsk_t
{
- io_generic *floppy_file;
+public:
+ td0dsk_t(util::random_read &f) : floppy_file(f) { }
+
+ void set_floppy_file_offset(uint64_t o) { floppy_file_offset = o; }
+
+ void init_Decode();
+ int Decode(uint8_t *buf, int len);
+
+private:
+ util::random_read &floppy_file;
uint64_t floppy_file_offset;
struct tdlzhuf tdctl;
@@ -79,7 +92,7 @@ struct td0dsk_t
uint8_t getlen;
int data_read(uint8_t *buf, uint16_t size);
- int next_word();
+ int next_word(int needed);
int GetBit();
int GetByte();
void StartHuff();
@@ -87,33 +100,10 @@ struct td0dsk_t
void update(int c);
int16_t DecodeChar();
int16_t DecodePosition();
- void init_Decode();
- int Decode(uint8_t *buf, int len);
};
//static td0dsk_t td0dsk;
-struct floppy_image_legacy
-{
- struct io_generic io;
-
- const struct FloppyFormat *floppy_option;
- struct FloppyCallbacks format;
-
- /* loaded track stuff */
- int loaded_track_head;
- int loaded_track_index;
- uint32_t loaded_track_size;
- void *loaded_track_data;
- uint8_t loaded_track_status;
- uint8_t flags;
-
- /* tagging system */
- object_pool *tags;
- void *tag_data;
-};
-
-
static struct td0dsk_tag *get_tag(floppy_image_legacy *floppy)
{
struct td0dsk_tag *tag;
@@ -186,7 +176,7 @@ static floperr_t get_offset(floppy_image_legacy *floppy, int head, int track, in
offs+= 6;
if ((header[4] & 0x30)==0) {
offs+= 2;
- offs+= header[6] + (header[7]<<8);
+ offs+= get_u16le(&header[6]);
}
}
// read size of sector
@@ -225,7 +215,7 @@ static floperr_t internal_td0_read_sector(floppy_image_legacy *floppy, int head,
offset+=3;
// take data size
- size = header[6] + (header[7]<<8)-1;
+ size = get_u16le(&header[6])-1;
// take real sector size
realsize = 1 << (header[3] + 7);
@@ -246,7 +236,7 @@ static floperr_t internal_td0_read_sector(floppy_image_legacy *floppy, int head,
// - 2 bytes of data
// data is reapeted specified number of times
while(buff_pos<realsize) {
- for (i=0;i<data[data_pos]+(data[data_pos+1] << 8);i++) {
+ for (i=0;i<get_u16le(&data[data_pos]);i++) {
buf[buff_pos] = data[data_pos+2];buff_pos++;
buf[buff_pos] = data[data_pos+3];buff_pos++;
}
@@ -336,11 +326,12 @@ static floperr_t td0_get_indexed_sector_info(floppy_image_legacy *floppy, int he
int td0dsk_t::data_read(uint8_t *buf, uint16_t size)
{
- uint64_t image_size = io_generic_size(floppy_file);
+ uint64_t image_size = 0;
+ floppy_file.length(image_size);
if (size > image_size - floppy_file_offset) {
size = image_size - floppy_file_offset;
}
- io_generic_read(floppy_file,buf,floppy_file_offset,size);
+ /*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;
}
@@ -422,16 +413,15 @@ static const uint8_t d_len[256] = {
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
};
-int td0dsk_t::next_word()
+int td0dsk_t::next_word(int needed)
{
- if(tdctl.ibufndx >= tdctl.ibufcnt)
- {
- tdctl.ibufndx = 0;
- tdctl.ibufcnt = data_read(tdctl.inbuf,BUFSZ);
- if(tdctl.ibufcnt <= 0)
- return(-1);
- }
while (getlen <= 8) { // typically reads a word at a time
+ if(tdctl.ibufndx >= tdctl.ibufcnt) {
+ tdctl.ibufndx = 0;
+ tdctl.ibufcnt = data_read(tdctl.inbuf,BUFSZ);
+ if(tdctl.ibufcnt <= 0)
+ return(getlen >= needed ? 0 : -1);
+ }
getbuf |= tdctl.inbuf[tdctl.ibufndx++] << (8 - getlen);
getlen += 8;
}
@@ -442,7 +432,7 @@ int td0dsk_t::next_word()
int td0dsk_t::GetBit() /* get one bit */
{
int16_t i;
- if(next_word() < 0)
+ if(next_word(1) < 0)
return(-1);
i = getbuf;
getbuf <<= 1;
@@ -456,7 +446,7 @@ int td0dsk_t::GetBit() /* get one bit */
int td0dsk_t::GetByte() /* get a byte */
{
uint16_t i;
- if(next_word() != 0)
+ if(next_word(8) != 0)
return(-1);
i = getbuf;
getbuf <<= 8;
@@ -653,7 +643,7 @@ int td0dsk_t::Decode(uint8_t *buf, int len) /* Decoding/Uncompressing */
}
else {
if((pos = DecodePosition()) < 0)
- return(count); // fatal error
+ return(count); // fatal error
tdctl.bufpos = (tdctl.r - pos - 1) & (N - 1);
tdctl.bufcnt = c - 255 + THRESHOLD;
tdctl.bufndx = 0;
@@ -679,7 +669,6 @@ int td0dsk_t::Decode(uint8_t *buf, int len) /* Decoding/Uncompressing */
FLOPPY_CONSTRUCT( td0_dsk_construct )
{
- td0dsk_t state;
struct FloppyCallbacks *callbacks;
struct td0dsk_tag *tag;
uint8_t *header;
@@ -710,9 +699,9 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
int rd;
int off = 12;
int size = 0;
- state.floppy_file = &(floppy->io);
+ td0dsk_t state(floppy_get_io(floppy));
state.init_Decode();
- state.floppy_file_offset = 12;
+ state.set_floppy_file_offset(12);
do
{
if((rd = state.Decode(obuf, BUFSZ)) > 0) size += rd;
@@ -724,7 +713,7 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
return FLOPPY_ERROR_OUTOFMEMORY;
}
memcpy(tag->data,obuf,12);
- state.floppy_file_offset = 12;
+ state.set_floppy_file_offset(12);
state.init_Decode();
do
{
@@ -743,7 +732,7 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
// header len + comment header + comment len
position = 12;
if (header[7] & 0x80) {
- position += 10 + header[14] + (header[15]<<8);
+ position += 10 + get_u16le(&header[14]);
}
tag->tracks = 0;
do {
@@ -764,7 +753,7 @@ FLOPPY_CONSTRUCT( td0_dsk_construct )
header = tag->data + position;
position+=2;
// skip sector data
- position+= header[0] + (header[1]<<8);
+ position+= get_u16le(&header[0]);
}
}
tag->tracks++;
@@ -792,7 +781,7 @@ FLOPPY_DESTRUCT( td0_dsk_destruct )
/*********************************************************************
- formats/td0_dsk.h
+ formats/td0_dsk.cpp
Teledisk disk images
@@ -804,60 +793,75 @@ td0_format::td0_format()
{
}
-const char *td0_format::name() const
+const char *td0_format::name() const noexcept
{
return "td0";
}
-const char *td0_format::description() const
+const char *td0_format::description() const noexcept
{
return "Teledisk disk image";
}
-const char *td0_format::extensions() const
+const char *td0_format::extensions() const noexcept
{
return "td0";
}
-int td0_format::identify(io_generic *io, uint32_t form_factor)
+int td0_format::identify(util::random_read &io, uint32_t form_factor, const std::vector<uint32_t> &variants) const
{
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_generic_read(io, h, 0, 7);
if(((h[0] == 'T') && (h[1] == 'D')) || ((h[0] == 't') && (h[1] == 'd')))
{
- return 100;
+ return FIFID_SIGN;
}
return 0;
}
-bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
+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;
int track_spt;
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];
- io_generic_read(io, header, 0, 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];
if(header[0] == 't')
{
- td0dsk_t disk_decode;
+ td0dsk_t disk_decode(io);
- disk_decode.floppy_file = io;
disk_decode.init_Decode();
- disk_decode.floppy_file_offset = 12;
- disk_decode.Decode(&imagebuf[0], max_size);
+ disk_decode.set_floppy_file_offset(12);
+ actual = disk_decode.Decode(&imagebuf[0], max_size);
}
else
- io_generic_read(io, &imagebuf[0], 12, io_generic_size(io));
+ {
+ uint64_t image_size;
+ if(io.length(image_size))
+ return false;
+ std::tie(err, actual) = read_at(io, 12, &imagebuf[0], image_size - 12);
+ if(err || (actual != (image_size - 12)))
+ return false;
+ }
+ // skip optional comment section
if(header[7] & 0x80)
- offset = 10 + imagebuf[2] + (imagebuf[3] << 8);
+ offset = 10 + get_u16le(&imagebuf[2]);
track_spt = imagebuf[offset];
if(track_spt == 255) // Empty file?
@@ -869,44 +873,45 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
if((imagebuf[offset + 2] & 0x7f) == 2) // ?
{
if(head_count == 2)
- image->set_variant(floppy_image::DSHD);
+ image.set_variant(floppy_image::DSHD);
else
return false; // single side hd?
break;
}
- /* no break; could be qd, won't know until tracks are counted */
+ // could be qd, won't know until tracks are counted
+ [[fallthrough]];
case 1:
if(head_count == 2)
- image->set_variant(floppy_image::DSDD);
+ image.set_variant(floppy_image::DSDD);
else
- image->set_variant(floppy_image::SSDD);
+ image.set_variant(floppy_image::SSDD);
break;
case 4:
if((imagebuf[offset + 2] & 0x7f) == 2) // ?
{
if(head_count == 2)
- image->set_variant(floppy_image::DSHD);
+ image.set_variant(floppy_image::DSHD);
else
return false; // single side 3.5?
break;
} else
- image->set_variant(floppy_image::SSDD);
- break;
+ image.set_variant(floppy_image::SSDD);
+ break; // FIXME: comment below says "no break" but this is a breal
/* no break */
case 3:
if(head_count == 2)
{
if(form_factor == floppy_image::FF_525)
- image->set_variant(floppy_image::DSQD);
+ image.set_variant(floppy_image::DSQD);
else
- image->set_variant(floppy_image::DSDD);
+ image.set_variant(floppy_image::DSDD);
}
else
{
if(form_factor == floppy_image::FF_525)
- image->set_variant(floppy_image::SSQD);
+ image.set_variant(floppy_image::SSQD);
else
- return false; // single side 3.5?
+ image.set_variant(floppy_image::SSDD);
}
break;
case 5:
@@ -922,6 +927,9 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
while(track_spt != 255)
{
+ if(actual < offset + 4)
+ return false;
+
desc_pc_sector sects[256];
uint8_t sect_data[65536];
int sdatapos = 0;
@@ -931,6 +939,9 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
offset += 4;
for(int i = 0; i < track_spt; i++)
{
+ if(actual < offset + 6)
+ return false;
+
uint8_t *hs = &imagebuf[offset];
uint16_t size;
offset += 6;
@@ -947,6 +958,8 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
else
{
offset += 3;
+ if(actual < offset)
+ return false;
size = 128 << hs[3];
int j, k;
switch(hs[8])
@@ -954,12 +967,16 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
default:
return false;
case 0:
+ if(actual < offset + size)
+ return false;
memcpy(&sect_data[sdatapos], &imagebuf[offset], size);
offset += size;
break;
case 1:
offset += 4;
- k = (hs[9] + (hs[10] << 8)) * 2;
+ if(actual < offset)
+ return false;
+ k = get_u16le(&hs[9]) * 2;
k = (k <= size) ? k : size;
for(j = 0; j < k; j += 2)
{
@@ -973,11 +990,15 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
k = 0;
while(k < size)
{
+ if(actual < offset + 2)
+ return false;
uint16_t len = imagebuf[offset];
uint16_t rep = imagebuf[offset + 1];
offset += 2;
if(!len)
{
+ if(actual < offset + rep)
+ return false;
memcpy(&sect_data[sdatapos + k], &imagebuf[offset], rep);
offset += rep;
k += rep;
@@ -985,6 +1006,8 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
else
{
len = (1 << len);
+ if(actual < offset + len)
+ return false;
rep = len * rep;
rep = ((rep + k) <= size) ? rep : (size - k);
for(j = 0; j < rep; j += len)
@@ -1014,27 +1037,24 @@ bool td0_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
else
build_pc_track_mfm(track, head, image, base_cell_count*2, track_spt, sects, calc_default_pc_gap3_size(form_factor, sects[0].actual_size));
+ if(actual <= offset)
+ return false;
track_spt = imagebuf[offset];
}
if((track_count > 50) && (form_factor == floppy_image::FF_525)) // ?
{
- if(image->get_variant() == floppy_image::DSDD)
- image->set_variant(floppy_image::DSQD);
- else if(image->get_variant() == floppy_image::SSDD)
- image->set_variant(floppy_image::SSQD);
+ if(image.get_variant() == floppy_image::DSDD)
+ image.set_variant(floppy_image::DSQD);
+ else if(image.get_variant() == floppy_image::SSDD)
+ image.set_variant(floppy_image::SSQD);
}
return true;
}
-bool td0_format::save(io_generic *io, floppy_image *image)
-{
- return false;
-}
-
-bool td0_format::supports_save() const
+bool td0_format::supports_save() const noexcept
{
return false;
}
-const floppy_format_type FLOPPY_TD0_FORMAT = &floppy_image_format_creator<td0_format>;
+const td0_format FLOPPY_TD0_FORMAT;