summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/dec/rainbow.cpp
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2024-09-25 16:11:06 +0200
committer hap <happppp@users.noreply.github.com>2024-09-25 16:11:06 +0200
commit9ca21b386bf7e0801b32e096dcde1cc8609f7b0c (patch)
tree8655fd011c5958c3cb48ca44c37b77953fb9cfa6 /src/mame/dec/rainbow.cpp
parent2b906b6f90fc5ffa64e2faae05d1ab9aa7e51437 (diff)
hmcs40: add hmcs46/hmcs47
Diffstat (limited to 'src/mame/dec/rainbow.cpp')
0 files changed, 0 insertions, 0 deletions
09'>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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 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;


static 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;
}


static 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( nullptr, 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,
	nullptr
};


CASSETTE_FORMATLIST_START(kim1_cassette_formats)
	CASSETTE_FORMAT(kim1_kim_format)
CASSETTE_FORMATLIST_END