trunk/src/mame/video/vsystem_spr.c
| r18502 | r18503 | |
| 15 | 15 | // Tecmo World Cup '94 |
| 16 | 16 | // Tao Taido |
| 17 | 17 | |
| 18 | /* old notes */ |
| 19 | |
| 20 | /*** Fujitsu CG10103 **********************************************/ |
| 21 | |
| 22 | /* |
| 23 | Fujitsu CG10103 sprite generator |
| 24 | -------------------------------- |
| 25 | |
| 26 | - Tile based |
| 27 | - 16x16 4bpp tiles |
| 28 | - Up to 7x7 in each block |
| 29 | - 5 bit of palette selection for the mixer |
| 30 | - Scaling (x/y) |
| 31 | - Flipping |
| 32 | - Indipendent sorting list |
| 33 | - 1 bit of pri for the mixer |
| 34 | |
| 35 | Note that this chip can be connected to a VS9210 which adds a level of indirection for |
| 36 | tile numbers. Basically, the VS9210 indirects the tilet number through a table in its attached |
| 37 | memory, before accessing the ROMs. |
| 38 | |
| 39 | |
| 40 | Sorting list format (VideoRAM offset 0) |
| 41 | --------------------------------------- |
| 42 | |
| 43 | de-- ---f ssss ssss |
| 44 | |
| 45 | e=end of list |
| 46 | f=sprite present in this position |
| 47 | s=sprite index |
| 48 | d=disable sprite? |
| 49 | |
| 50 | |
| 51 | TODO: |
| 52 | Priorities should be right, but they probably need to be orthogonal with the mixer priorities. |
| 53 | Zoom factor is not correct, the scale is probably non-linear |
| 54 | Horizontal wrapping is just a hack. The chip probably calculates if it needs to draw the sprite at the |
| 55 | normal position, or wrapped along X/Y. |
| 56 | Abstracts the VS9210 |
| 57 | |
| 58 | */ |
| 59 | |
| 60 | |
| 61 | |
| 18 | 62 | #include "emu.h" |
| 19 | 63 | #include "vsystem_spr.h" |
| 20 | 64 | |
| 65 | /* game specific tile indirection callbacks for different HW hookups */ |
| 66 | UINT32 inufuku_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 67 | { |
| 68 | return ((lookupram1[code*2] & 0x0007) << 16) + lookupram1[(code*2)+ 1]; |
| 69 | } |
| 21 | 70 | |
| 71 | UINT32 suprslam_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 72 | { |
| 73 | return lookupram1[code]; |
| 74 | } |
| 75 | |
| 76 | UINT32 crshrace_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 77 | { |
| 78 | return lookupram1[code&0x7fff]; |
| 79 | } |
| 80 | |
| 81 | UINT32 f1gp2_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 82 | { |
| 83 | return lookupram1[code&0x3fff]; |
| 84 | } |
| 85 | |
| 86 | UINT32 gstriker_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 87 | { |
| 88 | // straight through |
| 89 | return code; |
| 90 | } |
| 91 | |
| 92 | UINT32 taotaido_tile_callback( UINT32 code, UINT16* lookupram1, UINT16* lookupram2 ) |
| 93 | { |
| 94 | code = lookupram1[code&0x7fff]; |
| 95 | |
| 96 | if (code > 0x3fff) |
| 97 | { |
| 98 | int block = (code & 0x3800)>>11; |
| 99 | code &= 0x07ff; |
| 100 | code |= lookupram2[block] * 0x800; |
| 101 | } |
| 102 | |
| 103 | return code; |
| 104 | } |
| 105 | |
| 106 | |
| 22 | 107 | const device_type VSYSTEM_SPR = &device_creator<vsystem_spr_device>; |
| 23 | 108 | |
| 24 | 109 | vsystem_spr_device::vsystem_spr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 25 | 110 | : device_t(mconfig, VSYSTEM_SPR, "vsystem_spr_device", tag, owner, clock) |
| 26 | 111 | { |
| 112 | m_CG10103.transpen = 15; |
| 113 | m_CG10103.pal_base = 0; |
| 114 | |
| 27 | 115 | } |
| 28 | 116 | |
| 29 | 117 | |
| r18502 | r18503 | |
| 40 | 128 | |
| 41 | 129 | void vsystem_spr_device::get_sprite_attributes(UINT16* ram) |
| 42 | 130 | { |
| 43 | | /* |
| 44 | | attr_start + 0x0000 |
| 45 | | ---- ---x xxxx xxxx oy |
| 46 | | ---- xxx- ---- ---- ysize |
| 47 | | xxxx ---- ---- ---- zoomy |
| 131 | /* |
| 132 | attr_start + 0x0000 |
| 133 | ---- ---x xxxx xxxx oy |
| 134 | ---- xxx- ---- ---- ysize |
| 135 | xxxx ---- ---- ---- zoomy |
| 48 | 136 | |
| 49 | | attr_start + 0x0001 |
| 50 | | ---- ---x xxxx xxxx ox |
| 51 | | ---- xxx- ---- ---- xsize |
| 52 | | xxxx ---- ---- ---- zoomx |
| 137 | attr_start + 0x0001 |
| 138 | ---- ---x xxxx xxxx ox |
| 139 | ---- xxx- ---- ---- xsize |
| 140 | xxxx ---- ---- ---- zoomx |
| 53 | 141 | |
| 54 | | attr_start + 0x0002 |
| 55 | | -x-- ---- ---- ---- flipx |
| 56 | | x--- ---- ---- ---- flipy |
| 57 | | --xx xxxx ---- ---- color |
| 58 | | --xx ---- ---- ---- priority? (upper color bits) |
| 59 | | ---- ---- ---- ---x map start (msb) |
| 142 | attr_start + 0x0002 |
| 143 | -x-- ---- ---- ---- flipx |
| 144 | x--- ---- ---- ---- flipy |
| 145 | --xx xxxx ---- ---- color |
| 146 | --xx ---- ---- ---- priority? (upper color bits) |
| 147 | ---- ---- ---- ---x map start (msb) |
| 60 | 148 | |
| 61 | | attr_start + 0x0003 |
| 62 | | xxxx xxxx xxxx xxxx map start (lsb) |
| 63 | | */ |
| 149 | attr_start + 0x0003 |
| 150 | xxxx xxxx xxxx xxxx map start (lsb) |
| 151 | */ |
| 64 | 152 | |
| 65 | | curr_sprite.oy = (ram[0] & 0x01ff); |
| 66 | | curr_sprite.ysize = (ram[0] & 0x0e00) >> 9; |
| 67 | | curr_sprite.zoomy = (ram[0] & 0xf000) >> 12; |
| 153 | curr_sprite.oy = (ram[0] & 0x01ff); |
| 154 | curr_sprite.ysize = (ram[0] & 0x0e00) >> 9; |
| 155 | curr_sprite.zoomy = (ram[0] & 0xf000) >> 12; |
| 68 | 156 | |
| 69 | | curr_sprite.ox = (ram[1] & 0x01ff); |
| 70 | | curr_sprite.xsize = (ram[1] & 0x0e00) >> 9; |
| 71 | | curr_sprite.zoomx = (ram[1] & 0xf000) >> 12; |
| 157 | curr_sprite.ox = (ram[1] & 0x01ff); |
| 158 | curr_sprite.xsize = (ram[1] & 0x0e00) >> 9; |
| 159 | curr_sprite.zoomx = (ram[1] & 0xf000) >> 12; |
| 72 | 160 | |
| 73 | | curr_sprite.flipx = (ram[2] & 0x4000); |
| 74 | | curr_sprite.flipy = (ram[2] & 0x8000); |
| 75 | | curr_sprite.color = (ram[2] & 0x3f00) >> 8; |
| 76 | | curr_sprite.pri = (ram[2] & 0x3000) >> 12; |
| 77 | | curr_sprite.map = (ram[2] & 0x0001) << 16; |
| 161 | curr_sprite.flipx = (ram[2] & 0x4000); |
| 162 | curr_sprite.flipy = (ram[2] & 0x8000); |
| 163 | curr_sprite.color = (ram[2] & 0x3f00) >> 8; |
| 164 | curr_sprite.pri = (ram[2] & 0x3000) >> 12; |
| 165 | curr_sprite.map = (ram[2] & 0x0001) << 16; |
| 78 | 166 | |
| 79 | | curr_sprite.map |= (ram[3] & 0xffff); |
| 167 | curr_sprite.map |= (ram[3] & 0xffff); |
| 168 | } |
| 80 | 169 | |
| 170 | |
| 171 | void vsystem_spr_device::common_sprite_drawgfx(int gfxrgn, UINT16* spriteram2, UINT16* spriteram3, vsystem_spr_tile_indirection_callback tilecb, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 172 | { |
| 173 | gfx_element *gfx = machine.gfx[gfxrgn]; |
| 174 | |
| 175 | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 176 | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 177 | |
| 178 | int ystart, yend, yinc; |
| 179 | |
| 180 | if (!curr_sprite.flipy) { ystart = 0; yend = curr_sprite.ysize+1; yinc = 1; } |
| 181 | else { ystart = curr_sprite.ysize; yend = -1; yinc = -1; } |
| 182 | |
| 183 | int ycnt = ystart; |
| 184 | while (ycnt != yend) |
| 185 | { |
| 186 | int xstart, xend, xinc; |
| 187 | |
| 188 | if (!curr_sprite.flipx) { xstart = 0; xend = curr_sprite.xsize+1; xinc = 1; } |
| 189 | else { xstart = curr_sprite.xsize; xend = -1; xinc = -1; } |
| 190 | |
| 191 | int xcnt = xstart; |
| 192 | while (xcnt != xend) |
| 193 | { |
| 194 | int startno = tilecb(curr_sprite.map++, spriteram2, spriteram3); |
| 195 | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, m_CG10103.transpen); |
| 196 | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, -0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, m_CG10103.transpen); |
| 197 | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, curr_sprite.ox + xcnt * curr_sprite.zoomx/2, -0x200+curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, m_CG10103.transpen); |
| 198 | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, -0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, -0x200+curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, m_CG10103.transpen); |
| 199 | xcnt+=xinc; |
| 200 | } |
| 201 | ycnt+=yinc; |
| 202 | } |
| 203 | |
| 81 | 204 | } |
| 82 | 205 | |
| 83 | | // zooming is wrong for 3on3dunk ... suprslam implementation is probably better |
| 206 | // same as above but for pdrawgfx implementations |
| 207 | void vsystem_spr_device::common_sprite_pdrawgfx(int gfxrgn, UINT16* spriteram2, UINT16* spriteram3, vsystem_spr_tile_indirection_callback tilecb, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 208 | { |
| 209 | gfx_element *gfx = machine.gfx[gfxrgn]; |
| 210 | int priority_mask; |
| 211 | |
| 212 | switch (curr_sprite.pri) |
| 213 | { |
| 214 | default: |
| 215 | case 0: priority_mask = 0x00; break; |
| 216 | case 3: priority_mask = 0xfe; break; |
| 217 | case 2: priority_mask = 0xfc; break; |
| 218 | case 1: priority_mask = 0xf0; break; |
| 219 | } |
| 220 | |
| 221 | |
| 222 | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 223 | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 224 | |
| 225 | int ystart, yend, yinc; |
| 226 | |
| 227 | if (!curr_sprite.flipy) { ystart = 0; yend = curr_sprite.ysize+1; yinc = 1; } |
| 228 | else { ystart = curr_sprite.ysize; yend = -1; yinc = -1; } |
| 229 | |
| 230 | int ycnt = ystart; |
| 231 | while (ycnt != yend) |
| 232 | { |
| 233 | int xstart, xend, xinc; |
| 234 | |
| 235 | if (!curr_sprite.flipx) { xstart = 0; xend = curr_sprite.xsize+1; xinc = 1; } |
| 236 | else { xstart = curr_sprite.xsize; xend = -1; xinc = -1; } |
| 237 | |
| 238 | int xcnt = xstart; |
| 239 | while (xcnt != xend) |
| 240 | { |
| 241 | int startno = tilecb(curr_sprite.map++, spriteram2, spriteram3); |
| 242 | pdrawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, machine.priority_bitmap,priority_mask, m_CG10103.transpen); |
| 243 | pdrawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, -0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, machine.priority_bitmap,priority_mask, m_CG10103.transpen); |
| 244 | pdrawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, curr_sprite.ox + xcnt * curr_sprite.zoomx/2, -0x200+curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, machine.priority_bitmap,priority_mask, m_CG10103.transpen); |
| 245 | pdrawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color + m_CG10103.pal_base, curr_sprite.flipx, curr_sprite.flipy, -0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, -0x200+curr_sprite.oy + ycnt * curr_sprite.zoomy/2, curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, machine.priority_bitmap,priority_mask, m_CG10103.transpen); |
| 246 | xcnt+=xinc; |
| 247 | } |
| 248 | ycnt+=yinc; |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | |
| 84 | 253 | void vsystem_spr_device::draw_sprites_inufuku( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 85 | 254 | { |
| 86 | 255 | int offs; |
| r18502 | r18503 | |
| 97 | 266 | if ((spriteram[offs] & 0x8000) == 0x0000) |
| 98 | 267 | { |
| 99 | 268 | int attr_start; |
| 100 | | int x, y; |
| 101 | | int priority_mask; |
| 102 | 269 | |
| 103 | 270 | attr_start = 4 * (spriteram[offs] & 0x03ff); |
| 104 | 271 | |
| 105 | 272 | get_sprite_attributes(&spriteram[attr_start]); |
| 106 | 273 | |
| 107 | | curr_sprite.oy += 1; |
| 274 | // curr_sprite.oy += 1; |
| 108 | 275 | curr_sprite.map &= 0x7fff; |
| 109 | 276 | |
| 110 | | switch (curr_sprite.pri) |
| 111 | | { |
| 112 | | default: |
| 113 | | case 0: priority_mask = 0x00; break; |
| 114 | | case 3: priority_mask = 0xfe; break; |
| 115 | | case 2: priority_mask = 0xfc; break; |
| 116 | | case 1: priority_mask = 0xf0; break; |
| 117 | | } |
| 118 | | |
| 119 | | curr_sprite.ox += (curr_sprite.xsize * curr_sprite.zoomx + 2) / 4; |
| 120 | | curr_sprite.oy += (curr_sprite.ysize * curr_sprite.zoomy + 2) / 4; |
| 121 | | |
| 122 | | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 123 | | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 124 | | |
| 125 | | for (y = 0; y <= curr_sprite.ysize; y++) |
| 126 | | { |
| 127 | | int sx, sy; |
| 128 | | |
| 129 | | if (curr_sprite.flipy) |
| 130 | | sy = (curr_sprite.oy + curr_sprite.zoomy * (curr_sprite.ysize - y) / 2 + 16) & 0x1ff; |
| 131 | | else |
| 132 | | sy = (curr_sprite.oy + curr_sprite.zoomy * y / 2 + 16) & 0x1ff; |
| 133 | | |
| 134 | | for (x = 0; x <= curr_sprite.xsize; x++) |
| 135 | | { |
| 136 | | int code; |
| 137 | | |
| 138 | | if (curr_sprite.flipx) |
| 139 | | sx = (curr_sprite.ox + curr_sprite.zoomx * (curr_sprite.xsize - x) / 2 + 16) & 0x1ff; |
| 140 | | else |
| 141 | | sx = (curr_sprite.ox + curr_sprite.zoomx * x / 2 + 16) & 0x1ff; |
| 142 | | |
| 143 | | code = ((spriteram2[curr_sprite.map*2] & 0x0007) << 16) + spriteram2[(curr_sprite.map*2)+ 1]; |
| 144 | | |
| 145 | | pdrawgfxzoom_transpen(bitmap, cliprect, machine.gfx[2], |
| 146 | | code, |
| 147 | | curr_sprite.color, |
| 148 | | curr_sprite.flipx, curr_sprite.flipy, |
| 149 | | sx - 16, sy - 16, |
| 150 | | curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, |
| 151 | | machine.priority_bitmap,priority_mask, 15); |
| 152 | | |
| 153 | | curr_sprite.map ++; |
| 154 | | } |
| 155 | | } |
| 277 | common_sprite_pdrawgfx(2, spriteram2, NULL, inufuku_tile_callback, machine, bitmap, cliprect); |
| 156 | 278 | } |
| 157 | 279 | } |
| 158 | 280 | } |
| 159 | 281 | |
| 160 | 282 | |
| 161 | | |
| 162 | | /* todo, fix zooming correctly, it's _not_ like aerofgt */ |
| 163 | 283 | void vsystem_spr_device::draw_sprites_suprslam( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 164 | 284 | { |
| 165 | | gfx_element *gfx = machine.gfx[1]; |
| 166 | 285 | UINT16 *source = spriteram; |
| 167 | 286 | UINT16 *source2 = spriteram; |
| 168 | 287 | UINT16 *finish = source + 0x2000/2; |
| r18502 | r18503 | |
| 171 | 290 | { |
| 172 | 291 | UINT32 sprnum = source[0] & 0x03ff; |
| 173 | 292 | if (source[0] == 0x4000) break; |
| 174 | | |
| 175 | 293 | sprnum *= 4; |
| 176 | | |
| 177 | 294 | source++; |
| 178 | | /* DRAW START */ |
| 179 | | { |
| 180 | | get_sprite_attributes(&source2[sprnum]); |
| 181 | 295 | |
| 182 | | curr_sprite.map &= 0x7fff; |
| 183 | | |
| 184 | | int xcnt, ycnt; |
| 185 | 296 | |
| 186 | | int loopno = 0; |
| 297 | get_sprite_attributes(&source2[sprnum]); |
| 187 | 298 | |
| 188 | | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 189 | | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 299 | curr_sprite.map &= 0x7fff; |
| 190 | 300 | |
| 191 | | if (curr_sprite.oy > 0xff) curr_sprite.oy -=0x200; |
| 192 | | |
| 193 | | for (ycnt = 0; ycnt < curr_sprite.ysize+1; ycnt ++) |
| 194 | | { |
| 195 | | if (!curr_sprite.flipx) |
| 196 | | { |
| 197 | | for (xcnt = 0; xcnt < curr_sprite.xsize+1; xcnt ++) |
| 198 | | { |
| 199 | | int startno = spriteram2[curr_sprite.map + loopno]; |
| 200 | | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color, 0, 0,curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2,curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, 15); |
| 201 | | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color, 0, 0,-0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2,curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, 15); |
| 202 | | loopno ++; |
| 203 | | } |
| 204 | | } |
| 205 | | else |
| 206 | | { |
| 207 | | for (xcnt = curr_sprite.xsize; xcnt >= 0; xcnt --) |
| 208 | | { |
| 209 | | int startno = spriteram2[curr_sprite.map + loopno]; |
| 210 | | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color, 1, 0,curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2,curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, 15); |
| 211 | | drawgfxzoom_transpen(bitmap, cliprect, gfx, startno, curr_sprite.color, 1, 0,-0x200+curr_sprite.ox + xcnt * curr_sprite.zoomx/2, curr_sprite.oy + ycnt * curr_sprite.zoomy/2,curr_sprite.zoomx << 11, curr_sprite.zoomy << 11, 15); |
| 212 | | loopno ++; |
| 213 | | } |
| 214 | | } |
| 215 | | } |
| 216 | | } |
| 301 | common_sprite_drawgfx(1, spriteram2, NULL, suprslam_tile_callback, machine, bitmap, cliprect); |
| 217 | 302 | } |
| 218 | 303 | } |
| 219 | 304 | |
| r18502 | r18503 | |
| 221 | 306 | |
| 222 | 307 | void vsystem_spr_device::draw_sprite_taotaido( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, UINT16* spriteram3, running_machine &machine, UINT16 spriteno, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 223 | 308 | { |
| 224 | | /*- SPR RAM Format -** |
| 225 | | |
| 226 | | 4 words per sprite |
| 227 | | |
| 228 | | zzzz sssp pppp pppp (y zoom, y size, y position) |
| 229 | | zzzz sssp pppp pppp (x zoom, x size, x position) |
| 230 | | yxpc cccc ---- ---- (flipy, >flipx, priority?, color) |
| 231 | | -nnn nnnn nnnn nnnn (map_start lookup) |
| 232 | | |
| 233 | | */ |
| 234 | | |
| 235 | | int x,y; |
| 236 | | |
| 237 | 309 | UINT16 *source = &spriteram[spriteno*4]; |
| 238 | | gfx_element *gfx = machine.gfx[0]; |
| 239 | 310 | |
| 240 | 311 | get_sprite_attributes(&source[0]); |
| 241 | 312 | |
| 242 | 313 | curr_sprite.map &= 0xffff; |
| 243 | 314 | curr_sprite.color &= 0x1f; |
| 244 | 315 | |
| 245 | | curr_sprite.ox += (curr_sprite.xsize*curr_sprite.zoomx+2)/4; |
| 246 | | curr_sprite.oy += (curr_sprite.ysize*curr_sprite.zoomy+2)/4; |
| 247 | | |
| 248 | | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 249 | | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 250 | | |
| 251 | | |
| 252 | | for (y = 0;y <= curr_sprite.ysize;y++) |
| 253 | | { |
| 254 | | int sx,sy; |
| 255 | | |
| 256 | | if (curr_sprite.flipy) sy = ((curr_sprite.oy + curr_sprite.zoomy * (curr_sprite.ysize - y)/2 + 16) & 0x1ff) - 16; |
| 257 | | else sy = ((curr_sprite.oy + curr_sprite.zoomy * y / 2 + 16) & 0x1ff) - 16; |
| 258 | | |
| 259 | | for (x = 0;x <= curr_sprite.xsize;x++) |
| 260 | | { |
| 261 | | |
| 262 | | /* this indirection is a bit different to the other video system games */ |
| 263 | | int realstart; |
| 264 | | |
| 265 | | realstart = spriteram2[curr_sprite.map&0x7fff]; |
| 266 | | |
| 267 | | if (realstart > 0x3fff) |
| 268 | | { |
| 269 | | int block; |
| 270 | | |
| 271 | | block = (realstart & 0x3800)>>11; |
| 272 | | |
| 273 | | realstart &= 0x07ff; |
| 274 | | realstart |= spriteram3[block] * 0x800; |
| 275 | | } |
| 276 | | |
| 277 | | if (curr_sprite.flipx) sx = ((curr_sprite.ox + curr_sprite.zoomx * (curr_sprite.xsize - x) / 2 + 16) & 0x1ff) - 16; |
| 278 | | else sx = ((curr_sprite.ox + curr_sprite.zoomx * x / 2 + 16) & 0x1ff) - 16; |
| 279 | | |
| 280 | | |
| 281 | | drawgfxzoom_transpen(bitmap,cliprect,gfx, |
| 282 | | realstart, |
| 283 | | curr_sprite.color, |
| 284 | | curr_sprite.flipx,curr_sprite.flipy, |
| 285 | | sx,sy, |
| 286 | | curr_sprite.zoomx << 11, curr_sprite.zoomy << 11,15); |
| 287 | | |
| 288 | | curr_sprite.map++; |
| 289 | | |
| 290 | | } |
| 291 | | } |
| 316 | common_sprite_drawgfx(0, spriteram2, spriteram3, taotaido_tile_callback, machine, bitmap, cliprect); |
| 292 | 317 | } |
| 293 | 318 | |
| 294 | 319 | void vsystem_spr_device::draw_sprites_taotaido( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, UINT16* spriteram3, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| r18502 | r18503 | |
| 316 | 341 | while (offs < 0x0400 && (spriteram[offs] & 0x4000) == 0) |
| 317 | 342 | { |
| 318 | 343 | int attr_start; |
| 319 | | int x, y; |
| 320 | | /* table hand made by looking at the ship explosion in aerofgt attract mode */ |
| 321 | | /* it's almost a logarithmic scale but not exactly */ |
| 322 | | static const int zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; |
| 323 | 344 | |
| 324 | 345 | attr_start = 4 * (spriteram[offs++] & 0x03ff); |
| 325 | 346 | |
| r18502 | r18503 | |
| 328 | 349 | curr_sprite.color &= 0x1f; |
| 329 | 350 | curr_sprite.map &= 0x7fff; |
| 330 | 351 | |
| 331 | | curr_sprite.zoomx = 16 - zoomtable[curr_sprite.zoomx] / 8; |
| 332 | | curr_sprite.zoomy = 16 - zoomtable[curr_sprite.zoomy] / 8; |
| 333 | | |
| 334 | | if (spriteram[attr_start + 2] & 0x20ff) curr_sprite.color = machine.rand(); |
| 335 | | |
| 336 | | for (y = 0; y <= curr_sprite.ysize; y++) |
| 337 | | { |
| 338 | | int sx,sy; |
| 339 | | |
| 340 | | if (curr_sprite.flipy) sy = ((curr_sprite.oy + curr_sprite.zoomy * (curr_sprite.ysize - y) + 16) & 0x1ff) - 16; |
| 341 | | else sy = ((curr_sprite.oy + curr_sprite.zoomy * y + 16) & 0x1ff) - 16; |
| 342 | | |
| 343 | | for (x = 0; x <= curr_sprite.xsize; x++) |
| 344 | | { |
| 345 | | int code; |
| 346 | | |
| 347 | | if (curr_sprite.flipx) sx = ((curr_sprite.ox + curr_sprite.zoomx * (curr_sprite.xsize - x) + 16) & 0x1ff) - 16; |
| 348 | | else sx = ((curr_sprite.ox + curr_sprite.zoomx * x + 16) & 0x1ff) - 16; |
| 349 | | |
| 350 | | code = spriteram2[curr_sprite.map & 0x7fff]; |
| 351 | | curr_sprite.map++; |
| 352 | | |
| 353 | | if (flipscreen) |
| 354 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 355 | | code, |
| 356 | | curr_sprite.color, |
| 357 | | !curr_sprite.flipx,!curr_sprite.flipy, |
| 358 | | 304-sx,208-sy, |
| 359 | | 0x1000 * curr_sprite.zoomx,0x1000 * curr_sprite.zoomy,15); |
| 360 | | else |
| 361 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 362 | | code, |
| 363 | | curr_sprite.color, |
| 364 | | curr_sprite.flipx,curr_sprite.flipy, |
| 365 | | sx,sy, |
| 366 | | 0x1000 * curr_sprite.zoomx,0x1000 * curr_sprite.zoomy,15); |
| 367 | | } |
| 368 | | } |
| 352 | common_sprite_drawgfx(2, spriteram2, NULL, crshrace_tile_callback, machine, bitmap, cliprect); |
| 369 | 353 | } |
| 370 | 354 | } |
| 371 | 355 | |
| r18502 | r18503 | |
| 384 | 368 | /* is the way I handle pri correct? Or should I just check bit 13? */ |
| 385 | 369 | if ((spriteram3[attr_start + 2] & 0x3000) == pri) |
| 386 | 370 | { |
| 387 | | int x, y; |
| 388 | | |
| 389 | 371 | get_sprite_attributes(&spriteram3[attr_start]); |
| 390 | 372 | |
| 391 | | curr_sprite.color &=0xf; |
| 373 | curr_sprite.color &=0x1f; |
| 392 | 374 | curr_sprite.map &= 0x3fff; |
| 393 | | curr_sprite.ox += (curr_sprite.xsize * curr_sprite.zoomx + 2) / 4; |
| 394 | | curr_sprite.oy += (curr_sprite.ysize * curr_sprite.zoomy + 2) / 4; |
| 375 | |
| 376 | common_sprite_drawgfx(2, spriteram1, NULL, crshrace_tile_callback, machine, bitmap, cliprect); |
| 395 | 377 | |
| 396 | | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 397 | | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 398 | | |
| 399 | | for (y = 0; y <= curr_sprite.ysize; y++) |
| 400 | | { |
| 401 | | int sx, sy; |
| 402 | | |
| 403 | | if (curr_sprite.flipy) |
| 404 | | sy = ((curr_sprite.oy + curr_sprite.zoomy * (curr_sprite.ysize - y)/2 + 16) & 0x1ff) - 16; |
| 405 | | else |
| 406 | | sy = ((curr_sprite.oy + curr_sprite.zoomy * y / 2 + 16) & 0x1ff) - 16; |
| 407 | | |
| 408 | | for (x = 0; x <= curr_sprite.xsize; x++) |
| 409 | | { |
| 410 | | int code; |
| 411 | | |
| 412 | | if (curr_sprite.flipx) |
| 413 | | sx = ((curr_sprite.ox + curr_sprite.zoomx * (curr_sprite.xsize - x) / 2 + 16) & 0x1ff) - 16; |
| 414 | | else |
| 415 | | sx = ((curr_sprite.ox + curr_sprite.zoomx * x / 2 + 16) & 0x1ff) - 16; |
| 416 | | |
| 417 | | if (curr_sprite.map < 0x2000) |
| 418 | | code = spriteram1[curr_sprite.map & 0x1fff] & 0x1fff; |
| 419 | | else |
| 420 | | code = spriteram2[curr_sprite.map & 0x1fff] & 0x1fff; |
| 421 | | |
| 422 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2 + (curr_sprite.map >= 0x2000 ? 1 : 0)], |
| 423 | | code, |
| 424 | | curr_sprite.color, |
| 425 | | curr_sprite.flipx,curr_sprite.flipy, |
| 426 | | sx,sy, |
| 427 | | curr_sprite.zoomx << 11, curr_sprite.zoomy << 11,15); |
| 428 | | curr_sprite.map++; |
| 429 | | } |
| 430 | | } |
| 431 | 378 | } |
| 432 | 379 | offs++; |
| 433 | 380 | } |
| r18502 | r18503 | |
| 442 | 389 | while (offs < 0x0400 && (spritelist[offs] & 0x4000) == 0) |
| 443 | 390 | { |
| 444 | 391 | int attr_start; |
| 445 | | int x, y; |
| 446 | 392 | |
| 447 | 393 | attr_start = 4 * (spritelist[offs++] & 0x01ff); |
| 448 | 394 | |
| r18502 | r18503 | |
| 451 | 397 | curr_sprite.color &= 0x1f; |
| 452 | 398 | curr_sprite.map &= 0x7fff; |
| 453 | 399 | |
| 454 | | // aerofgt has the following adjustment, but doing it here would break the title screen |
| 455 | | // curr_sprite.ox += (curr_sprite.xsize*curr_sprite.zoomx+2)/4; |
| 456 | | // curr_sprite.oy += (curr_sprite.ysize*curr_sprite.zoomy+2)/4; |
| 457 | | |
| 458 | | curr_sprite.zoomx = 32 - curr_sprite.zoomx; |
| 459 | | curr_sprite.zoomy = 32 - curr_sprite.zoomy; |
| 460 | | |
| 461 | | if (spritelist[attr_start + 2] & 0x20ff) |
| 462 | | curr_sprite.color = machine.rand(); |
| 463 | | |
| 464 | | for (y = 0; y <= curr_sprite.ysize; y++) |
| 465 | | { |
| 466 | | int sx,sy; |
| 467 | | |
| 468 | | if (curr_sprite.flipy) sy = ((curr_sprite.oy + curr_sprite.zoomy * (curr_sprite.ysize - y)/2 + 16) & 0x1ff) - 16; |
| 469 | | else sy = ((curr_sprite.oy + curr_sprite.zoomy * y / 2 + 16) & 0x1ff) - 16; |
| 470 | | |
| 471 | | for (x = 0; x <= curr_sprite.xsize; x++) |
| 472 | | { |
| 473 | | int code; |
| 474 | | |
| 475 | | if (curr_sprite.flipx) sx = ((curr_sprite.ox + curr_sprite.zoomx * (curr_sprite.xsize - x) / 2 + 16) & 0x1ff) - 16; |
| 476 | | else sx = ((curr_sprite.ox + curr_sprite.zoomx * x / 2 + 16) & 0x1ff) - 16; |
| 477 | | |
| 478 | | code = sprcgram[curr_sprite.map & 0x3fff]; |
| 479 | | curr_sprite.map++; |
| 480 | | |
| 481 | | if (flipscreen) |
| 482 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[1], |
| 483 | | code, |
| 484 | | curr_sprite.color, |
| 485 | | !curr_sprite.flipx,!curr_sprite.flipy, |
| 486 | | 304-sx,208-sy, |
| 487 | | curr_sprite.zoomx << 11,curr_sprite.zoomy << 11,15); |
| 488 | | else |
| 489 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[1], |
| 490 | | code, |
| 491 | | curr_sprite.color, |
| 492 | | curr_sprite.flipx,curr_sprite.flipy, |
| 493 | | sx,sy, |
| 494 | | curr_sprite.zoomx << 11,curr_sprite.zoomy << 11,15); |
| 495 | | } |
| 496 | | } |
| 400 | common_sprite_drawgfx(1, sprcgram, NULL, f1gp2_tile_callback, machine, bitmap, cliprect); |
| 497 | 401 | } |
| 498 | 402 | } |
| 499 | 403 | |
| 500 | 404 | |
| 501 | | /*** Fujitsu CG10103 **********************************************/ |
| 502 | | |
| 503 | | /* |
| 504 | | Fujitsu CG10103 sprite generator |
| 505 | | -------------------------------- |
| 506 | | |
| 507 | | - Tile based |
| 508 | | - 16x16 4bpp tiles |
| 509 | | - Up to 7x7 in each block |
| 510 | | - 5 bit of palette selection for the mixer |
| 511 | | - Scaling (x/y) |
| 512 | | - Flipping |
| 513 | | - Indipendent sorting list |
| 514 | | - 1 bit of pri for the mixer |
| 515 | | |
| 516 | | Note that this chip can be connected to a VS9210 which adds a level of indirection for |
| 517 | | tile numbers. Basically, the VS9210 indirects the tilet number through a table in its attached |
| 518 | | memory, before accessing the ROMs. |
| 519 | | |
| 520 | | |
| 521 | | Sorting list format (VideoRAM offset 0) |
| 522 | | --------------------------------------- |
| 523 | | |
| 524 | | de-- ---f ssss ssss |
| 525 | | |
| 526 | | e=end of list |
| 527 | | f=sprite present in this position |
| 528 | | s=sprite index |
| 529 | | d=disable sprite? |
| 530 | | |
| 531 | | |
| 532 | | TODO: |
| 533 | | Priorities should be right, but they probably need to be orthogonal with the mixer priorities. |
| 534 | | Zoom factor is not correct, the scale is probably non-linear |
| 535 | | Horizontal wrapping is just a hack. The chip probably calculates if it needs to draw the sprite at the |
| 536 | | normal position, or wrapped along X/Y. |
| 537 | | Abstracts the VS9210 |
| 538 | | |
| 539 | | */ |
| 540 | | |
| 541 | | |
| 542 | | void vsystem_spr_device::CG10103_draw_sprite(running_machine &machine, bitmap_ind16& screen, const rectangle &cliprect, UINT16* spr, int drawpri) |
| 405 | void vsystem_spr_device::CG10103_draw_sprite(running_machine &machine, bitmap_ind16& bitmap, const rectangle &cliprect, UINT16* spr, int drawpri) |
| 543 | 406 | { |
| 544 | 407 | get_sprite_attributes(&spr[0]); |
| 545 | 408 | curr_sprite.color &=0x1f; |
| 546 | 409 | curr_sprite.pri >>= 1; |
| 547 | 410 | |
| 548 | | int x, y; |
| 549 | | int xstep, ystep; |
| 550 | | int xfact, yfact; |
| 551 | | |
| 552 | | |
| 553 | 411 | // Check if we want to draw this sprite now |
| 554 | 412 | if (curr_sprite.pri != drawpri) |
| 555 | 413 | return; |
| 556 | 414 | |
| 557 | | // Convert in fixed point to handle the scaling |
| 558 | | curr_sprite.ox <<= 16; |
| 559 | | curr_sprite.oy <<= 16; |
| 560 | | |
| 561 | | curr_sprite.xsize++; |
| 562 | | curr_sprite.ysize++; |
| 563 | | xstep = ystep = 16; |
| 564 | | |
| 565 | | // Linear scale, surely wrong |
| 566 | | xfact = 0x10000 - ((0x8000 * curr_sprite.zoomx) / 15); |
| 567 | | yfact = 0x10000 - ((0x8000 * curr_sprite.zoomy) / 15); |
| 568 | | |
| 569 | | xstep *= xfact; |
| 570 | | ystep *= yfact; |
| 571 | | |
| 572 | | // Handle flipping |
| 573 | | if (curr_sprite.flipy) |
| 574 | | { |
| 575 | | curr_sprite.oy += (curr_sprite.ysize-1) * ystep; |
| 576 | | ystep = -ystep; |
| 577 | | } |
| 578 | | |
| 579 | | if (curr_sprite.flipx) |
| 580 | | { |
| 581 | | curr_sprite.ox += (curr_sprite.xsize-1) * xstep; |
| 582 | | xstep = -xstep; |
| 583 | | } |
| 584 | | |
| 585 | | // Draw the block |
| 586 | | for (y=0;y<curr_sprite.ysize;y++) |
| 587 | | { |
| 588 | | int xp = curr_sprite.ox; |
| 589 | | |
| 590 | | for (x=0;x<curr_sprite.xsize;x++) |
| 591 | | { |
| 592 | | // Hack to handle horizontal wrapping |
| 593 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], curr_sprite.map, curr_sprite.color+m_CG10103_cur_chip->pal_base, curr_sprite.flipx, curr_sprite.flipy, xp>>16, curr_sprite.oy>>16, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 594 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], curr_sprite.map, curr_sprite.color+m_CG10103_cur_chip->pal_base, curr_sprite.flipx, curr_sprite.flipy, (xp>>16) - 0x200, curr_sprite.oy>>16, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 595 | | |
| 596 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], curr_sprite.map, curr_sprite.color+m_CG10103_cur_chip->pal_base, curr_sprite.flipx, curr_sprite.flipy, xp>>16, (curr_sprite.oy>>16)-0x200, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 597 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], curr_sprite.map, curr_sprite.color+m_CG10103_cur_chip->pal_base, curr_sprite.flipx, curr_sprite.flipy, (xp>>16) - 0x200, (curr_sprite.oy>>16)-0x200, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 598 | | |
| 599 | | xp += xstep; |
| 600 | | curr_sprite.map++; |
| 601 | | } |
| 602 | | |
| 603 | | curr_sprite.oy += ystep; |
| 604 | | } |
| 415 | common_sprite_drawgfx(m_CG10103.gfx_region, NULL, NULL, gstriker_tile_callback, machine, bitmap, cliprect); |
| 605 | 416 | } |
| 606 | 417 | |
| 607 | 418 | |
| r18502 | r18503 | |
| 610 | 421 | UINT16* splist; |
| 611 | 422 | int i; |
| 612 | 423 | |
| 613 | | m_CG10103_cur_chip = &m_CG10103; |
| 424 | splist = m_CG10103.vram; |
| 614 | 425 | |
| 615 | | splist = m_CG10103_cur_chip->vram; |
| 616 | | |
| 617 | 426 | // Parse the sorting list |
| 618 | 427 | for (i=0;i<0x400;i++) |
| 619 | 428 | { |
| r18502 | r18503 | |
| 629 | 438 | int num = cmd & 0x3FF; |
| 630 | 439 | |
| 631 | 440 | // Draw the sprite |
| 632 | | CG10103_draw_sprite(machine, screen, cliprect, m_CG10103_cur_chip->vram + num*4, pri); |
| 441 | CG10103_draw_sprite(machine, screen, cliprect, m_CG10103.vram + num*4, pri); |
| 633 | 442 | } |
| 634 | 443 | } |
| 635 | 444 | } |