mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
konamigs.cpp promote to working
This commit is contained in:
parent
4f96f9982a
commit
0cb747353b
@ -25,7 +25,7 @@ TODO:
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(S3520CF, s3520cf_device, "s3520cf", "Seiko Epson S-3520CF RTC")
|
||||
DEFINE_DEVICE_TYPE(RTC4553, rtc4553_device, "rtc4553", "Epson RTC-4553 RTC/EEPROM") // functionally same as above but integrated oscillator
|
||||
DEFINE_DEVICE_TYPE(RTC4553, rtc4553_device, "rtc4553", "Epson RTC-4553 RTC/SRAM") // functionally same as above but integrated oscillator
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
@ -44,6 +44,7 @@ s3520cf_device::s3520cf_device(const machine_config &mconfig, const char *tag, d
|
||||
s3520cf_device::s3520cf_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
|
||||
: device_t(mconfig, type, tag, owner, clock)
|
||||
, device_nvram_interface(mconfig, *this)
|
||||
, m_region(*this, DEVICE_SELF)
|
||||
, m_dir(0), m_latch(0), m_reset_line(0), m_read_latch(0), m_bitstream(0), m_stream_pos(0), m_mode(0), m_sysr(0), m_cntrl1(0), m_cntrl2(0)
|
||||
{
|
||||
}
|
||||
@ -156,7 +157,14 @@ void s3520cf_device::device_reset()
|
||||
void s3520cf_device::nvram_default()
|
||||
{
|
||||
for (auto & elem : m_nvdata)
|
||||
elem = 0xff;
|
||||
elem = 0x00;
|
||||
|
||||
if (!m_region.found())
|
||||
logerror("s3520cf(%s) region not found\n", tag());
|
||||
else if (m_region->bytes() != 15)
|
||||
logerror("s3520cf(%s) region length 0x%x expected 0x%x\n", tag(), m_region->bytes(), 15);
|
||||
else
|
||||
memcpy(m_nvdata, m_region->base(), 15);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
|
@ -51,6 +51,8 @@ protected:
|
||||
virtual void nvram_read(emu_file &file) override;
|
||||
virtual void nvram_write(emu_file &file) override;
|
||||
|
||||
optional_memory_region m_region;
|
||||
|
||||
inline u8 rtc_read(u8 offset);
|
||||
inline void rtc_write(u8 offset, u8 data);
|
||||
void check_overflow();
|
||||
|
@ -5,8 +5,6 @@
|
||||
Konami GSAN1 hardware
|
||||
(c) 2000
|
||||
|
||||
mostly preliminary driver
|
||||
|
||||
CPU: Hitachi HD6417709 SH-3
|
||||
GPU: Hitachi HD64413AF 'Q2SD' Quick 2D Graphics Renderer with Synchronous DRAM Interface
|
||||
SPU: Yamaha YMZ280B-F
|
||||
@ -15,14 +13,25 @@
|
||||
Altera Max EPM3064ATC100-10
|
||||
Epson RTC-4553
|
||||
|
||||
Known games:
|
||||
Dance Dance Revolution Kids (not dumped)
|
||||
Muscle Ranking Spray Hitter
|
||||
Known games (preliminary, some of listed below might not belong to this hardware):
|
||||
Dance Dance Revolution Kids
|
||||
Muscle Ranking Football Masters
|
||||
Muscle Ranking Kick Target
|
||||
*Muscle Ranking Spray Hitter
|
||||
Muscle Ranking Struck Out
|
||||
Neratte Don Don
|
||||
Pikkari Chance
|
||||
Run Run Puppy
|
||||
Soreike! Hanapuu
|
||||
|
||||
TODOs:
|
||||
- interrupt sources
|
||||
- I/O
|
||||
- GPU
|
||||
* denotes these games are archived
|
||||
|
||||
TODO:
|
||||
- currently implemented very basic set of Q2SD GPU features, required/used by Spray Hitter, should be improved if more games will be found.
|
||||
- hook IRQs from GPU and SPU (not used by Spray Hitter)
|
||||
|
||||
Notes:
|
||||
- hold Test + Service while booting to initialise RTC NVRAM
|
||||
|
||||
**************************************************************************/
|
||||
|
||||
@ -32,6 +41,7 @@
|
||||
#include "bus/ata/ataintf.h"
|
||||
#include "machine/ataflash.h"
|
||||
#include "machine/s3520cf.h"
|
||||
#include "machine/ticket.h"
|
||||
#include "sound/ymz280b.h"
|
||||
#include "speaker.h"
|
||||
#include "screen.h"
|
||||
@ -43,56 +53,461 @@ public:
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_ata(*this, "ata")
|
||||
, m_vram(*this, "vram")
|
||||
, m_hopper(*this, "hopper")
|
||||
, m_rtc_r(*this, "RTCR")
|
||||
, m_rtc_w(*this, "RTCW")
|
||||
{ }
|
||||
, m_dipsw_r(*this, "DSW")
|
||||
, m_vram(*this, "vram", 0)
|
||||
, m_gpuregs(*this, "gpu_regs", 0)
|
||||
{ }
|
||||
|
||||
void gsan(machine_config &config);
|
||||
void init_gsan();
|
||||
|
||||
private:
|
||||
protected:
|
||||
required_device<sh34_base_device> m_maincpu;
|
||||
required_device<ata_interface_device> m_ata;
|
||||
required_shared_ptr<uint64_t> m_vram;
|
||||
required_device<hopper_device> m_hopper;
|
||||
required_ioport m_rtc_r;
|
||||
required_ioport m_rtc_w;
|
||||
required_ioport m_dipsw_r;
|
||||
required_shared_ptr<u16> m_vram;
|
||||
required_shared_ptr<u16> m_gpuregs;
|
||||
|
||||
void main_map(address_map &map);
|
||||
void main_port(address_map &map);
|
||||
void ymz280b_map(address_map &map);
|
||||
|
||||
virtual void machine_start() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
DECLARE_READ16_MEMBER(cf_regs_r);
|
||||
DECLARE_WRITE16_MEMBER(cf_regs_w);
|
||||
DECLARE_READ16_MEMBER(cf_data_r);
|
||||
DECLARE_WRITE16_MEMBER(cf_data_w);
|
||||
DECLARE_READ8_MEMBER(rtc_r);
|
||||
DECLARE_WRITE8_MEMBER(rtc_w);
|
||||
DECLARE_READ64_MEMBER(portc_r);
|
||||
DECLARE_WRITE64_MEMBER(portc_w);
|
||||
DECLARE_READ64_MEMBER(porte_r);
|
||||
DECLARE_WRITE64_MEMBER(porte_w);
|
||||
DECLARE_READ16_MEMBER(dipsw_r);
|
||||
u8 m_portc_data = 0xff;
|
||||
u8 m_porte_data = 0xff;
|
||||
|
||||
// Q2SD GPU
|
||||
DECLARE_READ16_MEMBER(gpu_r);
|
||||
DECLARE_WRITE16_MEMBER(gpu_w);
|
||||
|
||||
DECLARE_READ16_MEMBER(vram_r);
|
||||
DECLARE_WRITE16_MEMBER(vram_w);
|
||||
DECLARE_WRITE_LINE_MEMBER(vblank);
|
||||
void draw_quad(u16 cmd, u16 *data);
|
||||
void fill_quad(u16 cmd, u16 *data);
|
||||
void draw_line(u16 cmd, u16 *data);
|
||||
u32 pix_address(u16 x, u16 y) { return (x & 0xf) | ((y & 0xf) << 4) | ((x & ~0xf) << 4) | ((y & ~0xf) << 9); };
|
||||
u32 screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// CF interface, looks like standard memory-mapped ATA layout, probably should be devicified
|
||||
READ16_MEMBER(gsan_state::cf_regs_r)
|
||||
{
|
||||
offset *= 2;
|
||||
u16 data = 0;
|
||||
if (ACCESSING_BITS_0_7)
|
||||
data |= m_ata->read_cs0(offset, 0xff) & 0xff;
|
||||
if (ACCESSING_BITS_8_15)
|
||||
data |= (m_ata->read_cs0(offset + 1, 0xff) << 8);
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gsan_state::cf_regs_w)
|
||||
{
|
||||
offset *= 2;
|
||||
if (ACCESSING_BITS_0_7)
|
||||
m_ata->write_cs0(offset, data & 0xff, 0xff);
|
||||
if (ACCESSING_BITS_8_15)
|
||||
m_ata->write_cs0(offset + 1, data >> 8, 0xff);
|
||||
}
|
||||
|
||||
READ16_MEMBER(gsan_state::cf_data_r)
|
||||
{
|
||||
u16 data = m_ata->read_cs0(0, 0xffff);
|
||||
return data;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gsan_state::cf_data_w)
|
||||
{
|
||||
m_ata->write_cs0(0, data, 0xffff);
|
||||
}
|
||||
|
||||
// misc I/O
|
||||
READ16_MEMBER(gsan_state::dipsw_r)
|
||||
{
|
||||
return m_dipsw_r->read();
|
||||
}
|
||||
READ8_MEMBER(gsan_state::rtc_r)
|
||||
{
|
||||
return m_rtc_r->read();
|
||||
}
|
||||
WRITE8_MEMBER(gsan_state::rtc_w)
|
||||
{
|
||||
m_rtc_w->write(data);
|
||||
}
|
||||
|
||||
// SH-3 GPIO output ports
|
||||
READ64_MEMBER(gsan_state::portc_r)
|
||||
{
|
||||
return m_portc_data;
|
||||
}
|
||||
WRITE64_MEMBER(gsan_state::portc_w)
|
||||
{
|
||||
#if 0
|
||||
if (m_portc_data != data)
|
||||
logerror("PORT_C %02X\n", (u8)data);
|
||||
#endif
|
||||
m_portc_data = data;
|
||||
m_hopper->motor_w(data & 0x80);
|
||||
machine().bookkeeping().coin_counter_w(0, data & 4);
|
||||
machine().bookkeeping().coin_counter_w(1, data & 1);
|
||||
}
|
||||
READ64_MEMBER(gsan_state::porte_r)
|
||||
{
|
||||
return m_porte_data;
|
||||
}
|
||||
WRITE64_MEMBER(gsan_state::porte_w)
|
||||
{
|
||||
// lamps
|
||||
#if 0
|
||||
if ((m_porte_data ^ data) & 0xff)
|
||||
{
|
||||
u8 mask = (m_porte_data ^ data) & 0xff;
|
||||
u8 nval = data & mask;
|
||||
logerror("PORT_E mask %02X val %02X\n", mask, nval);
|
||||
}
|
||||
#endif
|
||||
m_porte_data = data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Q2SD GPU
|
||||
READ16_MEMBER(gsan_state::vram_r)
|
||||
{
|
||||
return m_vram[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gsan_state::vram_w)
|
||||
{
|
||||
COMBINE_DATA(&m_vram[offset]);
|
||||
}
|
||||
|
||||
READ16_MEMBER(gsan_state::gpu_r)
|
||||
{
|
||||
return m_gpuregs[offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(gsan_state::gpu_w)
|
||||
{
|
||||
u16 prevval = m_gpuregs[offset];
|
||||
COMBINE_DATA(&m_gpuregs[offset]);
|
||||
data = m_gpuregs[offset];
|
||||
#if 0
|
||||
if (prevval != data)
|
||||
logerror("Q2SD reg %02X %04X\n", offset*2, data);
|
||||
#endif
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 0x000: // System control
|
||||
if (data & 0x8000) // reset
|
||||
{
|
||||
m_gpuregs[0x000] &= ~0x0400;
|
||||
m_gpuregs[0x001] &= ~0x1680;
|
||||
}
|
||||
if (data & 0x4000) // display reset
|
||||
{
|
||||
m_gpuregs[0x001] &= ~0x0800;
|
||||
}
|
||||
if (data & 0x0100) // start render
|
||||
{
|
||||
m_gpuregs[0x000] &= ~0x0100;
|
||||
|
||||
u32 listoffs = ((m_gpuregs[0x018 / 2] << 16) | m_gpuregs[0x01a / 2]) / 2;
|
||||
bool end_of_list = false;
|
||||
do
|
||||
{
|
||||
u16 cmd = m_vram[listoffs++];
|
||||
switch (cmd >> 11)
|
||||
{
|
||||
case 0x00: // POLYGON4A
|
||||
draw_quad(cmd, &m_vram[listoffs]);
|
||||
listoffs += 12;
|
||||
break;
|
||||
// case 0x01: // POLYGON4B
|
||||
// listoffs += 14;
|
||||
// break;
|
||||
case 0x02: // POLYGON4C
|
||||
fill_quad(cmd, &m_vram[listoffs]);
|
||||
listoffs += 9;
|
||||
break;
|
||||
case 0x0c: // LINE
|
||||
draw_line(cmd, &m_vram[listoffs]);
|
||||
listoffs += m_vram[listoffs + 1] * 2 + 2;
|
||||
break;
|
||||
case 0x12: // LCOFS
|
||||
m_gpuregs[0x84 / 2] = m_vram[listoffs++];
|
||||
m_gpuregs[0x86 / 2] = m_vram[listoffs++];
|
||||
break;
|
||||
case 0x16: // WPR
|
||||
gpu_w(space, m_vram[listoffs] & 0x3ff, m_vram[listoffs + 1]);
|
||||
listoffs += 2;
|
||||
break;
|
||||
case 0x17: // SCLIP
|
||||
m_gpuregs[0x90 / 2] = m_vram[listoffs++];
|
||||
m_gpuregs[0x92 / 2] = m_vram[listoffs++];
|
||||
break;
|
||||
case 0x1a: // VBKEM
|
||||
// TODO somehow wait vblank
|
||||
listoffs += 2;
|
||||
break;
|
||||
case 0x1e: // NOP3
|
||||
listoffs += 2;
|
||||
break;
|
||||
case 0x1f: // TRAP
|
||||
m_gpuregs[0x001] |= 0x0400;
|
||||
end_of_list = true;
|
||||
break;
|
||||
default:
|
||||
logerror("Q2SD not implemented command %04X addr %08X\n", cmd, (listoffs - 1) * 2);
|
||||
break;
|
||||
}
|
||||
} while (!end_of_list);
|
||||
}
|
||||
break;
|
||||
case 0x001: // Status (read only)
|
||||
m_gpuregs[offset] = prevval;
|
||||
break;
|
||||
case 0x002: // Status clear
|
||||
m_gpuregs[0x001] &= ~(data & 0xff80);
|
||||
break;
|
||||
case 0x003: // Interrupt mask, always set to 0, no interrupts ? so lame
|
||||
if (data)
|
||||
logerror("Q2SD enable IRQ %04X !\n", data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER(gsan_state::vblank)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
m_gpuregs[0x001] |= 0x0800; // VBLANK
|
||||
m_gpuregs[0x000] &= ~0x0200;
|
||||
}
|
||||
}
|
||||
|
||||
void gsan_state::draw_quad(u16 cmd, u16 *data)
|
||||
{
|
||||
// logerror("Q2SD draw %04X src %d:%d sz %d:%d dst %d:%d %d:%d %d:%d %d:%d\n", cmd, data[0], data[1], data[2], data[3], (s16)data[4], (s16)data[5], (s16)data[6], (s16)data[7], (s16)data[8], (s16)data[9], (s16)data[10], (s16)data[11]);
|
||||
if (cmd & 0x5ff)
|
||||
logerror("Q2SD unhandled draw mode %04X\n", cmd);
|
||||
u32 ssx = data[0];
|
||||
u32 ssy = data[1];
|
||||
s16 sdx = data[4];
|
||||
s16 sdy = data[5];
|
||||
s16 edx = data[8];
|
||||
s16 edy = data[9];
|
||||
s16 sclipx = m_gpuregs[0x90 / 2];
|
||||
s16 sclipy = m_gpuregs[0x92 / 2];
|
||||
|
||||
s16 ddx = (edx >= sdx) ? 1 : -1;
|
||||
s16 ddy = (edy >= sdy) ? 1 : -1;
|
||||
edx += ddx;
|
||||
edy += ddy;
|
||||
|
||||
u32 fg_offs = (m_gpuregs[0x014 / 2] & 0x7f) << 15;
|
||||
u32 src_offs = (((m_gpuregs[0x01c / 2] & 0x7f) << 16) | (m_gpuregs[0x01c / 2] & 0xe000)) / 2;
|
||||
|
||||
bool opaq = !(cmd & 0x0200);
|
||||
|
||||
for (int y = sdy, sy = 0; y != edy; y += ddy, sy++)
|
||||
for (int x = sdx, sx = 0; x != edx; x += ddx, sx++)
|
||||
if ((x >= 0 && x <= sclipx) && (y >= 0 && y <= sclipy))
|
||||
{
|
||||
u16 pix = m_vram[src_offs + pix_address(ssx + sx, ssy + sy)];
|
||||
if (pix || opaq)
|
||||
m_vram[fg_offs + pix_address(x, y)] = pix;
|
||||
}
|
||||
}
|
||||
|
||||
void gsan_state::fill_quad(u16 cmd, u16 *data)
|
||||
{
|
||||
// logerror("Q2SD fill dst %d:%d %d:%d %d:%d %d:%d col %04X\n", (s16)data[0], (s16)data[1], (s16)data[2], (s16)data[3], (s16)data[4], (s16)data[5], (s16)data[6], (s16)data[7], data[8]);
|
||||
if (cmd & 0x7ff)
|
||||
logerror("Q2SD unhandled draw mode %04X\n", cmd);
|
||||
s16 sdx = data[0];
|
||||
s16 sdy = data[1];
|
||||
s16 edx = data[4];
|
||||
s16 edy = data[5];
|
||||
u16 color = data[8];
|
||||
s16 sclipx = m_gpuregs[0x90 / 2];
|
||||
s16 sclipy = m_gpuregs[0x92 / 2];
|
||||
|
||||
s16 ddx = (edx >= sdx) ? 1 : -1;
|
||||
s16 ddy = (edy >= sdy) ? 1 : -1;
|
||||
edx += ddx;
|
||||
edy += ddy;
|
||||
|
||||
u32 fg_offs = (m_gpuregs[0x014 / 2] & 0x7f) << 15;
|
||||
|
||||
for (int y = sdy; y != edy; y += ddy)
|
||||
for (int x = sdx; x != edx; x += ddx)
|
||||
{
|
||||
if ((x >= 0 && x <= sclipx) && (y >= 0 && y <= sclipy))
|
||||
m_vram[fg_offs + pix_address(x, y)] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void gsan_state::draw_line(u16 cmd, u16 *data)
|
||||
{
|
||||
// TODO, test mode only
|
||||
}
|
||||
|
||||
u32 gsan_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
// display something
|
||||
u32 base_offs = 0;
|
||||
for (int y = 0; y < 240; y++)
|
||||
if (m_gpuregs[0x000 / 2] & 0x2000)
|
||||
{
|
||||
for (int x = 0; x < 320; x++)
|
||||
{
|
||||
u32 idx = (x & 0xf) | ((y & 0xf) << 4) | ((x & ~0xf) << 4) | ((y & ~0xf) << 9);
|
||||
u64 pix = (m_vram[base_offs + idx / 4] >> ((~idx & 3) * 16)) & 0xffff;
|
||||
bitmap.pix32(y, x) = pal555(pix, 0, 5, 10);
|
||||
}
|
||||
u32 fg_offs = (m_gpuregs[0x014 / 2] & 0x7f) << 15;
|
||||
bool fg_en = !(m_gpuregs[0x056 / 2] & 8);
|
||||
bool bg_en = m_gpuregs[0x00a / 2] & 0x0400;
|
||||
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
u16 pix = 0;
|
||||
u32 idx = pix_address(x, y);
|
||||
if (fg_en)
|
||||
pix = m_vram[fg_offs + idx];
|
||||
if (bg_en && pix == 0)
|
||||
pix = m_vram[idx];
|
||||
bitmap.pix32(y, x) = pal565(pix, 11, 5, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
bitmap.fill(rgb_t::black(), cliprect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void gsan_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x0000ffff).rom().region("maincpu", 0);
|
||||
map(0x08000000, 0x083fffff).rw(FUNC(gsan_state::vram_r), FUNC(gsan_state::vram_w)).share("vram");
|
||||
map(0x0c000000, 0x0c3fffff).ram().share("main_ram");
|
||||
map(0x10000000, 0x100007ff).rw(FUNC(gsan_state::gpu_r), FUNC(gsan_state::gpu_w)).share("gpu_regs");
|
||||
// misc I/O
|
||||
map(0x14000800, 0x14000807).rw(FUNC(gsan_state::cf_regs_r), FUNC(gsan_state::cf_regs_w));
|
||||
map(0x14000c00, 0x14000c03).rw(FUNC(gsan_state::cf_data_r), FUNC(gsan_state::cf_data_w));
|
||||
map(0x14001000, 0x14001001).r(FUNC(gsan_state::dipsw_r));
|
||||
map(0x14001019, 0x14001019).w(FUNC(gsan_state::rtc_w));
|
||||
map(0x14001039, 0x14001039).r(FUNC(gsan_state::rtc_r));
|
||||
|
||||
map(0x18000000, 0x18000001).rw("ymz", FUNC(ymz280b_device::read), FUNC(ymz280b_device::write));
|
||||
|
||||
map(0x1f000000, 0x1f000fff).ram(); // cache RAM-mode (SH3 internal), actually should be 7Fxxxxxx, but current SH3 core doesn't like 7Fxxxxxx
|
||||
map(0xa0000000, 0xa000ffff).rom().region("maincpu", 0); // uncached mirror, otherwise no disassembly can bee seen in debugger (bug?)
|
||||
}
|
||||
|
||||
void gsan_state::main_port(address_map &map)
|
||||
{
|
||||
map(SH3_PORT_C, SH3_PORT_C + 7).rw(FUNC(gsan_state::portc_r), FUNC(gsan_state::portc_w));
|
||||
map(SH3_PORT_E, SH3_PORT_E + 7).rw(FUNC(gsan_state::porte_r), FUNC(gsan_state::porte_w));
|
||||
map(SH3_PORT_F, SH3_PORT_F + 7).portr("PORT_F");
|
||||
map(SH3_PORT_L, SH3_PORT_L + 7).portr("PORT_L");
|
||||
}
|
||||
|
||||
void gsan_state::ymz280b_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x3fffff);
|
||||
map(0x000000, 0x3fffff).ram();
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( gsan )
|
||||
PORT_START("PORT_L")
|
||||
PORT_BIT( 0x00, IP_ACTIVE_HIGH, IPT_UNKNOWN ) // DIP switches ?
|
||||
PORT_SERVICE_NO_TOGGLE( 0x10, IP_ACTIVE_LOW )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x8f, IP_ACTIVE_LOW, IPT_UNKNOWN ) // unused
|
||||
|
||||
PORT_START("PORT_F")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN3 ) PORT_NAME("Medal")
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 ) // looks like not regular coin in to play, but coins for medals exchange
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN1 )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("hopper", hopper_device, line_r)
|
||||
PORT_BIT( 0x78, IP_ACTIVE_LOW, IPT_UNKNOWN ) // unused
|
||||
|
||||
PORT_START("DSW")
|
||||
PORT_DIPNAME( 0x0007, 0x0007, "Coin Slot 1" ) PORT_DIPLOCATION("SW1:1,2,3")
|
||||
PORT_DIPSETTING( 0x0003, DEF_STR( 5C_1C ) )
|
||||
PORT_DIPSETTING( 0x0005, DEF_STR( 3C_1C ) )
|
||||
PORT_DIPSETTING( 0x0006, DEF_STR( 2C_1C ) )
|
||||
PORT_DIPSETTING( 0x0004, DEF_STR( 4C_1C ) )
|
||||
PORT_DIPSETTING( 0x0007, DEF_STR( 1C_1C ) )
|
||||
PORT_DIPSETTING( 0x0001, DEF_STR( 4C_3C ) )
|
||||
PORT_DIPSETTING( 0x0002, DEF_STR( 2C_3C ) )
|
||||
PORT_DIPSETTING( 0x0000, "5 Coins/2 Credits" )
|
||||
PORT_DIPNAME( 0x0078, 0x0078, "Coin Slot 2" ) PORT_DIPLOCATION("SW1:4,5,6,7")
|
||||
PORT_DIPSETTING( 0x0078, "2 Medals" )
|
||||
// PORT_DIPSETTING( 0x0070, "2 Medals" )
|
||||
PORT_DIPSETTING( 0x0068, "3 Medals" )
|
||||
PORT_DIPSETTING( 0x0060, "4 Medals" )
|
||||
PORT_DIPSETTING( 0x0058, "5 Medals" )
|
||||
PORT_DIPSETTING( 0x0050, "6 Medals" )
|
||||
PORT_DIPSETTING( 0x0048, "7 Medals" )
|
||||
PORT_DIPSETTING( 0x0040, "8 Medals" )
|
||||
PORT_DIPSETTING( 0x0038, "9 Medals" )
|
||||
PORT_DIPSETTING( 0x0030, "10 Medals" )
|
||||
PORT_DIPSETTING( 0x0028, "11 Medals" )
|
||||
PORT_DIPSETTING( 0x0020, "12 Medals" )
|
||||
PORT_DIPSETTING( 0x0018, "13 Medals" )
|
||||
PORT_DIPSETTING( 0x0010, "14 Medals" )
|
||||
PORT_DIPSETTING( 0x0008, "15 Medals" )
|
||||
PORT_DIPSETTING( 0x0000, "16 Medals" )
|
||||
PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Free_Play ) ) PORT_DIPLOCATION("SW1:8")
|
||||
PORT_DIPSETTING( 0x0080, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
|
||||
PORT_DIPNAME( 0x0f00, 0x0000, "Standard of Payout" ) PORT_DIPLOCATION("SW2:1,2,3,4")
|
||||
PORT_DIPSETTING( 0x0f00, "15%" )
|
||||
PORT_DIPSETTING( 0x0e00, "20%" )
|
||||
PORT_DIPSETTING( 0x0d00, "25%" )
|
||||
PORT_DIPSETTING( 0x0c00, "30%" )
|
||||
PORT_DIPSETTING( 0x0b00, "35%" )
|
||||
PORT_DIPSETTING( 0x0a00, "40%" )
|
||||
PORT_DIPSETTING( 0x0900, "45%" )
|
||||
PORT_DIPSETTING( 0x0800, "50%" )
|
||||
PORT_DIPSETTING( 0x0700, "55%" )
|
||||
PORT_DIPSETTING( 0x0600, "60%" )
|
||||
PORT_DIPSETTING( 0x0500, "65%" )
|
||||
PORT_DIPSETTING( 0x0400, "70%" )
|
||||
PORT_DIPSETTING( 0x0300, "75%" )
|
||||
PORT_DIPSETTING( 0x0200, "80%" )
|
||||
PORT_DIPSETTING( 0x0100, "85%" )
|
||||
PORT_DIPSETTING( 0x0000, "90%" )
|
||||
PORT_DIPNAME( 0x3000, 0x0000, "Play Timer" ) PORT_DIPLOCATION("SW2:5,6")
|
||||
PORT_DIPSETTING( 0x3000, "1" )
|
||||
PORT_DIPSETTING( 0x2000, "2" )
|
||||
PORT_DIPSETTING( 0x1000, "3" )
|
||||
PORT_DIPSETTING( 0x0000, "4" )
|
||||
PORT_DIPNAME( 0x4000, 0x4000, "Backup Memory" ) PORT_DIPLOCATION("SW2:7")
|
||||
PORT_DIPSETTING( 0x4000, "Keep" )
|
||||
PORT_DIPSETTING( 0x0000, "Clear" )
|
||||
PORT_DIPNAME( 0x8000, 0x0000, DEF_STR( Demo_Sounds ) ) PORT_DIPLOCATION("SW2:8")
|
||||
PORT_DIPSETTING( 0x8000, DEF_STR( Off ) )
|
||||
PORT_DIPSETTING( 0x0000, DEF_STR( On ) )
|
||||
|
||||
PORT_START("RTCW")
|
||||
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER("rtc", rtc4553_device, set_dir_line)
|
||||
@ -105,85 +520,21 @@ static INPUT_PORTS_START( gsan )
|
||||
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_CUSTOM ) PORT_READ_LINE_DEVICE_MEMBER("rtc", rtc4553_device, read_bit)
|
||||
INPUT_PORTS_END
|
||||
|
||||
// CF interface, looks like standard memory-mapped ATA layout, probably should be devicified
|
||||
READ16_MEMBER(gsan_state::cf_regs_r)
|
||||
//**************************************************************************
|
||||
// MACHINE DRIVERS
|
||||
//**************************************************************************
|
||||
|
||||
void gsan_state::machine_start()
|
||||
{
|
||||
offset *= 2;
|
||||
u16 data = m_ata->read_cs0(offset, 0xff) & 0xff;
|
||||
data |= (m_ata->read_cs0(offset + 1, 0xff) << 8);
|
||||
return data;
|
||||
}
|
||||
WRITE16_MEMBER(gsan_state::cf_regs_w)
|
||||
{
|
||||
offset *= 2;
|
||||
m_ata->write_cs0(offset, data & 0xff, 0xff);
|
||||
m_ata->write_cs0(offset + 1, data >> 8, 0xff);
|
||||
}
|
||||
READ16_MEMBER(gsan_state::cf_data_r)
|
||||
{
|
||||
u16 data = m_ata->read_cs0(0, 0xffff);
|
||||
return data;
|
||||
}
|
||||
WRITE16_MEMBER(gsan_state::cf_data_w)
|
||||
{
|
||||
m_ata->write_cs0(0, data, 0xffff);
|
||||
save_item(NAME(m_portc_data));
|
||||
save_item(NAME(m_porte_data));
|
||||
}
|
||||
|
||||
READ8_MEMBER(gsan_state::rtc_r)
|
||||
void gsan_state::machine_reset()
|
||||
{
|
||||
return m_rtc_r->read();
|
||||
}
|
||||
WRITE8_MEMBER(gsan_state::rtc_w)
|
||||
{
|
||||
m_rtc_w->write(data);
|
||||
}
|
||||
|
||||
// Q2SD GPU
|
||||
READ16_MEMBER(gsan_state::gpu_r)
|
||||
{
|
||||
switch (offset)
|
||||
{
|
||||
case 1: // status
|
||||
return machine().rand(); // code must go on
|
||||
default:
|
||||
//logerror("GPU read %03X\n", offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
WRITE16_MEMBER(gsan_state::gpu_w)
|
||||
{
|
||||
// here be dragons...
|
||||
//logerror("GPU write %03X %04X\n", offset, data);
|
||||
}
|
||||
|
||||
|
||||
void gsan_state::main_map(address_map &map)
|
||||
{
|
||||
map(0x00000000, 0x0000ffff).rom().region("maincpu", 0);
|
||||
map(0x08000000, 0x083fffff).ram().share("vram");
|
||||
map(0x0c000000, 0x0c3fffff).ram().share("main_ram");
|
||||
map(0x10000000, 0x100007ff).rw(FUNC(gsan_state::gpu_r), FUNC(gsan_state::gpu_w));
|
||||
// misc I/O
|
||||
map(0x14000800, 0x14000807).rw(FUNC(gsan_state::cf_regs_r), FUNC(gsan_state::cf_regs_w));
|
||||
map(0x14000c00, 0x14000c03).rw(FUNC(gsan_state::cf_data_r), FUNC(gsan_state::cf_data_w));
|
||||
map(0x14001019, 0x14001019).w(FUNC(gsan_state::rtc_w));
|
||||
map(0x14001039, 0x14001039).r(FUNC(gsan_state::rtc_r));
|
||||
|
||||
map(0x18000000, 0x18000001).rw("ymz", FUNC(ymz280b_device::read), FUNC(ymz280b_device::write));
|
||||
|
||||
map(0x1f000000, 0x1f000fff).ram(); // cache RAM-mode (SH3 internal), actually should be 7Fxxxxxx, but current SH3 core doesn't like 7Fxxxxxx
|
||||
map(0xa0000000, 0xa000ffff).rom().region("maincpu", 0); // uncached mirror, otherwise no disassembly can bee seen in debugger (bug?)
|
||||
}
|
||||
|
||||
void gsan_state::main_port(address_map &map)
|
||||
{
|
||||
map(SH3_PORT_L, SH3_PORT_L + 7).portr("PORT_L");
|
||||
}
|
||||
|
||||
void gsan_state::ymz280b_map(address_map &map)
|
||||
{
|
||||
map.global_mask(0x3fffff);
|
||||
map(0x000000, 0x3fffff).ram();
|
||||
memset(&m_gpuregs[0], 0, 0x800);
|
||||
m_gpuregs[0] = 0xc000;
|
||||
m_gpuregs[1] = 0x0044;
|
||||
}
|
||||
|
||||
static void gsan_devices(device_slot_interface &device)
|
||||
@ -191,16 +542,11 @@ static void gsan_devices(device_slot_interface &device)
|
||||
device.option_add("cfcard", ATA_FLASH_PCCARD);
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// MACHINE DRIVERS
|
||||
//**************************************************************************
|
||||
|
||||
void gsan_state::gsan(machine_config &config)
|
||||
{
|
||||
// basic machine hardware
|
||||
// SH7709 is earlier version of SH7709S (cv1k), not exact same, have minor differences
|
||||
SH3BE(config, m_maincpu, 32_MHz_XTAL * 2); // not verified
|
||||
SH3BE(config, m_maincpu, 32_MHz_XTAL * 2); // not verified, TODO check TMU clock, here it should be XTAL*2/3
|
||||
m_maincpu->set_md(0, 0); // none of this is verified
|
||||
m_maincpu->set_md(1, 0); // (the sh3 is different to the sh4 anyway, should be changed)
|
||||
m_maincpu->set_md(2, 0);
|
||||
@ -214,9 +560,10 @@ void gsan_state::gsan(machine_config &config)
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &gsan_state::main_map);
|
||||
m_maincpu->set_addrmap(AS_IO, &gsan_state::main_port);
|
||||
|
||||
// misc
|
||||
ATA_INTERFACE(config, m_ata).options(gsan_devices, "cfcard", nullptr, true);
|
||||
|
||||
RTC4553(config, "rtc");
|
||||
HOPPER(config, "hopper", attotime::from_msec(100), TICKET_MOTOR_ACTIVE_LOW, TICKET_STATUS_ACTIVE_HIGH);
|
||||
|
||||
// video hardware
|
||||
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
|
||||
@ -224,6 +571,8 @@ void gsan_state::gsan(machine_config &config)
|
||||
screen.set_size(320, 240);
|
||||
screen.set_visarea(0, 320-1, 0, 240-1);
|
||||
screen.set_refresh_hz(60);
|
||||
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
|
||||
screen.screen_vblank().set(FUNC(gsan_state::vblank));
|
||||
|
||||
// sound hardware
|
||||
SPEAKER(config, "mono").front_center();
|
||||
@ -248,6 +597,9 @@ ROM_START( musclhit )
|
||||
ROM_REGION( 0x10000, "maincpu", 0 )
|
||||
ROM_LOAD( "gsan5-a.u17", 0x00000, 0x10000, CRC(6ae1d1e8) SHA1(3224e4b8198aa38c094088456281cbd62c085407) )
|
||||
|
||||
ROM_REGION( 0x0f, "rtc", 0 )
|
||||
ROM_LOAD( "nvram.u9", 0x00, 0x0f, CRC(17614a6a) SHA1(f4714659937e7dd3eedc18bbedc4b3000134df16) )
|
||||
|
||||
DISK_REGION( "ata:0:cfcard:image" )
|
||||
DISK_IMAGE( "gsan6_a-213", 0, SHA1(d9e7a350428d1621fc70e81561390c01837a94c0) )
|
||||
ROM_END
|
||||
@ -258,4 +610,4 @@ ROM_END
|
||||
// GAME DRIVERS
|
||||
//**************************************************************************
|
||||
|
||||
GAME( 2000, musclhit, 0, gsan, gsan, gsan_state, init_gsan, ROT0, "Konami / TBS", "Muscle Ranking Kinniku Banzuke Spray Hitter", MACHINE_IS_SKELETON )
|
||||
GAME( 2000, musclhit, 0, gsan, gsan, gsan_state, init_gsan, ROT0, "Konami / TBS", "Muscle Ranking Kinniku Banzuke Spray Hitter", MACHINE_IMPERFECT_GRAPHICS|MACHINE_SUPPORTS_SAVE )
|
||||
|
Loading…
Reference in New Issue
Block a user