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/kim1_cas.cpp | |
parent | a57b46ae933badd7441ce1644711dbb851e2b504 (diff) |
Rename *.c -> *.cpp in our source (nw)
Diffstat (limited to 'src/lib/formats/kim1_cas.cpp')
-rw-r--r-- | src/lib/formats/kim1_cas.cpp | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/lib/formats/kim1_cas.cpp b/src/lib/formats/kim1_cas.cpp new file mode 100644 index 00000000000..b8527e10462 --- /dev/null +++ b/src/lib/formats/kim1_cas.cpp @@ -0,0 +1,197 @@ +// license:BSD-3-Clause +// copyright-holders:Wilbert Pol +#include <assert.h> + +#include "kim1_cas.h" + +#define SMPLO -32768 +#define SMPHI 32767 + + +static int cas_size; + + +INLINE int kim1_output_signal( INT16 *buffer, int sample_pos, int high ) +{ + int sample_count, i, j; + + sample_count = 0; + + if ( high ) + { + /* high frequency (~3600Hz) */ + for ( i = 0; i < 9; i++ ) + { + if ( buffer ) + { + for ( j = 0; j < 6; j++ ) + buffer[ sample_pos + sample_count + j ] = SMPHI; + } + sample_count += 6; + + if ( buffer ) + { + for ( j = 0; j < 6; j++ ) + buffer[ sample_pos + sample_count + j ] = SMPLO; + } + sample_count += 6; + } + } + else + { + /* low frequency (~2400Hz) */ + for ( i = 0; i < 6; i++ ) + { + if ( buffer ) + { + for ( j = 0; j < 9; j++ ) + buffer[ sample_pos + sample_count + j ] = SMPHI; + } + sample_count += 9; + + if ( buffer ) + { + for ( j = 0; j < 9; j++ ) + buffer[ sample_pos + sample_count + j ] = SMPLO; + } + sample_count += 9; + } + } + + return sample_count; +} + + +INLINE int kim1_output_byte( INT16 *buffer, int sample_pos, UINT8 byte ) +{ + int i; + int sample_count = 0; + + for ( i = 0; i < 8; i++ ) + { + sample_count += kim1_output_signal( buffer, sample_pos + sample_count, 1 ); + sample_count += kim1_output_signal( buffer, sample_pos + sample_count, byte & 0x01 ? 0 : 1 ); + sample_count += kim1_output_signal( buffer, sample_pos + sample_count, 0 ); + byte >>= 1; + } + return sample_count; +} + + +static int kim1_handle_kim(INT16 *buffer, const UINT8 *casdata) +{ + static const UINT8 encoding[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }; + int i, data_pos, sample_count; + UINT16 size, address, file_id, checksum; + + if ( cas_size < 9 ) return -1; + if ( memcmp( casdata, "KIM1", 4 ) ) return -1; + + address = casdata[4] | ( casdata[5] << 8 ); + size = casdata[6] | ( casdata[7] << 8 ); + file_id = casdata[8]; + + data_pos = 9; + sample_count = 0; + checksum = casdata[4] + casdata[5]; + + /* First output a sync header: 100 x 16h */ + for ( i = 0; i < 100; i++ ) + sample_count += kim1_output_byte( buffer, sample_count, 0x16 ); + + /* Output end of sync: 2Ah */ + sample_count += kim1_output_byte( buffer, sample_count, 0x2A ); + + /* Output ID */ + sample_count += kim1_output_byte( buffer, sample_count, encoding[ file_id >> 4 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ file_id & 0x0f ] ); + + /* Output starting address */ + sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( address & 0xff ) >> 4 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ address & 0x0f ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ address >> 12 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( address >> 8 ) & 0x0f ] ); + + /* Output the data */ + while( data_pos < cas_size && data_pos < ( size + 9 ) ) + { + UINT8 data = casdata[data_pos]; + + sample_count += kim1_output_byte( buffer, sample_count, encoding[ data >> 4 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ data & 0x0f ] ); + checksum += data; + data_pos++; + } + + /* Output end of data marker: 2Fh */ + sample_count += kim1_output_byte( buffer, sample_count, 0x2F ); + + /* Output checksum */ + sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( checksum & 0xff ) >> 4 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ checksum & 0x0f ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ checksum >> 12 ] ); + sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( checksum >> 8 ) & 0x0f ] ); + + /* Output end of transmission marker: 2 x 04h */ + sample_count += kim1_output_byte( buffer, sample_count, 0x04 ); + sample_count += kim1_output_byte( buffer, sample_count, 0x04 ); + + return sample_count; +} + + +/******************************************************************* + Generate samples for the tape image +********************************************************************/ +static int kim1_kim_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes) +{ + return kim1_handle_kim( buffer, bytes ); +} + + +/******************************************************************* + Calculate the number of samples needed for this tape image +********************************************************************/ +static int kim1_kim_to_wav_size(const UINT8 *casdata, int caslen) +{ + cas_size = caslen; + + return kim1_handle_kim( NULL, casdata ); +} + +static const struct CassetteLegacyWaveFiller kim1_kim_legacy_fill_wave = +{ + kim1_kim_fill_wave, /* fill_wave */ + -1, /* chunk_size */ + 0, /* chunk_samples */ + kim1_kim_to_wav_size, /* chunk_sample_calc */ + 44100, /* sample_frequency */ + 0, /* header_samples */ + 0 /* trailer_samples */ +}; + + +static casserr_t kim1_kim_identify(cassette_image *cassette, struct CassetteOptions *opts) +{ + return cassette_legacy_identify(cassette, opts, &kim1_kim_legacy_fill_wave); +} + + +static casserr_t kim1_kim_load(cassette_image *cassette) +{ + return cassette_legacy_construct(cassette, &kim1_kim_legacy_fill_wave); +} + + +static const struct CassetteFormat kim1_kim_format = +{ + "kim,kim1", + kim1_kim_identify, + kim1_kim_load, + NULL +}; + + +CASSETTE_FORMATLIST_START(kim1_cassette_formats) + CASSETTE_FORMAT(kim1_kim_format) +CASSETTE_FORMATLIST_END |