1 /***************************************************************************
2 
3 TC0100SCN
4 ---------
5 Tilemap generator, has three 64x64 tilemaps with 8x8 tiles.
6 The front one fetches gfx data from RAM, the others use ROMs as usual.
7 
8 0000-3fff BG0
9 4000-5fff FG0
10 6000-6fff gfx data for FG0
11 7000-7fff unknown/unused?
12 8000-bfff BG1
13 c000-c1ff BG0 rowscroll (gunfront)
14 c200-c3ff unknown/unused? (FG0 rowscroll?)
15 c400-c5ff BG1 rowscroll (gunfront)
16 c600-ffff unknown/unused?
17 
18 control registers:
19 000-001 BG0 scroll X
20 002-003 BG1 scroll X
21 004-005 FG0 scroll X
22 006-007 BG0 scroll Y
23 008-009 BG1 scroll Y
24 00a-00b FG0 scroll Y
25 00c-00d ---------------x BG0 disable
26         --------------x- BG1 disable
27         -------------x-- FG0 disable
28         ------------x--- change priority order from BG0-BG1-FG0 to BG1-BG0-FG0
29         -----------x---- unknown (cameltru, NOT cameltry)
30 00e-00f ---------------x flip screen
31         --x------------- unknown (thunderfox)
32 
33 
34 TC0280GRD
35 TC0430GRW
36 ---------
37 These generate a zooming/rotating tilemap. The TC0280GRD has to be used in
38 pairs, while the TC0430GRW is a newer, single-chip solution.
39 Regardless of the hardware differences, the two are functionally identical
40 except for incxx and incxy, which need to be multiplied by 2 in the TC0280GRD
41 to bring them to the same scale of the other parameters.
42 
43 control registers:
44 000-003 start x
45 004-005 incxx
46 006-007 incyx
47 008-00b start y
48 00c-00d incxy
49 00e-00f incyy
50 
51 
52 TC0480SCP
53 ---------
54 Tilemap generator, has four zoomable 32x32 tilemaps with 16x16 tiles.
55 It also has a front 64x64 tilemap with 8x8 tiles which fetches gfx data
56 from RAM.
57 
58 0000-0fff BG0
59 1000-1fff BG1
60 2000-2fff BG2
61 3000-3fff BG3
62 4000-41ff BG0 rowscroll ?
63 4400-45ff BG1 rowscroll ?
64 4800-49ff BG2 rowscroll ?
65 4c00-4dff BG3 rowscroll ?
66 6000-61ff BG0 colscroll ??
67 6400-65ff BG1 colscroll ??
68 6800-69ff BG2 colscroll ??
69 6c00-6dff BG3 colscroll ??
70 [gaps above seem to be unused]
71 7000-bfff unknown/unused?
72 c000-dfff FG0
73 e000-ffff gfx data for FG0 (4bpp)
74 
75 Each tile in bg layers is two data words:
76 
77 +0x00   %yx..bbbb cccccccc      b=control bits(?) c=colour .=unused(?)
78 +0x02   tilenum                 (range 0 to $1fff)
79 
80 [y=yflip x=xflip I think. No idea what 4 lsbs do.]
81 
82 control registers:
83 000-001 BG0 x scroll     (layer priority order definable)
84 002-003 BG1 x scroll
85 004-005 BG2 x scroll
86 006-007 BG3 x scroll
87 008-009 BG0 y scroll
88 00a-00b BG1 y scroll
89 00c-00d BG2 y scroll
90 00e-00f BG3 y scroll
91 010-011 BG0 zoom  <0x7f = shrunk e.g. 0x1a in Footchmp hiscore; 0x7f = normal;
92 012-013 BG1 zoom   0xfefe = max(?) zoom e.g. start of game in Metalb
93 014-015 BG2 zoom
94 016-017 BG3 zoom
95 018-019 Text layer x scroll
96 01a-01b Text layer y scroll
97 01c-01d Unused (not written)
98 01e-01f Layer Control register
99 		x-------	(probably unused)
100 		-x------	Flip screen
101 		--x-----	unknown
102 
103 				Set in Metalb init by whether a byte in prg ROM $7fffe is zero.
104 				Subsequently Metalb changes it for some screen layer layouts.
105 				Footchmp clears it, Hthero sets it [then both leave it alone].
106 				Deadconx code at $10e2 is interesting, with possible values of:
107 				0x0, 0x20, 0x40, 0x60 poked in (via ram buffer) to control reg,
108 				dependent on byte in prg ROM $7fffd and whether screen is flipped.
109 
110 		---xxxxx	BG layer priority order (?)
111 
112 				In Metalb this takes various values [see Raine lookup table in
113 				vidhrdw\taito_f2.c]. Other games leave it at zero.
114 
115 020-021 BG0 dx?	(these four change when x-scrolling layer)
116 022-023 BG1 dx?
117 024-025 BG2 dx?
118 026-027 BG3 dx?
119 028-029 BG0 dy?	(these four change when y-scrolling layer)
120 02a-02b BG1 dy?
121 02c-02d BG2 dy?
122 02e-02f BG3 dy?
123 
124 
125 TC0110PCR
126 ---------
127 Interface to palette RAM, and simple tilemap/sprite priority handler. The
128 priority order seems to be fixed.
129 The data bus is 16 bits wide.
130 
131 000  W selects palette RAM address
132 002 RW read/write palette RAM
133 004  W unknown, often written to
134 
135 
136 TC0220IOC
137 ---------
138 A simple I/O interface with integrated watchdog.
139 It has four address inputs, which would suggest 16 bytes of addressing space,
140 but only the first 8 seem to be used.
141 
142 000 R  IN00-07 (DSA)
143 000  W watchdog reset
144 001 R  IN08-15 (DSB)
145 002 R  IN16-23 (1P)
146 002  W unknown. Usually written on startup: initialize?
147 003 R  IN24-31 (2P)
148 004 RW coin counters and lockout
149 005  W unknown
150 006  W unknown
151 007 R  INB0-7 (coin)
152 
153 
154 TC0510NIO
155 ---------
156 Newer version of the I/O chip
157 
158 000 R  DSWA
159 000  W watchdog reset
160 001 R  DSWB
161 001  W unknown (ssi)
162 002 R  1P
163 003 R  2P
164 003  W unknown (yuyugogo, qzquest and qzchikyu use it a lot)
165 004 RW coin counters and lockout
166 005  W unknown
167 006  W unknown (koshien and pulirula use it a lot)
168 007 R  coin
169 
170 ***************************************************************************/
171 
172 #include "driver.h"
173 #include "taitoic.h"
174 
175 
176 
177 static unsigned char taitof2_scrbank;
WRITE_HANDLER(taitof2_scrbank_w)178 WRITE_HANDLER( taitof2_scrbank_w )   /* Mjnquest banks its 2 sets of scr tiles */
179 {
180     taitof2_scrbank = (data & 0x1);
181 }
182 
183 #define TC0100SCN_RAM_SIZE 0x10000
184 #define TC0100SCN_TOTAL_CHARS 256
185 #define TC0100SCN_MAX_CHIPS 2
186 static int TC0100SCN_chips;
187 static UINT8 TC0100SCN_ctrl[TC0100SCN_MAX_CHIPS][16];
188 static UINT8 *TC0100SCN_ram[TC0100SCN_MAX_CHIPS],*TC0100SCN_bg_ram[TC0100SCN_MAX_CHIPS],
189 		*TC0100SCN_fg_ram[TC0100SCN_MAX_CHIPS],*TC0100SCN_tx_ram[TC0100SCN_MAX_CHIPS],
190 		*TC0100SCN_char_ram[TC0100SCN_MAX_CHIPS],
191 		*TC0100SCN_bgscroll_ram[TC0100SCN_MAX_CHIPS],*TC0100SCN_fgscroll_ram[TC0100SCN_MAX_CHIPS];
192 static int TC0100SCN_bgscrollx[TC0100SCN_MAX_CHIPS],TC0100SCN_bgscrolly[TC0100SCN_MAX_CHIPS],
193 		TC0100SCN_fgscrollx[TC0100SCN_MAX_CHIPS],TC0100SCN_fgscrolly[TC0100SCN_MAX_CHIPS];
194 static struct tilemap *TC0100SCN_tilemap[TC0100SCN_MAX_CHIPS][3];
195 static char *TC0100SCN_char_dirty[TC0100SCN_MAX_CHIPS];
196 static int TC0100SCN_chars_dirty[TC0100SCN_MAX_CHIPS];
197 static int TC0100SCN_bg_gfx[TC0100SCN_MAX_CHIPS],TC0100SCN_tx_gfx[TC0100SCN_MAX_CHIPS];
198 
199 
200 
201 
common_get_bg_tile_info(UINT8 * ram,int gfxnum,int tile_index)202 static INLINE void common_get_bg_tile_info(UINT8 *ram,int gfxnum,int tile_index)
203 {
204 	int code = (READ_WORD(&ram[4*tile_index + 2]) & 0x7fff) + (taitof2_scrbank << 15);
205 	int attr = READ_WORD(&ram[4*tile_index]);
206 	SET_TILE_INFO(gfxnum,code,attr & 0xff);
207 	tile_info.flags = TILE_FLIPYX((attr & 0xc000) >> 14);
208 }
209 
common_get_tx_tile_info(UINT8 * ram,int gfxnum,int tile_index)210 static INLINE void common_get_tx_tile_info(UINT8 *ram,int gfxnum,int tile_index)
211 {
212 	int attr = READ_WORD(&ram[2*tile_index]);
213 	SET_TILE_INFO(gfxnum,attr & 0xff,(attr & 0x3f00) >> 6);
214 	tile_info.flags = TILE_FLIPYX((attr & 0xc000) >> 14);
215 }
216 
TC0100SCN_get_bg_tile_info_0(int tile_index)217 static void TC0100SCN_get_bg_tile_info_0(int tile_index)
218 {
219 	common_get_bg_tile_info(TC0100SCN_bg_ram[0],TC0100SCN_bg_gfx[0],tile_index);
220 }
221 
TC0100SCN_get_fg_tile_info_0(int tile_index)222 static void TC0100SCN_get_fg_tile_info_0(int tile_index)
223 {
224 	common_get_bg_tile_info(TC0100SCN_fg_ram[0],TC0100SCN_bg_gfx[0],tile_index);
225 }
226 
TC0100SCN_get_tx_tile_info_0(int tile_index)227 static void TC0100SCN_get_tx_tile_info_0(int tile_index)
228 {
229 	common_get_tx_tile_info(TC0100SCN_tx_ram[0],TC0100SCN_tx_gfx[0],tile_index);
230 }
231 
TC0100SCN_get_bg_tile_info_1(int tile_index)232 static void TC0100SCN_get_bg_tile_info_1(int tile_index)
233 {
234 	common_get_bg_tile_info(TC0100SCN_bg_ram[1],TC0100SCN_bg_gfx[1],tile_index);
235 }
236 
TC0100SCN_get_fg_tile_info_1(int tile_index)237 static void TC0100SCN_get_fg_tile_info_1(int tile_index)
238 {
239 	common_get_bg_tile_info(TC0100SCN_fg_ram[1],TC0100SCN_bg_gfx[1],tile_index);
240 }
241 
TC0100SCN_get_tx_tile_info_1(int tile_index)242 static void TC0100SCN_get_tx_tile_info_1(int tile_index)
243 {
244 	common_get_tx_tile_info(TC0100SCN_tx_ram[1],TC0100SCN_tx_gfx[1],tile_index);
245 }
246 
247 
248 void (*get_tile_info[TC0100SCN_MAX_CHIPS][3])(int tile_index) =
249 {
250 	{ TC0100SCN_get_bg_tile_info_0, TC0100SCN_get_fg_tile_info_0 ,TC0100SCN_get_tx_tile_info_0 },
251 	{ TC0100SCN_get_bg_tile_info_1, TC0100SCN_get_fg_tile_info_1 ,TC0100SCN_get_tx_tile_info_1 }
252 };
253 
254 
255 static struct GfxLayout TC0100SCN_charlayout =
256 {
257 	8,8,	/* 8*8 characters */
258 	256,	/* 256 characters */
259 	2,	/* 2 bits per pixel */
260 	{ 0, 8 },
261 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
262 	{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
263 	16*8	/* every sprite takes 16 consecutive bytes */
264 };
265 
266 
TC0100SCN_vh_start(int chips,int gfxnum,int x_offset)267 int TC0100SCN_vh_start(int chips,int gfxnum,int x_offset)
268 {
269 	int gfx_index,i;
270 
271 
272 	if (chips > TC0100SCN_MAX_CHIPS) return 1;
273 
274 	TC0100SCN_chips = chips;
275 
276 	for (i = 0;i < chips;i++)
277 	{
278 		int xd,yd;
279 
280 		TC0100SCN_tilemap[i][0] = tilemap_create(get_tile_info[i][0],tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,64);
281 		TC0100SCN_tilemap[i][1] = tilemap_create(get_tile_info[i][1],tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,64);
282 		TC0100SCN_tilemap[i][2] = tilemap_create(get_tile_info[i][2],tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,64);
283 
284 		TC0100SCN_ram[i] = (UINT8*)malloc(TC0100SCN_RAM_SIZE);
285 		TC0100SCN_char_dirty[i] = (char*)malloc(TC0100SCN_TOTAL_CHARS);
286 
287 		if (!TC0100SCN_ram[i] || !TC0100SCN_tilemap[i][0] ||
288 				!TC0100SCN_tilemap[i][1] || !TC0100SCN_tilemap[i][2])
289 		{
290 			TC0100SCN_vh_stop();
291 			return 1;
292 		}
293 
294 		TC0100SCN_bg_ram[i]       = TC0100SCN_ram[i] + 0x0000;
295 		TC0100SCN_tx_ram[i]       = TC0100SCN_ram[i] + 0x4000;
296 		TC0100SCN_char_ram[i]     = TC0100SCN_ram[i] + 0x6000;
297 		TC0100SCN_fg_ram[i]       = TC0100SCN_ram[i] + 0x8000;
298 		TC0100SCN_bgscroll_ram[i] = TC0100SCN_ram[i] + 0xc000;
299 		TC0100SCN_fgscroll_ram[i] = TC0100SCN_ram[i] + 0xc400;
300 		memset(TC0100SCN_ram[i],0,TC0100SCN_RAM_SIZE);
301 		memset(TC0100SCN_char_dirty[i],1,TC0100SCN_TOTAL_CHARS);
302 		TC0100SCN_chars_dirty[i] = 1;
303 
304 		/* find first empty slot to decode gfx */
305 		for (gfx_index = 0; gfx_index < MAX_GFX_ELEMENTS; gfx_index++)
306 			if (Machine->gfx[gfx_index] == 0)
307 				break;
308 		if (gfx_index == MAX_GFX_ELEMENTS)
309 		{
310 			TC0100SCN_vh_stop();
311 			return 1;
312 		}
313 
314 		/* create the char set (gfx will then be updated dynamically from RAM) */
315 		Machine->gfx[gfx_index] = decodegfx(TC0100SCN_char_ram[i],&TC0100SCN_charlayout);
316 		if (!Machine->gfx[gfx_index])
317 			return 1;
318 
319 		/* set the color information */
320 		Machine->gfx[gfx_index]->colortable = Machine->remapped_colortable;
321 		Machine->gfx[gfx_index]->total_colors = 64;
322 
323 		TC0100SCN_tx_gfx[i] = gfx_index;
324 
325 		/* use the given gfx set for bg tiles */
326 		TC0100SCN_bg_gfx[i] = gfxnum + i;
327 
328 		TC0100SCN_tilemap[i][0]->transparent_pen = 0;
329 		TC0100SCN_tilemap[i][1]->transparent_pen = 0;
330 		TC0100SCN_tilemap[i][2]->transparent_pen = 0;
331 
332 		/* I'm setting the optional chip #2 7 bits higher and 2 pixels to the left
333 		   than chip #1 because that's how thundfox wants it. */
334 		xd = (i == 0) ? -x_offset : (-x_offset-2);
335 		yd = (i == 0) ? 8 : 1;
336 		tilemap_set_scrolldx(TC0100SCN_tilemap[i][0],-16 + xd,-16 - xd);
337 		tilemap_set_scrolldy(TC0100SCN_tilemap[i][0],yd,-yd);
338 		tilemap_set_scrolldx(TC0100SCN_tilemap[i][1],-16 + xd,-16 - xd);
339 		tilemap_set_scrolldy(TC0100SCN_tilemap[i][1],yd,-yd);
340 		tilemap_set_scrolldx(TC0100SCN_tilemap[i][2],-16 + xd,-16 - xd - 7);
341 		tilemap_set_scrolldy(TC0100SCN_tilemap[i][2],yd,-yd);
342 
343 		tilemap_set_scroll_rows(TC0100SCN_tilemap[i][0],512);
344 		tilemap_set_scroll_rows(TC0100SCN_tilemap[i][1],512);
345 	}
346 
347 	taitof2_scrbank = 0;
348 
349 	return 0;
350 }
351 
TC0100SCN_vh_stop(void)352 void TC0100SCN_vh_stop(void)
353 {
354 	int i;
355 
356 	for (i = 0;i < TC0100SCN_chips;i++)
357 	{
358 		free(TC0100SCN_ram[i]);
359 		TC0100SCN_ram[i] = 0;
360 		free(TC0100SCN_char_dirty[i]);
361 		TC0100SCN_char_dirty[i] = 0;
362 	}
363 }
364 
365 
TC0100SCN_word_r(int chip,offs_t offset)366 static int TC0100SCN_word_r(int chip,offs_t offset)
367 {
368 	int res;
369 
370 	res = READ_WORD(&TC0100SCN_ram[chip][offset]);
371 
372 #ifndef MSB_FIRST
373 	/* for char gfx data, we have to straighten out the 16-bit word into
374 	   bytes for gfxdecode() to work */
375    if (offset >= 0x6000 && offset < 0x7000)
376       res = ((res & 0x00ff) << 8) | ((res & 0xff00) >> 8);
377 #endif
378 
379 	return res;
380 }
381 
READ_HANDLER(TC0100SCN_word_0_r)382 READ_HANDLER( TC0100SCN_word_0_r )
383 {
384 	return TC0100SCN_word_r(0,offset);
385 }
386 
READ_HANDLER(TC0100SCN_word_1_r)387 READ_HANDLER( TC0100SCN_word_1_r )
388 {
389 	return TC0100SCN_word_r(1,offset);
390 }
391 
392 
TC0100SCN_word_w(int chip,offs_t offset,data_t data)393 static void TC0100SCN_word_w(int chip,offs_t offset,data_t data)
394 {
395 	int oldword = READ_WORD(&TC0100SCN_ram[chip][offset]);
396 	int newword;
397 
398 #ifndef MSB_FIRST
399 	/* for char gfx data, we have to straighten out the 16-bit word into
400 	   bytes for gfxdecode() to work */
401    if (offset >= 0x6000 && offset < 0x7000)
402       data = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
403 #endif
404 
405 	newword = COMBINE_WORD(oldword,data);
406 	if (oldword != newword)
407 	{
408 		WRITE_WORD(&TC0100SCN_ram[chip][offset],newword);
409 
410 		if (offset < 0x4000)
411 			tilemap_mark_tile_dirty(TC0100SCN_tilemap[chip][0],offset / 4);
412 		else if (offset < 0x6000)
413 			tilemap_mark_tile_dirty(TC0100SCN_tilemap[chip][2],(offset & 0x1fff) / 2);
414 		else if (offset < 0x7000)
415 		{
416 			TC0100SCN_char_dirty[chip][(offset - 0x6000) / 16] = 1;
417 			TC0100SCN_chars_dirty[chip] = 1;
418 		}
419 		else if (offset >= 0x8000 && offset < 0xc000)
420 			tilemap_mark_tile_dirty(TC0100SCN_tilemap[chip][1],(offset & 0x3fff) / 4);
421 	}
422 }
423 
WRITE_HANDLER(TC0100SCN_word_0_w)424 WRITE_HANDLER( TC0100SCN_word_0_w )
425 {
426 	TC0100SCN_word_w(0,offset,data);
427 }
428 
WRITE_HANDLER(TC0100SCN_word_1_w)429 WRITE_HANDLER( TC0100SCN_word_1_w )
430 {
431 	TC0100SCN_word_w(1,offset,data);
432 }
433 
434 
READ_HANDLER(TC0100SCN_ctrl_word_0_r)435 READ_HANDLER( TC0100SCN_ctrl_word_0_r )
436 {
437 	return READ_WORD(&TC0100SCN_ctrl[0][offset]);
438 }
439 
READ_HANDLER(TC0100SCN_ctrl_word_1_r)440 READ_HANDLER( TC0100SCN_ctrl_word_1_r )
441 {
442 	return READ_WORD(&TC0100SCN_ctrl[1][offset]);
443 }
444 
445 
TC0100SCN_ctrl_word_w(int chip,offs_t offset,data_t data)446 static void TC0100SCN_ctrl_word_w(int chip,offs_t offset,data_t data)
447 {
448 	COMBINE_WORD_MEM(&TC0100SCN_ctrl[chip][offset],data);
449 
450 	data = READ_WORD(&TC0100SCN_ctrl[chip][offset]);
451 
452 	switch (offset)
453 	{
454 		case 0x00:
455 			TC0100SCN_bgscrollx[chip] = -data;
456 			break;
457 
458 		case 0x02:
459 			TC0100SCN_fgscrollx[chip] = -data;
460 			break;
461 
462 		case 0x04:
463 			tilemap_set_scrollx(TC0100SCN_tilemap[chip][2],0,-data);
464 			break;
465 
466 		case 0x06:
467 			TC0100SCN_bgscrolly[chip] = -data;
468 			break;
469 
470 		case 0x08:
471 			TC0100SCN_fgscrolly[chip] = -data;
472 			break;
473 
474 		case 0x0a:
475 			tilemap_set_scrolly(TC0100SCN_tilemap[chip][2],0,-data);
476 			break;
477 
478 		case 0x0c:
479 			break;
480 
481 		case 0x0e:
482 		{
483 			int flip = (data & 0x01) ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0;
484 
485 			tilemap_set_flip(TC0100SCN_tilemap[chip][0],flip);
486 			tilemap_set_flip(TC0100SCN_tilemap[chip][1],flip);
487 			tilemap_set_flip(TC0100SCN_tilemap[chip][2],flip);
488 			break;
489 		}
490 	}
491 }
492 
WRITE_HANDLER(TC0100SCN_ctrl_word_0_w)493 WRITE_HANDLER( TC0100SCN_ctrl_word_0_w )
494 {
495 	TC0100SCN_ctrl_word_w(0,offset,data);
496 }
497 
WRITE_HANDLER(TC0100SCN_ctrl_word_1_w)498 WRITE_HANDLER( TC0100SCN_ctrl_word_1_w )
499 {
500 	TC0100SCN_ctrl_word_w(1,offset,data);
501 }
502 
503 
TC0100SCN_tilemap_update(void)504 void TC0100SCN_tilemap_update(void)
505 {
506 	int chip,j;
507 
508 	for (chip = 0;chip < TC0100SCN_chips;chip++)
509 	{
510 		tilemap_set_scrolly(TC0100SCN_tilemap[chip][0],0,TC0100SCN_bgscrolly[chip]);
511 		tilemap_set_scrolly(TC0100SCN_tilemap[chip][1],0,TC0100SCN_fgscrolly[chip]);
512 
513 		for (j = 0;j < 256;j++)
514 			tilemap_set_scrollx(TC0100SCN_tilemap[chip][0],
515 					(j + TC0100SCN_bgscrolly[chip]) & 0x1ff,
516 					TC0100SCN_bgscrollx[chip] - READ_WORD(&TC0100SCN_bgscroll_ram[chip][2*j]));
517 		for (j = 0;j < 256;j++)
518 			tilemap_set_scrollx(TC0100SCN_tilemap[chip][1],
519 					(j + TC0100SCN_fgscrolly[chip]) & 0x1ff,
520 					TC0100SCN_fgscrollx[chip] - READ_WORD(&TC0100SCN_fgscroll_ram[chip][2*j]));
521 
522 		/* Decode any characters that have changed */
523 		if (TC0100SCN_chars_dirty[chip])
524 		{
525 			int tile_index;
526 
527 
528 			for (tile_index = 0;tile_index < 64*64;tile_index++)
529 			{
530 				int attr = READ_WORD(&TC0100SCN_tx_ram[chip][2*tile_index]);
531 				if (TC0100SCN_char_dirty[chip][attr & 0xff])
532 					tilemap_mark_tile_dirty(TC0100SCN_tilemap[chip][2],tile_index);
533 			}
534 
535 			for (j = 0;j < TC0100SCN_TOTAL_CHARS;j++)
536 			{
537 				if (TC0100SCN_char_dirty[chip][j])
538 					decodechar(Machine->gfx[TC0100SCN_tx_gfx[chip]],j,TC0100SCN_char_ram[chip],&TC0100SCN_charlayout);
539 				TC0100SCN_char_dirty[chip][j] = 0;
540 			}
541 			TC0100SCN_chars_dirty[chip] = 0;
542 		}
543 
544 		tilemap_update(TC0100SCN_tilemap[chip][0]);
545 		tilemap_update(TC0100SCN_tilemap[chip][1]);
546 		tilemap_update(TC0100SCN_tilemap[chip][2]);
547 	}
548 }
549 
TC0100SCN_tilemap_draw(struct osd_bitmap * bitmap,int chip,int layer,int flags)550 void TC0100SCN_tilemap_draw(struct osd_bitmap *bitmap,int chip,int layer,int flags)
551 {
552 	int disable = READ_WORD(&TC0100SCN_ctrl[chip][12]) & 0xf7;
553 
554 	switch (layer)
555 	{
556 		case 0:
557 			if (disable & 0x01) return;
558 			tilemap_draw(bitmap,TC0100SCN_tilemap[chip][0],flags);
559 			break;
560 		case 1:
561 			if (disable & 0x02) return;
562 			tilemap_draw(bitmap,TC0100SCN_tilemap[chip][1],flags);
563 			break;
564 		case 2:
565 			if (disable & 0x04) return;
566 			if (disable & 0x10) return;	/* cameltru */
567 			tilemap_draw(bitmap,TC0100SCN_tilemap[chip][2],flags);
568 			break;
569 	}
570 }
571 
TC0100SCN_bottomlayer(int chip)572 int TC0100SCN_bottomlayer(int chip)
573 {
574 	return (READ_WORD(&TC0100SCN_ctrl[chip][12]) & 0x8) >> 3;
575 }
576 
577 
578 /***************************************************************************/
579 
580 #define TC0280GRD_RAM_SIZE 0x2000
581 static UINT8 TC0280GRD_ctrl[16];
582 static UINT8 *TC0280GRD_ram;
583 static struct tilemap *TC0280GRD_tilemap;
584 static int TC0280GRD_gfxnum,TC0280GRD_base_color;
585 
586 
TC0280GRD_get_tile_info(int tile_index)587 static void TC0280GRD_get_tile_info(int tile_index)
588 {
589 	int attr = READ_WORD(&TC0280GRD_ram[2*tile_index]);
590 	SET_TILE_INFO(TC0280GRD_gfxnum,attr & 0x3fff,((attr & 0xc000) >> 14) + TC0280GRD_base_color);
591 }
592 
593 
TC0280GRD_vh_start(int gfxnum)594 int TC0280GRD_vh_start(int gfxnum)
595 {
596 	TC0280GRD_ram = (UINT8*)malloc(TC0280GRD_RAM_SIZE);
597 	TC0280GRD_tilemap = tilemap_create(TC0280GRD_get_tile_info,tilemap_scan_rows,TILEMAP_OPAQUE,8,8,64,64);
598 
599 	if (!TC0280GRD_ram || !TC0280GRD_tilemap)
600 	{
601 		TC0280GRD_vh_stop();
602 		return 1;
603 	}
604 
605 	tilemap_set_clip(TC0280GRD_tilemap,0);
606 
607 	TC0280GRD_gfxnum = gfxnum;
608 
609 	return 0;
610 }
611 
TC0430GRW_vh_start(int gfxnum)612 int TC0430GRW_vh_start(int gfxnum)
613 {
614 	return TC0280GRD_vh_start(gfxnum);
615 }
616 
TC0280GRD_vh_stop(void)617 void TC0280GRD_vh_stop(void)
618 {
619 	free(TC0280GRD_ram);
620 	TC0280GRD_ram = 0;
621 }
622 
TC0430GRW_vh_stop(void)623 void TC0430GRW_vh_stop(void)
624 {
625 	TC0280GRD_vh_stop();
626 }
627 
READ_HANDLER(TC0280GRD_word_r)628 READ_HANDLER( TC0280GRD_word_r )
629 {
630 	return READ_WORD(&TC0280GRD_ram[offset]);
631 }
632 
READ_HANDLER(TC0430GRW_word_r)633 READ_HANDLER( TC0430GRW_word_r )
634 {
635 	return TC0280GRD_word_r(offset);
636 }
637 
WRITE_HANDLER(TC0280GRD_word_w)638 WRITE_HANDLER( TC0280GRD_word_w )
639 {
640 	int oldword = READ_WORD(&TC0280GRD_ram[offset]);
641 	int newword = COMBINE_WORD(oldword, data);
642 
643 	if (oldword != newword)
644 	{
645 		WRITE_WORD (&TC0280GRD_ram[offset],newword);
646 		tilemap_mark_tile_dirty(TC0280GRD_tilemap,offset / 2);
647 	}
648 }
649 
WRITE_HANDLER(TC0430GRW_word_w)650 WRITE_HANDLER( TC0430GRW_word_w )
651 {
652 	TC0280GRD_word_w(offset,data);
653 }
654 
WRITE_HANDLER(TC0280GRD_ctrl_word_w)655 WRITE_HANDLER( TC0280GRD_ctrl_word_w )
656 {
657 	COMBINE_WORD_MEM(&TC0280GRD_ctrl[offset],data);
658 }
659 
WRITE_HANDLER(TC0430GRW_ctrl_word_w)660 WRITE_HANDLER( TC0430GRW_ctrl_word_w )
661 {
662 	TC0280GRD_ctrl_word_w(offset,data);
663 }
664 
TC0280GRD_tilemap_update(int base_color)665 void TC0280GRD_tilemap_update(int base_color)
666 {
667 	if (TC0280GRD_base_color != base_color)
668 	{
669 		TC0280GRD_base_color = base_color;
670 		tilemap_mark_all_tiles_dirty(TC0280GRD_tilemap);
671 	}
672 
673 	tilemap_update(TC0280GRD_tilemap);
674 }
675 
TC0430GRW_tilemap_update(int base_color)676 void TC0430GRW_tilemap_update(int base_color)
677 {
678 	TC0280GRD_tilemap_update(base_color);
679 }
680 
zoom_draw(struct osd_bitmap * bitmap,int xoffset,int yoffset,UINT32 priority,int xmultiply)681 static void zoom_draw(struct osd_bitmap *bitmap,int xoffset,int yoffset,UINT32 priority,int xmultiply)
682 {
683 	UINT32 startx,starty;
684 	int incxx,incxy,incyx,incyy;
685 	struct osd_bitmap *srcbitmap = TC0280GRD_tilemap->pixmap;
686 
687 	/* 24-bit signed */
688 	startx = ((READ_WORD(&TC0280GRD_ctrl[0]) & 0xff) << 16) + READ_WORD(&TC0280GRD_ctrl[2]);
689 	if (startx & 0x800000) startx -= 0x1000000;
690 	incxx = (INT16)READ_WORD(&TC0280GRD_ctrl[4]);
691 	incxx *= xmultiply;
692 	incyx = (INT16)READ_WORD(&TC0280GRD_ctrl[6]);
693 	/* 24-bit signed */
694 	starty = ((READ_WORD(&TC0280GRD_ctrl[8]) & 0xff) << 16) + READ_WORD(&TC0280GRD_ctrl[10]);
695 	if (starty & 0x800000) starty -= 0x1000000;
696 	incxy = (INT16)READ_WORD(&TC0280GRD_ctrl[12]);
697 	incxy *= xmultiply;
698 	incyy = (INT16)READ_WORD(&TC0280GRD_ctrl[14]);
699 
700 	startx -= xoffset * incxx + yoffset * incyx;
701 	starty -= xoffset * incxy + yoffset * incyy;
702 
703 	copyrozbitmap(bitmap,srcbitmap,startx << 4,starty << 4,
704 			incxx << 4,incxy << 4,incyx << 4,incyy << 4,
705 			1,	/* copy with wraparound */
706 			&Machine->visible_area,TRANSPARENCY_PEN,palette_transparent_pen,priority);
707 }
708 
TC0280GRD_zoom_draw(struct osd_bitmap * bitmap,int xoffset,int yoffset,UINT32 priority)709 void TC0280GRD_zoom_draw(struct osd_bitmap *bitmap,int xoffset,int yoffset,UINT32 priority)
710 {
711 	zoom_draw(bitmap,xoffset,yoffset,priority,2);
712 }
713 
TC0430GRW_zoom_draw(struct osd_bitmap * bitmap,int xoffset,int yoffset,UINT32 priority)714 void TC0430GRW_zoom_draw(struct osd_bitmap *bitmap,int xoffset,int yoffset,UINT32 priority)
715 {
716 	zoom_draw(bitmap,xoffset,yoffset,priority,1);
717 }
718 
719 
720 /***************************************************************************/
721 
722 
723 #define TC0480SCP_RAM_SIZE 0x10000
724 #define TC0480SCP_TOTAL_CHARS 256
725 static UINT8 TC0480SCP_ctrl[48];
726 static UINT8 *TC0480SCP_ram,
727 		*TC0480SCP_bg_ram[4],
728 		*TC0480SCP_tx_ram,
729 		*TC0480SCP_char_ram,
730 		*TC0480SCP_bgscroll_ram[4];
731 static int TC0480SCP_bgscrollx[4];
732 static int TC0480SCP_bgscrolly[4];
733 static struct tilemap *TC0480SCP_tilemap[5];
734 static char *TC0480SCP_char_dirty;
735 static int TC0480SCP_chars_dirty;
736 static int TC0480SCP_bg_gfx,TC0480SCP_tx_gfx;
737 static int TC0480SCP_tile_colbase;
738 static int TC0480SCP_x_offs;
739 static int TC0480SCP_y_offs;
740 
741 int TC0480SCP_pri_reg;   // read externally in vidhrdw\taito_f2.c
742 
743 
common_get_tc0480bg_tile_info(UINT8 * ram,int gfxnum,int tile_index)744 static INLINE void common_get_tc0480bg_tile_info(UINT8 *ram,int gfxnum,int tile_index)
745 {
746 	int code = (READ_WORD(&ram[4*tile_index + 2]) & 0x7fff);
747 	int attr = READ_WORD(&ram[4*tile_index]);
748 	SET_TILE_INFO(gfxnum,code,(attr & 0xff) + TC0480SCP_tile_colbase);
749 	tile_info.flags = TILE_FLIPYX((attr & 0xc000) >> 14);
750 }
751 
common_get_tc0480tx_tile_info(UINT8 * ram,int gfxnum,int tile_index)752 static INLINE void common_get_tc0480tx_tile_info(UINT8 *ram,int gfxnum,int tile_index)
753 {
754 	int attr = READ_WORD(&ram[2*tile_index]);
755 	SET_TILE_INFO(gfxnum,attr & 0xff,((attr & 0x3f00) >> 8) + TC0480SCP_tile_colbase);   // >> 8 not 6 as 4bpp
756 	tile_info.flags = TILE_FLIPYX((attr & 0xc000) >> 14);
757 }
758 
TC0480SCP_get_bg0_tile_info(int tile_index)759 static void TC0480SCP_get_bg0_tile_info(int tile_index)
760 {
761 	common_get_tc0480bg_tile_info(TC0480SCP_bg_ram[0],TC0480SCP_bg_gfx,tile_index);
762 }
763 
TC0480SCP_get_bg1_tile_info(int tile_index)764 static void TC0480SCP_get_bg1_tile_info(int tile_index)
765 {
766 	common_get_tc0480bg_tile_info(TC0480SCP_bg_ram[1],TC0480SCP_bg_gfx,tile_index);
767 }
768 
TC0480SCP_get_bg2_tile_info(int tile_index)769 static void TC0480SCP_get_bg2_tile_info(int tile_index)
770 {
771 	common_get_tc0480bg_tile_info(TC0480SCP_bg_ram[2],TC0480SCP_bg_gfx,tile_index);
772 }
773 
TC0480SCP_get_bg3_tile_info(int tile_index)774 static void TC0480SCP_get_bg3_tile_info(int tile_index)
775 {
776 	common_get_tc0480bg_tile_info(TC0480SCP_bg_ram[3],TC0480SCP_bg_gfx,tile_index);
777 }
778 
TC0480SCP_get_tx_tile_info(int tile_index)779 static void TC0480SCP_get_tx_tile_info(int tile_index)
780 {
781 	common_get_tc0480tx_tile_info(TC0480SCP_tx_ram,TC0480SCP_tx_gfx,tile_index);
782 }
783 
784 void (*tc480_get_tile_info[5])(int tile_index) =
785 {
786 	TC0480SCP_get_bg0_tile_info, TC0480SCP_get_bg1_tile_info, TC0480SCP_get_bg2_tile_info, TC0480SCP_get_bg3_tile_info, TC0480SCP_get_tx_tile_info
787 };
788 
789 
790 static struct GfxLayout TC0480SCP_charlayout =
791 {
792 	8,8,	/* 8*8 characters */
793 	256,	/* 256 characters */
794 	4,	/* 4 bits per pixel */
795 	{ 0, 1, 2, 3 },
796 	{ 3*4, 2*4, 1*4, 0*4, 7*4, 6*4, 5*4, 4*4 },
797 	{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
798 	32*8	/* every sprite takes 32 consecutive bytes */
799 };
800 
801 
TC0480SCP_vh_start(int gfxnum,int pixels,int x_offset,int y_offset,int col_base)802 int TC0480SCP_vh_start(int gfxnum,int pixels,int x_offset,int y_offset,int col_base)
803 {
804 	int gfx_index;
805 
806 		int xd,yd;
807 		TC0480SCP_tile_colbase = col_base;
808 
809 		TC0480SCP_tilemap[0] = tilemap_create(tc480_get_tile_info[0],tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
810 		TC0480SCP_tilemap[1] = tilemap_create(tc480_get_tile_info[1],tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
811 		TC0480SCP_tilemap[2] = tilemap_create(tc480_get_tile_info[2],tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
812 		TC0480SCP_tilemap[3] = tilemap_create(tc480_get_tile_info[3],tilemap_scan_rows,TILEMAP_TRANSPARENT,16,16,32,32);
813 		TC0480SCP_tilemap[4] = tilemap_create(tc480_get_tile_info[4],tilemap_scan_rows,TILEMAP_TRANSPARENT,8,8,64,64);
814 
815 		TC0480SCP_ram = (UINT8*)malloc(TC0480SCP_RAM_SIZE);
816 		TC0480SCP_char_dirty = (char*)malloc(TC0480SCP_TOTAL_CHARS);
817 
818 		if (!TC0480SCP_ram || !TC0480SCP_tilemap[0] || !TC0480SCP_tilemap[1] ||
819 				!TC0480SCP_tilemap[2] || !TC0480SCP_tilemap[3] || !TC0480SCP_tilemap[4])
820 		{
821 			TC0480SCP_vh_stop();
822 			return 1;
823 		}
824 
825 		TC0480SCP_bg_ram[0]	  = TC0480SCP_ram + 0x0000;
826 		TC0480SCP_bg_ram[1]	  = TC0480SCP_ram + 0x1000;
827 		TC0480SCP_bg_ram[2]	  = TC0480SCP_ram + 0x2000;
828 		TC0480SCP_bg_ram[3]	  = TC0480SCP_ram + 0x3000;
829 		TC0480SCP_bgscroll_ram[0] = TC0480SCP_ram + 0x4000;
830 		TC0480SCP_bgscroll_ram[1] = TC0480SCP_ram + 0x4400;
831 		TC0480SCP_bgscroll_ram[2] = TC0480SCP_ram + 0x4800;
832 		TC0480SCP_bgscroll_ram[3] = TC0480SCP_ram + 0x4c00;
833 		TC0480SCP_tx_ram		  = TC0480SCP_ram + 0xc000;
834 		TC0480SCP_char_ram	  = TC0480SCP_ram + 0xe000;
835 
836 		memset(TC0480SCP_ram,0,TC0480SCP_RAM_SIZE);
837 		memset(TC0480SCP_char_dirty,1,TC0480SCP_TOTAL_CHARS);
838 		TC0480SCP_chars_dirty = 1;
839 
840 		/* find first empty slot to decode gfx */
841 		for (gfx_index = 0; gfx_index < MAX_GFX_ELEMENTS; gfx_index++)
842 			if (Machine->gfx[gfx_index] == 0)
843 				break;
844 		if (gfx_index == MAX_GFX_ELEMENTS)
845 		{
846 			TC0480SCP_vh_stop();
847 			return 1;
848 		}
849 
850 		/* create the char set (gfx will then be updated dynamically from RAM) */
851 		Machine->gfx[gfx_index] = decodegfx(TC0480SCP_char_ram,&TC0480SCP_charlayout);
852 		if (!Machine->gfx[gfx_index])
853 			return 1;
854 
855 		/* set the color information */
856 		Machine->gfx[gfx_index]->colortable = Machine->remapped_colortable;
857 		Machine->gfx[gfx_index]->total_colors = 64;
858 
859 		TC0480SCP_tx_gfx = gfx_index;
860 
861 		/* use the given gfx set for bg tiles */
862 		TC0480SCP_bg_gfx = gfxnum;
863 
864 		TC0480SCP_tilemap[0]->transparent_pen = 0;
865 		TC0480SCP_tilemap[1]->transparent_pen = 0;
866 		TC0480SCP_tilemap[2]->transparent_pen = 0;
867 		TC0480SCP_tilemap[3]->transparent_pen = 0;
868 		TC0480SCP_tilemap[4]->transparent_pen = 0;
869 
870 		TC0480SCP_x_offs = x_offset + pixels;
871 		TC0480SCP_y_offs = y_offset;
872 
873 		xd = -TC0480SCP_x_offs;
874 		yd =  TC0480SCP_y_offs;
875 
876 		tilemap_set_scrolldx(TC0480SCP_tilemap[0], xd,   319-xd);   // 40*8 = 320 (screen width)
877 		tilemap_set_scrolldy(TC0480SCP_tilemap[0], yd,   256-yd);   // 28*8 = 224 (screen height)
878 		tilemap_set_scrolldx(TC0480SCP_tilemap[1], xd,   319-xd);
879 		tilemap_set_scrolldy(TC0480SCP_tilemap[1], yd,   256-yd);
880 		tilemap_set_scrolldx(TC0480SCP_tilemap[2], xd,   319-xd);
881 		tilemap_set_scrolldy(TC0480SCP_tilemap[2], yd,   256-yd);
882 		tilemap_set_scrolldx(TC0480SCP_tilemap[3], xd,   319-xd);
883 		tilemap_set_scrolldy(TC0480SCP_tilemap[3], yd,   256-yd);
884 		tilemap_set_scrolldx(TC0480SCP_tilemap[4], xd-2, 315-xd);   /* text layer */
885 		tilemap_set_scrolldy(TC0480SCP_tilemap[4], yd,   256-yd);   /* text layer */
886 
887 		/* Make bg tilemaps scrollable per pixel row */
888 		tilemap_set_scroll_rows(TC0480SCP_tilemap[0],512);
889 		tilemap_set_scroll_rows(TC0480SCP_tilemap[1],512);
890 		tilemap_set_scroll_rows(TC0480SCP_tilemap[2],512);
891 		tilemap_set_scroll_rows(TC0480SCP_tilemap[3],512);
892 
893 	return 0;
894 }
895 
TC0480SCP_vh_stop(void)896 void TC0480SCP_vh_stop(void)
897 {
898 		free(TC0480SCP_ram);
899 		TC0480SCP_ram = 0;
900 		free(TC0480SCP_char_dirty);
901 		TC0480SCP_char_dirty = 0;
902 }
903 
904 
TC0480SCP_word_read(offs_t offset)905 static int TC0480SCP_word_read(offs_t offset)
906 {
907 	int res;
908 
909 	res = READ_WORD(&TC0480SCP_ram[offset]);
910 
911 #ifndef MSB_FIRST
912    /* for char gfx data, we have to straighten out the 16-bit word into
913       bytes for gfxdecode() to work */
914    if (offset >= 0xe000 && offset <= 0xffff)
915       res = ((res & 0x00ff) << 8) | ((res & 0xff00) >> 8);
916 #endif
917 
918 	return res;
919 }
920 
READ_HANDLER(TC0480SCP_word_r)921 READ_HANDLER( TC0480SCP_word_r )
922 {
923 	return TC0480SCP_word_read(offset);
924 }
925 
TC0480SCP_word_write(offs_t offset,data_t data)926 static void TC0480SCP_word_write(offs_t offset,data_t data)
927 {
928 	int oldword = READ_WORD(&TC0480SCP_ram[offset]);
929 	int newword;
930 
931 #ifndef MSB_FIRST
932    /* for char gfx data, we have to straighten out the 16-bit word into
933       bytes for gfxdecode() to work */
934    if (offset >= 0xe000 && offset <= 0xffff)
935       data = ((data & 0x00ff00ff) << 8) | ((data & 0xff00ff00) >> 8);
936 #endif
937 
938 	newword = COMBINE_WORD(oldword,data);
939 	if (oldword != newword)
940 	{
941 		WRITE_WORD(&TC0480SCP_ram[offset],newword);
942 
943 		if (offset < 0x4000)
944 		{
945 			tilemap_mark_tile_dirty(TC0480SCP_tilemap[(offset / 0x1000)],((offset % 0x1000) / 4));
946 		}
947 		else if (offset < 0xc000)
948 		{   // do nothing
949 		}
950 		else if (offset < 0xe000)
951 		{
952 			tilemap_mark_tile_dirty(TC0480SCP_tilemap[4],(offset - 0xc000) / 2);
953 		}
954 		else if (offset <= 0xffff)
955 		{
956 			TC0480SCP_char_dirty[(offset - 0xe000) / 32] = 1;
957 			TC0480SCP_chars_dirty = 1;
958 		}
959 	}
960 }
961 
WRITE_HANDLER(TC0480SCP_word_w)962 WRITE_HANDLER( TC0480SCP_word_w )
963 {
964 	TC0480SCP_word_write(offset,data);
965 }
966 
READ_HANDLER(TC0480SCP_ctrl_word_r)967 READ_HANDLER( TC0480SCP_ctrl_word_r )
968 {
969 	return READ_WORD(&TC0480SCP_ctrl[offset]);
970 }
971 
TC0480SCP_ctrl_word_write(offs_t offset,data_t data)972 static void TC0480SCP_ctrl_word_write(offs_t offset,data_t data)
973 {
974 	int flip = TC0480SCP_pri_reg & 0x40;
975 
976 	COMBINE_WORD_MEM(&TC0480SCP_ctrl[offset],data);
977 	data = READ_WORD(&TC0480SCP_ctrl[offset]);
978 
979 	switch( offset )
980 	{
981 		/* The x offsets of the four bg layers are staggered by intervals of 4 pixels */
982 /* NOTE:
983 Metalb does not always stick with this e.g. it wants bg0&1 further right
984 (see stick man on stairs and blue planet in attract).
985 There was a bg3 alignment problem with sprites in the round 4 long
986 spaceship boss: solved by pushing bg3 two pixels right [there may be a
987 single pixel left because of sprites being a frame "early"].
988 New offsets make "film" on skyscraper in round 1 slightly wrong.
989 */
990 		case 0x00:   /* bg0 x */
991 			if (TC0480SCP_tile_colbase) data += 2;   // improves Metalb attract
992 
993 			if (!flip)  data = -data;
994 			TC0480SCP_bgscrollx[0] = data;
995 			break;
996 
997 		case 0x02:   /* bg1 x */
998 			if (TC0480SCP_tile_colbase) data += 2;   // improves Metalb attract
999 
1000 			data += 4;
1001 			if (!flip)  data = -data;
1002 			TC0480SCP_bgscrollx[1] = data;
1003 			break;
1004 
1005 		case 0x04:   /* bg2 x */
1006 			if (TC0480SCP_tile_colbase) data += 2;   // same as other layers
1007 
1008 			data += 8;
1009 			if (!flip)  data = -data;
1010 			TC0480SCP_bgscrollx[2] = data;
1011 			break;
1012 
1013 		case 0x06:   /* bg3 x */
1014 			if (TC0480SCP_tile_colbase) data += 2;   // improves Metalb round 4 boss
1015 
1016 			data += 12;
1017 			if (!flip)  data = -data;
1018 			TC0480SCP_bgscrollx[3] = data;
1019 			break;
1020 
1021 		case 0x08:   /* bg0 y */
1022 			if (flip)  data = -data;
1023 			TC0480SCP_bgscrolly[0] = data;
1024 			break;
1025 
1026 		case 0x0a:   /* bg1 y */
1027 			if (flip)  data = -data;
1028 			TC0480SCP_bgscrolly[1] = data;
1029 			break;
1030 
1031 		case 0x0c:   /* bg2 y */
1032 			if (flip)  data = -data;
1033 			TC0480SCP_bgscrolly[2] = data;
1034 			break;
1035 
1036 		case 0x0e:   /* bg3 y */
1037 			if (flip)  data = -data;
1038 			TC0480SCP_bgscrolly[3] = data;
1039 			break;
1040 
1041 		case 0x10:   /* bg0 zoom */
1042 		case 0x12:   /* bg1 zoom */
1043 		case 0x14:   /* bg2 zoom */
1044 		case 0x16:   /* bg3 zoom */
1045 			break;
1046 
1047 		case 0x18:   /* fg (text) x */
1048 			tilemap_set_scrollx(TC0480SCP_tilemap[4], 0, -data);
1049 			break;
1050 
1051 		case 0x1a:   /* fg (text) y */
1052 			tilemap_set_scrolly(TC0480SCP_tilemap[4], 0, -data);
1053 			break;
1054 
1055 		// offset 0x1c is not used
1056 
1057 		case 0x1e:   /* control register */
1058 		{
1059 			flip = (data & 0x40) ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0;
1060 			TC0480SCP_pri_reg = data;
1061 
1062 			tilemap_set_flip(TC0480SCP_tilemap[0],flip);
1063 			tilemap_set_flip(TC0480SCP_tilemap[1],flip);
1064 			tilemap_set_flip(TC0480SCP_tilemap[2],flip);
1065 			tilemap_set_flip(TC0480SCP_tilemap[3],flip);
1066 			tilemap_set_flip(TC0480SCP_tilemap[4],flip);
1067 
1068 			break;
1069 		}
1070 
1071 		// Rest are (I think) layer specific delta x and y, used while scrolling that layer
1072 	}
1073 }
1074 
WRITE_HANDLER(TC0480SCP_ctrl_word_w)1075 WRITE_HANDLER( TC0480SCP_ctrl_word_w )
1076 {
1077 	TC0480SCP_ctrl_word_write(offset,data);
1078 }
1079 
TC0480SCP_tilemap_update(void)1080 void TC0480SCP_tilemap_update(void)
1081 {
1082 	int layer, zoom, i, j;
1083 	int flip = TC0480SCP_pri_reg & 0x40;
1084 
1085 	for (layer = 0; layer < 4; layer++)
1086 	{
1087 		tilemap_set_scrolly(TC0480SCP_tilemap[layer],0,TC0480SCP_bgscrolly[layer]);
1088 		zoom = 0x10000 + 0x7f - READ_WORD(&TC0480SCP_ctrl[0x10 + 2*layer]);
1089 
1090 		if (zoom != 0x10000)	/* currently we can't use scroll rows when zooming */
1091 		{
1092 			tilemap_set_scrollx(TC0480SCP_tilemap[layer],
1093 					0, TC0480SCP_bgscrollx[layer]);
1094 		}
1095 		else
1096 		{
1097 			for (j = 0;j < 256;j++)
1098 			{
1099 				i = READ_WORD(&TC0480SCP_bgscroll_ram[layer][(2*j)]);
1100 
1101 // DG: possible issues: check yellow bg layer when you kill metalb round 1 boss.
1102 // Top part doesn't behave like rest. But these are right for Footchmp+clones.
1103 
1104 				if (!flip)
1105 				tilemap_set_scrollx(TC0480SCP_tilemap[layer],
1106 						(j + TC0480SCP_bgscrolly[layer] + (16 - TC0480SCP_y_offs)) & 0x1ff,
1107 						TC0480SCP_bgscrollx[layer] - i);
1108 				if (flip)
1109 				tilemap_set_scrollx(TC0480SCP_tilemap[layer],
1110 						(j + TC0480SCP_bgscrolly[layer] + 0x100 + (16 + TC0480SCP_y_offs)) & 0x1ff,
1111 						TC0480SCP_bgscrollx[layer] + i);
1112 			}
1113 		}
1114 	}
1115 
1116 	/* Decode any characters that have changed */
1117 	if (TC0480SCP_chars_dirty)
1118 	{
1119 		int tile_index;
1120 
1121 		for (tile_index = 0;tile_index < 64*64;tile_index++)
1122 		{
1123 			int attr = READ_WORD(&TC0480SCP_tx_ram[2*tile_index]);
1124 			if (TC0480SCP_char_dirty[attr & 0xff])
1125 				tilemap_mark_tile_dirty(TC0480SCP_tilemap[4],tile_index);
1126 		}
1127 
1128 		for (j = 0;j < TC0480SCP_TOTAL_CHARS;j++)
1129 		{
1130 			if (TC0480SCP_char_dirty[j])
1131 				decodechar(Machine->gfx[TC0480SCP_tx_gfx],j,TC0480SCP_char_ram,&TC0480SCP_charlayout);
1132 			TC0480SCP_char_dirty[j] = 0;
1133 		}
1134 		TC0480SCP_chars_dirty = 0;
1135 	}
1136 
1137 	tilemap_update(TC0480SCP_tilemap[0]);
1138 	tilemap_update(TC0480SCP_tilemap[1]);
1139 	tilemap_update(TC0480SCP_tilemap[2]);
1140 	tilemap_update(TC0480SCP_tilemap[3]);
1141 	tilemap_update(TC0480SCP_tilemap[4]);
1142 }
1143 
1144 
1145 /*********************************************************************
1146 			LAYER ZOOM (still a WIP)
1147 
1148 1) bg layers got too far left and down, the greater the magnification.
1149    Largely fixed by adding offsets (to startx&y) which get bigger as
1150    we zoom in.
1151 
1152 2) Hthero and Footchmp bg layers behaved differently when zoomed.
1153    Fixed by bringing tc0480scp_x&y_offs into calculations.
1154 
1155 3) Metalb "TAITO" text in attract too far to the right.
1156    Fixed(?) by bringing (layer*4) into offset calculations.
1157 **********************************************************************/
1158 
zoomtilemap_draw(struct osd_bitmap * bitmap,int layer,int flags)1159 static void zoomtilemap_draw(struct osd_bitmap *bitmap,int layer,int flags)
1160 {
1161 	/* <0x7f = shrunk e.g. 0x1a in Footchmp hiscore; 0x7f = normal;
1162 		0xfefe = max(?) zoom e.g. start of game in Metalb */
1163 
1164 	int zoom = 0x10000 + 0x7f - READ_WORD(&TC0480SCP_ctrl[0x10 + 2*layer]);
1165 
1166 	if (zoom == 0x10000)	/* no zoom, so we won't need copyrozbitmap */
1167 	{
1168 		tilemap_set_clip(TC0480SCP_tilemap[layer],&Machine->visible_area);	// prevent bad things
1169 		tilemap_draw(bitmap,TC0480SCP_tilemap[layer],flags);
1170 	}
1171 	else	/* zoom */
1172 	{
1173 		UINT32 startx,starty;
1174 		int incxx,incxy,incyx,incyy;
1175 		struct osd_bitmap *srcbitmap = TC0480SCP_tilemap[layer]->pixmap;
1176 		int priority = flags >> 16;
1177 		int flip = TC0480SCP_pri_reg & 0x40;
1178 
1179 		tilemap_set_clip(TC0480SCP_tilemap[layer],0);
1180 
1181 		if (!flip)
1182 		{
1183 			startx = ((TC0480SCP_bgscrollx[layer] + 16 + layer*4) << 16)
1184 				- ((READ_WORD(&TC0480SCP_ctrl[0x20 + 2*layer]) & 0xff) << 8);	// low order byte
1185 
1186 			incxx = zoom;
1187 			incyx = 0;
1188 
1189 			starty = (TC0480SCP_bgscrolly[layer] << 16)
1190 				+ ((READ_WORD(&TC0480SCP_ctrl[0x28 + 2*layer]) & 0xff) << 8);	// low order byte
1191 			incxy = 0;
1192 			incyy = zoom;
1193 
1194 			startx += (TC0480SCP_x_offs - 16 - layer*4) * incxx;
1195 			starty -= (TC0480SCP_y_offs) * incyy;
1196 		}
1197 		else
1198 		{
1199 			startx = ((-TC0480SCP_bgscrollx[layer] + 16 + layer*4) << 16)
1200 				- ((READ_WORD(&TC0480SCP_ctrl[0x20 + 2*layer]) & 0xff) << 8);	// low order byte
1201 
1202 			incxx = zoom;
1203 			incyx = 0;
1204 
1205 			starty = (-TC0480SCP_bgscrolly[layer] << 16)
1206 				+ ((READ_WORD(&TC0480SCP_ctrl[0x28 + 2*layer]) & 0xff) << 8);	// low order byte
1207 			incxy = 0;
1208 			incyy = zoom;
1209 
1210 			startx += (TC0480SCP_x_offs - 16 - layer*4) * incxx;
1211 			starty -= (TC0480SCP_y_offs) * incyy;
1212 		}
1213 
1214 		copyrozbitmap(bitmap,srcbitmap,startx,starty,
1215 				incxx,incxy,incyx,incyy,
1216 				1,	/* copy with wraparound */
1217 				&Machine->visible_area,TRANSPARENCY_PEN,palette_transparent_pen,priority);
1218 	}
1219 }
1220 
TC0480SCP_tilemap_draw(struct osd_bitmap * bitmap,int layer,int flags)1221 void TC0480SCP_tilemap_draw(struct osd_bitmap *bitmap,int layer,int flags)
1222 {
1223 
1224 // DG: don't know where disable bit(s) are....
1225 //	int disable = READ_WORD(&TC0480SCP_ctrl[0x1e]) & 0x1f;
1226 
1227 	switch (layer)
1228 	{
1229 		case 0:
1230 //			if (disable & 0x??) return;
1231 			zoomtilemap_draw(bitmap,0,flags);
1232 			break;
1233 		case 1:
1234 //			if (disable & 0x??) return;
1235 			zoomtilemap_draw(bitmap,1,flags);
1236 			break;
1237 		case 2:
1238 //			if (disable & 0x??) return;
1239 			zoomtilemap_draw(bitmap,2,flags);
1240 			break;
1241 		case 3:
1242 //			if (disable & 0x??) return;
1243 			zoomtilemap_draw(bitmap,3,flags);
1244 			break;
1245 		case 4:
1246 //			if (disable & 0x??) return;
1247 			tilemap_draw(bitmap,TC0480SCP_tilemap[4],flags);
1248 			break;
1249 	}
1250 }
1251 
1252 
1253 /***************************************************************************/
1254 
1255 
1256 static int TC0110PCR_addr;
1257 static UINT16 *TC0110PCR_ram;
1258 #define TC0110PCR_RAM_SIZE 0x2000
1259 
TC0110PCR_vh_start(void)1260 int TC0110PCR_vh_start(void)
1261 {
1262 	TC0110PCR_ram = (UINT16*)malloc(TC0110PCR_RAM_SIZE * sizeof(*TC0110PCR_ram));
1263 
1264 	if (!TC0110PCR_ram) return 1;
1265 
1266 	return 0;
1267 }
1268 
TC0110PCR_vh_stop(void)1269 void TC0110PCR_vh_stop(void)
1270 {
1271 	free(TC0110PCR_ram);
1272 	TC0110PCR_ram = 0;
1273 }
1274 
READ_HANDLER(TC0110PCR_word_r)1275 READ_HANDLER( TC0110PCR_word_r )
1276 {
1277 	switch (offset)
1278 	{
1279 		case 2:
1280 			return TC0110PCR_ram[TC0110PCR_addr];
1281 
1282 		default:
1283 			return 0xff;
1284 	}
1285 }
1286 
WRITE_HANDLER(TC0110PCR_word_w)1287 WRITE_HANDLER( TC0110PCR_word_w )
1288 {
1289 	switch (offset)
1290 	{
1291 		case 0:
1292 			TC0110PCR_addr = (data >> 1) & 0xfff;   /* In test mode game writes to odd register number so it is (data>>1) */
1293 			break;
1294 
1295 		case 2:
1296 		{
1297 			int r,g,b;   /* data = palette BGR value */
1298 
1299 
1300 			TC0110PCR_ram[TC0110PCR_addr] = data & 0xffff;
1301 
1302 			r = (data >>  0) & 0x1f;
1303 			g = (data >>  5) & 0x1f;
1304 			b = (data >> 10) & 0x1f;
1305 
1306 			r = (r << 3) | (r >> 2);
1307 			g = (g << 3) | (g >> 2);
1308 			b = (b << 3) | (b >> 2);
1309 
1310 			palette_change_color(TC0110PCR_addr,r,g,b);
1311 			break;
1312 		}
1313 
1314 		default:
1315 			break;
1316 	}
1317 }
1318 
1319 
1320 /***************************************************************************/
1321 
1322 
1323 static unsigned char TC0220IOC_regs[16];
1324 
READ_HANDLER(TC0220IOC_r)1325 READ_HANDLER( TC0220IOC_r )
1326 {
1327 	switch (offset)
1328 	{
1329 		case 0x00:	/* IN00-07 (DSA) */
1330 			return readinputport(0);
1331 
1332 		case 0x01:	/* IN08-15 (DSB) */
1333 			return readinputport(1);
1334 
1335 		case 0x02:	/* IN16-23 (1P) */
1336 			return readinputport(2);
1337 
1338 		case 0x03:	/* IN24-31 (2P) */
1339 			return readinputport(3);
1340 
1341 		case 0x04:	/* coin counters and lockout */
1342 			return TC0220IOC_regs[4];
1343 
1344 		case 0x07:	/* INB0-7 (coin) */
1345 			return readinputport(4);
1346 
1347 		default:
1348 			return 0xff;
1349 	}
1350 }
1351 
WRITE_HANDLER(TC0220IOC_w)1352 WRITE_HANDLER( TC0220IOC_w )
1353 {
1354 	TC0220IOC_regs[offset] = data;
1355 
1356 	switch (offset)
1357 	{
1358 		case 0x00:
1359 			watchdog_reset_w(offset,data);
1360 			break;
1361 
1362 		case 0x04:	/* coin counters and lockout */
1363 			coin_lockout_w(0,~data & 0x01);
1364 			coin_lockout_w(1,~data & 0x02);
1365 			coin_counter_w(0,data & 0x04);
1366 			coin_counter_w(1,data & 0x08);
1367 			break;
1368 
1369 		default:
1370 			break;
1371 	}
1372 }
1373 
1374 
1375 /***************************************************************************/
1376 
1377 
1378 static unsigned char TC0510NIO_regs[16];
1379 
READ_HANDLER(TC0510NIO_r)1380 READ_HANDLER( TC0510NIO_r )
1381 {
1382 	switch (offset)
1383 	{
1384 		case 0x00:	/* DSA */
1385 			return readinputport(0);
1386 
1387 		case 0x01:	/* DSB */
1388 			return readinputport(1);
1389 
1390 		case 0x02:	/* 1P */
1391 			return readinputport(2);
1392 
1393 		case 0x03:	/* 2P */
1394 			return readinputport(3);
1395 
1396 		case 0x04:	/* coin counters and lockout */
1397 			return TC0510NIO_regs[4];
1398 
1399 		case 0x07:	/* coin */
1400 			return readinputport(4);
1401 
1402 		default:
1403 			return 0xff;
1404 	}
1405 }
1406 
WRITE_HANDLER(TC0510NIO_w)1407 WRITE_HANDLER( TC0510NIO_w )
1408 {
1409 	TC0510NIO_regs[offset] = data;
1410 
1411 	switch (offset)
1412 	{
1413 		case 0x00:
1414 			watchdog_reset_w(offset,data);
1415 			break;
1416 
1417 		case 0x04:	/* coin counters and lockout */
1418 			coin_lockout_w(0,~data & 0x01);
1419 			coin_lockout_w(1,~data & 0x02);
1420 			coin_counter_w(0,data & 0x04);
1421 			coin_counter_w(1,data & 0x08);
1422 			break;
1423 
1424 		default:
1425 			break;
1426 	}
1427 }
1428