Esempio n. 1
0
static floperr_t g64_read_track(floppy_image_legacy *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen)
{
    /*

        The following is written into the buffer:

        n bytes of track data
        1982 bytes of speed zone data

        get_track_size() returns n (size of track data)

    */

    struct g64dsk_tag *tag = get_tag(floppy);
    floperr_t err;
    UINT64 track_offset;
    UINT16 track_length = tag->track_size[head][track];

    // get track offset
    err = get_track_offset(floppy, head, track, &track_offset);

    if (err)
        return err;

    if ((head <= tag->heads) && track_offset)
    {
        if (buflen < track_length) {
            printf("G64 track buffer too small: %u < %u!", (UINT32)buflen, track_length);
            exit(-1);
        }

        // read track data
        floppy_image_read(floppy, ((UINT8*)buffer), track_offset + 2, track_length); // skip the 2 track length bytes in the beginning of track data

        if (tag->speed_zone_offset[head][track] > 3)
        {
            // read speed block
            floppy_image_read(floppy, ((UINT8*)buffer) + track_length, tag->speed_zone_offset[head][track], G64_SPEED_BLOCK_SIZE);
        }
        else
        {
            // create a speed block with the same speed zone for the whole track
            UINT8 speed = tag->speed_zone_offset[head][track] & 0x03;
            UINT8 speed_byte = (speed << 6) | (speed << 4) | (speed << 2) | speed;

            memset(((UINT8*)buffer) + track_length, speed_byte, G64_SPEED_BLOCK_SIZE);
        }

        LOG_FORMATS("G64 side %u track %.1f length %u\n", head, get_dos_track(track), track_length);
    }
    else
    {
        // no data for given track, or tried to read side 1
        memset(((UINT8*)buffer), 0, buflen);

        LOG_FORMATS("G64 side %u track %.1f\n", head, get_dos_track(track));
    }

    return FLOPPY_ERROR_SUCCESS;
}
Esempio n. 2
0
static uint32_t d88_get_sector_offset(floppy_image_legacy* floppy, int head, int track, int sector)
{
	struct d88_tag* tag = get_d88_tag(floppy);
	uint32_t offset = 0;
	uint8_t sector_hdr[16];
	uint32_t len;
	uint32_t secs;
	int count;

	// get offset of the beginning of the track
	offset = tag->trackoffset[(track*tag->heads)+head];

	floppy_image_read(floppy,sector_hdr,offset,16);
	secs = sector_hdr[4];

	for(count=0;count<secs;count++)
	{
		floppy_image_read(floppy,sector_hdr,offset,16);
		if(sector == sector_hdr[2])
		{
			LOG_FORMATS("d88_get_sector_offset - track %i, side %i, sector %02x, returns %08x\n",track,head,sector,offset+16);
			return offset + 16;
		}
		len = (sector_hdr[15] << 8) | sector_hdr[14];
		len += 16;
		offset += len;
	}
	LOG_FORMATS("d88_get_sector_offset - track %i, side %i, sector %02x, not found\n",track,head,sector);
	return 0;
}
Esempio n. 3
0
bool apd_format::load(io_generic *io, uint32_t form_factor, floppy_image *image)
{
	uint64_t size = io_generic_size(io);
	std::vector<uint8_t> img(size);
	io_generic_read(io, &img[0], 0, size);

	int err;
	std::vector<uint8_t> gz_ptr;
	z_stream d_stream;
	int inflate_size = (img[size - 1] << 24) | (img[size - 2] << 16) | (img[size - 3] << 8) | img[size - 4];
	uint8_t *in_ptr = &img[0];

	if (!memcmp(&img[0], GZ_HEADER, sizeof(GZ_HEADER))) {
		gz_ptr.resize(inflate_size);

		d_stream.zalloc = nullptr;
		d_stream.zfree = nullptr;
		d_stream.opaque = nullptr;
		d_stream.next_in = in_ptr;
		d_stream.avail_in = size;
		d_stream.next_out = &gz_ptr[0];
		d_stream.avail_out = inflate_size;

		err = inflateInit2(&d_stream, MAX_WBITS | 16);
		if (err != Z_OK) {
			LOG_FORMATS("inflateInit2 error: %d\n", err);
			return false;
		}
		err = inflate(&d_stream, Z_FINISH);
		if (err != Z_STREAM_END && err != Z_OK) {
			LOG_FORMATS("inflate error: %d\n", err);
			return false;
		}
		err = inflateEnd(&d_stream);
		if (err != Z_OK) {
			LOG_FORMATS("inflateEnd error: %d\n", err);
			return false;
		}
		size = inflate_size;
		img = gz_ptr;
	}

	int data = 0x7d0;
	for (int track = 0; track < 166; track++) {
		uint32_t sdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x0]));
		uint32_t ddlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x4]));
		uint32_t qdlen = little_endianize_int32(*(uint32_t *)(&img[(track * 12) + 8 + 0x8]));

		if (sdlen > 0) {
			generate_track_from_bitstream(track / 2, track % 2, &img[data], sdlen, image);
			data += (sdlen + 7) >> 3;
		}
		if (ddlen > 0) {
			generate_track_from_bitstream(track / 2, track % 2, &img[data], ddlen, image);
			data += (ddlen + 7) >> 3;
		}
