tatsumi.cpp: apply page wraparound for backgrounds, fixes various glitches in Big Fight and Cycle Warriors [Angelo Salese]

This commit is contained in:
angelosa 2018-06-07 00:54:11 +02:00
parent 1c75a851e3
commit 1f7a89052c
3 changed files with 67 additions and 22 deletions

View File

@ -16,8 +16,8 @@
- Round Up 5: Finish road layer. - Round Up 5: Finish road layer.
Tunnel sections are borderline unplayable, plus slopes are ugly to watch. Tunnel sections are borderline unplayable, plus slopes are ugly to watch.
- Apache 3: road layer, has twelve rotation registers! - Apache 3: road layer, has twelve rotation registers!
- Cycle Warriors: transparent road layer on sidelines, wrong mask_data? - (fixed) Cycle Warriors: transparent road layer on sidelines, wrong mask_data?
- Missing BG layer (Round Up 5) - banked VRAM data from somewhere!? - (fixed) Missing BG layer (Round Up 5) - banked VRAM data from somewhere!?
- Round Up 5: always boots with a coin inserted - Round Up 5: always boots with a coin inserted
$5152 is the coin counter, gets an explicit 1 at boot. $5152 is the coin counter, gets an explicit 1 at boot.
There are other two buffers read from 68k before that, written to $5156 and $515a There are other two buffers read from 68k before that, written to $5156 and $515a
@ -25,10 +25,10 @@
- (fixed) Round Up 5 doesn't survive a reset - (fixed) Round Up 5 doesn't survive a reset
- (fixed?) Cycle Warriors: test mode text does not appear as it needs a -256 Y - (fixed?) Cycle Warriors: test mode text does not appear as it needs a -256 Y
scroll offset from somewhere. scroll offset from somewhere.
- Cycle Warriors: sometimes it draws garbage on character select or even hangs - (fixed) Cycle Warriors: sometimes it draws garbage on character select or even hangs
depending on where player coins up, most likely caused by miscommunication with sub CPU? depending on where player coins up, most likely caused by miscommunication with sub CPU?
- Cycle Warriors: ranking screen is completely wrong; - (fixed) Cycle Warriors: ranking screen is completely wrong;
- Cycle Warriors: ugly orange color on character select and briefing screens, layer disable? - (fixed) Cycle Warriors: ugly orange color on character select and briefing screens, layer disable?
- Combine Big Fight & CycleWarriors video routines - currently each - Combine Big Fight & CycleWarriors video routines - currently each
game uses different sized tilemaps - these are probably software game uses different sized tilemaps - these are probably software
controlled rather than hardwired, but I don't think either game controlled rather than hardwired, but I don't think either game
@ -190,11 +190,6 @@ WRITE16_MEMBER(cyclwarr_state::cyclwarr_sprite_w)
COMBINE_DATA(&m_spriteram[offset]); COMBINE_DATA(&m_spriteram[offset]);
} }
WRITE16_MEMBER(cyclwarr_state::bigfight_a20000_w)
{
COMBINE_DATA(&m_bigfight_a20000[offset]);
}
WRITE16_MEMBER(cyclwarr_state::bigfight_a40000_w) WRITE16_MEMBER(cyclwarr_state::bigfight_a40000_w)
{ {
COMBINE_DATA(&m_bigfight_a40000[offset]); COMBINE_DATA(&m_bigfight_a40000[offset]);
@ -203,6 +198,7 @@ WRITE16_MEMBER(cyclwarr_state::bigfight_a40000_w)
WRITE16_MEMBER(cyclwarr_state::bigfight_a60000_w) WRITE16_MEMBER(cyclwarr_state::bigfight_a60000_w)
{ {
COMBINE_DATA(&m_bigfight_a60000[offset]); COMBINE_DATA(&m_bigfight_a60000[offset]);
// popmessage("%04x",m_bigfight_a60000[offset]);
} }
template<int Bank> template<int Bank>
@ -343,7 +339,7 @@ void cyclwarr_state::common_map(address_map &map)
map(0x080000, 0x08ffff).rw(this, FUNC(cyclwarr_state::cyclwarr_videoram_r<1>), FUNC(cyclwarr_state::cyclwarr_videoram_w<1>)).share("cw_videoram1"); map(0x080000, 0x08ffff).rw(this, FUNC(cyclwarr_state::cyclwarr_videoram_r<1>), FUNC(cyclwarr_state::cyclwarr_videoram_w<1>)).share("cw_videoram1");
map(0x090000, 0x09ffff).rw(this, FUNC(cyclwarr_state::cyclwarr_videoram_r<0>), FUNC(cyclwarr_state::cyclwarr_videoram_w<0>)).share("cw_videoram0"); map(0x090000, 0x09ffff).rw(this, FUNC(cyclwarr_state::cyclwarr_videoram_r<0>), FUNC(cyclwarr_state::cyclwarr_videoram_w<0>)).share("cw_videoram0");
map(0x0a2000, 0x0a2007).w(this, FUNC(cyclwarr_state::bigfight_a20000_w)); map(0x0a2000, 0x0a2007).w(this, FUNC(cyclwarr_state::video_config_w));
map(0x0a4000, 0x0a4001).w(this, FUNC(cyclwarr_state::bigfight_a40000_w)); map(0x0a4000, 0x0a4001).w(this, FUNC(cyclwarr_state::bigfight_a40000_w));
map(0x0a6000, 0x0a6001).w(this, FUNC(cyclwarr_state::bigfight_a60000_w)); map(0x0a6000, 0x0a6001).w(this, FUNC(cyclwarr_state::bigfight_a60000_w));
map(0x0ac000, 0x0ac003).w(this, FUNC(tatsumi_state::hd6445_crt_w)).umask16(0x00ff); map(0x0ac000, 0x0ac003).w(this, FUNC(tatsumi_state::hd6445_crt_w)).umask16(0x00ff);

View File

@ -195,7 +195,7 @@ public:
DECLARE_READ16_MEMBER(cyclwarr_sprite_r); DECLARE_READ16_MEMBER(cyclwarr_sprite_r);
DECLARE_WRITE16_MEMBER(cyclwarr_sprite_w); DECLARE_WRITE16_MEMBER(cyclwarr_sprite_w);
DECLARE_WRITE16_MEMBER(bigfight_a20000_w); DECLARE_WRITE16_MEMBER(video_config_w);
DECLARE_WRITE16_MEMBER(bigfight_a40000_w); DECLARE_WRITE16_MEMBER(bigfight_a40000_w);
DECLARE_WRITE16_MEMBER(bigfight_a60000_w); DECLARE_WRITE16_MEMBER(bigfight_a60000_w);
DECLARE_WRITE8_MEMBER(cyclwarr_control_w); DECLARE_WRITE8_MEMBER(cyclwarr_control_w);
@ -234,16 +234,17 @@ private:
std::vector<uint8_t> m_mask; std::vector<uint8_t> m_mask;
tilemap_t *m_layer[4]; tilemap_t *m_layer[4];
uint16_t m_bigfight_a20000[8]; uint16_t m_video_config[4];
uint16_t m_bigfight_a60000[2]; uint16_t m_bigfight_a60000[2];
uint16_t m_bigfight_a40000[2]; uint16_t m_bigfight_a40000[2];
uint16_t m_bigfight_bank; uint16_t m_bigfight_bank;
uint16_t m_bigfight_last_bank; uint16_t m_bigfight_last_bank;
uint16_t m_road_color_bank, m_prev_road_bank; uint16_t m_road_color_bank, m_prev_road_bank;
uint16_t m_layer_page_size[4];
bool m_layer1_can_be_road; bool m_layer1_can_be_road;
void tile_expand(); void tile_expand();
void draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *src, const uint16_t* scrollx, const uint16_t* scrolly, bool is_road, int hi_priority); void draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *src, const uint16_t* scrollx, const uint16_t* scrolly, const uint16_t layer_page_size, bool is_road, int hi_priority);
void draw_bg_layers(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int hi_priority); void draw_bg_layers(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int hi_priority);
}; };

View File

@ -1058,6 +1058,27 @@ uint32_t roundup5_state::screen_update_roundup5(screen_device &screen, bitmap_rg
* *
*********************************/ *********************************/
/*
* these video registers never changes
*
* Big Fight
* 72f2 5af2 3af2 22fa
*
* Cycle Warriors
* 5673 92c2 3673 267b
*
* Following is complete guesswork (since nothing changes it's very hard to pinpoint what these bits do :/)
* Layer order is 3-1-2-0 ?
* x--- -x-- ---- ---- one of these might be enable page select
* ---- ---- x--- ---- tilemap size
* ---x ---- ---- x--- one these might be color bank
*
*/
WRITE16_MEMBER(cyclwarr_state::video_config_w)
{
COMBINE_DATA(&m_video_config[offset]);
}
template<int Bank> template<int Bank>
TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_bigfight) TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_bigfight)
{ {
@ -1162,9 +1183,14 @@ VIDEO_START_MEMBER(cyclwarr_state,cyclwarr)
// set up scroll bases // set up scroll bases
// TODO: more HW configs // TODO: more HW configs
m_layer[3]->set_scrolldx(-8,-8); m_layer[3]->set_scrolldx(-8,-8);
m_layer_page_size[3] = 0x200;
m_layer[2]->set_scrolldx(-8,-8); m_layer[2]->set_scrolldx(-8,-8);
m_layer_page_size[2] = 0x200;
m_layer[1]->set_scrolldx(-8,-8); m_layer[1]->set_scrolldx(-8,-8);
m_layer_page_size[1] = 0x200;
m_layer[0]->set_scrolldx(-0x10,-0x10); m_layer[0]->set_scrolldx(-0x10,-0x10);
m_layer_page_size[0] = 0x100;
m_layer1_can_be_road = true; m_layer1_can_be_road = true;
} }
@ -1184,11 +1210,14 @@ VIDEO_START_MEMBER(cyclwarr_state,bigfight)
m_layer[2]->set_scrolldx(-8,-8); m_layer[2]->set_scrolldx(-8,-8);
m_layer[1]->set_scrolldx(-8,-8); m_layer[1]->set_scrolldx(-8,-8);
m_layer[0]->set_scrolldx(-0x10,-0x10); m_layer[0]->set_scrolldx(-0x10,-0x10);
for(int i=0;i<4;i++)
m_layer_page_size[i] = 0x200;
m_layer1_can_be_road = false; m_layer1_can_be_road = false;
} }
void cyclwarr_state::draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *src, const uint16_t* scrollx, const uint16_t* scrolly, bool is_road, int hi_priority) void cyclwarr_state::draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, tilemap_t *src, const uint16_t* scrollx, const uint16_t* scrolly, const uint16_t layer_page_size, bool is_road, int hi_priority)
{ {
rectangle clip; rectangle clip;
clip.min_x = cliprect.min_x; clip.min_x = cliprect.min_x;
@ -1196,21 +1225,31 @@ void cyclwarr_state::draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const
// TODO: both always enabled when this occurs // TODO: both always enabled when this occurs
bool rowscroll_enable = (scrollx[0] & 0x1000) == 0; bool rowscroll_enable = (scrollx[0] & 0x1000) == 0;
bool colscroll_enable = (scrollx[0] & 0x2000) == 0; bool colscroll_enable = (scrollx[0] & 0x2000) == 0;
// this controls wraparound (tilemap can't go above a threshold)
// TODO: Actually scrolly registers 0xf0 to 0xff are used (can split the tilemap furthermore?)
uint16_t page_select = scrolly[0xff];
for (int y=cliprect.min_y; y<=cliprect.max_y; y++) for (int y=cliprect.min_y; y<=cliprect.max_y; y++)
{ {
clip.min_y = clip.max_y = y; clip.min_y = clip.max_y = y;
int y_base = rowscroll_enable ? y : 0; int y_base = rowscroll_enable ? y : 0;
int x_base = colscroll_enable ? y : 0; int x_base = colscroll_enable ? y : 0;
int src_y = (scrolly[y_base] & 0xfff); int src_y = (scrolly[y_base] & 0x7ff);
int src_x = (scrollx[x_base] & 0x7ff); int src_x = (scrollx[x_base] & 0x7ff);
// apparently if this is on disables wraparound target
int page_disable = scrolly[y_base] & 0x800;
int cur_page = src_y + y;
// special handling for cycle warriors road: it reads in scrolly table bits 15-13 an // special handling for cycle warriors road: it reads in scrolly table bits 15-13 an
// additional tile color bank and per scanline. // additional tile color bank and per scanline.
if(is_road == true) if(is_road == true)
{ {
if(scrolly[y_base] & 0x8000) if(scrolly[y_base] & 0x8000)
{
m_road_color_bank = (scrolly[y_base] >> 13) & 3; m_road_color_bank = (scrolly[y_base] >> 13) & 3;
// road mode disables page wraparound
page_disable = 1;
}
else else
m_road_color_bank = 0; m_road_color_bank = 0;
@ -1221,6 +1260,13 @@ void cyclwarr_state::draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const
} }
} }
// apply wraparound, if enabled tilemaps can't go above a certain threshold
// cfr. Cycle Warriors scrolling text (ranking, ending), backgrounds when uphill,
// Big Fight vertical scrolling in the morning Funnel stage (not the one chosen at start),
// also Big Fight text garbage in the stage after Mevella joins you (forgot the name)
if((cur_page - page_select) >= layer_page_size && page_disable == 0)
src_y -= layer_page_size;
src->set_scrollx(0,src_x); src->set_scrollx(0,src_x);
src->set_scrolly(0,src_y); src->set_scrolly(0,src_y);
src->draw(screen, bitmap, clip, TILEMAP_DRAW_CATEGORY(hi_priority), 0); src->draw(screen, bitmap, clip, TILEMAP_DRAW_CATEGORY(hi_priority), 0);
@ -1229,10 +1275,10 @@ void cyclwarr_state::draw_bg(screen_device &screen, bitmap_rgb32 &bitmap, const
void cyclwarr_state::draw_bg_layers(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int hi_priority) void cyclwarr_state::draw_bg_layers(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int hi_priority)
{ {
draw_bg(screen, bitmap, cliprect, m_layer[3], &m_cyclwarr_videoram[1][0x000], &m_cyclwarr_videoram[1][0x100], false, hi_priority); draw_bg(screen, bitmap, cliprect, m_layer[3], &m_cyclwarr_videoram[1][0x000], &m_cyclwarr_videoram[1][0x100], m_layer_page_size[3], false, hi_priority);
draw_bg(screen, bitmap, cliprect, m_layer[2], &m_cyclwarr_videoram[1][0x200], &m_cyclwarr_videoram[1][0x300], false, hi_priority); draw_bg(screen, bitmap, cliprect, m_layer[2], &m_cyclwarr_videoram[1][0x200], &m_cyclwarr_videoram[1][0x300], m_layer_page_size[2],false, hi_priority);
draw_bg(screen, bitmap, cliprect, m_layer[1], &m_cyclwarr_videoram[0][0x000], &m_cyclwarr_videoram[0][0x100], m_layer1_can_be_road, hi_priority); draw_bg(screen, bitmap, cliprect, m_layer[1], &m_cyclwarr_videoram[0][0x000], &m_cyclwarr_videoram[0][0x100], m_layer_page_size[1],m_layer1_can_be_road, hi_priority);
draw_bg(screen, bitmap, cliprect, m_layer[0], &m_cyclwarr_videoram[0][0x200], &m_cyclwarr_videoram[0][0x300], false, hi_priority); draw_bg(screen, bitmap, cliprect, m_layer[0], &m_cyclwarr_videoram[0][0x200], &m_cyclwarr_videoram[0][0x300], m_layer_page_size[0], false, hi_priority);
} }
uint32_t cyclwarr_state::screen_update_cyclwarr(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) uint32_t cyclwarr_state::screen_update_cyclwarr(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@ -1258,6 +1304,8 @@ uint32_t cyclwarr_state::screen_update_cyclwarr(screen_device &screen, bitmap_rg
,m_cyclwarr_videoram[0][0x200],m_cyclwarr_videoram[0][0x300],m_cyclwarr_videoram[0][0x3ff]); ,m_cyclwarr_videoram[0][0x200],m_cyclwarr_videoram[0][0x300],m_cyclwarr_videoram[0][0x3ff]);
#endif #endif
// popmessage("%04x %04x %04x %04x",m_video_config[0],m_video_config[1],m_video_config[2],m_video_config[3]);
screen.priority().fill(0, cliprect); screen.priority().fill(0, cliprect);
draw_sprites(screen.priority(),cliprect,1,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); // Alpha pass only draw_sprites(screen.priority(),cliprect,1,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); // Alpha pass only
draw_bg_layers(screen, bitmap, cliprect, 0); draw_bg_layers(screen, bitmap, cliprect, 0);