From 7e23a9031777345a722c0f56fdd16b43d2eba38b Mon Sep 17 00:00:00 2001 From: etabeta78 Date: Fri, 24 Oct 2014 06:06:55 +0200 Subject: [PATCH] (MESS) spc1000: added support for tapes in .cas format [Fabio Priuli] (MESS) spc1000: added emulation of joystick inputs [Fabio Priuli] (MESS) added software list for Samsung spc1000 tapes [Fabio Priuli] out of whatsnew: addition of joystick support made playable Space Invaders, Super Xevious, The Goonies and King's Valley. --- src/lib/formats/spc1000_cas.c | 108 +++++++++++++++++++++++++++------- src/mess/drivers/spc1000.c | 72 ++++++++++++----------- 2 files changed, 126 insertions(+), 54 deletions(-) diff --git a/src/lib/formats/spc1000_cas.c b/src/lib/formats/spc1000_cas.c index 02ddb53aa06..03debc584dc 100644 --- a/src/lib/formats/spc1000_cas.c +++ b/src/lib/formats/spc1000_cas.c @@ -10,12 +10,14 @@ Tape formats: TAP: This is a series of 0x30 and 0x31 bytes, representing binary 0 and 1. It includes the header and leaders. -CAS: This format has not been investigated yet. +CAS: Files in this format consist of a 16 bytes header (SPC-1000.CASfmt ) + followed by cassette bits packed together (each byte of a .cas file + are 8 bits, most significant bit first) STA: This format has not been investigated yet, but is assumed to be the save state of some other emulator. -IPL: This format has not been investigated yet. +IPL: This seems a quickload format containing RAM dump, not a real tape ********************************************************************/ @@ -58,68 +60,132 @@ static int spc1000_output_bit(INT16 *buffer, int sample_pos, bool bit) return samples; } -static int spc1000_handle_cassette(INT16 *buffer, const UINT8 *bytes) +static int spc1000_handle_tap(INT16 *buffer, const UINT8 *bytes) { UINT32 sample_count = 0; - UINT32 i; /* data */ - for (i=0; i> (7 - j)) & 1); + + return sample_count; +} + /******************************************************************* Generate samples for the tape image ********************************************************************/ -static int spc1000_cassette_fill_wave(INT16 *buffer, int length, UINT8 *bytes) +static int spc1000_tap_fill_wave(INT16 *buffer, int length, UINT8 *bytes) { - return spc1000_handle_cassette(buffer, bytes); + return spc1000_handle_tap(buffer, bytes); +} + +static int spc1000_cas_fill_wave(INT16 *buffer, int length, UINT8 *bytes) +{ + return spc1000_handle_cas(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) +static int spc1000_tap_calculate_size_in_samples(const UINT8 *bytes, int length) { spc1000_image_size = length; - return spc1000_handle_cassette(NULL, bytes); + return spc1000_handle_tap(NULL, bytes); } -static const struct CassetteLegacyWaveFiller spc1000_legacy_fill_wave = +static int spc1000_cas_calculate_size_in_samples(const UINT8 *bytes, int length) { - spc1000_cassette_fill_wave, /* fill_wave */ + spc1000_image_size = length; + + return spc1000_handle_cas(NULL, bytes); +} + + +/******************************************************************* + Formats + ********************************************************************/ + + +// TAP +static const struct CassetteLegacyWaveFiller spc1000_tap_legacy_fill_wave = +{ + spc1000_tap_fill_wave, /* fill_wave */ -1, /* chunk_size */ 0, /* chunk_samples */ - spc1000_cassette_calculate_size_in_samples, /* chunk_sample_calc */ + spc1000_tap_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) +static casserr_t spc1000_tap_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts) { - return cassette_legacy_identify(cassette, opts, &spc1000_legacy_fill_wave); + return cassette_legacy_identify(cassette, opts, &spc1000_tap_legacy_fill_wave); } -static casserr_t spc1000_cassette_load(cassette_image *cassette) +static casserr_t spc1000_tap_cassette_load(cassette_image *cassette) { - return cassette_legacy_construct(cassette, &spc1000_legacy_fill_wave); + return cassette_legacy_construct(cassette, &spc1000_tap_legacy_fill_wave); } -static const struct CassetteFormat spc1000_cassette_image_format = +static const struct CassetteFormat spc1000_tap_cassette_image_format = { "tap", - spc1000_cassette_identify, - spc1000_cassette_load, + spc1000_tap_cassette_identify, + spc1000_tap_cassette_load, NULL }; + +// CAS +static const struct CassetteLegacyWaveFiller spc1000_cas_legacy_fill_wave = +{ + spc1000_cas_fill_wave, /* fill_wave */ + -1, /* chunk_size */ + 0, /* chunk_samples */ + spc1000_cas_calculate_size_in_samples, /* chunk_sample_calc */ + SPC1000_WAV_FREQUENCY, /* sample_frequency */ + 0, /* header_samples */ + 0 /* trailer_samples */ +}; + +static casserr_t spc1000_cas_cassette_identify(cassette_image *cassette, struct CassetteOptions *opts) +{ + return cassette_legacy_identify(cassette, opts, &spc1000_cas_legacy_fill_wave); +} + +static casserr_t spc1000_cas_cassette_load(cassette_image *cassette) +{ + return cassette_legacy_construct(cassette, &spc1000_cas_legacy_fill_wave); +} + +static const struct CassetteFormat spc1000_cas_cassette_image_format = +{ + "cas", + spc1000_cas_cassette_identify, + spc1000_cas_cassette_load, + NULL +}; + + + CASSETTE_FORMATLIST_START(spc1000_cassette_formats) - CASSETTE_FORMAT(spc1000_cassette_image_format) + CASSETTE_FORMAT(spc1000_tap_cassette_image_format) + CASSETTE_FORMAT(spc1000_cas_cassette_image_format) CASSETTE_FORMATLIST_END diff --git a/src/mess/drivers/spc1000.c b/src/mess/drivers/spc1000.c index dcfb79dca44..df98917e036 100644 --- a/src/mess/drivers/spc1000.c +++ b/src/mess/drivers/spc1000.c @@ -54,6 +54,7 @@ public: , m_pio(*this, "d8255_master") , m_ram(*this, RAM_TAG) , m_cass(*this, "cassette") + , m_io_joy(*this, "JOY") {} DECLARE_WRITE8_MEMBER(spc1000_iplk_w); @@ -69,8 +70,8 @@ public: DECLARE_WRITE8_MEMBER(fdc_8255_b_w); DECLARE_READ8_MEMBER(fdc_8255_c_r); DECLARE_WRITE8_MEMBER(fdc_8255_c_w); - DECLARE_READ8_MEMBER( upd765_tc_r ); - DECLARE_WRITE8_MEMBER( fdc_control_w ); + DECLARE_READ8_MEMBER(upd765_tc_r); + DECLARE_WRITE8_MEMBER(fdc_control_w); MC6847_GET_CHARROM_MEMBER(get_char_rom) { return m_p_videoram[0x1000 + (ch & 0x7f) * 16 + line]; @@ -82,6 +83,7 @@ private: UINT8 m_GMODE; UINT16 m_page; UINT8 *m_work_ram; + virtual void machine_start(); virtual void machine_reset(); required_device m_vdg; required_device m_maincpu; @@ -90,6 +92,7 @@ private: required_device m_pio; required_device m_ram; required_device m_cass; + required_ioport m_io_joy; floppy_image_device *m_fd0; floppy_image_device *m_fd1; @@ -110,36 +113,23 @@ void spc1000_state::device_timer(emu_timer &timer, device_timer_id id, int param static ADDRESS_MAP_START(spc1000_mem, AS_PROGRAM, 8, spc1000_state ) ADDRESS_MAP_UNMAP_HIGH - AM_RANGE( 0x0000, 0x7fff ) AM_READ_BANK("bank1") AM_WRITE_BANK("bank2") - AM_RANGE( 0x8000, 0xffff ) AM_READ_BANK("bank3") AM_WRITE_BANK("bank4") + AM_RANGE(0x0000, 0x7fff) AM_READ_BANK("bank1") AM_WRITE_BANK("bank2") + AM_RANGE(0x8000, 0xffff) AM_READ_BANK("bank3") AM_WRITE_BANK("bank4") ADDRESS_MAP_END WRITE8_MEMBER(spc1000_state::spc1000_iplk_w) { m_IPLK = m_IPLK ? 0 : 1; - if (m_IPLK == 1) { - UINT8 *mem = memregion("maincpu")->base(); - membank("bank1")->set_base(mem); - membank("bank3")->set_base(mem); - } else { - UINT8 *ram = m_ram->pointer(); - membank("bank1")->set_base(ram); - membank("bank3")->set_base(ram + 0x8000); - } + membank("bank1")->set_entry(m_IPLK); + membank("bank3")->set_entry(m_IPLK); } READ8_MEMBER(spc1000_state::spc1000_iplk_r) { m_IPLK = m_IPLK ? 0 : 1; - if (m_IPLK == 1) { - UINT8 *mem = memregion("maincpu")->base(); - membank("bank1")->set_base(mem); - membank("bank3")->set_base(mem); - } else { - UINT8 *ram = m_ram->pointer(); - membank("bank1")->set_base(ram); - membank("bank3")->set_base(ram + 0x8000); - } + membank("bank1")->set_entry(m_IPLK); + membank("bank3")->set_entry(m_IPLK); + return 0; } @@ -350,25 +340,38 @@ static INPUT_PORTS_START( spc1000 ) PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') PORT_CHAR(0x0c) PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') PORT_CHAR(0x0e) PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_KEYBOARD) PORT_NAME("9 )") PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') + + PORT_START("JOY") + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1) + PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_UNUSED) // Button 2? + PORT_BIT(0xc0, IP_ACTIVE_HIGH, IPT_UNUSED) // Cassette related INPUT_PORTS_END -void spc1000_state::machine_reset() +void spc1000_state::machine_start() { - address_space &space = m_maincpu->space(AS_PROGRAM); UINT8 *mem = memregion("maincpu")->base(); UINT8 *ram = m_ram->pointer(); - space.install_read_bank(0x0000, 0x7fff, "bank1"); - space.install_read_bank(0x8000, 0xffff, "bank3"); + // configure and intialize banks 1 & 3 (read banks) + membank("bank1")->configure_entry(0, ram); + membank("bank1")->configure_entry(1, mem); + membank("bank3")->configure_entry(0, ram + 0x8000); + membank("bank3")->configure_entry(1, mem); + membank("bank1")->set_entry(1); + membank("bank3")->set_entry(1); - space.install_write_bank(0x0000, 0x7fff, "bank2"); - space.install_write_bank(0x8000, 0xffff, "bank4"); - - membank("bank1")->set_base(mem); + // intialize banks 2 & 4 (write banks) membank("bank2")->set_base(ram); - membank("bank3")->set_base(mem); membank("bank4")->set_base(ram + 0x8000); +} + +void spc1000_state::machine_reset() +{ m_work_ram = auto_alloc_array_clear(machine(), UINT8, 0x10000); m_fdccpu->set_input_line_vector(0, 0); @@ -407,10 +410,11 @@ READ8_MEMBER(spc1000_state::mc6847_videoram_r) READ8_MEMBER( spc1000_state::porta_r ) { - UINT8 data = 0; + UINT8 data = 0x3f; data |= (m_cass->input() > 0.0038) ? 0x80 : 0; data |= ((m_cass->get_state() & CASSETTE_MASK_UISTATE) == CASSETTE_PLAY) ? 0x00 : 0x40; - + data &= ~(m_io_joy->read() & 0x3f); + return data; } @@ -491,6 +495,8 @@ static MACHINE_CONFIG_START( spc1000, spc1000_state ) MCFG_CASSETTE_FORMATS(spc1000_cassette_formats) MCFG_CASSETTE_DEFAULT_STATE(CASSETTE_STOPPED | CASSETTE_SPEAKER_ENABLED | CASSETTE_MOTOR_ENABLED) + MCFG_SOFTWARE_LIST_ADD("cass_list", "spc1000_cass") + /* internal ram */ MCFG_RAM_ADD(RAM_TAG) MCFG_RAM_DEFAULT_SIZE("64K")