sigmab98: Implemented sprite rotation [Luca Elia]

This commit is contained in:
Luca Elia 2015-05-10 15:28:41 +02:00
parent 7a0659dfa1
commit 9a84fe06c5

View File

@ -87,13 +87,13 @@ http://www.tsc-acnet.com/index.php?sort=8&action=cataloglist&s=1&mode=3&genre_id
To Do: To Do:
- KL5C80 emulation is needed to consolidate the sammymdl games in one memory map and to run the BIOS - KL5C80 emulation is needed to consolidate the sammymdl games in one memory map and to run the BIOS
- Sprites rotation, e.g. logo in dashhero, pepsiman https://youtu.be/p3cbZ67m4lo?t=1m24s, tdoboon https://youtu.be/loPP3jt0Ob0
- Remove ROM patches: gegege checks the EEPROM output after reset, and wants a timed 0->1 transition or locks up while - Remove ROM patches: gegege checks the EEPROM output after reset, and wants a timed 0->1 transition or locks up while
saving setting in service mode. Using a reset_delay of 7 works, unless when "play style" is set saving setting in service mode. Using a reset_delay of 7 works, unless when "play style" is set
to "coin" (it probably changes the number of reads from port $C0). to "coin" (it probably changes the number of reads from port $C0).
I guess the reset_delay mechanism should be implemented with a timer in eeprom.c. I guess the reset_delay mechanism should be implemented with a timer in eeprom.c.
- pyenaget intro: when the theater scrolls out to the left, the train should scroll in from the right, - pyenaget intro: when the theater scrolls out to the left, the train should scroll in from the right,
with no visible gaps. It currently leaves the screen empty instead, for several seconds. with no visible gaps. It currently leaves the screen empty instead, for several seconds.
- tdoboon: no smoke from hit planes as shown in the video? Tiles are present (f60-125f) and used in demo mode.
- dashhero does not acknowledge the button bashing correctly, it's very hard to win (a slower pace works better!) - dashhero does not acknowledge the button bashing correctly, it's very hard to win (a slower pace works better!)
Notes: Notes:
@ -140,6 +140,8 @@ public:
required_device<screen_device> m_screen; required_device<screen_device> m_screen;
required_device<palette_device> m_palette; required_device<palette_device> m_palette;
bitmap_ind16 *m_sprite_bitmap;
UINT8 m_reg; UINT8 m_reg;
UINT8 m_rombank; UINT8 m_rombank;
UINT8 m_reg2; UINT8 m_reg2;
@ -237,6 +239,7 @@ public:
DECLARE_MACHINE_RESET(sigmab98); DECLARE_MACHINE_RESET(sigmab98);
DECLARE_MACHINE_RESET(sammymdl); DECLARE_MACHINE_RESET(sammymdl);
virtual void video_start();
UINT32 screen_update_sigmab98(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); UINT32 screen_update_sigmab98(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
void screen_eof_sammymdl(screen_device &screen, bool state); void screen_eof_sammymdl(screen_device &screen, bool state);
INTERRUPT_GEN_MEMBER(sigmab98_vblank_interrupt); INTERRUPT_GEN_MEMBER(sigmab98_vblank_interrupt);
@ -251,6 +254,11 @@ public:
***************************************************************************/ ***************************************************************************/
void sigmab98_state::video_start()
{
m_sprite_bitmap = auto_bitmap_ind16_alloc(machine(), 512, 512);
}
/*************************************************************************** /***************************************************************************
Sprites Sprites
@ -274,19 +282,28 @@ public:
6 7654 3--- Number of Y Tiles - 1 6 7654 3--- Number of Y Tiles - 1
---- -210 Y (High) ---- -210 Y (High)
7 Y (Low) 7 Y (Low)
8 Shrink Factor (<< 8, High) 8 Destination Delta X, Scaled by Shrink Factor << 8 (High)
9 Shrink Factor (<< 8, Low) 9 Destination Delta X, Scaled by Shrink Factor << 8 (Low)
a ? rotation, see dashhero (Sigma logo) a Destination Delta Y, Scaled by Shrink Factor << 8 (High)
b ? and pepsiman (when falling) b Destination Delta Y, Scaled by Shrink Factor << 8 (Low)
c 7654 3--- c 7654 3---
---- -210 Delta X (High) ---- -210 Source X (High)
d Delta X (Low) d Source X (Low)
e 7654 3--- e 7654 3---
---- -210 Delta Y (High) ---- -210 Source Y (High)
f Delta Y (Low) f Source Y (Low)
Sprites rotation examples:
logo in dashhero, pepsiman https://youtu.be/p3cbZ67m4lo?t=1m24s, tdoboon https://youtu.be/loPP3jt0Ob0
***************************************************************************/ ***************************************************************************/
inline int integer_part(int x)
{
// return x >> 16;
return (x + 0x8000) >> 16;
}
void sigmab98_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri_mask) void sigmab98_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, int pri_mask)
{ {
UINT8 *end = (m_buffered_spriteram ? m_buffered_spriteram->buffer() : m_spriteram) - 0x10; UINT8 *end = (m_buffered_spriteram ? m_buffered_spriteram->buffer() : m_spriteram) - 0x10;
@ -294,60 +311,36 @@ void sigmab98_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprec
for ( ; s != end; s -= 0x10 ) for ( ; s != end; s -= 0x10 )
{ {
int gfx, code, color, zoom, /*rot,*/ dim, scale;
int sx, nx, x, x0, x1, dx, flipx;
int sy, ny, y, y0, y1, dy, flipy;
if ( (s[ 0x01 ] & 0x04) == 0) if ( (s[ 0x01 ] & 0x04) == 0)
continue; continue;
if ( ((1 << (s[ 0x01 ] & 0x03)) & pri_mask) == 0 ) if ( ((1 << (s[ 0x01 ] & 0x03)) & pri_mask) == 0 )
continue; continue;
color = s[ 0x00 ] & 0xf; int color = s[ 0x00 ] & 0xf;
gfx = (s[ 0x01 ] & 0x40 ) ? 1 : 0; int gfx = (s[ 0x01 ] & 0x40 ) ? 1 : 0;
int code = s[ 0x02 ] * 256 + s[ 0x03 ];
code = s[ 0x02 ] * 256 + s[ 0x03 ]; int nx = ((s[ 0x04 ] & 0xf8) >> 3) + 1;
int dstx = (s[ 0x04 ] & 0x03) * 256 + s[ 0x05 ];
nx = ((s[ 0x04 ] & 0xf8) >> 3) + 1; int ny = ((s[ 0x06 ] & 0xf8) >> 3) + 1;
int dsty = (s[ 0x06 ] & 0x03) * 256 + s[ 0x07 ];
sx = (s[ 0x04 ] & 0x03) * 256 + s[ 0x05 ]; int dstdx = (s[ 0x08 ] & 0xff) * 256 + s[ 0x09 ]; // 0x100 = no zoom, 0x200 = 50% zoom
int dstdy = (s[ 0x0a ] & 0xff) * 256 + s[ 0x0b ]; // ""
ny = ((s[ 0x06 ] & 0xf8) >> 3) + 1; int srcx = (s[ 0x0c ] & 0xff) * 256 + s[ 0x0d ];
int srcy = (s[ 0x0e ] & 0xff) * 256 + s[ 0x0f ];
sy = (s[ 0x06 ] & 0x03) * 256 + s[ 0x07 ];
zoom = (s[ 0x08 ] & 0xff) * 256 + s[ 0x09 ]; // 0x100 means no zoom
// rot = (s[ 0x0a ] & 0xff) * 256 + s[ 0x0b ]; // unimplemented!
dx = (s[ 0x0c ] & 0xff) * 256 + s[ 0x0d ];
dy = (s[ 0x0e ] & 0xff) * 256 + s[ 0x0f ];
// Sign extend the position // Sign extend the position
sx = (sx & 0x1ff) - (sx & 0x200); dstx = (dstx & 0x01ff) - (dstx & 0x0200); // or 0x3ff/0x400?
sy = (sy & 0x1ff) - (sy & 0x200); dsty = (dsty & 0x01ff) - (dsty & 0x0200);
dx = (dx & 0x7fff) - (dx & 0x8000);
dy = (dy & 0x7fff) - (dy & 0x8000);
// Use fixed point values (16.16), for accuracy // Flipping
sx <<= 16; int x0, x1, dx, flipx = s[ 0x01 ] & 0x10;
sy <<= 16; int y0, y1, dy, flipy = s[ 0x01 ] & 0x08;
zoom = (1 << 16) / (zoom ? zoom : 1);
dim = (0x10 << 8) * zoom;
// Add shift (negated)
sx -= (dx << 8) * zoom;
sy -= (dy << 8) * zoom;
scale = dim / 0x10;
// Let's approximate to the nearest greater integer value
// to avoid holes in between tiles
if (scale & 0xffff) scale += (1<<16) / 0x10;
flipx = s[ 0x01 ] & 0x10;
flipy = s[ 0x01 ] & 0x08;
if ( flipx ) { x0 = nx - 1; x1 = -1; dx = -1; } if ( flipx ) { x0 = nx - 1; x1 = -1; dx = -1; }
else { x0 = 0; x1 = nx; dx = +1; } else { x0 = 0; x1 = nx; dx = +1; }
@ -355,17 +348,134 @@ void sigmab98_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprec
if ( flipy ) { y0 = ny - 1; y1 = -1; dy = -1; } if ( flipy ) { y0 = ny - 1; y1 = -1; dy = -1; }
else { y0 = 0; y1 = ny; dy = +1; } else { y0 = 0; y1 = ny; dy = +1; }
for (y = y0; y != y1; y += dy) // Draw the sprite directly to screen if no zoom/rotation/offset is required
if (dstdx == 0x100 && !dstdy && !srcx && !srcy)
{ {
for (x = x0; x != x1; x += dx) for (int y = y0; y != y1; y += dy)
{ {
m_gfxdecode->gfx(gfx)->zoom_transpen(bitmap,cliprect, for (int x = x0; x != x1; x += dx)
{
m_gfxdecode->gfx(gfx)->transpen(bitmap, cliprect,
code++, color,
flipx, flipy,
dstx + x * 16, dsty + y * 16, 0);
}
}
continue;
}
// First draw the sprite in a buffer without zoom/rotation/offset, nor transparency
rectangle sprite_cliprect(0, nx * 16 - 1, 0, ny * 16 - 1);
for (int y = y0; y != y1; y += dy)
{
for (int x = x0; x != x1; x += dx)
{
m_gfxdecode->gfx(gfx)->opaque(*m_sprite_bitmap, sprite_cliprect,
code++, color, code++, color,
flipx, flipy, flipx, flipy,
(sx + x * dim) / 0x10000, (sy + y * dim) / 0x10000, x * 16, y * 16);
scale, scale, 0 );
} }
} }
// Sign extend the transformation values
dstdx = (dstdx & 0x7fff) - (dstdx & 0x8000);
dstdy = (dstdy & 0x7fff) - (dstdy & 0x8000);
srcx = (srcx & 0x7fff) - (srcx & 0x8000);
srcy = (srcy & 0x7fff) - (srcy & 0x8000);
dstdy = -dstdy;
// Use fixed point values (16.16), for accuracy
dstx <<= 16;
dsty <<= 16;
// Source delta (equal for x and y)
int z = int( sqrt(dstdx * dstdx + dstdy * dstdy) + 0.5 ); // dest delta vector is scaled by the source delta!?
if (!z)
z = 0x100;
int srcdzz = z << 8;
// Destination x and y deltas
int dstdxx = (dstdx << 16) / z; // dest x delta for source x increments
int dstdyx = (dstdy << 16) / z; // dest y delta for source x increments
int dstdxy = -dstdyx; // dest x delta for source y increments (orthogonal to the above vector)
int dstdyy = dstdxx; // dest y delta for source y increments
// Transform the source offset in a destination offset (negate, scale and rotate it)
srcx = (-srcx << 8) / z;
srcy = (-srcy << 8) / z;
dstx += srcx * dstdxx;
dsty += srcx * dstdyx;
dstx += srcy * dstdxy;
dsty += srcy * dstdyy;
// Supersampling (2x2) to avoid gaps in the destination
srcdzz /= 2;
dstdxx /= 2;
dstdyx /= 2;
dstdxy /= 2;
dstdyy /= 2;
// Transform the source image while drawing to the screen
UINT16 *src = &m_sprite_bitmap->pix16(0);
UINT16 *dst = &bitmap.pix16(0);
int src_rowpixels = m_sprite_bitmap->rowpixels();
int dst_rowpixels = bitmap.rowpixels();
UINT16 penmask = gfx ? 0xff : 0x0f;
// Scan source image top to bottom
srcy = 0;
for (;;)
{
int dstx_prev = dstx;
int dsty_prev = dsty;
int fy = integer_part(srcy);
if (fy > sprite_cliprect.max_y)
break;
if (fy >= sprite_cliprect.min_y)
{
// left to right
srcx = 0;
for (;;)
{
int fx = integer_part(srcx);
if (fx > sprite_cliprect.max_x)
break;
if (fx >= sprite_cliprect.min_x)
{
int px = integer_part(dstx);
int py = integer_part(dsty);
if (px >= cliprect.min_x && px <= cliprect.max_x && py >= cliprect.min_y && py <= cliprect.max_y)
{
UINT16 pen = src[fy * src_rowpixels + fx];
if (pen & penmask)
dst[py * dst_rowpixels + px] = pen;
}
}
// increment source x and dest x,y
srcx += srcdzz;
dstx += dstdxx;
dsty += dstdyx;
}
}
// increment source y and dest x,y
srcy += srcdzz;
dstx = dstx_prev;
dsty = dsty_prev;
dstx += dstdxy;
dsty += dstdyy;
}
} }
} }
@ -2807,18 +2917,18 @@ DRIVER_INIT_MEMBER(sigmab98_state,haekaka)
***************************************************************************/ ***************************************************************************/
GAME( 1997, dodghero, 0, dodghero, sigma_1b, sigmab98_state, dodghero, ROT0, "Sigma", "Minna Atsumare! Dodge Hero", GAME_IMPERFECT_GRAPHICS ) GAME( 1997, dodghero, 0, dodghero, sigma_1b, sigmab98_state, dodghero, ROT0, "Sigma", "Minna Atsumare! Dodge Hero", 0 )
GAME( 1997, sushimar, 0, dodghero, sigma_3b, sigmab98_state, dodghero, ROT0, "Sigma", "Itazura Daisuki! Sushimaru Kun", GAME_IMPERFECT_GRAPHICS ) GAME( 1997, sushimar, 0, dodghero, sigma_3b, sigmab98_state, dodghero, ROT0, "Sigma", "Itazura Daisuki! Sushimaru Kun", 0 )
GAME( 1997, gegege, 0, gegege, sigma_1b, sigmab98_state, gegege, ROT0, "Sigma / Banpresto", "GeGeGe no Kitarou Youkai Slot", GAME_IMPERFECT_GRAPHICS ) GAME( 1997, gegege, 0, gegege, sigma_1b, sigmab98_state, gegege, ROT0, "Sigma / Banpresto", "GeGeGe no Kitarou Youkai Slot", 0 )
GAME( 1997, b3rinsya, 0, gegege, sigma_5b, sigmab98_state, b3rinsya, ROT0, "Sigma", "Burning Sanrinsya - Burning Tricycle", GAME_IMPERFECT_GRAPHICS ) // 1997 in the rom GAME( 1997, b3rinsya, 0, gegege, sigma_5b, sigmab98_state, b3rinsya, ROT0, "Sigma", "Burning Sanrinsya - Burning Tricycle", 0 ) // 1997 in the rom
GAME( 1997, pepsiman, 0, gegege, sigma_3b, sigmab98_state, pepsiman, ROT0, "Sigma", "PEPSI Man", GAME_IMPERFECT_GRAPHICS ) GAME( 1997, pepsiman, 0, gegege, sigma_3b, sigmab98_state, pepsiman, ROT0, "Sigma", "PEPSI Man", 0 )
GAME( 1998, tbeastw2, 0, gegege, sigma_3b, sigmab98_state, tbeastw2, ROT0, "Sigma / Transformer Production Company / Takara", "Transformers Beast Wars II", GAME_IMPERFECT_GRAPHICS ) // 1997 in the rom GAME( 1998, tbeastw2, 0, gegege, sigma_3b, sigmab98_state, tbeastw2, ROT0, "Sigma / Transformer Production Company / Takara", "Transformers Beast Wars II", 0 ) // 1997 in the rom
GAME( 1997, ucytokyu, 0, gegege, sigma_js, sigmab98_state, ucytokyu, ROT0, "Sigma", "Uchuu Tokkyuu Medalian", GAME_IMPERFECT_GRAPHICS ) // Banpresto + others in the ROM GAME( 1997, ucytokyu, 0, gegege, sigma_js, sigmab98_state, ucytokyu, ROT0, "Sigma", "Uchuu Tokkyuu Medalian", 0 ) // Banpresto + others in the ROM
GAME( 2000, dashhero, 0, dashhero, sigma_1b, sigmab98_state, dashhero, ROT0, "Sigma", "Minna Ganbare! Dash Hero", GAME_IMPERFECT_GRAPHICS | GAME_NOT_WORKING ) // 1999 in the rom GAME( 2000, dashhero, 0, dashhero, sigma_1b, sigmab98_state, dashhero, ROT0, "Sigma", "Minna Ganbare! Dash Hero", GAME_NOT_WORKING ) // 1999 in the rom
// Sammy Medal Games: // Sammy Medal Games:
GAME( 2000, sammymdl, 0, sammymdl, sammymdl, sigmab98_state, animalc, ROT0, "Sammy", "Sammy Medal Game System Bios", GAME_IS_BIOS_ROOT ) GAME( 2000, sammymdl, 0, sammymdl, sammymdl, sigmab98_state, animalc, ROT0, "Sammy", "Sammy Medal Game System Bios", GAME_IS_BIOS_ROOT )
GAME( 2000, animalc, sammymdl, animalc, sammymdl, sigmab98_state, animalc, ROT0, "Sammy", "Animal Catch", GAME_IMPERFECT_GRAPHICS ) GAME( 2000, animalc, sammymdl, animalc, sammymdl, sigmab98_state, animalc, ROT0, "Sammy", "Animal Catch", 0 )
GAME( 2000, itazuram, sammymdl, itazuram, sammymdl, sigmab98_state, itazuram, ROT0, "Sammy", "Itazura Monkey", GAME_IMPERFECT_GRAPHICS ) GAME( 2000, itazuram, sammymdl, itazuram, sammymdl, sigmab98_state, itazuram, ROT0, "Sammy", "Itazura Monkey", 0 )
GAME( 2000, pyenaget, sammymdl, pyenaget, sammymdl, sigmab98_state, haekaka, ROT0, "Sammy", "Pye-nage Taikai", GAME_IMPERFECT_GRAPHICS ) GAME( 2000, pyenaget, sammymdl, pyenaget, sammymdl, sigmab98_state, haekaka, ROT0, "Sammy", "Pye-nage Taikai", 0 )
GAME( 2000, tdoboon, sammymdl, tdoboon, haekaka, sigmab98_state, haekaka, ROT0, "Sammy", "Taihou de Doboon", GAME_IMPERFECT_GRAPHICS ) GAME( 2000, tdoboon, sammymdl, tdoboon, haekaka, sigmab98_state, haekaka, ROT0, "Sammy", "Taihou de Doboon", 0 )
GAME( 2001, haekaka, sammymdl, haekaka, haekaka, sigmab98_state, haekaka, ROT0, "Sammy", "Hae Hae Ka Ka Ka", GAME_IMPERFECT_GRAPHICS ) GAME( 2001, haekaka, sammymdl, haekaka, haekaka, sigmab98_state, haekaka, ROT0, "Sammy", "Hae Hae Ka Ka Ka", 0 )