summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2012-04-16 14:20:10 +0000
committer Miodrag Milanovic <mmicko@gmail.com>2012-04-16 14:20:10 +0000
commit39746064c6b33907876194a9f7a0f19914b113d0 (patch)
tree3684425776ea13373cafd87f04cef47a388a54d6 /src
parent3f82bc4d81ff8bf80b7f8cda0ea8a664e5aa84c2 (diff)
Sync with MESS (no whatsnew)
Diffstat (limited to 'src')
-rw-r--r--src/emu/imagedev/cassette.c37
-rw-r--r--src/emu/imagedev/cassette.h7
-rw-r--r--src/lib/formats/adam_cas.c210
-rw-r--r--src/lib/formats/adam_cas.h17
-rw-r--r--src/lib/formats/cassimg.c2
-rw-r--r--src/lib/lib.mak1
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 \