1 /******************************************************************************
2 
3 	Video Hardware for Video System Mahjong series and Pipe Dream.
4 
5 	Driver by Takahiro Nogi <nogi@kt.rim.or.jp> 2001/02/04 -
6 	and Bryan McPhail, Nicola Salmoria, Aaron Giles
7 
8 ******************************************************************************/
9 
10 #include "driver.h"
11 #include "vidhrdw/generic.h"
12 #include "fromance.h"
13 
14 
15 static UINT8 selected_videoram;
16 static data8_t *local_videoram[2];
17 
18 static UINT8 selected_paletteram;
19 static data8_t *local_paletteram;
20 
21 static int scrollx[2], scrolly[2];
22 static UINT8 gfxreg;
23 static UINT8 flipscreen;
24 
25 static UINT8 crtc_register;
26 static UINT8 crtc_data[0x10];
27 static void *crtc_timer;
28 
29 static struct tilemap *bg_tilemap, *fg_tilemap;
30 
31 
32 static void crtc_interrupt_gen(int param);
33 
34 
35 /*************************************
36  *
37  *	Tilemap callbacks
38  *
39  *************************************/
40 
get_fromance_tile_info(int tile_index,int layer)41 static INLINE void get_fromance_tile_info(int tile_index,int layer)
42 {
43 	int tile = ((local_videoram[layer][0x0000 + tile_index] & 0x80) << 9) |
44 				(local_videoram[layer][0x1000 + tile_index] << 8) |
45 				local_videoram[layer][0x2000 + tile_index];
46 	int color = local_videoram[layer][tile_index] & 0x7f;
47 
48 	SET_TILE_INFO(layer, tile, color, 0);
49 }
50 
get_fromance_bg_tile_info(int tile_index)51 static void get_fromance_bg_tile_info(int tile_index) { get_fromance_tile_info(tile_index, 0); }
get_fromance_fg_tile_info(int tile_index)52 static void get_fromance_fg_tile_info(int tile_index) { get_fromance_tile_info(tile_index, 1); }
53 
get_nekkyoku_tile_info(int tile_index,int layer)54 static INLINE void get_nekkyoku_tile_info(int tile_index,int layer)
55 {
56 	int tile = (local_videoram[layer][0x0000 + tile_index] << 8) |
57 				local_videoram[layer][0x1000 + tile_index];
58 	int color = local_videoram[layer][tile_index + 0x2000] & 0x3f;
59 
60 	SET_TILE_INFO(layer, tile, color, 0);
61 }
62 
get_nekkyoku_bg_tile_info(int tile_index)63 static void get_nekkyoku_bg_tile_info(int tile_index) { get_nekkyoku_tile_info(tile_index, 0); }
get_nekkyoku_fg_tile_info(int tile_index)64 static void get_nekkyoku_fg_tile_info(int tile_index) { get_nekkyoku_tile_info(tile_index, 1); }
65 
66 
67 
68 /*************************************
69  *
70  *	Video system start
71  *
72  *************************************/
73 
VIDEO_START(fromance)74 VIDEO_START( fromance )
75 {
76 	/* allocate tilemaps */
77 	bg_tilemap = tilemap_create(get_fromance_bg_tile_info, tilemap_scan_rows, TILEMAP_OPAQUE,      8,4, 64,64);
78 	fg_tilemap = tilemap_create(get_fromance_fg_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8,4, 64,64);
79 
80 	/* allocate local videoram */
81 	local_videoram[0] = auto_malloc(0x1000 * 3);
82 	local_videoram[1] = auto_malloc(0x1000 * 3);
83 
84 	/* allocate local palette RAM */
85 	local_paletteram = auto_malloc(0x800 * 2);
86 
87 	/* handle failure */
88 	if (!bg_tilemap || !fg_tilemap || !local_videoram[0] || !local_videoram[1] || !local_paletteram)
89 		return 1;
90 
91 	/* configure tilemaps */
92 	tilemap_set_transparent_pen(fg_tilemap,15);
93 
94 	/* reset the timer */
95 	crtc_timer = timer_alloc(crtc_interrupt_gen);
96 	return 0;
97 }
98 
VIDEO_START(nekkyoku)99 VIDEO_START( nekkyoku )
100 {
101 	/* allocate tilemaps */
102 	bg_tilemap = tilemap_create(get_nekkyoku_bg_tile_info, tilemap_scan_rows, TILEMAP_OPAQUE,      8,4, 64,64);
103 	fg_tilemap = tilemap_create(get_nekkyoku_fg_tile_info, tilemap_scan_rows, TILEMAP_TRANSPARENT, 8,4, 64,64);
104 
105 	/* allocate local videoram */
106 	local_videoram[0] = auto_malloc(0x1000 * 3);
107 	local_videoram[1] = auto_malloc(0x1000 * 3);
108 
109 	/* allocate local palette RAM */
110 	local_paletteram = auto_malloc(0x800 * 2);
111 
112 	/* handle failure */
113 	if (!bg_tilemap || !fg_tilemap || !local_videoram[0] || !local_videoram[1] || !local_paletteram)
114 		return 1;
115 
116 	/* configure tilemaps */
117 	tilemap_set_transparent_pen(fg_tilemap,15);
118 
119 	/* reset the timer */
120 	crtc_timer = timer_alloc(crtc_interrupt_gen);
121 	return 0;
122 }
123 
124 
125 
126 /*************************************
127  *
128  *	Graphics control register
129  *
130  *************************************/
131 
WRITE_HANDLER(fromance_gfxreg_w)132 WRITE_HANDLER( fromance_gfxreg_w )
133 {
134 	static int flipscreen_old = -1;
135 
136 	gfxreg = data;
137 	flipscreen = (data & 0x01);
138 	selected_videoram = (~data >> 1) & 1;
139 	selected_paletteram = (data >> 6) & 1;
140 
141 	if (flipscreen != flipscreen_old)
142 	{
143 		flipscreen_old = flipscreen;
144 		tilemap_set_flip(ALL_TILEMAPS, flipscreen ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0);
145 	}
146 }
147 
148 
149 
150 /*************************************
151  *
152  *	Banked palette RAM
153  *
154  *************************************/
155 
READ_HANDLER(fromance_paletteram_r)156 READ_HANDLER( fromance_paletteram_r )
157 {
158 	/* adjust for banking and read */
159 	offset |= selected_paletteram << 11;
160 	return local_paletteram[offset];
161 }
162 
163 
WRITE_HANDLER(fromance_paletteram_w)164 WRITE_HANDLER( fromance_paletteram_w )
165 {
166 	int palword;
167 	int r, g, b;
168 
169 	/* adjust for banking and modify */
170 	offset |= selected_paletteram << 11;
171 	local_paletteram[offset] = data;
172 
173 	/* compute R,G,B */
174 	palword = (local_paletteram[offset | 1] << 8) | local_paletteram[offset & ~1];
175 	r = (palword >> 10) & 0x1f;
176 	g = (palword >>  5) & 0x1f;
177 	b = (palword >>  0) & 0x1f;
178 
179 	/* up to 8 bits */
180 	r = (r << 3) | (r >> 2);
181 	g = (g << 3) | (g >> 2);
182 	b = (b << 3) | (b >> 2);
183 	palette_set_color(offset / 2, r, g, b);
184 }
185 
186 
187 
188 /*************************************
189  *
190  *	Video RAM read/write
191  *
192  *************************************/
193 
READ_HANDLER(fromance_videoram_r)194 READ_HANDLER( fromance_videoram_r )
195 {
196 	return local_videoram[selected_videoram][offset];
197 }
198 
199 
WRITE_HANDLER(fromance_videoram_w)200 WRITE_HANDLER( fromance_videoram_w )
201 {
202 	local_videoram[selected_videoram][offset] = data;
203 	tilemap_mark_tile_dirty(selected_videoram ? fg_tilemap : bg_tilemap, offset & 0x0fff);
204 }
205 
206 
207 
208 /*************************************
209  *
210  *	Scroll registers
211  *
212  *************************************/
213 
WRITE_HANDLER(fromance_scroll_w)214 WRITE_HANDLER( fromance_scroll_w )
215 {
216 	if (flipscreen)
217 	{
218 		switch (offset)
219 		{
220 			case 0:
221 				scrollx[1] = (data + (((gfxreg & 0x08) >> 3) * 0x100) - 0x159);
222 				break;
223 			case 1:
224 				scrolly[1] = (data + (((gfxreg & 0x04) >> 2) * 0x100) - 0x10);
225 				break;
226 			case 2:
227 				scrollx[0] = (data + (((gfxreg & 0x20) >> 5) * 0x100) - 0x159);
228 				break;
229 			case 3:
230 				scrolly[0] = (data + (((gfxreg & 0x10) >> 4) * 0x100) - 0x10);
231 				break;
232 		}
233 	}
234 	else
235 	{
236 		switch (offset)
237 		{
238 			case 0:
239 				scrollx[1] = (data + (((gfxreg & 0x08) >> 3) * 0x100) - 0x1f7);
240 				break;
241 			case 1:
242 				scrolly[1] = (data + (((gfxreg & 0x04) >> 2) * 0x100) - 0xfa);
243 				break;
244 			case 2:
245 				scrollx[0] = (data + (((gfxreg & 0x20) >> 5) * 0x100) - 0x1f7);
246 				break;
247 			case 3:
248 				scrolly[0] = (data + (((gfxreg & 0x10) >> 4) * 0x100) - 0xfa);
249 				break;
250 		}
251 	}
252 }
253 
254 
255 
256 /*************************************
257  *
258  *	Fake video controller
259  *
260  *************************************/
261 
crtc_interrupt_gen(int param)262 static void crtc_interrupt_gen(int param)
263 {
264 	cpu_set_irq_line(1, 0, HOLD_LINE);
265 	if (param != 0)
266 		timer_adjust(crtc_timer, TIME_IN_HZ(Machine->drv->frames_per_second * param), 0, TIME_IN_HZ(Machine->drv->frames_per_second * param));
267 }
268 
269 
WRITE_HANDLER(fromance_crtc_data_w)270 WRITE_HANDLER( fromance_crtc_data_w )
271 {
272 	crtc_data[crtc_register] = data;
273 
274 	switch (crtc_register)
275 	{
276 		/* only register we know about.... */
277 		case 0x0b:
278 			timer_adjust(crtc_timer, cpu_getscanlinetime(Machine->visible_area.max_y + 1), (data > 0x80) ? 2 : 1, 0);
279 			break;
280 
281 		default:
282 			log_cb(RETRO_LOG_DEBUG, LOGPRE "CRTC register %02X = %02X\n", crtc_register, data & 0xff);
283 			break;
284 	}
285 }
286 
287 
WRITE_HANDLER(fromance_crtc_register_w)288 WRITE_HANDLER( fromance_crtc_register_w )
289 {
290 	crtc_register = data;
291 }
292 
293 
294 
295 /*************************************
296  *
297  *	Sprite routines (Pipe Dream)
298  *
299  *************************************/
300 
draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int draw_priority)301 static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int draw_priority)
302 {
303 	UINT8 zoomtable[16] = { 0,7,14,20,25,30,34,38,42,46,49,52,54,57,59,61 };
304 	int offs;
305 
306 	/* draw the sprites */
307 	for (offs = 0; offs < spriteram_size; offs += 8)
308 	{
309 		int data2 = spriteram[offs + 4] | (spriteram[offs + 5] << 8);
310 		int priority = (data2 >> 4) & 1;
311 
312 		/* turns out the sprites are the same as in aerofgt.c */
313 		if ((data2 & 0x80) && priority == draw_priority)
314 		{
315 			int data0 = spriteram[offs + 0] | (spriteram[offs + 1] << 8);
316 			int data1 = spriteram[offs + 2] | (spriteram[offs + 3] << 8);
317 			int data3 = spriteram[offs + 6] | (spriteram[offs + 7] << 8);
318 			int code = data3 & 0xfff;
319 			int color = data2 & 0x0f;
320 			int y = (data0 & 0x1ff) - 6;
321 			int x = (data1 & 0x1ff) - 13;
322 			int yzoom = (data0 >> 12) & 15;
323 			int xzoom = (data1 >> 12) & 15;
324 			int zoomed = (xzoom | yzoom);
325 			int ytiles = ((data2 >> 12) & 7) + 1;
326 			int xtiles = ((data2 >> 8) & 7) + 1;
327 			int yflip = (data2 >> 15) & 1;
328 			int xflip = (data2 >> 11) & 1;
329 			int xt, yt;
330 
331 			/* compute the zoom factor -- stolen from aerofgt.c */
332 			xzoom = 16 - zoomtable[xzoom] / 8;
333 			yzoom = 16 - zoomtable[yzoom] / 8;
334 
335 			/* wrap around */
336 			if (x > Machine->visible_area.max_x) x -= 0x200;
337 			if (y > Machine->visible_area.max_y) y -= 0x200;
338 
339 			/* normal case */
340 			if (!xflip && !yflip)
341 			{
342 				for (yt = 0; yt < ytiles; yt++)
343 					for (xt = 0; xt < xtiles; xt++, code++)
344 						if (!zoomed)
345 							drawgfx(bitmap, Machine->gfx[2], code, color, 0, 0,
346 									x + xt * 16, y + yt * 16, cliprect, TRANSPARENCY_PEN, 15);
347 						else
348 							drawgfxzoom(bitmap, Machine->gfx[2], code, color, 0, 0,
349 									x + xt * xzoom, y + yt * yzoom, cliprect, TRANSPARENCY_PEN, 15,
350 									0x1000 * xzoom, 0x1000 * yzoom);
351 			}
352 
353 			/* xflipped case */
354 			else if (xflip && !yflip)
355 			{
356 				for (yt = 0; yt < ytiles; yt++)
357 					for (xt = 0; xt < xtiles; xt++, code++)
358 						if (!zoomed)
359 							drawgfx(bitmap, Machine->gfx[2], code, color, 1, 0,
360 									x + (xtiles - 1 - xt) * 16, y + yt * 16, cliprect, TRANSPARENCY_PEN, 15);
361 						else
362 							drawgfxzoom(bitmap, Machine->gfx[2], code, color, 1, 0,
363 									x + (xtiles - 1 - xt) * xzoom, y + yt * yzoom, cliprect, TRANSPARENCY_PEN, 15,
364 									0x1000 * xzoom, 0x1000 * yzoom);
365 			}
366 
367 			/* yflipped case */
368 			else if (!xflip && yflip)
369 			{
370 				for (yt = 0; yt < ytiles; yt++)
371 					for (xt = 0; xt < xtiles; xt++, code++)
372 						if (!zoomed)
373 							drawgfx(bitmap, Machine->gfx[2], code, color, 0, 1,
374 									x + xt * 16, y + (ytiles - 1 - yt) * 16, cliprect, TRANSPARENCY_PEN, 15);
375 						else
376 							drawgfxzoom(bitmap, Machine->gfx[2], code, color, 0, 1,
377 									x + xt * xzoom, y + (ytiles - 1 - yt) * yzoom, cliprect, TRANSPARENCY_PEN, 15,
378 									0x1000 * xzoom, 0x1000 * yzoom);
379 			}
380 
381 			/* x & yflipped case */
382 			else
383 			{
384 				for (yt = 0; yt < ytiles; yt++)
385 					for (xt = 0; xt < xtiles; xt++, code++)
386 						if (!zoomed)
387 							drawgfx(bitmap, Machine->gfx[2], code, color, 1, 1,
388 									x + (xtiles - 1 - xt) * 16, y + (ytiles - 1 - yt) * 16, cliprect, TRANSPARENCY_PEN, 15);
389 						else
390 							drawgfxzoom(bitmap, Machine->gfx[2], code, color, 1, 1,
391 									x + (xtiles - 1 - xt) * xzoom, y + (ytiles - 1 - yt) * yzoom, cliprect, TRANSPARENCY_PEN, 15,
392 									0x1000 * xzoom, 0x1000 * yzoom);
393 			}
394 		}
395 	}
396 }
397 
398 
399 
400 /*************************************
401  *
402  *	Main screen refresh
403  *
404  *************************************/
405 
VIDEO_UPDATE(fromance)406 VIDEO_UPDATE( fromance )
407 {
408 	tilemap_set_scrollx(bg_tilemap, 0, scrollx[0]);
409 	tilemap_set_scrolly(bg_tilemap, 0, scrolly[0]);
410 	tilemap_set_scrollx(fg_tilemap, 0, scrollx[1]);
411 	tilemap_set_scrolly(fg_tilemap, 0, scrolly[1]);
412 
413 	tilemap_draw(bitmap,cliprect, bg_tilemap, 0, 0);
414 	tilemap_draw(bitmap,cliprect, fg_tilemap, 0, 0);
415 }
416 
417 
VIDEO_UPDATE(pipedrm)418 VIDEO_UPDATE( pipedrm )
419 {
420 	/* there seems to be no logical mapping for the X scroll register -- maybe it's gone */
421 	tilemap_set_scrolly(bg_tilemap, 0, scrolly[1]);
422 	tilemap_set_scrolly(fg_tilemap, 0, scrolly[0]);
423 
424 	tilemap_draw(bitmap,cliprect, bg_tilemap, 0, 0);
425 	tilemap_draw(bitmap,cliprect, fg_tilemap, 0, 0);
426 
427 	draw_sprites(bitmap,cliprect, 0);
428 	draw_sprites(bitmap,cliprect, 1);
429 }
430