summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2021-04-07 22:12:44 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2021-04-07 22:12:44 +1000
commitbbe2ab5923091954d28dc75cb64611ba88079f21 (patch)
tree162b334e0bd383c01908e7461afbce590d950ccc
parent3e28cafa550b94cc782a76b2ad15827d48b878bb (diff)
trs80: Added support for Level 1 CAS files.
-rw-r--r--src/lib/formats/trs_cas.cpp82
-rw-r--r--src/lib/formats/trs_cas.h1
-rw-r--r--src/mame/drivers/trs80.cpp3
3 files changed, 68 insertions, 18 deletions
diff --git a/src/lib/formats/trs_cas.cpp b/src/lib/formats/trs_cas.cpp
index 7d161d7c218..d41b69aa520 100644
--- a/src/lib/formats/trs_cas.cpp
+++ b/src/lib/formats/trs_cas.cpp
@@ -3,6 +3,15 @@
/********************************************************************
Support for TRS80 .cas cassette images
+Types handled:
+- Model 1 Level I: 250 baud
+- Model 1 Level II: 500 baud
+- Model 3/4: 1500 baud.
+
+Level I and II tape format is completely identical, apart from the
+baud rate. The contents are specific to each system though.
+The Model 3 and 4 can load either Level II tapes (by answering L
+to the Cass? prompt), or the fast format by hitting enter at Cass?
********************************************************************/
#include "formats/trs_cas.h"
@@ -21,7 +30,7 @@ static int cas_size = 0; // FIXME: global variable prevents multiple instances
/*******************************************************************
Generate one high-low cycle of sample data
********************************************************************/
-static inline int trs80l2_cas_cycle(int16_t *buffer, int sample_pos, bool bit)
+static inline int trs80m1_cas_cycle(int16_t *buffer, int sample_pos, bool bit)
{
uint8_t i;
@@ -38,7 +47,7 @@ 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)
+static int trs80m1_handle_cas(int16_t *buffer, const uint8_t *casdata)
{
int data_pos = 0, sample_count = 0;
bool sw = false;
@@ -58,10 +67,10 @@ static int trs80l2_handle_cas(int16_t *buffer, const uint8_t *casdata)
for (uint8_t i = 0; i < 8; i++ )
{
/* Signal code */
- sample_count += trs80l2_cas_cycle( buffer, sample_count, true );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, true );
/* Bit code */
- sample_count += trs80l2_cas_cycle( buffer, sample_count, data >> 7 );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, data >> 7 );
data <<= 1;
}
@@ -70,15 +79,15 @@ static int trs80l2_handle_cas(int16_t *buffer, const uint8_t *casdata)
{
sw = true;
// Need 1ms silence here while rom is busy
- sample_count += trs80l2_cas_cycle( buffer, sample_count, false );
+ sample_count += trs80m1_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 );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, false );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, false );
return sample_count;
}
@@ -104,6 +113,9 @@ static int trs80m3_handle_cas(int16_t *buffer, const uint8_t *casdata)
// Make sure this is a trs80m3 tape
// Should have ~256 0x55 then one 0x7f
+ // It's possible that 0x57 could be encountered instead,
+ // but no working tapes with it have been found.
+ // Other bit-shifted variants might exist too.
while ((cas_size > data_pos) && (casdata[data_pos] == 0x55))
data_pos++;
if (casdata[data_pos] != 0x7f)
@@ -142,19 +154,19 @@ static int trs80m3_handle_cas(int16_t *buffer, const uint8_t *casdata)
data <<= 1;
}
- if (!sw && (casdata[data_pos] == 0x7F))
+ if (!sw && (casdata[data_pos] != 0x55))
{
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 );
+ sample_count += trs80m1_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 );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, false );
+ sample_count += trs80m1_cas_cycle( buffer, sample_count, false );
return sample_count;
}
@@ -162,34 +174,66 @@ static int trs80m3_handle_cas(int16_t *buffer, const uint8_t *casdata)
/*******************************************************************
Generate samples for the tape image
********************************************************************/
-static int trs80l2_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
+static int trs80_cas_fill_wave(int16_t *buffer, int sample_count, uint8_t *bytes)
{
if (cas_size && (bytes[0] == 0x55))
return trs80m3_handle_cas( buffer, bytes );
else
- return trs80l2_handle_cas( buffer, bytes );
+ return trs80m1_handle_cas( buffer, bytes );
}
/*******************************************************************
Calculate the number of samples needed for this tape image
********************************************************************/
-static int trs80l2_cas_to_wav_size(const uint8_t *casdata, int caslen)
+static int trs80_cas_to_wav_size(const uint8_t *casdata, int caslen)
{
cas_size = caslen;
if (cas_size && (casdata[0] == 0x55))
return trs80m3_handle_cas( nullptr, casdata );
else
- return trs80l2_handle_cas( nullptr, casdata );
+ return trs80m1_handle_cas( nullptr, casdata );
+}
+
+static const cassette_image::LegacyWaveFiller trs80l1_cas_legacy_fill_wave =
+{
+ trs80_cas_fill_wave, /* fill_wave */
+ -1, /* chunk_size */
+ 0, /* chunk_samples */
+ trs80_cas_to_wav_size, /* chunk_sample_calc */
+ 22050, /* sample_frequency */
+ 0, /* header_samples */
+ 0 /* trailer_samples */
+};
+
+
+static cassette_image::error trs80l1_cas_identify(cassette_image *cassette, cassette_image::Options *opts)
+{
+ return cassette->legacy_identify(opts, &trs80l1_cas_legacy_fill_wave);
}
+
+static cassette_image::error trs80l1_cas_load(cassette_image *cassette)
+{
+ return cassette->legacy_construct(&trs80l1_cas_legacy_fill_wave);
+}
+
+
+static const cassette_image::Format trs80l1_cas_format =
+{
+ "cas",
+ trs80l1_cas_identify,
+ trs80l1_cas_load,
+ nullptr
+};
+
static const cassette_image::LegacyWaveFiller trs80l2_cas_legacy_fill_wave =
{
- trs80l2_cas_fill_wave, /* fill_wave */
+ trs80_cas_fill_wave, /* fill_wave */
-1, /* chunk_size */
0, /* chunk_samples */
- trs80l2_cas_to_wav_size, /* chunk_sample_calc */
+ trs80_cas_to_wav_size, /* chunk_sample_calc */
44100, /* sample_frequency */
0, /* header_samples */
0 /* trailer_samples */
@@ -217,6 +261,10 @@ static const cassette_image::Format trs80l2_cas_format =
};
+CASSETTE_FORMATLIST_START(trs80l1_cassette_formats)
+ CASSETTE_FORMAT(trs80l1_cas_format)
+CASSETTE_FORMATLIST_END
+
CASSETTE_FORMATLIST_START(trs80l2_cassette_formats)
CASSETTE_FORMAT(trs80l2_cas_format)
CASSETTE_FORMATLIST_END
diff --git a/src/lib/formats/trs_cas.h b/src/lib/formats/trs_cas.h
index 57954faf30c..139c519106f 100644
--- a/src/lib/formats/trs_cas.h
+++ b/src/lib/formats/trs_cas.h
@@ -14,6 +14,7 @@
#include "cassimg.h"
+CASSETTE_FORMATLIST_EXTERN(trs80l1_cassette_formats);
CASSETTE_FORMATLIST_EXTERN(trs80l2_cassette_formats);
#endif // MAME_FORMATS_TRS_CAS_H
diff --git a/src/mame/drivers/trs80.cpp b/src/mame/drivers/trs80.cpp
index 07dd84c0fbb..0683bb4647a 100644
--- a/src/mame/drivers/trs80.cpp
+++ b/src/mame/drivers/trs80.cpp
@@ -463,6 +463,8 @@ void trs80_state::trs80(machine_config &config) // the original model I, l
/* devices */
CASSETTE(config, m_cassette);
+ m_cassette->set_formats(trs80l1_cassette_formats);
+ m_cassette->set_default_state(CASSETTE_PLAY);
m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
}
@@ -476,7 +478,6 @@ void trs80_state::model1(machine_config &config) // model I, level II
/* devices */
m_cassette->set_formats(trs80l2_cassette_formats);
- m_cassette->set_default_state(CASSETTE_PLAY);
QUICKLOAD(config, "quickload", "cmd", attotime::from_seconds(1)).set_load_callback(FUNC(trs80_state::quickload_cb));