summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/jungleyo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/jungleyo.cpp')
-rw-r--r--src/mame/drivers/jungleyo.cpp263
1 files changed, 189 insertions, 74 deletions
diff --git a/src/mame/drivers/jungleyo.cpp b/src/mame/drivers/jungleyo.cpp
index eb87dc8cd84..23d66f0016c 100644
--- a/src/mame/drivers/jungleyo.cpp
+++ b/src/mame/drivers/jungleyo.cpp
@@ -1,7 +1,33 @@
// license:BSD-3-Clause
-// copyright-holders:David Haywood
+// copyright-holders:Angelo Salese
+/******************************************************************************
+
+ Jungle (c) 2001 Yonshi
+
+ TODO:
+ - with a clean NVRAM MAME needs to be soft reset after init or the game
+ will trip a '1111 exception' (caused by invalid opcode executed at
+ 0x102, incomplete decryption most likely);
+ - Likewise anything in the 0x100-0x1f7 range doesn't seem valid at all;
+ - game sometimes expects 1+ coins even if player has available points
+ (and freezing with "COIN" text blinking), very unlikely to be intended
+ behaviour?
+ - system setting screen shows the following settings that don't seem to be
+ affected by dips:
+ * Min. Bet (always 1),
+ * Credit X Ticket Mode (always Cencel (sic)),
+ * Max. 10 Mode (always Max. 10);
+ - sound doesn't seem to work 100% correctly (i.e. coin sound only seems
+ to work from 3rd coin on, lots of invalid sample msgs in error.log).
+ fwiw there's no extra OKI bank in the ROM, must be either invalid
+ decryption or fancy OKI status readback instead.
+ Latter may be confirmed by video display stalling at the end of a
+ normal round, OSD coin counter gets updated after the BGM completes
+ playback.
+ - outputs (lamps & ticket dispenser at very least);
+
+===============================================================================
-/*
CPUs
QTY Type clock position function
1x MC68HC000FN10 u3 16/32-bit Microprocessor - main
@@ -35,14 +61,7 @@ Others
Notes
PCB silkscreened: "MADE IN TAIWAN YONSHI PCB NO-006F"
-TODO:
-- driver is skeleton-ish, video emulation is at the bare minimum to see what's going on;
-- with a clean NVRAM MAME needs to be soft reset after init or the game will stop with '1111 exception' error;
-- decryption is believed complete, but there's something strange with the first bytes of the ROM;
-- system setting screen shows the following settings that don't seem to be affected by dips:
- Min. Bet (always 1), Credit X Ticket Mode (always Cencel (sic)), Max. 10 Mode (always Max. 10);
-- sound doesn't seem to work 100% correctly (i.e. coin sound only seems to work from 3rd coin on).
-*/
+*******************************************************************************/
#include "emu.h"
@@ -74,6 +93,9 @@ public:
, m_gfxdecode(*this, "gfxdecode")
, m_bg_videoram(*this, "bg_videoram")
, m_fg_videoram(*this, "fg_videoram")
+ , m_reel_vram(*this, "reel_vram%u", 1U)
+ , m_palette(*this, "palette")
+ , m_paletteram(*this, "paletteram", 0x18000, ENDIANNESS_BIG)
{ }
void jungleyo(machine_config &config);
@@ -90,86 +112,179 @@ private:
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
TILE_GET_INFO_MEMBER(get_bg_tile_info);
TILE_GET_INFO_MEMBER(get_fg_tile_info);
- void bg_videoram_w(offs_t offset, uint16_t data);
- void fg_videoram_w(offs_t offset, uint16_t data);
+ template <int Layer> TILE_GET_INFO_MEMBER(get_reel_tile_info);
+ void bg_videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ void fg_videoram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
+ template <int Layer> void reel_vram_w(offs_t offset, u16 data, u16 mem_mask = ~0);
void main_map(address_map &map);
+ u8 palette_ram_r(offs_t offset);
+ void palette_ram_w(offs_t offset, u8 data);
+ void layer_enable_w(u8 data);
+ void video_priority_w(u8 data);
+
required_device<cpu_device> m_maincpu;
required_device<gfxdecode_device> m_gfxdecode;
required_shared_ptr<uint16_t> m_bg_videoram;
required_shared_ptr<uint16_t> m_fg_videoram;
+ required_shared_ptr_array<u16, 3> m_reel_vram;
+ required_device<palette_device> m_palette;
+ memory_share_creator<u8> m_paletteram;
tilemap_t *m_bg_tilemap;
tilemap_t *m_fg_tilemap;
+ tilemap_t *m_reel_tilemap[3];
+ u8 m_layer_enable;
+ u8 m_video_priority;
};
-void jungleyo_state::output_w(uint16_t data)
+TILE_GET_INFO_MEMBER(jungleyo_state::get_bg_tile_info)
{
- // bit 15 ?
- // bit 14 coin counter?
- // bit 13 ?
- // bit 12 ?
- // bit 11 ?
- // bit 10 ?
- // bit 09 ?
- // bit 08 ?
- // bit 07 ?
- // bit 06 ?
- // bit 05 ?
- // bit 04 ?
- // bit 03 ?
- // bit 02 ?
- // bit 01 start lamp?
- // bit 00 bet lamp?
-
- machine().bookkeeping().coin_counter_w(0, BIT(data, 14));
-
- if (data & 0xbfff)
- LOGOUTPUTS("%s output_w: %04x\n", machine().describe_context(), data);
+ u16 code = m_bg_videoram[tile_index*2+1];
+ u16 color = m_bg_videoram[tile_index*2];
+ tileinfo.set(1, code, color & 0x1f, 0);
}
-
-TILE_GET_INFO_MEMBER(jungleyo_state::get_bg_tile_info)
+TILE_GET_INFO_MEMBER(jungleyo_state::get_fg_tile_info)
{
- uint16_t code = m_bg_videoram[tile_index];
- tileinfo.set(1, code, 0, 0);
+ u16 code = m_fg_videoram[tile_index*2+1];
+ u16 color = m_fg_videoram[tile_index*2];
+ tileinfo.set(2, code, color & 0x1f, 0);
}
-TILE_GET_INFO_MEMBER(jungleyo_state::get_fg_tile_info)
+template <int Layer> TILE_GET_INFO_MEMBER(jungleyo_state::get_reel_tile_info)
{
- uint16_t code = m_fg_videoram[tile_index];
- tileinfo.set(2, code, 0, 0);
+ u16 code = m_reel_vram[Layer][tile_index*2+1];
+ // colscroll is on upper 8 bits of this (handled in update)
+ u16 color = m_reel_vram[Layer][tile_index*2];
+ // TODO: confirm if bit 6 is really connected here
+ // upper palette bank is initialized with black at POST and never ever touched again,
+ // not enough to pinpoint one way or another ...
+ tileinfo.set(0, code, color & 0x3f, 0);
}
-void jungleyo_state::bg_videoram_w(offs_t offset, uint16_t data)
+void jungleyo_state::bg_videoram_w(offs_t offset, u16 data, u16 mem_mask)
{
- m_bg_videoram[offset / 2] = data;
+ COMBINE_DATA(&m_bg_videoram[offset]);
m_bg_tilemap->mark_tile_dirty(offset / 2);
}
-void jungleyo_state::fg_videoram_w(offs_t offset, uint16_t data)
+void jungleyo_state::fg_videoram_w(offs_t offset, u16 data, u16 mem_mask)
{
- m_fg_videoram[offset / 2] = data;
+ COMBINE_DATA(&m_fg_videoram[offset]);
m_fg_tilemap->mark_tile_dirty(offset / 2);
}
+template <int Layer> void jungleyo_state::reel_vram_w(offs_t offset, u16 data, u16 mem_mask)
+{
+ COMBINE_DATA(&m_reel_vram[Layer][offset]);
+ m_reel_tilemap[Layer]->mark_tile_dirty(offset / 2);
+}
+
void jungleyo_state::video_start()
{
m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(jungleyo_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(jungleyo_state::get_fg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
+ m_reel_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(jungleyo_state::get_reel_tile_info<0>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
+ m_reel_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(jungleyo_state::get_reel_tile_info<1>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
+ m_reel_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(jungleyo_state::get_reel_tile_info<2>)), TILEMAP_SCAN_ROWS, 8, 32, 64, 8);
+
m_fg_tilemap->set_transparent_pen(0);
+ m_bg_tilemap->set_transparent_pen(0);
+ for (auto &reel : m_reel_tilemap)
+ {
+ reel->set_scroll_cols(64);
+ reel->set_transparent_pen(0xff);
+ }
}
uint32_t jungleyo_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ bitmap.fill(m_palette->black_pen(), cliprect);
+
+ if (m_layer_enable == 0)
+ return 0;
+
+ for (int Layer = 0; Layer < 3; Layer++)
+ {
+ for (int i = 0; i < 64; i++)
+ {
+ u16 scroll = m_reel_vram[Layer][i*2] >> 8;
+ m_reel_tilemap[Layer]->set_scrolly(i, scroll);
+ }
+
+ m_reel_tilemap[Layer]->draw(screen, bitmap, cliprect, 0, 0);
+ }
+
+ if ((m_video_priority & 1) == 0)
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ if ((m_video_priority & 1) == 1)
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
return 0;
}
+u8 jungleyo_state::palette_ram_r(offs_t offset)
+{
+ return m_paletteram[offset];
+}
+
+void jungleyo_state::palette_ram_w(offs_t offset, u8 data)
+{
+ // RGB888 in three separate banks
+ m_paletteram[offset] = data;
+ const u32 pal_offs = offset & 0x7fff;
+ const int b = (m_paletteram[pal_offs | 0x00000] & 0xff);
+ const int g = (m_paletteram[pal_offs | 0x08000] & 0xff);
+ const int r = (m_paletteram[pal_offs | 0x10000] & 0xff);
+
+ m_palette->set_pen_color(pal_offs, rgb_t(r, g, b));
+}
+
+void jungleyo_state::output_w(uint16_t data)
+{
+ // bit 15 ?
+ // bit 14 coin counter?
+ // bit 13 ?
+ // bit 12 ?
+ // bit 11 ?
+ // bit 10 ?
+ // bit 09 ?
+ // bit 08 ?
+ // bit 07 ?
+ // bit 06 ?
+ // bit 05 ?
+ // bit 04 ?
+ // bit 03 ?
+ // bit 02 ?
+ // bit 01 start lamp?
+ // bit 00 bet lamp?
+
+ machine().bookkeeping().coin_counter_w(0, BIT(data, 14));
+
+ if (data & 0xbfff)
+ LOGOUTPUTS("%s output_w: %04x\n", machine().describe_context(), data);
+}
+
+void jungleyo_state::layer_enable_w(u8 data)
+{
+ m_layer_enable = data & 7;
+ // TODO: we just know that 7 enables and 0 disables all 3 layers, how the composition works out internally is MIA
+ if (((m_layer_enable != 7) && (m_layer_enable != 0)) || data & 0xf8)
+ popmessage("layer enable %02x contact MAMEdev", data);
+}
+
+void jungleyo_state::video_priority_w(u8 data)
+{
+ m_video_priority = data & 1;
+ if (data & 0xfe)
+ popmessage("video priority %02x contact MAMEdev", data & 0xfe);
+}
void jungleyo_state::main_map(address_map &map)
{
@@ -178,21 +293,23 @@ void jungleyo_state::main_map(address_map &map)
map(0xa0032a, 0xa0032b).portr("DSW12");
map(0xa0032c, 0xa0032d).portr("DSW34");
map(0xa00336, 0xa00337).w(FUNC(jungleyo_state::output_w)); // outputs? observed values: lots
- map(0xa00689, 0xa00689).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write)); // TODO: something's definitely wrong here, lots of errors in the log
+ map(0xa00689, 0xa00689).rw("oki", FUNC(okim6295_device::read), FUNC(okim6295_device::write));
//map(0xa0068a, 0xa0068b).nopw(); // observed values: 0x0101
//map(0xa0082e, 0xa0082f).nopw(); // observed values: 0x0000, 0x4000, 0x5900 (double up),
- //map(0xa00830, 0xa00831).nopw(); // observed values: 0x0000 and 0x0007
- //map(0xa00832, 0xa00833).nopw(); // tilemap priority ? observed values: 0x0000 and 0x0001
- //map(0xa00aaa, 0xa00aab).nopw(); // observed values: 0x0000, this is written continuously
+ map(0xa00831, 0xa00831).w(FUNC(jungleyo_state::layer_enable_w));
+ map(0xa00833, 0xa00833).w(FUNC(jungleyo_state::video_priority_w));
+ map(0xa00aaa, 0xa00aab).nopw(); // irq ack or watchdog (written at start of vblank irq)
//map(0xa00d58, 0xa00d59).nopw(); // observed values: 0x0004
//map(0xa00e9a, 0xa00e9b).nopw(); // observed values: 0x0005
//map(0xa00fc6, 0xa00fc7).nopw(); // observed values: 0x0006
- map(0xb00000, 0xb0ffff).ram();
- map(0xb10000, 0xb1ffff).ram();
- map(0xb20000, 0xb2ffff).ram();
+ map(0xb00000, 0xb2ffff).rw(FUNC(jungleyo_state::palette_ram_r), FUNC(jungleyo_state::palette_ram_w)).umask16(0x00ff);
map(0xb80000, 0xb81fff).ram().share(m_fg_videoram).w(FUNC(jungleyo_state::fg_videoram_w));
map(0xb90000, 0xb91fff).ram().share(m_bg_videoram).w(FUNC(jungleyo_state::bg_videoram_w));
- map(0xba0000, 0xba1fff).ram();
+ map(0xba0000, 0xba07ff).ram().share(m_reel_vram[0]).w(FUNC(jungleyo_state::reel_vram_w<0>));
+ map(0xba0800, 0xba0fff).ram().share(m_reel_vram[1]).w(FUNC(jungleyo_state::reel_vram_w<1>));
+ map(0xba1000, 0xba17ff).ram().share(m_reel_vram[2]).w(FUNC(jungleyo_state::reel_vram_w<2>));
+ map(0xba1800, 0xba1fff).ram(); // supposedly the 4th reel VRAM bank, inited at POST only and probably just tied to NOP instead
+
map(0xff0000, 0xff7fff).ram();
map(0xff8000, 0xffffff).ram().share("nvram");
}
@@ -299,9 +416,9 @@ static const gfx_layout jungleyo_layout =
8,8,
RGN_FRAC(1,1),
8,
- { 0,1,2,3,4,5,6,7 },
- { 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8 },
- { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64 },
+ { STEP8(0,1) },
+ { STEP8(0,8) },
+ { STEP8(0,8*8) },
8*64
};
@@ -310,19 +427,16 @@ static const gfx_layout jungleyo16_layout =
8,32,
RGN_FRAC(1,1),
8,
- { 0,1,2,3,4,5,6,7 },
- { 0*8,1*8,2*8,3*8,4*8,5*8,6*8,7*8 },
- { 0*64, 1*64, 2*64, 3*64, 4*64, 5*64, 6*64, 7*64,
- 8*64, 9*64,10*64,11*64,12*64,13*64,14*64,15*64,
- 16*64,17*64,18*64,19*64,20*64,21*64,22*64,23*64,
- 24*64,25*64,26*64,27*64,28*64,29*64,30*64,31*64 },
+ { STEP8(0,1) },
+ { STEP8(0,8) },
+ { STEP32(0,8*8) },
8*64*4
};
static GFXDECODE_START( gfx_jungleyo )
- GFXDECODE_ENTRY( "reelgfx", 0, jungleyo16_layout, 0x0, 2 )
- GFXDECODE_ENTRY( "gfx2", 0, jungleyo_layout, 0x0, 2 )
- GFXDECODE_ENTRY( "gfx3", 0, jungleyo_layout, 0x0, 2 )
+ GFXDECODE_ENTRY( "reelgfx", 0, jungleyo16_layout, 0x4000, 0x40 )
+ GFXDECODE_ENTRY( "gfx2", 0, jungleyo_layout, 0x2000, 0x20 )
+ GFXDECODE_ENTRY( "gfx3", 0, jungleyo_layout, 0x0000, 0x20 )
GFXDECODE_END
@@ -334,17 +448,17 @@ void jungleyo_state::jungleyo(machine_config &config)
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
- GFXDECODE(config, m_gfxdecode, "palette", gfx_jungleyo);
+ GFXDECODE(config, m_gfxdecode, m_palette, gfx_jungleyo);
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
screen.set_size(64*8, 32*8);
- screen.set_visarea(0*8, 64*8-1, 0*8, 32*8-1);
+ screen.set_visarea(0*8, 64*8-1, 2*8, 32*8-1);
screen.set_screen_update(FUNC(jungleyo_state::screen_update));
- screen.set_palette("palette");
+ screen.set_palette(m_palette);
- PALETTE(config, "palette").set_format(palette_device::xRGB_555, 0x200);
+ PALETTE(config, m_palette).set_entries(0x8000);
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
@@ -373,8 +487,7 @@ ROM_START( jungleyo )
ROM_LOAD( "jungle_rom6.u60", 0x000000, 0x80000, CRC(caab8eb2) SHA1(472ca9f396d7c01a1bd03485581cfae677a3b365) )
ROM_END
-
-void jungleyo_state::init_jungleyo() // TODO: the first bytes don't seem to decrypt correctly
+void jungleyo_state::init_jungleyo()
{
uint16_t *src = (uint16_t *)memregion("maincpu")->base();
@@ -390,14 +503,16 @@ void jungleyo_state::init_jungleyo() // TODO: the first bytes don't seem to decr
for (int i = 0x30000 / 2; i < 0x40000 / 2; i++)
src[i] = bitswap<16>(src[i] ^ 0xffff, 13, 15, 8, 9, 12, 11, 10, 14, 1, 3, 7, 5, 2, 6, 0, 4);
+ // TODO: Stack Pointer/Initial PC settings don't seem to decrypt correctly
// hack these until better understood (still wrong values)
src[0x000 / 2] = 0x0000;
src[0x002 / 2] = 0x0000;
src[0x004 / 2] = 0x0000;
- src[0x006 / 2] = 0x01fa;
+ src[0x006 / 2] = 0x01f8; // reset opcode
}
} // Anonymous namespace
-GAME( 2001, jungleyo, 0, jungleyo, jungleyo, jungleyo_state, init_jungleyo, ROT0, "Yonshi", "Jungle (VI3.02)", MACHINE_IS_SKELETON ) // version 3.02 built on 2001/02/09, there's copyright both for Yonshi and Global in strings
+// version 3.02 built on 2001/02/09, there's copyright both for Yonshi and Global in strings
+GAME( 2001, jungleyo, 0, jungleyo, jungleyo, jungleyo_state, init_jungleyo, ROT0, "Yonshi", "Jungle (Italy VI3.02)", MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION | MACHINE_IMPERFECT_SOUND )