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