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