formats/tzx_cas.cpp: Added block 4B support (TSX format) / Fixed bug in block 35

This commit is contained in:
Andrei Holub 2025-02-01 19:28:19 -05:00
parent ea9bc40370
commit 4b41673fdc
4 changed files with 109 additions and 3 deletions

View File

@ -1229,6 +1229,9 @@ void mame_formats_full_list(mame_formats_enumerator &en)
#ifdef HAS_FORMATS_FMSX_CAS
en.add(fmsx_cassette_formats); // fmsx_cas.h
#endif
#ifdef HAS_FORMATS_TZX_CAS
en.add(tsx_cassette_formats); // tzx_cas.h
#endif
#ifdef HAS_FORMATS_MSX_DSK
en.add(FLOPPY_MSX_FORMAT); // msx_dsk.h
#endif

View File

@ -2,6 +2,7 @@
// copyright-holders:Sean Young
#include "fmsx_cas.h"
#include "tzx_cas.h"
#include <cstring>
@ -144,4 +145,5 @@ static const cassette_image::Format fmsx_cas_format =
CASSETTE_FORMATLIST_START(fmsx_cassette_formats)
CASSETTE_FORMAT(fmsx_cas_format)
CASSETTE_FORMAT(tsx_cassette_format)
CASSETTE_FORMATLIST_END

View File

@ -186,6 +186,7 @@ static void tzx_cas_get_blocks( const uint8_t *casdata, int caslen )
case 0x5A:
pos += 9;
break;
case 0x4b:
default:
datasize = get_u32le(&casdata[pos]);
pos += 4 + datasize;
@ -299,6 +300,68 @@ static int tzx_cas_handle_block( int16_t **buffer, const uint8_t *bytes, int pau
return size;
}
static int tzx_handle_4b(int16_t **buffer, const uint8_t *bytes, uint32_t data_size, uint16_t pause_ms, uint16_t pilot, uint16_t pilot_num
, uint16_t zero, uint16_t one, uint8_t num_0, uint8_t num_1
, uint8_t leading_num, bool leading_bit, uint8_t trailing_num, bool trailing_bit, bool msb)
{
const int pilot_samples = tcycles_to_samplecount(pilot);
const int bit0_samples = tcycles_to_samplecount(zero);
const int bit1_samples = tcycles_to_samplecount(one);
int size = 0;
// pilot
for ( ; pilot_num > 0; pilot_num--)
{
tzx_output_wave(buffer, pilot_samples);
size += pilot_samples;
toggle_wave_data();
}
// data
uint16_t data_common = 0;
for (uint8_t i = leading_num; i > 0; i--)
{
data_common <<= 1;
data_common |= leading_bit;
}
data_common <<= 8;
for (uint8_t i = trailing_num; i > 0; i--)
{
data_common <<= 1;
data_common |= trailing_bit;
}
for (int data_index = 0; data_index < data_size; data_index++)
{
uint16_t data = data_common;
data |= (msb ? bytes[data_index] : util::bitswap<8>(bytes[data_index], 0, 1, 2, 3, 4, 5, 6, 7)) << trailing_num;
for (uint16_t mask = (1 << (leading_num + 7 + trailing_num)); mask > 0; mask >>= 1)
{
const bool bit = data & mask;
int bit_samples = bit ? bit1_samples : bit0_samples;
for(uint8_t i = (bit ? num_1 : num_0); i > 0; i--)
{
tzx_output_wave(buffer, bit_samples);
size += bit_samples;
toggle_wave_data();
}
}
}
// pause
if (pause_ms > 0)
{
size += pause_one_millisec(buffer);
const int rest_pause_samples = millisec_to_samplecount(pause_ms - 1);
wave_data = WAVE_NULL;
tzx_output_wave(buffer, rest_pause_samples);
size += rest_pause_samples;
}
return size;
}
static int tzx_handle_direct(int16_t **buffer, const uint8_t *bytes, int pause, int data_size, int tstates, int bits_in_last_byte)
{
int size = 0;
@ -648,14 +711,14 @@ static int tzx_cas_do_work( int16_t **buffer )
break;
case 0x35: /* Custom Info Block */
ascii_block_common_log("Custom Info Block", block_type);
for (data_size = 0; data_size < 10; data_size++)
for (data_size = 0; data_size < 0x10; data_size++)
{
LOG_FORMATS("%c", cur_block[1 + data_size]);
}
LOG_FORMATS(":\n");
text_size = get_u32le(&cur_block[11]);
text_size = get_u32le(&cur_block[0x11]);
for (data_size = 0; data_size < text_size; data_size++)
LOG_FORMATS("%c", cur_block[15 + data_size]);
LOG_FORMATS("%c", cur_block[0x15 + data_size]);
LOG_FORMATS("\n");
current_block++;
break;
@ -736,6 +799,30 @@ static int tzx_cas_do_work( int16_t **buffer )
}
break;
case 0x4b: // TSX Data Block
{
data_size = get_u32le(&cur_block[1]) - 12;
pause_time = get_u16le(&cur_block[5]);
pilot = get_u16le(&cur_block[7]);
pilot_length = get_u16le(&cur_block[9]);
uint16_t zero = get_u16le(&cur_block[11]);
uint16_t one = get_u16le(&cur_block[13]);
bit0 = (cur_block[15] >> 4) ?: 16;
bit1 = (cur_block[15] & 0x0f) ?: 16;
uint8_t leading_num = util::BIT(cur_block[16], 6, 2);
bool leading_bit = util::BIT(cur_block[16], 5);
uint8_t trailing_num = util::BIT(cur_block[16], 3, 2);
bool trailing_bit = util::BIT(cur_block[16], 2);
bool msb = util::BIT(cur_block[16], 0);
wave_data = WAVE_NULL;
size += tzx_handle_4b(buffer, &cur_block[17], data_size, pause_time, pilot, pilot_length
, zero, one, bit0, bit1
, leading_num, leading_bit, trailing_num, trailing_bit, msb);
current_block++;
}
break;
}
}
// Adding 1 ms. pause to ensure that the last edge is properly finished at the end of tape
@ -930,6 +1017,14 @@ const cassette_image::Format tzx_cassette_format =
nullptr
};
const cassette_image::Format tsx_cassette_format =
{
"tsx",
tzx_cassette_identify,
tzx_cassette_load,
nullptr
};
static const cassette_image::Format tap_cassette_format =
{
"tap,blk",
@ -946,6 +1041,10 @@ static const cassette_image::Format cdt_cassette_format =
nullptr
};
CASSETTE_FORMATLIST_START(tsx_cassette_formats)
CASSETTE_FORMAT(tsx_cassette_format)
CASSETTE_FORMATLIST_END
CASSETTE_FORMATLIST_START(tzx_cassette_formats)
CASSETTE_FORMAT(tzx_cassette_format)
CASSETTE_FORMAT(tap_cassette_format)

View File

@ -13,8 +13,10 @@
#include "cassimg.h"
extern const cassette_image::Format tsx_cassette_format;
extern const cassette_image::Format tzx_cassette_format;
CASSETTE_FORMATLIST_EXTERN(tsx_cassette_formats);
CASSETTE_FORMATLIST_EXTERN(tzx_cassette_formats);
CASSETTE_FORMATLIST_EXTERN(cdt_cassette_formats);