1 // license:LGPL-2.1+
2 // copyright-holders:David Haywood, Angelo Salese, ElSemi, Andrew Gardner
3
4 /* Hyper NeoGeo 64 Sprite bits */
5
6 /*
7 * Sprite Format
8 * ------------------
9 *
10 * uint32_t | Bits | Use
11 * | 3322 2222 2222 1111 1111 11 |
12 * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+----------------
13 * 0 | yyyy yyyy yyyy yyyy xxxx xxxx xxxx xxxx | x/y position
14 * 1 | YYYY YYYY YYYY YYYY XXXX XXXX XXXX XXXX | x/y zoom (*)
15 * 2 | ---- -zzz zzzz zzzz ---- ---I cccc CCCC | Z-buffer value, 'Inline' chain flag, x/y chain
16 * 3 | ---- ---- pppp pppp ---- ---- ---- ---- | palette entry
17 * 4 | mmmm -?fF a??? tttt tttt tttt tttt tttt | mosaic factor, unknown (**) , flip bits, additive blending, unknown (***), tile number
18 * 5 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
19 * 6 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
20 * 7 | ---- ---- ---- ---- ---- ---- ---- ---- | not used ??
21 *
22 * (*) Fatal Fury WA standard elements are 0x1000-0x1000, all the other games sets 0x100-0x100, related to the bit 27 of sprite regs 0?
23 * (**) setted by black squares in ranking screen in Samurai Shodown 64 1, sprite disable?
24 * (***) bit 22 is setted on some Fatal Fury WA snow (not all of them), bit 21 is setted on Xrally how to play elements in attract mode
25 ** Sprite Global Registers
26 * -----------------------
27 *
28 * uint32_t | Bits | Use
29 * | 3322 2222 2222 1111 1111 11 |
30 * -------+-1098-7654-3210-9876-5432-1098-7654-3210-+----------------
31 * 0 | ssss z--f b--- -aap ---- ---- ---- ---- | s = unknown, samsho z = zooming mode, f = depthfilter mode (unset set in roadedge ingame) b = bpp select a = always, p = post, disable?
32 * 1 | yyyy yyyy yyyy yyyy xxxx xxxx xxxx xxxx | global sprite offset (ss64 rankings in attract, roadedge HUD scroll when starting game)
33 * 2 | ---- ---- ---- uuuu uuuu uuuu uuuu uuuu | u = unknown, set to 0x000fffff in roadedge ingame, bbust2, samsho - also possible depthfilter related
34 * 3 | ---- ---- ---- ---- ---- ---- ---- ---- |
35 * 4 | ---- ---- ---- ---- ---- ---- ---- ---- |
36 * (anything else is unknown at the current time)
37 * Notes:
38 * [4]
39 * 0x0e0 in Samurai Shodown/Xrally games, 0x1c0 in all the others, zooming factor?
40
41 */
42
draw_sprites(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)43 void hng64_state::draw_sprites(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
44 {
45 gfx_element *gfx;
46 uint32_t *source = m_spriteram;
47 uint32_t *finish = m_spriteram + 0xc000/4;
48
49 // global offsets in sprite regs
50 int spriteoffsx = (m_spriteregs[1]>>0)&0xffff;
51 int spriteoffsy = (m_spriteregs[1]>>16)&0xffff;
52
53 #if 0
54 for (int iii = 0; iii < 0x0f; iii++)
55 osd_printf_debug("%.8x ", m_videoregs[iii]);
56 osd_printf_debug("\n");
57 #endif
58
59 while( source<finish )
60 {
61 int tileno,chainx,chainy,xflip;
62 int pal,xinc,yinc,yflip;
63 uint16_t xpos, ypos;
64 int xdrw,ydrw;
65 int chaini;
66 int zbuf;
67 uint32_t zoomx,zoomy;
68 float foomX, foomY;
69 int blend;
70 int disable;
71
72
73 ypos = (source[0]&0xffff0000)>>16;
74 xpos = (source[0]&0x0000ffff)>>0;
75 xpos += (spriteoffsx);
76 ypos += (spriteoffsy);
77
78 tileno= (source[4]&0x0007ffff);
79 blend= (source[4]&0x00800000);
80 yflip= (source[4]&0x01000000)>>24;
81 xflip= (source[4]&0x02000000)>>25;
82 disable=(source[4]&0x04000000)>>26; // ss64 rankings?
83
84 pal =(source[3]&0x00ff0000)>>16;
85
86 chainy=(source[2]&0x0000000f);
87 chainx=(source[2]&0x000000f0)>>4;
88 chaini=(source[2]&0x00000100);
89 zbuf = (source[2]&0x07ff0000)>>16; //?
90
91 zoomy = (source[1]&0xffff0000)>>16;
92 zoomx = (source[1]&0x0000ffff)>>0;
93
94 int filtervalue = 0x000;
95
96 // This flips between ingame and other screens for roadedge, where the sprites which are filtered definitely needs to change and the game explicitly swaps the values in the sprite list at the same time.
97 // m_spriteregs[2] could also play a part as it also flips between 0x00000000 and 0x000fffff at the same time
98 // Samsho games also set the upper 3 bits which could be related, samsho games still have some unwanted sprites (but also use the other 'sprite clear' mechanism)
99 // Could also be draw order related, check if it inverts the z value?
100 if (m_spriteregs[0] & 0x01000000)
101 filtervalue = 0x7ff;
102
103 if(zbuf == filtervalue)
104 {
105 source+=8;
106 continue;
107 }
108
109 if(disable)
110 {
111 source+=8;
112 continue;
113 }
114
115 #if 0
116 if (!(source[4] == 0x00000000 || source[4] == 0x000000aa))
117 osd_printf_debug("unknown : %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x \n", source[0], source[1], source[2], source[3],
118 source[4], source[5], source[6], source[7]);
119 #endif
120
121 /* Calculate the zoom */
122 {
123 int zoom_factor;
124
125 /* FIXME: regular zoom mode has precision bugs, can be easily seen in Samurai Shodown 64 intro */
126 zoom_factor = (m_spriteregs[0] & 0x08000000) ? 0x1000 : 0x100;
127 if(!zoomx) zoomx=zoom_factor;
128 if(!zoomy) zoomy=zoom_factor;
129
130 /* First, prevent any possible divide by zero errors */
131 foomX = (float)(zoom_factor) / (float)zoomx;
132 foomY = (float)(zoom_factor) / (float)zoomy;
133
134 zoomx = ((int)foomX) << 16;
135 zoomy = ((int)foomY) << 16;
136
137 zoomx += (int)((foomX - floor(foomX)) * (float)0x10000);
138 zoomy += (int)((foomY - floor(foomY)) * (float)0x10000);
139 }
140
141 if (m_spriteregs[0] & 0x00800000) //bpp switch
142 {
143 gfx= m_gfxdecode->gfx(4);
144 }
145 else
146 {
147 gfx= m_gfxdecode->gfx(5);
148 tileno>>=1;
149 pal&=0xf;
150 }
151
152 // Accommodate for chaining and flipping
153 if(xflip)
154 {
155 xinc=-(int)(16.0f*foomX);
156 xpos-=xinc*chainx;
157 }
158 else
159 {
160 xinc=(int)(16.0f*foomX);
161 }
162
163 if(yflip)
164 {
165 yinc=-(int)(16.0f*foomY);
166 ypos-=yinc*chainy;
167 }
168 else
169 {
170 yinc=(int)(16.0f*foomY);
171 }
172
173 #if 0
174 if (((source[2) & 0xffff0000) >> 16) == 0x0001)
175 {
176 popmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]);
177 //popmessage("T %.8x %.8x %.8x %.8x %.8x", source[0], source[1], source[2], source[3], source[4]);
178 }
179 #endif
180
181 for(ydrw=0;ydrw<=chainy;ydrw++)
182 {
183 for(xdrw=0;xdrw<=chainx;xdrw++)
184 {
185 int16_t drawx = xpos+(xinc*xdrw);
186 int16_t drawy = ypos+(yinc*ydrw);
187
188 // 0x3ff (0x200 sign bit) based on sams64_2 char select
189 drawx &= 0x3ff;
190 drawy &= 0x3ff;
191
192 if (drawx&0x0200)drawx-=0x400;
193 if (drawy&0x0200)drawy-=0x400;
194
195 if (!chaini)
196 {
197 if (!blend) gfx->prio_zoom_transpen(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
198 else gfx->prio_zoom_transpen_additive(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
199 tileno++;
200 }
201 else // inline chain mode, used by ss64
202 {
203 tileno=(source[4]&0x0007ffff);
204 pal =(source[3]&0x00ff0000)>>16;
205
206 if (m_spriteregs[0] & 0x00800000) //bpp switch
207 {
208 gfx= m_gfxdecode->gfx(4);
209 }
210 else
211 {
212 gfx= m_gfxdecode->gfx(5);
213 tileno>>=1;
214 pal&=0xf;
215 }
216
217 if (!blend) gfx->prio_zoom_transpen(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
218 else gfx->prio_zoom_transpen_additive(bitmap,cliprect,tileno,pal,xflip,yflip,drawx,drawy,zoomx,zoomy/*0x10000*/,screen.priority(), 0,0);
219 source +=8;
220 }
221
222 }
223 }
224
225 if (!chaini) source +=8;
226 }
227 }
228