trs80m3: Added support for high-speed CAS files.

This commit is contained in:
Robbbert 2021-03-29 04:19:43 +11:00
parent 2c52caf49a
commit c5f293954d

View File

@ -15,7 +15,7 @@ Support for TRS80 .cas cassette images
#define SMPHI 32767
static int cas_size; // FIXME: global variable prevents multiple instances
static int cas_size = 0; // FIXME: global variable prevents multiple instances
/*******************************************************************
@ -41,14 +41,11 @@ static inline int trs80l2_cas_cycle(int16_t *buffer, int sample_pos, bool bit)
static int trs80l2_handle_cas(int16_t *buffer, const uint8_t *casdata)
{
int data_pos = 0, sample_count = 0;
bool a5sw = false;
data_pos = 0;
sample_count = 0;
bool sw = false;
while( data_pos < cas_size )
{
uint8_t data = casdata[data_pos];
uint8_t data = casdata[data_pos];
for (uint8_t i = 0; i < 8; i++ )
{
@ -61,9 +58,9 @@ static int trs80l2_handle_cas(int16_t *buffer, const uint8_t *casdata)
data <<= 1;
}
if (!a5sw && (casdata[data_pos] == 0xA5))
if (!sw && (casdata[data_pos] == 0xA5))
{
a5sw = true;
sw = true;
// Need 1ms silence here while rom is busy
sample_count += trs80l2_cas_cycle( buffer, sample_count, false );
}
@ -77,13 +74,92 @@ static int trs80l2_handle_cas(int16_t *buffer, const uint8_t *casdata)
return sample_count;
}
static inline int trs80m3_cas_cycle(int16_t *buffer, int sample_pos, bool bit)
{
uint8_t i, counts = bit ? 8 : 16;
if ( buffer )
{
for (i = 0; i < counts; i++)
buffer[ sample_pos++ ] = SMPHI;
for (i = 0; i < counts; i++)
buffer[ sample_pos++ ] = SMPLO;
}
return counts*2;
}
static int trs80m3_handle_cas(int16_t *buffer, const uint8_t *casdata)
{
int data_pos = 0, sample_count = 0;
uint8_t sw = 0, bitout = 0, byteout = 0;
// Make sure this is a trs80m3 tape
// Should have ~256 0x55 then one 0x7f
while ((cas_size > data_pos) && (casdata[data_pos] == 0x55))
data_pos++;
if (casdata[data_pos] != 0x7f)
return 0;
data_pos = 0;
while( data_pos < cas_size )
{
uint8_t data = casdata[data_pos];
for (uint8_t i = 0; i < 8; i++ )
{
sample_count += trs80m3_cas_cycle( buffer, sample_count, data >> 7 );
// This paragraph unscrambles and prints the SYSTEM name.
// If the first character is U, type SYSTEM, then the next 6 characters; otherwise use CLOAD.
if ((sw == 1) && buffer)
{
if (bitout)
{
byteout = (byteout << 1) | (data >> 7);
if (bitout == 8)
{
if (byteout == 0)
sw = 2;
printf("%c",byteout);
byteout = 0;
bitout = 0;
}
else
bitout++;
}
else bitout++;
}
data <<= 1;
}
if (!sw && (casdata[data_pos] == 0x7F))
{
sw = 1;
// This 1ms of silence isn't absolutely necessary, but the system writes it, so we may as emulate it.
sample_count += trs80l2_cas_cycle( buffer, sample_count, false );
}
data_pos++;
}
// Specification requires a short silence to indicate EOF
sample_count += trs80l2_cas_cycle( buffer, sample_count, false );
sample_count += trs80l2_cas_cycle( buffer, sample_count, false );
return sample_count;
}
/*******************************************************************
Generate samples for the tape image
********************************************************************/
static int trs80l2_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
{
return trs80l2_handle_cas( buffer, bytes );
if (cas_size && (bytes[0] == 0x55))
return trs80m3_handle_cas( buffer, bytes );
else
return trs80l2_handle_cas( buffer, bytes );
}
@ -94,7 +170,10 @@ static int trs80l2_cas_to_wav_size(const uint8_t *casdata, int caslen)
{
cas_size = caslen;
return trs80l2_handle_cas( nullptr, casdata );
if (cas_size && (casdata[0] == 0x55))
return trs80m3_handle_cas( nullptr, casdata );
else
return trs80l2_handle_cas( nullptr, casdata );
}
static const cassette_image::LegacyWaveFiller trs80l2_cas_legacy_fill_wave =