diff options
author | 2012-04-16 14:20:10 +0000 | |
---|---|---|
committer | 2012-04-16 14:20:10 +0000 | |
commit | 39746064c6b33907876194a9f7a0f19914b113d0 (patch) | |
tree | 3684425776ea13373cafd87f04cef47a388a54d6 /src | |
parent | 3f82bc4d81ff8bf80b7f8cda0ea8a664e5aa84c2 (diff) |
Sync with MESS (no whatsnew)
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/imagedev/cassette.c | 37 | ||||
-rw-r--r-- | src/emu/imagedev/cassette.h | 7 | ||||
-rw-r--r-- | src/lib/formats/adam_cas.c | 210 | ||||
-rw-r--r-- | src/lib/formats/adam_cas.h | 17 | ||||
-rw-r--r-- | src/lib/formats/cassimg.c | 2 | ||||
-rw-r--r-- | src/lib/lib.mak | 1 |
6 files changed, 269 insertions, 5 deletions
diff --git a/src/emu/imagedev/cassette.c b/src/emu/imagedev/cassette.c index 8d56985c5f3..49db7966287 100644 --- a/src/emu/imagedev/cassette.c +++ b/src/emu/imagedev/cassette.c @@ -104,17 +104,17 @@ void cassette_image_device::update() if (is_motor_on()) { - double new_position = m_position + (cur_time - m_position_time); + double new_position = m_position + (cur_time - m_position_time)*m_speed*m_direction; switch(m_state & CASSETTE_MASK_UISTATE) { case CASSETTE_RECORD: - cassette_put_sample(m_cassette, 0, m_position, new_position - m_position, m_value); + cassette_put_sample(m_cassette, m_channel, m_position, new_position - m_position, m_value); break; case CASSETTE_PLAY: if ( m_cassette ) { - cassette_get_sample(m_cassette, 0, new_position, 0.0, &m_value); + cassette_get_sample(m_cassette, m_channel, new_position, 0.0, &m_value); /* See if reached end of tape */ double length = get_length(); if (new_position > length) @@ -122,6 +122,11 @@ void cassette_image_device::update() m_state = (cassette_state)(( m_state & ~CASSETTE_MASK_UISTATE ) | CASSETTE_STOPPED); new_position = length; } + else if (new_position < 0) + { + m_state = (cassette_state)(( m_state & ~CASSETTE_MASK_UISTATE ) | CASSETTE_STOPPED); + new_position = 0; + } } break; } @@ -182,7 +187,7 @@ double cassette_image_device::get_position() double position = m_position; if (is_motor_on()) - position += device().machine().time().as_double() - m_position_time; + position += (device().machine().time().as_double() - m_position_time)*m_speed*m_direction; return position; } @@ -196,6 +201,25 @@ double cassette_image_device::get_length() return ((double) info.sample_count) / info.sample_frequency; } +void cassette_image_device::set_channel(int channel) +{ + m_channel = channel; +} + +void cassette_image_device::set_speed(double speed) +{ + m_speed = speed; +} + +void cassette_image_device::go_forward() +{ + m_direction = 1; +} + +void cassette_image_device::go_reverse() +{ + m_direction = -1; +} void cassette_image_device::seek(double time, int origin) @@ -300,6 +324,11 @@ bool cassette_image_device::call_load() /* reset the position */ m_position = 0.0; m_position_time = device().machine().time().as_double(); + + /* default channel to 0, speed multiplier to 1 */ + m_channel = 0; + m_speed = 1; + m_direction = 1; return IMAGE_INIT_PASS; diff --git a/src/emu/imagedev/cassette.h b/src/emu/imagedev/cassette.h index cec381c2e0f..d43681d9ffa 100644 --- a/src/emu/imagedev/cassette.h +++ b/src/emu/imagedev/cassette.h @@ -92,6 +92,10 @@ public: cassette_image *get_image() { return m_cassette; } double get_position(); double get_length(); + void set_speed(double speed); + void set_channel(int channel); + void go_forward(); + void go_reverse(); void seek(double time, int origin); protected: @@ -107,6 +111,9 @@ private: double m_position; double m_position_time; INT32 m_value; + int m_channel; + double m_speed; // speed multiplier for tape speeds other than standard 1.875ips (used in adam driver) + int m_direction; // direction select char m_extension_list[256]; }; diff --git a/src/lib/formats/adam_cas.c b/src/lib/formats/adam_cas.c new file mode 100644 index 00000000000..376c95652be --- /dev/null +++ b/src/lib/formats/adam_cas.c @@ -0,0 +1,210 @@ + +#include "cassimg.h" +#include "adam_cas.h" + +// This code will reproduce the timing of an adam tape played back on a standard tape deck with a 1 7/8ips speed. +#define CASS_AMP 0x1fffffff +#define SPEED_MULTIPLIER 20.0/1.875 +#define COL_ADAM_PERIOD 0.00007*SPEED_MULTIPLIER +#define COL_ADAM_PERIOD1 0.000031*SPEED_MULTIPLIER +#define COL_ADAM_PERIOD2 0.000039*SPEED_MULTIPLIER +#define TYPE_HE 0 +#define TYPE_GW 1 + +/*************************************************************** +Coleco Adam Digital Data Pack format: +The packs are the same shape as a standard audio cassette, but with different alignment and capstan holes +The tape only has one side and has two widely separated mono data tracks (second track readable on an audio +cassette deck by flipping the tape over and reversing the recorded signal). + +Header format: +2 byte header id: 0x48 0x45 (central directory HE type) or 0x47 0x57 (GW type) +2 byte block number +2 byte NOT block number +1 byte number of blocks (0x80) +1 byte sum of the above (checksum) + + +track format: +leading zeros: ~2753 + +block format: +sync byte 0x16 +header +pad zero bytes ~21 +sync byte 0x16 +data(1k) +pad zero bytes ~21 +sync byte 0x16 +2 byte checksum-16 +pad zero bytes ~2 +sync bytes 0xaa ~922 +pad zero bytes ~2 + +Data is phase encoded, with 70us bit cells with a transition at 31us for a 1 and no transition for a 0 + +****************************************************************/ + + +static casserr_t coladam_ddp_identify ( cassette_image *cass, struct CassetteOptions *opts ) +{ + opts -> bits_per_sample = 16; + opts -> channels = 2; + opts -> sample_frequency = 44100; + return CASSETTE_ERROR_SUCCESS; +} + + +// Store byte of data +casserr_t coladam_put_byte(cassette_image *cass, int channel, double *time_index, int byte, int *prev_sign) +{ + casserr_t err; + for (int i = 0; i < 8; i++) + { + if(byte & 0x80) + { + err = cassette_put_sample( cass, channel, *time_index, COL_ADAM_PERIOD1, -CASS_AMP*(*prev_sign) ); + (*time_index) += COL_ADAM_PERIOD1; + err = cassette_put_sample( cass, channel, *time_index, COL_ADAM_PERIOD2, CASS_AMP*(*prev_sign) ); + (*time_index) += COL_ADAM_PERIOD2; + } + else + { + err = cassette_put_sample( cass, channel, *time_index, COL_ADAM_PERIOD, -CASS_AMP*(*prev_sign) ); + (*prev_sign) *=-1; + (*time_index) += COL_ADAM_PERIOD; + } + byte <<= 1; + } + return err; +} + +casserr_t coladam_put_block(cassette_image *cass, int channel, double *time_index, int *prev_sign, int block_index, UINT8 *buffer, int layout_type) +{ + int i, checksum_16=0; + UINT8 header[] = { 0x16, 0x48, 0x45, 0x00, block_index, 0xff, (0xff - block_index), 0x00, 0x80, 0xf4 }; + casserr_t err; + if (layout_type == TYPE_GW) + { + header[1] = 0x47; + header[2] = 0x57; + header[9] = 0xe3; + } + + for (i = 0; i < 10; i++) // header + { + err = coladam_put_byte(cass, channel, time_index, header[i], prev_sign); + } + for (i = 0; i < 21; i++) // leading zero bytes + { + err = coladam_put_byte(cass, channel, time_index, 0x00, prev_sign); + } + err = coladam_put_byte(cass, channel, time_index, 0x16, prev_sign); // data start + for ( i = 0; i < 0x400; i++ ) + { + err = coladam_put_byte(cass, channel, time_index, buffer[i], prev_sign); + checksum_16 += buffer[i]; + } + for (i = 0; i < 21; i++) // trailing padding zeros + { + err = coladam_put_byte(cass, channel, time_index, 0x00, prev_sign); + } + err = coladam_put_byte(cass, channel, time_index, 0x16, prev_sign); + err = coladam_put_byte(cass, channel, time_index, (checksum_16 & 0xff00) >> 8, prev_sign); // write checksum + err = coladam_put_byte(cass, channel, time_index, (checksum_16 & 0xff), prev_sign); + for (i = 0; i < 922; i++) // sync bytes + { + err = coladam_put_byte(cass, channel, time_index, 0xaa, prev_sign); + } + err = coladam_put_byte(cass, channel, time_index, 0x00, prev_sign); + err = coladam_put_byte(cass, channel, time_index, 0x00, prev_sign); + return err; +} + + +static casserr_t coladam_ddp_load( cassette_image *cass ) +{ + double time = 0.; + int i, block, prev_sign=-1; + UINT8 buffer[0x400]; + casserr_t err; + + // It would appear that data packs that originally had the type GW data layout and headers work fine when converted to type + // HE. Thus we set all tapes to type HE. + + int layout_type = TYPE_HE; + + // Track 0 + for ( i = 0; i < 2753; i++ ) // leading zero bytes + { + err = coladam_put_byte(cass, 0, &time, 0x00, &prev_sign); + } + + for (block = 0; block < 128; block++) + { + cassette_image_read( cass, buffer, 0x20000+0x400*block, 0x400 ); + err = coladam_put_block(cass, 0, &time, &prev_sign, block, buffer, layout_type); + } + for (block = 128; block < 131; block++) + { + cassette_image_read( cass, buffer, 0x3f400+0x400*(block-128), 0x400 ); + err = coladam_put_block(cass, 0, &time, &prev_sign, block, buffer, layout_type); + } + + // Track 1 + time = 0.; + for ( i = 0; i < 2753; i++ ) // leading zero bytes + { + err = coladam_put_byte(cass, 1, &time, 0x00, &prev_sign); + } + if (layout_type == TYPE_HE) + { + for (block = 0; block < 64; block++) + { + cassette_image_read( cass, buffer, 0x10000+0x400*block, 0x400 ); + err = coladam_put_block(cass, 1, &time, &prev_sign, block, buffer, layout_type); + } + for (block = 64; block < 128; block++) + { + cassette_image_read( cass, buffer, 0x00000+0x400*(block-64), 0x400 ); + err = coladam_put_block(cass, 1, &time, &prev_sign, block, buffer, layout_type); + } + for (block = 128; block < 131; block++) + { + cassette_image_read( cass, buffer, 0x0f400+0x400*(block-128), 0x400 ); + err = coladam_put_block(cass, 1, &time, &prev_sign, block, buffer, layout_type); + } + } + else + { + time = 0; + for ( i = 0; i < 2753; i++ ) // leading zero bytes + { + err = coladam_put_byte(cass, 1, &time, 0x00, &prev_sign); + } + for (block = 0; block < 128; block++) + { + cassette_image_read( cass, buffer, 0x400*block, 0x400 ); + err = coladam_put_block(cass, 1, &time, &prev_sign, block, buffer, layout_type); + } + for (block = 128; block < 131; block++) + { + cassette_image_read( cass, buffer, 0x1f400+0x400*(block-128), 0x400 ); + err = coladam_put_block(cass, 1, &time, &prev_sign, block, buffer, layout_type); + } + } + + if (err) + return err; + + return CASSETTE_ERROR_SUCCESS; +} + + + +static const struct CassetteFormat coladam_ddp = +{ "ddp", coladam_ddp_identify, coladam_ddp_load, NULL /* no save */ }; + +CASSETTE_FORMATLIST_START(coleco_adam_cassette_formats) + CASSETTE_FORMAT(coladam_ddp) +CASSETTE_FORMATLIST_END diff --git a/src/lib/formats/adam_cas.h b/src/lib/formats/adam_cas.h new file mode 100644 index 00000000000..a1e794c2981 --- /dev/null +++ b/src/lib/formats/adam_cas.h @@ -0,0 +1,17 @@ +/********************************************************************* + + adam_cas.h + + Format code for Coleco Adam .ddp casette files. + +*********************************************************************/ + +#ifndef __ADAM_CAS_H +#define __ADAM_CAS_H + +#include "cassimg.h" + +CASSETTE_FORMATLIST_EXTERN(coleco_adam_cassette_formats); + +#endif + diff --git a/src/lib/formats/cassimg.c b/src/lib/formats/cassimg.c index f2c69a7c583..809a60ce26a 100644 --- a/src/lib/formats/cassimg.c +++ b/src/lib/formats/cassimg.c @@ -479,7 +479,7 @@ casserr_t cassette_get_samples(cassette_image *cassette, int channel, /* and write out the result */ dest_ptr = (UINT8*)samples; - dest_ptr += waveform_bytes_per_sample(waveform_flags) * sample_index; + dest_ptr += waveform_bytes_per_sample(waveform_flags) * sample_index * cassette->channels; switch(waveform_bytes_per_sample(waveform_flags)) { case 1: diff --git a/src/lib/lib.mak b/src/lib/lib.mak index 8337e29eea6..3ba42bf4ffb 100644 --- a/src/lib/lib.mak +++ b/src/lib/lib.mak @@ -94,6 +94,7 @@ FORMATSOBJS = \ $(LIBOBJ)/formats/basicdsk.o \ $(LIBOBJ)/formats/a26_cas.o \ $(LIBOBJ)/formats/ace_tap.o \ + $(LIBOBJ)/formats/adam_cas.o \ $(LIBOBJ)/formats/ami_dsk.o \ $(LIBOBJ)/formats/ap2_dsk.o \ $(LIBOBJ)/formats/apf_apt.o \ |