Various improvements over Vrender0 based systems [Angelo Salese] (#5580)

*   Made some experimental work with menghong based HW, allowing crzyddz2 to boot and improving menghong colors;
*   Internalize video and audio components inside the SoC;
*   Wrote a preliminary UART subdevice;
*   Made external video clock to be settable by the host driver;
This commit is contained in:
Angelo Salese 2019-09-02 07:27:21 +02:00 committed by GitHub
parent 5aa10d4f7d
commit 11f9727726
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 863 additions and 797 deletions

View File

@ -4145,6 +4145,8 @@ end
if (MACHINES["VRENDER0"]~=null) then
files {
MAME_DIR .. "src/devices/machine/vrender0.cpp",
MAME_DIR .. "src/devices/machine/vr0uart.cpp",
MAME_DIR .. "src/devices/machine/vrender0.h",
}
end

View File

@ -0,0 +1,220 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
/***************************************************************************
MagicEyes VRender0 UART sub-device
Device by Angelo Salese
TODO:
- The only current example (Trivia R Us touchscreen) expects to read
stuff before transmitting anything, except for loopback test and a
signal break enabling at POST (!?).
***************************************************************************/
#include "emu.h"
#include "vrender0.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(VRENDER0_UART, vr0uart_device, "vr0uart", "MagicEyes VRender0 UART")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// vr0uart_device - constructor
//-------------------------------------------------
vr0uart_device::vr0uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VRENDER0_UART, tag, owner, clock),
device_serial_interface(mconfig, *this)
{
}
void vr0uart_device::regs_map(address_map &map)
{
map(0x00, 0x03).rw(FUNC(vr0uart_device::control_r), FUNC(vr0uart_device::control_w));
map(0x04, 0x07).r(FUNC(vr0uart_device::status_r));
map(0x08, 0x0b).w(FUNC(vr0uart_device::transmit_buffer_w));
map(0x0c, 0x0f).r(FUNC(vr0uart_device::receive_buffer_r));
map(0x10, 0x13).rw(FUNC(vr0uart_device::baud_rate_div_r), FUNC(vr0uart_device::baud_rate_div_w));
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void vr0uart_device::device_start()
{
save_item(NAME(m_ucon));
save_item(NAME(m_ubdr));
save_item(NAME(m_ustat));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void vr0uart_device::device_reset()
{
m_ucon = 0x001;
m_ubdr = 1;
m_urxb_fifo.clear();
update_serial_config();
}
inline void vr0uart_device::tx_send_byte(uint8_t val)
{
transmit_register_setup(val);
m_ustat |= 0x20;
}
inline uint32_t vr0uart_device::calculate_baud_rate()
{
uint32_t div_rate = ((m_ubdr & 0xffff) + 1) * 16;
// TODO: external / internal serial clock config
return (this->clock() / 2) / div_rate;
}
void vr0uart_device::update_serial_config()
{
const parity_t parity_modes[4] = { PARITY_NONE, PARITY_NONE, PARITY_EVEN, PARITY_ODD };
uint8_t word_length = m_ucon & 1 ? 8 : 7;
parity_t parity_mode = parity_modes[(m_ucon & 0xc) >> 2];
stop_bits_t stop_bits = m_ucon & 2 ? STOP_BITS_2 : STOP_BITS_1;
set_data_frame(1, word_length, parity_mode, stop_bits);
if (m_ucon & 0x100) // UART Enable
{
uint32_t clock_rate = calculate_baud_rate();
set_rcv_rate(clock_rate);
set_tra_rate(clock_rate);
}
else
{
set_rcv_rate(0);
set_tra_rate(0);
}
}
void vr0uart_device::tra_callback()
{
int bit = transmit_register_get_data_bit();
m_ustat |= 0x40;
m_parent->write_line_tx(m_channel_num, bit);
}
void vr0uart_device::tra_complete()
{
m_ustat &= ~0x60;
m_parent->IntReq(m_channel_num ? 18 : 15);
}
void vr0uart_device::rcv_complete()
{
receive_register_extract();
if (is_receive_parity_error())
m_ustat |= 2;
if (is_receive_framing_error())
m_ustat |= 4;
if (!m_urxb_fifo.full())
{
// TODO: break detection
m_urxb_fifo.enqueue(get_received_char());
}
else
m_ustat |= 1; // overrun
if (m_ucon & 0x20 && m_ustat & 0xf)
m_parent->IntReq(m_channel_num ? 16 : 13);
else
m_parent->IntReq(m_channel_num ? 17 : 14);
}
//**************************************************************************
// READ/WRITE HANDLERS
//**************************************************************************
/*
* ---x ---- ---- UART enable
* ---- x--- ---- Loopback Test
* ---- -x-- ---- Send Break mode
* ---- --x- ---- Generate interrupt on break or error
* ---- ---x ---- Serial Clock selection (1=external)
* ---- ---- xx-- Parity Mode (0x=No Parity, 10=Even, 11=Odd)
* ---- ---- --x- Stop Bits (1=2 bits, 0=1 Bit)
* ---- ---- ---x Word Length (1=8 bits, 0=7 bits)
*/
READ32_MEMBER( vr0uart_device::control_r )
{
return m_ucon;
}
WRITE32_MEMBER( vr0uart_device::control_w )
{
COMBINE_DATA(&m_ucon);
update_serial_config();
}
/*
* xxxx ---- ---- Receive FIFO count
* ---- -x-- ---- Tx buffer not empty, Tx holding data
* ---- --x- ---- Tx buffer not empty
* ---- ---x ---- Rx buffer not empty
* ---- ---- x--- Break detect
* ---- ---- -x-- Frame error
* ---- ---- --x- Parity error
* ---- ---- ---x Overrun Error
*/
READ32_MEMBER( vr0uart_device::status_r )
{
uint32_t res = m_ustat;
if (!m_urxb_fifo.empty())
{
res |= 0x10;
res |= (m_urxb_fifo.queue_length() << 8);
}
// Break detect and errors are cleared by reading this
m_ustat &= ~0xf;
return res;
}
WRITE32_MEMBER( vr0uart_device::transmit_buffer_w )
{
if (ACCESSING_BITS_0_7)
tx_send_byte(data & 0xff);
}
READ32_MEMBER( vr0uart_device::receive_buffer_r )
{
// TODO: unknown value & behaviour attempting to read this on empty FIFO (stall?)
uint8_t res = 0;
if (ACCESSING_BITS_0_7 && !m_urxb_fifo.empty())
res = m_urxb_fifo.dequeue();
return res;
}
READ32_MEMBER( vr0uart_device::baud_rate_div_r )
{
return m_ubdr;
}
WRITE32_MEMBER( vr0uart_device::baud_rate_div_w )
{
COMBINE_DATA(&m_ubdr);
update_serial_config();
}

View File

@ -19,7 +19,6 @@
#include "vrender0.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
@ -39,9 +38,15 @@ DEFINE_DEVICE_TYPE(VRENDER0_SOC, vrender0soc_device, "vrender0", "MagicEyes VRen
vrender0soc_device::vrender0soc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VRENDER0_SOC, tag, owner, clock),
m_host_cpu(*this, finder_base::DUMMY_TAG),
m_host_screen(*this, finder_base::DUMMY_TAG),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_lspeaker(*this, "lspeaker"),
m_rspeaker(*this, "rspeaker"),
m_uart(*this, "uart%u", 0),
m_crtcregs(*this, "crtcregs"),
m_idleskip_cb(*this)
write_tx{ { *this }, { *this } }
{
}
@ -67,6 +72,8 @@ void vrender0soc_device::regs_map(address_map &map)
map(0x00c08, 0x00c0b).rw(FUNC(vrender0soc_device::inten_r), FUNC(vrender0soc_device::inten_w));
map(0x00c0c, 0x00c0f).rw(FUNC(vrender0soc_device::intst_r), FUNC(vrender0soc_device::intst_w));
// map(0x01000, 0x013ff) // UART
map(0x01000, 0x0101f).m(m_uart[0], FUNC(vr0uart_device::regs_map));
map(0x01020, 0x0103f).m(m_uart[1], FUNC(vr0uart_device::regs_map));
// map(0x01400, 0x017ff) // Timer & Counter
map(0x01400, 0x01403).rw(FUNC(vrender0soc_device::tmcon_r<0>), FUNC(vrender0soc_device::tmcon_w<0>));
map(0x01404, 0x01407).rw(FUNC(vrender0soc_device::tmcnt_r<0>), FUNC(vrender0soc_device::tmcnt_w<0>)).umask32(0x0000ffff);
@ -88,6 +95,13 @@ void vrender0soc_device::regs_map(address_map &map)
// map(0x04000, 0x043ff) // RAMDAC & PLL
}
void vrender0soc_device::audiovideo_map(address_map &map)
{
map(0x00000000, 0x0000ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x00800000, 0x00ffffff).rw(FUNC(vrender0soc_device::textureram_r), FUNC(vrender0soc_device::textureram_w));
map(0x01000000, 0x017fffff).rw(FUNC(vrender0soc_device::frameram_r), FUNC(vrender0soc_device::frameram_w));
map(0x01800000, 0x01800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
}
//-------------------------------------------------
// device_add_mconfig - device-specific machine
@ -96,8 +110,29 @@ void vrender0soc_device::regs_map(address_map &map)
void vrender0soc_device::device_add_mconfig(machine_config &config)
{
// ...
for (required_device<vr0uart_device> &uart : m_uart)
VRENDER0_UART(config, uart, 3579500);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(vrender0soc_device::screen_update));
m_screen->screen_vblank().set(FUNC(vrender0soc_device::screen_vblank));
m_screen->set_palette(m_palette);
VIDEO_VRENDER0(config, m_vr0vid, 14318180);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0vid->idleskip_cb().set(FUNC(vrender0soc_device::idle_skip_speedup_w));
#endif
PALETTE(config, m_palette, palette_device::RGB_565);
SPEAKER(config, m_lspeaker).front_left();
SPEAKER(config, m_rspeaker).front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, m_lspeaker, 1.0);
m_vr0snd->add_route(1, m_rspeaker, 1.0);
}
@ -107,12 +142,29 @@ void vrender0soc_device::device_add_mconfig(machine_config &config)
void vrender0soc_device::device_start()
{
int i;
m_textureram = auto_alloc_array_clear(machine(), uint16_t, 0x00800000/2);
m_frameram = auto_alloc_array_clear(machine(), uint16_t, 0x00800000/2);
m_vr0vid->set_areas(m_textureram, m_frameram);
m_vr0snd->set_areas(m_textureram, m_frameram);
m_host_space = &m_host_cpu->space(AS_PROGRAM);
m_idleskip_cb.resolve_safe();
for (int i = 0; i < 4; i++)
if (this->clock() == 0)
fatalerror("%s: bus clock not setup properly",this->tag());
for (i = 0; i < 4; i++)
m_Timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(vrender0soc_device::Timercb),this), (void*)(uintptr_t)i);
for (auto &cb : write_tx)
cb.resolve_safe();
for (i = 0; i < 2; i++)
{
m_uart[i]->set_channel_num(i);
m_uart[i]->set_parent(this);
}
save_item(NAME(m_inten));
save_item(NAME(m_intst));
save_item(NAME(m_IntHigh));
@ -128,8 +180,19 @@ void vrender0soc_device::device_start()
save_item(NAME(m_dma[1].src));
save_item(NAME(m_dma[1].dst));
save_item(NAME(m_dma[1].size));
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
}
void vrender0soc_device::write_line_tx(int port, uint8_t value)
{
//printf("callback %d %02x\n",port,value);
write_tx[port & 1](value);
}
//-------------------------------------------------
// device_reset - device-specific reset
@ -138,7 +201,7 @@ void vrender0soc_device::device_start()
void vrender0soc_device::device_reset()
{
// TODO: improve CRT defaults
m_crtcregs[1] = 0x00000022;
m_crtcregs[1] = 0x0000002a;
//m_FlipCount = 0;
m_IntHigh = 0;
@ -151,6 +214,10 @@ void vrender0soc_device::device_reset()
m_timer_control[i] = 0xff << 8;
m_Timer[i]->adjust(attotime::never);
}
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
}
@ -158,6 +225,32 @@ void vrender0soc_device::device_reset()
// READ/WRITE HANDLERS
//**************************************************************************
/*
*
* Texture/FrameRAM 16-bit trampolines
*
*/
READ16_MEMBER(vrender0soc_device::textureram_r)
{
return m_textureram[offset];
}
WRITE16_MEMBER(vrender0soc_device::textureram_w)
{
COMBINE_DATA(&m_textureram[offset]);
}
READ16_MEMBER(vrender0soc_device::frameram_r)
{
return m_frameram[offset];
}
WRITE16_MEMBER(vrender0soc_device::frameram_w)
{
COMBINE_DATA(&m_frameram[offset]);
}
/*
*
* INT Controller
@ -214,7 +307,9 @@ void vrender0soc_device::IntReq( int num )
m_host_cpu->set_input_line(SE3208_INT, ASSERT_LINE);
}
m_idleskip_cb(ASSERT_LINE);
#ifdef IDLE_LOOP_SPEEDUP
idle_skip_resume_w(ASSERT_LINE);
#endif
}
@ -242,7 +337,8 @@ void vrender0soc_device::TimerStart(int which)
{
int PD = (m_timer_control[which] >> 8) & 0xff;
int TCV = m_timer_count[which] & 0xffff;
attotime period = attotime::from_hz(14318180 * 3) * ((PD + 1) * (TCV + 1)); // TODO : related to CPU clock
// TODO: documentation claims this is bus clock, may be slower than the CPU itself
attotime period = attotime::from_hz(this->clock()) * ((PD + 1) * (TCV + 1));
m_Timer[which]->adjust(period);
// printf("timer %d start, PD = %x TCV = %x period = %s\n", which, PD, TCV, period.as_string());
@ -369,6 +465,12 @@ WRITE32_MEMBER(vrender0soc_device::dmac_w)
COMBINE_DATA(&m_dma[Which].ctrl);
}
/*
*
* CRT Controller
*
*/
READ32_MEMBER(vrender0soc_device::crtc_r)
{
uint32_t res = m_crtcregs[offset];
@ -380,10 +482,10 @@ READ32_MEMBER(vrender0soc_device::crtc_r)
if (crt_is_interlaced()) // Interlace
vdisp <<= 1;
if (m_host_screen->vpos() <= vdisp) // Vertical display enable status
if (m_screen->vpos() <= vdisp) // Vertical display enable status
res |= 0x4000;
if (m_host_screen->hpos() > hdisp) // horizontal & vertical blank period
if (m_screen->hpos() > hdisp) // horizontal & vertical blank period
res &= ~0x2000;
else
res |= 0x2000;
@ -397,7 +499,7 @@ READ32_MEMBER(vrender0soc_device::crtc_r)
WRITE32_MEMBER(vrender0soc_device::crtc_w)
{
if (((m_crtcregs[0] & 0x0100) == 0x0100) && (offset > 0)) // Write protect
if (((m_crtcregs[0] & 0x0100) == 0x0100) && (offset > 0) && (offset < 0x28/4)) // Write protect
return;
uint32_t old = m_crtcregs[offset];
@ -481,7 +583,7 @@ bool vrender0soc_device::crt_active_vblank_irq()
return true;
// bit 3 of CRTC reg -> select display start even/odd fields
return (m_host_screen->frame_number() & 1) ^ ((m_crtcregs[0] & 8) >> 3);
return (m_screen->frame_number() & 1) ^ ((m_crtcregs[0] & 8) >> 3);
}
void vrender0soc_device::crtc_update()
@ -528,8 +630,11 @@ void vrender0soc_device::crtc_update()
m_crtcregs[0x24 / 4] = ((vtot & 0x7ff) - 1);
}
// TODO: the two Sealy games doesn't set this, eventually need to parametrize this one up
uint32_t pixel_clock = (BIT(m_crtcregs[0x04 / 4], 3)) ? 14318180 : 14318180*2;
// ext vclk set up by Sealy games in menghong.cpp
uint32_t pixel_clock = (BIT(m_crtcregs[0x04 / 4], 3)) ? 14318180 : m_ext_vclk;
if (pixel_clock == 0)
fatalerror("%s: Accessing external vclk in CRTC parameters, please set it up via setter in config\n",this->tag());
if (BIT(m_crtcregs[0x04 / 4], 7))
pixel_clock *= 2;
// TODO: divider setting = 0 is reserved, guess it just desyncs the signal?
@ -554,7 +659,7 @@ void vrender0soc_device::crtc_update()
//printf("%dX%d %dX%d %d\n",htot, vtot, hdisp, vdisp, pixel_clock);
rectangle const visarea(0, hdisp - 1, 0, vdisp - 1);
m_host_screen->configure(htot, vtot, visarea, HZ_TO_ATTOSECONDS(pixel_clock) * vtot * htot);
m_screen->configure(htot, vtot, visarea, HZ_TO_ATTOSECONDS(pixel_clock) * vtot * htot);
}
// accessed by cross puzzle
@ -562,15 +667,70 @@ READ32_MEMBER(vrender0soc_device::sysid_r)
{
// Device ID: VRender0+ -> 0x0a
// Revision Number -> 0x00
logerror("%s: read SYSID\n",this->tag());
return 0x00000a00;
}
READ32_MEMBER(vrender0soc_device::cfgr_r)
{
// TODO: this truly needs real HW verification
// TODO: this truly needs real HW verification,
// only Cross Puzzle reads this so far so leaving a logerror
// -x-- ---- Main Clock select (0 -> External Clock)
// --xx x--- Reserved for Chip Test Mode
// ---- -xx- Local ROM Data Bus Width (01 -> 16 bit)
// ---- ---x Local Memory Bus Width (0 -> 16 bit)
return 0x00000002;
logerror("%s: read CFGR\n",this->tag());
return 0x00000041;
}
/*
*
* Video configuration
*
*/
uint32_t vrender0soc_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
// TODO: chip can do superimposing, cfr. TCOL register in CRTC
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(vrender0soc_device::screen_vblank)
{
// rising edge
if (state)
{
if (crt_active_vblank_irq() == true)
IntReq(24); //VRender0 VBlank
m_vr0vid->execute_flipping();
}
}
/*
*
* Hacks
*
*/
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(vrender0soc_device::idle_skip_resume_w)
{
m_FlipCntRead = 0;
m_host_cpu->resume(SUSPEND_REASON_SPIN);
}
WRITE_LINE_MEMBER(vrender0soc_device::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && irq_pending() == false && state == ASSERT_LINE)
m_host_cpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif

