1 /* Jaleco MegaSystem 32 Video Hardware */
2
3 /* The Video Hardware is Similar to the Non-MS32 Version of Tetris Plus 2 */
4
5 /* Plenty to do, see list in drivers/ms32.c */
6
7 /*
8
9 priority should be given to
10 (a) dekluding the priorities, the kludge for kirarast made it easier to emulate the rest of it until then
11 (b) working out the background registers correctly ...
12 */
13
14
15 #include "driver.h"
16
17 data32_t *ms32_fce00000;
18 data32_t *ms32_roz_ctrl;
19 data32_t *ms32_tx_scroll;
20 data32_t *ms32_bg_scroll;
21 data32_t *ms32_priram;
22 data32_t *ms32_palram;
23 data32_t *ms32_bgram;
24 data32_t *ms32_rozram;
25 data32_t *ms32_lineram;
26 data32_t *ms32_spram;
27 data32_t *ms32_txram;
28 data32_t *ms32_mainram;
29
30 // kirarast, tp2m32, and 47pie2 require the sprites in a different order
31 int ms32_reverse_sprite_order;
32
33 /********** Tilemaps **********/
34
35 static struct tilemap *ms32_tx_tilemap, *ms32_roz_tilemap, *ms32_bg_tilemap;
36 static int flipscreen;
37
38
get_ms32_tx_tile_info(int tile_index)39 static void get_ms32_tx_tile_info(int tile_index)
40 {
41 int tileno, colour;
42
43 tileno = ms32_txram[tile_index *2] & 0x0000ffff;
44 colour = ms32_txram[tile_index *2+1] & 0x000000f;
45
46 SET_TILE_INFO(3,tileno,colour,0)
47 }
48
get_ms32_roz_tile_info(int tile_index)49 static void get_ms32_roz_tile_info(int tile_index)
50 {
51 int tileno,colour;
52
53 tileno = ms32_rozram[tile_index *2] & 0x0000ffff;
54 colour = ms32_rozram[tile_index *2+1] & 0x000000f;
55
56 SET_TILE_INFO(1,tileno,colour,0)
57 }
58
get_ms32_bg_tile_info(int tile_index)59 static void get_ms32_bg_tile_info(int tile_index)
60 {
61 int tileno,colour;
62
63 tileno = ms32_bgram[tile_index *2] & 0x0000ffff;
64 colour = ms32_bgram[tile_index *2+1] & 0x000000f;
65
66 SET_TILE_INFO(2,tileno,colour,0)
67 }
68
69 static data32_t brt[4];
70 static int brt_r,brt_g,brt_b;
71
VIDEO_START(ms32)72 VIDEO_START( ms32 )
73 {
74 ms32_tx_tilemap = tilemap_create(get_ms32_tx_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT, 8, 8,64,64);
75 ms32_bg_tilemap = tilemap_create(get_ms32_bg_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,64,64);
76 ms32_roz_tilemap = tilemap_create(get_ms32_roz_tile_info,tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,128,128);
77
78 if (!ms32_tx_tilemap || !ms32_roz_tilemap || !ms32_bg_tilemap)
79 return 1;
80
81 tilemap_set_transparent_pen(ms32_tx_tilemap,0);
82 tilemap_set_transparent_pen(ms32_bg_tilemap,0);
83 tilemap_set_transparent_pen(ms32_roz_tilemap,0);
84
85 ms32_reverse_sprite_order = 1;
86
87 /* i hate per game patches...how should priority really work? tetrisp2.c ? i can't follow it */
88 if (!strcmp(Machine->gamedrv->name,"kirarast")) ms32_reverse_sprite_order = 0;
89 if (!strcmp(Machine->gamedrv->name,"tp2m32")) ms32_reverse_sprite_order = 0;
90 if (!strcmp(Machine->gamedrv->name,"47pie2")) ms32_reverse_sprite_order = 0;
91 if (!strcmp(Machine->gamedrv->name,"47pie2o")) ms32_reverse_sprite_order = 0;
92
93 // tp2m32 doesn't set the brightness registers so we need sensible defaults
94 brt[0] = brt[1] = 0xffff;
95
96 return 0;
97 }
98
99 /********** PALETTE WRITES **********/
100
101
update_color(int color)102 static void update_color(int color)
103 {
104 int r,g,b;
105
106 /* I'm not sure how the brightness should be applied, currently I'm only
107 affecting bg & sprites, not fg.
108 The second brightness control might apply to shadows, see gametngk.
109 */
110 if (~color & 0x4000)
111 {
112 r = ((ms32_palram[color*2] & 0xff00) >>8 ) * brt_r / 0x100;
113 g = ((ms32_palram[color*2] & 0x00ff) >>0 ) * brt_g / 0x100;
114 b = ((ms32_palram[color*2+1] & 0x00ff) >>0 ) * brt_b / 0x100;
115 }
116 else
117 {
118 r = ((ms32_palram[color*2] & 0xff00) >>8 );
119 g = ((ms32_palram[color*2] & 0x00ff) >>0 );
120 b = ((ms32_palram[color*2+1] & 0x00ff) >>0 );
121 }
122
123 palette_set_color(color,r,g,b);
124 }
125
WRITE32_HANDLER(ms32_brightness_w)126 WRITE32_HANDLER( ms32_brightness_w )
127 {
128 int oldword = brt[offset];
129 COMBINE_DATA(&brt[offset]);
130
131 if (brt[offset] != oldword)
132 {
133 int bank = ((offset & 2) >> 1) * 0x4000;
134 int i;
135
136 if (bank == 0)
137 {
138 brt_r = 0x100 - ((brt[0] & 0xff00) >> 8);
139 brt_g = 0x100 - ((brt[0] & 0x00ff) >> 0);
140 brt_b = 0x100 - ((brt[1] & 0x00ff) >> 0);
141
142 for (i = 0;i < 0x3000;i++) // colors 0x3000-0x3fff are not used
143 update_color(i);
144 }
145 }
146
147 //usrintf_showmessage("%04x %04x %04x %04x",brt[0],brt[1],brt[2],brt[3]);
148 }
149
WRITE32_HANDLER(ms32_palram_w)150 WRITE32_HANDLER( ms32_palram_w )
151 {
152 COMBINE_DATA(&ms32_palram[offset]);
153
154 update_color(offset/2);
155 }
156
157
158
READ32_HANDLER(ms32_txram_r)159 READ32_HANDLER( ms32_txram_r )
160 {
161 return ms32_txram[offset];
162 }
163
WRITE32_HANDLER(ms32_txram_w)164 WRITE32_HANDLER( ms32_txram_w )
165 {
166 COMBINE_DATA(&ms32_txram[offset]);
167 tilemap_mark_tile_dirty(ms32_tx_tilemap,offset/2);
168 }
169
READ32_HANDLER(ms32_rozram_r)170 READ32_HANDLER( ms32_rozram_r )
171 {
172 return ms32_rozram[offset];
173 }
174
WRITE32_HANDLER(ms32_rozram_w)175 WRITE32_HANDLER( ms32_rozram_w )
176 {
177 COMBINE_DATA(&ms32_rozram[offset]);
178 tilemap_mark_tile_dirty(ms32_roz_tilemap,offset/2);
179 }
180
READ32_HANDLER(ms32_lineram_r)181 READ32_HANDLER( ms32_lineram_r )
182 {
183 return ms32_lineram[offset];
184 }
185
WRITE32_HANDLER(ms32_lineram_w)186 WRITE32_HANDLER( ms32_lineram_w )
187 {
188 COMBINE_DATA(&ms32_lineram[offset]);
189 }
190
READ32_HANDLER(ms32_bgram_r)191 READ32_HANDLER( ms32_bgram_r )
192 {
193 return ms32_bgram[offset];
194 }
195
WRITE32_HANDLER(ms32_bgram_w)196 WRITE32_HANDLER( ms32_bgram_w )
197 {
198 COMBINE_DATA(&ms32_bgram[offset]);
199 tilemap_mark_tile_dirty(ms32_bg_tilemap,offset/2);
200 }
201
READ32_HANDLER(ms32_spram_r)202 READ32_HANDLER( ms32_spram_r )
203 {
204 return ms32_spram[offset];
205 }
206
WRITE32_HANDLER(ms32_spram_w)207 WRITE32_HANDLER( ms32_spram_w )
208 {
209 COMBINE_DATA(&ms32_spram[offset]);
210 }
211
READ32_HANDLER(ms32_priram_r)212 READ32_HANDLER( ms32_priram_r )
213 {
214 return ms32_priram[offset];
215 }
216
WRITE32_HANDLER(ms32_priram_w)217 WRITE32_HANDLER( ms32_priram_w )
218 {
219 COMBINE_DATA(&ms32_priram[offset]);
220 }
221
WRITE32_HANDLER(ms32_gfxctrl_w)222 WRITE32_HANDLER( ms32_gfxctrl_w )
223 {
224 if (ACCESSING_LSB32)
225 {
226 /* bit 1 = flip screen */
227 flipscreen = data & 0x02;
228 tilemap_set_flip(ms32_tx_tilemap,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
229 tilemap_set_flip(ms32_bg_tilemap,flipscreen ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
230
231 /* bit 2 used by f1superb, unknown */
232
233 /* bit 3 used by several games, unknown */
234
235 //usrintf_showmessage("%08x",data);
236 }
237 }
238
239
240
241 /* SPRITES based on tetrisp2 for now, readd priority bits later */
242
ms32_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,data32_t * sprram_top,size_t sprram_size)243 static void ms32_draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, data32_t *sprram_top, size_t sprram_size)
244 {
245 /***************************************************************************
246
247
248 Sprites Drawing
249
250 Offset: Bits: Meaning:
251
252 0.w fedc ba98 ---- ----
253 ---- ---- 7654 ---- Priority
254 ---- ---- ---- 3---
255 ---- ---- ---- -2-- Draw this sprite
256 ---- ---- ---- --1- Flip Y
257 ---- ---- ---- ---0 Flip X
258
259 1.w fedc ba98 ---- ---- Tile's Y position in the tile page (*)
260 ---- ---- 7654 3210 Tile's X position in the tile page (*)
261
262 2.w fedc ---- ---- ---- Color
263 ---- ba98 7654 3210 Tile Page (32x32 tiles = 256x256 pixels each)
264
265 3.w fedc ba98 ---- ---- Y Size - 1 (*)
266 ---- ---- 7654 3210 X Size - 1 (*)
267
268 4.w fedc ba-- ---- ----
269 ---- --98 7654 3210 Y (Signed)
270
271 5.w fedc b--- ---- ----
272 ---- -a98 7654 3210 X (Signed)
273
274 6.w fedc ba98 7654 3210 Zoom Y
275
276 7.w fedc ba98 7654 3210 Zoom X
277
278 (*) 1 pixel granularity
279
280 ***************************************************************************/
281
282 int tx, ty, sx, sy, flipx, flipy;
283 int xsize, ysize, xzoom, yzoom;
284 int code, attr, color, size, pri, pri_mask, trans;
285 struct GfxElement *gfx = Machine->gfx[0];
286 struct GfxElement mygfx = *gfx;
287
288 data32_t *source = sprram_top;
289 const data32_t *finish = sprram_top + (sprram_size - 0x10) / 4;
290
291
292 if (ms32_reverse_sprite_order == 1)
293 {
294 source = sprram_top + (sprram_size - 0x10) / 4;
295 finish = sprram_top;
296 }
297
298
299 for (;ms32_reverse_sprite_order ? (source>=finish) : (source<finish); ms32_reverse_sprite_order ? (source-=4) : (source+=4))
300 {
301 attr = source[ 0 ];
302
303 if ((attr & 0x0004) == 0) continue;
304
305 flipx = attr & 1;
306 flipy = attr & 2;
307
308 pri = (attr >> 4)&0xf;
309
310 code = source[ 1 ];
311 color = source[ 2 ];
312
313 tx = (code >> 0) & 0xff;
314 ty = (code >> 8) & 0xff;
315
316 code = (color & 0x0fff);
317
318 color = (color >> 12) & 0xf;
319
320 size = source[ 3 ];
321
322 xsize = ((size >> 0) & 0xff) + 1;
323 ysize = ((size >> 8) & 0xff) + 1;
324
325 sy = source[ 4 ];
326 sx = source[ 5 ];
327
328 sx = (sx & 0x3ff) - (sx & 0x400);
329 sy = (sy & 0x1ff) - (sy & 0x200);
330
331 xzoom = (source[ 6 ]&0xffff);
332 yzoom = (source[ 7 ]&0xffff);
333
334 if (!yzoom || !xzoom) continue;
335
336 yzoom = 0x1000000/yzoom;
337 xzoom = 0x1000000/xzoom;
338
339 trans = TRANSPARENCY_PEN; // there are surely also shadows (see gametngk) but how they're enabled we don't know
340
341 if (flipscreen)
342 {
343 sx = 320 - ((xsize*xzoom)>>16) - sx;
344 sy = 224 - ((ysize*yzoom)>>16) - sy;
345 flipx = !flipx;
346 flipy = !flipy;
347 }
348
349 /* change GfxElement parameters to draw only the needed part of the 256x256 tile */
350 mygfx.width = xsize;
351 mygfx.height = ysize;
352 mygfx.gfxdata = gfx->gfxdata + tx + ty * gfx->line_modulo;
353
354 #if 0
355 if (keyboard_pressed(KEYCODE_A) && (pri & 8)) color = rand();
356 if (keyboard_pressed(KEYCODE_S) && (pri & 4)) color = rand();
357 if (keyboard_pressed(KEYCODE_D) && (pri & 2)) color = rand();
358 if (keyboard_pressed(KEYCODE_F) && (pri & 1)) color = rand();
359 #endif
360
361 /* TODO: priority handling is completely wrong, but better than nothing */
362 if (pri == 0x0)
363 pri_mask = 0x00;
364 else if (pri <= 0xd)
365 pri_mask = 0xf0;
366 else if (pri <= 0xe)
367 pri_mask = 0xfc;
368 else
369 pri_mask = 0xfe;
370
371 pdrawgfxzoom(bitmap, &mygfx,
372 code,
373 color,
374 flipx, flipy,
375 sx,sy,
376 cliprect, trans, 0,
377 xzoom, yzoom, pri_mask);
378 } /* end sprite loop */
379 }
380
381
382
draw_roz(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int priority)383 static void draw_roz(struct mame_bitmap *bitmap, const struct rectangle *cliprect,int priority)
384 {
385 /* TODO: registers 0x40/4 / 0x44/4 and 0x50/4 / 0x54/4 are used, meaning unknown */
386
387 if (ms32_roz_ctrl[0x5c/4] & 1) /* "super" mode */
388 {
389 struct rectangle my_clip;
390 int y,maxy;
391
392 my_clip.min_x = cliprect->min_x;
393 my_clip.max_x = cliprect->max_x;
394
395 y = cliprect->min_y;
396 maxy = cliprect->max_y;
397
398 while (y <= maxy)
399 {
400 data32_t *lineaddr = ms32_lineram + 8 * (y & 0xff);
401
402 int start2x = (lineaddr[0x00/4] & 0xffff) | ((lineaddr[0x04/4] & 3) << 16);
403 int start2y = (lineaddr[0x08/4] & 0xffff) | ((lineaddr[0x0c/4] & 3) << 16);
404 int incxx = (lineaddr[0x10/4] & 0xffff) | ((lineaddr[0x14/4] & 1) << 16);
405 int incxy = (lineaddr[0x18/4] & 0xffff) | ((lineaddr[0x1c/4] & 1) << 16);
406 int startx = (ms32_roz_ctrl[0x00/4] & 0xffff) | ((ms32_roz_ctrl[0x04/4] & 3) << 16);
407 int starty = (ms32_roz_ctrl[0x08/4] & 0xffff) | ((ms32_roz_ctrl[0x0c/4] & 3) << 16);
408 int offsx = ms32_roz_ctrl[0x30/4];
409 int offsy = ms32_roz_ctrl[0x34/4];
410
411 my_clip.min_y = my_clip.max_y = y;
412
413 offsx += (ms32_roz_ctrl[0x38/4] & 1) * 0x400; // ??? gratia, hayaosi1...
414 offsy += (ms32_roz_ctrl[0x3c/4] & 1) * 0x400; // ??? gratia, hayaosi1...
415
416 /* extend sign */
417 if (start2x & 0x20000) start2x |= ~0x3ffff;
418 if (start2y & 0x20000) start2y |= ~0x3ffff;
419 if (startx & 0x20000) startx |= ~0x3ffff;
420 if (starty & 0x20000) starty |= ~0x3ffff;
421 if (incxx & 0x10000) incxx |= ~0x1ffff;
422 if (incxy & 0x10000) incxy |= ~0x1ffff;
423
424 tilemap_draw_roz(bitmap, &my_clip, ms32_roz_tilemap,
425 (start2x+startx+offsx)<<16, (start2y+starty+offsy)<<16,
426 incxx<<8, incxy<<8, 0, 0,
427 1, // Wrap
428 0, priority);
429
430 y++;
431 }
432 }
433 else /* "simple" mode */
434 {
435 int startx = (ms32_roz_ctrl[0x00/4] & 0xffff) | ((ms32_roz_ctrl[0x04/4] & 3) << 16);
436 int starty = (ms32_roz_ctrl[0x08/4] & 0xffff) | ((ms32_roz_ctrl[0x0c/4] & 3) << 16);
437 int incxx = (ms32_roz_ctrl[0x10/4] & 0xffff) | ((ms32_roz_ctrl[0x14/4] & 1) << 16);
438 int incxy = (ms32_roz_ctrl[0x18/4] & 0xffff) | ((ms32_roz_ctrl[0x1c/4] & 1) << 16);
439 int incyy = (ms32_roz_ctrl[0x20/4] & 0xffff) | ((ms32_roz_ctrl[0x24/4] & 1) << 16);
440 int incyx = (ms32_roz_ctrl[0x28/4] & 0xffff) | ((ms32_roz_ctrl[0x2c/4] & 1) << 16);
441 int offsx = ms32_roz_ctrl[0x30/4];
442 int offsy = ms32_roz_ctrl[0x34/4];
443
444 offsx += (ms32_roz_ctrl[0x38/4] & 1) * 0x400; // ??? gratia, hayaosi1...
445 offsy += (ms32_roz_ctrl[0x3c/4] & 1) * 0x400; // ??? gratia, hayaosi1...
446
447 /* extend sign */
448 if (startx & 0x20000) startx |= ~0x3ffff;
449 if (starty & 0x20000) starty |= ~0x3ffff;
450 if (incxx & 0x10000) incxx |= ~0x1ffff;
451 if (incxy & 0x10000) incxy |= ~0x1ffff;
452 if (incyy & 0x10000) incyy |= ~0x1ffff;
453 if (incyx & 0x10000) incyx |= ~0x1ffff;
454
455 tilemap_draw_roz(bitmap, cliprect, ms32_roz_tilemap,
456 (startx+offsx)<<16, (starty+offsy)<<16,
457 incxx<<8, incxy<<8, incyx<<8, incyy<<8,
458 1, // Wrap
459 0, priority);
460 }
461 }
462
463
464
VIDEO_UPDATE(ms32)465 VIDEO_UPDATE( ms32 )
466 {
467 int scrollx,scrolly;
468
469 /* TODO: registers 0x04/4 and 0x10/4 are used too; the most interesting case
470 is gametngk, where they are *usually*, but not always, copies of 0x00/4
471 and 0x0c/4 (used for scrolling).
472 0x10/4 is 0xdf in most games (apart from gametngk's special case), but
473 it's 0x00 in hayaosi1 and kirarast, and 0xe2 (!) in gratia's tx layer.
474 The two registers might be somewhat related to the width and height of the
475 tilemaps, but there's something that just doesn't fit.
476 */
477 scrollx = ms32_tx_scroll[0x00/4] + ms32_tx_scroll[0x08/4] + 0x18;
478 scrolly = ms32_tx_scroll[0x0c/4] + ms32_tx_scroll[0x14/4];
479 tilemap_set_scrollx(ms32_tx_tilemap, 0, scrollx);
480 tilemap_set_scrolly(ms32_tx_tilemap, 0, scrolly);
481
482 scrollx = ms32_bg_scroll[0x00/4] + ms32_bg_scroll[0x08/4] + 0x10;
483 scrolly = ms32_bg_scroll[0x0c/4] + ms32_bg_scroll[0x14/4];
484 tilemap_set_scrollx(ms32_bg_tilemap, 0, scrollx);
485 tilemap_set_scrolly(ms32_bg_tilemap, 0, scrolly);
486
487
488 fillbitmap(priority_bitmap,0,cliprect);
489
490 /* TODO: 0 is correct for gametngk, but break f1superb scrolling grid (text at
491 top and bottom of the screen becomes black on black) */
492 fillbitmap(bitmap,Machine->pens[0],cliprect); /* bg color */
493
494 #ifdef MAME_DEBUG
495 if (!keyboard_pressed(KEYCODE_Q))
496 #endif
497 tilemap_draw(bitmap,cliprect,ms32_bg_tilemap,0,1);
498
499 #ifdef MAME_DEBUG
500 if (!keyboard_pressed(KEYCODE_W))
501 #endif
502 draw_roz(bitmap,cliprect,2);
503
504 #ifdef MAME_DEBUG
505 if (!keyboard_pressed(KEYCODE_E))
506 #endif
507 tilemap_draw(bitmap,cliprect,ms32_tx_tilemap,0,4);
508
509 #ifdef MAME_DEBUG
510 if (!keyboard_pressed(KEYCODE_R))
511 #endif
512 ms32_draw_sprites(bitmap,cliprect, ms32_spram, 0x40000);
513 }
514