From 582de7b8644c537535ba21fddd1108af7a79950b Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 12 Dec 2019 05:29:13 +0900 Subject: 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 --- src/mame/video/sknsspr.cpp | 148 +++++++++++++++++++++------------------------ src/mame/video/sknsspr.h | 6 +- 2 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/mame/video/sknsspr.cpp b/src/mame/video/sknsspr.cpp index a5ef849c4c4..ac40ce43792 100644 --- a/src/mame/video/sknsspr.cpp +++ b/src/mame/video/sknsspr.cpp @@ -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(SUPRNOVA_DECODE_BUFFER_SIZE); + m_decodebuffer = make_unique_clear(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; diff --git a/src/mame/video/sknsspr.h b/src/mame/video/sknsspr.h index ef6bde26986..e6dc9f2dc25 100644 --- a/src/mame/video/sknsspr.h +++ b/src/mame/video/sknsspr.h @@ -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 m_decodebuffer; + std::unique_ptr m_decodebuffer; int skns_rle_decode ( int romoffset, int size ); }; -- cgit v1.2.3