#include #include "mame.h" #include "fmsx_cas.h" #define CAS_PERIOD (16) #define CAS_HEADER_PERIODS (4000) #define CAS_EMPTY_PERIODS (1000) #define ALLOCATE_BLOCK (1024*8) static const UINT8 CasHeader[8] = { 0x1F,0xA6,0xDE,0xBA,0xCC,0x13,0x7D,0x74 }; static int fmsx_cas_to_wav_size (const UINT8 *casdata, int caslen) { int pos, size; if (caslen < 8) return -1; if (memcmp (casdata, CasHeader, sizeof (CasHeader) ) ) return -1; pos = size = 0; while (pos < caslen) { if ( (pos + 8) < caslen) if (!memcmp (casdata + pos, CasHeader, 8) ) { size += (CAS_EMPTY_PERIODS + CAS_HEADER_PERIODS) * CAS_PERIOD; pos += 8; continue; } size += CAS_PERIOD * 12; pos++; } return size; } static int fmsx_cas_to_wav (const UINT8 *casdata, int caslen, INT16 **wavdata, int *wavlen) { int cas_pos, samples_size, bit, state = 1, samples_pos, size, n, i, p; INT16 *samples, *nsamples; if (caslen < 8) return 1; if (memcmp (casdata, CasHeader, sizeof (CasHeader) ) ) return 1; cas_pos = 8; samples_size = ALLOCATE_BLOCK * 2; samples = (INT16*) malloc (samples_size); if (!samples) return 2; samples_pos = 0; while (cas_pos < caslen) { /* check memory for entire header (silence + header itself) */ size = (CAS_EMPTY_PERIODS + CAS_HEADER_PERIODS) * CAS_PERIOD; if ( (samples_pos + size) >= samples_size) { samples_size += size; nsamples = (INT16*) realloc (samples, samples_size * 2); if (!nsamples) { free (samples); return 2; } else samples = nsamples; } /* write CAS_EMPTY_PERIODS of silence */ memset (samples + samples_pos, 0, CAS_EMPTY_PERIODS * CAS_PERIOD * 2); samples_pos += CAS_EMPTY_PERIODS * CAS_PERIOD; /* write CAS_HEADER_PERIODS of header (high frequency) */ for (i=0;i= samples_size) { samples_size += ALLOCATE_BLOCK; nsamples = (INT16*) realloc (samples, samples_size * 2); if (!nsamples) { free (samples); return 2; } else samples = nsamples; } for (i=0;i<=11;i++) { if (i == 0) bit = 0; else if (i < 9) bit = (casdata[cas_pos] & (1 << (i - 1) ) ); else bit = 1; /* write this one bit */ for (n=0;n<(bit ? 4 : 2);n++) { size = (bit ? CAS_PERIOD / 4 : CAS_PERIOD / 2); for (p=0;p