(MESS) apf : added support for CAS and CPF cassettes [Robbbert]

removed APT support for the moment, it could not have ever worked.
This commit is contained in:
Robbbert 2014-02-13 12:20:48 +00:00
parent bc0672544f
commit c164e73a4b
2 changed files with 84 additions and 85 deletions

View file

@ -1,119 +1,124 @@
/* .APT tape images */
// license:BSD-3-Clause
// copyright-holders: Original author, Robbbert
/********************************************************************
Support for APF Imagination Machine cassette images
CPF and CAS images consist of the screen and then the program,
and are exactly 1E00 bytes in length.
Each byte after conversion becomes bit 7,6,etc to 0, There are
no start or stop bits.
An actual tape consists of 6 sections
a. silence until you press Enter (no offset)
b. 11secs of high bits then 1 low bit
c. The screen ram
d. The program ram
e. A checksum byte (8-bit addition)
********************************************************************/
#include "formats/apf_apt.h"
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767
#define WAVEENTRY_NULL 0
/* frequency of wave */
#define APF_WAV_FREQUENCY 11050
#define APF_APT_BIT_0_LENGTH ((int)(APF_WAV_FREQUENCY*0.0005))
#define APF_APT_BIT_1_LENGTH ((int)(APF_WAV_FREQUENCY*0.001))
struct apf_t
{
int cassette_length;
};
static apf_t apf;
#define APF_WAV_FREQUENCY 8000
/* 500 microsecond of bit 0 and 1000 microsecond of bit 1 */
static int apf_image_size;
static INT16 *apf_emit_level(INT16 *p, int count, INT16 wave_state)
static int apf_put_samples(INT16 *buffer, int sample_pos, int count, int level)
{
int i;
for (i=0; i<count; i++)
if (buffer)
{
*(p++) = wave_state;
for (int i=0; i<count; i++)
buffer[sample_pos + i] = level;
}
return p;
return count;
}
/* 4 periods at 1200Hz */
static INT16* apf_output_bit(INT16 *p, UINT8 b)
static int apf_output_bit(INT16 *buffer, int sample_pos, bool bit)
{
if (b)
int samples = 0;
if (bit)
{
p = apf_emit_level(p, (APF_APT_BIT_1_LENGTH>>1), WAVEENTRY_HIGH);
p = apf_emit_level(p, (APF_APT_BIT_1_LENGTH>>1), WAVEENTRY_LOW);
samples += apf_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_HIGH);
samples += apf_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_LOW);
}
else
{
p = apf_emit_level(p, (APF_APT_BIT_0_LENGTH>>1), WAVEENTRY_HIGH);
p = apf_emit_level(p, (APF_APT_BIT_0_LENGTH>>1), WAVEENTRY_LOW);
samples += apf_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_HIGH);
samples += apf_put_samples(buffer, sample_pos + samples, 2, WAVEENTRY_LOW);
}
return p;
return samples;
}
static int apf_get_bit_size_in_samples(UINT8 b)
static int apf_output_byte(INT16 *buffer, int sample_pos, UINT8 byte)
{
if (b)
{
return APF_APT_BIT_1_LENGTH;
}
int samples = 0;
UINT8 i;
return APF_APT_BIT_0_LENGTH;
/* data */
for (i = 0; i<8; i++)
samples += apf_output_bit (buffer, sample_pos + samples, (byte >> (7-i)) & 1);
return samples;
}
/*************************************************************************************/
/* each bit in the data represents a "1" or "0" waveform */
static int apf_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
static int apf_handle_cassette(INT16 *buffer, const UINT8 *bytes)
{
unsigned i;
int size;
int b;
UINT8 data;
UINT32 sample_count = 0;
UINT32 i;
UINT8 cksm = 0;
size = 0;
apf.cassette_length = length;
// silence
sample_count += apf_put_samples(buffer, 0, 12000, 0);
/* start */
for (i=0; i<10000; i++)
sample_count += apf_output_bit(buffer, sample_count, 1);
for (i=0; i<length; i++)
sample_count += apf_output_bit(buffer, sample_count, 0);
/* data */
for (i=0; i<apf_image_size; i++)
{
data = bytes[i];
for (b=0; b<8; b++)
{
size += apf_get_bit_size_in_samples((data>>7) & 0x01);
data = data<<1;
}
cksm += bytes[i];
sample_count += apf_output_byte(buffer, sample_count, bytes[i]);
}
return size;
/* checksum byte */
sample_count += apf_output_byte(buffer, sample_count, cksm);
return sample_count;
}
/*************************************************************************************/
/*******************************************************************
Generate samples for the tape image
********************************************************************/
static int apf_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes)
{
int i;
INT16 *p;
UINT8 data;
int b;
p = buffer;
for (i=0; i<apf.cassette_length; i++)
{
data = bytes[i];
for (b=0; b<8; b++)
{
p = apf_output_bit(p,(data>>7) & 0x01);
data = data<<1;
}
}
return p - buffer;
return apf_handle_cassette(buffer, bytes);
}
/*******************************************************************
Calculate the number of samples needed for this tape image
********************************************************************/
static int apf_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
{
apf_image_size = length;
return apf_handle_cassette(NULL, bytes);
}
static const struct CassetteLegacyWaveFiller apf_legacy_fill_wave =
{
@ -126,27 +131,21 @@ static const struct CassetteLegacyWaveFiller apf_legacy_fill_wave =
0 /* trailer_samples */
};
static casserr_t apf_apt_identify(cassette_image *cassette, struct CassetteOptions *opts)
static casserr_t apf_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts)
{
return cassette_legacy_identify(cassette, opts, &apf_legacy_fill_wave);
}
static casserr_t apf_apt_load(cassette_image *cassette)
static casserr_t apf_cassette_load(cassette_image *cassette)
{
return cassette_legacy_construct(cassette, &apf_legacy_fill_wave);
}
static const struct CassetteFormat apf_apt_format =
{
"apt",
apf_apt_identify,
apf_apt_load,
"cas,cpf",
apf_cassette_identify,
apf_cassette_load,
NULL
};

View file

@ -14,14 +14,14 @@ phc images consist of 5 sections
5. A 1-byte trailer of FF which we do not pass on
Each byte after conversion becomes a start bit, bit 0,1,etc to 7,
then 4 end bits.
then 4 stop bits.
An actual tape consists of 6 sections
a. 2.656secs of silence
b. 4.862secs of high bits
c. The header which is parts 1 and 2 above
d. 0.652secs of high bits
e. The main program wjich is parts 3 and 4 above
e. The main program which is parts 3 and 4 above
f. 1.771secs of silence
We don't emulate the full silence and high-bits periods, only just