Esempio n. 4
0
static floperr_t g64_read_track(floppy_image *floppy, int head, int track, UINT64 offset, void *buffer, size_t buflen)
{
	struct g64dsk_tag *tag = get_tag(floppy);
	floperr_t err;
	UINT64 track_offset;
	UINT16 track_length = 0;

	/* get track offset */
	err = get_track_offset(floppy, head, track, &track_offset);

	if (err)
		return err;

	if (!head && track_offset)
	{
		if (buflen < tag->track_size) { printf("G64 track buffer too small: %u!", (UINT32)buflen); exit(-1); }

		/* read track */
		floppy_image_read(floppy, buffer, track_offset + 2, tag->track_size);
	}
	else
	{
		/* set track length to 0 */
		memset(buffer, 0, buflen);
	}

	if (LOG) LOG_FORMATS("G64 track %.1f length %u\n", get_dos_track(track), track_length);

	return FLOPPY_ERROR_SUCCESS;
}
Esempio n. 5
0
bool g64_format::save(io_generic *io, floppy_image *image)
{
	int tracks, heads;
	image->get_actual_geometry(tracks, heads);
	tracks = TRACK_COUNT * heads;

	// write header
	UINT8 header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, tracks, TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 };
	io_generic_write(io, header, POS_SIGNATURE, sizeof(header));

	// write tracks
	for (int head = 0; head < heads; head++) {
		int tracks_written = 0;

		dynamic_buffer trackbuf(TRACK_LENGTH-2);

		for (int track = 0; track < TRACK_COUNT; track++) {
			UINT32 tpos = POS_TRACK_OFFSET + (track * 4);
			UINT32 spos = tpos + (tracks * 4);
			UINT32 dpos = POS_TRACK_OFFSET + (tracks * 4 * 2) + (tracks_written * TRACK_LENGTH);

			io_generic_write_filler(io, 0x00, tpos, 4);
			io_generic_write_filler(io, 0x00, spos, 4);

			if (image->get_buffer(track, head).size() <= 1)
				continue;

			int track_size;
			int speed_zone;

			// figure out the cell size and speed zone from the track data
			if ((speed_zone = generate_bitstream(track, head, 3, &trackbuf[0], track_size, image)) == -1)
				if ((speed_zone = generate_bitstream(track, head, 2, &trackbuf[0], track_size, image)) == -1)
					if ((speed_zone = generate_bitstream(track, head, 1, &trackbuf[0], track_size, image)) == -1)
						if ((speed_zone = generate_bitstream(track, head, 0, &trackbuf[0], track_size, image)) == -1)
							throw emu_fatalerror("g64_format: Cannot determine speed zone for track %u", track);

			LOG_FORMATS("head %u track %u size %u cell %u\n", head, track, track_size, c1541_cell_size[speed_zone]);

			UINT8 track_offset[4];
			UINT8 speed_offset[4];
			UINT8 track_length[2];

			place_integer_le(track_offset, 0, 4, dpos);
			place_integer_le(speed_offset, 0, 4, speed_zone);
			place_integer_le(track_length, 0, 2, track_size/8);

			io_generic_write(io, track_offset, tpos, 4);
			io_generic_write(io, speed_offset, spos, 4);
			io_generic_write_filler(io, 0xff, dpos, TRACK_LENGTH);
			io_generic_write(io, track_length, dpos, 2);
			io_generic_write(io, &trackbuf[0], dpos + 2, track_size);

			tracks_written++;
		}
	}

	return true;
}
Esempio n. 6
0
static int tap_cas_to_wav_size( const uint8_t *casdata, int caslen )
{
	int size = 0;
	const uint8_t *p = casdata;

	while (p < casdata + caslen)
	{
		int data_size = p[0] + (p[1] << 8);
		int pilot_length = (p[2] == 0x00) ? 8064 : 3220;    /* TZX specification */
//  int pilot_length = (p[2] == 0x00) ? 8063 : 3223;    /* worldofspectrum */
		LOG_FORMATS("tap_cas_to_wav_size: Handling TAP block containing 0x%X bytes", data_size);
		p += 2;
		size += tzx_cas_handle_block(nullptr, p, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
		LOG_FORMATS(", total size is now: %d\n", size);
		p += data_size;
	}
	return size;
}
Esempio n. 7
0
static int tzx_cas_to_wav_size( const uint8_t *casdata, int caslen )
{
	int size = 0;

	/* Header size plus major and minor version number */
	if (caslen < 10)
	{
		LOG_FORMATS("tzx_cas_to_wav_size: cassette image too small\n");
		goto cleanup;
	}

	/* Check for correct header */
	if (memcmp(casdata, TZX_HEADER, sizeof(TZX_HEADER)))
	{
		LOG_FORMATS("tzx_cas_to_wav_size: cassette image has incompatible header\n");
		goto cleanup;
	}

	/* Check major version number in header */
	if (casdata[0x08] > SUPPORTED_VERSION_MAJOR)
	{
		LOG_FORMATS("tzx_cas_to_wav_size: unsupported version\n");
		goto cleanup;
	}

	tzx_cas_get_blocks(casdata, caslen);

	LOG_FORMATS("tzx_cas_to_wav_size: %d blocks found\n", block_count);

	if (block_count == 0)
	{
		LOG_FORMATS("tzx_cas_to_wav_size: no blocks found!\n");
		goto cleanup;
	}

	size = tzx_cas_do_work(nullptr);

	return size;

cleanup:
	return -1;
}
Esempio n. 8
0
int fsd_format::identify(io_generic *io, UINT32 form_factor)
{
	UINT8 h[3];

	io_generic_read(io, h, 0, 3);
	if (memcmp(h, "FSD", 3) == 0) {
		return 100;
	}
	LOG_FORMATS("fsd: no match\n");
	return 0;
}
Esempio n. 9
0
bool g64_format::save(io_generic *io, floppy_image *image)
{
	UINT8 header[] = { 'G', 'C', 'R', '-', '1', '5', '4', '1', 0x00, 0x54, TRACK_LENGTH & 0xff, TRACK_LENGTH >> 8 };

	io_generic_write(io, header, SIGNATURE, sizeof(header));
	
	int head = 0;
	int tracks_written = 0;

	for (int track = 0; track < 84; track++) {
		offs_t tpos = TRACK_OFFSET + track * 4;
		offs_t spos = SPEED_ZONE + track * 4;
		offs_t dpos = TRACK_DATA + tracks_written * TRACK_LENGTH;

		io_generic_write_filler(io, 0x00, tpos, 4);
		io_generic_write_filler(io, 0x00, spos, 4);

		if (image->get_track_size(track, head) <= 1)
			continue;

		UINT8 *trackbuf = global_alloc_array(UINT8, TRACK_LENGTH-2);
		int track_size;
		int speed_zone;

		// figure out the cell size and speed zone from the track data
		if ((speed_zone = generate_bitstream(track, head, 3, trackbuf, track_size, image)) == -1)
			if ((speed_zone = generate_bitstream(track, head, 2, trackbuf, track_size, image)) == -1)
				if ((speed_zone = generate_bitstream(track, head, 1, trackbuf, track_size, image)) == -1)
					if ((speed_zone = generate_bitstream(track, head, 0, trackbuf, track_size, image)) == -1)
						throw emu_fatalerror("g64_format: Cannot determine speed zone for track %u", track);

		LOG_FORMATS("track %u size %u cell %u\n", track, track_size, c1541_cell_size[speed_zone]);

		UINT8 track_offset[4];
		UINT8 speed_offset[4];
		UINT8 track_length[2];

		place_integer_le(track_offset, 0, 4, dpos);
		place_integer_le(speed_offset, 0, 4, speed_zone);
		place_integer_le(track_length, 0, 2, track_size/8);

		io_generic_write(io, track_offset, tpos, 4);
		io_generic_write(io, speed_offset, spos, 4);
		io_generic_write_filler(io, 0xff, dpos, TRACK_LENGTH);
		io_generic_write(io, track_length, dpos, 2);
		io_generic_write(io, trackbuf, dpos + 2, track_size);
		
		tracks_written++;

		global_free(trackbuf);
	}

	return true;
}
Esempio n. 10
0
bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT64 size = io_generic_size(io);
	dynamic_buffer img(size);
	io_generic_read(io, &img[0], 0, size);

	if (img[POS_VERSION]) {
		throw emu_fatalerror("g64_format: Unsupported version %u", img[POS_VERSION]);
	}

	int track_count = img[POS_TRACK_COUNT];
	int head = 0;

	for (int track = 0; track < track_count; track++)
	{
		int cylinder = track % TRACK_COUNT;

		if (track == TRACK_COUNT)
			head = 1;

		UINT32 tpos = POS_TRACK_OFFSET + (track * 4);
		UINT32 spos = tpos + (track_count * 4);
		UINT32 dpos = pick_integer_le(&img[0], tpos, 4);

		if (!dpos)
			continue;

		if (dpos > size)
			throw emu_fatalerror("g64_format: Track %u offset %06x out of bounds", track, dpos);

		UINT32 speed_zone = pick_integer_le(&img[0], spos, 4);

		if (speed_zone > 3)
			throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track);

		UINT16 track_bytes = pick_integer_le(&img[0], dpos, 2);
		int track_size = track_bytes * 8;

		LOG_FORMATS("head %u track %u offs %u size %u cell %ld\n", head, cylinder, dpos, track_bytes, 200000000L/track_size);

		generate_track_from_bitstream(cylinder, head, &img[dpos+2], track_size, image);
	}

	if (!head)
		image->set_variant(floppy_image::SSSD);
	else
		image->set_variant(floppy_image::DSSD);

	return true;
}
Esempio n. 11
0
static int x1_handle_tap(INT16* buffer, const UINT8* casdata)
{
	int sample_count = 0;
	int data_pos = 0x28;

	if(memcmp(casdata, "TAPE",4))  // header check
	{
		LOG_FORMATS("TAP: image is not a 'new' format TAP image\n");
		return -1;
	}
	if(samplerate != 8000)
	{
		LOG_FORMATS("TAP: images that are not 8000Hz are not yet supported\n");
		return -1;
	}

	while(sample_count < cas_size)
	{
		sample_count += x1_fill_wave(buffer,casdata[data_pos],sample_count);
		data_pos++;
	}

	return sample_count;
}
Esempio n. 12
0
static int tap_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
{
	int16_t *p = buffer;
	int size = 0;

	while (size < length)
	{
		int data_size = bytes[0] + (bytes[1] << 8);
		int pilot_length = (bytes[2] == 0x00) ? 8064 : 3220;    /* TZX specification */
//  int pilot_length = (bytes[2] == 0x00) ? 8063 : 3223;    /* worldofspectrum */
		LOG_FORMATS("tap_cas_fill_wave: Handling TAP block containing 0x%X bytes\n", data_size);
		bytes += 2;
		size += tzx_cas_handle_block(&p, bytes, 1000, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
		bytes += data_size;
	}
	return size;
}
Esempio n. 13
0
static int x1_handle_tap(INT16* buffer, const UINT8* casdata)
{
	int sample_count = 0;
	int data_pos = new_format ? 0x28 : 0x04;

	if (samplerate != 8000)
	{
		LOG_FORMATS("TAP: images that are not 8000Hz are not yet supported\n");
		return -1;
	}

	while (sample_count < cas_size)
	{
		sample_count += x1_fill_wave(buffer, casdata[data_pos], sample_count);
		data_pos++;
	}

	return sample_count;
}
Esempio n. 14
0
bool g64_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT64 size = io_generic_size(io);
	UINT8 *img = global_alloc_array(UINT8, size);
	io_generic_read(io, img, 0, size);

	if (img[VERSION]) {
		throw emu_fatalerror("g64_format: Unsupported version %u", img[VERSION]);
	}

	int track_count = img[TRACK_COUNT];
	int head = 0;

	for (int track = 0; track < track_count; track++)
	{
		offs_t track_offset = pick_integer_le(img, TRACK_OFFSET + (track * 4), 4);
		
		if (!track_offset)
			continue;

		if (track_offset > size)
			throw emu_fatalerror("g64_format: Track %u offset %06x out of bounds", track, track_offset);

		offs_t speed_zone = pick_integer_le(img, SPEED_ZONE + (track * 4), 4);

		if (speed_zone > 3)
			throw emu_fatalerror("g64_format: Unsupported variable speed zones on track %d", track);

		UINT16 track_bytes = pick_integer_le(img, track_offset, 2);
		int track_size = track_bytes * 8;
		
		LOG_FORMATS("track %u size %u cell %ld\n", track, track_size, 200000000L/track_size);

		generate_track_from_bitstream(track, head, &img[track_offset+2], track_size, image);
	}

	global_free(img);

	image->set_variant(floppy_image::SSSD);

	return true;
}
Esempio n. 15
0
/* length is length of sample buffer to fill! */
static int oric_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes)
{
	unsigned char header[9];
	UINT8 *data_ptr;
	INT16 *p;
	int i;
	UINT8 data;

	p = buffer;


	/* header and trailer act as pauses */
	/* the trailer is required so that the via sees the last bit of the last
        byte */
	if (bytes == CODE_HEADER) {
		for (i = 0; i < ORIC_WAVESAMPLES_HEADER; i++)
			*(p++) = WAVEENTRY_NULL;
	}
	else if (bytes == CODE_TRAILER) {
		for (i = 0; i < ORIC_WAVESAMPLES_TRAILER; i++)
			*(p++) = WAVEENTRY_NULL;
	}
	else
{
	/* the length is the number of samples left in the buffer and NOT the number of bytes for the input file */
	length = length - ORIC_WAVESAMPLES_TRAILER;

	oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
	data_ptr = bytes;

	while ((data_ptr<(bytes + oric.tap_size)) && (p < (buffer+length)) )
	{
		data = data_ptr[0];
		data_ptr++;

		switch (oric.cassette_state)
		{
			case ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE:
			{
				if (data==ORIC_SYNC_BYTE)
				{
					LOG_FORMATS("found sync byte!\n");
					/* found first sync byte */
					oric.cassette_state = ORIC_CASSETTE_GOT_SYNC_BYTE;
				}
			}
			break;

			case ORIC_CASSETTE_GOT_SYNC_BYTE:
			{
				if (data!=ORIC_SYNC_BYTE)
				{
					/* 0.25 second pause */
					p = oric_fill_pause(p, oric_seconds_to_samples(0.25));

					LOG_FORMATS("found end of sync bytes!\n");
					/* found end of sync bytes */
					for (i=0; i<ORIC_LEADER_LENGTH; i++)
					{
						p = oric_output_byte(p,0x016);
					}

					if (data==0x024)
					{
						//LOG_FORMATS("reading header!\n");
						p = oric_output_byte(p,data);
						oric.cassette_state = ORIC_CASSETTE_READ_HEADER;
						oric.data_count = 0;
						oric.data_length = 9;
					}
				}
			}
			break;

			case ORIC_CASSETTE_READ_HEADER:
			{
				header[oric.data_count] = data;
				p = oric_output_byte(p, data);
				oric.data_count++;

				if (oric.data_count==oric.data_length)
				{
					//LOG_FORMATS("finished reading header!\n");
					oric.cassette_state = ORIC_CASSETTE_READ_FILENAME;
				}
			}
			break;

			case ORIC_CASSETTE_READ_FILENAME:
			{
				p = oric_output_byte(p, data);

				/* got end of filename? */
				if (data==0)
				{
					UINT16 end, start;
					LOG_FORMATS("got end of filename\n");

					/* oric includes a small delay, but I don't see
                    it being 1 bits */
					for (i=0; i<100; i++)
					{
                                            p = oric_output_bit(p,1);
					}

					oric.cassette_state = ORIC_CASSETTE_WRITE_DATA;
					oric.data_count = 0;

					end = (((header[4] & 0x0ff)<<8) | (header[5] & 0x0ff));
					start = (((header[6] & 0x0ff)<<8) | (header[7] & 0x0ff));
					LOG(("start (from header): %02x\n",start));
					LOG(("end (from header): %02x\n",end));
                                        oric.data_length = end - start + 1;
				}
			}
			break;

			case ORIC_CASSETTE_WRITE_DATA:
			{
				p = oric_output_byte(p, data);
				oric.data_count++;

				if (oric.data_count==oric.data_length)
				{
					LOG_FORMATS("finished writing data!\n");
					oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
				}
			}
			break;

		}
	}
}
	return p - buffer;
}
Esempio n. 16
0
static void read_g64_header(floppy_image_legacy *floppy, struct g64dsk_tag *tag, int head, UINT64 &pos)
{
    UINT8 header[HEADER_LENGTH];

    UINT64 start_pos = pos;

    // read header
    floppy_image_read(floppy, header, pos, HEADER_LENGTH);

    // get version
    tag->version = header[8];
    if (!head) LOG_FORMATS("G64 version: %u\n", tag->version);

    // get number of tracks
    tag->tracks = header[9];
    LOG_FORMATS("G64 side %u tracks: %u\n", head, tag->tracks);

    // get track size
    UINT16 track_size = (header[0xb] << 8) | header[0xa];

    // get data offsets
    pos = 0xc;
    for (int i = 0; i < tag->tracks; i++)
    {
        tag->track_offset[head][i] = pick_integer_le(header, pos, 4);

        if (tag->track_offset[head][i])
        {
            tag->track_offset[head][i] += start_pos;
        }

        pos += 4;
    }

    // get speed zone information
    UINT32 track_offs = 0;
    for (int i = 0; i < tag->tracks; i++)
    {
        tag->speed_zone_offset[head][i] = pick_integer_le(header, pos, 4);

        if (tag->speed_zone_offset[head][i] >= 4)
        {
            tag->speed_zone_offset[head][i] += start_pos;
        }

        pos += 4;

        tag->track_size[head][i] = g64_get_track_size(floppy, head, i);

        if (tag->track_offset[head][i] != 0)
        {
            LOG_FORMATS("G64 side %u track %.1f offset %05x length %04x ", head, get_dos_track(i), tag->track_offset[head][i], tag->track_size[head][i]);

            track_offs = tag->track_offset[head][i];

            if (tag->speed_zone_offset[head][i] < 4) {
                LOG_FORMATS("speed %u\n", tag->speed_zone_offset[head][i]);
            } else {
                LOG_FORMATS("speed offset %04x\n", tag->speed_zone_offset[head][i]);
            }
        }
    }

    pos = track_offs + 2 + track_size;
}
Esempio n. 17
0
static int csw_cas_fill_wave( int16_t *buffer, int length, uint8_t *bytes )
{
	uint32_t SampleRate;
	uint32_t NumberOfPulses;
	uint8_t  CompressionType;
	uint8_t  Flags;
	uint8_t  HeaderExtensionLength;
	int8_t   Bit;

	std::vector<uint8_t> gz_ptr;
	int         total_size;
	z_stream    d_stream;
	int         err;
	uint8_t       *in_ptr;
	int         bsize=0;
	int     i;


	LOG_FORMATS("Length %d\n",length);

	SampleRate=get_leuint32(bytes+0x19);
	LOG_FORMATS("Sample rate %u\n",SampleRate);

	NumberOfPulses=get_leuint32(bytes+0x1d);
	LOG_FORMATS("Number Of Pulses %u\n",NumberOfPulses);

	CompressionType=bytes[0x21];
	Flags=bytes[0x22];
	HeaderExtensionLength=bytes[0x23];

	if ((Flags&0)==0)
	{
		Bit=-100;
	}
	else
	{
		Bit=100;
	}

	LOG_FORMATS("CompressionType %u   Flast %u   HeaderExtensionLength %u\n",CompressionType,Flags,HeaderExtensionLength);


	//from here on down for now I am assuming it is compressed csw file.
	in_ptr = (uint8_t*) bytes+0x34+HeaderExtensionLength;

	gz_ptr.resize( 8 );

	d_stream.next_in = (unsigned char *)in_ptr;
	d_stream.avail_in = mycaslen - ( in_ptr - bytes );
	d_stream.total_in=0;

	d_stream.next_out = &gz_ptr[0];
	d_stream.avail_out = 1;
	d_stream.total_out=0;

	d_stream.zalloc = nullptr;
	d_stream.zfree = nullptr;
	d_stream.opaque = nullptr;
	d_stream.data_type=0;

	err = inflateInit( &d_stream );
	if ( err != Z_OK )
	{
		LOG_FORMATS( "inflateInit2 error: %d\n", err );
		goto cleanup;
	}

	total_size=0;

	do
	{
		d_stream.next_out = &gz_ptr[0];
		d_stream.avail_out=1;
		err=inflate( &d_stream, Z_SYNC_FLUSH );
		if (err==Z_OK)
		{
			bsize=gz_ptr[0];
			if (bsize==0)
			{
				d_stream.avail_out=4;
				d_stream.next_out = &gz_ptr[0];
				err=inflate( &d_stream, Z_SYNC_FLUSH );
				bsize=get_leuint32(&gz_ptr[0]);
			}
			for (i=0;i<bsize;i++)
			{
				buffer[total_size++]=Bit;
			}
			Bit=-Bit;
		}
	}
	while (err==Z_OK);

	if ( err != Z_STREAM_END )
	{
		LOG_FORMATS( "inflate error: %d\n", err );
		goto cleanup;
	}

	err = inflateEnd( &d_stream );
	if ( err != Z_OK )
	{
		LOG_FORMATS( "inflateEnd error: %d\n", err );
		goto cleanup;
	}

	return length;

cleanup:
	return -1;
}
Esempio n. 18
0
static int csw_cas_to_wav_size( const uint8_t *casdata, int caslen )
{
	uint32_t SampleRate;
	uint32_t NumberOfPulses;
	uint8_t  MajorRevision;
	uint8_t  MinorRevision;
	uint8_t  CompressionType;
	uint8_t  Flags;
	uint8_t  HeaderExtensionLength;
	std::vector<uint8_t> gz_ptr;

	int         total_size;
	z_stream    d_stream;
	int         err;
	uint8_t       *in_ptr;
	int         bsize=0;

	if ( memcmp( casdata, CSW_HEADER, sizeof(CSW_HEADER)-1 ) )
	{
		LOG_FORMATS( "csw_cas_to_wav_size: cassette image has incompatible header\n" );
		goto cleanup;
	}

	if (casdata[0x16]!=0x1a)
	{
		LOG_FORMATS( "csw_cas_to_wav_size: Terminator Code Not Found\n" );
		goto cleanup;
	}

	MajorRevision=casdata[0x17];
	MinorRevision=casdata[0x18];

	LOG_FORMATS("Version %d : %d\n",MajorRevision,MinorRevision);

	if (casdata[0x17]!=2)
	{
		LOG_FORMATS( "csw_cas_to_wav_size: Unsuported Major Version\n" );
		goto cleanup;
	}

	SampleRate=get_leuint32(casdata+0x19);
	LOG_FORMATS("Sample rate %u\n",SampleRate);

	NumberOfPulses=get_leuint32(casdata+0x1d);
	LOG_FORMATS("Number Of Pulses %u\n",NumberOfPulses);


	CompressionType=casdata[0x21];
	Flags=casdata[0x22];
	HeaderExtensionLength=casdata[0x23];

	LOG_FORMATS("CompressionType %u   Flast %u   HeaderExtensionLength %u\n",CompressionType,Flags,HeaderExtensionLength);

	mycaslen=caslen;
	//from here on down for now I am assuming it is compressed csw file.
	in_ptr = (uint8_t*) casdata+0x34+HeaderExtensionLength;

	gz_ptr.resize( 8 );

	d_stream.next_in = (unsigned char *)in_ptr;
	d_stream.avail_in = caslen - ( in_ptr - casdata );
	d_stream.total_in=0;

	d_stream.next_out = &gz_ptr[0];
	d_stream.avail_out = 1;
	d_stream.total_out=0;

	d_stream.zalloc = nullptr;
	d_stream.zfree = nullptr;
	d_stream.opaque = nullptr;
	d_stream.data_type=0;

	err = inflateInit( &d_stream );
	if ( err != Z_OK )
	{
		LOG_FORMATS( "inflateInit2 error: %d\n", err );
		goto cleanup;
	}


	total_size=1;
	do
	{
		d_stream.next_out = &gz_ptr[0];
		d_stream.avail_out=1;
		err=inflate( &d_stream, Z_SYNC_FLUSH );
		if (err==Z_OK)
		{
			bsize=gz_ptr[0];
			if (bsize==0)
			{
				d_stream.avail_out=4;
				d_stream.next_out = &gz_ptr[0];
				err=inflate( &d_stream, Z_SYNC_FLUSH );
				bsize=get_leuint32(&gz_ptr[0]);
			}
			total_size=total_size+bsize;
		}
	}
	while (err==Z_OK);

	if ( err != Z_STREAM_END )
	{
		LOG_FORMATS( "inflate error: %d\n", err );
		goto cleanup;
	}

	err = inflateEnd( &d_stream );
	if ( err != Z_OK )
	{
		LOG_FORMATS( "inflateEnd error: %d\n", err );
		goto cleanup;
	}

	return total_size;

cleanup:
	return -1;
}
Esempio n. 19
0
bool fsd_format::load(io_generic *io, UINT32 form_factor, floppy_image *image)
{
	UINT64 size = io_generic_size(io);
	dynamic_buffer img(size);
	io_generic_read(io, &img[0], 0, size);

	UINT64 pos;
	std::string title;
	for(pos=8; pos < size && img[pos] != '\0'; pos++)
		title += char(img[pos]);
	pos++;

	if(pos >= size)
		return false;

	//popmessage("Loading image of '%s'\n", title);

	desc_pc_sector sects[256];
	UINT8 total_tracks = img[pos++];
	UINT8 tnum, hnum, snum, ssize, error;

	hnum = 0;
	LOG_FORMATS("%02d Tracks\n", total_tracks+1);
	LOG_FORMATS("Tr.#  No.S  Sec.# Tr.ID Head# SecID IDsiz REsiz Error\n");
	for(int curr_track=0; curr_track <= total_tracks; curr_track++)
	{
		UINT8 track = img[pos++];
		UINT8 spt = img[pos++];
		LOG_FORMATS("%02X    %02X\n", track, spt);
		if (spt > 0) // formatted
		{
			UINT8 readable = img[pos++];
			for (int i = 0; i < spt; i++)
			{
				tnum = img[pos++];  // logical track
				hnum = img[pos++];  // head number
				snum = img[pos++];  // logical sector
				ssize = img[pos++]; // reported size
				sects[i].track = tnum;
				sects[i].head = hnum;
				sects[i].sector = snum;
				sects[i].size = ssize;
				if (readable == 0xff)
				{
					sects[i].actual_size = 1 << (img[pos++] + 7);
					error = img[pos++];
					sects[i].deleted = (error & 0x20) == 0x20;
					sects[i].bad_crc = (error & 0x0e) == 0x0e;
					sects[i].data = &img[pos];
					pos += sects[i].actual_size;
					LOG_FORMATS("Read        %02X    %02X    %02X    %02X    %02X    %02X   %02X\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, error);
				}
				else
				{
					LOG_FORMATS("Unreadable sector on track %02d sector %02X head %02d", track, i, hnum);
					sects[i].actual_size = 0;
					sects[i].deleted = false;
					sects[i].bad_crc = false;
					sects[i].data = nullptr;
					LOG_FORMATS("Unread      %02X    %02X    %02X    %02X    %02X    %02X   %02X\n", i, sects[i].track, sects[i].head, sects[i].sector, sects[i].size, sects[i].actual_size, 0);
				}
			}
		}
		else // unformatted
		{
			sects[0].track = curr_track;
			sects[0].head = hnum;
			sects[0].sector = 0;
			sects[0].size = 0;
			LOG_FORMATS("Unform      %02X    %02X    %02X    %02X    %02X    %02X   %02X\n", 0, sects[0].track, sects[0].head, sects[0].sector, sects[0].size, sects[0].actual_size, 0);
		}
		build_wd_track_fm(curr_track, hnum, image, 50000, spt, sects, 10, 40, 10);
	}
	return true;
}
Esempio n. 20
0
/* length is length of .tap file! */
static int oric_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
{
	unsigned char header[9];
	int count;

	const UINT8 *data_ptr;
	int i;
	UINT8 data;

	oric.tap_size = length;

	oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
	count = 0;
	data_ptr = bytes;

	while (data_ptr<(bytes+length))
	{
		data = data_ptr[0];
		data_ptr++;

		switch (oric.cassette_state)
		{
			case ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE:
			{
				if (data==ORIC_SYNC_BYTE)
				{
					LOG_FORMATS("found sync byte!\n");
					/* found first sync byte */
					oric.cassette_state = ORIC_CASSETTE_GOT_SYNC_BYTE;
				}
			}
			break;

			case ORIC_CASSETTE_GOT_SYNC_BYTE:
			{
				if (data!=ORIC_SYNC_BYTE)
				{
					/* 0.25 second pause */
					count += oric_seconds_to_samples(0.25);

					LOG_FORMATS("found end of sync bytes!\n");

					/* oric writes approx 512 bytes */
					/* found end of sync bytes */
					for (i=0; i<ORIC_LEADER_LENGTH; i++)
					{
						count+=oric_calculate_byte_size_in_samples(0x016);
					}

					if (data==0x024)
					{
						//LOG_FORMATS("reading header!\n");
						count+=oric_calculate_byte_size_in_samples(0x024);

						oric.cassette_state = ORIC_CASSETTE_READ_HEADER;
						oric.data_count = 0;
						oric.data_length = 9;
					}
				}
			}
			break;

			case ORIC_CASSETTE_READ_HEADER:
			{
				header[oric.data_count] = data;
				count+=oric_calculate_byte_size_in_samples(data);

				oric.data_count++;

				if (oric.data_count==oric.data_length)
				{
					//LOG_FORMATS("finished reading header!\n");
					oric.cassette_state = ORIC_CASSETTE_READ_FILENAME;
				}
			}
			break;

			case ORIC_CASSETTE_READ_FILENAME:
			{
				count+=oric_calculate_byte_size_in_samples(data);

				/* got end of filename? */
				if (data==0)
				{
					UINT16 end, start;
					LOG_FORMATS("got end of filename\n");

					/* 100 1 bits to separate header from data */
                                        for (i=0; i<100; i++)
                                        {
                                            count+=oric_get_bit_size_in_samples(1);
                                        }

					oric.cassette_state = ORIC_CASSETTE_WRITE_DATA;
					oric.data_count = 0;

					end = (((header[4] & 0x0ff)<<8) | (header[5] & 0x0ff));
					start = (((header[6] & 0x0ff)<<8) | (header[7] & 0x0ff));
					LOG(("start (from header): %02x\n",start));
					LOG(("end (from header): %02x\n",end));
                                        oric.data_length = end - start + 1;
				}
			}
			break;

			case ORIC_CASSETTE_WRITE_DATA:
			{
				count+=oric_calculate_byte_size_in_samples(data);
				oric.data_count++;

				if (oric.data_count==oric.data_length)
				{
					LOG_FORMATS("finished writing data!\n");
					oric.cassette_state = ORIC_CASSETTE_SEARCHING_FOR_SYNC_BYTE;
				}
			}
			break;

		}
	}

	return count;
}
Esempio n. 21
0
/*  Will go through blocks and calculate number of samples needed.
If buffer is not nullptr the sample data will also be written. */
static int tzx_cas_do_work( int16_t **buffer )
{
	int current_block = 0;
	int size = 0;

	wave_data = WAVE_LOW;

	int loopcount = 0, loopoffset = 0;

	while (current_block < block_count)
	{
		int pause_time;
		uint32_t data_size;
		int text_size, total_size, i;
		int pilot, pilot_length, sync1, sync2;
		int bit0, bit1, bits_in_last_byte;
		uint8_t *cur_block = blocks[current_block];
		uint8_t block_type = cur_block[0];
		uint16_t tstates = 0;

	/* Uncomment this to include into error.log a list of the types each block */
	LOG_FORMATS("tzx_cas_fill_wave: block %d, block_type %02x\n", current_block, block_type);

		switch (block_type)
		{
		case 0x10:  /* Standard Speed Data Block (.TAP block) */
			pause_time = cur_block[1] + (cur_block[2] << 8);
			data_size = cur_block[3] + (cur_block[4] << 8);
			pilot_length = (cur_block[5] == 0x00) ?  8064 : 3220;
			size += tzx_cas_handle_block(buffer, &cur_block[5], pause_time, data_size, 2168, pilot_length, 667, 735, 855, 1710, 8);
			current_block++;
			break;
		case 0x11:  /* Turbo Loading Data Block */
			pilot = cur_block[1] + (cur_block[2] << 8);
			sync1 = cur_block[3] + (cur_block[4] << 8);
			sync2 = cur_block[5] + (cur_block[6] << 8);
			bit0 = cur_block[7] + (cur_block[8] << 8);
			bit1 = cur_block[9] + (cur_block[10] << 8);
			pilot_length = cur_block[11] + (cur_block[12] << 8);
			bits_in_last_byte = cur_block[13];
			pause_time = cur_block[14] + (cur_block[15] << 8);
			data_size = cur_block[16] + (cur_block[17] << 8) + (cur_block[18] << 16);
			size += tzx_cas_handle_block(buffer, &cur_block[19], pause_time, data_size, pilot, pilot_length, sync1, sync2, bit0, bit1, bits_in_last_byte);
			current_block++;
			break;
		case 0x12:  /* Pure Tone */
			pilot = cur_block[1] + (cur_block[2] << 8);
			pilot_length = cur_block[3] + (cur_block[4] << 8);
			size += tzx_cas_handle_block(buffer, cur_block, 0, 0, pilot, pilot_length, 0, 0, 0, 0, 0);
			current_block++;
			break;
		case 0x13:  /* Sequence of Pulses of Different Lengths */
			for (data_size = 0; data_size < cur_block[1]; data_size++)
			{
				pilot = cur_block[2 + 2 * data_size] + (cur_block[3 + 2 * data_size] << 8);
				size += tzx_cas_handle_block(buffer, cur_block, 0, 0, pilot, 1, 0, 0, 0, 0, 0);
			}
			current_block++;
			break;
		case 0x14:  /* Pure Data Block */
			bit0 = cur_block[1] + (cur_block[2] << 8);
			bit1 = cur_block[3] + (cur_block[4] << 8);
			bits_in_last_byte = cur_block[5];
			pause_time = cur_block[6] + (cur_block[7] << 8);
			data_size = cur_block[8] + (cur_block[9] << 8) + (cur_block[10] << 16);
			size += tzx_cas_handle_block(buffer, &cur_block[11], pause_time, data_size, 0, 0, 0, 0, bit0, bit1, bits_in_last_byte);
			current_block++;
			break;
		case 0x20:  /* Pause (Silence) or 'Stop the Tape' Command */
			pause_time = cur_block[1] + (cur_block[2] << 8);
			if (pause_time == 0)
			{
				/* pause = 0 is used to let an emulator automagically stop the tape
				   in MESS we do not do that, so we insert a 5 second pause. */
				pause_time = 5000;
			}
			size += tzx_cas_handle_block(buffer, cur_block, pause_time, 0, 0, 0, 0, 0, 0, 0, 0);
			current_block++;
			break;
		case 0x16:  /* C64 ROM Type Data Block */       // Deprecated in TZX 1.20
		case 0x17:  /* C64 Turbo Tape Data Block */     // Deprecated in TZX 1.20
		case 0x34:  /* Emulation Info */                // Deprecated in TZX 1.20
		case 0x40:  /* Snapshot Block */                // Deprecated in TZX 1.20
			LOG_FORMATS("Deprecated block type (%02x) encountered.\n", block_type);
			LOG_FORMATS("Please look for an updated .tzx file.\n");
			current_block++;
			break;
		case 0x30:  /* Text Description */
			ascii_block_common_log("Text Description Block", block_type);
			for (data_size = 0; data_size < cur_block[1]; data_size++)
				LOG_FORMATS("%c", cur_block[2 + data_size]);
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x31:  /* Message Block */
			ascii_block_common_log("Message Block", block_type);
			LOG_FORMATS("Expected duration of the message display: %02x\n", cur_block[1]);
			LOG_FORMATS("Message: \n");
			for (data_size = 0; data_size < cur_block[2]; data_size++)
			{
				LOG_FORMATS("%c", cur_block[3 + data_size]);
				if (cur_block[3 + data_size] == 0x0d)
					LOG_FORMATS("\n");
			}
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x32:  /* Archive Info */
			ascii_block_common_log("Archive Info Block", block_type);
			total_size = cur_block[1] + (cur_block[2] << 8);
			text_size = 0;
			for (data_size = 0; data_size < cur_block[3]; data_size++)  // data_size = number of text blocks, in this case
			{
				if (cur_block[4 + text_size] < 0x09) {
					LOG_FORMATS("%s: \n", archive_ident[cur_block[4 + text_size]]);
				}
				else {
					LOG_FORMATS("Comment(s): \n");
				}

				for (i = 0; i < cur_block[4 + text_size + 1]; i++)
				{
					LOG_FORMATS("%c", cur_block[4 + text_size + 2 + i]);
				}
				text_size += 2 + i;
			}
			LOG_FORMATS("\n");
			if (text_size != total_size)
				LOG_FORMATS("Malformed Archive Info Block (Text length different from the declared one).\n Please verify your tape image.\n");
			current_block++;
			break;
		case 0x33:  /* Hardware Type */
			ascii_block_common_log("Hardware Type Block", block_type);
			for (data_size = 0; data_size < cur_block[1]; data_size++)  // data_size = number of hardware blocks, in this case
			{
				LOG_FORMATS("Hardware Type %02x - Hardware ID %02x - ", cur_block[2 + data_size * 3], cur_block[2 + data_size * 3 + 1]);
				LOG_FORMATS("%s \n ", hw_info[cur_block[2 + data_size * 3 + 2]]);
			}
			current_block++;
			break;
		case 0x35:  /* Custom Info Block */
			ascii_block_common_log("Custom Info Block", block_type);
			for (data_size = 0; data_size < 10; data_size++)
			{
				LOG_FORMATS("%c", cur_block[1 + data_size]);
			}
			LOG_FORMATS(":\n");
			text_size = cur_block[11] + (cur_block[12] << 8) + (cur_block[13] << 16) + (cur_block[14] << 24);
			for (data_size = 0; data_size < text_size; data_size++)
				LOG_FORMATS("%c", cur_block[15 + data_size]);
			LOG_FORMATS("\n");
			current_block++;
			break;
		case 0x5A:  /* "Glue" Block */
			LOG_FORMATS("Glue Block (type %02x) encountered.\n", block_type);
			LOG_FORMATS("Please use a .tzx handling utility to split the merged tape files.\n");
			current_block++;
			break;
		case 0x24:  /* Loop Start */
			loopcount = cur_block[1] + (cur_block[2] << 8);
			current_block++;
			loopoffset = current_block;

			LOG_FORMATS("loop start %d %d\n",  loopcount, current_block);
			break;
		case 0x25:  /* Loop End */
			if (loopcount>0)
			{
				current_block = loopoffset;
				loopcount--;
				LOG_FORMATS("do loop\n");
			}
			else
			{
				current_block++;
			}
			break;

		case 0x21:  /* Group Start */
		case 0x22:  /* Group End */
		case 0x23:  /* Jump To Block */
		case 0x26:  /* Call Sequence */
		case 0x27:  /* Return From Sequence */
		case 0x28:  /* Select Block */
		case 0x2A:  /* Stop Tape if in 48K Mode */
		case 0x2B:  /* Set signal level */
		default:
			LOG_FORMATS("Unsupported block type (%02x) encountered.\n", block_type);
			current_block++;
			break;

		case 0x15:  /* Direct Recording */ // used on 'bombscar' in the cpc_cass list
			// having this missing is fatal
			tstates = cur_block[1] + (cur_block[2] << 8);
			pause_time= cur_block[3] + (cur_block[4] << 8);
			bits_in_last_byte = cur_block[5];
			data_size = cur_block[6] + (cur_block[7] << 8) + (cur_block[8] << 16);
			size += tzx_handle_direct(buffer, &cur_block[9], pause_time, data_size, tstates, bits_in_last_byte);
			current_block++;
			break;

		case 0x18:  /* CSW Recording */
			// having this missing is fatal
			printf("Unsupported block type (0x15 - CSW Recording) encountered.\n");
			current_block++;
			break;

		case 0x19:  /* Generalized Data Block */
			{
				// having this missing is fatal
				// used crudely by batmanc in spectrum_cass list (which is just a redundant encoding of batmane ?)
				data_size = cur_block[1] + (cur_block[2] << 8) + (cur_block[3] << 16) + (cur_block[4] << 24);
				pause_time= cur_block[5] + (cur_block[6] << 8);

				uint32_t totp = cur_block[7] + (cur_block[8] << 8) + (cur_block[9] << 16) + (cur_block[10] << 24);
				int npp = cur_block[11];
				int asp = cur_block[12];
				if (asp == 0 && totp > 0) asp = 256;

				uint32_t totd = cur_block[13] + (cur_block[14] << 8) + (cur_block[15] << 16) + (cur_block[16] << 24);
				int npd = cur_block[17];
				int asd = cur_block[18];
				if (asd == 0 && totd > 0) asd = 256;

				size += tzx_handle_generalized(buffer, &cur_block[19], pause_time, data_size, totp, npp, asp, totd, npd, asd);

				current_block++;
			}
			break;

		}
	}
	return size;
}
Esempio n. 22
0
static void ascii_block_common_log( const char *block_type_string, uint8_t block_type )
{
	LOG_FORMATS("%s (type %02x) encountered:\n", block_type_string, block_type);
}
Esempio n. 23
0
static int cbm_tap_do_work( INT16 **buffer, int length, const UINT8 *data )
{
	int i, j = 0;
	int size = 0;

	int version = data[0x0c];
	int system = data[0x0d];
	int video_standard = data[0x0e];
	int tap_frequency = 0;

	int byte_samples = 0;
	UINT8 over_pulse_bytes[3] = {0 , 0, 0 };
	int over_pulse_length = 0;
	/* These waveamp_* values are currently stored but not used.
      Further investigations are needed to find real pulse amplitude
      in Commodore tapes. Implementation here would follow */
	/* int waveamp_high, waveamp_low; */

	/* Log .TAP info but only once */
	if (!(buffer == NULL))
	{
		LOG_FORMATS("TAP version    : %d\n", version);
		LOG_FORMATS("Machine type   : %d\n", system);
		LOG_FORMATS("Video standard : %d\n", video_standard);
		LOG_FORMATS("Tape frequency : %d\n", (tap_frequency) << 3);
	}


	/* is this a supported version? */
	if ((version < 0) || (version > 2))
	{
		LOG_FORMATS("Unsupported .tap version: %d \n", version);
		return -1;
	}

	/* is the .tap file corrupted? */
	if ((data == NULL) || (length <= CBM_HEADER_SIZE))
		return -1;


	/* read the frequency from the .tap header */
    switch (system)
    {
        case VIC20:
            tap_frequency = (video_standard == NTSC) ? VIC20_NTSC : VIC20_PAL;
            break;

        case C16:
            tap_frequency = (video_standard == NTSC) ? C16_NTSC : C16_PAL;
            break;

        case C64:
        default:
            tap_frequency = (video_standard == NTSC) ? C64_NTSC : C64_PAL;
            break;
    }


	for (i = CBM_HEADER_SIZE; i < length; i++)
	{
		UINT8 byte = data[i];

		/* .TAP v0 */
		/* Here is simple:
          if byte is != 0 -> length = byte
          otherwise -> length =  0x100 (i.e. 0xff + 1) */
		if (!version)
		{
			if (byte != 0x00)
			{
				byte_samples = tap_data_to_samplecount(byte, tap_frequency);
				/* waveamp_high = WAVE_HIGH; */
			}
			else
			{
				byte_samples = tap_data_to_samplecount(PAUSE, tap_frequency);	// tap2wav value
//              byte_samples = tap_data_to_samplecount(0x100, tap_frequency);   // vice value
				/* waveamp_high = WAVE_PAUSE; */
			}
			/* waveamp_low = WAVE_LOW; */
		}

		/* .TAP v1 & v2 */
		/* Here is a bit more complicate:
          if byte is != 0 -> length = byte
          otherwise -> the length of the pulse is stored as a 24bit value in the 3 bytes after the 0.
          See below for comments on the implementation of this mechanism */
		if (version)
		{
			if ((byte != 0x00) && !j)
			{
				byte_samples = tap_data_to_samplecount(byte, tap_frequency);
				/* waveamp_high = WAVE_HIGH; */
			}
			else
			{
				/* If we have a long pulse close to the end of the .TAP, check that bytes still
                  to be read are enough to complete it. */
				if (length - i + j >= 4)
				{
					/* Here we read the 3 following bytes, using an index j
                      j = 0 -> The 0x00 byte: we simply skip everything and go on
                      j = 1,2 -> The 1st and 2nd bytes after 0x00: we store them and go on
                      j = 3 -> The final byte of the pulse length: we store it,
                      and then we pass to finally output the wave */
					if (j > 0)
					{
						over_pulse_bytes[j-1] = byte;
						j += 1;

						if (j >= 4)
						{
							over_pulse_length = ((over_pulse_bytes[2] << 16) | (over_pulse_bytes[1] << 8) | over_pulse_bytes[0]) >> 3;
							byte_samples = tap_data_to_samplecount(over_pulse_length, tap_frequency);
							/* waveamp_high = WAVE_PAUSE; */
							j = 0;
						}
					}
					else
					{
						j += 1;
						LOG_FORMATS("Found a 00 byte close to the end of the .tap file.\n");
						LOG_FORMATS("This is not allowed by the format specs. \n");
						LOG_FORMATS("Check if your .tap file got corrupted when you created it!\n");
					}
				}
				else j = 1;
Esempio n. 24
0
static int csw_cas_fill_wave( INT16 *buffer, int length, UINT8 *bytes ) {
UINT32 SampleRate;
UINT32 NumberOfPulses;
UINT8  CompressionType;
UINT8  Flags;
UINT8  HeaderExtensionLength;
INT8   Bit;

UINT8 *gz_ptr = NULL;
int			total_size;
z_stream	d_stream;
int 		err;
UINT8		*in_ptr;
int 		bsize=0;
int		i;


	LOG_FORMATS("Length %d\n",length);

	SampleRate=get_leuint32(bytes+0x19);
	LOG_FORMATS("Sample rate %d\n",SampleRate);

	NumberOfPulses=get_leuint32(bytes+0x1d);
	LOG_FORMATS("Number Of Pulses %d\n",NumberOfPulses);

	CompressionType=bytes[0x21];
	Flags=bytes[0x22];
	HeaderExtensionLength=bytes[0x23];

	if ((Flags&0)==0)
	{
		Bit=-100;
	} else {
		Bit=100;
	}

	LOG_FORMATS("CompressionType %d   Flast %d   HeaderExtensionLength %d\n",CompressionType,Flags,HeaderExtensionLength);


	//from here on down for now I am assuming it is compressed csw file.
	in_ptr = (UINT8*) bytes+0x34+HeaderExtensionLength;

	gz_ptr = (UINT8*)malloc( 8 );


	d_stream.next_in = (unsigned char *)in_ptr;
	d_stream.avail_in = mycaslen - ( in_ptr - bytes );
	d_stream.total_in=0;

	d_stream.next_out = gz_ptr;
	d_stream.avail_out = 1;
	d_stream.total_out=0;

	d_stream.zalloc = 0;
	d_stream.zfree = 0;
	d_stream.opaque = 0;
	d_stream.data_type=0;

	err = inflateInit( &d_stream );
	if ( err != Z_OK ) {
		LOG_FORMATS( "inflateInit2 error: %d\n", err );
		goto cleanup;
	}

	total_size=0;

	do
	{
		d_stream.next_out = gz_ptr;
		d_stream.avail_out=1;
		err=inflate( &d_stream, Z_SYNC_FLUSH );
		if (err==Z_OK) {
			bsize=gz_ptr[0];
			if (bsize==0) {
				d_stream.avail_out=4;
				d_stream.next_out = gz_ptr;
				err=inflate( &d_stream, Z_SYNC_FLUSH );
				bsize=get_leuint32(gz_ptr);
			}
			for (i=0;i<bsize;i++)
			{
				buffer[total_size++]=Bit;
			}
			Bit=-Bit;
		}
	}
	while (err==Z_OK);

	if ( err != Z_STREAM_END ) {
		LOG_FORMATS( "inflate error: %d\n", err );
		goto cleanup;
	}

	err = inflateEnd( &d_stream );
	if ( err != Z_OK ) {
		LOG_FORMATS( "inflateEnd error: %d\n", err );
		goto cleanup;
	}






	if ( gz_ptr ) {
		free( gz_ptr );
		gz_ptr = NULL;
	}




	return length;



	cleanup:
		if ( gz_ptr ) {
			free( gz_ptr );
			gz_ptr = NULL;
		}
	return -1;
}