From 998d8e751fd507e254a69d7638d7598ba4787f5f Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Sun, 28 Jul 2019 21:23:55 +0200 Subject: [PATCH] legionna.cpp: fix sprite priorities for Seibu Cup Soccer and SD Gundam Rainbow [Angelo Salese] seibucop.cpp: identify sprite priority bit for command $c480, fixes 3rd level mid-boss in SD Gundam Rainbow being submerged when touching ground layers [Angelo Salese] new WORKING machine =================== SD Gundam Sangokushi Rainbow Tairiku Senki [Angelo Salese] --- src/mame/drivers/legionna.cpp | 4 +- src/mame/machine/seibucop/seibucop_cmd.hxx | 11 ++- src/mame/video/legionna.cpp | 102 +++++---------------- 3 files changed, 32 insertions(+), 85 deletions(-) diff --git a/src/mame/drivers/legionna.cpp b/src/mame/drivers/legionna.cpp index 2db91c69f2f..e344bd942c7 100644 --- a/src/mame/drivers/legionna.cpp +++ b/src/mame/drivers/legionna.cpp @@ -2539,8 +2539,8 @@ GAME( 1992, heatbrlu, heatbrl, heatbrl, heatbrl, legionna_state, empty_init, GAME( 1992, heatbrle, heatbrl, heatbrl, heatbrl, legionna_state, empty_init, ROT0, "TAD Corporation (Electronic Devices license)", "Heated Barrel (Electronic Devices license)", 0 ) GAME( 1993, godzilla, 0, godzilla, godzilla, legionna_state, init_godzilla, ROT0, "Banpresto", "Godzilla (Japan)", 0 ) -GAME( 1993, grainbow, 0, grainbow, grainbow, legionna_state, empty_init, ROT0, "Banpresto", "SD Gundam Sangokushi Rainbow Tairiku Senki (Japan)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) -GAME( 1993, grainbowk, grainbow, grainbow, grainbow, legionna_state, empty_init, ROT0, "Banpresto", "SD Gundam Sangokushi Rainbow Tairiku Senki (Korea)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) +GAME( 1993, grainbow, 0, grainbow, grainbow, legionna_state, empty_init, ROT0, "Banpresto", "SD Gundam Sangokushi Rainbow Tairiku Senki (Japan)", 0 ) +GAME( 1993, grainbowk, grainbow, grainbow, grainbow, legionna_state, empty_init, ROT0, "Banpresto", "SD Gundam Sangokushi Rainbow Tairiku Senki (Korea)", 0 ) GAME( 1994, denjinmk, 0, denjinmk, denjinmk, legionna_state, empty_init, ROT0, "Winkysoft (Banpresto license)", "Denjin Makai", 0 ) GAME( 1992, cupsoc, 0, cupsoc, cupsoc, legionna_state, init_cupsoc, ROT0, "Seibu Kaihatsu", "Seibu Cup Soccer (set 1)", MACHINE_UNEMULATED_PROTECTION | MACHINE_NOT_WORKING ) diff --git a/src/mame/machine/seibucop/seibucop_cmd.hxx b/src/mame/machine/seibucop/seibucop_cmd.hxx index 7bfd2f29fa5..da4a8521a7c 100644 --- a/src/mame/machine/seibucop/seibucop_cmd.hxx +++ b/src/mame/machine/seibucop/seibucop_cmd.hxx @@ -545,7 +545,7 @@ void raiden2cop_device::LEGACY_execute_c480(int offset, uint16_t data) offs = (offset & 3) * 4; - // TODO: upper bits of DMA params seems to go into sprite priority? + // TODO: bit 16 of sprite param may go there as well sprite_info = m_host_space->read_word(m_cop_sprite_dma_src + offs) + (m_cop_sprite_dma_param & 0x3f); m_host_space->write_word(cop_regs[4] + offs + 0, sprite_info); @@ -574,7 +574,14 @@ void raiden2cop_device::LEGACY_execute_c480(int offset, uint16_t data) else sprite_y = (m_sprite_dma_rel_y & 0x78) + (abs_y)-((m_sprite_dma_rel_y & 0x80) ? 0x80 : 0); - //m_host_space->write_word(cop_regs[4] + offs + 2,m_host_space->read_word(m_cop_sprite_dma_src+2 + offs)); + // 3rd midboss enables this bit for the sections that should be covered by the ground layers, + // effectively changing the priority value to 2 + if (m_cop_sprite_dma_param & 0x00020000) + { + uint16_t sprite_pri = m_host_space->read_word(cop_regs[4] + offs + 2); + sprite_pri |= 0x8000; + m_host_space->write_word(cop_regs[4] + offs + 2, sprite_pri); + } m_host_space->write_word(cop_regs[4] + offs + 4, sprite_x); m_host_space->write_word(cop_regs[4] + offs + 6, sprite_y); } diff --git a/src/mame/video/legionna.cpp b/src/mame/video/legionna.cpp index 1588ae56069..a723f92802d 100644 --- a/src/mame/video/legionna.cpp +++ b/src/mame/video/legionna.cpp @@ -207,6 +207,8 @@ void legionna_state::common_video_allocate_ptr() save_pointer(NAME(m_textram), 0x1000/2); save_pointer(NAME(m_scrollram16), 0x60/2); save_pointer(NAME(m_paletteram), 0x1000/2); + // saved for debugging + save_pointer(NAME(m_sprite_pri_mask), 4); save_item(NAME(m_back_gfx_bank)); save_item(NAME(m_mid_gfx_bank)); @@ -285,13 +287,22 @@ VIDEO_START_MEMBER(legionna_state,denjinmk) VIDEO_START_MEMBER(legionna_state,cupsoc) { - common_video_start(false, false, true); + common_video_start(false, false, false); + + m_sprite_pri_mask[0] = 0xfff0; // title screen "Seibu Cup Soccer" elements + m_sprite_pri_mask[1] = 0xfffc; // ? + m_sprite_pri_mask[2] = 0xfffe; // ? + m_sprite_pri_mask[3] = 0x0000; // 1P logo and radar dots (latter confirmed to stay above text layer) } VIDEO_START_MEMBER(legionna_state,grainbow) { common_video_start(false, false, true); m_sprite_xoffs = m_sprite_yoffs = 16; + m_sprite_pri_mask[0] = 0xfff0; // + m_sprite_pri_mask[1] = 0xfffc; // level 2 and 3 + m_sprite_pri_mask[2] = 0xfffe; // swamp monster mask effect + m_sprite_pri_mask[3] = 0x0000; // Insert coin m_layer_config = std::make_unique(0x8/2); } @@ -334,88 +345,17 @@ void legionna_state::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap,co if (m_has_extended_priority) { - cur_pri = (m_spriteram[offs+1] & 0xc000) >> 14; + // SD Gundam uses this arrangement, with bit 14 seemingly unused + // side effect of using the COP sprite DMA? + cur_pri = (m_spriteram[offs+1] & 0x8000) >> 14; if (data & 0x0040) - { - cur_pri |= 0x4; // definitely seems to be needed by grainbow - } - - // - // -4 behind bg? (mask sprites) - // -32 behind mid - // -256 behind tx - // 0 above all - - // is the low bit REALLY priority? - - switch (cur_pri) - { - case 0: pri_mask = -256; break; // gumdam swamp monster l2 - case 1: pri_mask = -256; break; // cupsoc - case 2: pri_mask = -4; break; // masking effect for gundam l2 monster - case 3: pri_mask = -4; break; // cupsoc (not sure what..) - case 4: pri_mask = -32; break; // gundam level 2/3 player - //case 5: pri_mask = 0; break; - case 6: pri_mask = 0; break; // insert coin in gundam - //case 7: pri_mask = 0; break; - - default: printf("unhandled pri %d\n",cur_pri); pri_mask=0; - } - + cur_pri |= 1; } else - { cur_pri = (m_spriteram[offs+1] & 0xc000) >> 14; - pri_mask = m_sprite_pri_mask[cur_pri]; - #if 0 - static u8 pri_test; - if (machine().input().code_pressed_once(KEYCODE_A)) - pri_test++; - - if (machine().input().code_pressed_once(KEYCODE_S)) - pri_test--; - - pri_test&=3; - popmessage("%02x",pri_test); - - // quick and dirty priority tester - if (cur_pri == pri_test) - { - static u16 test = 0xffff; - - if (machine().input().code_pressed_once(KEYCODE_Q)) - test^=1; - - if (machine().input().code_pressed_once(KEYCODE_W)) - test^=2; - - if (machine().input().code_pressed_once(KEYCODE_E)) - test^=4; - - if (machine().input().code_pressed_once(KEYCODE_R)) - test^=8; - - if (machine().input().code_pressed_once(KEYCODE_T)) - test^=0x10; - - if (machine().input().code_pressed_once(KEYCODE_Y)) - test^=0x20; - - if (machine().input().code_pressed_once(KEYCODE_U)) - test^=0x40; - - if (machine().input().code_pressed_once(KEYCODE_I)) - test^=0x80; - - pri_mask = 0xffff & test; - data = (data & 0xffc0) | (machine().rand() & 0x3f); - popmessage("%04x %04x %d",pri_mask,test,pri_test); - //pri_mask = test; - } - #endif - } + pri_mask = m_sprite_pri_mask[cur_pri]; u32 sprite = m_spriteram[offs+1]; @@ -585,16 +525,16 @@ u32 legionna_state::screen_update_grainbow(screen_device &screen, bitmap_ind16 & screen.priority().fill(0, cliprect); if (!(m_layer_disable & 1)) - m_background_layer->draw(screen, bitmap, cliprect, 0,1); + m_background_layer->draw(screen, bitmap, cliprect, 0,0); if (!(m_layer_disable & 2)) - m_midground_layer->draw(screen, bitmap, cliprect, 0,2); + m_midground_layer->draw(screen, bitmap, cliprect, 0,1); if (!(m_layer_disable & 4)) - m_foreground_layer->draw(screen, bitmap, cliprect, 0,4); + m_foreground_layer->draw(screen, bitmap, cliprect, 0,2); if (!(m_layer_disable & 8)) - m_text_layer->draw(screen, bitmap, cliprect, 0,8); + m_text_layer->draw(screen, bitmap, cliprect, 0,4); if (!(m_layer_disable & 0x0010)) draw_sprites(screen,bitmap,cliprect);