shtzone.cpp: added SMS side. Somewhat playable but needs more work.

This commit is contained in:
Ivan Vangelista 2021-07-16 18:22:54 +02:00
parent 9af8a3a0fa
commit 94a60b8f34

View File

@ -4,9 +4,7 @@
"Sega Shooting Zone" aka "Sega Sharp Shooter"
This is an SMS with a timer system, official Sega product. Cabinet has a lightgun, it runs the SMS light gun games.
It has 2 IO controllers, and 1 VDP, so I'm guessing the BIOS just displays to some kind of Segment LED display.
This is an SMS with a timer system, official Sega product.
---------------------------------
@ -32,32 +30,38 @@ GAMES for this system :
Black Belt (mpr10150.ic1)
Shooting Gallery(2)
Shooting Gallery
Gangster Town
Marksman Shooting / Trap Shooting / Safari Hunt (315-5028.ic1 + Mpr10157.ic2)
Fantasy Zone(1)
Fantasy Zone
---------------------------------
Notes:
(1) apparently.... seems a bit odd, because it's not a gun game
(2) an auction has been observed with Out Run instead of this
Apparently the first revision only had a gun, the second (the one dumped) had both a gun and a joystick.
Multiple auctions and pics on the web show different cartridge configurations, so the driver lets you select the whole SMS library.
To try the selection listed above use the following command:
mame shtzone -cart1 blackblt -cart2 shooting -cart3 gangster -cart4 marksman -cart5 fantzone
Stuck at 'set cartridge', currently only the VDP and basic inputs for the timer CPU are hooked up.
It's possible to enter test mode.
TODO:
- hook up SMS CPU and carts reading, SMS-side inputs;
- outputs (test mode lists LED lamp, gun solenoid and buzzer);
- very similar to smssdisp in sms.cpp, merge?
- gun?
- actual timer doesn't seem to match what's set by the dips. Communications problem?
- outputs (test mode lists LED lamp, gun solenoid and buzzer). Lamp is done, buzzer maybe, gun solenoid isn't.
- the driver currently assumes the buzzer is used to acknowledge when a coin is inserted.
- should also have 1 card slot according to forum posts.
- layout for the led.
*/
#include "emu.h"
#include "includes/sms.h"
#include "cpu/z80/z80.h"
#include "machine/nvram.h"
#include "video/315_5124.h"
#include "sound/beep.h"
#include "emupal.h"
#include "screen.h"
#include "speaker.h"
@ -65,54 +69,126 @@ TODO:
namespace {
class shtzone_state : public driver_device
class shtzone_state : public sms_state
{
public:
shtzone_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
: sms_state(mconfig, type, tag),
m_timercpu(*this, "timercpu"),
m_buzzer(*this, "buzzer"),
m_slots(*this, {"slot", "slot2", "slot3", "slot4", "slot5"}),
m_led(*this, "led")
{ }
void shtzone(machine_config &config);
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
virtual void video_start() override;
virtual void device_post_load() override;
private:
required_device<cpu_device> m_timercpu;
required_device<beep_device> m_buzzer;
required_device_array<sega8_cart_slot_device, 5> m_slots;
output_finder<> m_led;
uint8_t m_control;
uint8_t m_selected_cart;
uint8_t cart_select_r();
void cart_select_w(uint8_t data);
void select_cart(uint8_t data);
void control_w(uint8_t data);
uint8_t cart_r(offs_t offset);
DECLARE_WRITE_LINE_MEMBER(int_callback);
void prg_map(address_map &map);
void io_map(address_map &map);
};
uint8_t shtzone_state::cart_r(offs_t offset)
{
if (m_mem_device_enabled != 0x00)
{
uint8_t data = 0xff;
if (BIT(m_mem_device_enabled, 2))
data &= m_cartslot->read_cart(0x6000 + (offset & 0x1fff));
return data;
}
else
{
return m_region_maincpu->base()[offset];
}
}
uint8_t shtzone_state::cart_select_r()
{
return m_selected_cart;
}
void shtzone_state::cart_select_w(uint8_t data)
{
select_cart(data);
m_selected_cart = data;
setup_media_slots();
}
void shtzone_state::select_cart(uint8_t data)
{
m_cartslot = m_slots[data >> 4].target();
}
void shtzone_state::control_w(uint8_t data)
{
switch (data & 0xf0)
{
case 0x00: m_led = 0x06; break;
case 0x10: m_led = 0x5b; break;
case 0x20: m_led = 0x4f; break;
case 0x40: m_led = 0x66; break;
case 0x80: m_led = 0x6d; break;
}
if (BIT(data, 1))
{
m_maincpu->resume(SUSPEND_REASON_HALT);
}
else
{
// Pull reset line of CPU #0 low
m_maincpu->reset();
m_maincpu->suspend(SUSPEND_REASON_HALT, 1);
}
m_control = data;
}
WRITE_LINE_MEMBER(shtzone_state::int_callback)
{
if (BIT(m_control, 0))
m_timercpu->set_input_line(0, state);
else
m_maincpu->set_input_line(0, state);
}
void shtzone_state::prg_map(address_map &map)
{
map(0x0000, 0x3fff).rom();
map(0x4000, 0x4fff).ram();
map(0x5000, 0x5fff).ram().share("nvram");
map(0x8000, 0x8000).portr("DSW2");
map(0x6000, 0x7fff).r(FUNC(shtzone_state::cart_r));
map(0x8000, 0x8000).portr("DSW2").w(FUNC(shtzone_state::control_w));
map(0x8001, 0x8001).portr("DSW1");
// TODO: everything below
map(0x7ff0, 0x7ff0).nopr(); // checks for cart here?
map(0x8000, 0x8000).nopw();
map(0xa000, 0xa000).nopw();
map(0xc000, 0xc000).nopw(); // bits 4-6 slot selection?
map(0xc400, 0xc400).nopw();
// end of TODO
map(0xa000, 0xa000).lw8(NAME([this] (uint8_t data) { m_buzzer->set_state(BIT(data, 0)); })); // TODO: is it? or is it coin counter? other bits are also used
map(0xc000, 0xc000).rw(FUNC(shtzone_state::cart_select_r), FUNC(shtzone_state::cart_select_w));
map(0xd800, 0xd800).portr("IN0");
map(0xdc00, 0xdc00).portr("IN1");
}
void shtzone_state::io_map(address_map &map)
{
map.global_mask(0xff);
map(0x3e, 0x3f).nopw(); // TODO
map(0x7e, 0x7e).r("vdp", FUNC(sega315_5124_device::vcount_read));
map(0x7e, 0x7f).w("vdp", FUNC(sega315_5124_device::psg_w));
map(0xbe, 0xbe).rw("vdp", FUNC(sega315_5124_device::data_read), FUNC(sega315_5124_device::data_write));
map(0xbf, 0xbf).rw("vdp", FUNC(sega315_5124_device::control_read), FUNC(sega315_5124_device::control_write));
map(0xc0, 0xc0).nopr(); // TODO
}
static INPUT_PORTS_START( shtzone )
PORT_START("IN0")
@ -206,54 +282,79 @@ INPUT_PORTS_END
void shtzone_state::machine_start()
{
sms_state::machine_start();
m_led.resolve();
save_item(NAME(m_control));
save_item(NAME(m_selected_cart));
}
void shtzone_state::machine_reset()
{
sms_state::machine_reset();
m_control = 0;
m_selected_cart = 0;
select_cart(m_selected_cart);
}
void shtzone_state::video_start()
void shtzone_state::device_post_load()
{
select_cart(m_selected_cart);
}
void shtzone_state::shtzone(machine_config &config)
{
/* basic machine hardware */
z80_device &timercpu(Z80(config, "timercpu", 10.738_MHz_XTAL / 4));
timercpu.set_addrmap(AS_PROGRAM, &shtzone_state::prg_map);
timercpu.set_addrmap(AS_IO, &shtzone_state::io_map);
/* + SMS CPU */
// basic machine hardware
Z80(config, m_timercpu, 10.738_MHz_XTAL / 3); // divider not verified
m_timercpu->set_addrmap(AS_PROGRAM, &shtzone_state::prg_map);
m_timercpu->set_addrmap(AS_IO, &shtzone_state::sms_io);
// + SMS CPU
sms_ntsc_base(config);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
/* video hardware */
// video hardware
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_raw(10.738_MHz_XTAL / 2,
sega315_5124_device::WIDTH , sega315_5124_device::LBORDER_START + sega315_5124_device::LBORDER_WIDTH, sega315_5124_device::LBORDER_START + sega315_5124_device::LBORDER_WIDTH + 256,
sega315_5124_device::HEIGHT_NTSC, sega315_5124_device::TBORDER_START + sega315_5124_device::NTSC_192_TBORDER_HEIGHT, sega315_5124_device::TBORDER_START + sega315_5124_device::NTSC_192_TBORDER_HEIGHT + 192);
screen.set_screen_update("vdp", FUNC(sega315_5124_device::screen_update));
screen.set_screen_update(m_vdp, FUNC(sega315_5124_device::screen_update));
PALETTE(config, "palette").set_entries(0x100);
sega315_5124_device &vdp(SEGA315_5124(config, "vdp", 10.738_MHz_XTAL));
vdp.set_screen("screen");
vdp.set_is_pal(false);
vdp.n_int().set_inputline("timercpu", 0);
vdp.n_nmi().set_inputline("timercpu", INPUT_LINE_NMI);
vdp.add_route(ALL_OUTPUTS, "mono", 1.00);
SEGA315_5124(config, m_vdp, 10.738_MHz_XTAL);
m_vdp->set_screen("screen");
m_vdp->set_is_pal(false);
m_vdp->n_int().set(FUNC(shtzone_state::int_callback));
m_vdp->n_nmi().set_inputline(m_maincpu, INPUT_LINE_NMI);
m_vdp->add_route(ALL_OUTPUTS, "mono", 1.00);
SPEAKER(config, "mono").front_center();
BEEP(config, m_buzzer, 1000).add_route(ALL_OUTPUTS, "mono", 0.50);
for (int i = 1; i < 5; i++)
SMS_CART_SLOT(config, m_slots[i], sms_cart, nullptr);
m_has_bios_full = false;
m_has_pwr_led = false;
}
ROM_START( shtzone )
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0x00)
ROM_REGION( 0x4000, "timercpu", 0 )
ROM_LOAD( "epr10894a.20", 0x00000, 0x04000, CRC(ea8901d9) SHA1(43fd8bfc395e3b2e3fbe9645d692a5eb04783d9c) )
ROM_REGION(0x4000, "user1", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_END
} // Anonymous namespace
GAME( 1987, shtzone, 0, shtzone, shtzone, shtzone_state, empty_init, ROT0, "Sega", "Shooting Zone System BIOS", MACHINE_IS_SKELETON | MACHINE_IS_BIOS_ROOT )
GAME( 1987, shtzone, 0, shtzone, shtzone, shtzone_state, empty_init, ROT0, "Sega", "Shooting Zone System BIOS", MACHINE_NOT_WORKING | MACHINE_IS_BIOS_ROOT )