summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/fmsx_cas.cpp
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
committer Miodrag Milanovic <mmicko@gmail.com>2015-11-08 12:56:12 +0100
commit7c19aac60e12d6f5ea301bdb34d7826a01e0b06f (patch)
treef310d86aa2c6bfc19d115307dedde4eb0cd52dad /src/lib/formats/fmsx_cas.cpp
parenta57b46ae933badd7441ce1644711dbb851e2b504 (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.cpp146
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