diff options
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 |
commit | bbe2ab5923091954d28dc75cb64611ba88079f21 (patch) | |
tree | 162b334e0bd383c01908e7461afbce590d950ccc /src/lib | |
parent | 3e28cafa550b94cc782a76b2ad15827d48b878bb (diff) |
trs80: Added support for Level 1 CAS files.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/formats/trs_cas.cpp | 82 | ||||
-rw-r--r-- | src/lib/formats/trs_cas.h | 1 |
2 files changed, 66 insertions, 17 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 |