diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/bus/bus.mak | 14 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/chess.c | 58 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/chess.h | 31 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/rom.c | 95 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/rom.h | 65 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/slot.c | 279 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/slot.h | 120 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/voice.c | 101 | ||||
-rw-r--r-- | src/emu/bus/odyssey2/voice.h | 48 | ||||
-rw-r--r-- | src/mess/drivers/odyssey2.c | 179 | ||||
-rw-r--r-- | src/mess/mess.mak | 1 |
11 files changed, 837 insertions, 154 deletions
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak index d3f7c3b7cab..a6cd026c0a8 100644 --- a/src/emu/bus/bus.mak +++ b/src/emu/bus/bus.mak @@ -545,6 +545,20 @@ endif #------------------------------------------------- # +#@src/emu/bus/odyssey2/slot.h,BUSES += O2 +#------------------------------------------------- + +ifneq ($(filter O2,$(BUSES)),) +OBJDIRS += $(BUSOBJ)/odyssey2 +BUSOBJS += $(BUSOBJ)/odyssey2/slot.o +BUSOBJS += $(BUSOBJ)/odyssey2/rom.o +BUSOBJS += $(BUSOBJ)/odyssey2/chess.o +BUSOBJS += $(BUSOBJ)/odyssey2/voice.o +endif + + +#------------------------------------------------- +# #@src/emu/bus/pc_joy/pc_joy.h,BUSES += PC_JOY #------------------------------------------------- diff --git a/src/emu/bus/odyssey2/chess.c b/src/emu/bus/odyssey2/chess.c new file mode 100644 index 00000000000..6150e5f5a59 --- /dev/null +++ b/src/emu/bus/odyssey2/chess.c @@ -0,0 +1,58 @@ +/*********************************************************************************************************** + + + Videopac Chess Module emulation + + TODO: + - this code is just a stub... hence, almost everything is still to do! + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "chess.h" + + +//------------------------------------------------- +// o2_chess_device - constructor +//------------------------------------------------- + +const device_type O2_ROM_CHESS = &device_creator<o2_chess_device>; + + +o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : o2_rom_device(mconfig, O2_ROM_CHESS, "Odyssey 2 BASIC Carts", tag, owner, clock, "o2_chess", __FILE__), + m_cpu(*this, "subcpu") +{ +} + + +//------------------------------------------------- +// MACHINE_CONFIG_FRAGMENT( o2chess ) +//------------------------------------------------- + +static ADDRESS_MAP_START(chess_mem, AS_PROGRAM, 8, o2_chess_device) + AM_RANGE(0x0000, 0x07ff) AM_READ(read_rom04) +ADDRESS_MAP_END + +static ADDRESS_MAP_START(chess_io, AS_IO, 8, o2_chess_device) + ADDRESS_MAP_UNMAP_HIGH + ADDRESS_MAP_GLOBAL_MASK(0xff) +ADDRESS_MAP_END + +static MACHINE_CONFIG_FRAGMENT( o2chess ) + MCFG_CPU_ADD("subcpu", NSC800, XTAL_4MHz) + MCFG_CPU_PROGRAM_MAP(chess_mem) + MCFG_CPU_IO_MAP(chess_io) +MACHINE_CONFIG_END + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor o2_chess_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( o2chess ); +} diff --git a/src/emu/bus/odyssey2/chess.h b/src/emu/bus/odyssey2/chess.h new file mode 100644 index 00000000000..622392d13a4 --- /dev/null +++ b/src/emu/bus/odyssey2/chess.h @@ -0,0 +1,31 @@ +#ifndef __O2_CHESS_H +#define __O2_CHESS_H + +#include "slot.h" +#include "rom.h" +#include "cpu/z80/z80.h" + + +// ======================> o2_chess_device + +class o2_chess_device : public o2_rom_device +{ + + virtual machine_config_constructor device_mconfig_additions() const; +// virtual const rom_entry *device_rom_region() const; + +public: + // construction/destruction + o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + +private: + required_device<nsc800_device> m_cpu; +}; + + + +// device type definition +extern const device_type O2_ROM_CHESS; + + +#endif diff --git a/src/emu/bus/odyssey2/rom.c b/src/emu/bus/odyssey2/rom.c new file mode 100644 index 00000000000..1406129eabc --- /dev/null +++ b/src/emu/bus/odyssey2/rom.c @@ -0,0 +1,95 @@ +/*********************************************************************************************************** + + + Magnavox Odyssey cart emulation + + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "rom.h" + + +//------------------------------------------------- +// o2_rom_device - constructor +//------------------------------------------------- + +const device_type O2_ROM_STD = &device_creator<o2_rom_device>; +const device_type O2_ROM_12K = &device_creator<o2_rom12_device>; +const device_type O2_ROM_16K = &device_creator<o2_rom16_device>; + + +o2_rom_device::o2_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + device_o2_cart_interface( mconfig, *this ) +{ +} + +o2_rom_device::o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : device_t(mconfig, O2_ROM_STD, "Odyssey 2 Standard Carts", tag, owner, clock, "o2_rom", __FILE__), + device_o2_cart_interface( mconfig, *this ) +{ +} + +o2_rom12_device::o2_rom12_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : o2_rom_device(mconfig, O2_ROM_12K, "Odyssey 2 12K Carts", tag, owner, clock, "o2_rom12", __FILE__) +{ +} + +o2_rom16_device::o2_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : o2_rom_device(mconfig, O2_ROM_16K, "Odyssey 2 16K Carts", tag, owner, clock, "o2_rom16", __FILE__) +{ +} + + +//------------------------------------------------- +// device_start/device_reset - device-specific startup +//------------------------------------------------- + +void o2_rom_device::device_start() +{ + save_item(NAME(m_bank_base)); +} + +void o2_rom_device::device_reset() +{ + m_bank_base = 0; +} + +/*------------------------------------------------- + mapper specific handlers + -------------------------------------------------*/ + +void o2_rom_device::write_bank(int bank) +{ + m_bank_base = bank; +} + +READ8_MEMBER(o2_rom_device::read_rom04) +{ + return m_rom[(offset + (m_bank_base & 0x03) * 0x800) & (m_rom_size - 1)]; +} +READ8_MEMBER(o2_rom_device::read_rom0c) +{ + return m_rom[(offset + (m_bank_base & 0x03) * 0x800) & (m_rom_size - 1)]; +} + +READ8_MEMBER(o2_rom12_device::read_rom04) +{ + return m_rom[offset + (m_bank_base & 0x03) * 0xc00]; +} +READ8_MEMBER(o2_rom12_device::read_rom0c) +{ + return m_rom[offset + 0x800 + (m_bank_base & 0x03) * 0xc00]; +} + +READ8_MEMBER(o2_rom16_device::read_rom04) +{ + return m_rom[offset + 0x400 + (m_bank_base & 0x03) * 0x1000]; +} +READ8_MEMBER(o2_rom16_device::read_rom0c) +{ + return m_rom[offset + 0xc00 + (m_bank_base & 0x03) * 0x1000]; +} + diff --git a/src/emu/bus/odyssey2/rom.h b/src/emu/bus/odyssey2/rom.h new file mode 100644 index 00000000000..174e6dece30 --- /dev/null +++ b/src/emu/bus/odyssey2/rom.h @@ -0,0 +1,65 @@ +#ifndef __O2_ROM_H +#define __O2_ROM_H + +#include "slot.h" + + +// ======================> o2_rom_device + +class o2_rom_device : public device_t, + public device_o2_cart_interface +{ +public: + // construction/destruction + o2_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04); + virtual DECLARE_READ8_MEMBER(read_rom0c); + + virtual void write_bank(int bank); + +protected: + int m_bank_base; +}; + +// ======================> o2_rom12_device + +class o2_rom12_device : public o2_rom_device +{ +public: + // construction/destruction + o2_rom12_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04); + virtual DECLARE_READ8_MEMBER(read_rom0c); +}; + +// ======================> o2_rom16_device + +class o2_rom16_device : public o2_rom_device +{ +public: + // construction/destruction + o2_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04); + virtual DECLARE_READ8_MEMBER(read_rom0c); +}; + + + +// device type definition +extern const device_type O2_ROM_STD; +extern const device_type O2_ROM_12K; +extern const device_type O2_ROM_16K; + + +#endif diff --git a/src/emu/bus/odyssey2/slot.c b/src/emu/bus/odyssey2/slot.c new file mode 100644 index 00000000000..a434b32c2f5 --- /dev/null +++ b/src/emu/bus/odyssey2/slot.c @@ -0,0 +1,279 @@ +/*********************************************************************************************************** + + Magnavox Odyssey 2 cart emulation + (through slot devices) + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "slot.h" + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +const device_type O2_CART_SLOT = &device_creator<o2_cart_slot_device>; + +//************************************************************************** +// Odyssey 2 Cartridges Interface +//************************************************************************** + +//------------------------------------------------- +// device_o2_cart_interface - constructor +//------------------------------------------------- + +device_o2_cart_interface::device_o2_cart_interface(const machine_config &mconfig, device_t &device) + : device_slot_card_interface(mconfig, device), + m_rom(NULL), + m_rom_size(0) +{ +} + + +//------------------------------------------------- +// ~device_o2_cart_interface - destructor +//------------------------------------------------- + +device_o2_cart_interface::~device_o2_cart_interface() +{ +} + +//------------------------------------------------- +// rom_alloc - alloc the space for the cart +//------------------------------------------------- + +void device_o2_cart_interface::rom_alloc(UINT32 size, const char *tag) +{ + if (m_rom == NULL) + { + astring tempstring(tag); + tempstring.cat(O2SLOT_ROM_REGION_TAG); + m_rom = device().machine().memory().region_alloc(tempstring, size, 1, ENDIANNESS_LITTLE)->base(); + m_rom_size = size; + } +} + + +//------------------------------------------------- +// ram_alloc - alloc the space for the ram +//------------------------------------------------- + +void device_o2_cart_interface::ram_alloc(UINT32 size) +{ + m_ram.resize(size); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// o2_cart_slot_device - constructor +//------------------------------------------------- +o2_cart_slot_device::o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, O2_CART_SLOT, "Odyssey 2 Cartridge Slot", tag, owner, clock, "o2_cart_slot", __FILE__), + device_image_interface(mconfig, *this), + device_slot_interface(mconfig, *this), + m_type(O2_STD) +{ +} + + +//------------------------------------------------- +// o2_cart_slot_device - destructor +//------------------------------------------------- + +o2_cart_slot_device::~o2_cart_slot_device() +{ +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void o2_cart_slot_device::device_start() +{ + m_cart = dynamic_cast<device_o2_cart_interface *>(get_card_device()); +} + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void o2_cart_slot_device::device_config_complete() +{ + // set brief and instance name + update_names(); +} + + +//------------------------------------------------- +// O2 PCB +//------------------------------------------------- + +struct o2_slot +{ + int pcb_id; + const char *slot_option; +}; + +// Here, we take the feature attribute from .xml (i.e. the PCB name) and we assign a unique ID to it +static const o2_slot slot_list[] = +{ + { O2_STD, "o2_rom" }, + { O2_ROM12, "o2_rom12" }, + { O2_ROM16, "o2_rom16" }, + { O2_CHESS, "o2_chess" }, + { O2_VOICE, "o2_voice" } +}; + +static int o2_get_pcb_id(const char *slot) +{ + for (int i = 0; i < ARRAY_LENGTH(slot_list); i++) + { + if (!core_stricmp(slot_list[i].slot_option, slot)) + return slot_list[i].pcb_id; + } + + return 0; +} + +static const char *o2_get_slot(int type) +{ + for (int i = 0; i < ARRAY_LENGTH(slot_list); i++) + { + if (slot_list[i].pcb_id == type) + return slot_list[i].slot_option; + } + + return "o2_rom"; +} + + +/*------------------------------------------------- + call load + -------------------------------------------------*/ + +bool o2_cart_slot_device::call_load() +{ + if (m_cart) + { + UINT32 size = (software_entry() == NULL) ? length() : get_software_region_length("rom"); + m_cart->rom_alloc(size, tag()); + + if (software_entry() == NULL) + fread(m_cart->get_rom_base(), size); + else + memcpy(m_cart->get_rom_base(), get_software_region("rom"), size); + + if (software_entry() == NULL) + { + m_type = O2_STD; + if (size == 12288) + m_type = O2_ROM12; + if (size == 16384) + m_type = O2_ROM16; + } + else + { + const char *pcb_name = get_feature("slot"); + if (pcb_name) + m_type = o2_get_pcb_id(pcb_name); + } + + //printf("Type: %s\n", o2_get_slot(m_type)); + + return IMAGE_INIT_PASS; + } + + return IMAGE_INIT_PASS; +} + + +/*------------------------------------------------- + call softlist load + -------------------------------------------------*/ + +bool o2_cart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry) +{ + load_software_part_region(*this, swlist, swname, start_entry); + return TRUE; +} + + +/*------------------------------------------------- + get default card software + -------------------------------------------------*/ + +void o2_cart_slot_device::get_default_card_software(astring &result) +{ + if (open_image_file(mconfig().options())) + { + const char *slot_string = "o2_rom"; + UINT32 size = core_fsize(m_file); + int type = O2_STD; + + if (size == 12288) + type = O2_ROM12; + if (size == 16384) + type = O2_ROM16; + + slot_string = o2_get_slot(type); + + //printf("type: %s\n", slot_string); + clear(); + + result.cpy(slot_string); + return; + } + + software_get_default_slot(result, "o2_rom"); +} + +/*------------------------------------------------- + read_rom** + -------------------------------------------------*/ + +READ8_MEMBER(o2_cart_slot_device::read_rom04) +{ + if (m_cart) + return m_cart->read_rom04(space, offset); + else + return 0xff; +} + +READ8_MEMBER(o2_cart_slot_device::read_rom0c) +{ + if (m_cart) + return m_cart->read_rom0c(space, offset); + else + return 0xff; +} + +/*------------------------------------------------- + io_write + -------------------------------------------------*/ + +WRITE8_MEMBER(o2_cart_slot_device::io_write) +{ + if (m_cart) + m_cart->io_write(space, offset, data); +} + + +#include "bus/odyssey2/rom.h" +#include "bus/odyssey2/chess.h" +#include "bus/odyssey2/voice.h" + +SLOT_INTERFACE_START(o2_cart) + SLOT_INTERFACE_INTERNAL("o2_rom", O2_ROM_STD) + SLOT_INTERFACE_INTERNAL("o2_rom12", O2_ROM_12K) + SLOT_INTERFACE_INTERNAL("o2_rom16", O2_ROM_16K) + SLOT_INTERFACE_INTERNAL("o2_chess", O2_ROM_CHESS) + SLOT_INTERFACE_INTERNAL("o2_voice", O2_ROM_VOICE) +SLOT_INTERFACE_END + diff --git a/src/emu/bus/odyssey2/slot.h b/src/emu/bus/odyssey2/slot.h new file mode 100644 index 00000000000..f1f30c58587 --- /dev/null +++ b/src/emu/bus/odyssey2/slot.h @@ -0,0 +1,120 @@ +#ifndef __O2_SLOT_H +#define __O2_SLOT_H + +/*************************************************************************** + TYPE DEFINITIONS + ***************************************************************************/ + + +/* PCB */ +enum +{ + O2_STD = 0, + O2_ROM12, + O2_ROM16, + O2_CHESS, + O2_VOICE +}; + + +// ======================> device_o2_cart_interface + +class device_o2_cart_interface : public device_slot_card_interface +{ +public: + // construction/destruction + device_o2_cart_interface(const machine_config &mconfig, device_t &device); + virtual ~device_o2_cart_interface(); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04) { return 0xff; } + virtual DECLARE_READ8_MEMBER(read_rom0c) { return 0xff; } + virtual void write_bank(int bank) {} + + virtual DECLARE_WRITE8_MEMBER(io_write) {} + virtual DECLARE_READ8_MEMBER(t0_read) { return 0; } + + void rom_alloc(UINT32 size, const char *tag); + void ram_alloc(UINT32 size); + UINT8* get_rom_base() { return m_rom; } + UINT8* get_ram_base() { return m_ram; } + UINT32 get_rom_size() { return m_rom_size; } + UINT32 get_ram_size() { return m_ram.count(); } + +protected: + // internal state + UINT8 *m_rom; + UINT32 m_rom_size; + dynamic_buffer m_ram; +}; + + +// ======================> o2_cart_slot_device + +class o2_cart_slot_device : public device_t, + public device_image_interface, + public device_slot_interface +{ +public: + // construction/destruction + o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + virtual ~o2_cart_slot_device(); + + // device-level overrides + virtual void device_start(); + virtual void device_config_complete(); + + // image-level overrides + virtual bool call_load(); + virtual void call_unload() {} + virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry); + + int get_type() { return m_type; } + + virtual iodevice_t image_type() const { return IO_CARTSLOT; } + virtual bool is_readable() const { return 1; } + virtual bool is_writeable() const { return 0; } + virtual bool is_creatable() const { return 0; } + virtual bool must_be_loaded() const { return 0; } + virtual bool is_reset_on_load() const { return 1; } + virtual const option_guide *create_option_guide() const { return NULL; } + virtual const char *image_interface() const { return "odyssey_cart"; } + virtual const char *file_extensions() const { return "bin,rom"; } + + // slot interface overrides + virtual void get_default_card_software(astring &result); + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04); + virtual DECLARE_READ8_MEMBER(read_rom0c); + virtual DECLARE_WRITE8_MEMBER(io_write); + virtual DECLARE_READ8_MEMBER(t0_read) { if (m_cart) return m_cart->t0_read(space, offset); else return 0; } + + virtual void write_bank(int bank) { if (m_cart) m_cart->write_bank(bank); } + +protected: + + int m_type; + device_o2_cart_interface* m_cart; +}; + + + +// device type definition +extern const device_type O2_CART_SLOT; + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS + ***************************************************************************/ + +#define O2SLOT_ROM_REGION_TAG ":cart:rom" + +#define MCFG_O2_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \ + MCFG_DEVICE_ADD(_tag, O2_CART_SLOT, 0) \ + MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \ + + +SLOT_INTERFACE_EXTERN(o2_cart); + +#endif diff --git a/src/emu/bus/odyssey2/voice.c b/src/emu/bus/odyssey2/voice.c new file mode 100644 index 00000000000..7da5d308695 --- /dev/null +++ b/src/emu/bus/odyssey2/voice.c @@ -0,0 +1,101 @@ +/*********************************************************************************************************** + + + Magnavox The Voice emulation + + TODO: + - load speech ROM from softlist + - move external speech rom for S.I.D. the Spellbinder into the softlist entry + + ***********************************************************************************************************/ + + +#include "emu.h" +#include "voice.h" + + +//------------------------------------------------- +// o2_voice_device - constructor +//------------------------------------------------- + +const device_type O2_ROM_VOICE = &device_creator<o2_voice_device>; + + +o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : o2_rom_device(mconfig, O2_ROM_VOICE, "Odyssey 2 The Voice Passthrough Cart", tag, owner, clock, "o2_voice", __FILE__), + m_speech(*this, "sp0256_speech"), + m_subslot(*this, "subslot"), + m_lrq_state(0) +{ +} + + +void o2_voice_device::device_start() +{ + save_item(NAME(m_lrq_state)); +} + +//------------------------------------------------- +// MACHINE_CONFIG_FRAGMENT( sub_slot ) +//------------------------------------------------- + +static MACHINE_CONFIG_FRAGMENT( o2voice ) + MCFG_SPEAKER_STANDARD_MONO("mono") + + MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000) + MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(o2_voice_device, lrq_callback)) + // The Voice uses a speaker with its own volume control so the relative volumes to use are subjective, these sound good + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) + + MCFG_O2_CARTRIDGE_ADD("subslot", o2_cart, NULL) +MACHINE_CONFIG_END + + +//------------------------------------------------- +// machine_config_additions - device-specific +// machine configurations +//------------------------------------------------- + +machine_config_constructor o2_voice_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( o2voice ); +} + + +ROM_START( o2voice ) + ROM_REGION( 0x10000, "sp0256_speech", 0 ) + // SP0256B-019 Speech chip w/2KiB mask rom + ROM_LOAD( "sp0256b-019.bin", 0x1000, 0x0800, CRC(4bb43724) SHA1(49f5326ad45392dc96c89d1d4e089a20bd21e609) ) + + /* A note about "The Voice": Two versions of "The Voice" exist: + * An earlier version with eight 2KiB speech roms, spr016-??? through spr016-??? on a small daughterboard + <note to self: fill in numbers later> + * A later version with one 16KiB speech rom, spr128-003, mounted directly on the mainboard + The rom contents of these two versions are EXACTLY the same. + Both versions have an sp0256b-019 speech chip, which has 2KiB of its own internal speech data + Thanks to kevtris for this info. - LN + */ + + // External 16KiB speech ROM (spr128-003) from "The Voice" + ROM_LOAD( "spr128-003.bin", 0x4000, 0x4000, CRC(509367b5) SHA1(0f31f46bc02e9272885779a6dd7102c78b18895b) ) + // Additional External 16KiB speech ROM (spr128-004) from S.I.D. the Spellbinder + ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) ) +ROM_END + +const rom_entry *o2_voice_device::device_rom_region() const +{ + return ROM_NAME( o2voice ); +} + +WRITE_LINE_MEMBER(o2_voice_device::lrq_callback) +{ + m_lrq_state = state; +} + +WRITE8_MEMBER(o2_voice_device::io_write) +{ + if (data & 0x20) + m_speech->ald_w(space, 0, offset & 0x7f); + else + m_speech->reset(); +} diff --git a/src/emu/bus/odyssey2/voice.h b/src/emu/bus/odyssey2/voice.h new file mode 100644 index 00000000000..14ffb32c407 --- /dev/null +++ b/src/emu/bus/odyssey2/voice.h @@ -0,0 +1,48 @@ +#ifndef __O2_VOICE_H +#define __O2_VOICE_H + +#include "slot.h" +#include "rom.h" +#include "sound/sp0256.h" + + +// ======================> o2_voice_device + +class o2_voice_device : public o2_rom_device +{ +public: + // construction/destruction + o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start(); + virtual void device_reset() {} + + virtual machine_config_constructor device_mconfig_additions() const; + virtual const rom_entry *device_rom_region() const; + + // reading and writing + virtual DECLARE_READ8_MEMBER(read_rom04) { if (m_subslot->exists()) return m_subslot->read_rom04(space, offset); else return 0xff; } + virtual DECLARE_READ8_MEMBER(read_rom0c) { if (m_subslot->exists()) return m_subslot->read_rom0c(space, offset); else return 0xff; } + + virtual void write_bank(int bank) { if (m_subslot->exists()) m_subslot->write_bank(bank); } + + DECLARE_WRITE_LINE_MEMBER(lrq_callback); + DECLARE_WRITE8_MEMBER(io_write); + DECLARE_READ8_MEMBER(t0_read) { return m_speech->lrq_r() ? 0 : 1; } + +private: + required_device<sp0256_device> m_speech; + required_device<o2_cart_slot_device> m_subslot; + + int m_lrq_state; +}; + + + + +// device type definition +extern const device_type O2_ROM_VOICE; + + +#endif diff --git a/src/mess/drivers/odyssey2.c b/src/mess/drivers/odyssey2.c index 117a6f7cf50..3d1e22a28ec 100644 --- a/src/mess/drivers/odyssey2.c +++ b/src/mess/drivers/odyssey2.c @@ -14,12 +14,12 @@ #include "emu.h" #include "cpu/mcs48/mcs48.h" -#include "imagedev/cartslot.h" -#include "sound/sp0256.h" #include "video/i8244.h" #include "machine/i8243.h" #include "video/ef9340_1.h" +#include "bus/odyssey2/slot.h" + class odyssey2_state : public driver_device { @@ -28,24 +28,18 @@ public: : driver_device(mconfig, type, tag), m_maincpu(*this, "maincpu"), m_i8244(*this, "i8244"), - m_sp0256(*this, "sp0256_speech"), - m_user1(*this, "user1"), - m_bank1(*this, "bank1"), - m_bank2(*this, "bank2"), + m_cart(*this, "cartslot"), m_keyboard(*this, "KEY"), m_joysticks(*this, "JOY") { } required_device<cpu_device> m_maincpu; required_device<i8244_device> m_i8244; - required_device<sp0256_device> m_sp0256; + required_device<o2_cart_slot_device> m_cart; - int m_the_voice_lrq_state; UINT8 m_ram[256]; UINT8 m_p1; UINT8 m_p2; - int m_cart_size; UINT8 m_lum; - DECLARE_READ8_MEMBER(t0_read); DECLARE_READ8_MEMBER(io_read); DECLARE_WRITE8_MEMBER(io_write); DECLARE_READ8_MEMBER(bus_read); @@ -60,7 +54,6 @@ public: virtual void machine_reset(); DECLARE_PALETTE_INIT(odyssey2); UINT32 screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); - DECLARE_WRITE_LINE_MEMBER(the_voice_lrq_callback); DECLARE_WRITE_LINE_MEMBER(irq_callback); DECLARE_WRITE16_MEMBER(scanline_postprocess); @@ -76,15 +69,8 @@ protected: static const UINT8 P1_VDC_COPY_MODE_ENABLE = 0x40; static const UINT8 P2_KEYBOARD_SELECT_MASK = 0x07; /* select row to scan */ - required_memory_region m_user1; - - required_memory_bank m_bank1; - required_memory_bank m_bank2; - required_ioport_array<6> m_keyboard; required_ioport_array<2> m_joysticks; - - void switch_banks(); }; class g7400_state : public odyssey2_state @@ -115,9 +101,9 @@ protected: static ADDRESS_MAP_START( odyssey2_mem , AS_PROGRAM, 8, odyssey2_state ) - AM_RANGE(0x0000, 0x03FF) AM_ROM - AM_RANGE(0x0400, 0x0BFF) AM_RAMBANK("bank1") - AM_RANGE(0x0C00, 0x0FFF) AM_RAMBANK("bank2") + AM_RANGE(0x0000, 0x03ff) AM_ROM + AM_RANGE(0x0400, 0x0bff) AM_DEVREAD("cartslot", o2_cart_slot_device, read_rom04) + AM_RANGE(0x0c00, 0x0fff) AM_DEVREAD("cartslot", o2_cart_slot_device, read_rom0c) ADDRESS_MAP_END @@ -126,7 +112,7 @@ static ADDRESS_MAP_START( odyssey2_io , AS_IO, 8, odyssey2_state ) AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write) AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write) AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write) - AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read) + AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_DEVREAD("cartslot", o2_cart_slot_device, t0_read) AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read) ADDRESS_MAP_END @@ -136,7 +122,7 @@ static ADDRESS_MAP_START( g7400_io , AS_IO, 8, g7400_state ) AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write) AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write) AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write) - AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read) + AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_DEVREAD("cartslot", o2_cart_slot_device, t0_read) AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read) AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_DEVWRITE("i8243", i8243_device, i8243_prog_w); ADDRESS_MAP_END @@ -298,67 +284,15 @@ WRITE_LINE_MEMBER(odyssey2_state::irq_callback) } -void odyssey2_state::switch_banks() -{ - switch ( m_cart_size ) - { - case 12288: - /* 12KB cart support (for instance, KTAA as released) */ - m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0xC00 ); - m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0xC00 + 0x800 ); - break; - - case 16384: - /* 16KB cart support (for instance, full sized version KTAA) */ - m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0x1000 + 0x400 ); - m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0x1000 + 0xC00 ); - break; - - default: - m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0x800 ); - m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0x800 ); - break; - } -} - - -WRITE_LINE_MEMBER(odyssey2_state::the_voice_lrq_callback) -{ - m_the_voice_lrq_state = state; -} - - -READ8_MEMBER(odyssey2_state::t0_read) -{ - return m_sp0256->lrq_r() ? 0 : 1; -} - - DRIVER_INIT_MEMBER(odyssey2_state,odyssey2) { - int i; - int size = 0; UINT8 *gfx = memregion("gfx1")->base(); - device_image_interface *image = dynamic_cast<device_image_interface *>(machine().device("cart")); - for (i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { gfx[i] = i; /* TODO: Why i and not 0? */ m_ram[i] = 0; } - - if (image->exists()) - { - if (image->software_entry() == NULL) - { - size = image->length(); - } - else - { - size = image->get_software_region_length("rom"); - } - } - m_cart_size = size; } @@ -367,9 +301,7 @@ void odyssey2_state::machine_start() save_pointer(NAME(m_ram),256); save_item(NAME(m_p1)); save_item(NAME(m_p2)); - save_item(NAME(m_cart_size)); save_item(NAME(m_lum)); - save_item(NAME(m_the_voice_lrq_state)); } @@ -378,9 +310,9 @@ void odyssey2_state::machine_reset() m_lum = 0; /* jump to "last" bank, will work for all sizes due to being mirrored */ - m_p1 = 0xFF; - m_p2 = 0xFF; - switch_banks(); + m_p1 = 0xff; + m_p2 = 0xff; + m_cart->write_bank(m_p1); } @@ -426,17 +358,10 @@ WRITE8_MEMBER(odyssey2_state::io_write) if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) { m_ram[offset] = data; - if ( offset & 0x80 ) + if (offset & 0x80) { - if ( data & 0x20 ) - { - logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1 ); - m_sp0256->ald_w(space, 0, offset & 0x7f); - } - else - { - m_sp0256->reset(); - } + logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1); + m_cart->io_write(space, offset, data); } } else if (!(m_p1 & P1_VDC_ENABLE)) @@ -470,6 +395,11 @@ WRITE8_MEMBER(g7400_state::io_write) if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00) { m_ram[offset] = data; + if (offset & 0x80) + { + logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1); + m_cart->io_write(space, offset, data); + } } else if (!(m_p1 & P1_VDC_ENABLE)) { @@ -567,8 +497,7 @@ WRITE8_MEMBER(odyssey2_state::p1_write) { m_p1 = data; m_lum = ( data & 0x80 ) >> 4; - - switch_banks(); + m_cart->write_bank(m_p1); } @@ -735,11 +664,10 @@ static GFXDECODE_START( odyssey2 ) GFXDECODE_END + static MACHINE_CONFIG_FRAGMENT( odyssey2_cartslot ) - MCFG_CARTSLOT_ADD("cart") - MCFG_CARTSLOT_EXTENSION_LIST("bin,rom") - MCFG_CARTSLOT_NOT_MANDATORY - MCFG_CARTSLOT_INTERFACE("odyssey_cart") + MCFG_O2_CARTRIDGE_ADD("cartslot", o2_cart, NULL) + MCFG_SOFTWARE_LIST_ADD("cart_list","odyssey2") MACHINE_CONFIG_END @@ -766,11 +694,6 @@ static MACHINE_CONFIG_START( odyssey2, odyssey2_state ) MCFG_I8244_ADD( "i8244", XTAL_7_15909MHz/2 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) - MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000) - MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback)) - /* The Voice uses a speaker with its own volume control so the relative volumes to use are subjective, these sound good */ - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) - MCFG_FRAGMENT_ADD(odyssey2_cartslot) MACHINE_CONFIG_END @@ -797,10 +720,6 @@ static MACHINE_CONFIG_START( videopac, odyssey2_state ) MCFG_I8245_ADD( "i8244", XTAL_17_73447MHz/5 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) - MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000) - MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback)) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) - MCFG_FRAGMENT_ADD(odyssey2_cartslot) MACHINE_CONFIG_END @@ -830,10 +749,6 @@ static MACHINE_CONFIG_START( g7400, g7400_state ) MCFG_I8245_ADD( "i8244", 3540000 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( g7400_state, scanline_postprocess ) ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) - MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000) - MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback)) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) - MCFG_FRAGMENT_ADD(odyssey2_cartslot) MCFG_DEVICE_REMOVE("cart_list") MCFG_SOFTWARE_LIST_ADD("cart_list","g7400") @@ -866,10 +781,6 @@ static MACHINE_CONFIG_START( odyssey3, g7400_state ) MCFG_I8244_ADD( "i8244", 3540000 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( g7400_state, scanline_postprocess ) ) MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) - MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000) - MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback)) - MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) - MCFG_FRAGMENT_ADD(odyssey2_cartslot) MCFG_DEVICE_REMOVE("cart_list") MCFG_SOFTWARE_LIST_ADD("cart_list","g7400") @@ -881,26 +792,6 @@ ROM_START (odyssey2) ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee)) ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) - - ROM_REGION(0x4000, "user1", 0) - ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) - - ROM_REGION( 0x10000, "sp0256_speech", 0 ) - /* SP0256B-019 Speech chip w/2KiB mask rom */ - ROM_LOAD( "sp0256b-019.bin", 0x1000, 0x0800, CRC(4bb43724) SHA1(49f5326ad45392dc96c89d1d4e089a20bd21e609) ) - - /* A note about "The Voice": Two versions of "The Voice" exist: - * An earlier version with eight 2KiB speech roms, spr016-??? through spr016-??? on a small daughterboard - <note to self: fill in numbers later> - * A later version with one 16KiB speech rom, spr128-003, mounted directly on the mainboard - The rom contents of these two versions are EXACTLY the same. - Both versions have an sp0256b-019 speech chip, which has 2KiB of its own internal speech data - Thanks to kevtris for this info. - LN - */ - /* External 16KiB speech ROM (spr128-003) from "The Voice" */ - ROM_LOAD( "spr128-003.bin", 0x4000, 0x4000, CRC(509367b5) SHA1(0f31f46bc02e9272885779a6dd7102c78b18895b) ) - /* Additional External 16KiB ROM (spr128-004) from S.I.D. the Spellbinder */ - ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) ) ROM_END @@ -911,17 +802,6 @@ ROM_START (videopac) ROM_SYSTEM_BIOS( 1, "c52", "c52" ) ROMX_LOAD ("c52.bin", 0x0000, 0x0400, CRC(a318e8d6) SHA1(a6120aed50831c9c0d95dbdf707820f601d9452e), ROM_BIOS(2)) ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) - - ROM_REGION(0x4000, "user1", 0) - ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) - - ROM_REGION( 0x10000, "sp0256_speech", 0 ) - /* SP0256B-019 Speech chip w/2KiB mask rom */ - ROM_LOAD( "sp0256b-019.bin", 0x1000, 0x0800, CRC(4bb43724) SHA1(49f5326ad45392dc96c89d1d4e089a20bd21e609) ) - /* External 16KiB speech ROM (spr128-003) from "The Voice" */ - ROM_LOAD( "spr128-003.bin", 0x4000, 0x4000, CRC(509367b5) SHA1(0f31f46bc02e9272885779a6dd7102c78b18895b) ) - /* Additional External 16KiB speech ROM (spr128-004) from S.I.D. the Spellbinder */ - ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) ) ROM_END @@ -929,9 +809,6 @@ ROM_START (g7400) ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ ROM_LOAD ("g7400.bin", 0x0000, 0x0400, CRC(e20a9f41) SHA1(5130243429b40b01a14e1304d0394b8459a6fbae)) ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) - - ROM_REGION(0x4000, "user1", 0) - ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) ROM_END @@ -939,9 +816,6 @@ ROM_START (jopac) ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */ ROM_LOAD ("jopac.bin", 0x0000, 0x0400, CRC(11647ca5) SHA1(54b8d2c1317628de51a85fc1c424423a986775e4)) ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) - - ROM_REGION(0x4000, "user1", 0) - ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR) ROM_END @@ -950,9 +824,6 @@ ROM_START (odyssey3) ROM_LOAD ("odyssey3.bin", 0x0000, 0x0400, CRC(e2b23324) SHA1(0a38c5f2cea929d2fe0a23e5e1a60de9155815dc)) ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF) - - ROM_REGION(0x4000, "user1", 0) - ROM_CART_LOAD("cart", 0x000, 0x4000, ROM_MIRROR) ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ diff --git a/src/mess/mess.mak b/src/mess/mess.mak index ca411b1e79d..9495461e505 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -603,6 +603,7 @@ BUSES += MSX_SLOT BUSES += NEOGEO BUSES += NES BUSES += NUBUS +BUSES += O2 BUSES += ORICEXT BUSES += PCE BUSES += PCI |