diff options
Diffstat (limited to 'src/mame/olympia/portrait_v.cpp')
-rw-r--r-- | src/mame/olympia/portrait_v.cpp | 208 |
1 files changed, 127 insertions, 81 deletions
diff --git a/src/mame/olympia/portrait_v.cpp b/src/mame/olympia/portrait_v.cpp index 0ae1b40d2b7..a5ae385866d 100644 --- a/src/mame/olympia/portrait_v.cpp +++ b/src/mame/olympia/portrait_v.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Steve Ellenoff, Pierpaolo Prazzoli +// copyright-holders:Steve Ellenoff, Pierpaolo Prazzoli, Angelo Salese /*************************************************************************** Portraits @@ -23,6 +23,10 @@ void portrait_state::fgvideo_write(offs_t offset, uint8_t data) m_fgvideoram[offset] = data; } +// NB: undisplayed areas gets filled at POST but never really used +// $8x36-$8x3f / $8x76-$8x7f / $8xb6-$8xbf / $8xf6-$8xff +// given that tilemap doesn't really cope well with live editing your best bet in debugging this is +// potentially to subscribe these unused areas to a mark_all_dirty() fn. inline void portrait_state::get_tile_info( tile_data &tileinfo, int tile_index, const uint8_t *source ) { int attr = source[tile_index*2+0]; @@ -30,26 +34,25 @@ inline void portrait_state::get_tile_info( tile_data &tileinfo, int tile_index, int flags = 0; int color = 0; - /* or 0x10 ? */ + // TODO: always set with bit 4 if( attr & 0x20 ) flags = TILE_FLIPY; - switch( attr & 7 ) - { - case 1: - tilenum += 0x200; - break; - case 3: - tilenum += 0x300; - break; - case 5: - tilenum += 0x100; - break; - } + if (attr & 1) + tilenum += 0x200; + if (attr & 2) + tilenum += 0x100; + if (attr & 4) + tilenum ^= 0x300; + // TODO: is the wild arrangement above related to how color upper banks should work? + // cfr. trees in stage 4 leaving holes against the other layer + + // TODO: kludgy + // at worst this is modified at mixing time, outputting sprite color for the status bar. if (tilenum<0x100) - color = ((tilenum&0xff)>>1)+0x00; + color = ((tilenum&0xfe) >> 1) + 0x00; else - color = ((tilenum&0xff)>>1)+0x80; + color = ((tilenum&0xfe) >> 1) + 0x80; tileinfo.set(0, tilenum, color, flags ); } @@ -74,37 +77,68 @@ void portrait_state::video_start() save_item(NAME(m_scroll)); } +/* tileattr rom + this appears to be divided into 2 0x400 banks -void portrait_state::portrait_palette(palette_device &palette) const -{ - uint8_t const *const color_prom = memregion("proms")->base(); + 0x000 - 0x3ff relates to tiles 0x000-0x0ff -/* - for (int i = 0; i < 0x40; i++) - { - int const data = color_prom[i]; + 0x400 - 0x7ff relates to tiles 0x100-0x1ff, 0x200-0x2ff, and 0x300-0x3ff - int const r = (data >> 0) & 0x7; - int const g = (data >> 3) & 0x3; - int const b = (data >> 5) & 0x7; + every 2 tiles are somehow related to 8 bytes in the data + + so tiles 0x00 and 0x01 use bytes 0x000-0x007 + 0x02 0x008 + 0x04 0x010 + 0x06 0x018 + 0x08 0x020 + 0x0a 0x028 + 0x0c 0x030 + 0x0e 0x038 + 0x10 0x040 + ....... + 0xfe and 0xff use bytes 0x3f8-0x3ff + etc. + + it's probably some kind of lookup table for the colours (6bpp = 8 colours, maybe every 2 tiles share the same 8 colours) + I guess either the bank (0/1) can be selected, or bank 0 is hardcoded to tiles 0x000-0x0ff (because tilemaps can use + these tiles too, so it's not a case of it being a sprite/tilemap lookup split) + + anyway.. this is why the portraits logo is broken across 3 areas (0x1f2, 0x2f2, 0x3f2) so that they can share the same + attributes from this rom - palette.set_indirect_color(i, rgb_t(pal3bit(r), pal2bit(g), pal3bit(b))); - } */ +void portrait_state::portrait_palette(palette_device &palette) const +{ + uint8_t const *const color_prom = memregion("proms")->base(); for (int i = 0; i < 0x20; i++) { int const data = (color_prom[i + 0] << 0) | (color_prom[i + 0x20] << 8); - int const r = (data >> 0) & 0x1f; - int const g = (data >> 5) & 0x1f; - int const b = (data >> 10) & 0x1f; - - palette.set_indirect_color(i, rgb_t(pal5bit(r), pal5bit(g), pal5bit(b))); - - // ?? the lookup seems to reference 0x3f colours, unless 1 bit is priority or similar? - palette.set_indirect_color(i + 0x20, rgb_t(pal5bit(r >> 1), pal5bit(g >> 1), pal5bit(b >> 1))); + // TODO: experimental workbench, not using pal*bit intentionally. + // 13 valid bits: + // [+0x00] bit 0-3, bit 6-4 + // [+0x20] bit 0-2, bit 7-5 + // Only bit 0-3 seems to have a valid color ramp, is the rest actually bit mixed? + + int ii = (data >> 0) & 0x0f; + //int b = ((data >> 4) & 0x7) * ii; + //int r = ((data >> 8) & 0x7) * ii; + //int g = ((data >> 13) & 0x7) * ii; + int r = ii * 0x11; + int g = ii * 0x11; + int b = ii * 0x11; + + palette.set_indirect_color(i, rgb_t(r, g, b)); + + ii = (data >> 1) & 0x0f; + r = ii * 0x11; + g = ii * 0x11; + b = ii * 0x11; + + // ?? the lookup seems to reference 0x3f colours, unless 1 bit is something else (priority?) + palette.set_indirect_color(i + 0x20, rgb_t(r, g, b)); } uint8_t const *const lookup = memregion("tileattr")->base(); @@ -115,62 +149,70 @@ void portrait_state::portrait_palette(palette_device &palette) const } } - -void portrait_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect) +/* + * [2] + * x--- ---- priority? + * -x-- ---- more priority? + * \- eagle sprite in stage 4 sets this only, + * drawing should really go above the fg layer mountains + * (missing tile category?) + * --x- ---- flipy + * ---x ---- ? + * ---- x--- msb Y position? + * ---- -x-- msb X position? + */ +void portrait_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u8 priority) { uint8_t *source = m_spriteram; uint8_t *finish = source + 0x200; - while( source < finish ) + // TODO: is anything beyond byte [3] really just work RAM buffer? + for( ; source < finish; source += 0x10 ) { - int sy = source[0]; - int sx = source[1]; - int attr = source[2]; - /* xx-x---- ? - * --x----- flipy - * ----x--- msb source[0] - * -----x-- msb source[1] - */ - int tilenum = source[3]; - - int color = ((tilenum&0xff)>>1)+0x00; + u8 attr = source[2]; + if (BIT(attr, 7) != priority) + continue; + u16 sy = source[0]; + u16 sx = source[1]; + u8 tilenum = source[3]; - int fy = attr & 0x20; + // TODO: may be given by source[4] and/or source[5] instead + u8 color = ((tilenum&0xff)>>1)+0x00; - if(attr & 0x04) sx |= 0x100; + int fy = BIT(attr, 5); - if(attr & 0x08) sy |= 0x100; + if (BIT(attr, 2)) sx |= 0x100; + if (BIT(attr, 3)) sy |= 0x100; sx += (source - m_spriteram) - 8; sx &= 0x1ff; - sy = (512 - 64) - sy; - - /* wrong! */ - switch( attr & 0xc0 ) - { - case 0: - break; - - case 0x40: - sy -= m_scroll; - break; - - case 0x80: - sy -= m_scroll; - break; - - case 0xc0: - break; - - } - - m_gfxdecode->gfx(0)->transpen(bitmap,cliprect, - tilenum,color, - 0,fy, - sx,sy,7); - - source += 0x10; + // TODO: confirm Y calculation + // it expects to follow up whatever is the current scroll value (cfr. monkeys climbing trees in stage 1) + // but then there are various misc sprites that breaks this rule. Examples are: + // - player photo flash; + // - death animation sprites; + // - capturing photo frame in gameplay; + // PC=0x2828 is where all of these odd sprites happens, where: + // HL=ROM pointer for destination sprite pointer, IY=sprite pointer source + // where they copy the origin of the given sprite, read scroll buffer $9235-36 then apply offset, + // with [2] bits 7-6 set high and bits 5-4 copied from the source sprite. + // Note that this will break elsewhere by logically using any of the [2] bits, + // arguably SW does a very limited use to pinpoint what's the actual scroll disable condition, + // it just implicitly don't setup [4] to [7] ... + if ((source[5] & 0xf) == 0) + sy = (511 - 16) - sy; + else + sy = ((511 - m_scroll) - 16) - sy; + + sy &= 0x1ff; + + m_gfxdecode->gfx(0)->transpen( + bitmap, cliprect, + tilenum, color, + 0, fy, + sx, sy, + 7); } } @@ -180,19 +222,23 @@ uint32_t portrait_state::screen_update(screen_device &screen, bitmap_ind16 &bitm cliprect_scroll = cliprect_no_scroll = cliprect; + // TODO: make clipping areas more readable cliprect_no_scroll.min_x = cliprect_no_scroll.max_x - 111; cliprect_scroll.max_x = cliprect_scroll.min_x + 319; + // status bar m_background->set_scrolly(0, 0); m_foreground->set_scrolly(0, 0); m_background->draw(screen, bitmap, cliprect_no_scroll, 0, 0); m_foreground->draw(screen, bitmap, cliprect_no_scroll, 0, 0); + // playfield m_background->set_scrolly(0, m_scroll); m_foreground->set_scrolly(0, m_scroll); m_background->draw(screen, bitmap, cliprect_scroll, 0, 0); + draw_sprites(bitmap, cliprect_scroll, 0); m_foreground->draw(screen, bitmap, cliprect_scroll, 0, 0); + draw_sprites(bitmap, cliprect_scroll, 1); - draw_sprites(bitmap,cliprect); return 0; } |