1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// license:BSD-3-Clause
// copyright-holders:Robbbert
/********************************************************************
Support for Goldstar FC-100 cassette images
We don't actually have any info on the cassette frequencies, so
it's all a guess.
********************************************************************/
#include <assert.h>
#include "fc100_cas.h"
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767
#define FC100_WAV_FREQUENCY 9600
#define FC100_HEADER_BYTES 16
// image size
static int fc100_image_size;
static int fc100_put_samples(int16_t *buffer, int sample_pos, int count, int level)
{
if (buffer)
{
for (int i=0; i<count; i++)
buffer[sample_pos + i] = level;
}
return count;
}
static int fc100_output_bit(int16_t *buffer, int sample_pos, bool bit)
{
int samples = 0;
if (bit)
{
samples += fc100_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
samples += fc100_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
samples += fc100_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
samples += fc100_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
}
else
{
samples += fc100_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_LOW);
samples += fc100_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_HIGH);
}
return samples;
}
static int fc100_output_byte(int16_t *buffer, int sample_pos, uint8_t byte)
{
int samples = 0;
uint8_t i;
/* start */
samples += fc100_output_bit (buffer, sample_pos + samples, 0);
/* data */
for (i = 0; i<8; i++)
samples += fc100_output_bit (buffer, sample_pos + samples, (byte >> i) & 1);
/* stop */
for (i = 0; i<4; i++)
samples += fc100_output_bit (buffer, sample_pos + samples, 1);
return samples;
}
static int fc100_handle_cassette(int16_t *buffer, const uint8_t *bytes)
{
uint32_t sample_count = 0;
uint32_t byte_count = 0;
uint32_t i;
/* start */
for (i=0; i<2155; i++)
sample_count += fc100_output_bit(buffer, sample_count, 1);
/* header */
for (int i=0; i<FC100_HEADER_BYTES; i++)
sample_count += fc100_output_byte(buffer, sample_count, bytes[i]);
byte_count = FC100_HEADER_BYTES;
/* pause */
for (i=0; i<1630; i++)
sample_count += fc100_output_bit(buffer, sample_count, 1);
/* data */
for (i=byte_count; i<fc100_image_size; i++)
sample_count += fc100_output_byte(buffer, sample_count, bytes[i]);
return sample_count;
}
/*******************************************************************
Generate samples for the tape image
********************************************************************/
static int fc100_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes)
{
return fc100_handle_cassette(buffer, bytes);
}
/*******************************************************************
Calculate the number of samples needed for this tape image
********************************************************************/
static int fc100_cassette_calculate_size_in_samples(const uint8_t *bytes, int length)
{
fc100_image_size = length;
return fc100_handle_cassette(nullptr, bytes);
}
static const struct CassetteLegacyWaveFiller fc100_legacy_fill_wave =
{
fc100_cassette_fill_wave, /* fill_wave */
-1, /* chunk_size */
0, /* chunk_samples */
fc100_cassette_calculate_size_in_samples, /* chunk_sample_calc */
FC100_WAV_FREQUENCY, /* sample_frequency */
0, /* header_samples */
0 /* trailer_samples */
};
static cassette_image::error fc100_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts)
{
return cassette_legacy_identify(cassette, opts, &fc100_legacy_fill_wave);
}
static cassette_image::error fc100_cassette_load(cassette_image *cassette)
{
return cassette_legacy_construct(cassette, &fc100_legacy_fill_wave);
}
static const struct CassetteFormat fc100_cassette_image_format =
{
"cas",
fc100_cassette_identify,
fc100_cassette_load,
nullptr
};
CASSETTE_FORMATLIST_START(fc100_cassette_formats)
CASSETTE_FORMAT(fc100_cassette_image_format)
CASSETTE_FORMATLIST_END
|