mirror of
https://github.com/holub/mame
synced 2025-07-01 08:18:59 +03:00
snk/hng64_sprite.ipp, snk/hng64_v.cpp: Improved Hyper Neo Geo 64 sprite drawing. (#10914)
* Render sprites to intermediate buffer buffer and blend when mixing (fixes sprite/sprite priorities). * Implemented mesh/checkerboard fake transparency (previously sprites using this were skipped). * Improved precision of sprite scaling (fixes gaps and smoothness of scale in many places). * Improved floor layer rendering for buriki and fatfurwa. * Added preliminary sprite mosaic effect support.
This commit is contained in:
parent
9028bdba54
commit
ca235063b4
@ -2141,6 +2141,13 @@ TIMER_CALLBACK_MEMBER(hng64_state::comhack_callback)
|
||||
// different network IDs give different default colours for the cars in roadedge
|
||||
uint8_t network_id = 0x01;
|
||||
|
||||
// this fixes the stuck scroller text in the xrally intro (largest pink text) but prevents the inputs from working.
|
||||
// It's probably trying to sync the scroller with another unit? however the original machines can run as singles
|
||||
// if you loop some of the pins on the network connector back, so maybe MAME is just confused about the mode it's
|
||||
// running in.
|
||||
// network_id |= 0x08;
|
||||
|
||||
|
||||
m_comhack[0] = m_comhack[0] | network_id;
|
||||
}
|
||||
|
||||
@ -2582,7 +2589,8 @@ void hng64_state::hng64_fight(machine_config &config)
|
||||
ROM_REGION( 0x100, "eeprom", 0 ) /* EEPROMs on the I/O boards, mostly empty, currently not used by the emulation */ \
|
||||
ROM_LOAD( "lvs-ioj-br9020f.u2", 0x000, 0x100, CRC(78b7020d) SHA1(2b8549532ef5e1e8102dbe71af55fdfb27ccbba6) ) \
|
||||
ROM_LOAD( "lvs-igx-br9020f.u3", 0x000, 0x100, CRC(af9f4287) SHA1(6df0e35c77dbfee2fab7ff490dcd651db420e367) ) \
|
||||
ROM_LOAD( "lvs-jam-br9020f.u3", 0x000, 0x100, CRC(dabec5d2) SHA1(19c5be89c57387d6ea563b3dc55674d0692af98e) )
|
||||
ROM_LOAD( "lvs-jam-br9020f.u3", 0x000, 0x100, CRC(dabec5d2) SHA1(19c5be89c57387d6ea563b3dc55674d0692af98e) ) \
|
||||
ROM_DEFAULT_BIOS( "export" )
|
||||
|
||||
ROM_START( hng64 )
|
||||
/* BIOS */
|
||||
@ -2930,6 +2938,13 @@ ROM_START( fatfurwa )
|
||||
ROM_LOAD( "006sd02a.78", 0x0400000, 0x400000, CRC(f7f020c7) SHA1(b72fde4ff6384b80166a3cb67d31bf7afda750bc) )
|
||||
ROM_LOAD( "006sd03a.79", 0x0800000, 0x400000, CRC(1a678084) SHA1(f52efb6145102d289f332d8341d89a5d231ba003) )
|
||||
ROM_LOAD( "006sd04a.80", 0x0c00000, 0x400000, CRC(3c280a5c) SHA1(9d3fc78e18de45382878268db47ff9d9716f1505) )
|
||||
|
||||
/* this game does not initialize EEPROM automatically otherwise (each region requires different defaults) */
|
||||
ROM_REGION( 0x4000, "nvram", 0 )
|
||||
ROMX_LOAD( "default_nvram_japan", 0x00000, 0x4000, CRC(1f618d44) SHA1(c007c5f94b28b8c56c8c539d2f82336515c0ed84), ROM_BIOS(0) )
|
||||
ROMX_LOAD( "default_nvram_usa", 0x00000, 0x4000, CRC(f139f4a5) SHA1(6f7e2fc5d902c1499f3c55f9ca2ef7becc49103b), ROM_BIOS(1) )
|
||||
ROMX_LOAD( "default_nvram_others", 0x00000, 0x4000, CRC(bf1c3e4a) SHA1(454c6e5e505293bfdeb87d08e72420bba84c3b7b), ROM_BIOS(2) )
|
||||
ROMX_LOAD( "default_nvram_korea", 0x00000, 0x4000, CRC(e8fb68df) SHA1(3170e7465b93319c0550f35f8906b5bdc5332eec), ROM_BIOS(3) )
|
||||
ROM_END
|
||||
|
||||
|
||||
|
@ -271,7 +271,10 @@ private:
|
||||
|
||||
//uint32_t *q2 = nullptr;
|
||||
|
||||
std::vector< std::pair <int, uint32_t *> > m_spritelist;
|
||||
|
||||
bitmap_ind16 m_sprite_bitmap;
|
||||
bitmap_ind16 m_sprite_zbuffer;
|
||||
|
||||
|
||||
uint8_t m_screen_dis = 0U;
|
||||
|
||||
@ -433,7 +436,18 @@ private:
|
||||
|
||||
void clear3d();
|
||||
bool hng64_command3d(const uint16_t* packet);
|
||||
void draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
|
||||
void get_tile_details(bool chain, uint16_t spritenum, uint8_t xtile, uint8_t ytile, uint8_t xsize, uint8_t ysize, bool xflip, bool yflip, uint32_t& tileno, uint16_t& pal, uint8_t &gfxregion);
|
||||
void draw_sprites_buffer(screen_device &screen, const rectangle &cliprect);
|
||||
|
||||
void drawline(bitmap_ind16& dest, bitmap_ind16& destz, const rectangle& cliprect,
|
||||
gfx_element* gfx, uint32_t code, uint32_t color, int flipx, int flipy, int32_t destx, int32_t desty,
|
||||
int32_t dx, int32_t dy, uint32_t dstwidth, uint32_t dstheight, uint32_t trans_pen, uint32_t zval, bool zrev, bool blend, bool checkerboard, uint8_t mosaic, uint8_t &mosaic_count_x, int cury, const u8* srcdata, int32_t srcx, int32_t srcy_copy, uint32_t leftovers, int line, uint16_t &srcpix);
|
||||
|
||||
void zoom_transpen(bitmap_ind16 &dest, bitmap_ind16 &destz, const rectangle &cliprect,
|
||||
gfx_element *gfx, uint32_t code, uint32_t color, int flipx, int flipy, int32_t destx, int32_t desty,
|
||||
int32_t dx, int32_t dy, uint32_t dstwidth, uint32_t dstheight, uint32_t trans_pen, uint32_t zval, bool zrev, bool blend, bool checkerboard, uint8_t mosaic, uint8_t &mosaic_count_x, int line, uint16_t &srcpix);
|
||||
|
||||
void transition_control(bitmap_rgb32 &bitmap, const rectangle &cliprect);
|
||||
void setCameraTransformation(const uint16_t* packet);
|
||||
void setLighting(const uint16_t* packet);
|
||||
|
@ -7,25 +7,25 @@
|
||||
* Sprite Format
|
||||
* ------------------
|
||||
*
|
||||
* uint32_t | Bits | Use
|
||||
* offset | Bits | Use
|
||||
* | 3322 2222 2222 1111 1111 11 |
|
||||
* -------+-1098-7654-3210-9876-5432-1098-7654-3210-+----------------
|
||||
* 0 | yyyy yyyy yyyy yyyy xxxx xxxx xxxx xxxx | x/y position
|
||||
* 1 | YYYY YYYY YYYY YYYY XXXX XXXX XXXX XXXX | x/y zoom (*)
|
||||
* 2 | ---- -zzz zzzz zzzz ---- ---I cccc CCCC | Z-buffer value, 'Inline' chain flag, x/y chain
|
||||
* 2 | ---- Szzz zzzz zzzz ---- ---I cccc CCCC | S = set on CPU car markers above cars (in roadedge) z = Z-buffer value, i = 'Inline' chain flag, cC = x/y chain
|
||||
* 3 | ---- ---- pppp pppp ---- ---- ---- ---- | palette entry
|
||||
* 4 | mmmm -?fF a??? tttt tttt tttt tttt tttt | mosaic factor, unknown (**) , flip bits, additive blending, unknown (***), tile number
|
||||
* 4 | mmmm -cfF aggg tttt tttt tttt tttt tttt | mosaic factor, unknown (x1), checkerboard, flip bits, blend, group?, tile number
|
||||
* 5 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
|
||||
* 6 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
|
||||
* 7 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
|
||||
*
|
||||
* in (4) ggg seems to be either group, or priority against OTHER layers (7 being the lowest, 0 being the highest in normal situations eg most of the time in buriki)
|
||||
*
|
||||
* (*) Fatal Fury WA standard elements are 0x1000-0x1000, all the other games sets 0x100-0x100, related to the bit 27 of sprite regs 0?
|
||||
* (**) setted by black squares in ranking screen in Samurai Shodown 64 1, sprite disable?
|
||||
* (***) bit 22 is setted on some Fatal Fury WA snow (not all of them), bit 21 is setted on Xrally how to play elements in attract mode
|
||||
** Sprite Global Registers
|
||||
* -----------------------
|
||||
*
|
||||
* uint32_t | Bits | Use
|
||||
* offset | Bits | Use
|
||||
* | 3322 2222 2222 1111 1111 11 |
|
||||
* -------+-1098-7654-3210-9876-5432-1098-7654-3210-+----------------
|
||||
* 0 | ssss z--f b--- -aap ---- ---- ---- ---- | s = unknown, samsho z = zooming mode, f = priority sort mode (unset set in roadedge ingame) b = bpp select a = always, p = post, disable?
|
||||
@ -40,11 +40,236 @@
|
||||
|
||||
*/
|
||||
|
||||
void hng64_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
|
||||
|
||||
#define PIXEL_OP_REBASE_TRANSPEN(DEST, DESTZ, SOURCE) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t srcdata = (SOURCE); \
|
||||
if (xdrawpos <= cliprect.right() && xdrawpos >= cliprect.left() && cury <= cliprect.bottom() && cury >= cliprect.top()) \
|
||||
{ \
|
||||
if (zval < (DESTZ)) \
|
||||
{ \
|
||||
if (srcdata != trans_pen) \
|
||||
{ \
|
||||
(DESTZ) = zval; \
|
||||
(DEST) = color + srcdata; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
#define PIXEL_OP_REBASE_TRANSPEN_REV(DEST, DESTZ, SOURCE) \
|
||||
do \
|
||||
{ \
|
||||
uint32_t srcdata = (SOURCE); \
|
||||
if (xdrawpos <= cliprect.right() && xdrawpos >= cliprect.left() && cury <= cliprect.bottom() && cury >= cliprect.top()) \
|
||||
{ \
|
||||
if (zval > (DESTZ)) \
|
||||
{ \
|
||||
if (srcdata != trans_pen) \
|
||||
{ \
|
||||
(DESTZ) = zval; \
|
||||
(DEST) = color + srcdata; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define PIX_CHECKERBOARD \
|
||||
do \
|
||||
{ \
|
||||
if (!mosaic) \
|
||||
srcpix = srcptr[(cursrcx >> 16) & 0xf]; \
|
||||
else \
|
||||
{ \
|
||||
if (mosaic_count_x == 0) \
|
||||
{ \
|
||||
srcpix = srcptr[(cursrcx >> 16) & 0xf]; \
|
||||
mosaic_count_x = mosaic; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
mosaic_count_x--; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (checkerboard) \
|
||||
{ \
|
||||
if (cb & 1) \
|
||||
{ \
|
||||
if (!(cury & 1)) \
|
||||
srcpix = 0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if ((cury & 1)) \
|
||||
srcpix = 0; \
|
||||
} \
|
||||
cb++; \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void hng64_state::drawline(bitmap_ind16 & dest, bitmap_ind16 & destz, const rectangle & cliprect,
|
||||
gfx_element * gfx, uint32_t code, uint32_t color, int flipx, int flipy, int32_t destx, int32_t desty,
|
||||
int32_t dx, int32_t dy, uint32_t dstwidth, uint32_t dstheight, uint32_t trans_pen, uint32_t zval, bool zrev, bool blend, bool checkerboard, uint8_t mosaic, uint8_t &mosaic_count_x, int cury, const u8 *srcdata, int32_t srcx, int32_t srcy_copy, uint32_t leftovers, int line, uint16_t &srcpix)
|
||||
{
|
||||
gfx_element *gfx;
|
||||
uint32_t *source = m_spriteram;
|
||||
uint32_t *finish = m_spriteram + 0xc000/4;
|
||||
int srcy = dy * line + srcy_copy;
|
||||
|
||||
auto* destptr = &dest.pix(cury, 0);
|
||||
auto* destzptr = &destz.pix(cury, 0);
|
||||
|
||||
const u8* srcptr = srcdata + ((srcy >> 16) & 0xf) * gfx->rowbytes();
|
||||
int32_t cursrcx = srcx;
|
||||
|
||||
// iterate over unrolled blocks of 4
|
||||
if (zrev)
|
||||
{
|
||||
uint8_t cb = 0;
|
||||
// iterate over leftover pixels
|
||||
for (int32_t curx = 0; curx < leftovers; curx++)
|
||||
{
|
||||
int xdrawpos = destx + curx;
|
||||
PIX_CHECKERBOARD;
|
||||
PIXEL_OP_REBASE_TRANSPEN_REV(destptr[xdrawpos], destzptr[xdrawpos], srcpix);
|
||||
cursrcx += dx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t cb = 0;
|
||||
// iterate over leftover pixels
|
||||
for (int32_t curx = 0; curx < leftovers; curx++)
|
||||
{
|
||||
int xdrawpos = destx + curx;
|
||||
PIX_CHECKERBOARD;
|
||||
PIXEL_OP_REBASE_TRANSPEN(destptr[xdrawpos], destzptr[xdrawpos], srcpix);
|
||||
cursrcx += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hng64_state::zoom_transpen(bitmap_ind16 &dest, bitmap_ind16 &destz, const rectangle &cliprect,
|
||||
gfx_element *gfx, uint32_t code, uint32_t color, int flipx, int flipy, int32_t destx, int32_t desty,
|
||||
int32_t dx, int32_t dy, uint32_t dstwidth, uint32_t dstheight, uint32_t trans_pen, uint32_t zval, bool zrev, bool blend, bool checkerboard, uint8_t mosaic, uint8_t &mosaic_count_x, int line, uint16_t &srcpix)
|
||||
{
|
||||
// use pen usage to optimize
|
||||
code %= gfx->elements();
|
||||
if (gfx->has_pen_usage())
|
||||
{
|
||||
// fully transparent; do nothing
|
||||
uint32_t usage = gfx->pen_usage(code);
|
||||
if ((usage & ~(1 << trans_pen)) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// render
|
||||
color = gfx->colorbase() + gfx->granularity() * (color % gfx->colors());
|
||||
|
||||
if (blend)
|
||||
color |= 0x8000;
|
||||
|
||||
assert(dest.valid());
|
||||
assert(dest.cliprect().contains(cliprect));
|
||||
|
||||
// ignore empty/invalid cliprects
|
||||
if (cliprect.empty())
|
||||
return;
|
||||
|
||||
if (dstwidth < 1 || dstheight < 1)
|
||||
return;
|
||||
|
||||
int32_t srcx = 0;
|
||||
// apply X flipping
|
||||
if (flipx)
|
||||
{
|
||||
srcx = (dstwidth - 1) * dx - srcx;
|
||||
dx = -dx;
|
||||
}
|
||||
|
||||
int32_t srcy = 0;
|
||||
// apply Y flipping
|
||||
if (flipy)
|
||||
{
|
||||
srcy = (dstheight - 1) * dy - srcy;
|
||||
dy = -dy;
|
||||
}
|
||||
|
||||
// fetch the source data
|
||||
const u8 *srcdata = gfx->get_data(code);
|
||||
|
||||
// compute how many blocks of 4 pixels we have
|
||||
int32_t destendx = destx + dstwidth - 1;
|
||||
uint32_t leftovers = (destendx + 1 - destx);
|
||||
|
||||
// iterate over pixels in Y
|
||||
int32_t srcycopy = srcy;
|
||||
|
||||
drawline(dest, destz, cliprect,
|
||||
gfx, code, color, flipx, flipy, destx, desty,
|
||||
dx, dy, dstwidth, dstheight, trans_pen, zval, zrev, blend, checkerboard, mosaic, mosaic_count_x, desty, srcdata, srcx, srcycopy, leftovers, line, srcpix);
|
||||
|
||||
}
|
||||
|
||||
void hng64_state::get_tile_details(bool chain, uint16_t spritenum, uint8_t xtile, uint8_t ytile, uint8_t xsize, uint8_t ysize, bool xflip, bool yflip, uint32_t& tileno, uint16_t& pal, uint8_t &gfxregion)
|
||||
{
|
||||
int offset;
|
||||
if (!xflip)
|
||||
{
|
||||
if (!yflip)
|
||||
offset = (xtile + (ytile * (xsize + 1)));
|
||||
else
|
||||
offset = (xtile + ((ysize - ytile) * (xsize + 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!yflip)
|
||||
offset = ((xsize - xtile) + (ytile * (xsize + 1)));
|
||||
else
|
||||
offset = ((xsize - xtile) + ((ysize - ytile) * (xsize + 1)));
|
||||
}
|
||||
|
||||
if (!chain)
|
||||
{
|
||||
tileno = (m_spriteram[(spritenum * 8) + 4] & 0x0007ffff);
|
||||
pal = (m_spriteram[(spritenum * 8) + 3] & 0x00ff0000) >> 16;
|
||||
|
||||
if (m_spriteregs[0] & 0x00800000) //bpp switch
|
||||
{
|
||||
gfxregion = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfxregion = 5;
|
||||
tileno >>= 1;
|
||||
pal &= 0xf;
|
||||
}
|
||||
|
||||
tileno += offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
tileno = (m_spriteram[((spritenum + offset) * 8) + 4] & 0x0007ffff);
|
||||
pal = (m_spriteram[((spritenum + offset) * 8) + 3] & 0x00ff0000) >> 16;
|
||||
if (m_spriteregs[0] & 0x00800000) //bpp switch
|
||||
{
|
||||
gfxregion = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfxregion = 5;
|
||||
tileno >>= 1;
|
||||
pal &= 0xf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hng64_state::draw_sprites_buffer(screen_device& screen, const rectangle& cliprect)
|
||||
{
|
||||
m_sprite_bitmap.fill(0x0000, cliprect);
|
||||
|
||||
// global offsets in sprite regs
|
||||
int spriteoffsx = (m_spriteregs[1] >> 0) & 0xffff;
|
||||
@ -56,143 +281,97 @@ void hng64_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, cons
|
||||
// Could also be draw order related, check if it inverts the z value?
|
||||
bool zsort = !(m_spriteregs[0] & 0x01000000);
|
||||
|
||||
#if 0
|
||||
for (int iii = 0; iii < 0x0f; iii++)
|
||||
osd_printf_debug("%.8x ", m_videoregs[iii]);
|
||||
osd_printf_debug("\n");
|
||||
#endif
|
||||
|
||||
// start with empty list
|
||||
m_spritelist.clear();
|
||||
|
||||
while(source < finish)
|
||||
{
|
||||
if (source[4]&0x04000000) // disable bit, ss64 rankings ?
|
||||
{
|
||||
source += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((!zsort && (source[2]&0x07ff0000) != 0x07ff0000) || (zsort && (source[2]&0x07ff0000) != 0))
|
||||
{
|
||||
m_spritelist.emplace_back((source[2]&0x7ff0000)>>16, source);
|
||||
if (source[2]&0x00000100) // inline chain mode
|
||||
source += 8 * (1 + (source[2]&0x0000000f)) * (1 + ((source[2]&0x000000f0)>>4));
|
||||
else
|
||||
source += 8;
|
||||
}
|
||||
else
|
||||
source += 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (zsort)
|
||||
std::stable_sort(m_spritelist.begin(), m_spritelist.end(), [] (auto const &a, auto const &b) { return a.first > b.first; });
|
||||
m_sprite_zbuffer.fill(0x0000, cliprect);
|
||||
else
|
||||
m_sprite_zbuffer.fill(0x07ff, cliprect);
|
||||
|
||||
for(auto it : m_spritelist)
|
||||
int nextsprite = 0;
|
||||
int currentsprite = 0;
|
||||
|
||||
while (currentsprite < ((0xc000 / 4) / 8))
|
||||
{
|
||||
source = it.second;
|
||||
uint16_t zval = (m_spriteram[(currentsprite * 8) + 2] & 0x07ff0000) >> 16;
|
||||
|
||||
int tileno,chainx,chainy,xflip;
|
||||
int pal,xinc,yinc,yflip;
|
||||
uint16_t xpos, ypos;
|
||||
int xdrw,ydrw;
|
||||
int chaini;
|
||||
uint32_t zoomx,zoomy;
|
||||
float foomX, foomY;
|
||||
int blend;
|
||||
|
||||
ypos = (source[0]&0xffff0000)>>16;
|
||||
xpos = (source[0]&0x0000ffff)>>0;
|
||||
uint16_t ypos = (m_spriteram[(currentsprite * 8) + 0] & 0xffff0000) >> 16;
|
||||
uint16_t xpos = (m_spriteram[(currentsprite * 8) + 0] & 0x0000ffff) >> 0;
|
||||
xpos += (spriteoffsx);
|
||||
ypos += (spriteoffsy);
|
||||
|
||||
tileno= (source[4]&0x0007ffff);
|
||||
blend= (source[4]&0x00800000);
|
||||
yflip= (source[4]&0x01000000)>>24;
|
||||
xflip= (source[4]&0x02000000)>>25;
|
||||
bool blend = (m_spriteram[(currentsprite * 8) + 4] & 0x00800000);
|
||||
bool checkerboard = (m_spriteram[(currentsprite * 8) + 4] & 0x04000000);
|
||||
uint8_t mosaic = (m_spriteram[(currentsprite * 8) + 4] & 0xf0000000) >> 28;
|
||||
|
||||
pal =(source[3]&0x00ff0000)>>16;
|
||||
int yflip = (m_spriteram[(currentsprite * 8) + 4] & 0x01000000) >> 24;
|
||||
int xflip = (m_spriteram[(currentsprite * 8) + 4] & 0x02000000) >> 25;
|
||||
|
||||
chainy=(source[2]&0x0000000f);
|
||||
chainx=(source[2]&0x000000f0)>>4;
|
||||
chaini=(source[2]&0x00000100);
|
||||
int chainy = (m_spriteram[(currentsprite * 8) + 2] & 0x0000000f);
|
||||
int chainx = (m_spriteram[(currentsprite * 8) + 2] & 0x000000f0) >> 4;
|
||||
int chaini = (m_spriteram[(currentsprite * 8) + 2] & 0x00000100);
|
||||
|
||||
zoomy = (source[1]&0xffff0000)>>16;
|
||||
zoomx = (source[1]&0x0000ffff)>>0;
|
||||
if (!chaini)
|
||||
{
|
||||
nextsprite = currentsprite + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nextsprite = currentsprite + ((chainx + 1) * (chainy + 1));
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (!(source[4] == 0x00000000 || source[4] == 0x000000aa))
|
||||
osd_printf_debug("unknown : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n", source[0], source[1], source[2], source[3],
|
||||
source[4], source[5], source[6], source[7]);
|
||||
#endif
|
||||
uint32_t zoomy = (m_spriteram[(currentsprite * 8) + 1] & 0xffff0000) >> 16;
|
||||
uint32_t zoomx = (m_spriteram[(currentsprite * 8) + 1] & 0x0000ffff) >> 0;
|
||||
|
||||
/* Calculate the zoom */
|
||||
{
|
||||
int zoom_factor;
|
||||
|
||||
/* FIXME: regular zoom mode has precision bugs, can be easily seen in Samurai Shodown 64 intro */
|
||||
zoom_factor = (m_spriteregs[0] & 0x08000000) ? 0x1000 : 0x100;
|
||||
int zoom_factor = (m_spriteregs[0] & 0x08000000) ? 0x1000 : 0x100;
|
||||
if (!zoomx) zoomx = zoom_factor;
|
||||
if (!zoomy) zoomy = zoom_factor;
|
||||
|
||||
/* First, prevent any possible divide by zero errors */
|
||||
foomX = (float)(zoom_factor) / (float)zoomx;
|
||||
foomY = (float)(zoom_factor) / (float)zoomy;
|
||||
int32_t dx, dy;
|
||||
|
||||
zoomx = ((int)foomX) << 16;
|
||||
zoomy = ((int)foomY) << 16;
|
||||
|
||||
zoomx += (int)((foomX - floor(foomX)) * (float)0x10000);
|
||||
zoomy += (int)((foomY - floor(foomY)) * (float)0x10000);
|
||||
}
|
||||
|
||||
if (m_spriteregs[0] & 0x00800000) //bpp switch
|
||||
if (zoom_factor == 0x100)
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(4);
|
||||
dx = zoomx << 8;
|
||||
dy = zoomy << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(5);
|
||||
tileno>>=1;
|
||||
pal&=0xf;
|
||||
dx = zoomx << 4;
|
||||
dy = zoomy << 4;
|
||||
}
|
||||
|
||||
// Accommodate for chaining and flipping
|
||||
if(xflip)
|
||||
{
|
||||
xinc=-(int)(16.0f*foomX);
|
||||
xpos-=xinc*chainx;
|
||||
}
|
||||
else
|
||||
{
|
||||
xinc=(int)(16.0f*foomX);
|
||||
}
|
||||
int16_t drawy = ypos;
|
||||
uint32_t srcpix_y = 0;
|
||||
|
||||
if(yflip)
|
||||
for (int ydrw = 0; ydrw <= chainy; ydrw++)
|
||||
{
|
||||
yinc=-(int)(16.0f*foomY);
|
||||
ypos-=yinc*chainy;
|
||||
}
|
||||
else
|
||||
{
|
||||
yinc=(int)(16.0f*foomY);
|
||||
}
|
||||
uint32_t dstheight = 0;
|
||||
|
||||
#if 0
|
||||
if (((source[2) & 0xffff0000) >> 16) == 0x0001)
|
||||
do
|
||||
{
|
||||
popmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]);
|
||||
//popmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]);
|
||||
}
|
||||
#endif
|
||||
srcpix_y += dy;
|
||||
dstheight++;
|
||||
} while (srcpix_y < 0x100000);
|
||||
srcpix_y &= 0x0fffff;
|
||||
|
||||
for(ydrw=0;ydrw<=chainy;ydrw++)
|
||||
int32_t destendy = drawy + dstheight - 1;
|
||||
for (int32_t cury = drawy, line = 0; cury <= destendy; line++, cury++)
|
||||
{
|
||||
for(xdrw=0;xdrw<=chainx;xdrw++)
|
||||
int16_t drawx = xpos;
|
||||
uint32_t srcpix_x = 0;
|
||||
|
||||
uint16_t srcpix = 0;
|
||||
|
||||
uint8_t mosaic_count_x = 0;
|
||||
|
||||
for (int xdrw = 0; xdrw <= chainx; xdrw++)
|
||||
{
|
||||
int16_t drawx = xpos+(xinc*xdrw);
|
||||
int16_t drawy = ypos+(yinc*ydrw);
|
||||
uint32_t dstwidth = 0;
|
||||
do
|
||||
{
|
||||
srcpix_x += dx;
|
||||
dstwidth++;
|
||||
} while (srcpix_x < 0x100000);
|
||||
srcpix_x &= 0x0fffff;
|
||||
|
||||
// 0x3ff (0x200 sign bit) based on sams64_2 char select
|
||||
drawx &= 0x3ff;
|
||||
@ -201,33 +380,18 @@ void hng64_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, cons
|
||||
if (drawx & 0x0200)drawx -= 0x400;
|
||||
if (drawy & 0x0200)drawy -= 0x400;
|
||||
|
||||
if (!chaini)
|
||||
{
|
||||
if (!blend) gfx->prio_zoom_transpen(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
|
||||
else gfx->prio_zoom_transpen_additive(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
|
||||
tileno++;
|
||||
}
|
||||
else // inline chain mode, used by ss64
|
||||
{
|
||||
tileno=(source[4]&0x0007ffff);
|
||||
pal =(source[3]&0x00ff0000)>>16;
|
||||
uint32_t tileno;
|
||||
uint16_t pal;
|
||||
uint8_t gfxregion;
|
||||
|
||||
if (m_spriteregs[0] & 0x00800000) //bpp switch
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(4);
|
||||
get_tile_details(chaini, currentsprite, xdrw, ydrw, chainx, chainy, xflip, yflip, tileno, pal, gfxregion);
|
||||
zoom_transpen(m_sprite_bitmap, m_sprite_zbuffer, cliprect, m_gfxdecode->gfx(gfxregion), tileno, pal, xflip, yflip, drawx, cury, dx, dy, dstwidth, dstheight, 0, zval, zsort, blend, checkerboard, mosaic, mosaic_count_x, line, srcpix);
|
||||
drawx += dstwidth;
|
||||
}
|
||||
}
|
||||
drawy += dstheight;
|
||||
}
|
||||
currentsprite = nextsprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(5);
|
||||
tileno>>=1;
|
||||
pal&=0xf;
|
||||
}
|
||||
|
||||
if (!blend) gfx->prio_zoom_transpen(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
|
||||
else gfx->prio_zoom_transpen_additive(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
|
||||
source +=8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -304,12 +304,6 @@ void hng64_state::hng64_tilemap_draw_roz_core_line(screen_device &screen, bitmap
|
||||
else // line mode
|
||||
{
|
||||
const int global_alt_scroll_register_format = m_videoregs[0x00] & 0x04000000;
|
||||
if (global_alt_scroll_register_format) // globally selects alt scroll register layout???
|
||||
{
|
||||
//popmessage("global_alt_scroll_register_format in linemode");
|
||||
}
|
||||
//else
|
||||
{
|
||||
int32_t xmiddle;
|
||||
int32_t ymiddle;
|
||||
|
||||
@ -330,18 +324,37 @@ void hng64_state::hng64_tilemap_draw_roz_core_line(screen_device &screen, bitmap
|
||||
else
|
||||
{
|
||||
uint16_t line = source_line_to_use;
|
||||
xtopleft = (m_videoram[(0x40000 + (line * 0x10) + (scrollbase << 4)) / 4]);
|
||||
xmiddle = (m_videoram[(0x40004 + (line * 0x10) + (scrollbase << 4)) / 4]); // middle screen point
|
||||
xtopleft = (m_videoram[(0x40000 + (scrollbase << 4)) / 4]);
|
||||
xmiddle = (m_videoram[(0x40004 + (scrollbase << 4)) / 4]); // middle screen point
|
||||
|
||||
uint32_t xtopleft2 = (m_videoram[(0x40000 + (line * 0x10) + (scrollbase << 4)) / 4]);
|
||||
uint32_t xmiddle2 = (m_videoram[(0x40004 + (line * 0x10) + (scrollbase << 4)) / 4]); // middle screen point
|
||||
|
||||
if ((xtopleft2 & 0xff) == 0x00)// set to 0x00 if we should use the line data?
|
||||
xtopleft = xtopleft2;
|
||||
|
||||
if ((xmiddle2 & 0xff) == 0x00) // also set to 0x00 if we should use the line data?
|
||||
xmiddle = xmiddle2;
|
||||
|
||||
ytopleft = (m_videoram[(0x40008 + (line * 0x10) + (scrollbase << 4)) / 4]);
|
||||
ymiddle = (m_videoram[(0x4000c + (line * 0x10) + (scrollbase << 4)) / 4]); // middle screen point
|
||||
}
|
||||
|
||||
if (global_alt_scroll_register_format) // globally selects alt scroll register layout???
|
||||
{
|
||||
xinc = (xmiddle - xtopleft) / 512;
|
||||
yinc = 0;
|
||||
xinc2 = 0;
|
||||
yinc2 = (ymiddle - ytopleft) / 512;
|
||||
}
|
||||
else
|
||||
{
|
||||
xinc = (xmiddle - xtopleft) / 512;
|
||||
yinc = (ymiddle - ytopleft) / 512;
|
||||
// TODO: if global_alt_scroll_register_format is enabled uses incxy / incyx into calculation somehow ...
|
||||
xinc2 = 0;
|
||||
yinc2 = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t startx = xtopleft;
|
||||
@ -547,12 +560,13 @@ void hng64_state::hng64_tilemap_draw_roz_core_line(screen_device &screen, bitmap
|
||||
* uint32_t | Bits | Use
|
||||
* | 3322 2222 2222 1111 1111 11 |
|
||||
* -------+-1098-7654-3210-9876-5432-1098-7654-3210-+----------------
|
||||
* 0 | ---- -Cdd ---- -??Z ---- ---- ---- ---- | C = global complex zoom
|
||||
* 0 | ---- -Cdd ---- -??Z ---- ---- ---- ---u | C = global complex zoom
|
||||
| 0000 0011 - road edge alt 1 | dd = global tilemap dimension selector
|
||||
| 0000 0111 - road edge alt 2 | ? = Always Set?
|
||||
| | Z = Global Zoom Disable?
|
||||
* 1 | oooo oooo oooo oooo ---- ---- ---- ---- | unknown - 0001 is a popular value. Explore.
|
||||
* 1 | ---- ---- ---- ---- oooo oooo oooo oooo | unknown - untouched in sams64 games, initialized elsewhere
|
||||
| | u = explicitly cleared from initialized value in sams64
|
||||
* 1 | oooo oooo oooo oooX ---- ---- ---- ---- | unknown - X is sometimes used (1 in demo of xrally, 0 in game) not always initialized whole register gets set to 0xffff during mosaic bit of roadedge intro
|
||||
* 1 | ---- ---- ---- ---- oooo oooo oYoo oooo | unknown - untouched in sams64 games, initialized elsewhere Y gets set to 4 at some points in xrally attract
|
||||
* 2 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap0 per layer flags
|
||||
* 2 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 per layer flags
|
||||
* 3 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap2 per layer flags
|
||||
@ -561,15 +575,14 @@ void hng64_state::hng64_tilemap_draw_roz_core_line(screen_device &screen, bitmap
|
||||
* 4 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap1 scrollbase when not floor, lineram offset when floor
|
||||
* 5 | xxxx xxxx xxxx xxxx ---- ---- ---- ---- | tilemap3 scrollbase when not floor, lineram offset when floor
|
||||
* 5 | ---- ---- ---- ---- xxxx xxxx xxxx xxxx | tilemap4 scrollbase when not floor, lineram offset when floor
|
||||
* 6 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa)
|
||||
* 7 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa)
|
||||
* 8 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 80008000 (fatfurwa)
|
||||
* 6 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) ---- bfff (xrally, and fatfurwa despite comment? maybe reads MAME initialized value and changes it?)
|
||||
* 7 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 000001ff (fatfurwa) 5e00 3fff (xrally ^^ )
|
||||
* 8 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 80008000 (fatfurwa) 9e00 be00 (xrally ^^ )
|
||||
* 9 | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa)
|
||||
* a | oooo oooo oooo oooo oooo oooo oooo oooo | unknown - always seems to be 00000000 (fatfurwa)
|
||||
* b | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | auto animation mask for tilemaps
|
||||
* c | xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx | auto animation bits for tilemaps
|
||||
* d | oooo oooo oooo oooo oooo oooo oooo oooo | not used ??
|
||||
* e | oooo oooo oooo oooo oooo oooo oooo oooo | not used ??
|
||||
|
||||
// tilemap0 per layer flags
|
||||
// 0840 - startup tests, 8x8x4 layer
|
||||
@ -802,7 +815,34 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b
|
||||
}
|
||||
|
||||
// Draw the sprites on top of everything
|
||||
draw_sprites(screen, bitmap, cliprect);
|
||||
draw_sprites_buffer(screen, cliprect);
|
||||
|
||||
// copy sprites into display
|
||||
pen_t const *const clut = &m_palette->pen(0);
|
||||
for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
|
||||
{
|
||||
const uint16_t *src = &m_sprite_bitmap.pix(y, cliprect.min_x);
|
||||
uint32_t *dst = &bitmap.pix(y, cliprect.min_x);
|
||||
|
||||
for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
|
||||
{
|
||||
uint16_t srcpix = *src;
|
||||
if (srcpix & 0x7fff)
|
||||
{
|
||||
if (srcpix & 0x8000)
|
||||
{
|
||||
*dst = add_blend_r32(*dst, clut[srcpix & 0x7fff]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = clut[srcpix & 0x7fff];
|
||||
}
|
||||
}
|
||||
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
}
|
||||
|
||||
// Layer the global frame buffer operations on top of everything
|
||||
// transition_control(bitmap, cliprect);
|
||||
@ -812,7 +852,7 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b
|
||||
if (0)
|
||||
popmessage("%08x %08x %08x %08x %08x", m_spriteregs[0], m_spriteregs[1], m_spriteregs[2], m_spriteregs[3], m_spriteregs[4]);
|
||||
|
||||
if (1)
|
||||
if (0)
|
||||
popmessage("%08x %08x TR(%04x %04x %04x %04x) SB(%04x %04x %04x %04x) %08x %08x %08x %08x %08x AA(%08x %08x) %08x",
|
||||
m_videoregs[0x00],
|
||||
m_videoregs[0x01],
|
||||
@ -834,26 +874,36 @@ uint32_t hng64_state::screen_update_hng64(screen_device &screen, bitmap_rgb32 &b
|
||||
m_videoregs[0x0d]);
|
||||
|
||||
if (0)
|
||||
popmessage("TC: %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x : %08x %08x %08x %08x",
|
||||
popmessage("TC: %08x %08x %08x %08x : %08x %08x\n%08x %08x\n%08x %08x\n%08x %08x : %08x %08x %08x %08x : %08x %08x\n%08x %08x : %08x %08x %08x %08x",
|
||||
m_tcram[0x00 / 4],
|
||||
m_tcram[0x04 / 4],
|
||||
m_tcram[0x08 / 4], // tilemaps 0/1 ?
|
||||
m_tcram[0x0c / 4], // ss64_2 debug 04000000 = 'half' on tm1 00000004 = 'half' on tm3 (used in transitions?)
|
||||
m_tcram[0x10 / 4],
|
||||
m_tcram[0x14 / 4],
|
||||
m_tcram[0x18 / 4],
|
||||
m_tcram[0x1c / 4],
|
||||
m_tcram[0x20 / 4],
|
||||
m_tcram[0x24 / 4],
|
||||
m_tcram[0x28 / 4],
|
||||
m_tcram[0x2c / 4],
|
||||
|
||||
// these are used for 'fade to black' in most cases, but
|
||||
// in xrally attract, when one image is meant to fade into another, one value increases while the other decreases
|
||||
m_tcram[0x18 / 4], // xRGB fade values? (roadedge attract)
|
||||
m_tcram[0x1c / 4], // xRGB fade values? (roadedge attract) fades on fatfurwa before buildings in intro
|
||||
|
||||
m_tcram[0x20 / 4], // something else?
|
||||
m_tcram[0x24 / 4], // something else?
|
||||
|
||||
// 7 of these fade during the buriki SNK logo (probably redundant)
|
||||
// in roadedge they're just set to
|
||||
// 0x00000000, 0x01000000, 0x02000000, 0x03000000, 0x04000000, 0x05000000, 0x06000000, 0x07000000
|
||||
m_tcram[0x28 / 4], // ?RGB fade values (buriki jumbotron) fades on fatfurwa before high score table etc. + bottom value only on 'fade to red' part of fatfurywa intro
|
||||
m_tcram[0x2c / 4], // ?RGB fade values (buriki jumbotron)
|
||||
m_tcram[0x30 / 4],
|
||||
m_tcram[0x34 / 4],
|
||||
m_tcram[0x38 / 4],
|
||||
m_tcram[0x3c / 4],
|
||||
m_tcram[0x40 / 4],
|
||||
m_tcram[0x44 / 4],
|
||||
m_tcram[0x48 / 4],
|
||||
|
||||
|
||||
m_tcram[0x48 / 4], // this is where the 'vblank' thing lives
|
||||
m_tcram[0x4c / 4],
|
||||
m_tcram[0x50 / 4],
|
||||
m_tcram[0x54 / 4],
|
||||
@ -1085,7 +1135,12 @@ void hng64_state::video_start()
|
||||
m_texturerom = memregion("textures")->base();
|
||||
m_vertsrom = (uint16_t*)memregion("verts")->base();
|
||||
m_vertsrom_size = memregion("verts")->bytes();
|
||||
|
||||
m_screen->register_screen_bitmap(m_sprite_bitmap);
|
||||
m_screen->register_screen_bitmap(m_sprite_zbuffer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "hng64_3d.ipp"
|
||||
#include "hng64_sprite.ipp"
|
||||
|
Loading…
Reference in New Issue
Block a user