1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4
5 video.c
6
7 Functions to emulate the video hardware of the machine.
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "video/resnet.h"
13 #include "includes/taitosj.h"
14
15
16 #define GLOBAL_FLIP_X (*m_video_mode & 0x01)
17 #define GLOBAL_FLIP_Y (*m_video_mode & 0x02)
18 #define SPRITE_RAM_PAGE_OFFSET ((*m_video_mode & 0x04) ? 0x80 : 0x00)
19 #define SPRITES_ON (*m_video_mode & 0x80)
20 #define TRANSPARENT_PEN (0x40)
21
22
23
24 static const int layer_enable_mask[3] = { 0x10, 0x20, 0x40 };
25
26
27 /***************************************************************************
28
29 I call the three layers with the conventional names "front", "middle" and
30 "back", because that's their default order, but they can be arranged,
31 together with the sprites, in any order. The priority is selected by
32 register 0xd300, which works as follow:
33
34 bits 0-3 go to A4-A7 of a 256x4 PROM
35 bit 4 selects D0/D1 or D2/D3 of the PROM
36 bit 5-7 n.c.
37 A0-A3 of the PROM is fed with a mask of the inactive layers
38 (i.e. all-zero) in the order sprites-front-middle-back
39 the 2-bit code which comes out from the PROM selects the layer
40 to display.
41
42 Here is a dump of one of these PROMs; on the right is the resulting order
43 (s = sprites f = front m = middle b = back). Note that, in theory, the
44 PROM could encode some really funky priority schemes which couldn't be
45 reconducted to the simple layer order given here. Luckily, none of the
46 games seem to do that. Actually, all of them seem to use the same PROM,
47 with the exception of Wild Western.
48
49 d300 pri d300 pri
50 00: 08 09 08 0A 00 05 00 0F 08 09 08 0A 00 05 00 0F | 00 sfmb 10 msfb
51 10: 08 09 08 0B 00 0D 00 0F 08 09 08 0A 00 05 00 0F | 01 sfbm 11 msbf
52 20: 08 0A 08 0A 04 05 00 0F 08 0A 08 0A 04 05 00 0F | 02 smfb 12 mfsb
53 30: 08 0A 08 0A 04 07 0C 0F 08 0A 08 0A 04 05 00 0F | 03 smbf 13 mfbs
54 40: 08 0B 08 0B 0C 0F 0C 0F 08 09 08 0A 00 05 00 0F | 04 sbfm 14 mbsf
55 50: 08 0B 08 0B 0C 0F 0C 0F 08 0A 08 0A 04 05 00 0F | 05 sbmf 15 mbfs
56 60: 0D 0D 0C 0E 0D 0D 0C 0F 01 05 00 0A 01 05 00 0F | 06 fsmb 16 bsfm
57 70: 0D 0D 0C 0F 0D 0D 0C 0F 01 09 00 0A 01 05 00 0F | 07 fsbm 17 bsmf
58 80: 0D 0D 0E 0E 0D 0D 0C 0F 05 05 02 0A 05 05 00 0F | 08 fmsb 18 bfsm
59 90: 0D 0D 0E 0E 0D 0D 0F 0F 05 05 0A 0A 05 05 00 0F | 09 fmbs 19 bfms
60 A0: 0D 0D 0F 0F 0D 0D 0F 0F 09 09 08 0A 01 05 00 0F | 0A fbsm 1A bmsf
61 B0: 0D 0D 0F 0F 0D 0D 0F 0F 09 09 0A 0A 05 05 00 0F | 0B fbms 1B bmfs
62 C0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F | 0C - 1C -
63 D0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F | 0D - 1D -
64 E0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F | 0E - 1E -
65 F0: 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F 0F | 0F - 1F -
66
67 ***************************************************************************/
68
69
70
71 /***************************************************************************
72
73 Convert the color PROMs into a more useable format.
74
75 The Taito games don't have a color PROM. They use RAM to dynamically
76 create the palette. The resolution is 9 bit (3 bits per gun).
77
78 The RAM is connected to the RGB output this way:
79
80 bit 0 -- inverter -- 270 ohm resistor -- RED
81 bit 7 -- inverter -- 470 ohm resistor -- RED
82 -- inverter -- 1 kohm resistor -- RED
83 -- inverter -- 270 ohm resistor -- GREEN
84 -- inverter -- 470 ohm resistor -- GREEN
85 -- inverter -- 1 kohm resistor -- GREEN
86 -- inverter -- 270 ohm resistor -- BLUE
87 -- inverter -- 470 ohm resistor -- BLUE
88 bit 0 -- inverter -- 1 kohm resistor -- BLUE
89
90 ***************************************************************************/
91
set_pens()92 void taitosj_state::set_pens()
93 {
94 static const int resistances[3] = { 1000, 470, 270 };
95 double rweights[3], gweights[3], bweights[3];
96 int i;
97
98 /* compute the color output resistor weights */
99 compute_resistor_weights(0, 255, -1.0,
100 3, resistances, rweights, 0, 0,
101 3, resistances, gweights, 0, 0,
102 3, resistances, bweights, 0, 0);
103
104 for (i = 0; i < 0x40; i++)
105 {
106 int bit0, bit1, bit2;
107 int r, g, b, val;
108
109 /* red component */
110 val = m_paletteram[(i << 1) | 0x01];
111 bit0 = (~val >> 6) & 0x01;
112 bit1 = (~val >> 7) & 0x01;
113 val = m_paletteram[(i << 1) | 0x00];
114 bit2 = (~val >> 0) & 0x01;
115 r = combine_weights(rweights, bit0, bit1, bit2);
116
117 /* green component */
118 val = m_paletteram[(i << 1) | 0x01];
119 bit0 = (~val >> 3) & 0x01;
120 bit1 = (~val >> 4) & 0x01;
121 bit2 = (~val >> 5) & 0x01;
122 g = combine_weights(gweights, bit0, bit1, bit2);
123
124 /* blue component */
125 val = m_paletteram[(i << 1) | 0x01];
126 bit0 = (~val >> 0) & 0x01;
127 bit1 = (~val >> 1) & 0x01;
128 bit2 = (~val >> 2) & 0x01;
129 b = combine_weights(bweights, bit0, bit1, bit2);
130
131 m_palette->set_pen_color(i, rgb_t(r, g, b));
132 }
133 }
134
135 /***************************************************************************
136
137 Start the video hardware emulation.
138
139 ***************************************************************************/
140
compute_draw_order()141 void taitosj_state::compute_draw_order()
142 {
143 int i;
144 uint8_t *color_prom = memregion("proms")->base();
145
146 /* do a simple conversion of the PROM into layer priority order. Note that */
147 /* this is a simplification, which assumes the PROM encodes a sensible priority */
148 /* scheme. */
149 for (i = 0; i < 32; i++)
150 {
151 int j;
152 int mask = 0; /* start with all four layers active, so we'll get the highest */
153 /* priority one in the first loop */
154 for (j = 3; j >= 0; j--)
155 {
156 int data = color_prom[0x10 * (i & 0x0f) + mask] & 0x0f;
157
158 if (i & 0x10)
159 data = data >> 2;
160 else
161 data = data & 0x03;
162
163 mask |= (1 << data); /* in next loop, we'll see which of the remaining */
164 /* layers has top priority when this one is transparent */
165 m_draw_order[i][j] = data;
166 }
167 }
168 }
169
170
video_start()171 void taitosj_state::video_start()
172 {
173 int i;
174
175 m_sprite_layer_collbitmap1.allocate(16,16);
176
177 for (i = 0; i < 3; i++)
178 {
179 m_screen->register_screen_bitmap(m_layer_bitmap[i]);
180 m_screen->register_screen_bitmap(m_sprite_layer_collbitmap2[i]);
181 }
182
183 m_sprite_sprite_collbitmap1.allocate(32,32);
184 m_sprite_sprite_collbitmap2.allocate(32,32);
185
186 m_gfxdecode->gfx(0)->set_source(m_characterram);
187 m_gfxdecode->gfx(1)->set_source(m_characterram);
188 m_gfxdecode->gfx(2)->set_source(m_characterram + 0x1800);
189 m_gfxdecode->gfx(3)->set_source(m_characterram + 0x1800);
190
191 compute_draw_order();
192 }
193
194
195
taitosj_gfxrom_r()196 uint8_t taitosj_state::taitosj_gfxrom_r()
197 {
198 uint8_t ret;
199
200 offs_t offs = m_gfxpointer[0] | (m_gfxpointer[1] << 8);
201
202 if (offs < 0x8000)
203 ret = memregion("gfx1")->base()[offs];
204 else
205 ret = 0;
206
207 offs = offs + 1;
208
209 m_gfxpointer[0] = offs & 0xff;
210 m_gfxpointer[1] = offs >> 8;
211
212 return ret;
213 }
214
215
216
taitosj_characterram_w(offs_t offset,uint8_t data)217 void taitosj_state::taitosj_characterram_w(offs_t offset, uint8_t data)
218 {
219 if (m_characterram[offset] != data)
220 {
221 if (offset < 0x1800)
222 {
223 m_gfxdecode->gfx(0)->mark_dirty((offset / 8) & 0xff);
224 m_gfxdecode->gfx(1)->mark_dirty((offset / 32) & 0x3f);
225 }
226 else
227 {
228 m_gfxdecode->gfx(2)->mark_dirty((offset / 8) & 0xff);
229 m_gfxdecode->gfx(3)->mark_dirty((offset / 32) & 0x3f);
230 }
231
232 m_characterram[offset] = data;
233 }
234 }
235
junglhbr_characterram_w(offs_t offset,uint8_t data)236 void taitosj_state::junglhbr_characterram_w(offs_t offset, uint8_t data)
237 {
238 taitosj_characterram_w(offset, data ^ 0xfc);
239 }
240
241
taitosj_collision_reg_clear_w(uint8_t data)242 void taitosj_state::taitosj_collision_reg_clear_w(uint8_t data)
243 {
244 m_collision_reg[0] = 0;
245 m_collision_reg[1] = 0;
246 m_collision_reg[2] = 0;
247 m_collision_reg[3] = 0;
248 }
249
250
get_sprite_xy(uint8_t which,uint8_t * sx,uint8_t * sy)251 inline int taitosj_state::get_sprite_xy(uint8_t which, uint8_t* sx, uint8_t* sy)
252 {
253 offs_t offs = which * 4;
254
255 *sx = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 0] - 1;
256 *sy = 240 - m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 1];
257
258 return (*sy < 240);
259 }
260
261
get_sprite_gfx_element(uint8_t which)262 inline gfx_element * taitosj_state::get_sprite_gfx_element(uint8_t which)
263 {
264 offs_t offs = which * 4;
265
266 return m_gfxdecode->gfx((m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x40) ? 3 : 1);
267 }
268
269
check_sprite_sprite_bitpattern(int sx1,int sy1,int which1,int sx2,int sy2,int which2)270 int taitosj_state::check_sprite_sprite_bitpattern(int sx1, int sy1, int which1,int sx2, int sy2, int which2)
271 {
272 int minx, miny, maxx = 16, maxy = 16;
273
274 offs_t offs1 = which1 * 4;
275 offs_t offs2 = which2 * 4;
276
277 /* normalize coordinates to (0,0) and compute overlap */
278 if (sx1 < sx2)
279 {
280 sx2 -= sx1;
281 sx1 = 0;
282 minx = sx2;
283 }
284 else
285 {
286 sx1 -= sx2;
287 sx2 = 0;
288 minx = sx1;
289 }
290
291 if (sy1 < sy2)
292 {
293 sy2 -= sy1;
294 sy1 = 0;
295 miny = sy2;
296 }
297 else
298 {
299 sy1 -= sy2;
300 sy2 = 0;
301 miny = sy1;
302 }
303
304 /* draw the sprites into separate bitmaps and check overlapping region */
305 m_sprite_layer_collbitmap1.fill(TRANSPARENT_PEN);
306 get_sprite_gfx_element(which1)->transpen(m_sprite_sprite_collbitmap1,m_sprite_sprite_collbitmap1.cliprect(),
307 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 3] & 0x3f,
308 0,
309 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 2] & 0x01,
310 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs1 + 2] & 0x02,
311 sx1, sy1, 0);
312
313 m_sprite_sprite_collbitmap2.fill(TRANSPARENT_PEN);
314 get_sprite_gfx_element(which2)->transpen(m_sprite_sprite_collbitmap2,m_sprite_sprite_collbitmap2.cliprect(),
315 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 3] & 0x3f,
316 0,
317 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 2] & 0x01,
318 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs2 + 2] & 0x02,
319 sx2, sy2, 0);
320
321 for (int y = miny; y < maxy; y++)
322 for (int x = minx; x < maxx; x++)
323 if ((m_sprite_sprite_collbitmap1.pix(y, x) != TRANSPARENT_PEN) &&
324 (m_sprite_sprite_collbitmap2.pix(y, x) != TRANSPARENT_PEN))
325 return 1; /* collided */
326
327 return 0;
328 }
329
330
check_sprite_sprite_collision()331 void taitosj_state::check_sprite_sprite_collision()
332 {
333 if (SPRITES_ON)
334 {
335 int which1;
336
337 /* chech each pair of sprites */
338 for (which1 = 0; which1 < 0x20; which1++)
339 {
340 int which2;
341 uint8_t sx1, sy1;
342
343 if ((which1 >= 0x10) && (which1 <= 0x17)) continue; /* no sprites here */
344
345 if (!get_sprite_xy(which1, &sx1, &sy1)) continue;
346
347 for (which2 = which1 + 1; which2 < 0x20; which2++)
348 {
349 uint8_t sx2, sy2;
350
351 if ((which2 >= 0x10) && (which2 <= 0x17)) continue; /* no sprites here */
352
353 if (!get_sprite_xy(which2, &sx2, &sy2)) continue;
354
355 /* quickly rule out any pairs that cannot be touching */
356 if ((abs((int8_t)sx1 - (int8_t)sx2) < 16) &&
357 (abs((int8_t)sy1 - (int8_t)sy2) < 16))
358 {
359 int reg;
360
361 if (!check_sprite_sprite_bitpattern(sx1, sy1, which1, sx2, sy2, which2)) continue;
362
363 /* mark sprite as collided */
364 /* note that only the sprite with the higher number is marked */
365 /* as collided. This is how the hardware works and required */
366 /* by Pirate Pete to be able to finish the last round. */
367
368 /* the last sprite has to be moved at the start of the list */
369 if (which2 == 0x1f)
370 {
371 reg = which1 >> 3;
372 if (reg == 3) reg = 2;
373
374 m_collision_reg[reg] |= (1 << (which1 & 0x07));
375 }
376 else
377 {
378 reg = which2 >> 3;
379 if (reg == 3) reg = 2;
380
381 m_collision_reg[reg] |= (1 << (which2 & 0x07));
382 }
383 }
384 }
385 }
386 }
387 }
388
389
calculate_sprite_areas(int * sprites_on,rectangle * sprite_areas)390 void taitosj_state::calculate_sprite_areas(int *sprites_on, rectangle *sprite_areas)
391 {
392 int which;
393 int width = m_screen->width();
394 int height = m_screen->height();
395
396 for (which = 0; which < 0x20; which++)
397 {
398 uint8_t sx, sy;
399
400 if ((which >= 0x10) && (which <= 0x17)) continue; /* no sprites here */
401
402 if (get_sprite_xy(which, &sx, &sy))
403 {
404 int minx, miny, maxx, maxy;
405
406 if (GLOBAL_FLIP_X)
407 sx = 238 - sx;
408
409 if (GLOBAL_FLIP_Y)
410 sy = 242 - sy;
411
412 minx = sx;
413 miny = sy;
414
415 maxx = minx + 15;
416 maxy = miny + 15;
417
418 /* check for bitmap bounds to avoid illegal memory access */
419 if (minx < 0) minx = 0;
420 if (miny < 0) miny = 0;
421 if (maxx >= width - 1)
422 maxx = width - 1;
423 if (maxy >= height - 1)
424 maxy = height - 1;
425
426 sprite_areas[which].min_x = minx;
427 sprite_areas[which].max_x = maxx;
428 sprite_areas[which].min_y = miny;
429 sprite_areas[which].max_y = maxy;
430
431 sprites_on[which] = 1;
432 }
433 /* sprite is off */
434 else
435 sprites_on[which] = 0;
436 }
437 }
438
439
check_sprite_layer_bitpattern(int which,rectangle * sprite_areas)440 int taitosj_state::check_sprite_layer_bitpattern(int which, rectangle *sprite_areas)
441 {
442 offs_t offs = which * 4;
443 int result = 0; /* no collisions */
444
445 int check_layer_1 = *m_video_mode & layer_enable_mask[0];
446 int check_layer_2 = *m_video_mode & layer_enable_mask[1];
447 int check_layer_3 = *m_video_mode & layer_enable_mask[2];
448
449 int minx = sprite_areas[which].min_x;
450 int miny = sprite_areas[which].min_y;
451 int maxx = sprite_areas[which].max_x + 1;
452 int maxy = sprite_areas[which].max_y + 1;
453
454 int flip_x = (m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x01) ^ GLOBAL_FLIP_X;
455 int flip_y = (m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x02) ^ GLOBAL_FLIP_Y;
456
457 /* draw sprite into a bitmap and check if layers collide */
458 m_sprite_layer_collbitmap1.fill(TRANSPARENT_PEN);
459 get_sprite_gfx_element(which)->transpen(m_sprite_layer_collbitmap1,m_sprite_layer_collbitmap1.cliprect(),
460 m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x3f,
461 0,
462 flip_x, flip_y,
463 0,0,0);
464
465 for (int y = miny; y < maxy; y++)
466 for (int x = minx; x < maxx; x++)
467 if (m_sprite_layer_collbitmap1.pix(y - miny, x - minx) != TRANSPARENT_PEN) /* is there anything to check for ? */
468 {
469 if (check_layer_1 && (m_sprite_layer_collbitmap2[0].pix(y, x) != TRANSPARENT_PEN))
470 result |= 0x01; /* collided with layer 1 */
471
472 if (check_layer_2 && (m_sprite_layer_collbitmap2[1].pix(y, x) != TRANSPARENT_PEN))
473 result |= 0x02; /* collided with layer 2 */
474
475 if (check_layer_3 && (m_sprite_layer_collbitmap2[2].pix(y, x) != TRANSPARENT_PEN))
476 result |= 0x04; /* collided with layer 3 */
477 }
478
479 return result;
480 }
481
482
check_sprite_layer_collision(int * sprites_on,rectangle * sprite_areas)483 void taitosj_state::check_sprite_layer_collision(int *sprites_on, rectangle *sprite_areas)
484 {
485 if (SPRITES_ON)
486 {
487 /* check each sprite */
488 for (int which = 0; which < 0x20; which++)
489 {
490 if ((which >= 0x10) && (which <= 0x17)) continue; /* no sprites here */
491
492 if (sprites_on[which])
493 m_collision_reg[3] |= check_sprite_layer_bitpattern(which, sprite_areas);
494 }
495 }
496 }
497
498
draw_layers()499 void taitosj_state::draw_layers()
500 {
501 offs_t offs;
502
503 m_layer_bitmap[0].fill(TRANSPARENT_PEN);
504 m_layer_bitmap[1].fill(TRANSPARENT_PEN);
505 m_layer_bitmap[2].fill(TRANSPARENT_PEN);
506
507 for (offs = 0; offs < 0x0400; offs++)
508 {
509 int sx = offs % 32;
510 int sy = offs / 32;
511
512 if (GLOBAL_FLIP_X) sx = 31 - sx;
513 if (GLOBAL_FLIP_Y) sy = 31 - sy;
514
515 m_gfxdecode->gfx(m_colorbank[0] & 0x08 ? 2 : 0)->transpen(m_layer_bitmap[0],m_layer_bitmap[0].cliprect(),
516 m_videoram_1[offs],
517 m_colorbank[0] & 0x07,
518 GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
519 8*sx,8*sy,0);
520
521 m_gfxdecode->gfx(m_colorbank[0] & 0x80 ? 2 : 0)->transpen(m_layer_bitmap[1],m_layer_bitmap[1].cliprect(),
522 m_videoram_2[offs],
523 (m_colorbank[0] >> 4) & 0x07,
524 GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
525 8*sx,8*sy,0);
526
527 m_gfxdecode->gfx(m_colorbank[1] & 0x08 ? 2 : 0)->transpen(m_layer_bitmap[2],m_layer_bitmap[2].cliprect(),
528 m_videoram_3[offs],
529 m_colorbank[1] & 0x07,
530 GLOBAL_FLIP_X,GLOBAL_FLIP_Y,
531 8*sx,8*sy,0);
532 }
533 }
534
535
draw_sprites(bitmap_ind16 & bitmap)536 void taitosj_state::draw_sprites(bitmap_ind16 &bitmap)
537 {
538 /*
539 sprite visibility area is missing 4 pixels from the sides, surely to reduce
540 wraparound side effects. This was verified on a real Elevator Action.
541 Note that the clipping is asymmetrical. This matches the real thing.
542 I'm not sure of what should happen when the screen is flipped, though.
543 */
544 const rectangle spritevisiblearea(0*8+3, 32*8-1-1, 2*8, 30*8-1);
545 const rectangle spritevisibleareaflip(0*8+1, 32*8-3-1, 2*8, 30*8-1);
546
547 if (SPRITES_ON)
548 {
549 int sprite;
550
551 /* drawing order is a bit strange. The last sprite has to be moved at the start of the list. */
552 for (sprite = 0x1f; sprite >= 0; sprite--)
553 {
554 uint8_t sx, sy;
555
556 int which = (sprite - 1) & 0x1f; /* move last sprite at the head of the list */
557 offs_t offs = which * 4;
558
559 if ((which >= 0x10) && (which <= 0x17)) continue; /* no sprites here */
560
561 if (get_sprite_xy(which, &sx, &sy))
562 {
563 int code = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 3] & 0x3f;
564 int color = 2 * ((m_colorbank[1] >> 4) & 0x03) + ((m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] >> 2) & 0x01);
565 int flip_x = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x01;
566 int flip_y = m_spriteram[SPRITE_RAM_PAGE_OFFSET + offs + 2] & 0x02;
567
568 if (GLOBAL_FLIP_X)
569 {
570 sx = 238 - sx;
571 flip_x = !flip_x;
572 }
573
574 if (GLOBAL_FLIP_Y)
575 {
576 sy = 242 - sy;
577 flip_y = !flip_y;
578 }
579
580 get_sprite_gfx_element(which)->transpen(bitmap,GLOBAL_FLIP_X ? spritevisibleareaflip : spritevisiblearea, code, color,
581 flip_x, flip_y, sx, sy,0);
582
583 /* draw with wrap around. The horizontal games (eg. sfposeid) need this */
584 get_sprite_gfx_element(which)->transpen(bitmap,GLOBAL_FLIP_X ? spritevisibleareaflip : spritevisiblearea, code, color,
585 flip_x, flip_y, sx - 0x100, sy,0);
586 }
587 }
588 }
589 }
590
591
taitosj_copy_layer(bitmap_ind16 & bitmap,const rectangle & cliprect,int which,int * sprites_on,rectangle * sprite_areas)592 void taitosj_state::taitosj_copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,int which, int *sprites_on, rectangle *sprite_areas)
593 {
594 static const int fudge1[3] = { 3, 1, -1 };
595 static const int fudge2[3] = { 8, 10, 12 };
596
597 if (*m_video_mode & layer_enable_mask[which])
598 {
599 int i, scrollx, scrolly[32];
600
601 scrollx = m_scroll[2 * which];
602
603 if (GLOBAL_FLIP_X)
604 scrollx = (scrollx & 0xf8) + ((scrollx + fudge1[which]) & 7) + fudge2[which];
605 else
606 scrollx = -(scrollx & 0xf8) + ((scrollx + fudge1[which]) & 7) + fudge2[which];
607
608 if (GLOBAL_FLIP_Y)
609 for (i = 0;i < 32;i++)
610 scrolly[31 - i] = m_colscrolly[32 * which + i] + m_scroll[2 * which + 1];
611 else
612 for (i = 0;i < 32;i++)
613 scrolly[i] = -m_colscrolly[32 * which + i] - m_scroll[2 * which + 1];
614
615 copyscrollbitmap_trans(bitmap, m_layer_bitmap[which], 1, &scrollx, 32, scrolly, cliprect, TRANSPARENT_PEN);
616
617 /* store parts covered with sprites for sprites/layers collision detection */
618 for (i = 0; i < 0x20; i++)
619 {
620 if ((i >= 0x10) && (i <= 0x17)) continue; /* no sprites here */
621
622 if (sprites_on[i])
623 copyscrollbitmap(m_sprite_layer_collbitmap2[which], m_layer_bitmap[which], 1, &scrollx, 32, scrolly, sprite_areas[i]);
624 }
625 }
626 }
627
628
kikstart_copy_layer(bitmap_ind16 & bitmap,const rectangle & cliprect,int which,int * sprites_on,rectangle * sprite_areas)629 void taitosj_state::kikstart_copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,int which, int *sprites_on, rectangle *sprite_areas)
630 {
631 if (*m_video_mode & layer_enable_mask[which])
632 {
633 int i, scrolly, scrollx[32 * 8];
634
635 for (i = 1; i < 32*8; i++) /* 1-255 ! */
636 if (GLOBAL_FLIP_Y)
637 switch (which)
638 {
639 case 0: scrollx[32 * 8 - i] = 0 ;break;
640 case 1: scrollx[32 * 8 - i] = m_kikstart_scrollram[i] + ((m_scroll[2 * which] + 0x0a) & 0xff);break;
641 case 2: scrollx[32 * 8 - i] = m_kikstart_scrollram[0x100 + i] + ((m_scroll[2 * which] + 0xc) & 0xff);break;
642 }
643 else
644 switch (which)
645 {
646 case 0: scrollx[i] = 0 ;break;
647 case 1: scrollx[i] = 0xff - m_kikstart_scrollram[i - 1] - ((m_scroll[2 * which] - 0x10) & 0xff);break;
648 case 2: scrollx[i] = 0xff - m_kikstart_scrollram[0x100 + i - 1] - ((m_scroll[2 * which] - 0x12) & 0xff);break;
649 }
650
651 scrolly = m_scroll[2 * which + 1]; /* always 0 */
652 copyscrollbitmap_trans(bitmap, m_layer_bitmap[which], 32 * 8, scrollx, 1, &scrolly, cliprect, TRANSPARENT_PEN);
653
654 /* store parts covered with sprites for sprites/layers collision detection */
655 for (i = 0; i < 0x20; i++)
656 {
657 if ((i >= 0x10) && (i <= 0x17)) continue; /* no sprites here */
658
659 if (sprites_on[i])
660 copyscrollbitmap(m_sprite_layer_collbitmap2[which], m_layer_bitmap[which], 32 * 8, scrollx, 1, &scrolly, sprite_areas[i]);
661 }
662 }
663 }
664
665
copy_layer(bitmap_ind16 & bitmap,const rectangle & cliprect,copy_layer_func_t copy_layer_func,int which,int * sprites_on,rectangle * sprite_areas)666 void taitosj_state::copy_layer(bitmap_ind16 &bitmap, const rectangle &cliprect,copy_layer_func_t copy_layer_func, int which, int *sprites_on, rectangle *sprite_areas)
667 {
668 if (which == 0)
669 draw_sprites(bitmap);
670 else
671 (this->*copy_layer_func)(bitmap, cliprect, which - 1, sprites_on, sprite_areas);
672 }
673
674
copy_layers(bitmap_ind16 & bitmap,const rectangle & cliprect,copy_layer_func_t copy_layer_func,int * sprites_on,rectangle * sprite_areas)675 void taitosj_state::copy_layers(bitmap_ind16 &bitmap, const rectangle &cliprect,copy_layer_func_t copy_layer_func, int *sprites_on, rectangle *sprite_areas)
676 {
677 int i = 0;
678
679 /* fill the screen with the background color */
680 bitmap.fill(8 * (m_colorbank[1] & 0x07), cliprect);
681
682 for (i = 0; i < 4; i++)
683 {
684 int which = m_draw_order[*m_video_priority & 0x1f][i];
685
686 copy_layer(bitmap, cliprect, copy_layer_func, which, sprites_on, sprite_areas);
687 }
688 }
689
690
check_collision(int * sprites_on,rectangle * sprite_areas)691 void taitosj_state::check_collision(int *sprites_on, rectangle *sprite_areas)
692 {
693 check_sprite_sprite_collision();
694
695 check_sprite_layer_collision(sprites_on, sprite_areas);
696
697 /*check_layer_layer_collision();*/ /* not implemented !!! */
698 }
699
700
video_update_common(bitmap_ind16 & bitmap,const rectangle & cliprect,copy_layer_func_t copy_layer_func)701 int taitosj_state::video_update_common(bitmap_ind16 &bitmap, const rectangle &cliprect, copy_layer_func_t copy_layer_func)
702 {
703 int sprites_on[0x20]; /* 1 if sprite is active */
704 rectangle sprite_areas[0x20]; /* areas on bitmap (sprite locations) */
705
706 set_pens();
707
708 draw_layers();
709
710 calculate_sprite_areas(sprites_on, sprite_areas);
711
712 copy_layers(bitmap, cliprect, copy_layer_func, sprites_on, sprite_areas);
713
714 /*check_sprite_layer_collision() uses drawn bitmaps, so it must me called _AFTER_ draw_layers() */
715 check_collision(sprites_on, sprite_areas);
716
717 return 0;
718 }
719
720
screen_update_taitosj(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)721 uint32_t taitosj_state::screen_update_taitosj(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
722 {
723 return video_update_common(bitmap, cliprect, &taitosj_state::taitosj_copy_layer);
724 }
725
726
screen_update_kikstart(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)727 uint32_t taitosj_state::screen_update_kikstart(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
728 {
729 return video_update_common(bitmap, cliprect, &taitosj_state::kikstart_copy_layer);
730 }
731