View File

@ -13,6 +13,19 @@
#include "cpu/se3208/se3208.h"
#include "screen.h"
#include "video/vrender0.h"
#include "sound/vrender0.h"
#include "emupal.h"
#include "speaker.h"
#include "diserial.h"
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
//**************************************************************************
#define IDLE_LOOP_SPEEDUP
//**************************************************************************
// INTERFACE CONFIGURATION MACROS
@ -24,7 +37,57 @@
// TYPE DEFINITIONS
//**************************************************************************
// ======================> vrender0soc_device
// ======================> vr0uart_device
class vrender0soc_device;
class vr0uart_device : public device_t,
public device_serial_interface
{
public:
// construction/destruction
vr0uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void regs_map(address_map &map);
void set_channel_num(int ch) { m_channel_num = ch; }
void set_parent(vrender0soc_device *parent) { m_parent = parent; }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
private:
DECLARE_READ32_MEMBER( control_r );
DECLARE_WRITE32_MEMBER( control_w );
DECLARE_READ32_MEMBER( baud_rate_div_r );
DECLARE_WRITE32_MEMBER( baud_rate_div_w );
DECLARE_READ32_MEMBER( status_r );
DECLARE_WRITE32_MEMBER( transmit_buffer_w );
DECLARE_READ32_MEMBER( receive_buffer_r );
TIMER_CALLBACK_MEMBER( break_timer_cb );
uint32_t m_ucon; // control
uint32_t m_ubdr; // baud rate
uint32_t m_ustat; // status
util::fifo<uint8_t, 16> m_urxb_fifo; // receive FIFO
void update_serial_config();
inline uint32_t calculate_baud_rate();
virtual void tra_callback() override;
virtual void tra_complete() override;
virtual void rcv_complete() override;
inline void tx_send_byte(uint8_t val);
int m_channel_num;
vrender0soc_device *m_parent;
};
// device type definition
DECLARE_DEVICE_TYPE(VRENDER0_UART, vr0uart_device)
class vrender0soc_device : public device_t
{
@ -33,15 +96,19 @@ public:
vrender0soc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void regs_map(address_map &map);
void audiovideo_map(address_map &map);
template<class T> void set_host_cpu_tag(T &&tag) { m_host_cpu.set_tag(std::forward<T>(tag)); }
template<class T> void set_host_screen_tag(T &&tag) { m_host_screen.set_tag(std::forward<T>(tag)); }
void set_external_vclk(const uint32_t vclk) { m_ext_vclk = vclk; }
void set_external_vclk(const XTAL vclk) { m_ext_vclk = vclk.value(); }
bool crt_is_blanked() { return ((m_crtcregs[0] & 0x0200) == 0x0200); }
bool crt_active_vblank_irq();
void IntReq( int num );
int irq_callback();
auto idleskip_cb() { return m_idleskip_cb.bind(); }
bool irq_pending() { return m_intst & m_inten; }
bool irq_pending() { return m_intst; }
void write_line_tx(int port, uint8_t value);
template <int Port> auto tx_callback() { return write_tx[Port].bind(); }
template <int Port> DECLARE_WRITE_LINE_MEMBER(rx_w) { m_uart[Port]->rx_w((uint8_t)state); }
protected:
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
@ -51,12 +118,22 @@ protected:
private:
required_device <se3208_device> m_host_cpu;
required_device <screen_device> m_host_screen;
required_device <screen_device> m_screen;
required_device <palette_device> m_palette;
required_device <vr0video_device> m_vr0vid;
required_device <vr0sound_device> m_vr0snd;
required_device <speaker_device> m_lspeaker;
required_device <speaker_device> m_rspeaker;
required_device_array <vr0uart_device, 2> m_uart;
required_shared_ptr <uint32_t> m_crtcregs;
devcb_write_line m_idleskip_cb;
uint16_t *m_textureram;
uint16_t *m_frameram;
address_space *m_host_space;
// To move into SoC own device
uint32_t m_ext_vclk;
devcb_write_line write_tx[2];
// INTC
uint32_t m_inten;
DECLARE_READ32_MEMBER(inten_r);
@ -108,6 +185,21 @@ private:
// Misc
DECLARE_READ32_MEMBER( sysid_r );
DECLARE_READ32_MEMBER( cfgr_r );
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
DECLARE_READ16_MEMBER( textureram_r );
DECLARE_WRITE16_MEMBER( textureram_w );
DECLARE_READ16_MEMBER( frameram_r );
DECLARE_WRITE16_MEMBER( frameram_w );
// Hacks
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
};

