mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +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,15 +40,240 @@
|
||||
|
||||
*/
|
||||
|
||||
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;
|
||||
int spriteoffsy = (m_spriteregs[1]>>16)&0xffff;
|
||||
int spriteoffsx = (m_spriteregs[1] >> 0) & 0xffff;
|
||||
int spriteoffsy = (m_spriteregs[1] >> 16) & 0xffff;
|
||||
|
||||
// This flips between ingame and other screens for roadedge, where the sprites which are filtered definitely needs to change and the game explicitly swaps the values in the sprite list at the same time.
|
||||
// m_spriteregs[2] could also play a part as it also flips between 0x00000000 and 0x000fffff at the same time
|
||||
@ -56,178 +281,117 @@ 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 = (m_spriteregs[0] & 0x08000000) ? 0x1000 : 0x100;
|
||||
if (!zoomx) zoomx = zoom_factor;
|
||||
if (!zoomy) zoomy = zoom_factor;
|
||||
|
||||
int32_t dx, dy;
|
||||
|
||||
if (zoom_factor == 0x100)
|
||||
{
|
||||
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;
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
||||
for(ydrw=0;ydrw<=chainy;ydrw++)
|
||||
{
|
||||
for(xdrw=0;xdrw<=chainx;xdrw++)
|
||||
do
|
||||
{
|
||||
int16_t drawx = xpos+(xinc*xdrw);
|
||||
int16_t drawy = ypos+(yinc*ydrw);
|
||||
srcpix_y += dy;
|
||||
dstheight++;
|
||||
} while (srcpix_y < 0x100000);
|
||||
srcpix_y &= 0x0fffff;
|
||||
|
||||
// 0x3ff (0x200 sign bit) based on sams64_2 char select
|
||||
drawx &= 0x3ff;
|
||||
drawy &= 0x3ff;
|
||||
int32_t destendy = drawy + dstheight - 1;
|
||||
for (int32_t cury = drawy, line = 0; cury <= destendy; line++, cury++)
|
||||
{
|
||||
int16_t drawx = xpos;
|
||||
uint32_t srcpix_x = 0;
|
||||
|
||||
if (drawx&0x0200)drawx-=0x400;
|
||||
if (drawy&0x0200)drawy-=0x400;
|
||||
uint16_t srcpix = 0;
|
||||
|
||||
if (!chaini)
|
||||
uint8_t mosaic_count_x = 0;
|
||||
|
||||
for (int xdrw = 0; xdrw <= chainx; xdrw++)
|
||||
{
|
||||
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;
|
||||
|
||||
if (m_spriteregs[0] & 0x00800000) //bpp switch
|
||||
uint32_t dstwidth = 0;
|
||||
do
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx= m_gfxdecode->gfx(5);
|
||||
tileno>>=1;
|
||||
pal&=0xf;
|
||||
}
|
||||
srcpix_x += dx;
|
||||
dstwidth++;
|
||||
} while (srcpix_x < 0x100000);
|
||||
srcpix_x &= 0x0fffff;
|
||||
|
||||
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;
|
||||
// 0x3ff (0x200 sign bit) based on sams64_2 char select
|
||||
drawx &= 0x3ff;
|
||||
drawy &= 0x3ff;
|
||||
|
||||
if (drawx & 0x0200)drawx -= 0x400;
|
||||
if (drawy & 0x0200)drawy -= 0x400;
|
||||
|
||||
uint32_t tileno;
|
||||
uint16_t pal;
|
||||
uint8_t gfxregion;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,44 +304,57 @@ 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;
|
||||
int32_t xmiddle;
|
||||
int32_t ymiddle;
|
||||
|
||||
const uint32_t& global_tileregs = m_videoregs[0x00];
|
||||
const int global_zoom_disable = global_tileregs & 0x00010000;
|
||||
if (global_zoom_disable) // disable all scrolling / zoom (test screen) (maybe)
|
||||
{
|
||||
// If this bit is active the scroll registers don't seem valid at all?
|
||||
// It either disables zooming, or disables use of the scroll registers completely
|
||||
// - used at startup
|
||||
|
||||
xtopleft = 0;
|
||||
xmiddle = 256 << 16;
|
||||
|
||||
ytopleft = 0;
|
||||
ymiddle = 256 << 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t line = source_line_to_use;
|
||||
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???
|
||||
{
|
||||
//popmessage("global_alt_scroll_register_format in linemode");
|
||||
xinc = (xmiddle - xtopleft) / 512;
|
||||
yinc = 0;
|
||||
xinc2 = 0;
|
||||
yinc2 = (ymiddle - ytopleft) / 512;
|
||||
}
|
||||
//else
|
||||
else
|
||||
{
|
||||
int32_t xmiddle;
|
||||
int32_t ymiddle;
|
||||
|
||||
const uint32_t& global_tileregs = m_videoregs[0x00];
|
||||
const int global_zoom_disable = global_tileregs & 0x00010000;
|
||||
if (global_zoom_disable) // disable all scrolling / zoom (test screen) (maybe)
|
||||
{
|
||||
// If this bit is active the scroll registers don't seem valid at all?
|
||||
// It either disables zooming, or disables use of the scroll registers completely
|
||||
// - used at startup
|
||||
|
||||
xtopleft = 0;
|
||||
xmiddle = 256 << 16;
|
||||
|
||||
ytopleft = 0;
|
||||
ymiddle = 256 << 16;
|
||||
}
|
||||
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
|
||||
ytopleft = (m_videoram[(0x40008 + (line * 0x10) + (scrollbase << 4)) / 4]);
|
||||
ymiddle = (m_videoram[(0x4000c + (line * 0x10) + (scrollbase << 4)) / 4]); // middle screen point
|
||||
}
|
||||
|
||||
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