(MESS) spc1000 : added TAP cassette format [Robbbert]

This commit is contained in:
Robbbert 2014-02-16 15:15:05 +00:00
parent 7a78ea66d2
commit 6a57b6378f
22 changed files with 168 additions and 43 deletions

2
.gitattributes vendored
View File

@ -2932,6 +2932,8 @@ src/lib/formats/sorc_dsk.c svneol=native#text/plain
src/lib/formats/sorc_dsk.h svneol=native#text/plain
src/lib/formats/sord_cas.c svneol=native#text/plain
src/lib/formats/sord_cas.h svneol=native#text/plain
src/lib/formats/spc1000_cas.c svneol=native#text/plain
src/lib/formats/spc1000_cas.h svneol=native#text/plain
src/lib/formats/st_dsk.c svneol=native#text/plain
src/lib/formats/st_dsk.h svneol=native#text/plain
src/lib/formats/svi_cas.c svneol=native#text/plain

View File

@ -2,7 +2,7 @@
ace_tap.h
Format code for Jupiter Ace casette files
Format code for Jupiter Ace cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
adam_cas.h
Format code for Coleco Adam .ddp casette files.
Format code for Coleco Adam .ddp cassette files.
*********************************************************************/

View File

@ -1030,7 +1030,7 @@ done:
/*********************************************************************
cassette_dump
A debugging call to dump a casette image to a disk based wave file
A debugging call to dump a cassette image to a disk based wave file
*********************************************************************/
void cassette_dump(cassette_image *image, const char *filename)

View File

@ -2,7 +2,7 @@
cgen_cas.h
Format code for EACA Colour Genie .cas casette files.
Format code for EACA Colour Genie .cas cassette files.
*********************************************************************/

View File

@ -2,7 +2,7 @@
fmsx_cas.h
Format code for MSX casette files
Format code for MSX cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
kim1_cas.h
Format code for KIM-1 casette files.
Format code for KIM-1 cassette files.
*********************************************************************/

View File

@ -2,7 +2,7 @@
lviv_lvt.h
Format code for Lviv casette files
Format code for Lviv cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
mz_cas.h
Format code for MZ700 casette files
Format code for MZ700 cassette files
*********************************************************************/

View File

@ -4,7 +4,7 @@
phc25_cas.h
Format code for Sanyo PHC25 casette images (phc format)
Format code for Sanyo PHC25 cassette images (phc format)
*********************************************************************/

View File

@ -4,7 +4,7 @@
pmd_cas.h
Format code for PMD-85 casette files
Format code for PMD-85 cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
primoptp.h
Format code for Primo casette files
Format code for Primo cassette files
*********************************************************************/

View File