View File

@ -149,10 +149,10 @@ WRITE32_MEMBER(vr0sound_device::vr0_snd_write)
}
void vr0sound_device::set_areas(uint32_t *texture, uint32_t *frame)
void vr0sound_device::set_areas(uint16_t *texture, uint16_t *frame)
{
m_TexBase=texture;
m_FBBase=frame;
m_TexBase=(int16_t *)texture;
m_FBBase=(int16_t *)frame;
}
@ -170,9 +170,9 @@ void vr0sound_device::VR0_RenderAudio(int nsamples, stream_sample_t *l, stream_s
if(CT1&0x20)
SAMPLES=(int16_t *)m_TexBase;
SAMPLES = m_TexBase;
else
SAMPLES=(int16_t *)m_FBBase;
SAMPLES = m_FBBase;
if(CLK)
div=((30<<16)|0x8000)/(CLK+1);

View File

@ -22,7 +22,7 @@ public:
DECLARE_READ32_MEMBER( vr0_snd_read );
DECLARE_WRITE32_MEMBER( vr0_snd_write );
void set_areas(uint32_t *texture, uint32_t *frame);
void set_areas(uint16_t *texture, uint16_t *frame);
protected:
// device-level overrides
@ -32,8 +32,8 @@ protected:
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
private:
uint32_t *m_TexBase;
uint32_t *m_FBBase;
int16_t *m_TexBase;
int16_t *m_FBBase;
uint32_t m_SOUNDREGS[0x10000/4];
sound_stream *m_stream;

View File

@ -7,12 +7,17 @@
driver by Angelo Salese, based off original crystal.cpp by ElSemi
TODO:
- Dies at POST with a SPU error;
- Hooking up serflash_device instead of the custom implementation here
- Dies at POST with a SPU error,
supposedly it should print a "running system." instead of "Ok" at the
end of the POST routine.
Update: it tries to load a "sdata.bin" file, which is nowhere to be found in the dump.
Considering also that first $20000 block is empty and loading the flash linearly gives
the reference memory size but then game isn't detected at all.
- Hooking up nand_device instead of the custom implementation here
makes the game to print having all memory available and no game
detected, fun
- I2C RTC interface should be correct but still doesn't work, sending
unrecognized slave address 0x30 (device type might be wrong as well)
unrecognized slave address 0x30 (device type might be wrong as well)
Notes:
- Game enables UART1 receive irq, if that irq is enable it just prints
@ -30,31 +35,21 @@
#include "machine/pcf8583.h"
#include "machine/nvram.h"
#include "machine/vrender0.h"
#include "sound/vrender0.h"
#include "video/vrender0.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include <algorithm>
#define IDLE_LOOP_SPEEDUP
class crospuzl_state : public driver_device
{
public:
crospuzl_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_flash(*this, "flash"),
m_maincpu(*this, "maincpu"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_rtc(*this, "rtc"),
m_screen(*this, "screen")
m_rtc(*this, "rtc")
{ }
@ -64,23 +59,12 @@ private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
required_region_ptr<uint8_t> m_flash;
/* devices */
required_device<se3208_device> m_maincpu;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
required_device<pcf8583_device> m_rtc;
required_device<screen_device> m_screen;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
uint8_t m_FlashCmd;
uint8_t m_FlashPrevCommand;
@ -96,8 +80,6 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void crospuzl_mem(address_map &map);
// PIO
@ -111,30 +93,6 @@ private:
};
uint32_t crospuzl_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(crospuzl_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(crospuzl_state::icallback)
{
return m_vr0soc->irq_callback();
@ -142,7 +100,8 @@ IRQ_CALLBACK_MEMBER(crospuzl_state::icallback)
READ32_MEMBER(crospuzl_state::PIOedat_r)
{
// TODO: this doesn't work with regular serflash_device
// TODO: this needs fixing in serflash_device
// (has a laconic constant for the ready line)
return (m_rtc->sda_r() << 19)
| (machine().rand() & 0x04000000); // serial ready line
}
@ -161,7 +120,7 @@ READ8_MEMBER(crospuzl_state::FlashCmd_r)
// and the standard claims that the ID is 7 + 1 parity bit.
// TODO: Retrieve ID from actual HW service mode screen.
// const uint8_t id[5] = { 0xee, 0x81, 0x00, 0x15, 0x00 };
const uint8_t id[5] = { 0xec, 0xf1, 0x00, 0x15, 0x00 };
const uint8_t id[5] = { 0xec, 0xf1, 0x00, 0x95, 0x40 };
uint8_t res = id[m_FlashAddr];
m_FlashAddr ++;
m_FlashAddr %= 5;
@ -246,41 +205,14 @@ void crospuzl_state::crospuzl_mem(address_map &map)
map(0x02000000, 0x027fffff).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
// map(0x05000000, 0x05ffffff).bankr("mainbank");
// map(0x05000000, 0x05000003).rw(FUNC(crospuzl_state::FlashCmd_r), FUNC(crospuzl_state::FlashCmd_w));
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(crospuzl_state::idle_skip_resume_w)
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
}
WRITE_LINE_MEMBER(crospuzl_state::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif
void crospuzl_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
// save_item(NAME(m_Bank));
save_item(NAME(m_FlashCmd));
save_item(NAME(m_PIO));
@ -293,9 +225,6 @@ void crospuzl_state::machine_reset()
m_FlashAddr = 0;
m_FlashShift = 0;
m_FlashPrevCommand = 0xff;
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
m_ddr = 0xffffffff;
}
@ -433,49 +362,31 @@ INPUT_PORTS_END
void crospuzl_state::crospuzl(machine_config &config)
{
SE3208(config, m_maincpu, 14318180 * 3); // TODO : different between each PCBs
SE3208(config, m_maincpu, 14318180 * 3); // FIXME: 72 MHz-ish
m_maincpu->set_addrmap(AS_PROGRAM, &crospuzl_state::crospuzl_mem);
m_maincpu->set_irq_acknowledge_callback(FUNC(crospuzl_state::icallback));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(crospuzl_state::screen_update));
m_screen->screen_vblank().set(FUNC(crospuzl_state::screen_vblank));
m_screen->set_palette("palette");
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3); // FIXME: 72 MHz-ish
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
m_vr0soc->set_external_vclk(14318180 * 2); // Unknown clock, should output ~70 Hz?
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(crospuzl_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(crospuzl_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
// ROM strings have references to a K9FXX08 device
// TODO: use this device, in machine/smartmed.h (has issues with is_busy() emulation)
// NAND(config, m_nand, 0);
// m_nand->set_nand_type(nand_device::chip::K9F1G08U0B); // TODO: exact flavor
PCF8583(config, m_rtc, 32.768_kHz_XTAL);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
}
ROM_START( crospuzl )
ROM_REGION( 0x80010, "maincpu", 0 )
ROM_LOAD("en29lv040a.u5", 0x000000, 0x80010, CRC(d50e8500) SHA1(d681cd18cd0e48854c24291d417d2d6d28fe35c1) )
ROM_REGION( 0x8400010, "flash", ROMREGION_ERASEFF ) // NAND Flash
// mostly empty, but still looks good
ROM_LOAD("k9f1g08u0a.riser", 0x000000, 0x0020000, CRC(7f3c88c3) SHA1(db3169a7b4caab754e9d911998a2ece13c65ce5b) )
ROM_CONTINUE( 0x000000, 0x8400010-0x0020000 )
ROM_REGION( 0x8400010, "flash", ROMREGION_ERASE00 ) // NAND Flash
ROM_LOAD("k9f1g08u0a.riser", 0x00000, 0x8400010, BAD_DUMP CRC(7f3c88c3) SHA1(db3169a7b4caab754e9d911998a2ece13c65ce5b) )
ROM_COPY( "flash", 0x20000, 0x00000, 0x20000 )
ROM_END
GAME( 200?, crospuzl, 0, crospuzl, crospuzl, crospuzl_state, empty_init, ROT0, "<unknown>", "Cross Puzzle", MACHINE_NOT_WORKING )

View File

@ -141,33 +141,21 @@ Notes:
#include "machine/nvram.h"
#include "machine/eepromser.h"
#include "machine/vrender0.h"
#include "sound/vrender0.h"
#include "video/vrender0.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include <algorithm>
#define IDLE_LOOP_SPEEDUP
class crystal_state : public driver_device
{
public:
crystal_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_reset_patch(*this, "reset_patch"),
m_flash(*this, "flash"),
m_mainbank(*this, "mainbank"),
m_maincpu(*this, "maincpu"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_ds1302(*this, "rtc"),
m_screen(*this, "screen"),
m_eeprom(*this, "eeprom")
{ }
@ -184,8 +172,6 @@ public:
private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
optional_shared_ptr<uint32_t> m_reset_patch;
optional_region_ptr<uint32_t> m_flash;
@ -194,18 +180,9 @@ private:
/* devices */
required_device<se3208_device> m_maincpu;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
required_device<ds1302_device> m_ds1302;
required_device<screen_device> m_screen;
optional_device<eeprom_serial_93cxx_device> m_eeprom;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
uint32_t m_Bank;
uint32_t m_maxbank;
uint32_t m_FlashCmd;
@ -219,8 +196,6 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void PatchReset();
void crystal_mem(address_map &map);
@ -231,51 +206,11 @@ private:
uint32_t m_PIO;
};
uint32_t crystal_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(crystal_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(crystal_state::icallback)
{
return m_vr0soc->irq_callback();
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(crystal_state::idle_skip_resume_w)
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
}
WRITE_LINE_MEMBER(crystal_state::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif
READ32_MEMBER(crystal_state::system_input_r)
{
return ( ioport("SYSTEM")->read() << 16) | (ioport("DSW")->read()) | 0xff00ff00;
@ -368,10 +303,7 @@ void crystal_state::crystal_mem(address_map &map)
// mirror is accessed by donghaer on later levels
map(0x02000000, 0x027fffff).mirror(0x00800000).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
map(0x05000000, 0x05ffffff).bankr("mainbank");
map(0x05000000, 0x05000003).rw(FUNC(crystal_state::FlashCmd_r), FUNC(crystal_state::FlashCmd_w));
@ -433,9 +365,6 @@ loop:
void crystal_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
PatchReset();
if (m_mainbank)
@ -452,10 +381,6 @@ void crystal_state::machine_start()
m_mainbank->configure_entry(i, dummy_region);
}
}
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
}
void crystal_state::machine_reset()
@ -464,10 +389,6 @@ void crystal_state::machine_reset()
m_mainbank->set_entry(m_Bank);
m_FlashCmd = 0xff;
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
PatchReset();
}
@ -636,33 +557,10 @@ void crystal_state::crystal(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(crystal_state::screen_update));
m_screen->screen_vblank().set(FUNC(crystal_state::screen_vblank));
m_screen->set_palette("palette");
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3);
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(crystal_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(crystal_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
DS1302(config, m_ds1302, 32.768_kHz_XTAL);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
}

View File

@ -59,15 +59,10 @@ public:
ddz_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_ipl(*this, "ipl"),
m_encdata(*this, "enc_data"),
m_maincpu(*this, "maincpu"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_screen(*this, "screen")
m_vr0soc(*this, "vr0soc")
{ }
@ -78,78 +73,25 @@ private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
required_region_ptr<uint8_t> m_ipl;
required_region_ptr<uint8_t> m_encdata;
/* devices */
required_device<se3208_device> m_maincpu;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
required_device<screen_device> m_screen;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
IRQ_CALLBACK_MEMBER(icallback);
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void ddz_mem(address_map &map);
};
uint32_t ddz_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(ddz_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(ddz_state::icallback)
{
return m_vr0soc->irq_callback();
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(ddz_state::idle_skip_resume_w)
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
}
WRITE_LINE_MEMBER(ddz_state::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif
void ddz_state::ddz_mem(address_map &map)
{
map(0x00000000, 0x00ffffff).rom().nopw().region("ipl", 0);
@ -162,10 +104,7 @@ void ddz_state::ddz_mem(address_map &map)
map(0x02000000, 0x027fffff).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
}
static INPUT_PORTS_START( ddz )
@ -181,19 +120,12 @@ INPUT_PORTS_END
void ddz_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
// ...
}
void ddz_state::machine_reset()
{
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
// ...
}
void ddz_state::ddz(machine_config &config)
@ -202,31 +134,8 @@ void ddz_state::ddz(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &ddz_state::ddz_mem);
m_maincpu->set_irq_acknowledge_callback(FUNC(ddz_state::icallback));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(ddz_state::screen_update));
m_screen->screen_vblank().set(FUNC(ddz_state::screen_vblank));
m_screen->set_palette("palette");
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3);
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(ddz_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(ddz_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
}
ROM_START( ddz )

View File

@ -7,11 +7,13 @@
driver by Angelo Salese, based off original crystal.cpp by ElSemi
TODO:
- HY04 protection (controls tile RNG at very least)
- HY04 protection (controls tile RNG, 8bpp colors, a few program flow bits)
- 8bpp colors are washed, data from flash ROMs is XORed with contents
of NVRAM area 0x14000700-80f, might be shared with HY04 as well.
of NVRAM area 0x1400070b-80f in menghong, might be shared with
HY04 as well.
- EEPROM hookup;
- extract password code when entering test mode in-game;
- extract password code when entering test mode in-game (assuming the
0x485 workaround isn't enough);
=============================================================================
@ -71,60 +73,44 @@ Red PCB, very similar to crzyddz2
#include "machine/nvram.h"
#include "machine/eepromser.h"
#include "machine/vrender0.h"
#include "sound/vrender0.h"
#include "video/vrender0.h"
#include "machine/timer.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include <algorithm>
#define IDLE_LOOP_SPEEDUP
class menghong_state : public driver_device
{
public:
menghong_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_flash(*this, "flash"),
m_mainbank(*this, "mainbank"),
m_maincpu(*this, "maincpu"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
// m_nvram(*this, "nvram"),
m_ds1302(*this, "rtc"),
m_screen(*this, "screen"),
m_eeprom(*this, "eeprom")
m_eeprom(*this, "eeprom"),
m_prot_data(*this, "pic_data")
{ }
void crzyddz2(machine_config &config);
void menghong(machine_config &config);
private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
optional_region_ptr<uint32_t> m_flash;
optional_memory_bank m_mainbank;
/* devices */
required_device<se3208_device> m_maincpu;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
// required_device<nvram_device> m_nvram;
required_device<ds1302_device> m_ds1302;
required_device<screen_device> m_screen;
optional_device<eeprom_serial_93cxx_device> m_eeprom;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
required_region_ptr <uint8_t> m_prot_data;
uint32_t m_Bank;
uint32_t m_maxbank;
@ -140,46 +126,25 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void menghong_mem(address_map &map);
void crzyddz2_mem(address_map &map);
// PIO
DECLARE_READ32_MEMBER(PIOldat_r);
DECLARE_WRITE32_MEMBER(PIOldat_w);
DECLARE_READ32_MEMBER(PIOedat_r);
uint32_t m_PIO;
DECLARE_WRITE32_MEMBER(crzyddz2_PIOldat_w);
DECLARE_READ32_MEMBER(crzyddz2_PIOedat_r);
uint8_t m_crzyddz2_prot;
DECLARE_READ8_MEMBER(menghong_shared_r);
DECLARE_WRITE8_MEMBER(menghong_shared_w);
DECLARE_READ8_MEMBER(crzyddz2_shared_r);
DECLARE_WRITE8_MEMBER(crzyddz2_shared_w);
uint8_t *m_sharedram;
};
uint32_t menghong_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(menghong_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(menghong_state::icallback)
{
return m_vr0soc->irq_callback();
@ -223,6 +188,73 @@ WRITE32_MEMBER(menghong_state::FlashCmd_w)
// Crazy Dou Di Zhu II
// To do: HY04 (pic?) protection, 93C46 hookup
READ8_MEMBER(menghong_state::menghong_shared_r)
{
return m_sharedram[offset];
}
WRITE8_MEMBER(menghong_state::menghong_shared_w)
{
m_sharedram[offset] = data;
if (offset == 0x2a0)
{
if (data == 0x09)
{
// enables game settings by pressing start on password screen
m_sharedram[0x485] = 0x02;
// start at 0x140071b, up to 0x806, rolls back at 0x70c
// we conveniently use an handcrafted ROM here, created by guessing colors from
// transparencies and shading.
// This will be useful for comparison when the actual PIC data will be extracted.
for (int i=0;i<0x100;i++)
m_sharedram[i+0x70c] = m_prot_data[i];
// MCU also has a part in providing RNG
// hold service1 while selecting makes the user select "a set" (location in NVRAM tbd)
// 0x14005ca player 1 tiles
// 0x14005d9 player 1 discard pond
// 0x14005f9 available tiles
// 0x14005a5 cpu tiles
// 0x14005b4 cpu discard pond
}
}
}
READ8_MEMBER(menghong_state::crzyddz2_shared_r)
{
return m_sharedram[offset];
}
WRITE8_MEMBER(menghong_state::crzyddz2_shared_w)
{
m_sharedram[offset] = data;
// State machine is unconfirmed
if (offset == 0x7e3)
{
switch(data)
{
case 0x00:
m_sharedram[0x650] = 0x00; // prints 93c46 error otherwise
m_sharedram[0x651] = 0x03; // PC=2012188
break;
case 0xbb:
// this actually affects color again, game checksums the NVRAM contents
// at PC=0x2011f9a, expecting a value of 0x7ebe otherwise locks up
// after Sealy logo. Every single value is added to the routine and left
// shifted by 1 (including the two values above)
for(int i=0;i<0x3f;i++)
m_sharedram[i+0x652] = 0xff;
m_sharedram[0x691] = 0x9b;
break;
// additional locking protection is also applied with RNG feature
// PC=0x2036756 tight loops if R1=0
}
}
}
READ32_MEMBER(menghong_state::PIOldat_r)
{
return m_PIO;
@ -279,14 +311,16 @@ crzyddz2 in out
return 0xffffff00 | data | m_crzyddz2_prot;
}
void menghong_state::crzyddz2_mem(address_map &map)
void menghong_state::menghong_mem(address_map &map)
{
map(0x00000000, 0x003fffff).rom().nopw();
map(0x01280000, 0x01280003).w(FUNC(menghong_state::Banksw_w));
map(0x01400000, 0x0140ffff).ram().share("nvram");
// map(0x01400000, 0x0140ffff).ram().share("nvram");
map(0x01400000, 0x0140ffff).rw(FUNC(menghong_state::menghong_shared_r), FUNC(menghong_state::menghong_shared_w));
map(0x01500000, 0x01500003).portr("P1_P2");
map(0x01500004, 0x01500007).r(FUNC(menghong_state::crzyddz2_key_r));
map(0x01500008, 0x0150000b).portr("SYSTEM");
map(0x01800000, 0x01ffffff).m(m_vr0soc, FUNC(vrender0soc_device::regs_map));
map(0x01802004, 0x01802007).rw(FUNC(menghong_state::PIOldat_r), FUNC(menghong_state::crzyddz2_PIOldat_w));
@ -294,36 +328,22 @@ void menghong_state::crzyddz2_mem(address_map &map)
map(0x02000000, 0x027fffff).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
map(0x05000000, 0x05ffffff).bankr("mainbank");
map(0x05000000, 0x05000003).rw(FUNC(menghong_state::FlashCmd_r), FUNC(menghong_state::FlashCmd_w));
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(menghong_state::idle_skip_resume_w)
void menghong_state::crzyddz2_mem(address_map &map)
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
menghong_mem(map);
map(0x01400000, 0x0140ffff).rw(FUNC(menghong_state::crzyddz2_shared_r), FUNC(menghong_state::crzyddz2_shared_w));
}
WRITE_LINE_MEMBER(menghong_state::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif
void menghong_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
m_sharedram = auto_alloc_array_clear(machine(), uint8_t, 0x10000);
if (m_mainbank)
{
m_maxbank = (m_flash) ? m_flash.bytes() / 0x1000000 : 0;
@ -339,11 +359,6 @@ void menghong_state::machine_start()
}
}
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
save_item(NAME(m_Bank));
save_item(NAME(m_FlashCmd));
save_item(NAME(m_PIO));
@ -355,10 +370,6 @@ void menghong_state::machine_reset()
m_mainbank->set_entry(m_Bank);
m_FlashCmd = 0xff;
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
m_crzyddz2_prot = 0x00;
}
@ -374,14 +385,42 @@ static INPUT_PORTS_START(crzyddz2)
PORT_BIT( 0x00000080, IP_ACTIVE_LOW, IPT_BUTTON4 ) // D
PORT_BIT( 0x0000ff00, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_START1 ) // start (secret code screen)
PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_SERVICE2 ) // .. 2 (next secret code / stats)
PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_SERVICE ) // .. 1 (secret code screen / service mode)
PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_SERVICE1 ) // .. 3 (inc secret code / credit)
PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_SERVICE3 ) // .. 4 (exit secret screen / clear credits)
PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_SERVICE4 ) // (reset and clear ram?)
PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_START1 ) // start (secret code screen)
PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Operator Mode")
PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_SERVICE ) // .. 1 (secret code screen / service mode)
PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_SERVICE2 ) // not service mode
PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_SERVICE3 ) PORT_NAME("Clear RAM")
PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0xff000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("SYSTEM")
PORT_BIT( 0x0000ffff, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_DIPNAME( 0x010000, 0x010000, "DSWA" )
PORT_DIPSETTING( 0x010000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x020000, 0x020000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x020000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x040000, 0x040000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x040000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x080000, 0x080000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x080000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x100000, 0x100000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x100000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x200000, 0x200000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x200000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x400000, 0x400000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x400000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_DIPNAME( 0x800000, 0x800000, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x800000, DEF_STR( Off ) )
PORT_DIPSETTING( 0x000000, DEF_STR( On ) )
PORT_BIT( 0xff000000, IP_ACTIVE_LOW, IPT_UNKNOWN )
// 1500004 (multiplexed by 1802005)
@ -426,68 +465,58 @@ static INPUT_PORTS_START(crzyddz2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_MAHJONG_SMALL ) // small + D
INPUT_PORTS_END
void menghong_state::crzyddz2(machine_config &config)
void menghong_state::menghong(machine_config &config)
{
SE3208(config, m_maincpu, 14318180 * 3); // TODO : different between each PCBs
m_maincpu->set_addrmap(AS_PROGRAM, &menghong_state::crzyddz2_mem);
m_maincpu->set_addrmap(AS_PROGRAM, &menghong_state::menghong_mem);
m_maincpu->set_irq_acknowledge_callback(FUNC(menghong_state::icallback));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
// HY04 running at 8 MHz
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(menghong_state::screen_update));
m_screen->screen_vblank().set(FUNC(menghong_state::screen_vblank));
m_screen->set_palette("palette");
// NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3);
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(menghong_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(menghong_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
m_vr0soc->set_external_vclk(28636360); // Assumed from the only available XTal on PCB
DS1302(config, m_ds1302, 32.768_kHz_XTAL);
EEPROM_93C46_16BIT(config, "eeprom");
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
}
ROM_START( crzyddz2 )
ROM_REGION32_LE( 0x1000000, "flash", 0 ) // Flash
ROM_LOAD( "rom.u48", 0x000000, 0x1000000, CRC(0f3a1987) SHA1(6cad943846c79db31226676c7391f32216cfff79) )
ROM_REGION( 0x0400000, "maincpu", ROMREGION_ERASEFF )
//ROM_COPY( "flash", 0x000000, 0x000000, 0x1000000 ) // copy flash here
ROM_LOAD( "27c322.u49", 0x000000, 0x0400000, CRC(b3177f39) SHA1(2a28bf8045bd2e053d88549b79fbc11f30ef9a32) ) // 1ST AND 2ND HALF IDENTICAL
ROM_REGION( 0x4280, "pic", 0 ) // hy04
ROM_LOAD("hy04", 0x000000, 0x4280, NO_DUMP )
ROM_END
void menghong_state::crzyddz2(machine_config &config)
{
menghong(config);
m_maincpu->set_addrmap(AS_PROGRAM, &menghong_state::crzyddz2_mem);
}
ROM_START( menghong )
ROM_REGION32_LE( 0x1000000, "flash", 0 ) // Flash
ROM_LOAD( "rom.u48", 0x000000, 0x1000000, CRC(e24257c4) SHA1(569d79a61ff6d35100ba5727069363146df9e0b7) )
ROM_REGION( 0x0400000, "maincpu", 0 )
//ROM_COPY( "flash", 0x000000, 0x000000, 0x1000000 ) // copy flash here
ROM_LOAD( "060511_08-01-18.u49", 0x0000000, 0x0200000, CRC(b0c12107) SHA1(b1753757bbdb7d996df563ac6abdc6b46676704b) ) // 27C160
ROM_RELOAD( 0x0200000, 0x0200000 )
ROM_REGION( 0x4280, "pic", 0 ) // hy04
ROM_LOAD("menghong_hy04", 0x000000, 0x4280, NO_DUMP )
ROM_REGION( 0x0100, "pic_data", ROMREGION_ERASEFF )
ROM_LOAD("hy04_fake_data.bin", 0, 0x100, BAD_DUMP CRC(73cc964b) SHA1(39d223c550e38c97135322e43ccabb70f04964b9) )
ROM_END
GAME( 2004?,menghong, 0, crzyddz2, crzyddz2, menghong_state, empty_init, ROT0, "Sealy", "Meng Hong Lou", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION )
ROM_START( crzyddz2 )
ROM_REGION32_LE( 0x1000000, "flash", 0 ) // Flash
ROM_LOAD( "rom.u48", 0x000000, 0x1000000, CRC(0f3a1987) SHA1(6cad943846c79db31226676c7391f32216cfff79) )
ROM_REGION( 0x0400000, "maincpu", ROMREGION_ERASEFF )
ROM_LOAD( "27c322.u49", 0x000000, 0x0400000, CRC(b3177f39) SHA1(2a28bf8045bd2e053d88549b79fbc11f30ef9a32) ) // 1ST AND 2ND HALF IDENTICAL
ROM_REGION( 0x4280, "pic", 0 ) // hy04
ROM_LOAD("hy04", 0x000000, 0x4280, NO_DUMP )
ROM_REGION( 0x0100, "pic_data", ROMREGION_ERASEFF )
ROM_END
GAME( 2004?,menghong, 0, menghong, crzyddz2, menghong_state, empty_init, ROT0, "Sealy", "Meng Hong Lou", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION )
GAME( 2006, crzyddz2, 0, crzyddz2, crzyddz2, menghong_state, empty_init, ROT0, "Sealy", "Crazy Dou Di Zhu II", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION )

View File

@ -8,7 +8,10 @@
TODO:
- Compact Flash hookup;
- Enables wavetable IRQ;
- Requires timed based FIFO renderer, loops until both rear and front
are equal.
- Enables wavetable IRQ, even if so far no channel enables the submask;
- Unemulated 93C86 EEPROM device;
=============================================================================
@ -127,15 +130,9 @@ GUN_xP are 6 pin gun connectors (pins 3-6 match the UNICO sytle guns):
#include "machine/nvram.h"
#include "machine/eepromser.h"
#include "machine/vrender0.h"
#include "sound/vrender0.h"
#include "video/vrender0.h"
#include "machine/ataintf.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include <algorithm>
#define IDLE_LOOP_SPEEDUP
class psattack_state : public driver_device
{
@ -143,13 +140,9 @@ public:
psattack_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_maincpu(*this, "maincpu"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_screen(*this, "screen")
m_ata(*this, "ata")
{ }
@ -160,75 +153,51 @@ private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
/* devices */
required_device<se3208_device> m_maincpu;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
required_device<screen_device> m_screen;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
required_device<ata_interface_device> m_ata;
IRQ_CALLBACK_MEMBER(icallback);
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void psattack_mem(address_map &map);
DECLARE_READ16_MEMBER(cfcard_data_r);
DECLARE_READ8_MEMBER(cfcard_regs_r);
DECLARE_WRITE8_MEMBER(cfcard_regs_w);
DECLARE_WRITE32_MEMBER(output_w);
};
uint32_t psattack_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(psattack_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(psattack_state::icallback)
{
return m_vr0soc->irq_callback();
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(psattack_state::idle_skip_resume_w)
// TODO: wrong, likely PIC protected too
READ8_MEMBER( psattack_state::cfcard_regs_r )
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
return m_ata->read_cs0(offset & 7, 0x000000ff);
}
WRITE_LINE_MEMBER(psattack_state::idle_skip_speedup_w)
WRITE8_MEMBER( psattack_state::cfcard_regs_w )
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
m_ata->write_cs0(offset & 7, 0x000000ff);
}
#endif
READ16_MEMBER( psattack_state::cfcard_data_r )
{
return m_ata->read_cs0(0, 0x0000ffff);
}
WRITE32_MEMBER( psattack_state::output_w )
{
// suppress logging for now
if (data)
logerror("output_w: %08x & %08x\n",data,mem_mask);
}
void psattack_state::psattack_mem(address_map &map)
{
@ -236,20 +205,21 @@ void psattack_state::psattack_mem(address_map &map)
// 0x1400c00, 0x1400c01 read cfcard memory (auto increment?)
// 0x1402800, 0x1402807 read/write regs?
// 0x1802410, 0x1802413 peripheral chip select for above
map(0x01500000, 0x01500003).portr("IN0");
// cf card interface
map(0x01400c00, 0x01400c01).r(FUNC(psattack_state::cfcard_data_r));
map(0x01402800, 0x01402807).rw(FUNC(psattack_state::cfcard_regs_r), FUNC(psattack_state::cfcard_regs_w));
map(0x01500000, 0x01500003).portr("IN0").w(FUNC(psattack_state::output_w));
map(0x01500004, 0x01500007).portr("IN1");
map(0x01500008, 0x0150000b).portr("IN2");
//0x0150000c is prolly eeprom
// 0x0150000c is prolly eeprom
map(0x01800000, 0x01ffffff).m(m_vr0soc, FUNC(vrender0soc_device::regs_map));
// map(0x01802410, 0x01802413) peripheral chip select for cf?
map(0x02000000, 0x027fffff).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
}
static INPUT_PORTS_START( psattack )
@ -265,19 +235,12 @@ INPUT_PORTS_END
void psattack_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
// ...
}
void psattack_state::machine_reset()
{
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
// ...
}
void psattack_state::psattack(machine_config &config)
@ -286,31 +249,13 @@ void psattack_state::psattack(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &psattack_state::psattack_mem);
m_maincpu->set_irq_acknowledge_callback(FUNC(psattack_state::icallback));
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(psattack_state::screen_update));
m_screen->screen_vblank().set(FUNC(psattack_state::screen_vblank));
m_screen->set_palette("palette");
// PIC16C711
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3);
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
m_vr0soc->set_external_vclk(XTAL(25'175'000)); // assumed from the only available XTal on PCB
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(psattack_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(psattack_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
ATA_INTERFACE(config, m_ata).options(ata_devices, "hdd", nullptr, true);
}
ROM_START( psattack )
@ -321,8 +266,8 @@ ROM_START( psattack )
ROM_LOAD("16c711.pic", 0x0000, 0x137b, CRC(617d8292) SHA1(d32d6054ce9db2e31efaf41015afcc78ed32f6aa) ) // raw dump
ROM_LOAD("16c711.bin", 0x0000, 0x4010, CRC(b316693f) SHA1(eba1f75043bd415268eedfdb95c475e73c14ff86) ) // converted to binary
DISK_REGION( "cfcard" )
DISK_IMAGE_READONLY( "psattack", 0, SHA1(e99cd0dafc33ec13bf56061f81dc7c0a181594ee) )
DISK_REGION( "ata:0:hdd:image" )
DISK_IMAGE( "psattack", 0, SHA1(e99cd0dafc33ec13bf56061f81dc7c0a181594ee) )
ROM_END
void psattack_state::init_psattack()

View File

@ -1,14 +1,17 @@
// license:BSD-3-Clause
// copyright-holders:Angelo Salese
// copyright-holders:Luca Elia, Angelo Salese
/****************************************************************************
Trivia R Us (c) 2009 AGT
driver by Angelo Salese, based off original crystal.cpp by ElSemi
original mods on this driver by Luca Elia
TODO:
- touch panel;
- RTC;
- touch panel, according to service mode can be generic, atouch or 3M
(microtouch?). It interfaces thru UART0 port;
- RTC (unknown type);
- Split romset or add a slot option supporting debug terminal mode;
=============================================================================
@ -16,36 +19,26 @@
#include "emu.h"
#include "cpu/se3208/se3208.h"
#include "machine/ds1302.h"
#include "machine/nvram.h"
#include "machine/eepromser.h"
#include "machine/vrender0.h"
#include "sound/vrender0.h"
#include "video/vrender0.h"
#include "machine/microtch.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
#include <algorithm>
#define IDLE_LOOP_SPEEDUP
class trivrus_state : public driver_device
{
public:
trivrus_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_workram(*this, "workram"),
m_textureram(*this, "textureram"),
m_frameram(*this, "frameram"),
m_flash(*this, "flash"),
m_maincpu(*this, "maincpu"),
m_mainbank(*this, "mainbank"),
m_vr0soc(*this, "vr0soc"),
m_vr0vid(*this, "vr0vid"),
m_vr0snd(*this, "vr0snd"),
m_ds1302(*this, "rtc"),
m_screen(*this, "screen")
m_microtouch(*this, "microtouch")
{ }
@ -55,24 +48,13 @@ private:
/* memory pointers */
required_shared_ptr<uint32_t> m_workram;
required_shared_ptr<uint32_t> m_textureram;
required_shared_ptr<uint32_t> m_frameram;
required_region_ptr<uint32_t> m_flash;
/* devices */
required_device<se3208_device> m_maincpu;
optional_memory_bank m_mainbank;
required_device<vrender0soc_device> m_vr0soc;
required_device<vr0video_device> m_vr0vid;
required_device<vr0sound_device> m_vr0snd;
required_device<ds1302_device> m_ds1302;
required_device<screen_device> m_screen;
#ifdef IDLE_LOOP_SPEEDUP
uint8_t m_FlipCntRead;
DECLARE_WRITE_LINE_MEMBER(idle_skip_resume_w);
DECLARE_WRITE_LINE_MEMBER(idle_skip_speedup_w);
#endif
required_device<microtouch_device> m_microtouch;
uint32_t m_FlashCmd;
uint32_t m_Bank;
@ -86,8 +68,6 @@ private:
virtual void machine_start() override;
virtual void machine_reset() override;
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
DECLARE_WRITE_LINE_MEMBER(screen_vblank);
void trivrus_mem(address_map &map);
// PIO
@ -101,31 +81,6 @@ private:
uint8_t m_trivrus_input;
};
uint32_t trivrus_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
if (m_vr0soc->crt_is_blanked()) // Blank Screen
{
bitmap.fill(0, cliprect);
return 0;
}
m_vr0vid->screen_update(screen, bitmap, cliprect);
return 0;
}
WRITE_LINE_MEMBER(trivrus_state::screen_vblank)
{
// rising edge
if (state)
{
if (m_vr0soc->crt_active_vblank_irq() == true)
m_vr0soc->IntReq(24); //VRender0 VBlank
m_vr0vid->execute_drawing();
}
}
IRQ_CALLBACK_MEMBER(trivrus_state::icallback)
{
return m_vr0soc->irq_callback();
@ -138,26 +93,19 @@ WRITE32_MEMBER(trivrus_state::FlashCmd_w)
READ32_MEMBER(trivrus_state::PIOedat_r)
{
return m_ds1302->io_r() << 28;
return 0;
}
READ32_MEMBER(trivrus_state::PIOldat_r)
{
// ...
return m_PIO;
}
// PIO Latched output DATa Register
// TODO: change me
WRITE32_MEMBER(trivrus_state::PIOldat_w)
{
uint32_t RST = data & 0x01000000;
uint32_t CLK = data & 0x02000000;
uint32_t DAT = data & 0x10000000;
m_ds1302->ce_w(RST ? 1 : 0);
m_ds1302->io_w(DAT ? 1 : 0);
m_ds1302->sclk_w(CLK ? 1 : 0);
// ...
COMBINE_DATA(&m_PIO);
}
@ -214,16 +162,19 @@ void trivrus_state::trivrus_mem(address_map &map)
{
map(0x00000000, 0x0007ffff).rom().nopw();
// map(0x01280000, 0x01280003).w(FUNC(trivrus_state::Banksw_w));
map(0x01280000, 0x01280003).w(FUNC(trivrus_state::Banksw_w));
// 0x01280000 & 0x0000ffff (written at boot)
map(0x01500000, 0x01500000).rw(FUNC(trivrus_state::trivrus_input_r), FUNC(trivrus_state::trivrus_input_w));
// 0x01500010 & 0x000000ff = sec
// 0x01500010 & 0x00ff0000 = min
// 0x01500014 & 0x000000ff = hour
// 0x01500014 & 0x00ff0000 = day
// 0x01500018 & 0x000000ff = month
// 0x0150001c & 0x000000ff = year - 2000
// reads occurs by SELECTING the given register on successive ODD addresses then reading at 0x01500011
// bit 0 of 1500010 looks some kind of busy flag (game tight loops if on)
// on write:
// 0x01500010 = sec
// 0x01500012 = min
// 0x01500014 = hour
// 0x01500016 = day
// 0x01500018 = month
// 0x0150001c = year - 2000
// all regs are in BCD format
map(0x01600000, 0x01607fff).ram().share("nvram");
map(0x01800000, 0x01ffffff).m(m_vr0soc, FUNC(vrender0soc_device::regs_map));
@ -232,36 +183,15 @@ void trivrus_state::trivrus_mem(address_map &map)
map(0x02000000, 0x027fffff).ram().share("workram");
map(0x03000000, 0x0300ffff).m(m_vr0vid, FUNC(vr0video_device::regs_map));
map(0x03800000, 0x03ffffff).ram().share("textureram");
map(0x04000000, 0x047fffff).ram().share("frameram");
map(0x04800000, 0x04800fff).rw(m_vr0snd, FUNC(vr0sound_device::vr0_snd_read), FUNC(vr0sound_device::vr0_snd_write));
map(0x03000000, 0x04ffffff).m(m_vr0soc, FUNC(vrender0soc_device::audiovideo_map));
map(0x05000000, 0x05ffffff).bankr("mainbank");
map(0x05000000, 0x05000003).rw(FUNC(trivrus_state::FlashCmd_r), FUNC(trivrus_state::FlashCmd_w));
// 0x06000000 accessed during POST during above check then discarded, probably a debug left-over
}
#ifdef IDLE_LOOP_SPEEDUP
WRITE_LINE_MEMBER(trivrus_state::idle_skip_resume_w)
{
m_FlipCntRead = 0;
m_maincpu->resume(SUSPEND_REASON_SPIN);
}
WRITE_LINE_MEMBER(trivrus_state::idle_skip_speedup_w)
{
m_FlipCntRead++;
if (m_FlipCntRead >= 16 && m_vr0soc->irq_pending() == false && state == ASSERT_LINE)
m_maincpu->suspend(SUSPEND_REASON_SPIN, 1);
}
#endif
void trivrus_state::machine_start()
{
m_vr0vid->set_areas(reinterpret_cast<uint8_t*>(m_textureram.target()), reinterpret_cast<uint16_t*>(m_frameram.target()));
m_vr0snd->set_areas(m_textureram, m_frameram);
if (m_mainbank)
{
m_maxbank = (m_flash) ? m_flash.bytes() / 0x1000000 : 0;
@ -277,10 +207,6 @@ void trivrus_state::machine_start()
}
}
#ifdef IDLE_LOOP_SPEEDUP
save_item(NAME(m_FlipCntRead));
#endif
save_item(NAME(m_Bank));
save_item(NAME(m_FlashCmd));
save_item(NAME(m_PIO));
@ -292,31 +218,27 @@ void trivrus_state::machine_reset()
m_Bank = 0;
m_mainbank->set_entry(m_Bank);
m_FlashCmd = 0xff;
#ifdef IDLE_LOOP_SPEEDUP
m_FlipCntRead = 0;
#endif
}
static INPUT_PORTS_START(trivrus)
static INPUT_PORTS_START( trivrus )
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Up") PORT_CODE(KEYCODE_UP)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Left/True") PORT_CODE(KEYCODE_LEFT)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Up")
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Left/True")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Down")
PORT_START("IN2")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Enter/Exit")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Next")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_NAME("Enter/Exit")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_NAME("Next")
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Right/False") PORT_CODE(KEYCODE_RIGHT)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_NAME("Right/False")
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(2) // with 1 impulse it misses often
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN3")
@ -325,30 +247,30 @@ static INPUT_PORTS_START(trivrus)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Sound")
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_NAME("Sound")
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN4")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_OTHER )PORT_CODE(KEYCODE_9)
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN5")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) // Free Game
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Free Game Switch")
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) // Setup
PORT_SERVICE_NO_TOGGLE( 0x08, IP_ACTIVE_LOW ) PORT_NAME("Setup")
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("DSW")
PORT_DIPNAME( 0x01, 0x01, "Interlace?" )
PORT_DIPSETTING( 0x01, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x02, 0x02, "Serial?" )
PORT_DIPNAME( 0x01, 0x01, "Monitor Type" )
PORT_DIPSETTING( 0x01, "VGA" )
PORT_DIPSETTING( 0x00, "Normal" )
PORT_DIPNAME( 0x02, 0x02, "UART Monitor Mode" ) // communicates via UART0 port to an unknown device (presumably a terminal, unemulated)
PORT_DIPSETTING( 0x02, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) ) // hangs at boot
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) )
PORT_DIPSETTING( 0x04, DEF_STR( Off ) )
PORT_DIPSETTING( 0x00, DEF_STR( On ) )
@ -371,39 +293,19 @@ INPUT_PORTS_END
void trivrus_state::trivrus(machine_config &config)
{
SE3208(config, m_maincpu, 14318180 * 3); // TODO : different between each PCBs
SE3208(config, m_maincpu, 14318180 * 3); // unknown clock
m_maincpu->set_addrmap(AS_PROGRAM, &trivrus_state::trivrus_mem);
m_maincpu->set_irq_acknowledge_callback(FUNC(trivrus_state::icallback));
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
// evolution soccer defaults
m_screen->set_raw((XTAL(14'318'180)*2)/4, 455, 0, 320, 262, 0, 240);
m_screen->set_screen_update(FUNC(trivrus_state::screen_update));
m_screen->screen_vblank().set(FUNC(trivrus_state::screen_vblank));
m_screen->set_palette("palette");
VRENDER0_SOC(config, m_vr0soc, 0);
VRENDER0_SOC(config, m_vr0soc, 14318180 * 3);
m_vr0soc->set_host_cpu_tag(m_maincpu);
m_vr0soc->set_host_screen_tag(m_screen);
VIDEO_VRENDER0(config, m_vr0vid, 14318180, m_maincpu);
#ifdef IDLE_LOOP_SPEEDUP
m_vr0soc->idleskip_cb().set(FUNC(trivrus_state::idle_skip_resume_w));
m_vr0vid->idleskip_cb().set(FUNC(trivrus_state::idle_skip_speedup_w));
#endif
PALETTE(config, "palette", palette_device::RGB_565);
DS1302(config, m_ds1302, 32.768_kHz_XTAL);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
SOUND_VRENDER0(config, m_vr0snd, 0);
m_vr0snd->add_route(0, "lspeaker", 1.0);
m_vr0snd->add_route(1, "rspeaker", 1.0);
m_vr0soc->set_external_vclk(28636360);
m_vr0soc->tx_callback<0>().set(m_microtouch, FUNC(microtouch_device::rx));
// TODO: 3M from service mode, most likely wrong?
MICROTOUCH(config, m_microtouch, 9600).stx().set(m_vr0soc, FUNC(vrender0soc_device::rx_w<0>));
}
ROM_START( trivrus )

