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]
This commit is contained in:
Angelo Salese 2019-07-28 21:23:55 +02:00
parent 4b5f54dd41
commit 998d8e751f
3 changed files with 32 additions and 85 deletions

View File

@ -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 )

View File

@ -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);
}

View File

@ -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<u16[]>(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);