6
Offset Value Type Description
7
0x00 (note) ASCII 22 bytes "Compressed Square Wave" signature
8
0x16 0x1A BYTE Terminator code
9
0x17 0x02 BYTE CSW major revision number
10
0x18 0x00 BYTE CSW minor revision number
11
0x19 DWORD Sample rate
12
0x1D DWORD Total number of pulses (after decompression)
13
0x21 BYTE Compression type 0x01: RLE 0x02: Z-RLE
14
0x22 BYTE Flags b0: initial polarity: if set, the signal starts at logical high
15
0x23 HDR BYTE Header extension length in bytes (0x00)
16
0x24 ASCII 16 bytes free use
17
0x34 BYTE Start of Header is HDR>0
30
#define CSW_WAV_FREQUENCY 44100
32
static const UINT8 CSW_HEADER[] = { "Compressed Square Wave" };
34
static UINT32 get_leuint32(const void *ptr)
37
memcpy(&value, ptr, sizeof(value));
38
return LITTLE_ENDIANIZE_INT32(value);
43
static int csw_cas_to_wav_size( const UINT8 *casdata, int caslen ) {
45
UINT32 NumberOfPulses;
48
UINT8 CompressionType;
50
UINT8 HeaderExtensionLength;
59
if ( memcmp( casdata, CSW_HEADER, sizeof(CSW_HEADER) ) ) {
60
LOG_FORMATS( "csw_cas_to_wav_size: cassette image has incompatible header\n" );
64
if (casdata[0x16]!=0x1a) {
65
LOG_FORMATS( "csw_cas_to_wav_size: Terminator Code Not Found\n" );
69
MajorRevision=casdata[0x17];
70
MinorRevision=casdata[0x18];
72
LOG_FORMATS("Version %d : %d\n",MajorRevision,MinorRevision);
74
if (casdata[0x17]!=2){
75
LOG_FORMATS( "csw_cas_to_wav_size: Unsuported Major Version\n" );
79
SampleRate=get_leuint32(casdata+0x19);
80
LOG_FORMATS("Sample rate %d\n",SampleRate);
82
NumberOfPulses=get_leuint32(casdata+0x1d);
83
LOG_FORMATS("Number Of Pulses %d\n",NumberOfPulses);
86
CompressionType=casdata[0x21];
88
HeaderExtensionLength=casdata[0x23];
90
LOG_FORMATS("CompressionType %d Flast %d HeaderExtensionLength %d\n",CompressionType,Flags,HeaderExtensionLength);
93
//from here on down for now I am assuming it is compressed csw file.
94
in_ptr = (UINT8*) casdata+0x34+HeaderExtensionLength;
96
gz_ptr = (UINT8*)malloc( 8 );
99
d_stream.next_in = (unsigned char *)in_ptr;
100
d_stream.avail_in = caslen - ( in_ptr - casdata );
103
d_stream.next_out = gz_ptr;
104
d_stream.avail_out = 1;
105
d_stream.total_out=0;
110
d_stream.data_type=0;
112
err = inflateInit( &d_stream );
114
LOG_FORMATS( "inflateInit2 error: %d\n", err );
122
d_stream.next_out = gz_ptr;
123
d_stream.avail_out=1;
124
err=inflate( &d_stream, Z_SYNC_FLUSH );
128
d_stream.avail_out=4;
129
d_stream.next_out = gz_ptr;
130
err=inflate( &d_stream, Z_SYNC_FLUSH );
131
bsize=get_leuint32(gz_ptr);
133
total_size=total_size+bsize;
138
if ( err != Z_STREAM_END ) {
139
LOG_FORMATS( "inflate error: %d\n", err );
143
err = inflateEnd( &d_stream );
145
LOG_FORMATS( "inflateEnd error: %d\n", err );
172
static int csw_cas_fill_wave( INT16 *buffer, int length, UINT8 *bytes ) {
174
UINT32 NumberOfPulses;
175
UINT8 CompressionType;
177
UINT8 HeaderExtensionLength;
180
UINT8 *gz_ptr = NULL;
189
LOG_FORMATS("Length %d\n",length);
191
SampleRate=get_leuint32(bytes+0x19);
192
LOG_FORMATS("Sample rate %d\n",SampleRate);
194
NumberOfPulses=get_leuint32(bytes+0x1d);
195
LOG_FORMATS("Number Of Pulses %d\n",NumberOfPulses);
197
CompressionType=bytes[0x21];
199
HeaderExtensionLength=bytes[0x23];
208
LOG_FORMATS("CompressionType %d Flast %d HeaderExtensionLength %d\n",CompressionType,Flags,HeaderExtensionLength);
211
//from here on down for now I am assuming it is compressed csw file.
212
in_ptr = (UINT8*) bytes+0x34+HeaderExtensionLength;
214
gz_ptr = (UINT8*)malloc( 8 );
217
d_stream.next_in = (unsigned char *)in_ptr;
218
d_stream.avail_in = mycaslen - ( in_ptr - bytes );
221
d_stream.next_out = gz_ptr;
222
d_stream.avail_out = 1;
223
d_stream.total_out=0;
228
d_stream.data_type=0;
230
err = inflateInit( &d_stream );
232
LOG_FORMATS( "inflateInit2 error: %d\n", err );
240
d_stream.next_out = gz_ptr;
241
d_stream.avail_out=1;
242
err=inflate( &d_stream, Z_SYNC_FLUSH );
246
d_stream.avail_out=4;
247
d_stream.next_out = gz_ptr;
248
err=inflate( &d_stream, Z_SYNC_FLUSH );
249
bsize=get_leuint32(gz_ptr);
251
for (i=0;i<bsize;i++)
253
buffer[total_size++]=Bit;
260
if ( err != Z_STREAM_END ) {
261
LOG_FORMATS( "inflate error: %d\n", err );
265
err = inflateEnd( &d_stream );
267
LOG_FORMATS( "inflateEnd error: %d\n", err );
297
static const struct CassetteLegacyWaveFiller csw_legacy_fill_wave = {
298
csw_cas_fill_wave, /* fill_wave */
300
0, /* chunk_samples */
301
csw_cas_to_wav_size, /* chunk_sample_calc */
302
CSW_WAV_FREQUENCY, /* sample_frequency */
303
0, /* header_samples */
304
0 /* trailer_samples */
307
static casserr_t csw_cassette_identify( cassette_image *cassette, struct CassetteOptions *opts ) {
308
return cassette_legacy_identify( cassette, opts, &csw_legacy_fill_wave );
311
static casserr_t csw_cassette_load( cassette_image *cassette ) {
312
return cassette_legacy_construct( cassette, &csw_legacy_fill_wave );
315
static const struct CassetteFormat csw_cassette_format = {
317
csw_cassette_identify,
322
CASSETTE_FORMATLIST_START(csw_cassette_formats)
323
CASSETTE_FORMAT(csw_cassette_format)
324
CASSETTE_FORMATLIST_END
326
CASSETTE_FORMATLIST_START(bbc_cassette_formats)
327
CASSETTE_FORMAT(csw_cassette_format)
328
CASSETTE_FORMAT(uef_cassette_format)
329
CASSETTE_FORMATLIST_END