View File

@ -1,10 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:ElSemi
#include "emu.h"
#include "vrender0.h"
/***********************************
/*****************************************************************************************
VRENDER ZERO
VIDEO EMULATION By ElSemi
@ -16,8 +12,17 @@
It supports alphablend with programmable factors per channel and for source and dest
color.
************************************/
TODO:
- Dither Mode;
- Draw select to Front buffer is untested, speculatively gonna be used for raster
effects;
- screen_update doesn't honor CRT Display Start registers,
so far only psattack changes it on-the-fly, for unknown reasons;
*****************************************************************************************/
#include "emu.h"
#include "vrender0.h"
/*****************************************************************************
DEVICE INTERFACE
@ -28,7 +33,6 @@ DEFINE_DEVICE_TYPE(VIDEO_VRENDER0, vr0video_device, "vr0video", "MagicEyes VRend
vr0video_device::vr0video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, VIDEO_VRENDER0, tag, owner, clock)
, device_video_interface(mconfig, *this)
, m_cpu(*this, finder_base::DUMMY_TAG)
, m_idleskip_cb(*this)
{
@ -158,9 +162,10 @@ void vr0video_device::device_start()
save_item(NAME(m_dither_mode));
}
void vr0video_device::set_areas(uint8_t *textureram, uint16_t *frameram)
void vr0video_device::set_areas(uint16_t *textureram, uint16_t *frameram)
{
m_textureram = textureram;
m_textureram = (uint8_t *)textureram;
m_packetram = textureram;
m_frameram = frameram;
}
@ -172,6 +177,8 @@ void vr0video_device::device_reset()
{
memset(m_InternalPalette, 0, sizeof(m_InternalPalette));
m_LastPalUpdate = 0xffffffff;
m_DisplayDest = m_DrawDest = m_frameram;
}
/*****************************************************************************
@ -495,22 +502,21 @@ static const _DrawTemplate DrawTile[]=
TILENAME(16,1,2),
};
#define Packet(i) space.read_word(PacketPtr + 2 * i)
//Returns true if the operation was a flip (sync or async)
// TODO: async loading actually doesn't stop rendering but just flips the render bank
int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr)
{
// TODO: this need to be removed
address_space &space = m_cpu->space(AS_PROGRAM);
uint16_t *Packet = m_packetram;
uint8_t *TEXTURE = m_textureram;
uint32_t Dx = Packet(1) & 0x3ff;
uint32_t Dy = Packet(2) & 0x1ff;
uint32_t Endx = Packet(3) & 0x3ff;
uint32_t Endy = Packet(4) & 0x1ff;
Packet += PacketPtr;
uint32_t Dx = Packet[1] & 0x3ff;
uint32_t Dy = Packet[2] & 0x1ff;
uint32_t Endx = Packet[3] & 0x3ff;
uint32_t Endy = Packet[4] & 0x1ff;
uint32_t Mode = 0;
uint16_t Packet0 = Packet(0);
uint16_t Packet0 = Packet[0];
if (Packet0 & 0x81) //Sync or ASync flip
{
@ -520,8 +526,8 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
if (Packet0 & 0x200)
{
m_RenderState.Tx = Packet(5) | ((Packet(6) & 0x1f) << 16);
m_RenderState.Ty = Packet(7) | ((Packet(8) & 0x1f) << 16);
m_RenderState.Tx = Packet[5] | ((Packet[6] & 0x1f) << 16);
m_RenderState.Ty = Packet[7] | ((Packet[8] & 0x1f) << 16);
}
else
{
@ -530,10 +536,10 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
}
if (Packet0 & 0x400)
{
m_RenderState.Txdx = Packet(9) | ((Packet(10) & 0x1f) << 16);
m_RenderState.Tydx = Packet(11) | ((Packet(12) & 0x1f) << 16);
m_RenderState.Txdy = Packet(13) | ((Packet(14) & 0x1f) << 16);
m_RenderState.Tydy = Packet(15) | ((Packet(16) & 0x1f) << 16);
m_RenderState.Txdx = Packet[9] | ((Packet[10] & 0x1f) << 16);
m_RenderState.Tydx = Packet[11] | ((Packet[12] & 0x1f) << 16);
m_RenderState.Txdy = Packet[13] | ((Packet[14] & 0x1f) << 16);
m_RenderState.Tydy = Packet[15] | ((Packet[16] & 0x1f) << 16);
}
else
{
@ -544,25 +550,25 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
}
if (Packet0 & 0x800)
{
m_RenderState.SrcAlphaColor = Packet(17) | ((Packet(18) & 0xff) << 16);
m_RenderState.SrcBlend = (Packet(18) >> 8) & 0x3f;
m_RenderState.DstAlphaColor = Packet(19) | ((Packet(20) & 0xff) << 16);
m_RenderState.DstBlend = (Packet(20) >> 8) & 0x3f;
m_RenderState.SrcAlphaColor = Packet[17] | ((Packet[18] & 0xff) << 16);
m_RenderState.SrcBlend = (Packet[18] >> 8) & 0x3f;
m_RenderState.DstAlphaColor = Packet[19] | ((Packet[20] & 0xff) << 16);
m_RenderState.DstBlend = (Packet[20] >> 8) & 0x3f;
}
if (Packet0 & 0x1000)
m_RenderState.ShadeColor = Packet(21) | ((Packet(22) & 0xff) << 16);
m_RenderState.ShadeColor = Packet[21] | ((Packet[22] & 0xff) << 16);
if (Packet0 & 0x2000)
m_RenderState.TransColor = Packet(23) | ((Packet(24) & 0xff) << 16);
m_RenderState.TransColor = Packet[23] | ((Packet[24] & 0xff) << 16);
if (Packet0 & 0x4000)
{
m_RenderState.TileOffset = Packet(25);
m_RenderState.FontOffset = Packet(26);
m_RenderState.PalOffset = Packet(27) >> 3;
m_RenderState.PaletteBank = (Packet(28) >> 8) & 0xf;
m_RenderState.TextureMode = Packet(28) & 0x1000;
m_RenderState.PixelFormat = (Packet(28) >> 6) & 3;
m_RenderState.Width = 8 << ((Packet(28) >> 0) & 0x7);
m_RenderState.Height = 8 << ((Packet(28) >> 3) & 0x7);
m_RenderState.TileOffset = Packet[25];
m_RenderState.FontOffset = Packet[26];
m_RenderState.PalOffset = Packet[27] >> 3;
m_RenderState.PaletteBank = (Packet[28] >> 8) & 0xf;
m_RenderState.TextureMode = Packet[28] & 0x1000;
m_RenderState.PixelFormat = (Packet[28] >> 6) & 3;
m_RenderState.Width = 8 << ((Packet[28] >> 0) & 0x7);
m_RenderState.Height = 8 << ((Packet[28] >> 3) & 0x7);
}
if (Packet0 & 0x40 && m_RenderState.PalOffset != m_LastPalUpdate)
@ -574,6 +580,8 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
{
uint32_t p = Pal[i];
uint16_t v = RGB32TO16(p);
// TODO: this is most likely an artifact of not emulating the dither modes,
// and it's wrong anyway: topbladv gameplay fighters sports a slighty visible square shadow block.
if ((v == Trans && p != m_RenderState.TransColor) || v == NOTRANSCOLOR) //Error due to conversion. caused transparent
{
if ((v & 0x1f) != 0x1f)
@ -608,7 +616,7 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
Quad.w = 1 + Endx - Dx;
Quad.h = 1 + Endy - Dy;
Quad.Dest = (uint16_t*) Dest;
Quad.Dest = m_DrawDest;
Quad.Dest = Quad.Dest + Dx + (Dy * Quad.Pitch);
Quad.Tx = m_RenderState.Tx;
@ -647,6 +655,7 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
Quad.Pal = m_InternalPalette + (m_RenderState.PaletteBank * 16);
else
Quad.Pal = m_InternalPalette;
if (m_RenderState.TextureMode) //Tiled
DrawTile[m_RenderState.PixelFormat + 4 * Mode](&Quad);
else
@ -658,14 +667,13 @@ int vr0video_device::vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest)
return 0;
}
void vr0video_device::execute_drawing()
void vr0video_device::execute_flipping()
{
if (m_render_start == false)
return;
uint32_t B0 = 0x000000;
uint32_t B1 = (m_bank1_select == true ? 0x400000 : 0x100000)/2;
uint16_t *DrawDest;
uint16_t *Front, *Back;
int DoFlip = 0;
@ -680,11 +688,12 @@ void vr0video_device::execute_drawing()
Back = (m_frameram + B1);
}
DrawDest = ((m_draw_select == true) ? Front : Back);
m_DrawDest = ((m_draw_select == true) ? Front : Back);
m_DisplayDest = Front;
while ((m_queue_rear & 0x7ff) != (m_queue_front & 0x7ff))
{
DoFlip = vrender0_ProcessPacket(0x03800000 + m_queue_rear * 64, DrawDest);
DoFlip = vrender0_ProcessPacket(m_queue_rear * 32);
m_queue_rear ++;
m_queue_rear &= 0x7ff;
if (DoFlip)
@ -703,20 +712,11 @@ void vr0video_device::execute_drawing()
uint32_t vr0video_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
uint16_t *Visible;
const uint32_t width = cliprect.width();
uint32_t B0 = 0x000000;
uint32_t B1 = (m_bank1_select == true ? 0x400000 : 0x100000)/2;
if (m_display_bank & 1)
Visible = (m_frameram + B1);
else
Visible = (m_frameram + B0);
uint32_t const dx = cliprect.left();
for (int y = cliprect.top(); y <= cliprect.bottom(); y++)
std::copy_n(&Visible[(y * 1024) + dx], width, &bitmap.pix16(y, dx));
std::copy_n(&m_DisplayDest[(y * 1024) + dx], width, &bitmap.pix16(y, dx));
return 0;
}

View File

@ -14,17 +14,11 @@ class vr0video_device : public device_t,
public device_video_interface
{
public:
template <typename T> vr0video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, T &&cpu_tag)
: vr0video_device(mconfig, tag, owner, clock)
{
m_cpu.set_tag(std::forward<T>(cpu_tag));
}
vr0video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
void set_areas(uint8_t *textureram, uint16_t *frameram);
void set_areas(uint16_t *textureram, uint16_t *frameram);
void regs_map(address_map &map);
void execute_drawing();
void execute_flipping();
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
auto idleskip_cb() { return m_idleskip_cb.bind(); }
@ -37,9 +31,8 @@ protected:
virtual void device_reset() override;
private:
int vrender0_ProcessPacket(uint32_t PacketPtr, uint16_t *Dest);
int vrender0_ProcessPacket(uint32_t PacketPtr);
required_device<cpu_device> m_cpu;
devcb_write_line m_idleskip_cb;
struct RenderStateInfo
@ -73,6 +66,7 @@ private:
RenderStateInfo m_RenderState;
uint8_t *m_textureram;
uint16_t *m_packetram;
uint16_t *m_frameram;
DECLARE_READ16_MEMBER( cmd_queue_front_r );
@ -83,18 +77,22 @@ private:
DECLARE_READ16_MEMBER( bank1_select_r );
DECLARE_WRITE16_MEMBER( bank1_select_w );
bool m_bank1_select;
bool m_bank1_select; //!< Select framebuffer bank1 address
DECLARE_READ16_MEMBER( display_bank_r );
uint8_t m_display_bank;
uint8_t m_display_bank; //!< Current display bank
DECLARE_READ16_MEMBER( render_control_r );
DECLARE_WRITE16_MEMBER( render_control_w );
bool m_draw_select;
bool m_render_reset;
bool m_render_start;
uint8_t m_dither_mode;
uint8_t m_flip_count;
bool m_draw_select; //!< If true, device draws to Front buffer instead of Back
bool m_render_reset; //!< Reset pipeline FIFO
bool m_render_start; //!< Enable pipeline processing
uint8_t m_dither_mode; //!< applied on RGB888 to RGB565 conversions (00: 2x2, 01:4x4, 1x disable)
uint8_t m_flip_count; //!< number of framebuffer "syncs" loaded in the parameter RAM,
//!< a.k.a. how many full (vblank) buffers are ready for the device to parse.
uint16_t *m_DrawDest; //!< frameram pointer to draw buffer area
uint16_t *m_DisplayDest; //!< frameram pointer to display buffer area
};
DECLARE_DEVICE_TYPE(VIDEO_VRENDER0, vr0video_device)