trunk/src/mame/video/gstriker.c
| r18385 | r18386 | |
| 318 | 318 | |
| 319 | 319 | |
| 320 | 320 | |
| 321 | | /*** Fujitsu CG10103 **********************************************/ |
| 322 | 321 | |
| 323 | | /* |
| 324 | | Fujitsu CG10103 sprite generator |
| 325 | | -------------------------------- |
| 326 | 322 | |
| 327 | | - Tile based |
| 328 | | - 16x16 4bpp tiles |
| 329 | | - Up to 7x7 in each block |
| 330 | | - 5 bit of palette selection for the mixer |
| 331 | | - Scaling (x/y) |
| 332 | | - Flipping |
| 333 | | - Indipendent sorting list |
| 334 | | - 1 bit of priority for the mixer |
| 335 | | |
| 336 | | Note that this chip can be connected to a VS9210 which adds a level of indirection for |
| 337 | | tile numbers. Basically, the VS9210 indirects the tile number through a table in its attached |
| 338 | | memory, before accessing the ROMs. |
| 339 | | |
| 340 | | |
| 341 | | Sorting list format (VideoRAM offset 0) |
| 342 | | --------------------------------------- |
| 343 | | |
| 344 | | ?e-- ---f ssss ssss |
| 345 | | |
| 346 | | e=end of list |
| 347 | | f=sprite present in this position |
| 348 | | s=sprite index |
| 349 | | ?=used together with 'e' almost always |
| 350 | | |
| 351 | | |
| 352 | | Sprite format (VideoRAM offset 0x400) |
| 353 | | ------------------------------------- |
| 354 | | |
| 355 | | 0: nnnn jjjy yyyy yyyy |
| 356 | | 1: mmmm iiix xxxx xxxx |
| 357 | | 2: fFpc cccc ---- ---t |
| 358 | | 3: tttt tttt tttt tttt |
| 359 | | |
| 360 | | t=tile, x=posx, y=posy, i=blockx, j=blocky |
| 361 | | c=color, m=zoomx, n=zoomy, p=priority |
| 362 | | |
| 363 | | The zoom (scaling) is probably non-linear, it would require a hand-made table unless we find the correct |
| 364 | | formula. I'd probably try 1/x. I'm almost sure that it scales between full size (value=0) and half size |
| 365 | | (value=0xF) but I couldn't get much more than that from a soccer game. |
| 366 | | |
| 367 | | |
| 368 | | TODO: |
| 369 | | Priorities should be right, but they probably need to be orthogonal with the mixer priorities. |
| 370 | | Zoom factor is not correct, the scale is probably non-linear |
| 371 | | Horizontal wrapping is just a hack. The chip probably calculates if it needs to draw the sprite at the |
| 372 | | normal position, or wrapped along X/Y. |
| 373 | | Abstracts the VS9210 |
| 374 | | |
| 375 | | */ |
| 376 | | |
| 377 | | |
| 378 | | static void CG10103_draw_sprite(running_machine &machine, bitmap_ind16& screen, const rectangle &cliprect, UINT16* spr, int drawpri) |
| 379 | | { |
| 380 | | gstriker_state *state = machine.driver_data<gstriker_state>(); |
| 381 | | int ypos = spr[0] & 0x1FF; |
| 382 | | int xpos = (spr[1] & 0x1FF); |
| 383 | | UINT32 tile = (spr[3] & 0xFFFF) | ((spr[2] & 1) << 16); |
| 384 | | int ynum = (spr[0] >> 9) & 0x7; |
| 385 | | int xnum = (spr[1] >> 9) & 0x7; |
| 386 | | int color = (spr[2] >> 8) & 0x1F; |
| 387 | | int flipx = (spr[2] >> 14) & 1; |
| 388 | | int flipy = (spr[2] >> 15) & 1; |
| 389 | | int yzoom = (spr[0] >> 12) & 0xF; |
| 390 | | int xzoom = (spr[1] >> 12) & 0xF; |
| 391 | | int pri = (spr[2] >> 13) & 1; |
| 392 | | int x, y; |
| 393 | | int xstep, ystep; |
| 394 | | int xfact, yfact; |
| 395 | | |
| 396 | | // Check if we want to draw this sprite now |
| 397 | | if (pri != drawpri) |
| 398 | | return; |
| 399 | | |
| 400 | | // Convert in fixed point to handle the scaling |
| 401 | | xpos <<= 16; |
| 402 | | ypos <<= 16; |
| 403 | | |
| 404 | | xnum++; |
| 405 | | ynum++; |
| 406 | | xstep = ystep = 16; |
| 407 | | |
| 408 | | // Linear scale, surely wrong |
| 409 | | xfact = 0x10000 - ((0x8000 * xzoom) / 15); |
| 410 | | yfact = 0x10000 - ((0x8000 * yzoom) / 15); |
| 411 | | |
| 412 | | xstep *= xfact; |
| 413 | | ystep *= yfact; |
| 414 | | |
| 415 | | // Handle flipping |
| 416 | | if (flipy) |
| 417 | | { |
| 418 | | ypos += (ynum-1) * ystep; |
| 419 | | ystep = -ystep; |
| 420 | | } |
| 421 | | |
| 422 | | if (flipx) |
| 423 | | { |
| 424 | | xpos += (xnum-1) * xstep; |
| 425 | | xstep = -xstep; |
| 426 | | } |
| 427 | | |
| 428 | | // @@@ Add here optional connection to the VS9210 for extra level of tile number indirection |
| 429 | | #if 0 |
| 430 | | if (state->m_CG10103_cur_chip->connected_vs9210) |
| 431 | | { |
| 432 | | // ... |
| 433 | | } |
| 434 | | #endif |
| 435 | | |
| 436 | | // Draw the block |
| 437 | | for (y=0;y<ynum;y++) |
| 438 | | { |
| 439 | | int xp = xpos; |
| 440 | | |
| 441 | | for (x=0;x<xnum;x++) |
| 442 | | { |
| 443 | | // Hack to handle horizontal wrapping |
| 444 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[state->m_CG10103_cur_chip->gfx_region], tile, color+state->m_CG10103_cur_chip->pal_base, flipx, flipy, xp>>16, ypos>>16, xfact, yfact, state->m_CG10103_cur_chip->transpen); |
| 445 | | drawgfxzoom_transpen(screen, cliprect, machine.gfx[state->m_CG10103_cur_chip->gfx_region], tile, color+state->m_CG10103_cur_chip->pal_base, flipx, flipy, (xp>>16) - 0x200, ypos>>16, xfact, yfact, state->m_CG10103_cur_chip->transpen); |
| 446 | | xp += xstep; |
| 447 | | tile++; |
| 448 | | } |
| 449 | | |
| 450 | | ypos += ystep; |
| 451 | | } |
| 452 | | } |
| 453 | | |
| 454 | | |
| 455 | | static void CG10103_draw(running_machine &machine, int numchip, bitmap_ind16& screen, const rectangle &cliprect, int priority) |
| 456 | | { |
| 457 | | gstriker_state *state = machine.driver_data<gstriker_state>(); |
| 458 | | UINT16* splist; |
| 459 | | int i; |
| 460 | | |
| 461 | | state->m_CG10103_cur_chip = &state->m_CG10103[numchip]; |
| 462 | | |
| 463 | | splist = state->m_CG10103_cur_chip->vram; |
| 464 | | |
| 465 | | // Parse the sorting list |
| 466 | | for (i=0;i<0x400;i++) |
| 467 | | { |
| 468 | | UINT16 cmd = *splist++; |
| 469 | | |
| 470 | | // End of list |
| 471 | | if (cmd & 0x4000) |
| 472 | | break; |
| 473 | | |
| 474 | | // Normal sprite here |
| 475 | | if (cmd & 0x100) |
| 476 | | { |
| 477 | | // Extract sprite index |
| 478 | | int num = cmd & 0xFF; |
| 479 | | |
| 480 | | // Draw the sprite |
| 481 | | CG10103_draw_sprite(machine, screen, cliprect, state->m_CG10103_cur_chip->vram + 0x400 + num*4, priority); |
| 482 | | } |
| 483 | | } |
| 484 | | } |
| 485 | | |
| 486 | | static void CG10103_init(int numchips) |
| 487 | | { |
| 488 | | int i; |
| 489 | | |
| 490 | | if (numchips > MAX_CG10103) |
| 491 | | numchips = MAX_CG10103; |
| 492 | | |
| 493 | | for (i=0;i<numchips;i++) |
| 494 | | { |
| 495 | | // No initalization required, as for now. I'll keep the init function in case we later |
| 496 | | // need something |
| 497 | | } |
| 498 | | } |
| 499 | | |
| 500 | | static void CG10103_set_pal_base(gstriker_state *state, int numchip, int pal_base) |
| 501 | | { |
| 502 | | state->m_CG10103[numchip].pal_base = pal_base; |
| 503 | | } |
| 504 | | |
| 505 | | static void CG10103_set_gfx_region(gstriker_state *state, int numchip, int gfx_region) |
| 506 | | { |
| 507 | | state->m_CG10103[numchip].gfx_region = gfx_region; |
| 508 | | } |
| 509 | | |
| 510 | | static void CG10103_set_transpen(gstriker_state *state, int numchip, int transpen) |
| 511 | | { |
| 512 | | state->m_CG10103[numchip].transpen = transpen; |
| 513 | | } |
| 514 | | |
| 515 | | |
| 516 | 323 | /*** VIDEO UPDATE/START **********************************************/ |
| 517 | 324 | |
| 518 | 325 | |
| r18385 | r18386 | |
| 533 | 340 | // needs sprite orthogonality |
| 534 | 341 | MB60553_draw(machine(), 0, bitmap,cliprect, 0); |
| 535 | 342 | |
| 536 | | CG10103_draw(machine(), 0, bitmap, cliprect, 0); |
| 343 | m_spr->CG10103_draw(machine(), 0, bitmap, cliprect, 0); |
| 537 | 344 | |
| 538 | 345 | VS920A_draw(this, 0, bitmap, cliprect, 0); |
| 539 | 346 | |
| 540 | | CG10103_draw(machine(), 0, bitmap, cliprect, 1); |
| 347 | m_spr->CG10103_draw(machine(), 0, bitmap, cliprect, 1); |
| 541 | 348 | |
| 542 | 349 | #if 0 |
| 543 | 350 | popmessage("%04x %04x %04x %04x %04x %04x %04x %04x", |
| r18385 | r18386 | |
| 573 | 380 | MB60553_get_tilemap(this, 0)->set_transparent_pen(0xf); |
| 574 | 381 | |
| 575 | 382 | // Initialize the sprite generator |
| 576 | | CG10103_init(1); |
| 577 | | CG10103_set_gfx_region(this, 0, 2); |
| 578 | | CG10103_set_pal_base(this, 0, 0x10); |
| 579 | | CG10103_set_transpen(this, 0, 0x0); |
| 383 | m_spr->CG10103_set_ram(m_CG10103_vram); |
| 384 | m_spr->CG10103_set_gfx_region(2); |
| 385 | m_spr->CG10103_set_pal_base(0x10); |
| 386 | m_spr->CG10103_set_transpen(0x0); |
| 580 | 387 | } |
| 581 | 388 | |
| 582 | 389 | VIDEO_START_MEMBER(gstriker_state,twrldc94) |
| r18385 | r18386 | |
| 597 | 404 | MB60553_get_tilemap(this, 0)->set_transparent_pen(0xf); |
| 598 | 405 | |
| 599 | 406 | // Initialize the sprite generator |
| 600 | | CG10103_init(1); |
| 601 | | CG10103_set_gfx_region(this, 0, 2); |
| 602 | | CG10103_set_pal_base(this, 0, 0x60); |
| 603 | | CG10103_set_transpen(this, 0, 0x0); |
| 407 | m_spr->CG10103_set_ram(m_CG10103_vram); |
| 408 | m_spr->CG10103_set_gfx_region(2); |
| 409 | m_spr->CG10103_set_pal_base(0x60); |
| 410 | m_spr->CG10103_set_transpen(0x0); |
| 604 | 411 | } |
| 605 | 412 | |
| 606 | 413 | VIDEO_START_MEMBER(gstriker_state,vgoalsoc) |
| r18385 | r18386 | |
| 621 | 428 | MB60553_get_tilemap(this, 0)->set_transparent_pen(0xf); |
| 622 | 429 | |
| 623 | 430 | // Initialize the sprite generator |
| 624 | | CG10103_init(1); |
| 625 | | CG10103_set_gfx_region(this, 0, 2); |
| 626 | | CG10103_set_pal_base(this, 0, 0x00); |
| 627 | | CG10103_set_transpen(this, 0, 0xf); |
| 431 | m_spr->CG10103_set_ram(m_CG10103_vram); |
| 432 | m_spr->CG10103_set_gfx_region(2); |
| 433 | m_spr->CG10103_set_pal_base(0x00); |
| 434 | m_spr->CG10103_set_transpen(0xf); |
| 628 | 435 | } |
trunk/src/mame/video/taotaido.c
| r18385 | r18386 | |
| 9 | 9 | */ |
| 10 | 10 | |
| 11 | 11 | #include "emu.h" |
| 12 | #include "vsystem_spr.h" |
| 12 | 13 | #include "includes/taotaido.h" |
| 13 | 14 | |
| 14 | | |
| 15 | 15 | /* sprite tile codes 0x4000 - 0x7fff get remapped according to the content of these registers */ |
| 16 | 16 | WRITE16_MEMBER(taotaido_state::taotaido_sprite_character_bank_select_w) |
| 17 | 17 | { |
| r18385 | r18386 | |
| 24 | 24 | /* sprites are like the other video system / psikyo games, we can merge this with aerofgt and plenty of other |
| 25 | 25 | things eventually */ |
| 26 | 26 | |
| 27 | | static void draw_sprite(running_machine &machine, UINT16 spriteno, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 28 | | { |
| 29 | | taotaido_state *state = machine.driver_data<taotaido_state>(); |
| 30 | | /*- SPR RAM Format -** |
| 31 | 27 | |
| 32 | | 4 words per sprite |
| 33 | | |
| 34 | | zzzz sssp pppp pppp (y zoom, y size, y position) |
| 35 | | zzzz sssp pppp pppp (x zoom, x size, x position) |
| 36 | | yxpc cccc ---- ---- (flipy, flipx, priority?, colour) |
| 37 | | -nnn nnnn nnnn nnnn (tile lookup) |
| 38 | | |
| 39 | | */ |
| 40 | | |
| 41 | | int x,y; |
| 42 | | |
| 43 | | UINT16 *source = &state->m_spriteram_older[spriteno*4]; |
| 44 | | gfx_element *gfx = machine.gfx[0]; |
| 45 | | |
| 46 | | |
| 47 | | int yzoom = (source[0] & 0xf000) >> 12; |
| 48 | | int xzoom = (source[1] & 0xf000) >> 12; |
| 49 | | |
| 50 | | int ysize = (source[0] & 0x0e00) >> 9; |
| 51 | | int xsize = (source[1] & 0x0e00) >> 9; |
| 52 | | |
| 53 | | int ypos = source[0] & 0x01ff; |
| 54 | | int xpos = source[1] & 0x01ff; |
| 55 | | |
| 56 | | int yflip = source[2] & 0x8000; |
| 57 | | int xflip = source[2] & 0x4000; |
| 58 | | int color = (source[2] & 0x1f00) >> 8; |
| 59 | | |
| 60 | | int tile = source[3] & 0xffff; |
| 61 | | |
| 62 | | xpos += (xsize*xzoom+2)/4; |
| 63 | | ypos += (ysize*yzoom+2)/4; |
| 64 | | |
| 65 | | xzoom = 32 - xzoom; |
| 66 | | yzoom = 32 - yzoom; |
| 67 | | |
| 68 | | |
| 69 | | for (y = 0;y <= ysize;y++) |
| 70 | | { |
| 71 | | int sx,sy; |
| 72 | | |
| 73 | | if (yflip) sy = ((ypos + yzoom * (ysize - y)/2 + 16) & 0x1ff) - 16; |
| 74 | | else sy = ((ypos + yzoom * y / 2 + 16) & 0x1ff) - 16; |
| 75 | | |
| 76 | | for (x = 0;x <= xsize;x++) |
| 77 | | { |
| 78 | | |
| 79 | | /* this indirection is a bit different to the other video system games */ |
| 80 | | int realtile; |
| 81 | | |
| 82 | | realtile = state->m_spriteram2_older[tile&0x7fff]; |
| 83 | | |
| 84 | | if (realtile > 0x3fff) |
| 85 | | { |
| 86 | | int block; |
| 87 | | |
| 88 | | block = (realtile & 0x3800)>>11; |
| 89 | | |
| 90 | | realtile &= 0x07ff; |
| 91 | | realtile |= state->m_sprite_character_bank_select[block] * 0x800; |
| 92 | | } |
| 93 | | |
| 94 | | if (xflip) sx = ((xpos + xzoom * (xsize - x) / 2 + 16) & 0x1ff) - 16; |
| 95 | | else sx = ((xpos + xzoom * x / 2 + 16) & 0x1ff) - 16; |
| 96 | | |
| 97 | | |
| 98 | | drawgfxzoom_transpen(bitmap,cliprect,gfx, |
| 99 | | realtile, |
| 100 | | color, |
| 101 | | xflip,yflip, |
| 102 | | sx,sy, |
| 103 | | xzoom << 11, yzoom << 11,15); |
| 104 | | |
| 105 | | tile++; |
| 106 | | |
| 107 | | } |
| 108 | | } |
| 109 | | } |
| 110 | | |
| 111 | | static void draw_sprites(running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 112 | | { |
| 113 | | taotaido_state *state = machine.driver_data<taotaido_state>(); |
| 114 | | /* first part of sprite ram is the list of sprites to draw, terminated with 0x4000 */ |
| 115 | | UINT16 *source = state->m_spriteram_older; |
| 116 | | UINT16 *finish = state->m_spriteram_older + 0x2000/2; |
| 117 | | |
| 118 | | while( source<finish ) |
| 119 | | { |
| 120 | | if (source[0] == 0x4000) break; |
| 121 | | |
| 122 | | draw_sprite(machine, source[0]&0x3ff, bitmap, cliprect); |
| 123 | | |
| 124 | | source++; |
| 125 | | } |
| 126 | | } |
| 127 | | |
| 128 | | |
| 129 | 28 | /* the tilemap */ |
| 130 | 29 | |
| 131 | 30 | WRITE16_MEMBER(taotaido_state::taotaido_tileregs_w) |
| r18385 | r18386 | |
| 214 | 113 | m_bg_tilemap->draw(bitmap, clip, 0,0); |
| 215 | 114 | } |
| 216 | 115 | |
| 217 | | draw_sprites(machine(), bitmap,cliprect); |
| 116 | m_spr->draw_sprites_taotaido(m_spriteram_older, m_spriteram.bytes(), m_spriteram2_older, m_sprite_character_bank_select, machine(), bitmap,cliprect); |
| 218 | 117 | return 0; |
| 219 | 118 | } |
| 220 | 119 | |
trunk/src/mame/video/crshrace.c
| r18385 | r18386 | |
| 92 | 92 | |
| 93 | 93 | ***************************************************************************/ |
| 94 | 94 | |
| 95 | | static void draw_sprites(running_machine &machine, bitmap_ind16 &bitmap,const rectangle &cliprect) |
| 96 | | { |
| 97 | | crshrace_state *state = machine.driver_data<crshrace_state>(); |
| 98 | | UINT16 *buffered_spriteram = state->m_spriteram->buffer(); |
| 99 | | UINT16 *buffered_spriteram_2 = state->m_spriteram2->buffer(); |
| 100 | | int offs; |
| 101 | | |
| 102 | | offs = 0; |
| 103 | | while (offs < 0x0400 && (buffered_spriteram[offs] & 0x4000) == 0) |
| 104 | | { |
| 105 | | int attr_start; |
| 106 | | int map_start; |
| 107 | | int ox, oy, x, y, xsize, ysize, zoomx, zoomy, flipx, flipy, color; |
| 108 | | /* table hand made by looking at the ship explosion in aerofgt attract mode */ |
| 109 | | /* it's almost a logarithmic scale but not exactly */ |
| 110 | | static const int zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; |
| 111 | | |
| 112 | | attr_start = 4 * (buffered_spriteram[offs++] & 0x03ff); |
| 113 | | |
| 114 | | ox = buffered_spriteram[attr_start + 1] & 0x01ff; |
| 115 | | xsize = (buffered_spriteram[attr_start + 1] & 0x0e00) >> 9; |
| 116 | | zoomx = (buffered_spriteram[attr_start + 1] & 0xf000) >> 12; |
| 117 | | oy = buffered_spriteram[attr_start + 0] & 0x01ff; |
| 118 | | ysize = (buffered_spriteram[attr_start + 0] & 0x0e00) >> 9; |
| 119 | | zoomy = (buffered_spriteram[attr_start + 0] & 0xf000) >> 12; |
| 120 | | flipx = buffered_spriteram[attr_start + 2] & 0x4000; |
| 121 | | flipy = buffered_spriteram[attr_start + 2] & 0x8000; |
| 122 | | color = (buffered_spriteram[attr_start + 2] & 0x1f00) >> 8; |
| 123 | | map_start = buffered_spriteram[attr_start + 3] & 0x7fff; |
| 124 | | |
| 125 | | zoomx = 16 - zoomtable[zoomx] / 8; |
| 126 | | zoomy = 16 - zoomtable[zoomy] / 8; |
| 127 | | |
| 128 | | if (buffered_spriteram[attr_start + 2] & 0x20ff) color = machine.rand(); |
| 129 | | |
| 130 | | for (y = 0; y <= ysize; y++) |
| 131 | | { |
| 132 | | int sx,sy; |
| 133 | | |
| 134 | | if (flipy) sy = ((oy + zoomy * (ysize - y) + 16) & 0x1ff) - 16; |
| 135 | | else sy = ((oy + zoomy * y + 16) & 0x1ff) - 16; |
| 136 | | |
| 137 | | for (x = 0; x <= xsize; x++) |
| 138 | | { |
| 139 | | int code; |
| 140 | | |
| 141 | | if (flipx) sx = ((ox + zoomx * (xsize - x) + 16) & 0x1ff) - 16; |
| 142 | | else sx = ((ox + zoomx * x + 16) & 0x1ff) - 16; |
| 143 | | |
| 144 | | code = buffered_spriteram_2[map_start & 0x7fff]; |
| 145 | | map_start++; |
| 146 | | |
| 147 | | if (state->m_flipscreen) |
| 148 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 149 | | code, |
| 150 | | color, |
| 151 | | !flipx,!flipy, |
| 152 | | 304-sx,208-sy, |
| 153 | | 0x1000 * zoomx,0x1000 * zoomy,15); |
| 154 | | else |
| 155 | | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 156 | | code, |
| 157 | | color, |
| 158 | | flipx,flipy, |
| 159 | | sx,sy, |
| 160 | | 0x1000 * zoomx,0x1000 * zoomy,15); |
| 161 | | } |
| 162 | | } |
| 163 | | } |
| 164 | | } |
| 165 | | |
| 166 | | |
| 167 | 95 | static void draw_bg( running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 168 | 96 | { |
| 169 | 97 | crshrace_state *state = machine.driver_data<crshrace_state>(); |
| r18385 | r18386 | |
| 189 | 117 | |
| 190 | 118 | bitmap.fill(0x1ff, cliprect); |
| 191 | 119 | |
| 120 | |
| 121 | |
| 192 | 122 | switch (m_gfxctrl & 0xfb) |
| 193 | 123 | { |
| 194 | 124 | case 0x00: /* high score screen */ |
| 195 | | draw_sprites(machine(), bitmap, cliprect); |
| 125 | m_spr->draw_sprites_crshrace(m_spriteram->buffer(), 0x2000, m_spriteram2->buffer(), machine(), bitmap, cliprect, m_flipscreen); |
| 196 | 126 | draw_bg(machine(), bitmap, cliprect); |
| 197 | 127 | draw_fg(machine(), bitmap, cliprect); |
| 198 | 128 | break; |
| r18385 | r18386 | |
| 200 | 130 | case 0x02: |
| 201 | 131 | draw_bg(machine(), bitmap, cliprect); |
| 202 | 132 | draw_fg(machine(), bitmap, cliprect); |
| 203 | | draw_sprites(machine(), bitmap, cliprect); |
| 133 | m_spr->draw_sprites_crshrace(m_spriteram->buffer(), 0x2000, m_spriteram2->buffer(), machine(), bitmap, cliprect, m_flipscreen); |
| 204 | 134 | break; |
| 205 | 135 | default: |
| 206 | 136 | popmessage("gfxctrl = %02x", m_gfxctrl); |
trunk/src/mame/video/vsystem_spr.c
| r18385 | r18386 | |
| 1 | 1 | // Video System Sprites |
| 2 | 2 | // todo: |
| 3 | 3 | // move various vsystem sprite functions here |
| 4 | | // unify common ones + convert to device |
| 4 | // unify common ones + convert to device (secondary stage tile lookup differs between games, use callback) |
| 5 | 5 | |
| 6 | // according to gstriker this is probably the Fujitsu CG10103 |
| 7 | |
| 6 | 8 | #include "emu.h" |
| 9 | #include "vsystem_spr.h" |
| 7 | 10 | |
| 11 | |
| 12 | const device_type VSYSTEM_SPR = &device_creator<vsystem_spr_device>; |
| 13 | |
| 14 | vsystem_spr_device::vsystem_spr_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 15 | : device_t(mconfig, VSYSTEM_SPR, "vsystem_spr_device", tag, owner, clock) |
| 16 | { |
| 17 | } |
| 18 | |
| 19 | |
| 20 | |
| 21 | void vsystem_spr_device::device_start() |
| 22 | { |
| 23 | |
| 24 | } |
| 25 | |
| 26 | void vsystem_spr_device::device_reset() |
| 27 | { |
| 28 | |
| 29 | } |
| 30 | |
| 31 | |
| 32 | |
| 8 | 33 | // zooming is wrong for 3on3dunk ... suprslam implementation is probably better |
| 9 | | void draw_sprites_inufuku( UINT16* spriteram1, int spriteram1_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 34 | void vsystem_spr_device::draw_sprites_inufuku( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 10 | 35 | { |
| 11 | 36 | int offs; |
| 12 | 37 | int end = 0; |
| 13 | 38 | |
| 14 | | for (offs = 0; offs < (spriteram1_bytes / 16 ); offs++) |
| 39 | for (offs = 0; offs < (spriteram_bytes / 16 ); offs++) |
| 15 | 40 | { |
| 16 | | if (spriteram1[offs] & 0x4000) break; |
| 41 | if (spriteram[offs] & 0x4000) break; |
| 17 | 42 | } |
| 18 | 43 | end = offs; |
| 19 | 44 | |
| 20 | 45 | for (offs = end - 1; offs >= 0; offs--) |
| 21 | 46 | { |
| 22 | | if ((spriteram1[offs] & 0x8000) == 0x0000) |
| 47 | if ((spriteram[offs] & 0x8000) == 0x0000) |
| 23 | 48 | { |
| 24 | 49 | int attr_start; |
| 25 | 50 | int map_start; |
| 26 | 51 | int ox, oy, x, y, xsize, ysize, zoomx, zoomy, flipx, flipy, color; |
| 27 | 52 | int priority, priority_mask; |
| 28 | 53 | |
| 29 | | attr_start = 4 * (spriteram1[offs] & 0x03ff); |
| 54 | attr_start = 4 * (spriteram[offs] & 0x03ff); |
| 30 | 55 | |
| 31 | 56 | /* |
| 32 | 57 | attr_start + 0x0000 |
| r18385 | r18386 | |
| 51 | 76 | x--- ---- ---- ---- unused? |
| 52 | 77 | */ |
| 53 | 78 | |
| 54 | | ox = (spriteram1[attr_start + 1] & 0x01ff) + 0; |
| 55 | | xsize = (spriteram1[attr_start + 1] & 0x0e00) >> 9; |
| 56 | | zoomx = (spriteram1[attr_start + 1] & 0xf000) >> 12; |
| 57 | | oy = (spriteram1[attr_start + 0] & 0x01ff) + 1; |
| 58 | | ysize = (spriteram1[attr_start + 0] & 0x0e00) >> 9; |
| 59 | | zoomy = (spriteram1[attr_start + 0] & 0xf000) >> 12; |
| 60 | | flipx = spriteram1[attr_start + 2] & 0x4000; |
| 61 | | flipy = spriteram1[attr_start + 2] & 0x8000; |
| 62 | | color = (spriteram1[attr_start + 2] & 0x3f00) >> 8; |
| 63 | | priority = (spriteram1[attr_start + 2] & 0x3000) >> 12; |
| 64 | | map_start = (spriteram1[attr_start + 3] & 0x7fff) << 1; |
| 79 | ox = (spriteram[attr_start + 1] & 0x01ff) + 0; |
| 80 | xsize = (spriteram[attr_start + 1] & 0x0e00) >> 9; |
| 81 | zoomx = (spriteram[attr_start + 1] & 0xf000) >> 12; |
| 82 | oy = (spriteram[attr_start + 0] & 0x01ff) + 1; |
| 83 | ysize = (spriteram[attr_start + 0] & 0x0e00) >> 9; |
| 84 | zoomy = (spriteram[attr_start + 0] & 0xf000) >> 12; |
| 85 | flipx = spriteram[attr_start + 2] & 0x4000; |
| 86 | flipy = spriteram[attr_start + 2] & 0x8000; |
| 87 | color = (spriteram[attr_start + 2] & 0x3f00) >> 8; |
| 88 | priority = (spriteram[attr_start + 2] & 0x3000) >> 12; |
| 89 | map_start = (spriteram[attr_start + 3] & 0x7fff) << 1; |
| 65 | 90 | |
| 66 | 91 | switch (priority) |
| 67 | 92 | { |
| r18385 | r18386 | |
| 116 | 141 | |
| 117 | 142 | |
| 118 | 143 | /* todo, fix zooming correctly, it's _not_ like aerofgt */ |
| 119 | | void draw_sprites_suprslam( UINT16* spriteram, int spriteram_bytes, UINT16* sp_videoram, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 144 | void vsystem_spr_device::draw_sprites_suprslam( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 120 | 145 | { |
| 121 | 146 | /* SPRITE INFO |
| 122 | 147 | |
| r18385 | r18386 | |
| 180 | 205 | for (ycnt = 0; ycnt < high+1; ycnt ++) |
| 181 | 206 | { |
| 182 | 207 | if (!flipx) |
| 183 | | { |
| 208 | { |
| 184 | 209 | for (xcnt = 0; xcnt < wide+1; xcnt ++) |
| 185 | 210 | { |
| 186 | | int tileno = sp_videoram[word_offset + loopno]; |
| 211 | int tileno = spriteram2[word_offset + loopno]; |
| 187 | 212 | drawgfxzoom_transpen(bitmap, cliprect, gfx, tileno, col, 0, 0,xpos + xcnt * xzoom/2, ypos + ycnt * yzoom/2,xzoom << 11, yzoom << 11, 15); |
| 188 | 213 | drawgfxzoom_transpen(bitmap, cliprect, gfx, tileno, col, 0, 0,-0x200+xpos + xcnt * xzoom/2, ypos + ycnt * yzoom/2,xzoom << 11, yzoom << 11, 15); |
| 189 | 214 | loopno ++; |
| r18385 | r18386 | |
| 193 | 218 | { |
| 194 | 219 | for (xcnt = wide; xcnt >= 0; xcnt --) |
| 195 | 220 | { |
| 196 | | int tileno = sp_videoram[word_offset + loopno]; |
| 221 | int tileno = spriteram2[word_offset + loopno]; |
| 197 | 222 | drawgfxzoom_transpen(bitmap, cliprect, gfx, tileno, col, 1, 0,xpos + xcnt * xzoom/2, ypos + ycnt * yzoom/2,xzoom << 11, yzoom << 11, 15); |
| 198 | 223 | drawgfxzoom_transpen(bitmap, cliprect, gfx, tileno, col, 1, 0,-0x200+xpos + xcnt * xzoom/2, ypos + ycnt * yzoom/2,xzoom << 11, yzoom << 11, 15); |
| 199 | 224 | loopno ++; |
| r18385 | r18386 | |
| 203 | 228 | } |
| 204 | 229 | } |
| 205 | 230 | } |
| 231 | |
| 232 | |
| 233 | |
| 234 | static void draw_sprite_taotaido( UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, UINT16* spriteram3, running_machine &machine, UINT16 spriteno, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 235 | { |
| 236 | /*- SPR RAM Format -** |
| 237 | |
| 238 | 4 words per sprite |
| 239 | |
| 240 | zzzz sssp pppp pppp (y zoom, y size, y position) |
| 241 | zzzz sssp pppp pppp (x zoom, x size, x position) |
| 242 | yxpc cccc ---- ---- (flipy, flipx, priority?, colour) |
| 243 | -nnn nnnn nnnn nnnn (tile lookup) |
| 244 | |
| 245 | */ |
| 246 | |
| 247 | int x,y; |
| 248 | |
| 249 | UINT16 *source = &spriteram[spriteno*4]; |
| 250 | gfx_element *gfx = machine.gfx[0]; |
| 251 | |
| 252 | |
| 253 | int yzoom = (source[0] & 0xf000) >> 12; |
| 254 | int xzoom = (source[1] & 0xf000) >> 12; |
| 255 | |
| 256 | int ysize = (source[0] & 0x0e00) >> 9; |
| 257 | int xsize = (source[1] & 0x0e00) >> 9; |
| 258 | |
| 259 | int ypos = source[0] & 0x01ff; |
| 260 | int xpos = source[1] & 0x01ff; |
| 261 | |
| 262 | int yflip = source[2] & 0x8000; |
| 263 | int xflip = source[2] & 0x4000; |
| 264 | int color = (source[2] & 0x1f00) >> 8; |
| 265 | |
| 266 | int tile = source[3] & 0xffff; |
| 267 | |
| 268 | xpos += (xsize*xzoom+2)/4; |
| 269 | ypos += (ysize*yzoom+2)/4; |
| 270 | |
| 271 | xzoom = 32 - xzoom; |
| 272 | yzoom = 32 - yzoom; |
| 273 | |
| 274 | |
| 275 | for (y = 0;y <= ysize;y++) |
| 276 | { |
| 277 | int sx,sy; |
| 278 | |
| 279 | if (yflip) sy = ((ypos + yzoom * (ysize - y)/2 + 16) & 0x1ff) - 16; |
| 280 | else sy = ((ypos + yzoom * y / 2 + 16) & 0x1ff) - 16; |
| 281 | |
| 282 | for (x = 0;x <= xsize;x++) |
| 283 | { |
| 284 | |
| 285 | /* this indirection is a bit different to the other video system games */ |
| 286 | int realtile; |
| 287 | |
| 288 | realtile = spriteram2[tile&0x7fff]; |
| 289 | |
| 290 | if (realtile > 0x3fff) |
| 291 | { |
| 292 | int block; |
| 293 | |
| 294 | block = (realtile & 0x3800)>>11; |
| 295 | |
| 296 | realtile &= 0x07ff; |
| 297 | realtile |= spriteram3[block] * 0x800; |
| 298 | } |
| 299 | |
| 300 | if (xflip) sx = ((xpos + xzoom * (xsize - x) / 2 + 16) & 0x1ff) - 16; |
| 301 | else sx = ((xpos + xzoom * x / 2 + 16) & 0x1ff) - 16; |
| 302 | |
| 303 | |
| 304 | drawgfxzoom_transpen(bitmap,cliprect,gfx, |
| 305 | realtile, |
| 306 | color, |
| 307 | xflip,yflip, |
| 308 | sx,sy, |
| 309 | xzoom << 11, yzoom << 11,15); |
| 310 | |
| 311 | tile++; |
| 312 | |
| 313 | } |
| 314 | } |
| 315 | } |
| 316 | |
| 317 | 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 ) |
| 318 | { |
| 319 | UINT16 *source = spriteram; |
| 320 | UINT16 *finish = spriteram + spriteram_bytes/2; |
| 321 | |
| 322 | while( source<finish ) |
| 323 | { |
| 324 | if (source[0] == 0x4000) break; |
| 325 | |
| 326 | draw_sprite_taotaido(spriteram, spriteram_bytes, spriteram2, spriteram3, machine, source[0]&0x3ff, bitmap, cliprect); |
| 327 | |
| 328 | source++; |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | |
| 333 | |
| 334 | void vsystem_spr_device::draw_sprites_crshrace(UINT16* spriteram, int spriteram_bytes, UINT16* spriteram2, running_machine &machine, bitmap_ind16 &bitmap,const rectangle &cliprect, int flipscreen) |
| 335 | { |
| 336 | int offs; |
| 337 | |
| 338 | offs = 0; |
| 339 | while (offs < 0x0400 && (spriteram[offs] & 0x4000) == 0) |
| 340 | { |
| 341 | int attr_start; |
| 342 | int map_start; |
| 343 | int ox, oy, x, y, xsize, ysize, zoomx, zoomy, flipx, flipy, color; |
| 344 | /* table hand made by looking at the ship explosion in aerofgt attract mode */ |
| 345 | /* it's almost a logarithmic scale but not exactly */ |
| 346 | static const int zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 }; |
| 347 | |
| 348 | attr_start = 4 * (spriteram[offs++] & 0x03ff); |
| 349 | |
| 350 | ox = spriteram[attr_start + 1] & 0x01ff; |
| 351 | xsize = (spriteram[attr_start + 1] & 0x0e00) >> 9; |
| 352 | zoomx = (spriteram[attr_start + 1] & 0xf000) >> 12; |
| 353 | oy = spriteram[attr_start + 0] & 0x01ff; |
| 354 | ysize = (spriteram[attr_start + 0] & 0x0e00) >> 9; |
| 355 | zoomy = (spriteram[attr_start + 0] & 0xf000) >> 12; |
| 356 | flipx = spriteram[attr_start + 2] & 0x4000; |
| 357 | flipy = spriteram[attr_start + 2] & 0x8000; |
| 358 | color = (spriteram[attr_start + 2] & 0x1f00) >> 8; |
| 359 | map_start = spriteram[attr_start + 3] & 0x7fff; |
| 360 | |
| 361 | zoomx = 16 - zoomtable[zoomx] / 8; |
| 362 | zoomy = 16 - zoomtable[zoomy] / 8; |
| 363 | |
| 364 | if (spriteram[attr_start + 2] & 0x20ff) color = machine.rand(); |
| 365 | |
| 366 | for (y = 0; y <= ysize; y++) |
| 367 | { |
| 368 | int sx,sy; |
| 369 | |
| 370 | if (flipy) sy = ((oy + zoomy * (ysize - y) + 16) & 0x1ff) - 16; |
| 371 | else sy = ((oy + zoomy * y + 16) & 0x1ff) - 16; |
| 372 | |
| 373 | for (x = 0; x <= xsize; x++) |
| 374 | { |
| 375 | int code; |
| 376 | |
| 377 | if (flipx) sx = ((ox + zoomx * (xsize - x) + 16) & 0x1ff) - 16; |
| 378 | else sx = ((ox + zoomx * x + 16) & 0x1ff) - 16; |
| 379 | |
| 380 | code = spriteram2[map_start & 0x7fff]; |
| 381 | map_start++; |
| 382 | |
| 383 | if (flipscreen) |
| 384 | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 385 | code, |
| 386 | color, |
| 387 | !flipx,!flipy, |
| 388 | 304-sx,208-sy, |
| 389 | 0x1000 * zoomx,0x1000 * zoomy,15); |
| 390 | else |
| 391 | drawgfxzoom_transpen(bitmap,cliprect,machine.gfx[2], |
| 392 | code, |
| 393 | color, |
| 394 | flipx,flipy, |
| 395 | sx,sy, |
| 396 | 0x1000 * zoomx,0x1000 * zoomy,15); |
| 397 | } |
| 398 | } |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | |
| 403 | |
| 404 | /*** Fujitsu CG10103 **********************************************/ |
| 405 | |
| 406 | /* |
| 407 | Fujitsu CG10103 sprite generator |
| 408 | -------------------------------- |
| 409 | |
| 410 | - Tile based |
| 411 | - 16x16 4bpp tiles |
| 412 | - Up to 7x7 in each block |
| 413 | - 5 bit of palette selection for the mixer |
| 414 | - Scaling (x/y) |
| 415 | - Flipping |
| 416 | - Indipendent sorting list |
| 417 | - 1 bit of priority for the mixer |
| 418 | |
| 419 | Note that this chip can be connected to a VS9210 which adds a level of indirection for |
| 420 | tile numbers. Basically, the VS9210 indirects the tile number through a table in its attached |
| 421 | memory, before accessing the ROMs. |
| 422 | |
| 423 | |
| 424 | Sorting list format (VideoRAM offset 0) |
| 425 | --------------------------------------- |
| 426 | |
| 427 | ?e-- ---f ssss ssss |
| 428 | |
| 429 | e=end of list |
| 430 | f=sprite present in this position |
| 431 | s=sprite index |
| 432 | ?=used together with 'e' almost always |
| 433 | |
| 434 | |
| 435 | Sprite format (VideoRAM offset 0x400) |
| 436 | ------------------------------------- |
| 437 | |
| 438 | 0: nnnn jjjy yyyy yyyy |
| 439 | 1: mmmm iiix xxxx xxxx |
| 440 | 2: fFpc cccc ---- ---t |
| 441 | 3: tttt tttt tttt tttt |
| 442 | |
| 443 | t=tile, x=posx, y=posy, i=blockx, j=blocky |
| 444 | c=color, m=zoomx, n=zoomy, p=priority |
| 445 | |
| 446 | The zoom (scaling) is probably non-linear, it would require a hand-made table unless we find the correct |
| 447 | formula. I'd probably try 1/x. I'm almost sure that it scales between full size (value=0) and half size |
| 448 | (value=0xF) but I couldn't get much more than that from a soccer game. |
| 449 | |
| 450 | |
| 451 | TODO: |
| 452 | Priorities should be right, but they probably need to be orthogonal with the mixer priorities. |
| 453 | Zoom factor is not correct, the scale is probably non-linear |
| 454 | Horizontal wrapping is just a hack. The chip probably calculates if it needs to draw the sprite at the |
| 455 | normal position, or wrapped along X/Y. |
| 456 | Abstracts the VS9210 |
| 457 | |
| 458 | */ |
| 459 | |
| 460 | |
| 461 | void vsystem_spr_device::CG10103_draw_sprite(running_machine &machine, bitmap_ind16& screen, const rectangle &cliprect, UINT16* spr, int drawpri) |
| 462 | { |
| 463 | int ypos = spr[0] & 0x1FF; |
| 464 | int xpos = (spr[1] & 0x1FF); |
| 465 | UINT32 tile = (spr[3] & 0xFFFF) | ((spr[2] & 1) << 16); |
| 466 | int ynum = (spr[0] >> 9) & 0x7; |
| 467 | int xnum = (spr[1] >> 9) & 0x7; |
| 468 | int color = (spr[2] >> 8) & 0x1F; |
| 469 | int flipx = (spr[2] >> 14) & 1; |
| 470 | int flipy = (spr[2] >> 15) & 1; |
| 471 | int yzoom = (spr[0] >> 12) & 0xF; |
| 472 | int xzoom = (spr[1] >> 12) & 0xF; |
| 473 | int pri = (spr[2] >> 13) & 1; |
| 474 | int x, y; |
| 475 | int xstep, ystep; |
| 476 | int xfact, yfact; |
| 477 | |
| 478 | // Check if we want to draw this sprite now |
| 479 | if (pri != drawpri) |
| 480 | return; |
| 481 | |
| 482 | // Convert in fixed point to handle the scaling |
| 483 | xpos <<= 16; |
| 484 | ypos <<= 16; |
| 485 | |
| 486 | xnum++; |
| 487 | ynum++; |
| 488 | xstep = ystep = 16; |
| 489 | |
| 490 | // Linear scale, surely wrong |
| 491 | xfact = 0x10000 - ((0x8000 * xzoom) / 15); |
| 492 | yfact = 0x10000 - ((0x8000 * yzoom) / 15); |
| 493 | |
| 494 | xstep *= xfact; |
| 495 | ystep *= yfact; |
| 496 | |
| 497 | // Handle flipping |
| 498 | if (flipy) |
| 499 | { |
| 500 | ypos += (ynum-1) * ystep; |
| 501 | ystep = -ystep; |
| 502 | } |
| 503 | |
| 504 | if (flipx) |
| 505 | { |
| 506 | xpos += (xnum-1) * xstep; |
| 507 | xstep = -xstep; |
| 508 | } |
| 509 | |
| 510 | // @@@ Add here optional connection to the VS9210 for extra level of tile number indirection |
| 511 | #if 0 |
| 512 | if (m_CG10103_cur_chip->connected_vs9210) |
| 513 | { |
| 514 | // ... |
| 515 | } |
| 516 | #endif |
| 517 | |
| 518 | // Draw the block |
| 519 | for (y=0;y<ynum;y++) |
| 520 | { |
| 521 | int xp = xpos; |
| 522 | |
| 523 | for (x=0;x<xnum;x++) |
| 524 | { |
| 525 | // Hack to handle horizontal wrapping |
| 526 | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], tile, color+m_CG10103_cur_chip->pal_base, flipx, flipy, xp>>16, ypos>>16, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 527 | drawgfxzoom_transpen(screen, cliprect, machine.gfx[m_CG10103_cur_chip->gfx_region], tile, color+m_CG10103_cur_chip->pal_base, flipx, flipy, (xp>>16) - 0x200, ypos>>16, xfact, yfact, m_CG10103_cur_chip->transpen); |
| 528 | xp += xstep; |
| 529 | tile++; |
| 530 | } |
| 531 | |
| 532 | ypos += ystep; |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | |
| 537 | void vsystem_spr_device::CG10103_draw(running_machine &machine, int numchip, bitmap_ind16& screen, const rectangle &cliprect, int priority) |
| 538 | { |
| 539 | UINT16* splist; |
| 540 | int i; |
| 541 | |
| 542 | m_CG10103_cur_chip = &m_CG10103; |
| 543 | |
| 544 | splist = m_CG10103_cur_chip->vram; |
| 545 | |
| 546 | // Parse the sorting list |
| 547 | for (i=0;i<0x400;i++) |
| 548 | { |
| 549 | UINT16 cmd = *splist++; |
| 550 | |
| 551 | // End of list |
| 552 | if (cmd & 0x4000) |
| 553 | break; |
| 554 | |
| 555 | // Normal sprite here |
| 556 | if (cmd & 0x100) |
| 557 | { |
| 558 | // Extract sprite index |
| 559 | int num = cmd & 0xFF; |
| 560 | |
| 561 | // Draw the sprite |
| 562 | CG10103_draw_sprite(machine, screen, cliprect, m_CG10103_cur_chip->vram + 0x400 + num*4, priority); |
| 563 | } |
| 564 | } |
| 565 | } |
| 566 | |
| 567 | |
| 568 | |
| 569 | void vsystem_spr_device::CG10103_set_pal_base(int pal_base) |
| 570 | { |
| 571 | m_CG10103.pal_base = pal_base; |
| 572 | } |
| 573 | |
| 574 | void vsystem_spr_device::CG10103_set_gfx_region(int gfx_region) |
| 575 | { |
| 576 | m_CG10103.gfx_region = gfx_region; |
| 577 | } |
| 578 | |
| 579 | void vsystem_spr_device::CG10103_set_transpen(int transpen) |
| 580 | { |
| 581 | m_CG10103.transpen = transpen; |
| 582 | } |
| 583 | |
| 584 | void vsystem_spr_device::CG10103_set_ram(UINT16* vram) |
| 585 | { |
| 586 | m_CG10103.vram = vram; |
| 587 | } |