diff options
author | 2015-11-08 12:56:12 +0100 | |
---|---|---|
committer | 2015-11-08 12:56:12 +0100 | |
commit | 7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch) | |
tree | f310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/lib/formats/fmsx_cas.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/lib/formats/fmsx_cas.cpp')
-rw-r--r-- | src/lib/formats/fmsx_cas.cpp | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/src/lib/formats/fmsx_cas.cpp b/src/lib/formats/fmsx_cas.cpp new file mode 100644 index 00000000000..10a26d2e232 --- /dev/null +++ b/src/lib/formats/fmsx_cas.cpp @@ -0,0 +1,146 @@ +// license:BSD-3-Clause +// copyright-holders:Sean Young +#include <assert.h> + +#include "formats/fmsx_cas.h" + + +#define CAS_PERIOD (16) +#define CAS_HEADER_PERIODS (4000) +#define CAS_EMPTY_PERIODS (1000) +static const UINT8 CasHeader[8] = { 0x1F,0xA6,0xDE,0xBA,0xCC,0x13,0x7D,0x74 }; + +static int cas_size; + + +/******************************************************************* + Calculate the number of samples needed for this tape image +********************************************************************/ +static int fmsx_cas_to_wav_size (const UINT8 *casdata, int caslen) +{ + int pos, size; + + if (caslen < 8) return -1; + if (memcmp (casdata, CasHeader, sizeof (CasHeader) ) ) return -1; + + pos = size = 0; + + while (pos < caslen) + { + if ( (pos + 8) < caslen) + if (!memcmp (casdata + pos, CasHeader, 8) ) + { + size += (CAS_EMPTY_PERIODS + CAS_HEADER_PERIODS) * CAS_PERIOD; + pos += 8; + continue; + } + + size += CAS_PERIOD * 12; + pos++; + } + + cas_size = caslen; + + return size; +} + + +/******************************************************************* + Generate samples for the tape image +********************************************************************/ +static int fmsx_cas_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes) +{ + int cas_pos, bit, state = 1, samples_pos, size, n, i, p; + + cas_pos = 0; + samples_pos = 0; + + while (samples_pos < sample_count && cas_pos < cas_size) + { + /* Check if we need to output a header */ + if ( cas_pos + 8 < cas_size ) + { + if ( ! memcmp( bytes + cas_pos, CasHeader, 8 ) ) + { + /* Write CAS_EMPTY_PERIODS of silence */ + n = CAS_EMPTY_PERIODS * CAS_PERIOD; while (n--) buffer[samples_pos++] = 0; + + /* Write CAS_HEADER_PERIODS of header (high frequency) */ + for (i=0;i<CAS_HEADER_PERIODS*4;i++) + { + for (n=0;n<CAS_PERIOD / 4;n++) + buffer[samples_pos + n] = (state ? 32767 : -32767); + + samples_pos += CAS_PERIOD / 4 ; + state = !state; + } + + cas_pos += 8; + } + } + + for (i=0;i<=11;i++) + { + if (i == 0) bit = 0; + else if (i < 9) bit = (bytes[cas_pos] & (1 << (i - 1) ) ); + else bit = 1; + + /* write this one bit */ + for (n=0;n<(bit ? 4 : 2);n++) + { + size = (bit ? CAS_PERIOD / 4 : CAS_PERIOD / 2); + for (p=0;p<size;p++) + { + buffer[samples_pos + p] = (state ? 32767 : -32767); + } + state = !state; + samples_pos += size; + } + } + cas_pos++; + } + + return samples_pos; +} + + +static const struct CassetteLegacyWaveFiller fmsx_legacy_fill_wave = +{ + fmsx_cas_fill_wave, /* fill_wave */ + -1, /* chunk_size */ + 0, /* chunk_samples */ + fmsx_cas_to_wav_size, /* chunk_sample_calc */ + 22050, /* sample_frequency */ + 0, /* header_samples */ + 0 /* trailer_samples */ +}; + + + +static casserr_t fmsx_cas_identify(cassette_image *cassette, struct CassetteOptions *opts) +{ + return cassette_legacy_identify(cassette, opts, &fmsx_legacy_fill_wave); +} + + + +static casserr_t fmsx_cas_load(cassette_image *cassette) +{ + return cassette_legacy_construct(cassette, &fmsx_legacy_fill_wave); +} + + + +static const struct CassetteFormat fmsx_cas_format = +{ + "tap,cas", + fmsx_cas_identify, + fmsx_cas_load, + NULL +}; + + + +CASSETTE_FORMATLIST_START(fmsx_cassette_formats) + CASSETTE_FORMAT(fmsx_cas_format) +CASSETTE_FORMATLIST_END |