1 #include "driver.h"
2 #include "vidhrdw/generic.h"
3 #include "vidhrdw/taitoic.h"
4
5 #define TC0480SCP_GFX_NUM 1
6
7 struct tempsprite
8 {
9 int gfx;
10 int code,color;
11 int flipx,flipy;
12 int x,y;
13 int zoomx,zoomy;
14 int primask;
15 };
16 static struct tempsprite *spritelist;
17
VIDEO_START(superchs)18 VIDEO_START( superchs )
19 {
20 spritelist = auto_malloc(0x4000 * sizeof(*spritelist));
21 if (!spritelist)
22 return 1;
23
24 if (TC0480SCP_vh_start(TC0480SCP_GFX_NUM,0,0x20,0x08,-1,0,0,0,0))
25 return 1;
26
27 return 0;
28 }
29
30 /************************************************************
31 SPRITE DRAW ROUTINES
32
33 We draw a series of small tiles ("chunks") together to
34 create each big sprite. The spritemap rom provides the lookup
35 table for this. The game hardware looks up 16x16 sprite chunks
36 from the spritemap rom, creating a 64x64 sprite like this:
37
38 0 1 2 3
39 4 5 6 7
40 8 9 10 11
41 12 13 14 15
42
43 (where the number is the word offset into the spritemap rom).
44 It can also create 32x32 sprites.
45
46 NB: unused portions of the spritemap rom contain hex FF's.
47 It is a useful coding check to warn in the log if these
48 are being accessed. [They can be inadvertently while
49 spriteram is being tested, take no notice of that.]
50
51 Heavy use is made of sprite zooming.
52
53 ***
54
55 Sprite table layout (4 long words per entry)
56
57 ------------------------------------------
58 0 | ........ x....... ........ ........ | Flip X
59 0 | ........ .xxxxxxx ........ ........ | ZoomX
60 0 | ........ ........ .xxxxxxx xxxxxxxx | Sprite Tile
61 | |
62 2 | ........ ....xx.. ........ ........ | Sprite/tile priority [*]
63 2 | ........ ......xx xxxxxx.. ........ | Palette bank
64 2 | ........ ........ ......xx xxxxxxxx | X position
65 | |
66 3 | ........ .....x.. ........ ........ | Sprite size (0=32x32, 1=64x64)
67 3 | ........ ......x. ........ ........ | Flip Y
68 3 | ........ .......x xxxxxx.. ........ | ZoomY
69 3 | ........ ........ ......xx xxxxxxxx | Y position
70 ------------------------------------------
71
72 [* 00=over BG1; 01=BG2; 10=BG3; 11=over text]
73
74 ********************************************************/
75
superchs_draw_sprites_16x16(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int * primasks,int x_offs,int y_offs)76 static void superchs_draw_sprites_16x16(struct mame_bitmap *bitmap,const struct rectangle *cliprect,int *primasks,int x_offs,int y_offs)
77 {
78 data16_t *spritemap = (data16_t *)memory_region(REGION_USER1);
79 int offs, data, tilenum, color, flipx, flipy;
80 int x, y, priority, dblsize, curx, cury;
81 int sprites_flipscreen = 0;
82 int zoomx, zoomy, zx, zy;
83 int sprite_chunk,map_offset,code,j,k,px,py;
84 int dimension,total_chunks,bad_chunks;
85
86 /* pdrawgfx() needs us to draw sprites front to back, so we have to build a list
87 while processing sprite ram and then draw them all at the end */
88 struct tempsprite *sprite_ptr = spritelist;
89
90 for (offs = (spriteram_size/4-4);offs >= 0;offs -= 4)
91 {
92 data = spriteram32[offs+0];
93 flipx = (data & 0x00800000) >> 23;
94 zoomx = (data & 0x007f0000) >> 16;
95 tilenum = (data & 0x00007fff);
96
97 data = spriteram32[offs+2];
98 priority = (data & 0x000c0000) >> 18;
99 color = (data & 0x0003fc00) >> 10;
100 x = (data & 0x000003ff);
101
102 data = spriteram32[offs+3];
103 dblsize = (data & 0x00040000) >> 18;
104 flipy = (data & 0x00020000) >> 17;
105 zoomy = (data & 0x0001fc00) >> 10;
106 y = (data & 0x000003ff);
107
108 color |= 0x100;
109
110 if (!tilenum) continue;
111
112 flipy = !flipy;
113 zoomx += 1;
114 zoomy += 1;
115
116 y += y_offs;
117
118 /* treat coords as signed */
119 if (x>0x340) x -= 0x400;
120 if (y>0x340) y -= 0x400;
121
122 x -= x_offs;
123
124 bad_chunks = 0;
125 dimension = ((dblsize*2) + 2); /* 2 or 4*/
126 total_chunks = ((dblsize*3) + 1) << 2; /* 4 or 16*/
127 map_offset = tilenum << 2;
128
129 {
130 for (sprite_chunk=0;sprite_chunk<total_chunks;sprite_chunk++)
131 {
132 j = sprite_chunk / dimension; /* rows */
133 k = sprite_chunk % dimension; /* chunks per row */
134
135 px = k;
136 py = j;
137 /* pick tiles back to front for x and y flips */
138 if (flipx) px = dimension-1-k;
139 if (flipy) py = dimension-1-j;
140
141 code = spritemap[map_offset + px + (py<<(dblsize+1))];
142
143 if (code==0xffff)
144 {
145 bad_chunks += 1;
146 continue;
147 }
148
149 curx = x + ((k*zoomx)/dimension);
150 cury = y + ((j*zoomy)/dimension);
151
152 zx= x + (((k+1)*zoomx)/dimension) - curx;
153 zy= y + (((j+1)*zoomy)/dimension) - cury;
154
155 if (sprites_flipscreen)
156 {
157 /* -zx/y is there to fix zoomed sprite coords in screenflip.
158 drawgfxzoom does not know to draw from flip-side of sprites when
159 screen is flipped; so we must correct the coords ourselves. */
160
161 curx = 320 - curx - zx;
162 cury = 256 - cury - zy;
163 flipx = !flipx;
164 flipy = !flipy;
165 }
166
167 sprite_ptr->gfx = 0;
168 sprite_ptr->code = code;
169 sprite_ptr->color = color;
170 sprite_ptr->flipx = !flipx;
171 sprite_ptr->flipy = flipy;
172 sprite_ptr->x = curx;
173 sprite_ptr->y = cury;
174 sprite_ptr->zoomx = zx << 12;
175 sprite_ptr->zoomy = zy << 12;
176
177 if (primasks)
178 {
179 sprite_ptr->primask = primasks[priority];
180
181 sprite_ptr++;
182 }
183 else
184 {
185 drawgfxzoom(bitmap,Machine->gfx[sprite_ptr->gfx],
186 sprite_ptr->code,
187 sprite_ptr->color,
188 sprite_ptr->flipx,sprite_ptr->flipy,
189 sprite_ptr->x,sprite_ptr->y,
190 cliprect,TRANSPARENCY_PEN,0,
191 sprite_ptr->zoomx,sprite_ptr->zoomy);
192 }
193 }
194 }
195
196 if (bad_chunks)
197 log_cb(RETRO_LOG_DEBUG, LOGPRE "Sprite number %04x had %02x invalid chunks\n",tilenum,bad_chunks);
198 }
199
200 /* this happens only if primsks != NULL */
201 while (sprite_ptr != spritelist)
202 {
203 sprite_ptr--;
204
205 pdrawgfxzoom(bitmap,Machine->gfx[sprite_ptr->gfx],
206 sprite_ptr->code,
207 sprite_ptr->color,
208 sprite_ptr->flipx,sprite_ptr->flipy,
209 sprite_ptr->x,sprite_ptr->y,
210 cliprect,TRANSPARENCY_PEN,0,
211 sprite_ptr->zoomx,sprite_ptr->zoomy,
212 sprite_ptr->primask);
213 }
214 }
215
216
217 /**************************************************************
218 SCREEN REFRESH
219 **************************************************************/
220
VIDEO_UPDATE(superchs)221 VIDEO_UPDATE( superchs )
222 {
223 UINT8 layer[5];
224 UINT16 priority;
225 int primasks[4] = {0xfffc, 0xfff0, 0xff00, 0x0};
226
227 TC0480SCP_tilemap_update();
228
229 priority = TC0480SCP_get_bg_priority();
230 layer[0] = (priority &0xf000) >> 12; /* tells us which bg layer is bottom */
231 layer[1] = (priority &0x0f00) >> 8;
232 layer[2] = (priority &0x00f0) >> 4;
233 layer[3] = (priority &0x000f) >> 0; /* tells us which is top */
234 layer[4] = 4; /* text layer always over bg layers */
235
236 fillbitmap(priority_bitmap,0,cliprect);
237
238 /* We have to assume 2nd to bottom layer is always underneath
239 sprites as pdrawgfx cannot yet cope with more than 4 layers */
240
241 #ifdef MAME_DEBUG
242 if (!keyboard_pressed (KEYCODE_Z)) TC0480SCP_tilemap_draw(bitmap,cliprect,layer[0],TILEMAP_IGNORE_TRANSPARENCY,0);
243 if (!keyboard_pressed (KEYCODE_X)) TC0480SCP_tilemap_draw(bitmap,cliprect,layer[1],0,1);
244 if (!keyboard_pressed (KEYCODE_C)) TC0480SCP_tilemap_draw(bitmap,cliprect,layer[2],0,2);
245 if (!keyboard_pressed (KEYCODE_V)) TC0480SCP_tilemap_draw(bitmap,cliprect,layer[3],0,4);
246 if (!keyboard_pressed (KEYCODE_B)) TC0480SCP_tilemap_draw(bitmap,cliprect,layer[4],0,8);
247 if (!keyboard_pressed (KEYCODE_N)) superchs_draw_sprites_16x16(bitmap,cliprect,primasks,48,-116);
248 #else
249 TC0480SCP_tilemap_draw(bitmap,cliprect,layer[0],TILEMAP_IGNORE_TRANSPARENCY,0);
250 TC0480SCP_tilemap_draw(bitmap,cliprect,layer[1],0,1);
251 TC0480SCP_tilemap_draw(bitmap,cliprect,layer[2],0,2);
252 TC0480SCP_tilemap_draw(bitmap,cliprect,layer[3],0,4);
253 TC0480SCP_tilemap_draw(bitmap,cliprect,layer[4],0,8); /* text layer */
254 superchs_draw_sprites_16x16(bitmap,cliprect,primasks,48,-116);
255 #endif
256 }
257