@ -0,0 +1,113 @@
// license:BSD-3-Clause
// copyright-holders:Robbbert
/********************************************************************
Support for Samsung SPC-1000 cassette images
********************************************************************/
#include "spc1000_cas.h"
#define WAVEENTRY_LOW -32768
#define WAVEENTRY_HIGH 32767
#define SPC1000_WAV_FREQUENCY 17000
// image size
static int spc1000_image_size;
static int spc1000_put_samples(INT16 *buffer, int sample_pos, int count, int level)
{
if (buffer)
{
for (int i=0; i<count; i++)
buffer[sample_pos + i] = level;
}
return count;
}
static int spc1000_output_bit(INT16 *buffer, int sample_pos, bool bit)
{
int samples = 0;
if (bit)
{
samples += spc1000_put_samples(buffer, sample_pos + samples, 9, WAVEENTRY_LOW);
samples += spc1000_put_samples(buffer, sample_pos + samples, 9, WAVEENTRY_HIGH);
}
else
{
samples += spc1000_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_LOW);
samples += spc1000_put_samples(buffer, sample_pos + samples, 4, WAVEENTRY_HIGH);
}
return samples;
}
static int spc1000_handle_cassette(INT16 *buffer, const UINT8 *bytes)
{
UINT32 sample_count = 0;
UINT32 i;
/* data */
for (i=0; i<spc1000_image_size; i++)
sample_count += spc1000_output_bit(buffer, sample_count, bytes[i]&1);
return sample_count;
}
/*******************************************************************
Generate samples for the tape image
********************************************************************/
static int spc1000_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes)
{
return spc1000_handle_cassette(buffer, bytes);
}
/*******************************************************************
Calculate the number of samples needed for this tape image
********************************************************************/
static int spc1000_cassette_calculate_size_in_samples(const UINT8 *bytes, int length)
{
spc1000_image_size = length;
return spc1000_handle_cassette(NULL, bytes);
}
static const struct CassetteLegacyWaveFiller spc1000_legacy_fill_wave =
{
spc1000_cassette_fill_wave, /* fill_wave */
-1, /* chunk_size */
0, /* chunk_samples */
spc1000_cassette_calculate_size_in_samples, /* chunk_sample_calc */
SPC1000_WAV_FREQUENCY, /* sample_frequency */
0, /* header_samples */
0 /* trailer_samples */
};
static casserr_t spc1000_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts)
{
return cassette_legacy_identify(cassette, opts, &spc1000_legacy_fill_wave);
}
static casserr_t spc1000_cassette_load(cassette_image *cassette)
{
return cassette_legacy_construct(cassette, &spc1000_legacy_fill_wave);
}
static const struct CassetteFormat spc1000_cassette_image_format =
{
"tap",
spc1000_cassette_identify,
spc1000_cassette_load,
NULL
};
CASSETTE_FORMATLIST_START(spc1000_cassette_formats)
CASSETTE_FORMAT(spc1000_cassette_image_format)
CASSETTE_FORMATLIST_END

View File

@ -0,0 +1,15 @@
// license:BSD-3-Clause
// copyright-holders:Robbbert
/*********************************************************************
spc1000_cas.h
Format code for Samsung SPC-1000 cassette images
*********************************************************************/
#include "cassimg.h"
CASSETTE_FORMATLIST_EXTERN(spc1000_cassette_formats);

View File

@ -2,7 +2,7 @@
svi_cas.h
Format code for SVI casette files
Format code for SVI cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
trs_cas.h
Format code for TRS80 (level 2) casette files.
Format code for TRS80 (level 2) cassette files.
*********************************************************************/

View File

@ -4,7 +4,7 @@
tvc_cas.h
Format code for Videoton TVC casette files
Format code for Videoton TVC cassette files
*********************************************************************/

View File

@ -2,7 +2,7 @@
vt_cas.h
Format code for VTech casette files
Format code for VTech cassette files
*********************************************************************/

View File

@ -4,7 +4,7 @@
x07_cas.h
Format code for Canon X-07 casette images
Format code for Canon X-07 cassette images
*********************************************************************/

View File

@ -2,7 +2,7 @@
zx81_p.h
Format code for ZX-81 casette files
Format code for ZX-81 cassette files
*********************************************************************/

View File

@ -180,6 +180,7 @@ FORMATSOBJS = \
$(LIBOBJ)/formats/smx_dsk.o \
$(LIBOBJ)/formats/sorc_dsk.o \
$(LIBOBJ)/formats/sord_cas.o \
$(LIBOBJ)/formats/spc1000_cas.o \
$(LIBOBJ)/formats/st_dsk.o \
$(LIBOBJ)/formats/svi_cas.o \
$(LIBOBJ)/formats/svi_dsk.o \

View File

