1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 d800-dbff	foreground:			char low bits (1 screen * 1024 chars/screen)
8 dc00-dfff	foreground attribute:	7		?
9 						 6543		color
10 						     21	?
11 						       0	char hi bit
12 
13 
14 e000-e0ff	spriteram:  64 sprites (4 bytes/sprite)
15 		offset :	0		1		2		3
16 		meaning:	ypos(lo)	sprite(lo)	attribute	xpos(lo)
17 								7   flipy
18 								6   flipx
19 								5-2 color
20 								1   sprite(hi)
21 								0   xpos(hi)
22 
23 
24 background:	0x4000 bytes of ROM:	76543210	tile code low bits
25 		0x4000 bytes of ROM:	7		?
26 						 6543		color
27 						     2	?
28 						      10	tile code high bits
29 
30 ***************************************************************************/
31 
32 #include "driver.h"
33 #include "vidhrdw/generic.h"
34 
35 static unsigned char scrollx[2], scrolly[2];
36 
37 /* Layers has only bits 5-6 active.
38    6 selects background off/on
39    5 is unknown (active only on title screen,
40      not for scores or push start nor game)
41 */
42 
43 static int flipscreen, layers;
44 
45 static struct tilemap *bg_tilemap, *tx_tilemap;
46 
47 static const unsigned char *spritepalettebank;
48 static int ninjemak_dispdisable;
49 
50 
51 
52 /***************************************************************************
53 
54   Convert the color PROMs into a more useable format.
55 
56 ***************************************************************************/
57 
PALETTE_INIT(galivan)58 PALETTE_INIT( galivan )
59 {
60 	int i;
61 	#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
62 	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
63 
64 	for (i = 0;i < Machine->drv->total_colors;i++)
65 	{
66 		int bit0,bit1,bit2,bit3,r,g,b;
67 
68 		bit0 = (color_prom[0] >> 0) & 0x01;
69 		bit1 = (color_prom[0] >> 1) & 0x01;
70 		bit2 = (color_prom[0] >> 2) & 0x01;
71 		bit3 = (color_prom[0] >> 3) & 0x01;
72 		r = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
73 		bit0 = (color_prom[Machine->drv->total_colors] >> 0) & 0x01;
74 		bit1 = (color_prom[Machine->drv->total_colors] >> 1) & 0x01;
75 		bit2 = (color_prom[Machine->drv->total_colors] >> 2) & 0x01;
76 		bit3 = (color_prom[Machine->drv->total_colors] >> 3) & 0x01;
77 		g = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
78 		bit0 = (color_prom[2*Machine->drv->total_colors] >> 0) & 0x01;
79 		bit1 = (color_prom[2*Machine->drv->total_colors] >> 1) & 0x01;
80 		bit2 = (color_prom[2*Machine->drv->total_colors] >> 2) & 0x01;
81 		bit3 = (color_prom[2*Machine->drv->total_colors] >> 3) & 0x01;
82 		b = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
83 
84 		palette_set_color(i,r,g,b);
85 		color_prom++;
86 	}
87 
88 	color_prom += 2*Machine->drv->total_colors;
89 	/* color_prom now points to the beginning of the lookup tables */
90 
91 
92 	/* characters use colors 0-127 */
93 	for (i = 0;i < TOTAL_COLORS(0);i++)
94 		COLOR(0,i) = i;
95 
96 	/* I think that */
97 	/* background tiles use colors 192-255 in four banks */
98 	/* the bottom two bits of the color code select the palette bank for */
99 	/* pens 0-7; the top two bits for pens 8-15. */
100 	for (i = 0;i < TOTAL_COLORS(1);i++)
101 	{
102 		if (i & 8) COLOR(1,i) = 192 + (i & 0x0f) + ((i & 0xc0) >> 2);
103 		else COLOR(1,i) = 192 + (i & 0x0f) + ((i & 0x30) >> 0);
104 	}
105 
106 
107 	/* sprites use colors 128-191 in four banks */
108 	/* The lookup table tells which colors to pick from the selected bank */
109 	/* the bank is selected by another PROM and depends on the top 7 bits of */
110 	/* the sprite code. The PROM selects the bank *separately* for pens 0-7 and */
111 	/* 8-15 (like for tiles). */
112 	for (i = 0;i < TOTAL_COLORS(2)/16;i++)
113 	{
114 		int j;
115 
116 		for (j = 0;j < 16;j++)
117 		{
118 			if (i & 8)
119 				COLOR(2,i + j * (TOTAL_COLORS(2)/16)) = 128 + ((j & 0x0c) << 2) + (*color_prom & 0x0f);
120 			else
121 				COLOR(2,i + j * (TOTAL_COLORS(2)/16)) = 128 + ((j & 0x03) << 4) + (*color_prom & 0x0f);
122 		}
123 
124 		color_prom++;
125 	}
126 
127 	/* color_prom now points to the beginning of the sprite palette bank table */
128 	spritepalettebank = color_prom;	/* we'll need it at run time */
129 }
130 
131 
132 
133 /***************************************************************************
134 
135   Callbacks for the TileMap code
136 
137 ***************************************************************************/
138 
get_bg_tile_info(int tile_index)139 static void get_bg_tile_info(int tile_index)
140 {
141 	unsigned char *BGROM = memory_region(REGION_GFX4);
142 	int attr = BGROM[tile_index + 0x4000];
143 	int code = BGROM[tile_index] | ((attr & 0x03) << 8);
144 	SET_TILE_INFO(
145 			1,
146 			code,
147 			(attr & 0x78) >> 3,		/* seems correct */
148 			0)
149 }
150 
get_tx_tile_info(int tile_index)151 static void get_tx_tile_info(int tile_index)
152 {
153 	int attr = colorram[tile_index];
154 	int code = videoram[tile_index] | ((attr & 0x01) << 8);
155 	SET_TILE_INFO(
156 			0,
157 			code,
158 			(attr & 0xe0) >> 5,		/* not sure */
159 			0)
160 	tile_info.priority = attr & 8 ? 0 : 1;	/* wrong */
161 }
162 
ninjemak_get_bg_tile_info(int tile_index)163 static void ninjemak_get_bg_tile_info(int tile_index)
164 {
165 	unsigned char *BGROM = memory_region(REGION_GFX4);
166 	int attr = BGROM[tile_index + 0x4000];
167 	int code = BGROM[tile_index] | ((attr & 0x03) << 8);
168 	SET_TILE_INFO(
169 			1,
170 			code,
171 			((attr & 0x60) >> 3) | ((attr & 0x0c) >> 2),	/* seems correct */
172 			0)
173 }
174 
ninjemak_get_tx_tile_info(int tile_index)175 static void ninjemak_get_tx_tile_info(int tile_index)
176 {
177 	int attr = colorram[tile_index];
178 	int code = videoram[tile_index] | ((attr & 0x03) << 8);
179 	SET_TILE_INFO(
180 			0,
181 			code,
182 			(attr & 0x1c) >> 2,		/* seems correct ? */
183 			0)
184 }
185 
186 
187 
188 /***************************************************************************
189 
190   Start the video hardware emulation.
191 
192 ***************************************************************************/
193 
VIDEO_START(galivan)194 VIDEO_START( galivan )
195 {
196 	bg_tilemap = tilemap_create(get_bg_tile_info,tilemap_scan_rows,TILEMAP_OPAQUE,   16,16,128,128);
197 	tx_tilemap = tilemap_create(get_tx_tile_info,tilemap_scan_cols,TILEMAP_TRANSPARENT,8,8,32,32);
198 
199 	if (!bg_tilemap || !tx_tilemap)
200 		return 1;
201 
202 	tilemap_set_transparent_pen(tx_tilemap,15);
203 
204 	return 0;
205 }
206 
VIDEO_START(ninjemak)207 VIDEO_START( ninjemak )
208 {
209 	bg_tilemap = tilemap_create(ninjemak_get_bg_tile_info,tilemap_scan_cols,TILEMAP_OPAQUE,   16,16,512,32);
210 	tx_tilemap = tilemap_create(ninjemak_get_tx_tile_info,tilemap_scan_cols,TILEMAP_TRANSPARENT,8,8,32,32);
211 
212 	if (!bg_tilemap || !tx_tilemap)
213 		return 1;
214 
215 	tilemap_set_transparent_pen(tx_tilemap,15);
216 
217 	return 0;
218 }
219 
220 
221 
222 /***************************************************************************
223 
224   Memory handlers
225 
226 ***************************************************************************/
227 
WRITE_HANDLER(galivan_videoram_w)228 WRITE_HANDLER( galivan_videoram_w )
229 {
230 	if (videoram[offset] != data)
231 	{
232 		videoram[offset] = data;
233 		tilemap_mark_tile_dirty(tx_tilemap,offset);
234 	}
235 }
236 
WRITE_HANDLER(galivan_colorram_w)237 WRITE_HANDLER( galivan_colorram_w )
238 {
239 	if (colorram[offset] != data)
240 	{
241 		colorram[offset] = data;
242 		tilemap_mark_tile_dirty(tx_tilemap,offset);
243 	}
244 }
245 
246 /* Written through port 40 */
WRITE_HANDLER(galivan_gfxbank_w)247 WRITE_HANDLER( galivan_gfxbank_w )
248 {
249 	/* bits 0 and 1 coin counters */
250 	coin_counter_w(0,data & 1);
251 	coin_counter_w(1,data & 2);
252 
253 	/* bit 2 flip screen */
254 	flipscreen = data & 0x04;
255 	tilemap_set_flip (bg_tilemap, flipscreen ? TILEMAP_FLIPX|TILEMAP_FLIPY : 0);
256 	tilemap_set_flip (tx_tilemap, flipscreen ? TILEMAP_FLIPX|TILEMAP_FLIPY : 0);
257 
258 	/* bit 7 selects one of two ROM banks for c000-dfff */
259 	{
260 		int bank = (data & 0x80) >> 7;
261 		unsigned char *RAM = memory_region(REGION_CPU1);
262 
263 		cpu_setbank(1,&RAM[0x10000 + 0x2000 * bank]);
264 	}
265 
266 /*	log_cb(RETRO_LOG_DEBUG, LOGPRE "Address: %04X - port 40 = %02x\n",activecpu_get_pc(),data); */
267 }
268 
WRITE_HANDLER(ninjemak_gfxbank_w)269 WRITE_HANDLER( ninjemak_gfxbank_w )
270 {
271 	/* bits 0 and 1 coin counters */
272 	coin_counter_w(0,data & 1);
273 	coin_counter_w(1,data & 2);
274 
275 	/* bit 2 flip screen */
276 	flipscreen = data & 0x04;
277 	tilemap_set_flip (bg_tilemap, flipscreen ? TILEMAP_FLIPX|TILEMAP_FLIPY : 0);
278 	tilemap_set_flip (tx_tilemap, flipscreen ? TILEMAP_FLIPX|TILEMAP_FLIPY : 0);
279 
280 	/* bit 3 text bank flag ??? */
281 	if (data & 0x08)
282 	{
283 		/* This is a temporary condition specification. */
284 
285 		int offs;
286 
287 log_cb(RETRO_LOG_DEBUG, LOGPRE "%04x: write %02x to port 80\n",activecpu_get_pc(),data);
288 
289 		for (offs = 0; offs < videoram_size; offs++)
290 		{
291 			galivan_videoram_w(offs, 0x20);
292 		}
293 		for (offs = 0; offs < videoram_size; offs++)
294 		{
295 			galivan_colorram_w(offs, 0x03);
296 		}
297 	}
298 
299 	/* bit 4 background disable flag */
300 	ninjemak_dispdisable = data & 0x10;
301 
302 	/* bit 5 sprite flag ??? */
303 
304 	/* bit 6, 7 ROM bank select */
305 	{
306 		int bank = (data & 0xc0) >> 6;
307 		unsigned char *RAM = memory_region(REGION_CPU1);
308 
309 		cpu_setbank(1,&RAM[0x10000 + 0x2000 * bank]);
310 	}
311 
312 #if 0
313 	{
314 		char mess[80];
315 		int btz[8];
316 		int offs;
317 
318 		for (offs = 0; offs < 8; offs++) btz[offs] = (((data >> offs) & 0x01) ? 1 : 0);
319 
320 		sprintf(mess, "BK:%01X%01X S:%01X B:%01X T:%01X FF:%01X C2:%01X C1:%01X", btz[7], btz[6], btz[5], btz[4], btz[3], btz[2], btz[1], btz[0]);
321 		usrintf_showmessage(mess);
322 	}
323 #endif
324 }
325 
326 
327 
328 /* Written through port 41-42 */
WRITE_HANDLER(galivan_scrollx_w)329 WRITE_HANDLER( galivan_scrollx_w )
330 {
331 	static int up = 0;
332 	if (offset == 1) {
333 		if (data & 0x80)
334 			up = 1;
335 		else if (up) {
336 			layers = data & 0x60;
337 			up = 0;
338 		}
339 	}
340 	scrollx[offset] = data;
341 }
342 
343 /* Written through port 43-44 */
WRITE_HANDLER(galivan_scrolly_w)344 WRITE_HANDLER( galivan_scrolly_w )
345 {
346 	scrolly[offset] = data;
347 }
348 
349 
WRITE_HANDLER(ninjemak_scrollx_w)350 WRITE_HANDLER( ninjemak_scrollx_w )
351 {
352 	scrollx[offset] = data;
353 }
354 
WRITE_HANDLER(ninjemak_scrolly_w)355 WRITE_HANDLER( ninjemak_scrolly_w )
356 {
357 	scrolly[offset] = data;
358 }
359 
360 
361 
362 /***************************************************************************
363 
364   Display refresh
365 
366 ***************************************************************************/
367 
draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect)368 static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
369 {
370 	int offs;
371 
372 	/* draw the sprites */
373 	for (offs = 0;offs < spriteram_size;offs += 4)
374 	{
375 		int code;
376 		int attr = spriteram[offs+2];
377 		int color = (attr & 0x3c) >> 2;
378 		int flipx = attr & 0x40;
379 		int flipy = attr & 0x80;
380 		int sx,sy;
381 
382 		sx = (spriteram[offs+3] - 0x80) + 256 * (attr & 0x01);
383 		sy = 240 - spriteram[offs];
384 		if (flipscreen)
385 		{
386 			sx = 240 - sx;
387 			sy = 240 - sy;
388 			flipx = !flipx;
389 			flipy = !flipy;
390 		}
391 
392 /*		code = spriteram[offs+1] + ((attr & 0x02) << 7);*/
393 		code = spriteram[offs+1] + ((attr & 0x06) << 7);	/* for ninjemak, not sure ?*/
394 
395 		drawgfx(bitmap,Machine->gfx[2],
396 				code,
397 				color + 16 * (spritepalettebank[code >> 2] & 0x0f),
398 				flipx,flipy,
399 				sx,sy,
400 				cliprect,TRANSPARENCY_PEN,15);
401 	}
402 }
403 
404 
VIDEO_UPDATE(galivan)405 VIDEO_UPDATE( galivan )
406 {
407 	tilemap_set_scrollx(bg_tilemap,0,scrollx[0] + 256 * (scrollx[1] & 0x07));
408 	tilemap_set_scrolly(bg_tilemap,0,scrolly[0] + 256 * (scrolly[1] & 0x07));
409 
410 	if (layers & 0x40)
411 		fillbitmap(bitmap,Machine->pens[0],cliprect);
412 	else
413 		tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
414 
415 	tilemap_draw(bitmap,cliprect,tx_tilemap,0,0);
416 
417 	draw_sprites(bitmap,cliprect);
418 
419 	tilemap_draw(bitmap,cliprect,tx_tilemap,1,0);
420 }
421 
VIDEO_UPDATE(ninjemak)422 VIDEO_UPDATE( ninjemak )
423 {
424 	/* (scrollx[1] & 0x40) does something */
425 	tilemap_set_scrollx(bg_tilemap,0,scrollx[0] + 256 * (scrollx[1] & 0x1f));
426 	tilemap_set_scrolly(bg_tilemap,0,scrolly[0] + 256 * (scrolly[1] & 0xff));
427 
428 	if (ninjemak_dispdisable)
429 		fillbitmap(bitmap,Machine->pens[0],cliprect);
430 	else
431 		tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
432 
433 	draw_sprites(bitmap,cliprect);
434 
435 	tilemap_draw(bitmap,cliprect,tx_tilemap,0,0);
436 }
437