summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/tatsumi/tzbx15_sprites.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/tatsumi/tzbx15_sprites.cpp')
-rw-r--r--src/mame/tatsumi/tzbx15_sprites.cpp561
1 files changed, 561 insertions, 0 deletions
diff --git a/src/mame/tatsumi/tzbx15_sprites.cpp b/src/mame/tatsumi/tzbx15_sprites.cpp
new file mode 100644
index 00000000000..68b91a8265f
--- /dev/null
+++ b/src/mame/tatsumi/tzbx15_sprites.cpp
@@ -0,0 +1,561 @@
+// license:BSD-3-Clause
+// copyright-holders:Bryan McPhail, Angelo Salese
+
+#include "emu.h"
+#include "tzbx15_sprites.h"
+#include "screen.h"
+
+// TZB215 on Apache 3
+// TZB315 on Round Up 5, Big Fight, Cycle Warriors
+// differences, if any, unknown
+// (does not appear to be CLUT size, even if that would have made sense.
+// Round Up 5 uses the smaller CLUT like Apache 3 yet is confirmed to be a TZB315)
+
+DEFINE_DEVICE_TYPE(TZB215_SPRITES, tzb215_device, "tzb215_sprites", "Tatsumi TZB215 Rotating Sprites")
+DEFINE_DEVICE_TYPE(TZB315_SPRITES, tzb315_device, "tzb315_sprites", "Tatsumi TZB315 Rotating Sprites")
+
+tzbx15_device::tzbx15_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, type, tag, owner, clock)
+ , device_gfx_interface(mconfig, *this)
+ , m_palette_clut(*this, "palette_clut")
+ , m_palette_base(*this, finder_base::DUMMY_TAG)
+ , m_spriteram(*this, finder_base::DUMMY_TAG)
+ , m_sprites_l_rom(*this, "sprites_l")
+ , m_sprites_h_rom(*this, "sprites_h")
+{
+}
+
+tzbx15_device::tzbx15_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 clut_size)
+ : tzbx15_device(mconfig, type, tag, owner, clock)
+{
+ m_rom_clut_size = clut_size;
+}
+
+tzb215_device::tzb215_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 clut_size)
+ : tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, clut_size)
+{
+}
+
+tzb215_device::tzb215_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : tzbx15_device(mconfig, TZB215_SPRITES, tag, owner, clock, 0)
+{
+}
+
+tzb315_device::tzb315_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, u32 clut_size)
+ : tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, clut_size)
+{
+}
+
+tzb315_device::tzb315_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : tzbx15_device(mconfig, TZB315_SPRITES, tag, owner, clock, 0)
+{
+}
+
+
+
+
+static const gfx_layout spritelayout =
+{
+ 8,8,
+ RGN_FRAC(1,1),
+ 4,
+ { STEP4(0,1) },
+ { 8,12,0,4, 24,28,16,20 },
+ { STEP8(0,4*8) },
+ 32*8
+};
+
+GFXDECODE_MEMBER( tzbx15_device::gfxinfo )
+ GFXDECODE_DEVICE("sprites_l", 0, spritelayout, 0, 256)
+ GFXDECODE_DEVICE("sprites_h", 0, spritelayout, 0, 256)
+GFXDECODE_END
+
+void tzbx15_device::device_start()
+{
+ m_rom_clut_offset = memregion("sprites_l")->bytes() - m_rom_clut_size;
+
+ m_shadow_pen_array = make_unique_clear<uint8_t[]>(m_rom_clut_size * 2);
+ m_temp_bitmap.allocate(512, 512);
+
+ decode_gfx(gfxinfo);
+ gfx(0)->set_colors(m_rom_clut_size / 8);
+ gfx(1)->set_colors(m_rom_clut_size / 8);
+}
+
+void tzbx15_device::device_reset()
+{
+}
+
+void tzbx15_device::device_add_mconfig(machine_config &config)
+{
+ // 4096 or 8192 arranged as series of CLUTs
+ PALETTE(config, m_palette_clut).set_format(palette_device::xRGB_555, m_rom_clut_size * 2);
+}
+
+void tzbx15_device::mycopyrozbitmap_core(bitmap_ind8 &bitmap, const bitmap_rgb32 &srcbitmap,
+ int dstx, int dsty, int srcwidth, int srcheight, int incxx, int incxy, int incyx, int incyy,
+ const rectangle &clip, int transparent_color)
+{ }
+
+void tzbx15_device::mycopyrozbitmap_core(bitmap_rgb32 &bitmap, const bitmap_rgb32 &srcbitmap,
+ int dstx, int dsty, int srcwidth, int srcheight, int incxx, int incxy, int incyx, int incyy,
+ const rectangle &clip, int transparent_color)
+{
+ // const int xmask = srcbitmap.width()-1;
+ // const int ymask = srcbitmap.height()-1;
+ const int widthshifted = srcwidth << 16;
+ const int heightshifted = srcheight << 16;
+
+ uint32_t startx = 0;
+ uint32_t starty = 0;
+
+ int sx = dstx;
+ int sy = dsty;
+ int ex = dstx + srcwidth;
+ int ey = dsty + srcheight;
+
+ if (sx < clip.min_x) sx = clip.min_x;
+ if (ex > clip.max_x) ex = clip.max_x;
+ if (sy < clip.min_y) sy = clip.min_y;
+ if (ey > clip.max_y) ey = clip.max_y;
+
+ if (sx <= ex)
+ {
+ while (sy <= ey)
+ {
+ int x = sx;
+ uint32_t cx = startx;
+ uint32_t cy = starty;
+ uint32_t *dest = &bitmap.pix(sy, sx);
+
+ while (x <= ex)
+ {
+ if (cx < widthshifted && cy < heightshifted)
+ {
+ int c = srcbitmap.pix(cy >> 16, cx >> 16);
+
+ if (c != transparent_color)
+ *dest = c;
+ }
+
+ cx += incxx;
+ cy += incxy;
+ x++;
+ dest++;
+ }
+ startx += incyx;
+ starty += incyy;
+ sy++;
+ }
+ }
+}
+
+template<class BitmapClass>
+void tzbx15_device::roundupt_drawgfxzoomrotate(
+ BitmapClass &dest_bmp, const rectangle &clip,
+ gfx_element *gfx, uint32_t code, uint32_t color,
+ int flipx, int flipy, uint32_t ssx, uint32_t ssy,
+ int scalex, int scaley, int rotate,
+ int write_priority_only)
+{
+ if (!scalex || !scaley) return;
+
+ /*
+ scalex and scaley are 16.16 fixed point numbers
+ 1<<15 : shrink to 50%
+ 1<<16 : uniform scale
+ 1<<17 : double to 200%
+ */
+
+ /* KW 991012 -- Added code to force clip to bitmap boundary */
+ rectangle myclip = clip;
+ myclip &= dest_bmp.cliprect();
+
+ if (gfx)
+ {
+ const pen_t *pal = &m_palette_clut->pen(gfx->colorbase() + gfx->granularity() * (color % gfx->colors()));
+ const uint8_t *shadow_pens = m_shadow_pen_array.get() + (gfx->granularity() * (color % gfx->colors()));
+ const uint8_t *code_base = gfx->get_data(code % gfx->elements());
+
+ int block_size = 8 * scalex;
+ int sprite_screen_height = ((ssy&0xffff)+block_size)>>16;
+ int sprite_screen_width = ((ssx&0xffff)+block_size)>>16;
+
+ if (sprite_screen_width && sprite_screen_height)
+ {
+ /* compute sprite increment per screen pixel */
+ int dx = (gfx->width()<<16)/sprite_screen_width;
+ int dy = (gfx->height()<<16)/sprite_screen_height;
+
+ int sx;//=ssx>>16;
+ int sy;//=ssy>>16;
+
+
+// int ex = sx+sprite_screen_width;
+// int ey = sy+sprite_screen_height;
+
+ int incxx=0x10000;//(int)((float)dx * cos(theta));
+// int incxy=0x0;//(int)((float)dy * -sin(theta));
+ int incyx=0x0;//(int)((float)dx * sin(theta));
+// int incyy=0x10000;//(int)((float)dy * cos(theta));
+
+ if (ssx&0x80000000) sx=0-(0x10000 - (ssx>>16)); else sx=ssx>>16;
+ if (ssy&0x80000000) sy=0-(0x10000 - (ssy>>16)); else sy=ssy>>16;
+ int ex = sx+sprite_screen_width;
+ int ey = sy+sprite_screen_height;
+ int x_index_base;
+ if( flipx )
+ {
+ x_index_base = (sprite_screen_width-1)*dx;
+ dx = -dx;
+ incxx=-incxx;
+ incyx=-incyx;
+ }
+ else
+ {
+ x_index_base = 0;
+ }
+
+ int y_index;
+ if( flipy )
+ {
+ y_index = (sprite_screen_height-1)*dy;
+ dy = -dy;
+ }
+ else
+ {
+ y_index = 0;
+ }
+
+ if( sx < myclip.min_x)
+ { /* clip left */
+ int pixels = myclip.min_x-sx;
+ sx += pixels;
+ x_index_base += pixels*dx;
+ }
+ if( sy < myclip.min_y )
+ { /* clip top */
+ int pixels = myclip.min_y-sy;
+ sy += pixels;
+ y_index += pixels*dy;
+ }
+ /* NS 980211 - fixed incorrect clipping */
+ if( ex > myclip.max_x+1 )
+ { /* clip right */
+ int pixels = ex-myclip.max_x-1;
+ ex -= pixels;
+ }
+ if( ey > myclip.max_y+1 )
+ { /* clip bottom */
+ int pixels = ey-myclip.max_y-1;
+ ey -= pixels;
+ }
+
+ if( ex>sx )
+ { /* skip if inner loop doesn't draw anything */
+#if 0
+ int startx=0;
+ int starty=0;
+
+// int incxx=0x10000;
+// int incxy=0;
+// int incyx=0;
+// int incyy=0x10000;
+ double theta=rotate * ((2.0 * M_PI)/512.0);
+ double c=cos(theta);
+ double s=sin(theta);
+
+
+ // if (ey-sy > 0)
+ // dy=dy / (ey-sy);
+ {
+ float angleAsRadians=(float)rotate * (7.28f / 512.0f);
+ //float ccx = cosf(angleAsRadians);
+ //float ccy = sinf(angleAsRadians);
+ float a=0;
+
+ }
+
+ for( int y=sy; y<ey; y++ )
+ {
+ uint32_t *const dest = &dest_bmp.pix(y);
+ int cx = startx;
+ int cy = starty;
+
+ int x_index = x_index_base;
+ for( int x=sx; x<ex; x++ )
+ {
+ const uint8_t *source = code_base + (cy>>16) * gfx->rowbytes();
+ int c = source[(cx >> 16)];
+ if( c != transparent_color )
+ {
+ if (write_priority_only)
+ dest[x]=shadow_pens[c];
+ else
+ dest[x]=pal[c];
+ }
+ cx += incxx;
+ cy += incxy;
+ }
+ startx += incyx;
+ starty += incyy;
+ }
+#endif
+#if 1 // old
+ for( int y=sy; y<ey; y++ )
+ {
+ uint8_t const *const source = code_base + (y_index>>16) * gfx->rowbytes();
+ typename BitmapClass::pixel_t *const dest = &dest_bmp.pix(y);
+
+ int x_index = x_index_base;
+ for( int x=sx; x<ex; x++ )
+ {
+ int c = source[x_index>>16];
+ if( c )
+ {
+ // Only draw shadow pens if writing priority buffer
+ if (write_priority_only)
+ dest[x]=shadow_pens[c];
+ else if (!shadow_pens[c])
+ dest[x]=pal[c];
+ }
+ x_index += dx;
+ }
+
+ y_index += dy;
+ }
+#endif
+ }
+ }
+ }
+}
+
+/*
+ Sprite RAM itself uses an index into two ROM tables to actually draw the object.
+
+ Sprite RAM format:
+
+ Word 0: 0xf000 - ?
+ 0x0fff - Index into ROM sprite table
+ Word 1: 0x8000 - X Flip
+ 0x4000 - Y Flip
+ 0x3000 - ?
+ 0x0ff8 - Color
+ 0x0007 - ?
+ Word 2: 0xffff - X position
+ Word 3: 0xffff - Y position
+ Word 4: 0x01ff - Scale
+ Word 5: 0x01ff - Rotation
+
+ Sprite ROM table format, alternate lines come from each bank, with the
+ very first line indicating control information:
+
+ First bank:
+ Byte 0: Y destination offset (in scanlines, unaffected by scale).
+ Byte 1: Always 0?
+ Byte 2: Number of source scanlines to render from (so unaffected by destination scale).
+ Byte 3: Usually 0, sometimes 0x80??
+
+ Other banks:
+ Byte 0: Width of line in tiles (-1)
+ Byte 1: X offset to start drawing line at (multipled by scale * 8)
+ Bytes 2/3: Tile index to start fetching tiles from (increments per tile).
+
+*/
+template<class BitmapClass>
+void tzbx15_device::draw_sprites_main(BitmapClass &bitmap, const rectangle &cliprect, int write_priority_only, int rambank)
+{
+ // Sprite data is double buffered
+ for (int offs = rambank;offs < rambank + 0x800;offs += 6)
+ {
+ int y = m_spriteram[offs+3];
+ int x = m_spriteram[offs+2];
+ int scale = m_spriteram[offs+4] & 0x1ff;
+ int color = m_spriteram[offs+1] >> 3 & 0x1ff;
+ int flip_x = m_spriteram[offs+1] & 0x8000;
+ int flip_y = m_spriteram[offs+1] & 0x4000;
+ int rotate = 0;//m_spriteram[offs+5]&0x1ff; // Todo: Turned off for now
+
+ int index = m_spriteram[offs];
+
+// if (m_spriteram[offs+1]&0x7)
+// color=machine().rand()%0xff;
+
+ /* End of sprite list marker */
+ if (index == 0xffff || m_spriteram[offs + 4] == 0xffff) // todo
+ return;
+
+ if (index >= 0x4000)
+ continue;
+
+ uint8_t const *src1 = m_sprites_l_rom + (index * 4);
+ uint8_t const *src2 = m_sprites_h_rom + (index * 4);
+
+ int lines = src1[2];
+ int y_offset = src1[0]&0xf8;
+
+ lines -= y_offset;
+
+ int render_x = x << 16;
+ int render_y = y << 16;
+ scale = scale << 9; /* 0x80 becomes 0x10000 */
+
+ if (flip_y)
+ render_y -= y_offset * scale;
+ else
+ render_y += y_offset * scale;
+
+ if (rotate)
+ {
+ render_y = 0;
+ m_temp_bitmap.fill(0);
+ }
+
+ int extent_x = 0, extent_y = 0;
+
+ src1 += 4;
+ int h = 0;
+
+ while (lines > 0)
+ {
+ int base, x_offs, x_width, x_pos, draw_this_line = 1;
+ int this_extent = 0;
+
+ /* Odd and even lines come from different banks */
+ if (h & 1)
+ {
+ x_width = src1[0] + 1;
+ x_offs = src1[1] * scale * 8;
+ base = src1[2] | (src1[3] << 8);
+ }
+ else
+ {
+ x_width = src2[0] + 1;
+ x_offs = src2[1] * scale * 8;
+ base = src2[2] | (src2[3] << 8);
+ }
+
+ if (draw_this_line)
+ {
+ base *= 2;
+
+ if (!rotate)
+ {
+ if (flip_x)
+ x_pos = render_x - x_offs - scale * 8;
+ else
+ x_pos = render_x + x_offs;
+ }
+ else
+ x_pos = x_offs;
+
+ for (int w = 0; w < x_width; w++)
+ {
+ if (rotate)
+ roundupt_drawgfxzoomrotate(
+ m_temp_bitmap,cliprect,gfx(0 + (base & 1)),
+ base >> 1,
+ color,flip_x,flip_y,x_pos,render_y,
+ scale,scale,0,write_priority_only);
+ else
+ roundupt_drawgfxzoomrotate(
+ bitmap,cliprect,gfx(0 + (base & 1)),
+ base >> 1,
+ color,flip_x,flip_y,x_pos,render_y,
+ scale,scale,0,write_priority_only);
+ base++;
+
+ if (flip_x)
+ x_pos -= scale * 8;
+ else
+ x_pos += scale * 8;
+
+ this_extent += scale * 8;
+ }
+ if (h & 1)
+ src1 += 4;
+ else
+ src2 += 4;
+
+ if (this_extent > extent_x)
+ extent_x = this_extent;
+ this_extent = 0;
+
+ if (flip_y)
+ render_y -= 8 * scale;
+ else
+ render_y += 8 * scale;
+ extent_y += 8 * scale;
+
+ h++;
+ lines -= 8;
+ }
+ else
+ {
+ h = 32; // hack
+ }
+ }
+
+ if (rotate)
+ {
+ double theta = rotate * ((2.0 * M_PI) / 512.0);
+
+ int incxx = (int)(65536.0 * cos(theta));
+ int incxy = (int)(65536.0 * -sin(theta));
+ int incyx = (int)(65536.0 * sin(theta));
+ int incyy = (int)(65536.0 * cos(theta));
+
+ extent_x = extent_x >> 16;
+ extent_y = extent_y >> 16;
+ if (extent_x > 2 && extent_y > 2)
+ mycopyrozbitmap_core(bitmap, m_temp_bitmap, x/* + (extent_x/2)*/, y /*+ (extent_y/2)*/, extent_x, extent_y, incxx, incxy, incyx, incyy, cliprect, 0);
+ }
+ }
+}
+
+void tzbx15_device::draw_sprites(bitmap_rgb32 &bitmap, const rectangle &cliprect, int write_priority_only, int rambank)
+{
+ draw_sprites_main(bitmap, cliprect, write_priority_only, rambank);
+}
+
+void tzbx15_device::draw_sprites(bitmap_ind8& bitmap, const rectangle &cliprect, int write_priority_only, int rambank)
+{
+ draw_sprites_main(bitmap, cliprect, write_priority_only, rambank);
+}
+
+/*
+ * Object palettes are build from a series of cluts stored in the object roms.
+ *
+ * We update 'Mame palettes' from the clut here in order to simplify the
+ * draw routines. We also note down any uses of the 'shadow' pen (index 255).
+ */
+void tzbx15_device::update_cluts()
+{
+ const int length = m_rom_clut_size * 2;
+ const uint8_t* bank1 = m_sprites_l_rom + m_rom_clut_offset;
+ const uint8_t* bank2 = m_sprites_h_rom + m_rom_clut_offset;
+
+ for (int i = 0; i < length; i+=8)
+ {
+ m_palette_clut->set_pen_color(i + 0, m_palette_base->pen_color(bank1[1] + m_sprite_palette_base));
+ m_shadow_pen_array[i+0]=(bank1[1] == 255);
+ m_palette_clut->set_pen_color(i + 1, m_palette_base->pen_color(bank1[0] + m_sprite_palette_base));
+ m_shadow_pen_array[i+1]=(bank1[0] == 255);
+ m_palette_clut->set_pen_color(i + 2, m_palette_base->pen_color(bank1[3] + m_sprite_palette_base));
+ m_shadow_pen_array[i+2]=(bank1[3] == 255);
+ m_palette_clut->set_pen_color(i + 3, m_palette_base->pen_color(bank1[2] + m_sprite_palette_base));
+ m_shadow_pen_array[i+3]=(bank1[2] == 255);
+
+ m_palette_clut->set_pen_color(i + 4, m_palette_base->pen_color(bank2[1] + m_sprite_palette_base));
+ m_shadow_pen_array[i+4]=(bank2[1] == 255);
+ m_palette_clut->set_pen_color(i + 5, m_palette_base->pen_color(bank2[0] + m_sprite_palette_base));
+ m_shadow_pen_array[i+5]=(bank2[0] == 255);
+ m_palette_clut->set_pen_color(i + 6, m_palette_base->pen_color(bank2[3] + m_sprite_palette_base));
+ m_shadow_pen_array[i+6]=(bank2[3] == 255);
+ m_palette_clut->set_pen_color(i + 7, m_palette_base->pen_color(bank2[2] + m_sprite_palette_base));
+ m_shadow_pen_array[i+7]=(bank2[2] == 255);
+
+ bank1+=4;
+ bank2+=4;
+ }
+}