mame/src/lib/formats/atom_tap.cpp
Nigel Barnes 29a7778ae7 atom: Added csw cassette format
csw_cas: Fixed Coverity CID 136200 Logically dead code (nw)
2017-04-17 18:49:42 +01:00

150 lines
4.5 KiB
C++

// license:BSD-3-Clause
// copyright-holders:Curt Coder
/*********************************************************************
formats/atom_tap.c
Cassette code for Acorn Atom tap files (Kansas City Standard)
*********************************************************************/
/*
http://beebwiki.jonripley.com/Acorn_cassette_format#Atom
The Atom supports the System series format (as a 'nameless file') and its own format. The data consists of files separated
by carrier breaks and the appropriate leaders and trailers, and further subdivided into blocks separated by inter-block gaps.
An Atom block consists of the following sequence of bytes:
Four synchronisation bytes (&2A).
File name (one to thirteen characters).
One end of file name marker byte (&0D).
Block flag, one byte.
Block number, two bytes, high byte first.
Data block length ? 1, one byte.
Execution address, two bytes, high byte first.
Load address, two bytes, high byte first.
Data, 0 to 256 bytes.
Checksum, one byte.
The block flag is set as follows:
Bit 7 is set if this block is not the last block of a file.
Bit 6 is set if the block contains data. If clear then the 'data block length' field is invalid.
Bit 5 is set if this block is not the first block of a file.
Bits 4 to 0 are undefined. Normally their contents are:
in the first block, bits 15 to 11 of the end address (=1 + the last address saved in the file);
in subsequent blocks, bits 6 to 2 of the previous block flag.
The checksum is a simple sum (modulo 256) of all bytes from the start of the filename to the end of the data.
*/
#include <assert.h>
#include "atom_tap.h"
#include "csw_cas.h"
#include "uef_cas.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
#define LOG 1
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
CassetteModulation atom_tap_modulation
-------------------------------------------------*/
static const struct CassetteModulation atom_tap_modulation =
{
CASSETTE_MODULATION_SINEWAVE,
1200.0 - 300, 1200.0, 1200.0 + 300,
2400.0 - 600, 2400.0, 2400.0 + 600
};
/*-------------------------------------------------
cassette_image_read_uint8 - read tape data
-------------------------------------------------*/
static uint8_t cassette_image_read_uint8(cassette_image *cassette, uint64_t offset)
{
uint8_t data;
cassette_image_read(cassette, &data, offset, 1);
return data;
}
/*-------------------------------------------------
atom_tap_identify - identify cassette
-------------------------------------------------*/
static cassette_image::error atom_tap_identify(cassette_image *cassette, struct CassetteOptions *opts)
{
return cassette_modulation_identify( cassette, &atom_tap_modulation, opts);
}
/*-------------------------------------------------
atom_tap_load - load cassette
-------------------------------------------------*/
#define MODULATE(_value) \
for (int i = 0; i < (_value ? 8 : 4); i++) { \
err = cassette_put_modulated_data_bit(cassette, 0, time_index, _value, &atom_tap_modulation, &time_displacement);\
if (err != cassette_image::error::SUCCESS) return err;\
time_index += time_displacement;\
}
#define BIT(x,n) (((x)>>(n))&1)
static cassette_image::error atom_tap_load(cassette_image *cassette)
{
cassette_image::error err;
uint64_t image_size = cassette_image_size(cassette);
uint64_t image_pos = 0;
double time_index = 0.0;
double time_displacement;
while (image_pos < image_size)
{
uint8_t data = cassette_image_read_uint8(cassette, image_pos);
/* start bit */
MODULATE(0);
/* data bits */
for (int bit = 0; bit < 8; bit++)
{
MODULATE(BIT(data, bit));
}
/* stop bits */
MODULATE(1);
MODULATE(1);
image_pos++;
}
return cassette_image::error::SUCCESS;
}
/*-------------------------------------------------
CassetteFormat atom_tap_cassette_format
-------------------------------------------------*/
const struct CassetteFormat atom_tap_format =
{
"tap",
atom_tap_identify,
atom_tap_load,
nullptr
};
CASSETTE_FORMATLIST_START( atom_cassette_formats )
CASSETTE_FORMAT(atom_tap_format)
CASSETTE_FORMAT(csw_cassette_format)
CASSETTE_FORMAT(uef_cassette_format)
CASSETTE_FORMATLIST_END