@ -14,6 +14,7 @@
#include "sound/wave.h"
#include "imagedev/cassette.h"
#include "machine/ram.h"
#include "formats/spc1000_cas.h"
class spc1000_state : public driver_device
@ -21,6 +22,7 @@ class spc1000_state : public driver_device
public:
spc1000_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_p_videoram(*this, "videoram")
, m_vdg(*this, "mc6847")
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
@ -41,13 +43,14 @@ public:
static UINT8 get_char_rom(running_machine &machine, UINT8 ch, int line)
{
spc1000_state *state = machine.driver_data<spc1000_state>();
return state->m_video_ram[0x1000+(ch&0x7F)*16+line];
return state->m_p_videoram[0x1000+(ch&0x7F)*16+line];
}
required_shared_ptr<const UINT8> m_p_videoram;
private:
UINT8 m_IPLK;
UINT8 m_GMODE;
UINT8 m_video_ram[0x2000];
UINT16 m_page;
virtual void machine_reset();
required_device<mc6847_base_device> m_vdg;
required_device<cpu_device> m_maincpu;
@ -92,18 +95,6 @@ READ8_MEMBER(spc1000_state::spc1000_iplk_r)
return 0;
}
WRITE8_MEMBER(spc1000_state::spc1000_video_ram_w)
{
m_video_ram[offset] = data;
}
READ8_MEMBER(spc1000_state::spc1000_video_ram_r)
{
return m_video_ram[offset];
}
WRITE8_MEMBER( spc1000_state::cass_w )
{
m_cass->output(BIT(data, 0) ? -1.0 : 1.0);
@ -119,6 +110,7 @@ WRITE8_MEMBER(spc1000_state::spc1000_gmode_w)
m_vdg->gm0_w(BIT(data, 2));
m_vdg->ag_w(BIT(data, 3));
m_vdg->css_w(BIT(data, 7));
m_page = ( (BIT(data, 5) << 1) | BIT(data, 4) )*0x200;
}
READ8_MEMBER(spc1000_state::spc1000_gmode_r)
@ -128,7 +120,7 @@ READ8_MEMBER(spc1000_state::spc1000_gmode_r)
static ADDRESS_MAP_START( spc1000_io , AS_IO, 8, spc1000_state )
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x0000, 0x1fff) AM_READWRITE(spc1000_video_ram_r, spc1000_video_ram_w)
AM_RANGE(0x0000, 0x1fff) AM_RAM AM_SHARE("videoram")
AM_RANGE(0x2000, 0x3fff) AM_READWRITE(spc1000_gmode_r, spc1000_gmode_w)
AM_RANGE(0x4000, 0x4000) AM_DEVWRITE("ay8910", ay8910_device, address_w)
AM_RANGE(0x4001, 0x4001) AM_DEVREADWRITE("ay8910", ay8910_device, data_r, data_w)
@ -266,16 +258,18 @@ READ8_MEMBER(spc1000_state::spc1000_mc6847_videoram_r)
if (offset == ~0) return 0xff;
// m_GMODE layout: CSS|NA|PS2|PS1|~A/G|GM0|GM1|NA
// [PS2,PS1] is used to set screen 0/1 pages
if ( !BIT(m_GMODE, 3) ) { // text mode (~A/G set to A)
unsigned int page = (BIT(m_GMODE, 5) << 1) | BIT(m_GMODE, 4);
m_vdg->inv_w(BIT(m_video_ram[offset+page*0x200+0x800], 0));
m_vdg->css_w(BIT(m_video_ram[offset+page*0x200+0x800], 1));
m_vdg->as_w(BIT(m_video_ram[offset+page*0x200+0x800], 2));
m_vdg->intext_w(BIT(m_video_ram[offset+page*0x200+0x800], 3));
return m_video_ram[offset+page*0x200];
} else { // graphics mode: uses full 6KB of VRAM
return m_video_ram[offset];
if ( !BIT(m_GMODE, 3) )
{ // text mode (~A/G set to A)
UINT8 data = m_p_videoram[offset+m_page+0x800];
m_vdg->inv_w(BIT(data, 0));
m_vdg->css_w(BIT(data, 1));
m_vdg->as_w (BIT(data, 2));
m_vdg->intext_w(BIT(data, 3));
return m_p_videoram[offset+m_page];
}
else
{ // graphics mode: uses full 6KB of VRAM
return m_p_videoram[offset];
}
}
@ -299,7 +293,7 @@ static const ay8910_interface spc1000_ay_interface =
static const cassette_interface spc1000_cassette_interface =
{
cassette_default_formats,
spc1000_cassette_formats,
NULL,
(cassette_state)(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED),
NULL,