diff options
author | 2021-01-27 15:45:26 +0100 | |
---|---|---|
committer | 2021-01-28 01:45:26 +1100 | |
commit | 832acf5731d68ca411b5fb358ddb4e79ef0faffa (patch) | |
tree | 103e96fc0cf8a6271dde2bade9932d5b8b9164b6 /src | |
parent | fd5fb05aceeea0822ae268a8af0ce54001c244f8 (diff) |
jungleyo.cpp: Added reel layer drawing, implemented priority selection, and hooked up palette. (#7710) [Angelo Salese]
Diffstat (limited to 'src')
-rw-r--r-- | src/mame/drivers/jungleyo.cpp | 263 |
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 ) |