/* sys16spr.c ** ** This module maps spriteram for various Sega System16/System18 games to ** a shared abstraction represented by the sys16_sprite_attributes ** structure. ** ** Each function takes a pointer to a sprite attribute structure to fill ** out. This function is initialized to zero automatically prior to the ** function call. ** ** The next parameter, source points to the spriteram ** associated with a particular sprite. ** ** The final parameter bJustGetColor is set when this function is called while ** marking colors. During this pass, only the palette field needs to be ** populated. ** ** This function must return 1 if the sprite was flagged as the last sprite, ** or 0 if the sprite was not flagged as the last sprite. ** ** We should probably unpack sprites into an array once, rather than processing ** sprites one at a time, once when marking colors and once when rendering them. ** Note that we need to draw sprites from front to back to achieve proper sprite-tilemap ** orthogonality, so would make it easier to know how many sprites there are (and ** thus which is the 'last sprite' with which we need to start. */ /* Changes: 03/12/04 Charles MacDonald - Fixed end of list and sprite hide flag processing in sys16_sprite_shinobi, hwchamp output test works properly. - Fixed size of zoom fields, fixes sprite alignment issues in hwchamp */ #include "driver.h" #include "system16.h" int sys16_sprite_shinobi( struct sys16_sprite_attributes *sprite, const UINT16 *source, int bJustGetColor ){ /* standard sprite hardware (Shinobi, Altered Beast, Golden Axe 0 YYYYYYYY YYYYYYYY top, bottom (screen coordinates) 1 -------X XXXXXXXX left (screen coordinate) 2 EH------F WWWWWWWW end list flag, hide sprite flag, flipx, signed pitch 3 TTTTTTTT TTTTTTTT word offset for start of sprite data; each word is 16 bits (4 pixels) 4 ----BBBB PPCCCCCC attributes: bank, priority, color 5 ------YY YYYXXXXX zoomy, zoomx 6 -------- -------- 7 -------- -------- */ UINT16 ypos = source[0]; UINT16 width = source[2]; int top = ypos&0xff; int bottom = ypos>>8; if(width & 0x8000) return 1; // End of list bit set if(width & 0x4000) return 0; // Hide this sprite bit set if(top >= bottom || top >= 0xe0) return 0; // Invalid height or off-screen if(bottom >= 0xe0) bottom = 0xe0; // Clip bottom of sprite { UINT16 attributes = source[4]; UINT16 zoomx = source[5] & 0x1F; UINT16 zoomy = (source[5] >> 5) & 0x1F; // Rest of rendering code expects zoom to be 10 bits zoomx <<= 5; zoomy <<= 5; // Having zoomy set to zoomx when zoomy is zero heavily distorts the multi-sprite opponents in hwchamp //if( zoomy==0 || source[6]==0xffff ) zoomy = zoomx; /* if zoomy is 0, use zoomx instead */ sprite->x = source[1] + sys16_sprxoffset; sprite->y = top; sprite->priority = (attributes>>6)&0x3; sprite->color = 1024/16 + (attributes&0x3f); sprite->screen_height = bottom-top; sprite->flags = SYS16_SPR_VISIBLE; if( width&0x100 ) sprite->flags |= SYS16_SPR_FLIPX; if ((attributes&0x3f)==0x3f) sprite->flags|= SYS16_SPR_SHADOW; sprite->zoomx = zoomx; sprite->zoomy = zoomy; sprite->pitch = source[2]&0xff; sprite->gfx = ( source[3] + (sys16_obj_bank[(attributes>>8)&0xf]<<16) ) << 1; //* } return 0; } int sys16_sprite_passshot( struct sys16_sprite_attributes *sprite, const UINT16 *source, int bJustGetColor ){ /* Passing shot 4p needs: passshot_y=-0x23; passshot_width=1; 0 -------X XXXXXXXX left (screen coordinate) 1 YYYYYYYY YYYYYYYY bottom, top (screen coordinates) 2 XTTTTTTT TTTTTTTT (pen data, flipx, flipy) 3 -------- FWWWWWWW pitch: flipy, logical width 4 ------ZZ ZZZZZZZZ zoom 5 PPCCCCCC BBBB---- attributes: priority, color, bank 6 -------- -------- 7 -------- -------- */ int passshot_y=0; int passshot_width=0; UINT16 attributes = source[5]; UINT16 ypos = source[1]; int bottom = (ypos>>8)+passshot_y; int top = (ypos&0xff)+passshot_y; if( bottom>top && ypos!=0xffff ){ int bank = (attributes>>4)&0xf; UINT16 number = source[2]; UINT16 width = source[3]; int zoom = source[4]&0x3ff; int xpos = source[0] + sys16_sprxoffset; sprite->screen_height = bottom - top; sprite->priority = attributes>>14; sprite->color = 1024/16+ ((attributes>>8)&0x3f); /* hack */ if( passshot_width) { /* 4 player bootleg version */ width = -width; number -= width*(bottom-top-1)-1; } sprite->flags = SYS16_SPR_VISIBLE; if( number & 0x8000 ) sprite->flags |= SYS16_SPR_FLIPX; if (((attributes>>8)&0x3f)==0x3f) // shadow sprite sprite->flags|= SYS16_SPR_SHADOW; sprite->pitch = width&0xff; if( sprite->flags&SYS16_SPR_FLIPX ){ bank = (bank-1) & 0xf; /* ? */ } sprite->gfx = ((number-(short)width)*4 + (sys16_obj_bank[bank] << 17))/2; //* sprite->x = xpos; sprite->y = top+2; //* sprite->zoomx = sprite->zoomy = zoom; } return 0; } int sys16_sprite_quartet2( struct sys16_sprite_attributes *sprite, const UINT16 *source, int bJustGetColor ){ /* Quartet2, Alexkidd, Bodyslam, mjleague, shinobibl 0 YYYYYYYY YYYYYYYY bottom, top 1 -------X XXXXXXXX xpos 2 -------- WWWWWWWW pitch 3 FTTTTTTT TTTTTTTT flipx, gfx 4 --CCCCCC BBBBPPPP color, bank, priority 5 -------- -------- 6 -------- -------- 7 -------- -------- */ UINT16 ypos = source[0]; int top = ypos&0xff; int bottom = ypos>>8; if( bottom == 0xff ) return 1; if(bottom !=0 && bottom > top){ UINT16 spr_pri=(source[4])&0xf; /* ?? */ UINT16 bank=(source[4]>>4) &0xf; UINT16 pal=(source[4]>>8)&0x3f; UINT16 tsource[4]; UINT16 width; int gfx; if (spr_pri) { /* MASH - ?? */ tsource[2]=source[2]; tsource[3]=source[3]; if((tsource[3] & 0x7f80) == 0x7f80){ bank=(bank-1)&0xf; tsource[3]^=0x8000; } tsource[2] &= 0x00ff; if (tsource[3]&0x8000){ // reverse tsource[2] |= 0x0100; tsource[3] &= 0x7fff; } gfx = tsource[3]*4; width = tsource[2]; //top++; //bottom++; sprite->x = source[1] + sys16_sprxoffset; if(sprite->x > 0x140) sprite->x-=0x200; sprite->y = top; sprite->priority = spr_pri; sprite->color = 1024/16 + pal; sprite->screen_height = bottom-top; sprite->pitch = width&0xff; sprite->flags = SYS16_SPR_VISIBLE; if( width&0x100 ) sprite->flags |= SYS16_SPR_FLIPX; if( pal==0x3f ) sprite->flags|= SYS16_SPR_SHADOW; // shadow sprite sprite->gfx = ((gfx &0x3ffff) + (sys16_obj_bank[bank] << 17))/2; } } return 0; }