sknsspr.cpp : Correct algorithm for high precision shrink sprite, Use 10.6 fixed point for position values (#6030)

* sknsspr.cpp : Correct algorithm for high precision shrink sprite, Use 10.6 fixed point for position values

* sknsspr.cpp : Add notes
This commit is contained in:
cam900 2019-12-12 05:29:13 +09:00 committed by Vas Crabb
parent c89df40e20
commit 582de7b864
2 changed files with 72 additions and 82 deletions

View File

@ -25,7 +25,7 @@
DEFINE_DEVICE_TYPE(SKNS_SPRITE, sknsspr_device, "sknsspr", "SKNS Sprite")
sknsspr_device::sknsspr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
sknsspr_device::sknsspr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, SKNS_SPRITE, tag, owner, clock)
, device_video_interface(mconfig, *this)
, device_rom_interface(mconfig, *this, 27) // TODO : Unknown address bits; maybe 27?
@ -34,7 +34,7 @@ sknsspr_device::sknsspr_device(const machine_config &mconfig, const char *tag, d
void sknsspr_device::device_start()
{
m_decodebuffer = make_unique_clear<uint8_t[]>(SUPRNOVA_DECODE_BUFFER_SIZE);
m_decodebuffer = make_unique_clear<u8[]>(SUPRNOVA_DECODE_BUFFER_SIZE);
save_pointer(NAME(m_decodebuffer), SUPRNOVA_DECODE_BUFFER_SIZE);
//printf("sknsspr_device::device_start()\n");
@ -55,7 +55,7 @@ int sknsspr_device::skns_rle_decode ( int romoffset, int size )
int decodeoffset = 0;
while(size>0) {
uint8_t code = read_byte((romoffset++) % (1<<27));
u8 code = read_byte((romoffset++) % (1<<27));
size -= (code & 0x7f) + 1;
if(code & 0x80) { /* (code & 0x7f) normal values will follow */
code &= 0x7f;
@ -64,7 +64,7 @@ int sknsspr_device::skns_rle_decode ( int romoffset, int size )
code--;
} while(code != 0xff);
} else { /* repeat next value (code & 0x7f) times */
uint8_t val = read_byte((romoffset++) % (1<<27));
u8 val = read_byte((romoffset++) % (1<<27));
do {
m_decodebuffer[(decodeoffset++)%SUPRNOVA_DECODE_BUFFER_SIZE] = val;
code--;
@ -76,30 +76,30 @@ int sknsspr_device::skns_rle_decode ( int romoffset, int size )
void sknsspr_device::skns_sprite_kludge(int x, int y)
{
m_sprite_kludge_x = x;
m_sprite_kludge_y = y;
m_sprite_kludge_x = x << 6;
m_sprite_kludge_y = y << 6;
}
/* Zooming blitter, zoom is by way of both source and destination offsets */
/* We are working in .6 fixed point if you hadn't guessed */
/* We are working in .16 fixed point if you hadn't guessed */
#define z_decls(step) \
uint16_t zxs = 0x40-(zx_m>>2); \
uint16_t zxd = 0x40-(zx_s>>2); \
uint16_t zys = 0x40-(zy_m>>2); \
uint16_t zyd = 0x40-(zy_s>>2); \
u32 zxs = 0x10000-(zx_m); \
u32 zxd = 0x10000-(zx_s); \
u32 zys = 0x10000-(zy_m); \
u32 zyd = 0x10000-(zy_s); \
int xs, ys, xd, yd, old, old2; \
int step_spr = step; \
int bxs = 0, bys = 0; \
rectangle clip; \
clip.min_x = cliprect.min_x<<6; \
clip.max_x = (cliprect.max_x+1)<<6; \
clip.min_y = cliprect.min_y<<6; \
clip.max_y = (cliprect.max_y+1)<<6; \
sx <<= 6; \
sy <<= 6; \
x <<= 6; \
y <<= 6;
clip.min_x = cliprect.min_x<<16; \
clip.max_x = (cliprect.max_x+1)<<16; \
clip.min_y = cliprect.min_y<<16; \
clip.max_y = (cliprect.max_y+1)<<16; \
sx <<= 16; \
sy <<= 16; \
x <<= 10; \
y <<= 10;
#define z_clamp_x_min() \
if(x < clip.min_x) { \
@ -123,7 +123,7 @@ void sknsspr_device::skns_sprite_kludge(int x, int y)
bys += zys; \
y += zyd; \
} while(y < clip.min_y); \
src += (bys>>6)*step_spr; \
src += (bys>>16)*step_spr; \
}
#define z_clamp_y_max() \
@ -132,7 +132,7 @@ void sknsspr_device::skns_sprite_kludge(int x, int y)
bys += zys; \
y -= zyd; \
} while(y > clip.max_y); \
src += (bys>>6)*step_spr; \
src += (bys>>16)*step_spr; \
}
#define z_loop_x() \
@ -156,16 +156,16 @@ void sknsspr_device::skns_sprite_kludge(int x, int y)
while(ys < sy && yd >= clip.min_y)
#define z_draw_pixel() \
uint8_t val = src[xs >> 6]; \
u8 val = src[xs >> 16]; \
if(val) \
bitmap.pix16(yd>>6, xd>>6) = val + colour;
bitmap.pix16(yd>>16, xd>>16) = val + colour;
#define z_x_dst(op) \
old = xd; \
do { \
xs += zxs; \
xd op zxd; \
} while(!((xd^old) & ~0x3f));
} while(!((xd^old) & ~0xffff));
#define z_y_dst(op) \
old = yd; \
@ -173,13 +173,13 @@ void sknsspr_device::skns_sprite_kludge(int x, int y)
do { \
ys += zys; \
yd op zyd; \
} while(!((yd^old) & ~0x3f)); \
while((ys^old2) & ~0x3f) { \
} while(!((yd^old) & ~0xffff)); \
while((ys^old2) & ~0xffff) { \
src += step_spr; \
old2 += 0x40; \
old2 += 0x10000; \
}
static void blit_nf_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t *src, int x, int y, int sx, int sy, uint16_t zx_m, uint16_t zx_s, uint16_t zy_m, uint16_t zy_s, int colour)
static void blit_nf_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const u8 *src, int x, int y, int sx, int sy, u16 zx_m, u16 zx_s, u16 zy_m, u16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
@ -193,7 +193,7 @@ static void blit_nf_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uin
}
}
static void blit_fy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t *src, int x, int y, int sx, int sy, uint16_t zx_m, uint16_t zx_s, uint16_t zy_m, uint16_t zy_s, int colour)
static void blit_fy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const u8 *src, int x, int y, int sx, int sy, u16 zx_m, u16 zx_s, u16 zy_m, u16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
@ -207,7 +207,7 @@ static void blit_fy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uin
}
}
static void blit_fx_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t *src, int x, int y, int sx, int sy, uint16_t zx_m, uint16_t zx_s, uint16_t zy_m, uint16_t zy_s, int colour)
static void blit_fx_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const u8 *src, int x, int y, int sx, int sy, u16 zx_m, u16 zx_s, u16 zy_m, u16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
@ -221,7 +221,7 @@ static void blit_fx_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uin
}
}
static void blit_fxy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t *src, int x, int y, int sx, int sy, uint16_t zx_m, uint16_t zx_s, uint16_t zy_m, uint16_t zy_s, int colour)
static void blit_fxy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const u8 *src, int x, int y, int sx, int sy, u16 zx_m, u16 zx_s, u16 zy_m, u16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
@ -235,14 +235,14 @@ static void blit_fxy_z(bitmap_ind16 &bitmap, const rectangle &cliprect, const ui
}
}
static void (*const blit_z[4])(bitmap_ind16 &bitmap, const rectangle &cliprect, const uint8_t *src, int x, int y, int sx, int sy, uint16_t zx_m, uint16_t zx_s, uint16_t zy_m, uint16_t zy_s, int colour) = {
static void (*const blit_z[4])(bitmap_ind16 &bitmap, const rectangle &cliprect, const u8 *src, int x, int y, int sx, int sy, u16 zx_m, u16 zx_s, u16 zy_m, u16 zy_s, int colour) = {
blit_nf_z,
blit_fy_z,
blit_fx_z,
blit_fxy_z,
};
void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint32_t* spriteram_source, size_t spriteram_size, uint32_t* sprite_regs)
void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u32* spriteram_source, size_t spriteram_size, u32* sprite_regs)
{
/*- SPR RAM Format -**
@ -262,17 +262,17 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
a = ROM address of sprite data
0x08 ZZZZ ZZ-- zzzz zz-- xxxx xxxx xx-- ----
0x08 ZZZZ ZZ-- zzzz zz-- xxxx xxxx xxxx xxxx
Z = horizontal zoom table
z = horizontal zoom subtable
x = x position
x = x position (10.6 fixed point)
0x0C ZZZZ ZZ-- zzzz zz-- yyyy yyyy yy-- ----
0x0C ZZZZ ZZ-- zzzz zz-- yyyy yyyy yyyy yyyy
Z = vertical zoom table
z = vertical zoom subtable
x = y position
x = y position (10.6 fixed point)
**- End of Comments -*/
@ -281,24 +281,25 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
//printf ("addr %08x\n", (sprite_regs[0x14/4]));
uint32_t *source = spriteram_source;
uint32_t *finish = source + spriteram_size/4;
u32 *source = spriteram_source;
u32 *finish = source + spriteram_size/4;
int group_x_offset[4];
s16 group_x_offset[4];
int group_y_offset[4];
int group_enable;
int group_number;
int sprite_flip;
int sprite_x_scroll;
int sprite_y_scroll;
s16 sprite_x_scroll;
s16 sprite_y_scroll;
/* galpani3 uses sprite trail effect (disable clearing sprite bitmap) */
int clear_bitmap = (~sprite_regs[0x04/4] & 0x04); // RWR1
int disabled = sprite_regs[0x04/4] & 0x08; // RWR1
int xsize,ysize, size, xpos=0,ypos=0, pri=0, romoffset, colour=0, xflip,yflip, joint;
int xsize,ysize, size, pri=0, romoffset, colour=0, xflip,yflip, joint;
int sx,sy;
int endromoffs=0;
int grow;
uint16_t zoomx_m, zoomx_s, zoomy_m, zoomy_s;
u16 zoomx_m, zoomx_s, zoomy_m, zoomy_s;
s16 xpos=0,ypos=0;
if (clear_bitmap)
{
@ -311,30 +312,20 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
/* Sengekis uses global flip */
sprite_flip = (sprite_regs[0x04/4] & 0x03); // RWR1
sprite_y_scroll = ((sprite_regs[0x08/4] & 0x7fc0) >> 6); // RWR2
sprite_x_scroll = ((sprite_regs[0x10/4] & 0x7fc0) >> 6); // RWR4
if (sprite_y_scroll&0x100) sprite_y_scroll -= 0x200; // Signed
if (sprite_x_scroll&0x100) sprite_x_scroll -= 0x200; // Signed
sprite_y_scroll = s16((sprite_regs[0x08/4] & 0x7fff) << 1) >> 1; // RWR2
sprite_x_scroll = s16((sprite_regs[0x10/4] & 0x7fff) << 1) >> 1; // RWR4
group_x_offset[0] = (sprite_regs[0x18/4] & 0xffc0) >> 6; // RWR6
group_y_offset[0] = (sprite_regs[0x1c/4] & 0xffc0) >> 6; // RWR7
if (group_x_offset[0]&0x200) group_x_offset[0] -= 0x400; // Signed
if (group_y_offset[0]&0x200) group_y_offset[0] -= 0x400; // Signed
group_x_offset[0] = (sprite_regs[0x18/4] & 0xffff); // RWR6
group_y_offset[0] = (sprite_regs[0x1c/4] & 0xffff); // RWR7
group_x_offset[1] = (sprite_regs[0x20/4] & 0xffc0) >> 6; // RWR8
group_y_offset[1] = (sprite_regs[0x24/4] & 0xffc0) >> 6; // RWR9
if (group_x_offset[1]&0x200) group_x_offset[1] -= 0x400; // Signed
if (group_y_offset[1]&0x200) group_y_offset[1] -= 0x400; // Signed
group_x_offset[1] = (sprite_regs[0x20/4] & 0xffff); // RWR8
group_y_offset[1] = (sprite_regs[0x24/4] & 0xffff); // RWR9
group_x_offset[2] = (sprite_regs[0x28/4] & 0xffc0) >> 6; // RWR10
group_y_offset[2] = (sprite_regs[0x2c/4] & 0xffc0) >> 6; // RWR11
if (group_x_offset[2]&0x200) group_x_offset[2] -= 0x400; // Signed
if (group_y_offset[2]&0x200) group_y_offset[2] -= 0x400; // Signed
group_x_offset[2] = (sprite_regs[0x28/4] & 0xffff); // RWR10
group_y_offset[2] = (sprite_regs[0x2c/4] & 0xffff); // RWR11
group_x_offset[3] = (sprite_regs[0x30/4] & 0xffc0) >> 6; // RWR12
group_y_offset[3] = (sprite_regs[0x34/4] & 0xffc0) >> 6; // RWR13
if (group_x_offset[3]&0x200) group_x_offset[3] -= 0x400; // Signed
if (group_y_offset[3]&0x200) group_y_offset[3] -= 0x400; // Signed
group_x_offset[3] = (sprite_regs[0x30/4] & 0xffff); // RWR12
group_y_offset[3] = (sprite_regs[0x34/4] & 0xffff); // RWR13
// popmessage ("x %08x y %08x x2 %08x y2 %08x",sprite_x_scroll, sprite_y_scroll,group_x_offset[1], group_y_offset[1]);
// popmessage("%d %d %d %d A:%d B:%d", m_sprite_kludge_x, m_sprite_kludge_y, sprite_x_scroll, sprite_y_scroll, (skns_pal_regs[0x00/4] & 0x7000) >> 12, (skns_pal_regs[0x10/4] & 0x7000) >> 12);
@ -370,8 +361,8 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
if (!(joint & 1))
{
xpos = (source[2] & 0x0000ffc0) >> 6;
ypos = (source[3] & 0x0000ffc0) >> 6;
xpos = (source[2] & 0x0000ffff);
ypos = (source[3] & 0x0000ffff);
xpos += sprite_x_scroll; // Global offset
ypos += sprite_y_scroll;
@ -397,13 +388,10 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
}
else
{
xpos += (source[2] & 0x0000ffc0) >> 6;
ypos += (source[3] & 0x0000ffc0) >> 6;
xpos += (source[2] & 0x0000ffff);
ypos += (source[3] & 0x0000ffff);
}
if (xpos > 0x1ff) xpos -= 0x400;
if (ypos > 0x1ff) ypos -= 0x400;
/* Local sprite offset (for taking flip into account and drawing offset) */
sx = xpos;
sy = ypos;
@ -412,12 +400,12 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
if (sprite_flip&2)
{
xflip ^= 1;
sx = screen().visible_area().max_x+1 - sx;
sx = ((screen().visible_area().max_x+1) << 6) - sx;
}
if (sprite_flip&1)
{
yflip ^= 1;
sy = screen().visible_area().max_y+1 - sy;
sy = ((screen().visible_area().max_y+1) << 6) - sy;
}
/* Palette linking */
@ -439,10 +427,10 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
if (!grow)
{
zoomx_m = (source[2] >> 24)&0x00fc;
zoomx_s = (source[2] >> 16)&0x00fc;
zoomy_m = (source[3] >> 24)&0x00fc;
zoomy_s = (source[3] >> 16)&0x00fc;
zoomx_m = (source[2] & 0xff000000) >> 16;
zoomx_s = (source[2] & 0x00ff0000) >> 8;
zoomy_m = (source[3] & 0xff000000) >> 16;
zoomy_s = (source[3] & 0x00ff0000) >> 8;
}
else
{
@ -453,9 +441,9 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
// convinced this implementation is correct because we simply end up ignoring
// part of the data)
zoomx_m = 0;
zoomx_s = (source[2] >> 24)&0x00fc;
zoomx_s = (source[2] & 0xffff0000) >> 16;
zoomy_m = 0;
zoomy_s = (source[3] >> 24)&0x00fc;
zoomy_s = (source[3] & 0xffff0000) >> 16;
}
@ -483,6 +471,8 @@ void sknsspr_device::skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cl
}
else
{
sx >>= 6;
sy >>= 6;
if (!xflip && !yflip) {
int xx,yy;

View File

@ -8,9 +8,9 @@
class sknsspr_device : public device_t, public device_video_interface, public device_rom_interface
{
public:
sknsspr_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
sknsspr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
void skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint32_t* spriteram_source, size_t spriteram_size, uint32_t* sprite_regs);
void skns_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, u32* spriteram_source, size_t spriteram_size, u32* sprite_regs);
void skns_sprite_kludge(int x, int y);
protected:
@ -21,7 +21,7 @@ protected:
private:
static constexpr unsigned SUPRNOVA_DECODE_BUFFER_SIZE = 0x2000;
int m_sprite_kludge_x, m_sprite_kludge_y;
std::unique_ptr<uint8_t[]> m_decodebuffer;
std::unique_ptr<u8[]> m_decodebuffer;
int skns_rle_decode ( int romoffset, int size );
};