summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/formats/trs_cas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/formats/trs_cas.cpp')
-rw-r--r--src/lib/formats/trs_cas.cpp99
1 files changed, 89 insertions, 10 deletions
diff --git a/src/lib/formats/trs_cas.cpp b/src/lib/formats/trs_cas.cpp
index 0c17daaa493..17ce879eba7 100644
--- a/src/lib/formats/trs_cas.cpp
+++ b/src/lib/formats/trs_cas.cpp
@@ -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 =