mirror of
https://github.com/mamedev/mame.git
synced 2024-11-18 10:06:19 +01:00
(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:
parent
bc0672544f
commit
c164e73a4b
2 changed files with 84 additions and 85 deletions
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue