From 63cf91f2142c69fed817b4b1119e4cf7ee84ca77 Mon Sep 17 00:00:00 2001 From: angelosa Date: Fri, 1 Jun 2018 17:17:39 +0200 Subject: tatsumi.cpp: cycle warriors and big fight bit 15 of tilemap code is per-tile high priority with regards to sprites. Fixes several priority glitches [Angelo Salese] (out of whatsnew: also made a massive order cleanup) --- src/mame/drivers/tatsumi.cpp | 13 +- src/mame/includes/tatsumi.h | 10 +- src/mame/video/tatsumi.cpp | 813 ++++++++++++++++++++++--------------------- 3 files changed, 433 insertions(+), 403 deletions(-) diff --git a/src/mame/drivers/tatsumi.cpp b/src/mame/drivers/tatsumi.cpp index 4fbf3b9fb41..ca41af11d9f 100644 --- a/src/mame/drivers/tatsumi.cpp +++ b/src/mame/drivers/tatsumi.cpp @@ -215,11 +215,8 @@ template WRITE16_MEMBER(cyclwarr_state::cyclwarr_videoram_w) { COMBINE_DATA(&m_cyclwarr_videoram[Bank][offset]); - if (offset>=0x400) - { - m_layer[(Bank<<1)|0]->mark_tile_dirty(offset-0x400); - m_layer[(Bank<<1)|1]->mark_tile_dirty(offset-0x400); - } + m_layer[(Bank<<1)|0]->mark_tile_dirty(offset); + m_layer[(Bank<<1)|1]->mark_tile_dirty(offset); } WRITE16_MEMBER(cyclwarr_state::output_w) @@ -1012,6 +1009,8 @@ void cyclwarr_state::machine_reset() m_last_control = 0; m_control_word = 0; + + m_road_color_bank = m_prev_road_bank = 0; } MACHINE_CONFIG_START(cyclwarr_state::cyclwarr) @@ -1076,8 +1075,8 @@ MACHINE_CONFIG_START(cyclwarr_state::bigfight) cyclwarr(config); // TODO: it's same video HW, we don't know how/where video registers are mapped - MCFG_SCREEN_MODIFY("screen") - MCFG_SCREEN_UPDATE_DRIVER(cyclwarr_state, screen_update_bigfight) +// MCFG_SCREEN_MODIFY("screen") +// MCFG_SCREEN_UPDATE_DRIVER(cyclwarr_state, screen_update_bigfight) MCFG_VIDEO_START_OVERRIDE(cyclwarr_state, bigfight) diff --git a/src/mame/includes/tatsumi.h b/src/mame/includes/tatsumi.h index 029e1f2e9dd..74bc9a31266 100644 --- a/src/mame/includes/tatsumi.h +++ b/src/mame/includes/tatsumi.h @@ -212,7 +212,6 @@ public: DECLARE_VIDEO_START(cyclwarr); DECLARE_VIDEO_START(bigfight); uint32_t screen_update_cyclwarr(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); - uint32_t screen_update_bigfight(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); void cyclwarr(machine_config &config); void bigfight(machine_config &config); @@ -240,8 +239,11 @@ private: uint16_t m_bigfight_a40000[2]; uint16_t m_bigfight_bank; uint16_t m_bigfight_last_bank; - uint16_t m_cyclwarr_color_bank; - + uint16_t m_road_color_bank, m_prev_road_bank; + bool m_layer1_can_be_road; + 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, int xscroll_offset, int yscroll_offset, bool is_road, bool is_opaque); + 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, bool is_opaque, int hi_priority); + void draw_bg_layers(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int hi_priority); }; + diff --git a/src/mame/video/tatsumi.cpp b/src/mame/video/tatsumi.cpp index 09abc3408ca..a252dbd1597 100644 --- a/src/mame/video/tatsumi.cpp +++ b/src/mame/video/tatsumi.cpp @@ -5,75 +5,11 @@ #include "screen.h" -/******************************************************************************/ - -READ16_MEMBER(tatsumi_state::tatsumi_sprite_control_r) -{ - return m_sprite_control_ram[offset]; -} - -WRITE16_MEMBER(tatsumi_state::tatsumi_sprite_control_w) -{ - COMBINE_DATA(&m_sprite_control_ram[offset]); - - /* 0xe0 is bank switch, others unknown */ -// if ((offset==0xe0 && data&0xefff) || offset!=0xe0) -// logerror("%s: Tatsumi TZB215 sprite control %04x %08x\n", m_maincpu->pc(), offset, data); -} - -/******************************************************************************/ - -WRITE16_MEMBER(apache3_state::apache3_road_z_w) -{ - m_apache3_road_z = data & 0xff; -} - -WRITE8_MEMBER(apache3_state::apache3_road_x_w) -{ - // Note: Double buffered. Yes, this is correct :) - m_apache3_road_x_ram[data] = offset; -} - -READ8_MEMBER(roundup5_state::gfxdata_r) -{ - if((m_control_word & 0x200) == 0x200) - { - offset += (m_control_word & 0x6000) << 2; - - return m_bg_gfxram[offset]; - } - - offset+=((m_control_word&0x0c00)>>10) * 0x8000; - return m_tx_gfxram[offset]; -} - -WRITE8_MEMBER(roundup5_state::gfxdata_w) -{ - if((m_control_word & 0x200) == 0x200) - { - offset += (m_control_word & 0x6000) << 2; - m_bg_gfxram[offset] = data; - return; - } - - offset+=((m_control_word&0x0c00)>>10) * 0x8000; - - if (offset>=0x18000 && data) - logerror("effective write to vram %06x %02x (control %04x)\n",offset,data,m_control_word); - - m_tx_gfxram[offset] = data; - - offset=offset%0x8000; - - m_gfxdecode->gfx(1)->mark_dirty(offset/8); -} - -WRITE16_MEMBER(tatsumi_state::text_w) -{ - uint16_t *videoram = m_videoram; - COMBINE_DATA(&videoram[offset]); - m_tx_layer->mark_tile_dirty(offset); -} +/********************************** + * + * Common routines + * + *********************************/ // TODO: move into device WRITE8_MEMBER(tatsumi_state::hd6445_crt_w) @@ -105,130 +41,54 @@ WRITE8_MEMBER(tatsumi_state::hd6445_crt_w) } } -/********************************************************************/ - -TILE_GET_INFO_MEMBER(tatsumi_state::get_text_tile_info) +READ16_MEMBER(tatsumi_state::tatsumi_sprite_control_r) { - int tile = m_videoram[tile_index]; - SET_TILE_INFO_MEMBER(1, - tile & 0xfff, - tile >> 12, - 0); + return m_sprite_control_ram[offset]; } -template -TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_bigfight) +WRITE16_MEMBER(tatsumi_state::tatsumi_sprite_control_w) { - int tile=m_cyclwarr_videoram[Bank][(tile_index+0x400)&0x7fff]; - int bank = (m_bigfight_a40000[0] >> (((tile&0xc00)>>10)*4))&0xf; - SET_TILE_INFO_MEMBER(1,(tile&0x3ff)|(bank<<10),(tile>>12)&0xf,0); - tileinfo.mask_data = &m_mask[((tile&0x3ff)|(bank<<10))<<3]; -} + COMBINE_DATA(&m_sprite_control_ram[offset]); -template -TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_cyclwarr_road) -{ - int tile=m_cyclwarr_videoram[Bank][(tile_index+0x400)&0x7fff]; - int bank = (m_bigfight_a40000[0] >> (((tile&0xc00)>>10)*4))&0xf; - SET_TILE_INFO_MEMBER(1,(tile&0x3ff)|(bank<<10),((tile>>12)&0xf) | m_cyclwarr_color_bank,0); - // TODO: enables transparent pen on sideways - tileinfo.mask_data = &m_mask[((tile&0x3ff)|(bank<<10))<<3]; + /* 0xe0 is bank switch, others unknown */ +// if ((offset==0xe0 && data&0xefff) || offset!=0xe0) +// logerror("%s: Tatsumi TZB215 sprite control %04x %08x\n", m_maincpu->pc(), offset, data); } - -/********************************************************************/ - -void cyclwarr_state::tile_expand() +// apply shadowing to underlying layers +// TODO: it might mix up with the lower palette bank instead +void tatsumi_state::apply_shadow_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &shadow_bitmap) { - /* - Each tile (0x4000 of them) has a lookup table in ROM to build an individual 3-bit palette - from sets of 8 bit palettes! - */ - gfx_element *gx0 = m_gfxdecode->gfx(1); - m_mask.resize(gx0->elements() << 3,0); - uint8_t *srcdata, *dest; - - // allocate memory for the assembled data - srcdata = auto_alloc_array(machine(), uint8_t, gx0->elements() * gx0->width() * gx0->height()); - - // loop over elements - dest = srcdata; - for (int c = 0; c < gx0->elements(); c++) + for(int y=cliprect.min_y;yget_data(c); - - // loop over height - for (int y = 0; y < gx0->height(); y++) + for(int x=cliprect.min_x;xwidth(); x++) + uint8_t shadow = shadow_bitmap.pix8(y, x); + if(shadow) { - uint8_t pix = (*c0++ & 7); - uint8_t respix = m_cyclwarr_tileclut[(c << 3)|pix]; - *dest++ = respix; - // Transparent pixels are set by both the tile pixel data==0 AND colour palette & 7 == 0 - m_mask[(c << 3) | (y & 7)] |= ((pix&0x7)!=0 || ((pix&0x7)==0 && (respix&0x7)!=0)) ? (0x80 >> (x & 7)) : 0; + rgb_t shadow_pen = bitmap.pix32(y, x); + bitmap.pix32(y, x) = rgb_t(shadow_pen.r() >> 1,shadow_pen.g() >> 1, shadow_pen.b() >> 1); } - c0base += gx0->rowbytes(); } - } - - gx0->set_raw_layout(srcdata, gx0->width(), gx0->height(), gx0->elements(), 8 * gx0->width(), 8 * gx0->width() * gx0->height()); - gx0->set_granularity(256); -} - -/********************************************************************/ - -VIDEO_START_MEMBER(apache3_state,apache3) -{ - m_tx_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tatsumi_state::get_text_tile_info),this),TILEMAP_SCAN_ROWS,8,8,64,64); - m_shadow_pen_array = make_unique_clear(8192); - m_temp_bitmap.allocate(512, 512); - m_apache3_road_x_ram = std::make_unique(512); - - m_tx_layer->set_transparent_pen(0); -} - -VIDEO_START_MEMBER(roundup5_state,roundup5) -{ - m_tx_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tatsumi_state::get_text_tile_info),this),TILEMAP_SCAN_ROWS,8,8,128,64); - m_shadow_pen_array = make_unique_clear(8192); - m_tx_gfxram = std::make_unique(0x20000); - m_bg_gfxram = std::make_unique(0x20000); - - m_tx_layer->set_transparent_pen(0); - - m_gfxdecode->gfx(1)->set_source(m_tx_gfxram.get()); - - save_pointer(NAME(m_tx_gfxram.get()),0x20000); - save_pointer(NAME(m_bg_gfxram.get()),0x20000); + } } -VIDEO_START_MEMBER(cyclwarr_state,cyclwarr) +WRITE16_MEMBER(tatsumi_state::text_w) { - tile_expand(); - m_layer[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,64,512); - m_layer[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_cyclwarr_road<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); - m_layer[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,64,512); - m_layer[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,64,512); - - m_shadow_pen_array = make_unique_clear(8192); + uint16_t *videoram = m_videoram; + COMBINE_DATA(&videoram[offset]); + m_tx_layer->mark_tile_dirty(offset); } -VIDEO_START_MEMBER(cyclwarr_state,bigfight) +TILE_GET_INFO_MEMBER(tatsumi_state::get_text_tile_info) { - tile_expand(); - m_layer[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); - m_layer[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); - m_layer[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,128,256); - m_layer[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,128,256); - - m_shadow_pen_array = make_unique_clear(8192); + int tile = m_videoram[tile_index]; + SET_TILE_INFO_MEMBER(1, + tile & 0xfff, + tile >> 12, + 0); } -/********************************************************************/ - template inline void tatsumi_state::roundupt_drawgfxzoomrotate( _BitmapClass &dest_bmp, const rectangle &clip, gfx_element *gfx, uint32_t code,uint32_t color,int flipx,int flipy,uint32_t ssx,uint32_t ssy, @@ -679,6 +539,61 @@ void tatsumi_state::draw_sprites(_BitmapClass &bitmap, const rectangle &cliprect } } +/* + * Object palettes are build from a series of cluts stored in the object roms. + * + * We update 'Mame palettes' from the clut here in order to simplify the + * draw routines. We also note down any uses of the 'shadow' pen (index 255). + */ +void tatsumi_state::update_cluts(int fake_palette_offset, int object_base, int length) +{ + + int i; + const uint8_t* bank1 = m_rom_clut[0]; + const uint8_t* bank2 = m_rom_clut[1]; + for (i=0; iset_pen_color(fake_palette_offset+i+0,m_palette->pen_color(bank1[1]+object_base)); + m_shadow_pen_array[i+0]=(bank1[1]==255); + m_palette->set_pen_color(fake_palette_offset+i+1,m_palette->pen_color(bank1[0]+object_base)); + m_shadow_pen_array[i+1]=(bank1[0]==255); + m_palette->set_pen_color(fake_palette_offset+i+2,m_palette->pen_color(bank1[3]+object_base)); + m_shadow_pen_array[i+2]=(bank1[3]==255); + m_palette->set_pen_color(fake_palette_offset+i+3,m_palette->pen_color(bank1[2]+object_base)); + m_shadow_pen_array[i+3]=(bank1[2]==255); + + m_palette->set_pen_color(fake_palette_offset+i+4,m_palette->pen_color(bank2[1]+object_base)); + m_shadow_pen_array[i+4]=(bank2[1]==255); + m_palette->set_pen_color(fake_palette_offset+i+5,m_palette->pen_color(bank2[0]+object_base)); + m_shadow_pen_array[i+5]=(bank2[0]==255); + m_palette->set_pen_color(fake_palette_offset+i+6,m_palette->pen_color(bank2[3]+object_base)); + m_shadow_pen_array[i+6]=(bank2[3]==255); + m_palette->set_pen_color(fake_palette_offset+i+7,m_palette->pen_color(bank2[2]+object_base)); + m_shadow_pen_array[i+7]=(bank2[2]==255); + + bank1+=4; + bank2+=4; + } +} + + +/********************************** + * + * Apache 3 + * + *********************************/ + +WRITE16_MEMBER(apache3_state::apache3_road_z_w) +{ + m_apache3_road_z = data & 0xff; +} + +WRITE8_MEMBER(apache3_state::apache3_road_x_w) +{ + // Note: Double buffered. Yes, this is correct :) + m_apache3_road_x_ram[data] = offset; +} + void apache3_state::draw_sky(bitmap_rgb32 &bitmap,const rectangle &cliprect, int palette_base, int start_offset) { // all todo @@ -701,33 +616,181 @@ start_offset-=48; } } -void roundup5_state::draw_road(bitmap_rgb32 &bitmap, const rectangle &cliprect) +/* Draw the sky and ground, applying rotation (eventually). Experimental! */ +void apache3_state::draw_ground(bitmap_rgb32 &dst, const rectangle &cliprect) { -/* -0xf980 0x0008 0x8c80 0x4a00 - road right to below, width unknown (32 pixels guess) -0xfa80 0x0008 0x8c80 0x4a00 - road right to below, width unknown (32 pixels guess) - -0xfb80 0x0008 0x8c80 0x4a00 - road in middle of screen, width unknown (32 pixels guess) + if (0) + { + int x, y; -0xfc80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) -0xfd80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) -0xfe80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) -0xff80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) -0x0001 - road half/width above to left, (ie, xpos - 16) -0x0081 - road width to left as usual (xpos-16 from above, or 32 from above2) + uint16_t gva = 0x180; // TODO + uint8_t sky_val = m_apache3_rotate_ctrl[1] & 0xff; -0xfb0b 0x210b 0x8cf5 0x0dea - blue & left & right, with blue|----|----|----|----|blue -in this mode changing columns 2 & 3 have no apparent effect -0xfb0b 0x7b09 0x8cf5 0x0dea - as above, but scaled up - perhaps 18 pixels shifted (twice that overall size) -0xfb0b 0x6c07 0x8cf5 0x0dea - as above, but scaled up - perhaps 40 pixels shifted from above -0xfb0b 0xaa06 0x8cf5 0x0dea - as above, but scaled up - perhaps 16 pixels shifted from above -0xfb0b 0xb005 0x8cf5 0x0dea - as above, but scaled up - perhaps 38 pixels shifted from above + for (y = cliprect.min_y; y <= cliprect.max_y; ++y) + { + uint16_t rgdb = 0;//m_apache3_road_x_ram[gva & 0xff]; + uint16_t gha = 0xf60; // test + int ln = (((m_apache3_prom[gva & 0x7f] & 0x7f) + (m_apache3_road_z & 0x7f)) >> 5) & 3; -b21 diff is 1a6 -97b 20f -76c c2 -6aa fa -5b0 + if (gva & 0x100) + { + /* Sky */ + for (x = cliprect.min_x; x <= cliprect.max_x; ++x) + { + dst.pix32(y, x) = m_palette->pen(0x100 + (sky_val & 0x7f)); + + /* Update horizontal counter? */ + gha = (gha + 1) & 0xfff; + } + } + else + { + /* Ground */ + for (x = cliprect.min_x; x <= cliprect.max_x; ++x) + { + uint8_t colour; + uint16_t hval; + uint8_t pixels; + int pix_sel; + + hval = (rgdb + gha) & 0xfff; // Not quite + + if (hval & 0x800) + hval ^= 0x1ff; // TEST + //else + //hval = hval; + + pixels = m_apache3_g_ram[(((gva & 0xff) << 7) | ((hval >> 2) & 0x7f))]; + pix_sel = hval & 3; + + colour = (pixels >> (pix_sel << 1)) & 3; + colour = (BIT(hval, 11) << 4) | (colour << 2) | ln; + + /* Draw the pixel */ + dst.pix32(y, x) = m_palette->pen(0x200 + colour); + + /* Update horizontal counter */ + gha = (gha + 1) & 0xfff; + } + } + + /* Update sky counter */ + sky_val++; + gva = (gva + 1) & 0x1ff; + } + } +} + + +VIDEO_START_MEMBER(apache3_state,apache3) +{ + m_tx_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tatsumi_state::get_text_tile_info),this),TILEMAP_SCAN_ROWS,8,8,64,64); + m_shadow_pen_array = make_unique_clear(8192); + m_temp_bitmap.allocate(512, 512); + m_apache3_road_x_ram = std::make_unique(512); + + m_tx_layer->set_transparent_pen(0); +} + +uint32_t apache3_state::screen_update_apache3(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + update_cluts(1024, 0, 2048+2048); + + m_tx_layer->set_scrollx(0,24); + + bitmap.fill(m_palette->pen(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_sky(bitmap, cliprect, 256, m_apache3_rotate_ctrl[1]); + apply_shadow_bitmap(bitmap,cliprect,screen.priority()); +// draw_ground(bitmap, cliprect); + draw_sprites(bitmap,cliprect,0, (m_sprite_control_ram[0x20]&0x1000) ? 0x1000 : 0); + m_tx_layer->draw(screen, bitmap, cliprect, 0,0); + return 0; +} + +/********************************** + * + * Round Up 5 + * + *********************************/ + +READ8_MEMBER(roundup5_state::gfxdata_r) +{ + if((m_control_word & 0x200) == 0x200) + { + offset += (m_control_word & 0x6000) << 2; + + return m_bg_gfxram[offset]; + } + + offset+=((m_control_word&0x0c00)>>10) * 0x8000; + return m_tx_gfxram[offset]; +} + +WRITE8_MEMBER(roundup5_state::gfxdata_w) +{ + if((m_control_word & 0x200) == 0x200) + { + offset += (m_control_word & 0x6000) << 2; + m_bg_gfxram[offset] = data; + return; + } + + offset+=((m_control_word&0x0c00)>>10) * 0x8000; + + if (offset>=0x18000 && data) + logerror("effective write to vram %06x %02x (control %04x)\n",offset,data,m_control_word); + + m_tx_gfxram[offset] = data; + + offset=offset%0x8000; + + m_gfxdecode->gfx(1)->mark_dirty(offset/8); +} + +VIDEO_START_MEMBER(roundup5_state,roundup5) +{ + m_tx_layer = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(tatsumi_state::get_text_tile_info),this),TILEMAP_SCAN_ROWS,8,8,128,64); + m_shadow_pen_array = make_unique_clear(8192); + m_tx_gfxram = std::make_unique(0x20000); + m_bg_gfxram = std::make_unique(0x20000); + + m_tx_layer->set_transparent_pen(0); + + m_gfxdecode->gfx(1)->set_source(m_tx_gfxram.get()); + + save_pointer(NAME(m_tx_gfxram.get()),0x20000); + save_pointer(NAME(m_bg_gfxram.get()),0x20000); +} + +void roundup5_state::draw_road(bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ +/* +0xf980 0x0008 0x8c80 0x4a00 - road right to below, width unknown (32 pixels guess) +0xfa80 0x0008 0x8c80 0x4a00 - road right to below, width unknown (32 pixels guess) + +0xfb80 0x0008 0x8c80 0x4a00 - road in middle of screen, width unknown (32 pixels guess) + +0xfc80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) +0xfd80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) +0xfe80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) +0xff80 0x0008 0x8c80 0x4a00 - road width above to left, same width as above (ie, xpos - 32) +0x0001 - road half/width above to left, (ie, xpos - 16) +0x0081 - road width to left as usual (xpos-16 from above, or 32 from above2) + +0xfb0b 0x210b 0x8cf5 0x0dea - blue & left & right, with blue|----|----|----|----|blue +in this mode changing columns 2 & 3 have no apparent effect +0xfb0b 0x7b09 0x8cf5 0x0dea - as above, but scaled up - perhaps 18 pixels shifted (twice that overall size) +0xfb0b 0x6c07 0x8cf5 0x0dea - as above, but scaled up - perhaps 40 pixels shifted from above +0xfb0b 0xaa06 0x8cf5 0x0dea - as above, but scaled up - perhaps 16 pixels shifted from above +0xfb0b 0xb005 0x8cf5 0x0dea - as above, but scaled up - perhaps 38 pixels shifted from above + +b21 diff is 1a6 +97b 20f +76c c2 +6aa fa +5b0 0x0000 0x0008 0xxxxx 0xxxx - line starting at 0 for 128 pixels - 1 to 1 with road pixel data @@ -778,6 +841,8 @@ pos is 11.5 fixed point for (/*y=0*/; y>8)&0xf; @@ -915,140 +980,6 @@ offset is from last pixel of first road segment? } } -void tatsumi_state::update_cluts(int fake_palette_offset, int object_base, int length) -{ - /* Object palettes are build from a series of cluts stored in the object roms. - - We update 'Mame palettes' from the clut here in order to simplify the - draw routines. We also note down any uses of the 'shadow' pen (index 255). - */ - int i; - const uint8_t* bank1=m_rom_clut[0]; - const uint8_t* bank2=m_rom_clut[1]; - for (i=0; iset_pen_color(fake_palette_offset+i+0,m_palette->pen_color(bank1[1]+object_base)); - m_shadow_pen_array[i+0]=(bank1[1]==255); - m_palette->set_pen_color(fake_palette_offset+i+1,m_palette->pen_color(bank1[0]+object_base)); - m_shadow_pen_array[i+1]=(bank1[0]==255); - m_palette->set_pen_color(fake_palette_offset+i+2,m_palette->pen_color(bank1[3]+object_base)); - m_shadow_pen_array[i+2]=(bank1[3]==255); - m_palette->set_pen_color(fake_palette_offset+i+3,m_palette->pen_color(bank1[2]+object_base)); - m_shadow_pen_array[i+3]=(bank1[2]==255); - - m_palette->set_pen_color(fake_palette_offset+i+4,m_palette->pen_color(bank2[1]+object_base)); - m_shadow_pen_array[i+4]=(bank2[1]==255); - m_palette->set_pen_color(fake_palette_offset+i+5,m_palette->pen_color(bank2[0]+object_base)); - m_shadow_pen_array[i+5]=(bank2[0]==255); - m_palette->set_pen_color(fake_palette_offset+i+6,m_palette->pen_color(bank2[3]+object_base)); - m_shadow_pen_array[i+6]=(bank2[3]==255); - m_palette->set_pen_color(fake_palette_offset+i+7,m_palette->pen_color(bank2[2]+object_base)); - m_shadow_pen_array[i+7]=(bank2[2]==255); - - bank1+=4; - bank2+=4; - } -} - -/**********************************************************************/ - -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, int xscroll_offset, int yscroll_offset, bool is_road, bool is_opaque) -{ - rectangle clip; - clip.min_x = cliprect.min_x; - clip.max_x = cliprect.max_x; - // TODO: both enabled when this occurs - bool rowscroll_enable = (scrollx[0] & 0x1000) == 0; - bool colscroll_enable = (scrollx[0] & 0x2000) == 0; - - for (int y=cliprect.min_y; y<=cliprect.max_y; y++) - { - clip.min_y = clip.max_y = y; - int y_base = rowscroll_enable ? y : 0; - int x_base = colscroll_enable ? y : 0; - int src_y = (scrolly[y_base] & 0xfff) + yscroll_offset; - int src_x = (scrollx[x_base] & 0xfff) + xscroll_offset; - - // special handling for cycle warriors road: it reads in scrolly table bits 15-13 an - // additional tile color bank and per scanline. - if(is_road == true && scrolly[y_base] & 0x8000) - { - m_cyclwarr_color_bank = (scrolly[y_base] >> 13) & 3; - src->mark_all_dirty(); - // TODO: road sidelines attempt, still not right (cuts off cyan color at intro and farmost road lines) - //if(m_cyclwarr_color_bank) - // is_opaque = true; - } - - src->set_scrollx(0,src_x); - src->set_scrolly(0,src_y); - src->draw(screen, bitmap, clip, is_opaque ? TILEMAP_DRAW_OPAQUE : 0, 0); - } -} - -/* Draw the sky and ground, applying rotation (eventually). Experimental! */ -void apache3_state::draw_ground(bitmap_rgb32 &dst, const rectangle &cliprect) -{ -if (0) { - int x, y; - - uint16_t gva = 0x180; // TODO - uint8_t sky_val = m_apache3_rotate_ctrl[1] & 0xff; - - for (y = cliprect.min_y; y <= cliprect.max_y; ++y) - { - uint16_t rgdb = 0;//m_apache3_road_x_ram[gva & 0xff]; - uint16_t gha = 0xf60; // test - int ln = (((m_apache3_prom[gva & 0x7f] & 0x7f) + (m_apache3_road_z & 0x7f)) >> 5) & 3; - - if (gva & 0x100) - { - /* Sky */ - for (x = cliprect.min_x; x <= cliprect.max_x; ++x) - { - dst.pix32(y, x) = m_palette->pen(0x100 + (sky_val & 0x7f)); - - /* Update horizontal counter? */ - gha = (gha + 1) & 0xfff; - } - } - else - { - /* Ground */ - for (x = cliprect.min_x; x <= cliprect.max_x; ++x) - { - uint8_t colour; - uint16_t hval; - uint8_t pixels; - int pix_sel; - - hval = (rgdb + gha) & 0xfff; // Not quite - - if (hval & 0x800) - hval ^= 0x1ff; // TEST - //else - //hval = hval; - - pixels = m_apache3_g_ram[(((gva & 0xff) << 7) | ((hval >> 2) & 0x7f))]; - pix_sel = hval & 3; - - colour = (pixels >> (pix_sel << 1)) & 3; - colour = (BIT(hval, 11) << 4) | (colour << 2) | ln; - - /* Draw the pixel */ - dst.pix32(y, x) = m_palette->pen(0x200 + colour); - - /* Update horizontal counter */ - gha = (gha + 1) & 0xfff; - } - } - - /* Update sky counter */ - sky_val++; - gva = (gva + 1) & 0x1ff; - } -} -} - // background layer landscape for Round Up 5 // two bitmap layers, back layer is 512 x 128, the other one is 512 x 64 // it's safe to assume that three monitor version will have a different arrangement here ... @@ -1089,25 +1020,6 @@ void roundup5_state::draw_landscape(bitmap_rgb32 &bitmap, const rectangle &clipr } -/**********************************************************************/ - -uint32_t apache3_state::screen_update_apache3(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) -{ - update_cluts(1024, 0, 2048+2048); - - m_tx_layer->set_scrollx(0,24); - - bitmap.fill(m_palette->pen(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_sky(bitmap, cliprect, 256, m_apache3_rotate_ctrl[1]); - apply_shadow_bitmap(bitmap,cliprect,screen.priority()); -// draw_ground(bitmap, cliprect); - draw_sprites(bitmap,cliprect,0, (m_sprite_control_ram[0x20]&0x1000) ? 0x1000 : 0); - m_tx_layer->draw(screen, bitmap, cliprect, 0,0); - return 0; -} - uint32_t roundup5_state::screen_update_roundup5(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) { int tx_start_addr; @@ -1140,57 +1052,177 @@ uint32_t roundup5_state::screen_update_roundup5(screen_device &screen, bitmap_rg return 0; } -void tatsumi_state::apply_shadow_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, bitmap_ind8 &shadow_bitmap) +/********************************** + * + * Cycle Warriors / Big Fight + * + *********************************/ + +// TODO: color offset is a mystery, it's certainly not masked with 0xf +// cfr. Big Fight fade in/out effects or CRT test +template +TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_bigfight) { - for(int y=cliprect.min_y;y> (((tile&0xc00)>>10)*4))&0xf; + uint16_t tileno = (tile&0x3ff)|(bank<<10); + + SET_TILE_INFO_MEMBER(1, + tileno, + (tile >> 12) & 0xf, + 0); + + // bit 15: tile appears in front of sprites + tileinfo.category = (tile >> 15) & 1; + tileinfo.mask_data = &m_mask[tileno<<3]; +} + +// same as above but additionally apply per-scanline color banking +// TODO: split for simplicity, need to merge with above +template +TILE_GET_INFO_MEMBER(cyclwarr_state::get_tile_info_cyclwarr_road) +{ + int tile = m_cyclwarr_videoram[Bank][tile_index&0x7fff]; + int bank = (m_bigfight_a40000[0] >> (((tile&0xc00)>>10)*4))&0xf; + uint16_t tileno = (tile&0x3ff)|(bank<<10); + + SET_TILE_INFO_MEMBER(1, + tileno, + ((tile>>12) & 0xf) | m_road_color_bank, + 0); + + tileinfo.category = (tile >> 15) & 1; + // TODO: enables transparent pen on sideways + tileinfo.mask_data = &m_mask[((tile&0x3ff)|(bank<<10))<<3]; +} + +void cyclwarr_state::tile_expand() +{ + /* + Each tile (0x4000 of them) has a lookup table in ROM to build an individual 3-bit palette + from sets of 8 bit palettes! + */ + gfx_element *gx0 = m_gfxdecode->gfx(1); + m_mask.resize(gx0->elements() << 3,0); + uint8_t *srcdata, *dest; + + // allocate memory for the assembled data + srcdata = auto_alloc_array(machine(), uint8_t, gx0->elements() * gx0->width() * gx0->height()); + + // loop over elements + dest = srcdata; + for (int c = 0; c < gx0->elements(); c++) { - for(int x=cliprect.min_x;xget_data(c); + + // loop over height + for (int y = 0; y < gx0->height(); y++) { - uint8_t shadow = shadow_bitmap.pix8(y, x); - if(shadow) + const uint8_t *c0 = c0base; + + for (int x = 0; x < gx0->width(); x++) { - rgb_t shadow_pen = bitmap.pix32(y, x); - bitmap.pix32(y, x) = rgb_t(shadow_pen.r() >> 1,shadow_pen.g() >> 1, shadow_pen.b() >> 1); + uint8_t pix = (*c0++ & 7); + uint8_t respix = m_cyclwarr_tileclut[(c << 3)|pix]; + *dest++ = respix; + // Transparent pixels are set by both the tile pixel data==0 AND colour palette & 7 == 0 + m_mask[(c << 3) | (y & 7)] |= ((pix&0x7)!=0 || ((pix&0x7)==0 && (respix&0x7)!=0)) ? (0x80 >> (x & 7)) : 0; } + c0base += gx0->rowbytes(); } - } + } + + gx0->set_raw_layout(srcdata, gx0->width(), gx0->height(), gx0->elements(), 8 * gx0->width(), 8 * gx0->width() * gx0->height()); + gx0->set_granularity(256); } -uint32_t cyclwarr_state::screen_update_cyclwarr(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) + +VIDEO_START_MEMBER(cyclwarr_state,cyclwarr) { - m_bigfight_bank=m_bigfight_a40000[0]; - if (m_bigfight_bank!=m_bigfight_last_bank) + tile_expand(); + m_layer[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,64,512); + m_layer[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_cyclwarr_road<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); + m_layer[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,64,512); + m_layer[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,64,512); + + m_shadow_pen_array = make_unique_clear(8192); + + m_layer[3]->set_scrolldx(-8,-8); + m_layer[2]->set_scrolldx(-8,-8); + m_layer[1]->set_scrolldx(-8,-8); + m_layer[0]->set_scrolldx(-0x10,-0x10); + m_layer1_can_be_road = true; +} + +VIDEO_START_MEMBER(cyclwarr_state,bigfight) +{ + tile_expand(); + m_layer[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); + m_layer[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<0>),this),TILEMAP_SCAN_ROWS,8,8,128,256); + m_layer[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,128,256); + m_layer[3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(cyclwarr_state::get_tile_info_bigfight<1>),this),TILEMAP_SCAN_ROWS,8,8,128,256); + + m_shadow_pen_array = make_unique_clear(8192); + + m_layer[3]->set_scrolldx(-8,-8); + m_layer[2]->set_scrolldx(-8,-8); + m_layer[1]->set_scrolldx(-8,-8); + m_layer[0]->set_scrolldx(-0x10,-0x10); + 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, bool is_opaque, int hi_priority) +{ + rectangle clip; + clip.min_x = cliprect.min_x; + clip.max_x = cliprect.max_x; + // TODO: both always enabled when this occurs + bool rowscroll_enable = (scrollx[0] & 0x1000) == 0; + bool colscroll_enable = (scrollx[0] & 0x2000) == 0; + + for (int y=cliprect.min_y; y<=cliprect.max_y; y++) { - for (int i = 0; i < 4; i++) + clip.min_y = clip.max_y = y; + int y_base = rowscroll_enable ? y : 0; + int x_base = colscroll_enable ? y : 0; + int src_y = (scrolly[y_base] & 0xfff); + int src_x = (scrollx[x_base] & 0x7ff); + + // special handling for cycle warriors road: it reads in scrolly table bits 15-13 an + // additional tile color bank and per scanline. + if(is_road == true) { - m_layer[i]->mark_all_dirty(); + if(scrolly[y_base] & 0x8000) + m_road_color_bank = (scrolly[y_base] >> 13) & 3; + else + m_road_color_bank = 0; + + if(m_road_color_bank != m_prev_road_bank) + { + m_prev_road_bank = m_road_color_bank; + src->mark_all_dirty(); + } + // TODO: road sidelines attempt, still not right (cuts off cyan color at intro and farmost road lines) + //if(m_road_color_bank) + // is_opaque = true; } - m_bigfight_last_bank=m_bigfight_bank; - } - update_cluts(8192, 4096, 8192); - - bitmap.fill(m_palette->pen(0), cliprect); - #ifdef UNUSED_FUNCTION - popmessage("%04x %04x|%04x %04x|%04x %04x|%04x %04x",m_cyclwarr_videoram[1][0x000],m_cyclwarr_videoram[1][0x100] - ,m_cyclwarr_videoram[1][0x200],m_cyclwarr_videoram[1][0x300] - ,m_cyclwarr_videoram[0][0x000],m_cyclwarr_videoram[0][0x100] - ,m_cyclwarr_videoram[0][0x200],m_cyclwarr_videoram[0][0x300]); - #endif - - screen.priority().fill(0, cliprect); - draw_sprites(screen.priority(),cliprect,1,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); // Alpha pass only - draw_bg(screen, bitmap, cliprect, m_layer[3], &m_cyclwarr_videoram[1][0x000], &m_cyclwarr_videoram[1][0x100], 8, -0x80, false, true); - draw_bg(screen, bitmap, cliprect, m_layer[2], &m_cyclwarr_videoram[1][0x200], &m_cyclwarr_videoram[1][0x300], 8, -0x80, false, false); - draw_bg(screen, bitmap, cliprect, m_layer[1], &m_cyclwarr_videoram[0][0x000], &m_cyclwarr_videoram[0][0x100], 8, -0x40, true, false); - apply_shadow_bitmap(bitmap,cliprect,screen.priority()); - draw_sprites(bitmap,cliprect,0,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); - draw_bg(screen, bitmap, cliprect, m_layer[0], &m_cyclwarr_videoram[0][0x200], &m_cyclwarr_videoram[0][0x300], 0x10, -0x80, false, false); + src->set_scrollx(0,src_x); + src->set_scrolly(0,src_y); + src->draw(screen, bitmap, clip, (is_opaque ? TILEMAP_DRAW_OPAQUE : 0) | TILEMAP_DRAW_CATEGORY(hi_priority), 0); + } +} - return 0; +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 == 0, hi_priority); + draw_bg(screen, bitmap, cliprect, m_layer[2], &m_cyclwarr_videoram[1][0x200], &m_cyclwarr_videoram[1][0x300], false, 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, false, hi_priority); + draw_bg(screen, bitmap, cliprect, m_layer[0], &m_cyclwarr_videoram[0][0x200], &m_cyclwarr_videoram[0][0x300], false, false,hi_priority); } -uint32_t cyclwarr_state::screen_update_bigfight(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) { m_bigfight_bank=m_bigfight_a40000[0]; if (m_bigfight_bank!=m_bigfight_last_bank) @@ -1202,24 +1234,21 @@ uint32_t cyclwarr_state::screen_update_bigfight(screen_device &screen, bitmap_rg m_bigfight_last_bank=m_bigfight_bank; } update_cluts(8192, 4096, 8192); + + bitmap.fill(m_palette->pen(0), cliprect); #ifdef UNUSED_FUNCTION popmessage("%04x %04x|%04x %04x|%04x %04x|%04x %04x",m_cyclwarr_videoram[1][0x000],m_cyclwarr_videoram[1][0x100] ,m_cyclwarr_videoram[1][0x200],m_cyclwarr_videoram[1][0x300] ,m_cyclwarr_videoram[0][0x000],m_cyclwarr_videoram[0][0x100] ,m_cyclwarr_videoram[0][0x200],m_cyclwarr_videoram[0][0x300]); - #endif - - bitmap.fill(m_palette->pen(0), cliprect); - + #endif + screen.priority().fill(0, cliprect); draw_sprites(screen.priority(),cliprect,1,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); // Alpha pass only - draw_bg(screen, bitmap, cliprect, m_layer[3], &m_cyclwarr_videoram[1][0x000], &m_cyclwarr_videoram[1][0x100], 8, -0x40, false, true); - draw_bg(screen, bitmap, cliprect, m_layer[2], &m_cyclwarr_videoram[1][0x200], &m_cyclwarr_videoram[1][0x300], 8, -0x40, false, false); - draw_bg(screen, bitmap, cliprect, m_layer[1], &m_cyclwarr_videoram[0][0x000], &m_cyclwarr_videoram[0][0x100], 8, -0x40, false, false); + draw_bg_layers(screen, bitmap, cliprect, 0); apply_shadow_bitmap(bitmap,cliprect,screen.priority()); draw_sprites(bitmap,cliprect,0,(m_sprite_control_ram[0xe0]&0x1000) ? 0x1000 : 0); - draw_bg(screen, bitmap, cliprect, m_layer[0], &m_cyclwarr_videoram[0][0x200], &m_cyclwarr_videoram[0][0x300], 0x10, -0x40, false, false); - + draw_bg_layers(screen, bitmap, cliprect, 1); return 0; } -- cgit v1.2.3