diff options
Diffstat (limited to 'src/lib/formats')
-rw-r--r-- | src/lib/formats/apd_dsk.cpp | 145 | ||||
-rw-r--r-- | src/lib/formats/apd_dsk.h | 31 | ||||
-rw-r--r-- | src/lib/formats/tzx_cas.cpp | 77 | ||||
-rw-r--r-- | src/lib/formats/tzx_cas.h | 2 | ||||
-rw-r--r-- | src/lib/formats/zx81_p.cpp | 22 | ||||
-rw-r--r-- | src/lib/formats/zx81_p.h | 1 |
6 files changed, 217 insertions, 61 deletions
diff --git a/src/lib/formats/apd_dsk.cpp b/src/lib/formats/apd_dsk.cpp new file mode 100644 index 00000000000..3c972c25e49 --- /dev/null +++ b/src/lib/formats/apd_dsk.cpp @@ -0,0 +1,145 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************* + + formats/apd_dsk.c + + Archimedes Protected Disk Image format + +*********************************************************************/ + +#include <zlib.h> +#include "formats/apd_dsk.h" + +static const uint8_t APD_HEADER[8] = { 'A', 'P', 'D', 'X', '0', '0', '0', '1' }; +static const uint8_t GZ_HEADER[2] = { 0x1f, 0x8b }; + +apd_format::apd_format() +{ +} + +const char *apd_format::name() const +{ + return "apd"; +} + +const char *apd_format::description() const +{ + return "Archimedes Protected Disk Image"; +} + +const char *apd_format::extensions() const +{ + return "apd"; +} + +int apd_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(8); + 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 = 8; + + 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], APD_HEADER, sizeof(APD_HEADER))) { + return 100; + } + + return 0; +} + +bool apd_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]; + uint8_t *in_ptr = &img[0]; + + 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 = in_ptr; + 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) { + LOG_FORMATS("inflateInit2 error: %d\n", err); + return false; + } + err = inflate(&d_stream, Z_FINISH); + if (err != Z_STREAM_END && err != Z_OK) { + LOG_FORMATS("inflate error: %d\n", err); + return false; + } + err = inflateEnd(&d_stream); + if (err != Z_OK) { + LOG_FORMATS("inflateEnd error: %d\n", err); + return false; + } + size = inflate_size; + img = gz_ptr; + } + + int data = 0x7d0; + for (int track = 0; track < 166; track++) { + uint32_t sdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x0])); + uint32_t ddlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x4])); + uint32_t qdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x8])); + + if (sdlen > 0) { + generate_track_from_bitstream(track / 2, track % 2, &img[data], sdlen, image); + data += (sdlen + 7) >> 3; + } + if (ddlen > 0) { + generate_track_from_bitstream(track / 2, track % 2, &img[data], ddlen, image); + data += (ddlen + 7) >> 3; + } + if (qdlen > 0) { + generate_track_from_bitstream(track / 2, track % 2, &img[data], qdlen, image); + data += (qdlen + 7) >> 3; + } + } + image->set_variant(floppy_image::DSDD); + + return true; +} + +bool apd_format::supports_save() const +{ + return false; +} + +const floppy_format_type FLOPPY_APD_FORMAT = &floppy_image_format_creator<apd_format>; diff --git a/src/lib/formats/apd_dsk.h b/src/lib/formats/apd_dsk.h new file mode 100644 index 00000000000..3bf40055a7b --- /dev/null +++ b/src/lib/formats/apd_dsk.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************* + + formats/apd_dsk.h + + Archimedes Protected Disk Image format + +*********************************************************************/ + +#ifndef APD_DSK_H_ +#define APD_DSK_H_ + +#include "flopimg.h" + +class apd_format : public floppy_image_format_t { +public: + apd_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_APD_FORMAT; + +#endif diff --git a/src/lib/formats/tzx_cas.cpp b/src/lib/formats/tzx_cas.cpp index 748f0227c65..7f03be7977a 100644 --- a/src/lib/formats/tzx_cas.cpp +++ b/src/lib/formats/tzx_cas.cpp @@ -8,7 +8,6 @@ TODO: Add support for the remaining block types: case 0x15: Direct Recording case 0x18: CSW Recording - case 0x19: Generalized Data Block case 0x21: Group Start case 0x22: Group End case 0x23: Jump To Block @@ -31,7 +30,7 @@ Notes: TZX format specification lists 8064 pulses for a header block and 3220 for a data block -but the documentaiton on worldofspectrum lists +but the documentation on worldofspectrum lists 8063 pulses for a header block and 3223 for a data block see http://www.worldofspectrum.org/faq/reference/48kreference.htm#TapeDataStructure @@ -315,7 +314,6 @@ static int tzx_handle_direct(int16_t **buffer, const uint8_t *bytes, int pause, tzx_output_wave(buffer, samples); size += samples; - } } @@ -342,8 +340,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u uint8_t starttype = cursymb[0]; -// printf("start polarity %01x (max number of symbols is %d)\n", starttype, maxp); - switch (starttype) { case 0x00: @@ -371,7 +367,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u for (int i = 0; i < maxp; i++) { uint16_t pulse_length = cursymb[1 + (i*2)] | (cursymb[2 + (i*2)] << 8); - // printf("pulse_length %04x\n", pulse_length); // shorter lists can be terminated with a pulse_length of 0 if (pulse_length != 0) @@ -380,7 +375,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u tzx_output_wave(buffer, samples); size += samples; toggle_wave_data(); - } else { @@ -390,8 +384,6 @@ static inline int tzx_handle_symbol(int16_t **buffer, const uint8_t *symtable, u } } - //toggle_wave_data(); - return size; } @@ -405,7 +397,6 @@ static inline int stream_get_bit(const uint8_t *bytes, uint8_t &stream_bit, uint if (byte & 0x80) retbit = 1; - stream_bit++; if (stream_bit == 8) @@ -433,34 +424,26 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa { uint8_t symbol = table2[i + 0]; uint16_t repetitions = table2[i + 1] + (table2[i + 2] << 8); - //printf("symbol %02x repititions %04x\n", symbol, repetitions); // does 1 mean repeat once, or that it only occurs once? + //printf("symbol %02x repetitions %04x\n", symbol, repetitions); // does 1 mean repeat once, or that it only occurs once? for (int j = 0; j < repetitions; j++) { size += tzx_handle_symbol(buffer, symtable, symbol, npp); - // toggle_wave_data(); } - - } // advance to after this data bytes += ((2 * npp + 1)*asp) + totp * 3; } - else - { - printf("no pilot block\n"); - } if (totd > 0) { - printf("data block table %04x (has %0d symbols, max symbol length is %d)\n", totd, asd, npd); + // printf("data block table %04x (has %0d symbols, max symbol length is %d)\n", totd, asd, npd); const uint8_t *symtable = bytes; const uint8_t *table2 = bytes + (2 * npd + 1)*asd; int NB = ceil(compute_log2(asd)); // number of bits needed to represent each symbol - printf("NB is %d\n", NB); uint8_t stream_bit = 0; uint32_t stream_byte = 0; @@ -475,16 +458,8 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa } size += tzx_handle_symbol(buffer, symtable, symbol, npd); - - //toggle_wave_data(); } } - else - { - printf("no data block\n"); - } - - /* pause */ if (pause > 0) @@ -505,9 +480,7 @@ static int tzx_handle_generalized(int16_t **buffer, const uint8_t *bytes, int pa static void ascii_block_common_log( const char *block_type_string, uint8_t block_type ) { - LOG_FORMATS("%s (type %02x) encountered.\n", block_type_string, block_type); - LOG_FORMATS("This block contains info on the .tzx file you are loading.\n"); - LOG_FORMATS("Please include the following info in your bug reports, if the image has issue in M.E.S.S.\n"); + LOG_FORMATS("%s (type %02x) encountered:\n", block_type_string, block_type); } static const char *const archive_ident[] = @@ -744,20 +717,18 @@ static int tzx_cas_do_work( int16_t **buffer ) { // having this missing is fatal // used crudely by batmanc in spectrum_cass list (which is just a redundant encoding of batmane ?) - printf("Unsupported block type (0x19 - Generalized Data Block) encountered.\n"); - data_size = cur_block[1] + (cur_block[2] << 8) + (cur_block[3] << 16) + (cur_block[4] << 24); pause_time= cur_block[5] + (cur_block[6] << 8); uint32_t totp = cur_block[7] + (cur_block[8] << 8) + (cur_block[9] << 16) + (cur_block[10] << 24); int npp = cur_block[11]; int asp = cur_block[12]; - if (asp == 0) asp = 256; + if (asp == 0 && totp > 0) asp = 256; uint32_t totd = cur_block[13] + (cur_block[14] << 8) + (cur_block[15] << 16) + (cur_block[16] << 24); int npd = cur_block[17]; int asd = cur_block[18]; - if (asd == 0) asd = 256; + if (asd == 0 && totd > 0) asd = 256; size += tzx_handle_generalized(buffer, &cur_block[19], pause_time, data_size, totp, npp, asp, totd, npd, asd); @@ -840,7 +811,7 @@ static int tap_cas_to_wav_size( const uint8_t *casdata, int caslen ) { int data_size = p[0] + (p[1] << 8); int pilot_length = (p[2] == 0x00) ? 8064 : 3220; /* TZX specification */ -// int pilot_length = (p[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */ +// int pilot_length = (p[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */ LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size); p += 2; size += tzx_cas_handle_block(nullptr, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8); @@ -859,7 +830,7 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) { int data_size = bytes[0] + (bytes[1] << 8); int pilot_length = (bytes[2] == 0x00) ? 8064 : 3220; /* TZX specification */ -// int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */ +// int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223; /* worldofspectrum */ LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size); bytes += 2; size += tzx_cas_handle_block(&p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8); @@ -871,34 +842,34 @@ static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes ) static const struct CassetteLegacyWaveFiller tzx_legacy_fill_wave = { tzx_cas_fill_wave, /* fill_wave */ - -1, /* chunk_size */ - 0, /* chunk_samples */ - tzx_cas_to_wav_size, /* chunk_sample_calc */ + -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 */ + 0, /* header_samples */ + 0 /* trailer_samples */ }; static const struct CassetteLegacyWaveFiller tap_legacy_fill_wave = { tap_cas_fill_wave, /* fill_wave */ - -1, /* chunk_size */ - 0, /* chunk_samples */ - tap_cas_to_wav_size, /* chunk_sample_calc */ + -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 */ + 0, /* header_samples */ + 0 /* trailer_samples */ }; static const struct CassetteLegacyWaveFiller cdt_legacy_fill_wave = { cdt_cas_fill_wave, /* fill_wave */ - -1, /* chunk_size */ - 0, /* chunk_samples */ - tzx_cas_to_wav_size, /* chunk_sample_calc */ + -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 */ + 0, /* header_samples */ + 0 /* trailer_samples */ }; static cassette_image::error tzx_cassette_identify( cassette_image *cassette, struct CassetteOptions *opts ) @@ -931,7 +902,7 @@ static cassette_image::error cdt_cassette_load( cassette_image *cassette ) return cassette_legacy_construct(cassette, &cdt_legacy_fill_wave); } -static const struct CassetteFormat tzx_cassette_format = +const struct CassetteFormat tzx_cassette_format = { "tzx", tzx_cassette_identify, diff --git a/src/lib/formats/tzx_cas.h b/src/lib/formats/tzx_cas.h index 8610fb0cdd4..2db31245310 100644 --- a/src/lib/formats/tzx_cas.h +++ b/src/lib/formats/tzx_cas.h @@ -12,6 +12,8 @@ #include "cassimg.h" +extern const struct CassetteFormat tzx_cassette_format; + CASSETTE_FORMATLIST_EXTERN(tzx_cassette_formats); CASSETTE_FORMATLIST_EXTERN(cdt_cassette_formats); diff --git a/src/lib/formats/zx81_p.cpp b/src/lib/formats/zx81_p.cpp index 7f359ccaca3..9fa5814385f 100644 --- a/src/lib/formats/zx81_p.cpp +++ b/src/lib/formats/zx81_p.cpp @@ -34,6 +34,7 @@ medium transfer rate is approx. 307 bps (38 bytes/sec) for files that contain #include <assert.h> #include "zx81_p.h" +#include "tzx_cas.h" #define WAVEENTRY_LOW -32768 @@ -197,13 +198,13 @@ static int zx81_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes) static const struct CassetteLegacyWaveFiller zx81_legacy_fill_wave = { - zx81_cassette_fill_wave, /* fill_wave */ - -1, /* chunk_size */ - 0, /* chunk_samples */ + zx81_cassette_fill_wave, /* fill_wave */ + -1, /* chunk_size */ + 0, /* chunk_samples */ zx81_cassette_calculate_size_in_samples, /* chunk_sample_calc */ - ZX81_WAV_FREQUENCY, /* sample_frequency */ - 0, /* header_samples */ - 0 /* trailer_samples */ + ZX81_WAV_FREQUENCY, /* sample_frequency */ + 0, /* header_samples */ + 0 /* trailer_samples */ }; static cassette_image::error zx81_p_identify(cassette_image *cassette, struct CassetteOptions *opts) @@ -233,6 +234,11 @@ CASSETTE_FORMATLIST_START(zx81_p_format) CASSETTE_FORMAT(zx81_p_image_format) CASSETTE_FORMATLIST_END +CASSETTE_FORMATLIST_START(zx81_cassette_formats) + CASSETTE_FORMAT(zx81_p_image_format) + CASSETTE_FORMAT(tzx_cassette_format) +CASSETTE_FORMATLIST_END + /* ZX-80 functions */ static int zx80_cassette_calculate_size_in_samples(const uint8_t *bytes, int length) @@ -265,11 +271,11 @@ static int zx80_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes) static const struct CassetteLegacyWaveFiller zx80_legacy_fill_wave = { - zx80_cassette_fill_wave, /* fill_wave */ + zx80_cassette_fill_wave, /* fill_wave */ -1, /* chunk_size */ 0, /* chunk_samples */ zx80_cassette_calculate_size_in_samples, /* chunk_sample_calc */ - ZX81_WAV_FREQUENCY, /* sample_frequency */ + ZX81_WAV_FREQUENCY, /* sample_frequency */ 0, /* header_samples */ 0 /* trailer_samples */ }; diff --git a/src/lib/formats/zx81_p.h b/src/lib/formats/zx81_p.h index 16a1b22724d..36da808c989 100644 --- a/src/lib/formats/zx81_p.h +++ b/src/lib/formats/zx81_p.h @@ -14,6 +14,7 @@ #include "cassimg.h" CASSETTE_FORMATLIST_EXTERN(zx81_p_format); +CASSETTE_FORMATLIST_EXTERN(zx81_cassette_formats); CASSETTE_FORMATLIST_EXTERN(zx80_o_format); #endif /* ZX81_P_H */ |