mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
-jaleco/tetrisp2.cpp: Added partial emulation of PC for music games. [Windy Fairy]
-emu/devcb.h: Allow base device to be specified directly in delegate setters. [Vas Crabb] -taito/tnzs.cpp: Untangled inheritance a bit. [Vas Crabb]
This commit is contained in:
parent
5159d1a271
commit
47c281d0fc
@ -716,6 +716,13 @@ private:
|
||||
return delegate_builder<delegate_type_t<T> >(m_target, m_append, m_target.owner(), devcb_read::cast_reference<delegate_device_class_t<T> >(obj), std::forward<T>(func), name);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<is_read_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_t &devbase, char const *tag, T &&func, char const *name)
|
||||
{
|
||||
set_used();
|
||||
return delegate_builder<delegate_type_t<T> >(m_target, m_append, devbase, tag, std::forward<T>(func), name);
|
||||
}
|
||||
|
||||
template <typename T, typename U, bool R>
|
||||
std::enable_if_t<is_read_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_finder<U, R> &finder, T &&func, char const *name)
|
||||
{
|
||||
@ -2055,6 +2062,7 @@ private:
|
||||
{ if ((data ^ exor) & mask) devbase.logerror("%s: %s\n", devbase.machine().describe_context(), message); };
|
||||
}
|
||||
};
|
||||
|
||||
class binder
|
||||
{
|
||||
public:
|
||||
@ -2092,6 +2100,13 @@ private:
|
||||
return delegate_builder<delegate_type_t<T> >(m_target, m_append, m_target.owner(), devcb_write::cast_reference<delegate_device_class_t<T> >(obj), std::forward<T>(func), name);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<is_write_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_t &devbase, char const *tag, T &&func, char const *name)
|
||||
{
|
||||
set_used();
|
||||
return delegate_builder<delegate_type_t<T> >(m_target, m_append, devbase, tag, std::forward<T>(func), name);
|
||||
}
|
||||
|
||||
template <typename T, typename U, bool R>
|
||||
std::enable_if_t<is_write_method<T>::value, delegate_builder<delegate_type_t<T> > > set(device_finder<U, R> &finder, T &&func, char const *name)
|
||||
{
|
||||
|
163
src/mame/jaleco/jaleco_vj_pc.cpp
Normal file
163
src/mame/jaleco/jaleco_vj_pc.cpp
Normal file
@ -0,0 +1,163 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
/*
|
||||
Hardware to run VJ Windows PC side software
|
||||
|
||||
Motherboard is similar to EP-5BVPXB but says REV 1.3 which matches NMC-5VXC
|
||||
but the board used does not have the NMC markings like the NMC-5VXC.
|
||||
|
||||
VIA 82C586B PCI ISA/IDE bridge
|
||||
VIA 82C585VPX
|
||||
Winbond W83877F IO Core Logic
|
||||
|
||||
S3 Virge/DX Q5C2BB (not connected to a monitor)
|
||||
|
||||
UPS is connected to COM1 port
|
||||
|
||||
CD-ROM: Mitsumi CRMC-FX3210S(?)
|
||||
Floppy: Unidentified but machine has floppy drive
|
||||
|
||||
|
||||
TODO: None of the VIA chips are emulated in the new PCI code
|
||||
Windows 95 will ask you to install the new hardware every boot. There's an autoexec.bat that'll
|
||||
restore the registry and other configs back to the factory setup every boot so
|
||||
the hardware will never stay "installed" between boots.
|
||||
|
||||
Keyboard and mouse should not enabled by default but it'd be impossible to install drivers currently.
|
||||
It's recommended to disable the keyboard (Input Settings > Keyboard Selection > AT Keyboard > Disabled)
|
||||
when actually playing the games because otherwise you'll be sending inputs to the Windows PC in the background.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "jaleco_vj_pc.h"
|
||||
|
||||
#include "jaleco_vj_ups.h"
|
||||
|
||||
#include "bus/isa/isa_cards.h"
|
||||
#include "bus/rs232/rs232.h"
|
||||
#include "machine/fdc37c93x.h"
|
||||
#include "machine/i82371sb.h"
|
||||
#include "machine/i82439hx.h"
|
||||
#include "machine/i82439tx.h"
|
||||
#include "machine/pci-ide.h"
|
||||
#include "machine/pci.h"
|
||||
#include "video/virge_pci.h"
|
||||
|
||||
|
||||
jaleco_vj_pc_device::jaleco_vj_pc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, JALECO_VJ_PC, tag, owner, clock),
|
||||
device_mixer_interface(mconfig, *this, 2),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_sound(*this, "isa1:vj_sound"),
|
||||
m_is_steppingstage(false)
|
||||
{
|
||||
}
|
||||
|
||||
void jaleco_vj_pc_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
static void isa_internal_devices(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("fdc37c93x", FDC37C93X);
|
||||
}
|
||||
|
||||
static void isa_com(device_slot_interface &device)
|
||||
{
|
||||
// TODO: Stepping Stage uses a different UPS but will still boot unlike VJ without a valid UPS attached
|
||||
device.option_add("vj_ups", JALECO_VJ_UPS);
|
||||
}
|
||||
|
||||
static void isa_cards(device_slot_interface &device)
|
||||
{
|
||||
device.option_add("vj_sound", JALECO_VJ_ISA16_SOUND);
|
||||
}
|
||||
|
||||
void jaleco_vj_pc_device::superio_config(device_t &device)
|
||||
{
|
||||
// TODO: This should be a Winbond W83877F Super I/O
|
||||
fdc37c93x_device &fdc = downcast<fdc37c93x_device &>(device);
|
||||
fdc.set_sysopt_pin(1);
|
||||
fdc.gp20_reset().set_inputline(m_maincpu, INPUT_LINE_RESET);
|
||||
fdc.gp25_gatea20().set_inputline(m_maincpu, INPUT_LINE_A20);
|
||||
fdc.irq1().set(*this, "pci:07.0", FUNC(i82371sb_isa_device::pc_irq1_w));
|
||||
fdc.irq8().set(*this, "pci:07.0", FUNC(i82371sb_isa_device::pc_irq8n_w));
|
||||
fdc.txd1().set(*this, "serport0", FUNC(rs232_port_device::write_txd));
|
||||
fdc.ndtr1().set(*this, "serport0", FUNC(rs232_port_device::write_dtr));
|
||||
fdc.nrts1().set(*this, "serport0", FUNC(rs232_port_device::write_rts));
|
||||
fdc.txd2().set(*this, "serport1", FUNC(rs232_port_device::write_txd));
|
||||
fdc.ndtr2().set(*this, "serport1", FUNC(rs232_port_device::write_dtr));
|
||||
fdc.nrts2().set(*this, "serport1", FUNC(rs232_port_device::write_rts));
|
||||
}
|
||||
|
||||
void jaleco_vj_pc_device::sound_config(device_t &device)
|
||||
{
|
||||
jaleco_vj_isa16_sound_device &sound = downcast<jaleco_vj_isa16_sound_device &>(device);
|
||||
sound.set_steppingstage_mode(m_is_steppingstage);
|
||||
sound.add_route(0, *this, 1.0, AUTO_ALLOC_INPUT, 0);
|
||||
sound.add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
|
||||
}
|
||||
|
||||
void jaleco_vj_pc_device::boot_state_w(uint8_t data)
|
||||
{
|
||||
logerror("Boot state %02x\n", data);
|
||||
}
|
||||
|
||||
void jaleco_vj_pc_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
// PCI config IDs pulled from Windows registry
|
||||
PENTIUM(config, m_maincpu, 20'000'000); // TODO: Pentium 60/90mhz? Underclocked for performance reasons
|
||||
m_maincpu->set_irq_acknowledge_callback("pci:07.0:pic8259_master", FUNC(pic8259_device::inta_cb));
|
||||
m_maincpu->smiact().set("pci:00.0", FUNC(i82439hx_host_device::smi_act_w));
|
||||
|
||||
PCI_ROOT(config, "pci", 0);
|
||||
I82439HX(config, "pci:00.0", 0, m_maincpu, 256*1024*1024); // TODO: Should be 0x05851106 VIA VT82C585 Apollo VP,VPX,VPX-97 System Controller
|
||||
|
||||
i82371sb_isa_device &isa(I82371SB_ISA(config, "pci:07.0", 0, m_maincpu));
|
||||
// isa.set_ids(0x05861106, 0x23, 0x060100, 0x00000000); // TODO: Should be VIA VT82C586B, PCI-to-ISA Bridge
|
||||
isa.boot_state_hook().set(FUNC(jaleco_vj_pc_device::boot_state_w));
|
||||
isa.smi().set_inputline(m_maincpu, INPUT_LINE_SMI);
|
||||
|
||||
i82371sb_ide_device &ide(I82371SB_IDE(config, "pci:07.1", 0, m_maincpu));
|
||||
// ide.set_ids(0x05711106, 0x06, 0x01018a, 0x00000000); // TODO: Should be VIA VT82C586B, IDE Controller
|
||||
ide.irq_pri().set("pci:07.0", FUNC(i82371sb_isa_device::pc_irq14_w));
|
||||
ide.irq_sec().set("pci:07.0", FUNC(i82371sb_isa_device::pc_mirq0_w));
|
||||
|
||||
// TODO: pci:07.3 0x30401106 VIA VT83C572, VT86C586/A/B Power Management Controller
|
||||
|
||||
VIRGEDX_PCI(config, "pci:10.0", 0); // TODO: Should actually be pci:0a.0 but it only shows a black screen
|
||||
|
||||
ISA16_SLOT(config, "board4", 0, "pci:07.0:isabus", isa_internal_devices, "fdc37c93x", true).set_option_machine_config("fdc37c93x", [this] (device_t *device) { superio_config(*device); });
|
||||
ISA16_SLOT(config, "isa1", 0, "pci:07.0:isabus", isa_cards, "vj_sound", true).set_option_machine_config("vj_sound", [this] (device_t *device) { sound_config(*device); });
|
||||
ISA16_SLOT(config, "isa2", 0, "pci:07.0:isabus", isa_cards, nullptr, true);
|
||||
ISA16_SLOT(config, "isa3", 0, "pci:07.0:isabus", isa_cards, nullptr, true);
|
||||
|
||||
rs232_port_device& serport0(RS232_PORT(config, "serport0", isa_com, "vj_ups"));
|
||||
serport0.rxd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::rxd1_w));
|
||||
serport0.dcd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndcd1_w));
|
||||
serport0.dsr_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndsr1_w));
|
||||
serport0.ri_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::nri1_w));
|
||||
serport0.cts_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ncts1_w));
|
||||
|
||||
rs232_port_device &serport1(RS232_PORT(config, "serport1", isa_com, nullptr));
|
||||
serport1.rxd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::rxd2_w));
|
||||
serport1.dcd_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndcd2_w));
|
||||
serport1.dsr_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ndsr2_w));
|
||||
serport1.ri_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::nri2_w));
|
||||
serport1.cts_handler().set("board4:fdc37c93x", FUNC(fdc37c93x_device::ncts2_w));
|
||||
}
|
||||
|
||||
ROM_START(jaleco_vj_pc)
|
||||
// TODO: BIOS undumped. Seems like it should be an Award BIOS which won't boot currently.
|
||||
// Placeholder BIOS taken from pcipc
|
||||
ROM_REGION32_LE(0x40000, "pci:07.0", 0) // PC bios
|
||||
ROM_SYSTEM_BIOS(0, "m55ns04", "m55ns04") // Micronics M55HI-Plus with no sound
|
||||
ROMX_LOAD("m55-04ns.rom", 0x20000, 0x20000, CRC(0116b2b0) SHA1(19b0203decfd4396695334517488d488aec3ccde) BAD_DUMP, ROM_BIOS(0))
|
||||
ROM_END
|
||||
|
||||
const tiny_rom_entry *jaleco_vj_pc_device::device_rom_region() const
|
||||
{
|
||||
return ROM_NAME(jaleco_vj_pc);
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(JALECO_VJ_PC, jaleco_vj_pc_device, "jaleco_vj_pc", "Jaleco VJ PC")
|
45
src/mame/jaleco/jaleco_vj_pc.h
Normal file
45
src/mame/jaleco/jaleco_vj_pc.h
Normal file
@ -0,0 +1,45 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
#ifndef MAME_JALECO_JALECO_VJ_PC_H
|
||||
#define MAME_JALECO_JALECO_VJ_PC_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "jaleco_vj_sound.h"
|
||||
|
||||
#include "cpu/i386/i386.h"
|
||||
|
||||
|
||||
class jaleco_vj_pc_device :
|
||||
public device_t,
|
||||
public device_mixer_interface
|
||||
{
|
||||
public:
|
||||
jaleco_vj_pc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void set_steppingstage_mode(bool mode) { m_is_steppingstage = mode; }
|
||||
|
||||
uint16_t response_r(offs_t offset, uint16_t mem_mask = ~0) { return m_sound->response_r(offset, mem_mask); }
|
||||
void comm_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_sound->comm_w(offset, data, mem_mask); }
|
||||
void ymz_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0) { m_sound->ymz_w(offset, data, mem_mask); }
|
||||
|
||||
protected:
|
||||
virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
|
||||
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
|
||||
void superio_config(device_t &device) ATTR_COLD;
|
||||
void sound_config(device_t &device) ATTR_COLD;
|
||||
|
||||
private:
|
||||
void boot_state_w(uint8_t data);
|
||||
|
||||
required_device<pentium_device> m_maincpu;
|
||||
required_device<jaleco_vj_isa16_sound_device> m_sound;
|
||||
bool m_is_steppingstage;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(JALECO_VJ_PC, jaleco_vj_pc_device)
|
||||
|
||||
#endif // MAME_JALECO_JALECO_VJ_PC_H
|
328
src/mame/jaleco/jaleco_vj_sound.cpp
Normal file
328
src/mame/jaleco/jaleco_vj_sound.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
/*
|
||||
ISA card used by VJ
|
||||
Handles sound playback and communication between PC and arcade PCB
|
||||
|
||||
------------------------------------------------------------------
|
||||
| IC26? CN6 |
|
||||
| IC23 IC24 IC25 |
|
||||
| IC27 IC28 IC2x1 |
|
||||
| IC15 IC16 IC17 IC29 IC2x2 |
|
||||
| CN5 IC18 CN4 |
|
||||
| IC9 IC10 IC11 IC19 IC20 IC14 |
|
||||
| X1 IC13 IC6 |
|
||||
| IC1 IC2 IC3 IC4 IC12 IC5 IC7 IC8 |
|
||||
---------------------| |-| |-------------
|
||||
|-----------| |----------------|
|
||||
|
||||
|
||||
CN4 - 34-pin connector for IDC cable (chains to both CN6 on main board and CN1 on subboard)
|
||||
CN5 - 80-pin connector
|
||||
CN6 - 8-pin header, carries 4 channel stereo audio
|
||||
|
||||
IC1, IC2, IC3, IC9, IC10, IC11, IC15, IC16, IC17, IC23, IC24, IC25 - Toshiba TC554001 FL-70 4MBit 512Kx8 SRAM
|
||||
IC4 - ?
|
||||
IC5 - XILINX XC9572
|
||||
IC7 - Texas Instruments HC24(5?)
|
||||
IC6 - Texas Instruments HC244
|
||||
IC12 - XILINX XCS30 PQ240CKN9817 A2014617A 3C
|
||||
IC13 - Motorola 74HCU04A 845UE
|
||||
IC14 - Texas Instruments HC245
|
||||
IC18 - XILINX 17S30PC One-Time Programmable Configuration PROM
|
||||
IC19 - Yamaha YMZ280B-F sound chip
|
||||
IC20 - Yamaha YAC516-M DAC
|
||||
IC2x1 - Unidentified 8-pin chip
|
||||
IC2x2 - Unidentified TO-92 package 3-pin IC
|
||||
IC26 - XILINX 17S30PC One-Time Programmable Configuration PROM
|
||||
IC27 - XILINX XCS30 PQ240CKN9817 A2014617A 3C
|
||||
IC28 - Yamaha YMZ280B-F sound chip
|
||||
IC29 - Yamaha YAC516-M DAC
|
||||
X1 - 16.9344MHz clock
|
||||
|
||||
Audio gets sent to the VJ-98346 4ch amp via 8 pin header (CN6) on ISA card
|
||||
|
||||
|
||||
TODO: Check Stepping Stage
|
||||
VJ and Stepping Stage most likely have different FPGA programs in IC18 and IC26 based on the differences in where
|
||||
each game expects to be able to play certain audio files when loaded into the assigned channels.
|
||||
|
||||
TODO: Main PCB's YMZ should be used for the sound effects
|
||||
Main board PCB's YMZ is used for sound effect channels (0x01, 0x02) but there's no way to differentiate
|
||||
what YMZ chip a write to the YMZ register should go to so just using the two YMZ chips in this driver simplifies
|
||||
the code a lot and also fixes some popping issues that would result from trying to play empty buffers.
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "jaleco_vj_sound.h"
|
||||
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
#define LOG_COMM (1U << 1)
|
||||
#define LOG_SOUND (1U << 2)
|
||||
// #define VERBOSE (LOG_SOUND | LOG_COMM)
|
||||
// #define LOG_OUTPUT_STREAM std::cout
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
|
||||
uint8_t jaleco_vj_isa16_sound_device::comm_r(offs_t offset)
|
||||
{
|
||||
uint8_t r = 0;
|
||||
|
||||
if (offset == 0) {
|
||||
r = m_comm & 0xff;
|
||||
} else if (offset == 1) {
|
||||
r = m_comm >> 8;
|
||||
}
|
||||
|
||||
LOGMASKED(LOG_COMM, "comm_r: %04x\n", r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t jaleco_vj_isa16_sound_device::unk2_r(offs_t offset)
|
||||
{
|
||||
// Usage unknown but it's known that it's a single byte sized register thanks to the
|
||||
// debug GUI output in the vj.exe program used by Stepping 3 Superior.
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_COMM, "unk2_r called!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t jaleco_vj_isa16_sound_device::buffer_status_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
// This will only be checked if there is additional BGM data that can be transferred
|
||||
uint16_t r = m_request_extra_data && !m_receiving_extra_data ? 3 : 0;
|
||||
if (!machine().side_effects_disabled()) {
|
||||
m_is_checking_additional_bgm = true;
|
||||
LOGMASKED(LOG_COMM, "buffer_status_r: %04x\n", r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16_t jaleco_vj_isa16_sound_device::response_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
uint16_t r = m_response;
|
||||
if (!machine().side_effects_disabled()) {
|
||||
m_response = 0;
|
||||
LOGMASKED(LOG_COMM, "response_r: %04x\n", r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::response_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (offset == 0)
|
||||
m_response = (m_response & ~0xff) | (data & 0xff);
|
||||
else if (offset == 1)
|
||||
m_response = (m_response & ~0xff00) | ((data & 0xff) << 8);
|
||||
|
||||
LOGMASKED(LOG_COMM, "response_w: %04x\n", m_response);
|
||||
}
|
||||
|
||||
uint16_t jaleco_vj_isa16_sound_device::target_buffer_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
if (!machine().side_effects_disabled())
|
||||
LOGMASKED(LOG_COMM, "target_buffer_r called!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::target_buffer_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
// 0x01 Game SE
|
||||
// 0x02 Song SE
|
||||
// 0x09 Song BGM Normal
|
||||
// 0x0a Song BGM Woofer
|
||||
// 0x0b Song BGM Normal
|
||||
// 0x0c Song BGM Woofer
|
||||
if (data == 0x0101) {
|
||||
m_target_addr = 0x000000;
|
||||
} else if (data == 0x0202) {
|
||||
m_target_addr = 0x080000;
|
||||
} else if (data == 0x0909) {
|
||||
if (m_is_steppingstage)
|
||||
m_target_addr = 0x900000;
|
||||
else
|
||||
m_target_addr = m_receiving_extra_data ? 0x500000 : 0x400000;
|
||||
} else if (data == 0x0b0b) {
|
||||
if (m_is_steppingstage)
|
||||
m_target_addr = 0x980000;
|
||||
else
|
||||
m_target_addr = m_receiving_extra_data ? 0x500000 : 0x480000;
|
||||
} else if (data == 0x0a0a) {
|
||||
if (m_is_steppingstage)
|
||||
m_target_addr = 0xa00000;
|
||||
else
|
||||
m_target_addr = m_receiving_extra_data ? 0xb00000 : 0xa00000;
|
||||
} else if (data == 0x0c0c) {
|
||||
if (m_is_steppingstage)
|
||||
m_target_addr = 0xa80000;
|
||||
else
|
||||
m_target_addr = m_receiving_extra_data ? 0xb00000 : 0xa80000;
|
||||
}
|
||||
|
||||
if (data == 0 && (m_target_buffer == 0x0101 || m_target_buffer == 0x0202) && m_is_checking_additional_bgm) {
|
||||
// The code used to load additional BGM is run in a separate thread, and it does not check if another file
|
||||
// is being transferred already, so if the code is called too soon then it'll clash with the code to load
|
||||
// the song keysound effects by overwriting the target address.
|
||||
m_request_extra_data = true;
|
||||
}
|
||||
|
||||
m_target_buffer = data;
|
||||
|
||||
LOGMASKED(LOG_COMM, "target_buffer_w: %04x (%08x)\n", data, m_target_addr);
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::sound_data_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
LOGMASKED(LOG_SOUND, "sound_data_w: %08x %04x\n", m_target_addr, data);
|
||||
|
||||
m_ymzram[m_target_addr] = BIT(data, 0, 8);
|
||||
m_ymzram2[m_target_addr] = BIT(data, 8, 8);
|
||||
m_target_addr++;
|
||||
}
|
||||
|
||||
uint16_t jaleco_vj_isa16_sound_device::unkc_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
// unkc_r and unke_r combined seem to do something together but it's unclear.
|
||||
// The values read back are never used, but the number of times unke_r is called before unkc_r is unique for different situations.
|
||||
// no calls to unke_r = writing additional BGM data
|
||||
// 1 call to unke_r = a BGM/sound request that will overwrite the address using the value written to target_buffer_w
|
||||
// 3 calls to unkc_r = preparing the thread that will write additional BGM data
|
||||
// It may be a hack but it's the only unique action performed that can differentiate between the different types of requests.
|
||||
if (!machine().side_effects_disabled()) {
|
||||
LOGMASKED(LOG_COMM, "unkc_r: %d\n", m_unke_read_cnt);
|
||||
|
||||
if (m_unke_read_cnt == 0) {
|
||||
m_request_extra_data = false;
|
||||
m_receiving_extra_data = true;
|
||||
} else {
|
||||
m_receiving_extra_data = false;
|
||||
}
|
||||
|
||||
m_unke_read_cnt = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t jaleco_vj_isa16_sound_device::unke_r(offs_t offset, uint16_t mem_mask)
|
||||
{
|
||||
if (!machine().side_effects_disabled()) {
|
||||
m_unke_read_cnt++;
|
||||
LOGMASKED(LOG_COMM, "unke_r: %d\n", m_unke_read_cnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::comm_w(offs_t offset, uint16_t data, uint16_t mem_mask)
|
||||
{
|
||||
// 0x00XX - "Rewrite" (Skipped)
|
||||
// 0x0100 - NOP?
|
||||
// 0x0101 - Check video ready
|
||||
// 0x0102 - COM_MSTART Start music
|
||||
// 0x0103 - COM_STOP Stop video
|
||||
// 0x0104 - Check music ready
|
||||
// 0x0106 - COM_RESTART (restarts video, Stepping Stage only)
|
||||
// 0x0107 - JSP dongle check (Stepping Stage only)
|
||||
// 0x0165 - COM_INIT
|
||||
// 0x029a - COM_START
|
||||
// 0x03XX - Video load command
|
||||
// 0x07XX - Music load command
|
||||
LOGMASKED(LOG_COMM, "comm_w: %04x\n", data);
|
||||
|
||||
m_comm = data;
|
||||
}
|
||||
|
||||
jaleco_vj_isa16_sound_device::jaleco_vj_isa16_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
|
||||
device_t(mconfig, JALECO_VJ_ISA16_SOUND, tag, owner, clock),
|
||||
device_isa16_card_interface(mconfig, *this),
|
||||
device_mixer_interface(mconfig, *this, 2),
|
||||
m_ymz(*this, "ymz%u", 1),
|
||||
m_ymzram(*this, "ymz_ram"),
|
||||
m_ymzram2(*this, "ymz_ram2"),
|
||||
m_response(0),
|
||||
m_comm(0),
|
||||
m_target_buffer(0),
|
||||
m_target_addr(0),
|
||||
m_unke_read_cnt(0),
|
||||
m_request_extra_data(false),
|
||||
m_receiving_extra_data(false),
|
||||
m_is_checking_additional_bgm(false),
|
||||
m_is_steppingstage(false)
|
||||
{
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::device_add_mconfig(machine_config &config)
|
||||
{
|
||||
// BGM normal
|
||||
YMZ280B(config, m_ymz[0], 16.9344_MHz_XTAL);
|
||||
m_ymz[0]->set_addrmap(0, &jaleco_vj_isa16_sound_device::ymz280b_map);
|
||||
m_ymz[0]->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 0);
|
||||
|
||||
// BGM subwoofer
|
||||
YMZ280B(config, m_ymz[1], 16.9344_MHz_XTAL);
|
||||
m_ymz[1]->set_addrmap(0, &jaleco_vj_isa16_sound_device::ymz280b_map2);
|
||||
m_ymz[1]->add_route(1, *this, 1.0, AUTO_ALLOC_INPUT, 1);
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::device_start()
|
||||
{
|
||||
set_isa_device();
|
||||
|
||||
save_item(NAME(m_response));
|
||||
save_item(NAME(m_comm));
|
||||
save_item(NAME(m_target_buffer));
|
||||
save_item(NAME(m_target_addr));
|
||||
save_item(NAME(m_unke_read_cnt));
|
||||
save_item(NAME(m_request_extra_data));
|
||||
save_item(NAME(m_receiving_extra_data));
|
||||
save_item(NAME(m_is_checking_additional_bgm));
|
||||
save_item(NAME(m_is_steppingstage));
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::device_reset()
|
||||
{
|
||||
m_response = 0;
|
||||
m_comm = 0;
|
||||
m_target_buffer = 0;
|
||||
m_target_addr = 0;
|
||||
m_unke_read_cnt = 0;
|
||||
m_request_extra_data = false;
|
||||
m_receiving_extra_data = false;
|
||||
m_is_checking_additional_bgm = false;
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::ymz280b_map(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xffffff).ram().share(m_ymzram);
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::ymz280b_map2(address_map &map)
|
||||
{
|
||||
map(0x000000, 0xffffff).ram().share(m_ymzram2);
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::io_map(address_map &map)
|
||||
{
|
||||
map(0x00, 0x01).r(FUNC(jaleco_vj_isa16_sound_device::comm_r));
|
||||
map(0x02, 0x02).r(FUNC(jaleco_vj_isa16_sound_device::unk2_r));
|
||||
map(0x04, 0x05).r(FUNC(jaleco_vj_isa16_sound_device::buffer_status_r));
|
||||
map(0x05, 0x06).w(FUNC(jaleco_vj_isa16_sound_device::response_w));
|
||||
map(0x08, 0x09).rw(FUNC(jaleco_vj_isa16_sound_device::target_buffer_r), FUNC(jaleco_vj_isa16_sound_device::target_buffer_w));
|
||||
map(0x0a, 0x0b).w(FUNC(jaleco_vj_isa16_sound_device::sound_data_w));
|
||||
map(0x0c, 0x0d).r(FUNC(jaleco_vj_isa16_sound_device::unkc_r));
|
||||
map(0x0e, 0x0f).r(FUNC(jaleco_vj_isa16_sound_device::unke_r));
|
||||
}
|
||||
|
||||
void jaleco_vj_isa16_sound_device::remap(int space_id, offs_t start, offs_t end)
|
||||
{
|
||||
if (space_id == AS_IO) {
|
||||
m_isa->install_device(0x300, 0x30f, *this, &jaleco_vj_isa16_sound_device::io_map);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_DEVICE_TYPE(JALECO_VJ_ISA16_SOUND, jaleco_vj_isa16_sound_device, "jaleco_vj_sound", "VJSlap ISA Sound Card")
|
76
src/mame/jaleco/jaleco_vj_sound.h
Normal file
76
src/mame/jaleco/jaleco_vj_sound.h
Normal file
@ -0,0 +1,76 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
#ifndef MAME_JALECO_JALECO_VJ_SOUND_H
|
||||
#define MAME_JALECO_JALECO_VJ_SOUND_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bus/isa/isa.h"
|
||||
#include "sound/ymz280b.h"
|
||||
|
||||
|
||||
class jaleco_vj_isa16_sound_device :
|
||||
public device_t,
|
||||
public device_isa16_card_interface,
|
||||
public device_mixer_interface
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
jaleco_vj_isa16_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
void set_steppingstage_mode(bool mode) { m_is_steppingstage = mode; } // TODO: Split this out into a device specific to Stepping Stage
|
||||
|
||||
uint16_t response_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void comm_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
|
||||
void ymz_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0)
|
||||
{
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_ymz[0]->write(offset, BIT(data, 0, 8));
|
||||
if (ACCESSING_BITS_8_15)
|
||||
m_ymz[1]->write(offset, BIT(data, 8, 8));
|
||||
}
|
||||
|
||||
virtual void remap(int space_id, offs_t start, offs_t end) override;
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
|
||||
private:
|
||||
uint8_t comm_r(offs_t offset);
|
||||
uint8_t unk2_r(offs_t offset);
|
||||
uint16_t buffer_status_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void response_w(offs_t offset, uint8_t data);
|
||||
uint16_t target_buffer_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
void target_buffer_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
void sound_data_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
|
||||
uint16_t unkc_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
uint16_t unke_r(offs_t offset, uint16_t mem_mask = ~0);
|
||||
|
||||
void io_map(address_map &map) ATTR_COLD;
|
||||
void ymz280b_map(address_map &map) ATTR_COLD;
|
||||
void ymz280b_map2(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device_array<ymz280b_device, 2> m_ymz;
|
||||
required_shared_ptr<uint8_t> m_ymzram;
|
||||
required_shared_ptr<uint8_t> m_ymzram2;
|
||||
|
||||
uint16_t m_response;
|
||||
uint16_t m_comm;
|
||||
uint16_t m_target_buffer;
|
||||
uint32_t m_target_addr;
|
||||
uint32_t m_unke_read_cnt;
|
||||
bool m_request_extra_data;
|
||||
bool m_receiving_extra_data;
|
||||
bool m_is_checking_additional_bgm;
|
||||
|
||||
bool m_is_steppingstage;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(JALECO_VJ_ISA16_SOUND, jaleco_vj_isa16_sound_device)
|
||||
|
||||
#endif // MAME_JALECO_JALECO_VJ_SOUND_H
|
44
src/mame/jaleco/jaleco_vj_ups.cpp
Normal file
44
src/mame/jaleco/jaleco_vj_ups.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
/*
|
||||
* Densei UPS for VJ
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "jaleco_vj_ups.h"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class jaleco_vj_ups_device : public device_t, public device_rs232_port_interface
|
||||
{
|
||||
public:
|
||||
jaleco_vj_ups_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
protected:
|
||||
virtual void device_start() override ATTR_COLD;
|
||||
virtual void device_reset() override ATTR_COLD;
|
||||
};
|
||||
|
||||
|
||||
jaleco_vj_ups_device::jaleco_vj_ups_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, JALECO_VJ_UPS, tag, owner, clock)
|
||||
, device_rs232_port_interface(mconfig, *this)
|
||||
{
|
||||
}
|
||||
|
||||
void jaleco_vj_ups_device::device_start()
|
||||
{
|
||||
}
|
||||
|
||||
void jaleco_vj_ups_device::device_reset()
|
||||
{
|
||||
// TODO: provide a way for the user to change the status?
|
||||
output_cts(1); // line power down
|
||||
output_dsr(1); // line shutdown
|
||||
output_dcd(0); // line low battery
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
DEFINE_DEVICE_TYPE_PRIVATE(JALECO_VJ_UPS, device_rs232_port_interface, jaleco_vj_ups_device, "rs232_densei_ups", "RS232 Densei UPS")
|
13
src/mame/jaleco/jaleco_vj_ups.h
Normal file
13
src/mame/jaleco/jaleco_vj_ups.h
Normal file
@ -0,0 +1,13 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:windyfairy
|
||||
#ifndef MAME_JALECO_JALECO_VJ_UPS_H
|
||||
#define MAME_JALECO_JALECO_VJ_UPS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "bus/rs232/rs232.h"
|
||||
|
||||
|
||||
DECLARE_DEVICE_TYPE(JALECO_VJ_UPS, device_rs232_port_interface)
|
||||
|
||||
#endif // MAME_JALECO_JALECO_VJ_UPS_H
|
@ -523,11 +523,6 @@ void stepstag_state::stepstag_b00000_w(u16 data)
|
||||
vj_upload_fini = false;
|
||||
}
|
||||
|
||||
void stepstag_state::stepstag_main2pc_w(u16 data)
|
||||
{
|
||||
popmessage("cmd @ pc: 0x%x\n", data);
|
||||
}
|
||||
|
||||
u16 stepstag_state::stepstag_sprite_status_status_r()
|
||||
{
|
||||
// Guessed based on usage, but this is checked to make sure
|
||||
@ -540,11 +535,6 @@ u16 stepstag_state::unknown_read_0xffff00()
|
||||
return machine().rand();
|
||||
}
|
||||
|
||||
u16 stepstag_state::stepstag_pc2main_r()
|
||||
{
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
void stepstag_state::stepstag_soundlatch_word_w(u16 data)
|
||||
{
|
||||
m_soundlatch->write(data);
|
||||
@ -726,7 +716,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
|
||||
logerror("Mode register 0\n");
|
||||
logerror("\tencode mode control %02x ", encode_mode_control);
|
||||
switch(encode_mode_control)
|
||||
switch (encode_mode_control)
|
||||
{
|
||||
case 0b00: logerror("NTSC\n"); break;
|
||||
case 0b01: logerror("PAL (B, D, G, H, I)\n"); break;
|
||||
@ -737,7 +727,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
logerror("\tpedestal control %02x %s\n", pedestal_control, pedestal_control ? "on" : "off");
|
||||
|
||||
logerror("\tluminance filter control %02x ", luminance_filter_control);
|
||||
switch(luminance_filter_control)
|
||||
switch (luminance_filter_control)
|
||||
{
|
||||
case 0b00: logerror("Low pass filter (A)\n"); break;
|
||||
case 0b01: logerror("Notch filter\n"); break;
|
||||
@ -762,7 +752,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
logerror("Mode register 1\n");
|
||||
logerror("\tinterlaced mode control %02x %s\n", interlaced_mode_control, interlaced_mode_control ? "non-interlaced" : "interlaced");
|
||||
logerror("\tclosed captioning field control %02x ", closed_captioning_field_control);
|
||||
switch(closed_captioning_field_control)
|
||||
switch (closed_captioning_field_control)
|
||||
{
|
||||
case 0b00: logerror("No data out\n"); break;
|
||||
case 0b01: logerror("Odd field only\n"); break;
|
||||
@ -798,7 +788,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
logerror("\tblank control %02x %s\n", blank_control, blank_control ? "disable" : "enable");
|
||||
|
||||
logerror("\tluma delay %02x ", luma_delay_control);
|
||||
switch(luma_delay_control)
|
||||
switch (luma_delay_control)
|
||||
{
|
||||
case 0b00: logerror("0ns delay\n"); break;
|
||||
case 0b01: logerror("74ns delay\n"); break;
|
||||
@ -819,7 +809,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
|
||||
logerror("Timing register 1\n");
|
||||
auto d = 1;
|
||||
switch(hsync_width)
|
||||
switch (hsync_width)
|
||||
{
|
||||
case 0b00: d = 1; break;
|
||||
case 0b01: d = 4; break;
|
||||
@ -827,7 +817,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
case 0b11: d = 128; break;
|
||||
}
|
||||
logerror("\thsync width %02x %d\n", hsync_width, d);
|
||||
switch(hsync_to_vsync_delay)
|
||||
switch (hsync_to_vsync_delay)
|
||||
{
|
||||
case 0b00: d = 0; break;
|
||||
case 0b01: d = 4; break;
|
||||
@ -852,7 +842,7 @@ void stepstag_state::adv7176a_w(u16 data)
|
||||
logerror("Mode register 2\n");
|
||||
logerror("\tsquare pixel control %02x %s\n", square_pixel_mode_control, square_pixel_mode_control ? "enable" : "disable");
|
||||
logerror("\tgenlock control %02x ", genlock_control);
|
||||
switch(genlock_control)
|
||||
switch (genlock_control)
|
||||
{
|
||||
case 0b00: case 0b10:
|
||||
logerror("Disable genlock\n"); break;
|
||||
@ -918,12 +908,12 @@ void stepstag_state::stepstag_map(address_map &map)
|
||||
map(0xa10000, 0xa10001).portr("RHYTHM").w(FUNC(stepstag_state::stepstag_step_leds_w)); // I/O
|
||||
map(0xa20000, 0xa20001).nopr().w(FUNC(stepstag_state::stepstag_button_leds_w)); // I/O
|
||||
map(0xa30000, 0xa30001).r(FUNC(stepstag_state::stepstag_soundvolume_r)).nopw(); // Sound Volume
|
||||
map(0xa42000, 0xa42001).r(FUNC(stepstag_state::stepstag_pc2main_r));
|
||||
map(0xa42000, 0xa42001).r(m_jaleco_vj_pc, FUNC(jaleco_vj_pc_device::response_r));
|
||||
map(0xa44000, 0xa44001).nopr(); // watchdog
|
||||
map(0xa48000, 0xa48001).w(FUNC(stepstag_state::stepstag_main2pc_w)); // PC Comm
|
||||
map(0xa48000, 0xa48001).w(m_jaleco_vj_pc, FUNC(jaleco_vj_pc_device::comm_w));
|
||||
// map(0xa4c000, 0xa4c001).noprw(); // Related to 0xa60000
|
||||
map(0xa50000, 0xa50001).r(m_soundlatch, FUNC(generic_latch_16_device::read)).w(FUNC(stepstag_state::stepstag_soundlatch_word_w));
|
||||
map(0xa60000, 0xa60003).w("ymz", FUNC(ymz280b_device::write)).umask16(0x00ff); // Sound
|
||||
map(0xa60000, 0xa60003).w(m_jaleco_vj_pc, FUNC(jaleco_vj_pc_device::ymz_w));
|
||||
|
||||
map(0xb00000, 0xb00001).w(FUNC(stepstag_state::stepstag_b00000_w)); // init xilinx uploading??
|
||||
map(0xb20000, 0xb20001).w(FUNC(stepstag_state::stepstag_b20000_w)); // 98343 interface board xilinx uploading?
|
||||
@ -974,9 +964,9 @@ void stepstag_state::stepstag_sub_map(address_map &map)
|
||||
// map(0xac0000, 0xac0001).nopw(); // cleared at boot
|
||||
|
||||
// The code for PC comms fully exists in VJ but it doesn't appear to ever be called
|
||||
// map(0xa42000, 0xa42001).r(":jaleco_vj_pc:isa1:jaleco_vj_sound", FUNC(jaleco_vj_isa16_sound_device::response_r));
|
||||
// map(0xa44000, 0xa44001).nopr(); // watchdog
|
||||
// map(0xa48000, 0xa48001).w(":jaleco_vj_pc:isa1:jaleco_vj_sound", FUNC(jaleco_vj_isa16_sound_device::comm_w));
|
||||
//map(0xa42000, 0xa42001).r(m_jaleco_vj_pc, FUNC(jaleco_vj_pc_device::response_r));
|
||||
//map(0xa44000, 0xa44001).nopr(); // watchdog
|
||||
//map(0xa48000, 0xa48001).w(m_jaleco_vj_pc, FUNC(jaleco_vj_pc_device::comm_w));
|
||||
|
||||
map(0xb00000, 0xb00001).rw(m_soundlatch, FUNC(generic_latch_16_device::read), FUNC(generic_latch_16_device::write));
|
||||
|
||||
@ -1762,12 +1752,6 @@ void tetrisp2_state::init_rockn3()
|
||||
m_rockn_protectdata = 4;
|
||||
}
|
||||
|
||||
void stepstag_state::init_stepstag()
|
||||
{
|
||||
init_rockn_timer(); // used
|
||||
m_rockn_protectdata = 1; // unused?
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(tetrisp2_state::field_irq_w)
|
||||
{
|
||||
// irq1 is valid on all games but tetrisp2, but always masked by SR?
|
||||
@ -2137,9 +2121,10 @@ void stepstag_state::stepstag(machine_config &config)
|
||||
|
||||
GENERIC_LATCH_16(config, m_soundlatch);
|
||||
|
||||
ymz280b_device &ymz(YMZ280B(config, "ymz", subxtal/3)); // unknown
|
||||
ymz.add_route(0, "lspeaker", 1.0);
|
||||
ymz.add_route(1, "rspeaker", 1.0);
|
||||
JALECO_VJ_PC(config, m_jaleco_vj_pc, 0);
|
||||
m_jaleco_vj_pc->set_steppingstage_mode(true);
|
||||
m_jaleco_vj_pc->add_route(0, "lspeaker", 1.0);
|
||||
m_jaleco_vj_pc->add_route(1, "rspeaker", 1.0);
|
||||
}
|
||||
|
||||
void stepstag_state::vjdash(machine_config &config) // 4 Screens
|
||||
@ -2224,9 +2209,10 @@ void stepstag_state::vjdash(machine_config &config) // 4 Screens
|
||||
|
||||
GENERIC_LATCH_16(config, m_soundlatch);
|
||||
|
||||
ymz280b_device &ymz(YMZ280B(config, "ymz", subxtal/3)); // unknown
|
||||
ymz.add_route(0, "lspeaker", 1.0);
|
||||
ymz.add_route(1, "rspeaker", 1.0);
|
||||
JALECO_VJ_PC(config, m_jaleco_vj_pc, 0);
|
||||
m_jaleco_vj_pc->set_steppingstage_mode(false);
|
||||
m_jaleco_vj_pc->add_route(0, "lspeaker", 1.0);
|
||||
m_jaleco_vj_pc->add_route(1, "rspeaker", 1.0);
|
||||
}
|
||||
|
||||
void stepstag_state::machine_start()
|
||||
@ -3251,9 +3237,6 @@ ROM_START( vjdasha )
|
||||
ROM_REGION( 0x010000, "xilinx", 0 ) // XILINX CPLD
|
||||
ROM_LOAD( "15c.ic49", 0x000000, 38807, CRC(60d50907) SHA1(c5a837b3105ba15fcec103154c8c4d00924974e1) )
|
||||
|
||||
ROM_REGION( 0x400000, "ymz", ROMREGION_ERASE ) // Samples
|
||||
ROM_LOAD( "vjdash-sound", 0x000000, 0x400000, NO_DUMP )
|
||||
|
||||
DISK_REGION( "jaleco_vj_pc:pci:07.1:ide1:0:hdd:image" )
|
||||
DISK_IMAGE( "vj_ver1", 0, SHA1(bf5c70fba13186854ff0b7eafab07dd527aac663) BAD_DUMP )
|
||||
ROM_END
|
||||
@ -3304,9 +3287,6 @@ ROM_START( stepstag )
|
||||
ROM_REGION( 0x400000, "gfx3", ROMREGION_ERASE ) /* 16x16x8 (Rotation) */
|
||||
ROM_LOAD( "stepstag_rott", 0x000000, 0x400000, NO_DUMP )
|
||||
|
||||
ROM_REGION( 0x400000, "ymz", ROMREGION_ERASE ) // Samples
|
||||
ROM_LOAD( "stepstag-sound", 0x000000, 0x400000, NO_DUMP )
|
||||
|
||||
DISK_REGION( "jaleco_vj_pc:pci:07.1:ide1:0:hdd:image" )
|
||||
DISK_IMAGE( "stepstag", 0, NO_DUMP )
|
||||
ROM_END
|
||||
@ -3357,9 +3337,6 @@ ROM_START( step3 )
|
||||
|
||||
ROM_REGION( 0x400000, "gfx3", ROMREGION_ERASE ) /* 16x16x8 (Rotation) */
|
||||
|
||||
ROM_REGION( 0x400000, "ymz", ROMREGION_ERASE ) /* Samples */
|
||||
ROM_LOAD( "step3-sound", 0x000000, 0x400000, NO_DUMP )
|
||||
|
||||
DISK_REGION( "jaleco_vj_pc:pci:07.1:ide1:0:hdd:image" )
|
||||
DISK_IMAGE( "step3", 0, SHA1(926a32998c837f7ba45d07db243c43c1f9d46d6a) )
|
||||
ROM_END
|
||||
@ -3399,5 +3376,5 @@ GAME( 1999, vjdasha, vjslap, vjdash, vjdash, stepstag_state, empty_init
|
||||
// - Stepping Stage <- the original Game
|
||||
// - Stepping Stage 2 Supreme
|
||||
// Dumped (partially):
|
||||
GAME( 1999, stepstag, 0, stepstag, stepstag, stepstag_state, init_stepstag, ROT0, "Jaleco", "Stepping Stage Special", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
|
||||
GAME( 1999, step3, 0, stepstag, stepstag, stepstag_state, init_stepstag, ROT0, "Jaleco", "Stepping 3 Superior", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
|
||||
GAME( 1999, stepstag, 0, stepstag, stepstag, stepstag_state, empty_init, ROT0, "Jaleco", "Stepping Stage Special", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
|
||||
GAME( 1999, step3, 0, stepstag, stepstag, stepstag_state, empty_init, ROT0, "Jaleco", "Stepping 3 Superior", MACHINE_NO_SOUND | MACHINE_NOT_WORKING )
|
||||
|
@ -6,6 +6,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "jaleco_ms32_sysctrl.h"
|
||||
#include "jaleco_vj_pc.h"
|
||||
#include "ms32_sprite.h"
|
||||
|
||||
#include "machine/gen_latch.h"
|
||||
@ -222,6 +223,7 @@ public:
|
||||
, m_vj_paletteram_m(*this, "paletteram2")
|
||||
, m_vj_paletteram_r(*this, "paletteram3")
|
||||
, m_soundlatch(*this, "soundlatch")
|
||||
, m_jaleco_vj_pc(*this, "jaleco_vj_pc")
|
||||
, m_soundvr(*this, "SOUND_VR%u", 1)
|
||||
, m_rscreen(*this, "rscreen")
|
||||
{ }
|
||||
@ -229,8 +231,6 @@ public:
|
||||
void stepstag(machine_config &config);
|
||||
void vjdash(machine_config &config);
|
||||
|
||||
void init_stepstag();
|
||||
|
||||
DECLARE_VIDEO_START(stepstag);
|
||||
|
||||
protected:
|
||||
@ -243,10 +243,8 @@ private:
|
||||
bool vj_upload_fini = false;
|
||||
void stepstag_b00000_w(u16 data);
|
||||
void stepstag_b20000_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void stepstag_main2pc_w(u16 data);
|
||||
u16 stepstag_sprite_status_status_r();
|
||||
u16 unknown_read_0xffff00();
|
||||
u16 stepstag_pc2main_r();
|
||||
void stepstag_soundlatch_word_w(u16 data);
|
||||
void stepstag_neon_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
void stepstag_step_leds_w(offs_t offset, u16 data, u16 mem_mask = ~0);
|
||||
@ -295,6 +293,7 @@ private:
|
||||
optional_shared_ptr<u16> m_vj_paletteram_m;
|
||||
optional_shared_ptr<u16> m_vj_paletteram_r;
|
||||
required_device<generic_latch_16_device> m_soundlatch;
|
||||
required_device<jaleco_vj_pc_device> m_jaleco_vj_pc;
|
||||
optional_ioport_array<2> m_soundvr;
|
||||
required_device<screen_device> m_rscreen;
|
||||
|
||||
|
@ -29,14 +29,14 @@ cha1 $dc81
|
||||
cha2 $cca8
|
||||
cha3 $10d8
|
||||
|
||||
2 color proms for the output. will get those dumped as well.
|
||||
2 color PROMs for the output. will get those dumped as well.
|
||||
|
||||
|
||||
*****************************************************************************************************************************/
|
||||
|
||||
|
||||
#include "emu.h"
|
||||
#include "tnzs.h"
|
||||
#include "tnzs_video.h"
|
||||
|
||||
#include "cpu/z80/z80.h"
|
||||
#include "sound/ay8910.h"
|
||||
@ -228,8 +228,8 @@ void cchance_state::cchance(machine_config &config)
|
||||
m_maincpu->set_vblank_int("screen", FUNC(cchance_state::irq0_line_hold));
|
||||
|
||||
X1_001(config, m_spritegen, 12_MHz_XTAL, m_palette, gfx_cchance);
|
||||
m_spritegen->set_fg_yoffsets( -0x12, 0x0e );
|
||||
m_spritegen->set_bg_yoffsets( 0x1, -0x1 );
|
||||
m_spritegen->set_fg_yoffsets(-0x12, 0x0e);
|
||||
m_spritegen->set_bg_yoffsets(0x1, -0x1);
|
||||
|
||||
// video hardware
|
||||
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
|
||||
@ -261,7 +261,7 @@ ROM_START( cchance )
|
||||
ROM_LOAD("chance-cccha2.bin", 0x10000, 0x10000, CRC(fa5ccf5b) SHA1(21957a6a7b88c315d1fbb82e98a924a637a28397) )
|
||||
ROM_LOAD("chance-cccha3.bin", 0x00000, 0x10000, CRC(2a2979c9) SHA1(5036313e219ec561fa6753f0db6bb28c6fc97963) )
|
||||
|
||||
ROM_REGION( 0x0400, "proms", 0 ) /* color proms */
|
||||
ROM_REGION( 0x0400, "proms", 0 ) // color PROMs
|
||||
ROM_LOAD( "prom1", 0x0000, 0x0200, NO_DUMP )
|
||||
ROM_LOAD( "prom2", 0x0200, 0x0200, NO_DUMP )
|
||||
ROM_END
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,305 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, Mirko Buffoni, Takahiro Nogi
|
||||
#ifndef MAME_TAITO_TNZS_H
|
||||
#define MAME_TAITO_TNZS_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "machine/gen_latch.h"
|
||||
#include "machine/upd4701.h"
|
||||
#include "sound/dac.h"
|
||||
#include "sound/samples.h"
|
||||
#include "video/x1_001.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
class tnzs_video_state_base : public driver_device
|
||||
{
|
||||
protected:
|
||||
tnzs_video_state_base(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_spritegen(*this, "spritegen")
|
||||
, m_palette(*this, "palette")
|
||||
, m_screen(*this, "screen")
|
||||
{
|
||||
}
|
||||
|
||||
void prompalette(palette_device &palette) const;
|
||||
uint32_t screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank_tnzs);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<x1_001_device> m_spritegen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<screen_device> m_screen;
|
||||
};
|
||||
|
||||
|
||||
class tnzs_base_state : public tnzs_video_state_base
|
||||
{
|
||||
protected:
|
||||
tnzs_base_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_video_state_base(mconfig, type, tag)
|
||||
, m_subcpu(*this, "sub")
|
||||
, m_subbank(*this, "subbank")
|
||||
, m_ramromview(*this, "ramrom")
|
||||
{ }
|
||||
|
||||
void tnzs_base(machine_config &config) ATTR_COLD;
|
||||
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
|
||||
virtual void bankswitch1_w(uint8_t data);
|
||||
|
||||
void ramrom_bankswitch_w(uint8_t data);
|
||||
|
||||
void prompal_main_map(address_map &map) ATTR_COLD;
|
||||
void rampal_main_map(address_map &map) ATTR_COLD;
|
||||
|
||||
void base_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
// devices
|
||||
required_device<cpu_device> m_subcpu;
|
||||
required_memory_bank m_subbank;
|
||||
|
||||
private:
|
||||
memory_view m_ramromview;
|
||||
};
|
||||
|
||||
|
||||
class tnzs_mcu_state : public tnzs_base_state
|
||||
{
|
||||
public:
|
||||
tnzs_mcu_state(const machine_config &mconfig, device_type type, const char *tag, bool lockout_level)
|
||||
: tnzs_base_state(mconfig, type, tag)
|
||||
, m_mcu(*this, "mcu")
|
||||
, m_upd4701(*this, "upd4701")
|
||||
, m_in0(*this, "IN0")
|
||||
, m_in1(*this, "IN1")
|
||||
, m_in2(*this, "IN2")
|
||||
, m_input_select(0)
|
||||
, m_lockout_level(lockout_level)
|
||||
{ }
|
||||
|
||||
void tnzs(machine_config &config) ATTR_COLD;
|
||||
|
||||
protected:
|
||||
virtual void bankswitch1_w(uint8_t data) override;
|
||||
|
||||
uint8_t mcu_port1_r();
|
||||
void mcu_port2_w(uint8_t data);
|
||||
uint8_t mcu_r(offs_t offset);
|
||||
void mcu_w(offs_t offset, uint8_t data);
|
||||
|
||||
uint8_t analog_r(offs_t offset);
|
||||
|
||||
void tnzs_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device<upi41_cpu_device> m_mcu;
|
||||
optional_device<upd4701_device> m_upd4701;
|
||||
|
||||
required_ioport m_in0;
|
||||
required_ioport m_in1;
|
||||
required_ioport m_in2;
|
||||
|
||||
int m_input_select = 0;
|
||||
bool m_lockout_level = false;
|
||||
};
|
||||
|
||||
class tnzs_state : public tnzs_mcu_state
|
||||
{
|
||||
public:
|
||||
tnzs_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_mcu_state(mconfig, type, tag, true)
|
||||
{ }
|
||||
};
|
||||
|
||||
class extrmatn_state : public tnzs_mcu_state
|
||||
{
|
||||
public:
|
||||
extrmatn_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_mcu_state(mconfig, type, tag, false)
|
||||
{ }
|
||||
|
||||
void extrmatn(machine_config &config) ATTR_COLD;
|
||||
void plumppop(machine_config &config) ATTR_COLD;
|
||||
};
|
||||
|
||||
class arknoid2_state : public extrmatn_state
|
||||
{
|
||||
public:
|
||||
arknoid2_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: extrmatn_state(mconfig, type, tag)
|
||||
, m_coin1(*this, "COIN1")
|
||||
, m_coin2(*this, "COIN2")
|
||||
, m_in0(*this, "IN0")
|
||||
, m_in1(*this, "IN1")
|
||||
, m_in2(*this, "IN2")
|
||||
{ }
|
||||
|
||||
void arknoid2(machine_config &config) ATTR_COLD;
|
||||
|
||||
private:
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
virtual void machine_reset() override ATTR_COLD;
|
||||
|
||||
virtual void bankswitch1_w(uint8_t data) override;
|
||||
|
||||
uint8_t mcu_r(offs_t offset);
|
||||
void mcu_w(offs_t offset, uint8_t data);
|
||||
INTERRUPT_GEN_MEMBER(mcu_interrupt);
|
||||
|
||||
void arknoid2_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
void mcu_reset();
|
||||
|
||||
required_ioport m_coin1;
|
||||
required_ioport m_coin2;
|
||||
required_ioport m_in0;
|
||||
required_ioport m_in1;
|
||||
required_ioport m_in2;
|
||||
|
||||
int m_mcu_initializing = 0;
|
||||
int m_mcu_coinage_init = 0;
|
||||
int m_mcu_command = 0;
|
||||
int m_mcu_readcredits = 0;
|
||||
int m_mcu_reportcoin = 0;
|
||||
int m_insertcoin = 0;
|
||||
uint8_t m_mcu_coinage[4]{};
|
||||
uint8_t m_mcu_coins_a = 0;
|
||||
uint8_t m_mcu_coins_b = 0;
|
||||
uint8_t m_mcu_credits = 0;
|
||||
|
||||
void mcu_handle_coins(int coin);
|
||||
};
|
||||
|
||||
class kageki_state : public tnzs_base_state
|
||||
{
|
||||
public:
|
||||
kageki_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_base_state(mconfig, type, tag)
|
||||
, m_samples(*this, "samples")
|
||||
, m_dswa(*this, "DSWA")
|
||||
, m_dswb(*this, "DSWB")
|
||||
, m_csport_sel(0)
|
||||
{ }
|
||||
|
||||
void kageki(machine_config &config) ATTR_COLD;
|
||||
|
||||
void init_kageki() ATTR_COLD;
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
virtual void machine_reset() override ATTR_COLD;
|
||||
|
||||
private:
|
||||
static constexpr unsigned MAX_SAMPLES = 0x2f;
|
||||
|
||||
virtual void bankswitch1_w(uint8_t data) override;
|
||||
|
||||
uint8_t csport_r();
|
||||
void csport_w(uint8_t data);
|
||||
|
||||
SAMPLES_START_CB_MEMBER(init_samples);
|
||||
|
||||
void kageki_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device<samples_device> m_samples;
|
||||
|
||||
required_ioport m_dswa;
|
||||
required_ioport m_dswb;
|
||||
|
||||
// sound-related
|
||||
std::unique_ptr<int16_t[]> m_sampledata[MAX_SAMPLES];
|
||||
int m_samplesize[MAX_SAMPLES]{};
|
||||
|
||||
int m_csport_sel = 0;
|
||||
};
|
||||
|
||||
class jpopnics_state : public tnzs_base_state
|
||||
{
|
||||
public:
|
||||
jpopnics_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_base_state(mconfig, type, tag)
|
||||
, m_upd4701(*this, "upd4701")
|
||||
{ }
|
||||
|
||||
void jpopnics(machine_config &config) ATTR_COLD;
|
||||
|
||||
private:
|
||||
void subbankswitch_w(uint8_t data);
|
||||
|
||||
void jpopnics_main_map(address_map &map) ATTR_COLD;
|
||||
void jpopnics_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device<upd4701_device> m_upd4701;
|
||||
};
|
||||
|
||||
class insectx_state : public tnzs_base_state
|
||||
{
|
||||
public:
|
||||
insectx_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_base_state(mconfig, type, tag)
|
||||
{ }
|
||||
|
||||
void insectx(machine_config &config) ATTR_COLD;
|
||||
|
||||
private:
|
||||
virtual void bankswitch1_w(uint8_t data) override;
|
||||
void insectx_sub_map(address_map &map) ATTR_COLD;
|
||||
};
|
||||
|
||||
class tnzsb_state : public tnzs_base_state
|
||||
{
|
||||
public:
|
||||
tnzsb_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzs_base_state(mconfig, type, tag)
|
||||
, m_audiocpu(*this, "audiocpu")
|
||||
, m_soundlatch(*this, "soundlatch")
|
||||
{ }
|
||||
|
||||
void tnzsb(machine_config &config) ATTR_COLD;
|
||||
|
||||
protected:
|
||||
DECLARE_WRITE_LINE_MEMBER(ym2203_irqhandler);
|
||||
|
||||
void sound_command_w(uint8_t data);
|
||||
|
||||
virtual void bankswitch1_w(uint8_t data) override;
|
||||
|
||||
void tnzsb_base_sub_map(address_map &map) ATTR_COLD;
|
||||
void tnzsb_sub_map(address_map &map) ATTR_COLD;
|
||||
void tnzsb_cpu2_map(address_map &map) ATTR_COLD;
|
||||
void tnzsb_io_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_device<cpu_device> m_audiocpu;
|
||||
required_device<generic_latch_8_device> m_soundlatch;
|
||||
};
|
||||
|
||||
class kabukiz_state : public tnzsb_state
|
||||
{
|
||||
public:
|
||||
kabukiz_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: tnzsb_state(mconfig, type, tag)
|
||||
, m_audiobank(*this, "audiobank")
|
||||
{ }
|
||||
|
||||
void kabukiz(machine_config &config) ATTR_COLD;
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override ATTR_COLD;
|
||||
|
||||
private:
|
||||
void sound_bank_w(uint8_t data);
|
||||
|
||||
void kabukiz_cpu2_map(address_map &map) ATTR_COLD;
|
||||
void kabukiz_sub_map(address_map &map) ATTR_COLD;
|
||||
|
||||
required_memory_bank m_audiobank;
|
||||
};
|
||||
|
||||
#endif // MAME_TAITO_TNZS_H
|
@ -1,495 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, Mirko Buffoni, Takahiro Nogi,Stephane Humbert
|
||||
/***************************************************************************
|
||||
|
||||
machine.c
|
||||
|
||||
Functions to emulate general aspects of the machine (RAM, ROM, interrupts,
|
||||
I/O ports)
|
||||
|
||||
The I8742 MCU takes care of handling the coin inputs and the tilt switch.
|
||||
To simulate this, we read the status in the interrupt handler for the main
|
||||
CPU and update the counters appropriately. We also must take care of
|
||||
handling the coin/credit settings ourselves.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/mcs48/mcs48.h"
|
||||
#include "tnzs.h"
|
||||
|
||||
uint8_t tnzs_mcu_state::mcu_r(offs_t offset)
|
||||
{
|
||||
uint8_t data = m_mcu->upi41_master_r(offset & 1);
|
||||
m_subcpu->yield();
|
||||
|
||||
// logerror("%s: read %02x from mcu $c00%01x\n", m_maincpu->pcbase(), data, offset);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void tnzs_mcu_state::mcu_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
// logerror("%s: write %02x to mcu $c00%01x\n", m_maincpu->pcbase(), data, offset);
|
||||
|
||||
m_mcu->upi41_master_w(offset & 1, data);
|
||||
}
|
||||
|
||||
uint8_t tnzs_mcu_state::mcu_port1_r()
|
||||
{
|
||||
int data = 0;
|
||||
|
||||
switch (m_input_select)
|
||||
{
|
||||
case 0x0a: data = m_in2->read(); break;
|
||||
case 0x0c: data = m_in0->read(); break;
|
||||
case 0x0d: data = m_in1->read(); break;
|
||||
default: data = 0xff; break;
|
||||
}
|
||||
|
||||
// logerror("%s: Read %02x from port 1\n", m_maincpu->pcbase(), data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void tnzs_mcu_state::mcu_port2_w(uint8_t data)
|
||||
{
|
||||
machine().bookkeeping().coin_lockout_w(0, (data & 0x40) != 0 ? m_lockout_level : !m_lockout_level);
|
||||
machine().bookkeeping().coin_lockout_w(1, (data & 0x80) != 0 ? m_lockout_level : !m_lockout_level);
|
||||
machine().bookkeeping().coin_counter_w(0, (~data & 0x10));
|
||||
machine().bookkeeping().coin_counter_w(1, (~data & 0x20));
|
||||
|
||||
m_input_select = data & 0xf;
|
||||
}
|
||||
|
||||
uint8_t tnzs_mcu_state::analog_r(offs_t offset)
|
||||
{
|
||||
return m_upd4701.found() ? m_upd4701->read_xy(offset) : 0;
|
||||
}
|
||||
|
||||
void arknoid2_state::mcu_reset()
|
||||
{
|
||||
m_mcu_initializing = 3;
|
||||
m_mcu_coinage_init = 0;
|
||||
m_mcu_coinage[0] = 1;
|
||||
m_mcu_coinage[1] = 1;
|
||||
m_mcu_coinage[2] = 1;
|
||||
m_mcu_coinage[3] = 1;
|
||||
m_mcu_coins_a = 0;
|
||||
m_mcu_coins_b = 0;
|
||||
m_mcu_credits = 0;
|
||||
m_mcu_reportcoin = 0;
|
||||
m_mcu_command = 0;
|
||||
}
|
||||
|
||||
void arknoid2_state::mcu_handle_coins( int coin )
|
||||
{
|
||||
/* The coin inputs and coin counters are managed by the i8742 mcu. */
|
||||
/* Here we simulate it. */
|
||||
/* Credits are limited to 9, so more coins should be rejected */
|
||||
/* Coin/Play settings must also be taken into consideration */
|
||||
|
||||
if (coin & 0x08) /* tilt */
|
||||
m_mcu_reportcoin = coin;
|
||||
else if (coin && coin != m_insertcoin)
|
||||
{
|
||||
if (coin & 0x01) /* coin A */
|
||||
{
|
||||
// logerror("Coin dropped into slot A\n");
|
||||
machine().bookkeeping().coin_counter_w(0,1); machine().bookkeeping().coin_counter_w(0,0); /* Count slot A */
|
||||
m_mcu_coins_a++;
|
||||
if (m_mcu_coins_a >= m_mcu_coinage[0])
|
||||
{
|
||||
m_mcu_coins_a -= m_mcu_coinage[0];
|
||||
m_mcu_credits += m_mcu_coinage[1];
|
||||
if (m_mcu_credits >= 9)
|
||||
{
|
||||
m_mcu_credits = 9;
|
||||
machine().bookkeeping().coin_lockout_global_w(1); /* Lock all coin slots */
|
||||
}
|
||||
else
|
||||
{
|
||||
machine().bookkeeping().coin_lockout_global_w(0); /* Unlock all coin slots */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (coin & 0x02) /* coin B */
|
||||
{
|
||||
// logerror("Coin dropped into slot B\n");
|
||||
machine().bookkeeping().coin_counter_w(1,1); machine().bookkeeping().coin_counter_w(1,0); /* Count slot B */
|
||||
m_mcu_coins_b++;
|
||||
if (m_mcu_coins_b >= m_mcu_coinage[2])
|
||||
{
|
||||
m_mcu_coins_b -= m_mcu_coinage[2];
|
||||
m_mcu_credits += m_mcu_coinage[3];
|
||||
if (m_mcu_credits >= 9)
|
||||
{
|
||||
m_mcu_credits = 9;
|
||||
machine().bookkeeping().coin_lockout_global_w(1); /* Lock all coin slots */
|
||||
}
|
||||
else
|
||||
{
|
||||
machine().bookkeeping().coin_lockout_global_w(0); /* Unlock all coin slots */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (coin & 0x04) /* service */
|
||||
{
|
||||
// logerror("Coin dropped into service slot C\n");
|
||||
m_mcu_credits++;
|
||||
}
|
||||
|
||||
m_mcu_reportcoin = coin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_mcu_credits < 9)
|
||||
machine().bookkeeping().coin_lockout_global_w(0); /* Unlock all coin slots */
|
||||
|
||||
m_mcu_reportcoin = 0;
|
||||
}
|
||||
m_insertcoin = coin;
|
||||
}
|
||||
|
||||
/*********************************
|
||||
|
||||
TNZS sync bug kludge
|
||||
|
||||
In all TNZS versions there is code like this:
|
||||
|
||||
0C5E: ld ($EF10),a
|
||||
0C61: ld a,($EF10)
|
||||
0C64: inc a
|
||||
0C65: ret nz
|
||||
0C66: jr $0C61
|
||||
|
||||
which is sometimes executed by the main cpu when it writes to shared RAM a
|
||||
command for the second CPU. The intended purpose of the code is to wait an
|
||||
acknowledge from the sub CPU: the sub CPU writes FF to the same location
|
||||
after reading the command.
|
||||
|
||||
However the above code is wrong. The "ret nz" instruction means that the
|
||||
loop will be exited only when the contents of $EF10 are *NOT* $FF!!
|
||||
On the real board, this casues little harm: the main CPU will just write
|
||||
the command, read it back and, since it's not $FF, return immediately. There
|
||||
is a chance that the command might go lost, but this will cause no major
|
||||
harm, the worse that can happen is that the background tune will not change.
|
||||
|
||||
In MAME, however, since CPU interleaving is not perfect, it can happen that
|
||||
the main CPU ends its timeslice after writing to EF10 but before reading it
|
||||
back. In the meantime, the sub CPU will run, read the command and write FF
|
||||
there - therefore causing the main CPU to enter an endless loop.
|
||||
|
||||
Unlike the usual sync problems in MAME, which can be fixed by increasing the
|
||||
interleave factor, in this case increasing it will actually INCREASE the
|
||||
chance of entering the endless loop - because it will increase the chances of
|
||||
the main CPU ending its timeslice at the wrong moment.
|
||||
|
||||
So what we do here is catch writes by the main CPU to the RAM location, and
|
||||
process them using a timer, in order to
|
||||
a) force a resync of the two CPUs
|
||||
b) make sure the main CPU will be the first one to run after the location is
|
||||
changed
|
||||
|
||||
Since the answer from the sub CPU is ignored, we don't even need to boost
|
||||
interleave.
|
||||
|
||||
*********************************/
|
||||
|
||||
/*
|
||||
TIMER_CALLBACK_MEMBER(tnzs_base_state::kludge_callback)
|
||||
{
|
||||
tnzs_sharedram[0x0f10] = param;
|
||||
}
|
||||
|
||||
void tnzs_base_state::tnzs_sync_kludge_w(uint8_t data)
|
||||
{
|
||||
machine().scheduler().synchronize(timer_expired_delegate(FUNC(tnzs_base_state::kludge_callback),this), data);
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t arknoid2_state::mcu_r(offs_t offset)
|
||||
{
|
||||
static const char mcu_startup[] = "\x55\xaa\x5a";
|
||||
|
||||
//logerror("%s: read mcu %04x\n", m_maincpu->pc(), 0xc000 + offset);
|
||||
|
||||
if (offset == 0)
|
||||
{
|
||||
/* if the mcu has just been reset, return startup code */
|
||||
if (m_mcu_initializing)
|
||||
{
|
||||
m_mcu_initializing--;
|
||||
return mcu_startup[2 - m_mcu_initializing];
|
||||
}
|
||||
|
||||
switch (m_mcu_command)
|
||||
{
|
||||
case 0x41:
|
||||
return m_mcu_credits;
|
||||
|
||||
case 0xc1:
|
||||
/* Read the credit counter or the inputs */
|
||||
if (m_mcu_readcredits == 0)
|
||||
{
|
||||
m_mcu_readcredits = 1;
|
||||
if (m_mcu_reportcoin & 0x08)
|
||||
{
|
||||
m_mcu_initializing = 3;
|
||||
return 0xee; /* tilt */
|
||||
}
|
||||
else return m_mcu_credits;
|
||||
}
|
||||
else return m_in0->read(); /* buttons */
|
||||
|
||||
default:
|
||||
logerror("error, unknown mcu command\n");
|
||||
/* should not happen */
|
||||
return 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
status bits:
|
||||
0 = mcu is ready to send data (read from c000)
|
||||
1 = mcu has read data (from c000)
|
||||
2 = unused
|
||||
3 = unused
|
||||
4-7 = coin code
|
||||
0 = nothing
|
||||
1,2,3 = coin switch pressed
|
||||
e = tilt
|
||||
*/
|
||||
if (m_mcu_reportcoin & 0x08) return 0xe1; /* tilt */
|
||||
if (m_mcu_reportcoin & 0x01) return 0x11; /* coin 1 (will trigger "coin inserted" sound) */
|
||||
if (m_mcu_reportcoin & 0x02) return 0x21; /* coin 2 (will trigger "coin inserted" sound) */
|
||||
if (m_mcu_reportcoin & 0x04) return 0x31; /* coin 3 (will trigger "coin inserted" sound) */
|
||||
return 0x01;
|
||||
}
|
||||
}
|
||||
|
||||
void arknoid2_state::mcu_w(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (offset == 0)
|
||||
{
|
||||
//logerror("%s: write %02x to mcu %04x\n", m_maincpu->pc(), data, 0xc000 + offset);
|
||||
if (m_mcu_command == 0x41)
|
||||
{
|
||||
m_mcu_credits = (m_mcu_credits + data) & 0xff;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
0xc1: read number of credits, then buttons
|
||||
0x54+0x41: add value to number of credits
|
||||
0x15: sub 1 credit (when "Continue Play" only)
|
||||
0x84: coin 1 lockout (issued only in test mode)
|
||||
0x88: coin 2 lockout (issued only in test mode)
|
||||
0x80: release coin lockout (issued only in test mode)
|
||||
during initialization, a sequence of 4 bytes sets coin/credit settings
|
||||
*/
|
||||
//logerror("%s: write %02x to mcu %04x\n", m_maincpu->pc(), data, 0xc000 + offset);
|
||||
|
||||
if (m_mcu_initializing)
|
||||
{
|
||||
/* set up coin/credit settings */
|
||||
m_mcu_coinage[m_mcu_coinage_init++] = data;
|
||||
if (m_mcu_coinage_init == 4)
|
||||
m_mcu_coinage_init = 0; /* must not happen */
|
||||
}
|
||||
|
||||
if (data == 0xc1)
|
||||
m_mcu_readcredits = 0; /* reset input port number */
|
||||
|
||||
if (data == 0x15)
|
||||
{
|
||||
m_mcu_credits = (m_mcu_credits - 1) & 0xff;
|
||||
if (m_mcu_credits == 0xff)
|
||||
m_mcu_credits = 0;
|
||||
}
|
||||
m_mcu_command = data;
|
||||
}
|
||||
}
|
||||
|
||||
INTERRUPT_GEN_MEMBER(arknoid2_state::mcu_interrupt)
|
||||
{
|
||||
int coin = ((m_coin1->read() & 1) << 0);
|
||||
coin |= ((m_coin2->read() & 1) << 1);
|
||||
coin |= ((m_in2->read() & 3) << 2);
|
||||
coin ^= 0x0c;
|
||||
mcu_handle_coins(coin);
|
||||
|
||||
device.execute().set_input_line(0, HOLD_LINE);
|
||||
}
|
||||
|
||||
void arknoid2_state::machine_reset()
|
||||
{
|
||||
extrmatn_state::machine_reset();
|
||||
|
||||
// initialize the MCU simulation
|
||||
mcu_reset();
|
||||
|
||||
m_mcu_readcredits = 0;
|
||||
m_insertcoin = 0;
|
||||
}
|
||||
|
||||
void kageki_state::machine_reset()
|
||||
{
|
||||
tnzs_base_state::machine_reset();
|
||||
|
||||
m_csport_sel = 0;
|
||||
}
|
||||
|
||||
void tnzs_base_state::machine_start()
|
||||
{
|
||||
tnzs_video_state_base::machine_start();
|
||||
|
||||
uint8_t *const sub = memregion("sub")->base();
|
||||
m_subbank->configure_entries(0, 4, &sub[0x08000], 0x2000);
|
||||
m_subbank->set_entry(0);
|
||||
|
||||
m_ramromview.select(2);
|
||||
}
|
||||
|
||||
void arknoid2_state::machine_start()
|
||||
{
|
||||
extrmatn_state::machine_start();
|
||||
|
||||
save_item(NAME(m_mcu_readcredits));
|
||||
save_item(NAME(m_insertcoin));
|
||||
save_item(NAME(m_mcu_initializing));
|
||||
save_item(NAME(m_mcu_coinage_init));
|
||||
save_item(NAME(m_mcu_coinage));
|
||||
save_item(NAME(m_mcu_coins_a));
|
||||
save_item(NAME(m_mcu_coins_b));
|
||||
save_item(NAME(m_mcu_credits));
|
||||
save_item(NAME(m_mcu_reportcoin));
|
||||
save_item(NAME(m_mcu_command));
|
||||
|
||||
// kludge to make device work with active-high coin inputs
|
||||
m_upd4701->left_w(0);
|
||||
m_upd4701->middle_w(0);
|
||||
}
|
||||
|
||||
void kageki_state::machine_start()
|
||||
{
|
||||
tnzs_base_state::machine_start();
|
||||
|
||||
save_item(NAME(m_csport_sel));
|
||||
}
|
||||
|
||||
void kabukiz_state::machine_start()
|
||||
{
|
||||
tnzsb_state::machine_start();
|
||||
|
||||
uint8_t *sound = memregion("audiocpu")->base();
|
||||
m_audiobank->configure_entries(0, 8, &sound[0x00000], 0x4000);
|
||||
}
|
||||
|
||||
void tnzs_base_state::ramrom_bankswitch_w(uint8_t data)
|
||||
{
|
||||
// logerror("%s: writing %02x to bankswitch\n", m_maincpu->pc(),data);
|
||||
|
||||
// bit 4 resets the second CPU
|
||||
m_subcpu->set_input_line(INPUT_LINE_RESET, BIT(data, 4) ? CLEAR_LINE : ASSERT_LINE);
|
||||
|
||||
// bits 0-2 select RAM/ROM bank
|
||||
m_ramromview.select(data & 0x07);
|
||||
}
|
||||
|
||||
void arknoid2_state::bankswitch1_w(uint8_t data)
|
||||
{
|
||||
tnzs_base_state::bankswitch1_w(data);
|
||||
|
||||
if (BIT(data, 2))
|
||||
mcu_reset();
|
||||
|
||||
// never actually written by arknoid2 (though code exists to do it)
|
||||
m_upd4701->resetx_w(BIT(data, 5));
|
||||
m_upd4701->resety_w(BIT(data, 5));
|
||||
}
|
||||
|
||||
void insectx_state::bankswitch1_w(uint8_t data)
|
||||
{
|
||||
tnzs_base_state::bankswitch1_w(data);
|
||||
|
||||
machine().bookkeeping().coin_lockout_w(0, BIT(~data, 2));
|
||||
machine().bookkeeping().coin_lockout_w(1, BIT(~data, 3));
|
||||
machine().bookkeeping().coin_counter_w(0, BIT(data, 4));
|
||||
machine().bookkeeping().coin_counter_w(1, BIT(data, 5));
|
||||
}
|
||||
|
||||
void tnzsb_state::bankswitch1_w(uint8_t data) // kabukiz_state
|
||||
{
|
||||
tnzs_base_state::bankswitch1_w(data);
|
||||
|
||||
machine().bookkeeping().coin_lockout_w(0, BIT(~data, 4));
|
||||
machine().bookkeeping().coin_lockout_w(1, BIT(~data, 5));
|
||||
machine().bookkeeping().coin_counter_w(0, BIT(data, 2));
|
||||
machine().bookkeeping().coin_counter_w(1, BIT(data, 3));
|
||||
}
|
||||
|
||||
void kageki_state::bankswitch1_w(uint8_t data)
|
||||
{
|
||||
tnzs_base_state::bankswitch1_w(data);
|
||||
|
||||
machine().bookkeeping().coin_lockout_global_w(BIT(~data, 5));
|
||||
machine().bookkeeping().coin_counter_w(0, BIT(data, 2));
|
||||
machine().bookkeeping().coin_counter_w(1, BIT(data, 3));
|
||||
}
|
||||
|
||||
void tnzs_mcu_state::bankswitch1_w(uint8_t data)
|
||||
{
|
||||
tnzs_base_state::bankswitch1_w(data);
|
||||
|
||||
if (BIT(data, 2) && m_mcu)
|
||||
m_mcu->pulse_input_line(INPUT_LINE_RESET, attotime::zero);
|
||||
|
||||
// written only at startup by plumppop?
|
||||
if (m_upd4701.found())
|
||||
{
|
||||
m_upd4701->resetx_w(BIT(data, 5));
|
||||
m_upd4701->resety_w(BIT(data, 5));
|
||||
}
|
||||
}
|
||||
|
||||
void tnzs_base_state::bankswitch1_w(uint8_t data)
|
||||
{
|
||||
// logerror("%s: writing %02x to bankswitch 1\n", m_maincpu->pc(),data);
|
||||
|
||||
// bits 0-1 select ROM bank
|
||||
m_subbank->set_entry(data & 0x03);
|
||||
}
|
||||
|
||||
void jpopnics_state::subbankswitch_w(uint8_t data)
|
||||
{
|
||||
// bits 0-1 select ROM bank
|
||||
m_subbank->set_entry(data & 0x03);
|
||||
|
||||
// written once at startup
|
||||
m_upd4701->resetx_w(BIT(data, 5));
|
||||
m_upd4701->resety_w(BIT(data, 5));
|
||||
}
|
||||
|
||||
void tnzsb_state::sound_command_w(uint8_t data)
|
||||
{
|
||||
m_soundlatch->write(data);
|
||||
m_audiocpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); // Z80
|
||||
}
|
||||
|
||||
// handler called by the 2203 emulator when the internal timers cause an IRQ
|
||||
WRITE_LINE_MEMBER(tnzsb_state::ym2203_irqhandler)
|
||||
{
|
||||
m_audiocpu->set_input_line(INPUT_LINE_NMI, state ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
void kabukiz_state::sound_bank_w(uint8_t data)
|
||||
{
|
||||
// to avoid the write when the sound chip is initialized
|
||||
if (data != 0xff)
|
||||
m_audiobank->set_entry(data & 0x07);
|
||||
}
|
@ -2,25 +2,12 @@
|
||||
// copyright-holders:Luca Elia, Mirko Buffoni, Takahiro Nogi
|
||||
/***************************************************************************
|
||||
|
||||
video.c
|
||||
|
||||
Functions to emulate the video hardware of the machine.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "tnzs.h"
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
The New Zealand Story doesn't have a color PROM. It uses 1024 bytes of RAM
|
||||
to dynamically create the palette. Each couple of bytes defines one
|
||||
color (15 bits per pixel; the top bit of the second byte is unused).
|
||||
Since the graphics use 4 bitplanes, hence 16 colors, this makes for 32
|
||||
different color codes.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "tnzs_video.h"
|
||||
|
||||
/***************************************************************************
|
||||
|
36
src/mame/taito/tnzs_video.h
Normal file
36
src/mame/taito/tnzs_video.h
Normal file
@ -0,0 +1,36 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, Mirko Buffoni, Takahiro Nogi
|
||||
#ifndef MAME_TAITO_TNZS_VIDEO_H
|
||||
#define MAME_TAITO_TNZS_VIDEO_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "video/x1_001.h"
|
||||
|
||||
#include "emupal.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
class tnzs_video_state_base : public driver_device
|
||||
{
|
||||
protected:
|
||||
tnzs_video_state_base(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_spritegen(*this, "spritegen")
|
||||
, m_palette(*this, "palette")
|
||||
, m_screen(*this, "screen")
|
||||
{
|
||||
}
|
||||
|
||||
void prompalette(palette_device &palette) const;
|
||||
uint32_t screen_update_tnzs(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
DECLARE_WRITE_LINE_MEMBER(screen_vblank_tnzs);
|
||||
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<x1_001_device> m_spritegen;
|
||||
required_device<palette_device> m_palette;
|
||||
required_device<screen_device> m_screen;
|
||||
};
|
||||
|
||||
#endif // MAME_TAITO_TNZS_VIDEO_H
|
Loading…
Reference in New Issue
Block a user