1 /***********************************************************************
2 
3 	DECO Cassette System vidhrdw
4 
5  ***********************************************************************/
6 
7 #include "driver.h"
8 #include "vidhrdw/generic.h"
9 #include "machine/decocass.h"
10 #include "state.h"
11 
12 static int watchdog_count;
13 static int watchdog_flip;
14 static int color_missiles;
15 static int color_center_bot;
16 static int mode_set;
17 static int back_h_shift;
18 static int back_vl_shift;
19 static int back_vr_shift;
20 static int part_h_shift;
21 static int part_v_shift;
22 static int center_h_shift_space;
23 static int center_v_shift;
24 
25 unsigned char *decocass_charram;
26 unsigned char *decocass_fgvideoram;
27 unsigned char *decocass_colorram;
28 unsigned char *decocass_bgvideoram; /* shares bits D0-3 with tileram! */
29 unsigned char *decocass_tileram;
30 unsigned char *decocass_objectram;
31 
32 size_t decocass_fgvideoram_size;
33 size_t decocass_colorram_size;
34 size_t decocass_bgvideoram_size;
35 size_t decocass_tileram_size;
36 size_t decocass_objectram_size;
37 
38 static struct tilemap *fg_tilemap, *bg_tilemap_l, *bg_tilemap_r;
39 
40 static char *sprite_dirty;
41 static char *char_dirty;
42 static char *tile_dirty;
43 static char object_dirty;
44 
45 static struct rectangle bg_tilemap_l_clip;
46 static struct rectangle bg_tilemap_r_clip;
47 
48 static UINT32 tile_offset[32*32] = {
49 	0x078,0x079,0x07a,0x07b,0x07c,0x07d,0x07e,0x07f,0x0ff,0x0fe,0x0fd,0x0fc,0x0fb,0x0fa,0x0f9,0x0f8,0x278,0x279,0x27a,0x27b,0x27c,0x27d,0x27e,0x27f,0x2ff,0x2fe,0x2fd,0x2fc,0x2fb,0x2fa,0x2f9,0x2f8,
50 	0x070,0x071,0x072,0x073,0x074,0x075,0x076,0x077,0x0f7,0x0f6,0x0f5,0x0f4,0x0f3,0x0f2,0x0f1,0x0f0,0x270,0x271,0x272,0x273,0x274,0x275,0x276,0x277,0x2f7,0x2f6,0x2f5,0x2f4,0x2f3,0x2f2,0x2f1,0x2f0,
51 	0x068,0x069,0x06a,0x06b,0x06c,0x06d,0x06e,0x06f,0x0ef,0x0ee,0x0ed,0x0ec,0x0eb,0x0ea,0x0e9,0x0e8,0x268,0x269,0x26a,0x26b,0x26c,0x26d,0x26e,0x26f,0x2ef,0x2ee,0x2ed,0x2ec,0x2eb,0x2ea,0x2e9,0x2e8,
52 	0x060,0x061,0x062,0x063,0x064,0x065,0x066,0x067,0x0e7,0x0e6,0x0e5,0x0e4,0x0e3,0x0e2,0x0e1,0x0e0,0x260,0x261,0x262,0x263,0x264,0x265,0x266,0x267,0x2e7,0x2e6,0x2e5,0x2e4,0x2e3,0x2e2,0x2e1,0x2e0,
53 	0x058,0x059,0x05a,0x05b,0x05c,0x05d,0x05e,0x05f,0x0df,0x0de,0x0dd,0x0dc,0x0db,0x0da,0x0d9,0x0d8,0x258,0x259,0x25a,0x25b,0x25c,0x25d,0x25e,0x25f,0x2df,0x2de,0x2dd,0x2dc,0x2db,0x2da,0x2d9,0x2d8,
54 	0x050,0x051,0x052,0x053,0x054,0x055,0x056,0x057,0x0d7,0x0d6,0x0d5,0x0d4,0x0d3,0x0d2,0x0d1,0x0d0,0x250,0x251,0x252,0x253,0x254,0x255,0x256,0x257,0x2d7,0x2d6,0x2d5,0x2d4,0x2d3,0x2d2,0x2d1,0x2d0,
55 	0x048,0x049,0x04a,0x04b,0x04c,0x04d,0x04e,0x04f,0x0cf,0x0ce,0x0cd,0x0cc,0x0cb,0x0ca,0x0c9,0x0c8,0x248,0x249,0x24a,0x24b,0x24c,0x24d,0x24e,0x24f,0x2cf,0x2ce,0x2cd,0x2cc,0x2cb,0x2ca,0x2c9,0x2c8,
56 	0x040,0x041,0x042,0x043,0x044,0x045,0x046,0x047,0x0c7,0x0c6,0x0c5,0x0c4,0x0c3,0x0c2,0x0c1,0x0c0,0x240,0x241,0x242,0x243,0x244,0x245,0x246,0x247,0x2c7,0x2c6,0x2c5,0x2c4,0x2c3,0x2c2,0x2c1,0x2c0,
57 	0x038,0x039,0x03a,0x03b,0x03c,0x03d,0x03e,0x03f,0x0bf,0x0be,0x0bd,0x0bc,0x0bb,0x0ba,0x0b9,0x0b8,0x238,0x239,0x23a,0x23b,0x23c,0x23d,0x23e,0x23f,0x2bf,0x2be,0x2bd,0x2bc,0x2bb,0x2ba,0x2b9,0x2b8,
58 	0x030,0x031,0x032,0x033,0x034,0x035,0x036,0x037,0x0b7,0x0b6,0x0b5,0x0b4,0x0b3,0x0b2,0x0b1,0x0b0,0x230,0x231,0x232,0x233,0x234,0x235,0x236,0x237,0x2b7,0x2b6,0x2b5,0x2b4,0x2b3,0x2b2,0x2b1,0x2b0,
59 	0x028,0x029,0x02a,0x02b,0x02c,0x02d,0x02e,0x02f,0x0af,0x0ae,0x0ad,0x0ac,0x0ab,0x0aa,0x0a9,0x0a8,0x228,0x229,0x22a,0x22b,0x22c,0x22d,0x22e,0x22f,0x2af,0x2ae,0x2ad,0x2ac,0x2ab,0x2aa,0x2a9,0x2a8,
60 	0x020,0x021,0x022,0x023,0x024,0x025,0x026,0x027,0x0a7,0x0a6,0x0a5,0x0a4,0x0a3,0x0a2,0x0a1,0x0a0,0x220,0x221,0x222,0x223,0x224,0x225,0x226,0x227,0x2a7,0x2a6,0x2a5,0x2a4,0x2a3,0x2a2,0x2a1,0x2a0,
61 	0x018,0x019,0x01a,0x01b,0x01c,0x01d,0x01e,0x01f,0x09f,0x09e,0x09d,0x09c,0x09b,0x09a,0x099,0x098,0x218,0x219,0x21a,0x21b,0x21c,0x21d,0x21e,0x21f,0x29f,0x29e,0x29d,0x29c,0x29b,0x29a,0x299,0x298,
62 	0x010,0x011,0x012,0x013,0x014,0x015,0x016,0x017,0x097,0x096,0x095,0x094,0x093,0x092,0x091,0x090,0x210,0x211,0x212,0x213,0x214,0x215,0x216,0x217,0x297,0x296,0x295,0x294,0x293,0x292,0x291,0x290,
63 	0x008,0x009,0x00a,0x00b,0x00c,0x00d,0x00e,0x00f,0x08f,0x08e,0x08d,0x08c,0x08b,0x08a,0x089,0x088,0x208,0x209,0x20a,0x20b,0x20c,0x20d,0x20e,0x20f,0x28f,0x28e,0x28d,0x28c,0x28b,0x28a,0x289,0x288,
64 	0x000,0x001,0x002,0x003,0x004,0x005,0x006,0x007,0x087,0x086,0x085,0x084,0x083,0x082,0x081,0x080,0x200,0x201,0x202,0x203,0x204,0x205,0x206,0x207,0x287,0x286,0x285,0x284,0x283,0x282,0x281,0x280,
65 	0x178,0x179,0x17a,0x17b,0x17c,0x17d,0x17e,0x17f,0x1ff,0x1fe,0x1fd,0x1fc,0x1fb,0x1fa,0x1f9,0x1f8,0x378,0x379,0x37a,0x37b,0x37c,0x37d,0x37e,0x37f,0x3ff,0x3fe,0x3fd,0x3fc,0x3fb,0x3fa,0x3f9,0x3f8,
66 	0x170,0x171,0x172,0x173,0x174,0x175,0x176,0x177,0x1f7,0x1f6,0x1f5,0x1f4,0x1f3,0x1f2,0x1f1,0x1f0,0x370,0x371,0x372,0x373,0x374,0x375,0x376,0x377,0x3f7,0x3f6,0x3f5,0x3f4,0x3f3,0x3f2,0x3f1,0x3f0,
67 	0x168,0x169,0x16a,0x16b,0x16c,0x16d,0x16e,0x16f,0x1ef,0x1ee,0x1ed,0x1ec,0x1eb,0x1ea,0x1e9,0x1e8,0x368,0x369,0x36a,0x36b,0x36c,0x36d,0x36e,0x36f,0x3ef,0x3ee,0x3ed,0x3ec,0x3eb,0x3ea,0x3e9,0x3e8,
68 	0x160,0x161,0x162,0x163,0x164,0x165,0x166,0x167,0x1e7,0x1e6,0x1e5,0x1e4,0x1e3,0x1e2,0x1e1,0x1e0,0x360,0x361,0x362,0x363,0x364,0x365,0x366,0x367,0x3e7,0x3e6,0x3e5,0x3e4,0x3e3,0x3e2,0x3e1,0x3e0,
69 	0x158,0x159,0x15a,0x15b,0x15c,0x15d,0x15e,0x15f,0x1df,0x1de,0x1dd,0x1dc,0x1db,0x1da,0x1d9,0x1d8,0x358,0x359,0x35a,0x35b,0x35c,0x35d,0x35e,0x35f,0x3df,0x3de,0x3dd,0x3dc,0x3db,0x3da,0x3d9,0x3d8,
70 	0x150,0x151,0x152,0x153,0x154,0x155,0x156,0x157,0x1d7,0x1d6,0x1d5,0x1d4,0x1d3,0x1d2,0x1d1,0x1d0,0x350,0x351,0x352,0x353,0x354,0x355,0x356,0x357,0x3d7,0x3d6,0x3d5,0x3d4,0x3d3,0x3d2,0x3d1,0x3d0,
71 	0x148,0x149,0x14a,0x14b,0x14c,0x14d,0x14e,0x14f,0x1cf,0x1ce,0x1cd,0x1cc,0x1cb,0x1ca,0x1c9,0x1c8,0x348,0x349,0x34a,0x34b,0x34c,0x34d,0x34e,0x34f,0x3cf,0x3ce,0x3cd,0x3cc,0x3cb,0x3ca,0x3c9,0x3c8,
72 	0x140,0x141,0x142,0x143,0x144,0x145,0x146,0x147,0x1c7,0x1c6,0x1c5,0x1c4,0x1c3,0x1c2,0x1c1,0x1c0,0x340,0x341,0x342,0x343,0x344,0x345,0x346,0x347,0x3c7,0x3c6,0x3c5,0x3c4,0x3c3,0x3c2,0x3c1,0x3c0,
73 	0x138,0x139,0x13a,0x13b,0x13c,0x13d,0x13e,0x13f,0x1bf,0x1be,0x1bd,0x1bc,0x1bb,0x1ba,0x1b9,0x1b8,0x338,0x339,0x33a,0x33b,0x33c,0x33d,0x33e,0x33f,0x3bf,0x3be,0x3bd,0x3bc,0x3bb,0x3ba,0x3b9,0x3b8,
74 	0x130,0x131,0x132,0x133,0x134,0x135,0x136,0x137,0x1b7,0x1b6,0x1b5,0x1b4,0x1b3,0x1b2,0x1b1,0x1b0,0x330,0x331,0x332,0x333,0x334,0x335,0x336,0x337,0x3b7,0x3b6,0x3b5,0x3b4,0x3b3,0x3b2,0x3b1,0x3b0,
75 	0x128,0x129,0x12a,0x12b,0x12c,0x12d,0x12e,0x12f,0x1af,0x1ae,0x1ad,0x1ac,0x1ab,0x1aa,0x1a9,0x1a8,0x328,0x329,0x32a,0x32b,0x32c,0x32d,0x32e,0x32f,0x3af,0x3ae,0x3ad,0x3ac,0x3ab,0x3aa,0x3a9,0x3a8,
76 	0x120,0x121,0x122,0x123,0x124,0x125,0x126,0x127,0x1a7,0x1a6,0x1a5,0x1a4,0x1a3,0x1a2,0x1a1,0x1a0,0x320,0x321,0x322,0x323,0x324,0x325,0x326,0x327,0x3a7,0x3a6,0x3a5,0x3a4,0x3a3,0x3a2,0x3a1,0x3a0,
77 	0x118,0x119,0x11a,0x11b,0x11c,0x11d,0x11e,0x11f,0x19f,0x19e,0x19d,0x19c,0x19b,0x19a,0x199,0x198,0x318,0x319,0x31a,0x31b,0x31c,0x31d,0x31e,0x31f,0x39f,0x39e,0x39d,0x39c,0x39b,0x39a,0x399,0x398,
78 	0x110,0x111,0x112,0x113,0x114,0x115,0x116,0x117,0x197,0x196,0x195,0x194,0x193,0x192,0x191,0x190,0x310,0x311,0x312,0x313,0x314,0x315,0x316,0x317,0x397,0x396,0x395,0x394,0x393,0x392,0x391,0x390,
79 	0x108,0x109,0x10a,0x10b,0x10c,0x10d,0x10e,0x10f,0x18f,0x18e,0x18d,0x18c,0x18b,0x18a,0x189,0x188,0x308,0x309,0x30a,0x30b,0x30c,0x30d,0x30e,0x30f,0x38f,0x38e,0x38d,0x38c,0x38b,0x38a,0x389,0x388,
80 	0x100,0x101,0x102,0x103,0x104,0x105,0x106,0x107,0x187,0x186,0x185,0x184,0x183,0x182,0x181,0x180,0x300,0x301,0x302,0x303,0x304,0x305,0x306,0x307,0x387,0x386,0x385,0x384,0x383,0x382,0x381,0x380
81 };
82 
83 /********************************************
84 	tilemap callbacks
85  ********************************************/
86 
fgvideoram_scan_cols(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)87 static UINT32 fgvideoram_scan_cols( UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows )
88 {
89 	/* logical (col,row) -> memory offset */
90 	return (num_cols - 1 - col) * num_rows + row;
91 }
92 
bgvideoram_scan_cols(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)93 static UINT32 bgvideoram_scan_cols( UINT32 col, UINT32 row, UINT32 num_cols, UINT32 num_rows )
94 {
95 	/* logical (col,row) -> memory offset */
96 	return tile_offset[col * num_rows + row];
97 }
98 
get_bg_l_tile_info(int tile_index)99 static void get_bg_l_tile_info(int tile_index)
100 {
101 	int color = (color_center_bot >> 7) & 1;
102 	SET_TILE_INFO(
103 			2,
104 			(0x80 == (tile_index & 0x80)) ? 16 : decocass_bgvideoram[tile_index] >> 4,
105 			color,
106 			0)
107 }
108 
get_bg_r_tile_info(int tile_index)109 static void get_bg_r_tile_info(int tile_index)
110 {
111 	int color = (color_center_bot >> 7) & 1;
112 	SET_TILE_INFO(
113 			2,
114 			(0x00 == (tile_index & 0x80)) ? 16 : decocass_bgvideoram[tile_index] >> 4,
115 			color,
116 			TILE_FLIPY)
117 }
118 
get_fg_tile_info(int tile_index)119 static void get_fg_tile_info(int tile_index)
120 {
121 	unsigned char code = decocass_fgvideoram[tile_index];
122 	unsigned char attr = decocass_colorram[tile_index];
123 	SET_TILE_INFO(
124 			0,
125 			256 * (attr & 3) + code,
126 			color_center_bot & 1,
127 			0)
128 }
129 
130 /********************************************
131 	big object
132  ********************************************/
133 
draw_object(struct mame_bitmap * bitmap,const struct rectangle * cliprect)134 static void draw_object(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
135 {
136 	int sx, sy, color;
137 
138 	if (0 == (mode_set & 0x80))  /* part_h_enable off? */
139 		return;
140 
141 	color = (color_center_bot >> 4) & 15;
142 
143 	sy = 192 - (part_v_shift & 0x7f);
144 
145 	if (part_h_shift & 0x80)
146 		sx = (part_h_shift & 0x7f) + 1;
147 	else
148 		sx = 91 - (part_h_shift & 0x7f);
149 
150 	drawgfx(bitmap, Machine->gfx[3], 0, color, 0, 0, sx + 64, sy, cliprect, TRANSPARENCY_PEN, 0);
151 	drawgfx(bitmap, Machine->gfx[3], 1, color, 0, 0, sx, sy, cliprect, TRANSPARENCY_PEN, 0);
152 	drawgfx(bitmap, Machine->gfx[3], 0, color, 0, 1, sx + 64, sy - 64, cliprect, TRANSPARENCY_PEN, 0);
153 	drawgfx(bitmap, Machine->gfx[3], 1, color, 0, 1, sx, sy - 64, cliprect, TRANSPARENCY_PEN, 0);
154 }
155 
draw_center(struct mame_bitmap * bitmap,const struct rectangle * cliprect)156 static void draw_center(struct mame_bitmap *bitmap, const struct rectangle *cliprect)
157 {
158 	int sx, sy, x, y, color;
159 
160 	color = 0;
161 	if (color_center_bot & 0x10)
162 		color |= 4;
163 	if (color_center_bot & 0x20)
164 		color |= 2;
165 	if (color_center_bot & 0x40)
166 		color |= 1;
167 	if (color_center_bot & 0x80)
168 		color = (color & 4) + ((color << 1) & 2) + ((color >> 1) & 1);
169 
170 	sy = center_v_shift;
171 	sx = (center_h_shift_space >> 2) & 0x3c;
172 
173 	for (y = 0; y < 4; y++)
174 		if ((sy + y) >= cliprect->min_y && (sy + y) <= cliprect->max_y)
175 		{
176 			if (((sy + y) & color_center_bot & 3) == (sy & color_center_bot & 3))
177 				for (x = 0; x < 256; x++)
178 					if (0 != (x & 16) || 0 != (center_h_shift_space & 1))
179 						plot_pixel(bitmap, (sx + x) & 255, sy + y, Machine->pens[color]);
180 		}
181 }
182 
183 /********************************************
184 	memory handlers
185  ********************************************/
186 
WRITE_HANDLER(decocass_paletteram_w)187 WRITE_HANDLER( decocass_paletteram_w )
188 {
189 	/*
190 	 * RGB output is inverted and A4 is inverted too
191 	 * (ME/ input on 1st paletteram, inverter -> ME/ on 2nd)
192 	 */
193 	offset = (offset & 31) ^ 16;
194 	paletteram_BBGGGRRR_w( offset, ~data );
195 }
196 
WRITE_HANDLER(decocass_charram_w)197 WRITE_HANDLER( decocass_charram_w )
198 {
199 	if (data == decocass_charram[offset])
200 		return;
201 	decocass_charram[offset] = data;
202 	/* dirty sprite */
203 	sprite_dirty[(offset >> 5) & 255] = 1;
204 	/* dirty char */
205 	char_dirty[(offset >> 3) & 1023] = 1;
206 }
207 
208 
WRITE_HANDLER(decocass_fgvideoram_w)209 WRITE_HANDLER( decocass_fgvideoram_w )
210 {
211 	if (data == decocass_fgvideoram[offset])
212 		return;
213 	decocass_fgvideoram[offset] = data;
214 	tilemap_mark_tile_dirty( fg_tilemap, offset );
215 }
216 
WRITE_HANDLER(decocass_colorram_w)217 WRITE_HANDLER( decocass_colorram_w )
218 {
219 	if (data == decocass_colorram[offset])
220 		return;
221 	decocass_colorram[offset] = data;
222 	tilemap_mark_tile_dirty( fg_tilemap, offset );
223 }
224 
mark_bg_tile_dirty(offs_t offset)225 static void mark_bg_tile_dirty(offs_t offset)
226 {
227 	if (offset & 0x80)
228 		tilemap_mark_tile_dirty( bg_tilemap_r, offset );
229 	else
230 		tilemap_mark_tile_dirty( bg_tilemap_l, offset );
231 }
232 
WRITE_HANDLER(decocass_tileram_w)233 WRITE_HANDLER( decocass_tileram_w )
234 {
235 	if (data == decocass_tileram[offset])
236 		return;
237 	decocass_tileram[offset] = data;
238 	/* dirty tile (64 bytes per tile) */
239 	tile_dirty[(offset / 64) & 15] = 1;
240 	/* first 1KB of tile RAM is shared with tilemap RAM */
241 	if (offset < decocass_bgvideoram_size)
242 		mark_bg_tile_dirty( offset );
243 }
244 
WRITE_HANDLER(decocass_objectram_w)245 WRITE_HANDLER( decocass_objectram_w )
246 {
247 	if (data == decocass_objectram[offset])
248 		return;
249 	decocass_objectram[offset] = data;
250 	/* dirty the object */
251 	object_dirty = 1;
252 }
253 
WRITE_HANDLER(decocass_bgvideoram_w)254 WRITE_HANDLER( decocass_bgvideoram_w )
255 {
256 	if (data == decocass_bgvideoram[offset])
257 		return;
258 	decocass_bgvideoram[offset] = data;
259 	mark_bg_tile_dirty( offset );
260 }
261 
READ_HANDLER(decocass_mirrorvideoram_r)262 READ_HANDLER( decocass_mirrorvideoram_r )
263 {
264 	int x,y;
265 
266 	/* swap x and y coordinates */
267 	x = offset / 32;
268 	y = offset % 32;
269 	offset = 32 * y + x;
270 
271 	return decocass_fgvideoram[offset];
272 }
273 
READ_HANDLER(decocass_mirrorcolorram_r)274 READ_HANDLER( decocass_mirrorcolorram_r )
275 {
276 	int x,y;
277 
278 	/* swap x and y coordinates */
279 	x = offset / 32;
280 	y = offset % 32;
281 	offset = 32 * y + x;
282 
283 	return decocass_colorram[offset];
284 }
285 
WRITE_HANDLER(decocass_mirrorvideoram_w)286 WRITE_HANDLER( decocass_mirrorvideoram_w )
287 {
288 	int x,y;
289 
290 	/* swap x and y coordinates */
291 	x = offset / 32;
292 	y = offset % 32;
293 	offset = 32 * y + x;
294 
295 	decocass_fgvideoram_w(offset,data);
296 }
297 
WRITE_HANDLER(decocass_mirrorcolorram_w)298 WRITE_HANDLER( decocass_mirrorcolorram_w )
299 {
300 	int x,y;
301 
302 	/* swap x and y coordinates */
303 	x = offset / 32;
304 	y = offset % 32;
305 	offset = 32 * y + x;
306 
307 	decocass_colorram_w(offset,data);
308 }
309 
310 /* The watchdog is a 4bit counter counting down every frame */
WRITE_HANDLER(decocass_watchdog_count_w)311 WRITE_HANDLER( decocass_watchdog_count_w )
312 {
313 	LOG(1,("decocass_watchdog_count_w: $%02x\n", data));
314 	watchdog_count = data & 0x0f;
315 }
316 
WRITE_HANDLER(decocass_watchdog_flip_w)317 WRITE_HANDLER( decocass_watchdog_flip_w )
318 {
319 	LOG(1,("decocass_watchdog_flip_w: $%02x\n", data));
320 	watchdog_flip = data;
321 }
322 
WRITE_HANDLER(decocass_color_missiles_w)323 WRITE_HANDLER( decocass_color_missiles_w )
324 {
325 	LOG(1,("decocass_color_missiles_w: $%02x\n", data));
326 	/* only bits D0-D2 and D4-D6 are connected to
327 	 * the color RAM demux:
328 	 * D0-D2 to the IC0 inputs
329 	 * D4-D6 to the IC1 inputs
330 	 */
331 	color_missiles = data & 0x77;
332 }
333 
334 /*
335  * D0 - ??
336  * D1 - ??
337  * D2 - ptn 1/2
338  * D3 - BKG ena
339  * D4 - center L on
340  * D5 - cross on
341  * D6 - tunnel
342  * D7 - part h enable
343  */
WRITE_HANDLER(decocass_mode_set_w)344 WRITE_HANDLER( decocass_mode_set_w )
345 {
346 	if (data == mode_set)
347 		return;
348 	LOG(1,("decocass_mode_set_w: $%02x (%s%s%s%s%s%s%s%s)\n", data,
349 		(data & 0x01) ? "D0?" : "",
350 		(data & 0x02) ? " D1?" : "",
351 		(data & 0x04) ? " ptn1/2" : "",
352 		(data & 0x08) ? " bkg_ena" : "",
353 		(data & 0x10) ? " center_l_on" : "",
354 		(data & 0x20) ? " cross_on" : "",
355 		(data & 0x40) ? " tunnel" : "",
356 		(data & 0x80) ? " part_h_enable" : ""));
357 
358 	set_vh_global_attribute( &mode_set, data );
359 }
360 
WRITE_HANDLER(decocass_color_center_bot_w)361 WRITE_HANDLER( decocass_color_center_bot_w )
362 {
363 	if (data == color_center_bot)
364 		return;
365 	LOG(1,("decocass_color_center_bot_w: $%02x (color:%d, center_bot:%d)\n", data, data&3, data>>4));
366 	/*
367 	 * D7	CL3/4 (swap 2+4)
368 	 * D6	CL1
369 	 * D5	CL2
370 	 * D4	CL4
371 	 * D3	nc
372 	 * D2	nc
373 	 * D1	CLD4
374 	 * D0	CLD3
375 	 */
376 	set_vh_global_attribute( &color_center_bot, data);
377 }
378 
WRITE_HANDLER(decocass_back_h_shift_w)379 WRITE_HANDLER( decocass_back_h_shift_w )
380 {
381 	if (data == back_h_shift)
382 		return;
383 	LOG(1,("decocass_back_h_shift_w: $%02x\n", data));
384 	back_h_shift = data;
385 }
386 
WRITE_HANDLER(decocass_back_vl_shift_w)387 WRITE_HANDLER( decocass_back_vl_shift_w )
388 {
389 	if (data == back_vl_shift)
390 		return;
391 	LOG(1,("decocass_back_vl_shift_w: $%02x\n", data));
392 	back_vl_shift = data;
393 }
394 
WRITE_HANDLER(decocass_back_vr_shift_w)395 WRITE_HANDLER( decocass_back_vr_shift_w )
396 {
397 	if (data == back_vr_shift)
398 		return;
399 	LOG(1,("decocass_back_vr_shift_w: $%02x\n", data));
400 	back_vr_shift = data;
401 }
402 
WRITE_HANDLER(decocass_part_h_shift_w)403 WRITE_HANDLER( decocass_part_h_shift_w )
404 {
405 	if (data == part_v_shift )
406 		return;
407 	LOG(1,("decocass_part_h_shift_w: $%02x\n", data));
408 	part_h_shift = data;
409 }
410 
WRITE_HANDLER(decocass_part_v_shift_w)411 WRITE_HANDLER( decocass_part_v_shift_w )
412 {
413 	if (data == part_v_shift )
414 		return;
415 	LOG(1,("decocass_part_v_shift_w: $%02x\n", data));
416 	part_v_shift = data;
417 }
418 
WRITE_HANDLER(decocass_center_h_shift_space_w)419 WRITE_HANDLER( decocass_center_h_shift_space_w )
420 {
421 	if (data == center_h_shift_space)
422 		return;
423 	LOG(1,("decocass_center_h_shift_space_w: $%02x\n", data));
424 	center_h_shift_space = data;
425 }
426 
WRITE_HANDLER(decocass_center_v_shift_w)427 WRITE_HANDLER( decocass_center_v_shift_w )
428 {
429 	LOG(1,("decocass_center_v_shift_w: $%02x\n", data));
430 	center_v_shift = data;
431 }
432 
433 /********************************************
434 	memory handlers
435  ********************************************/
436 
draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int color,int sprite_y_adjust,int sprite_y_adjust_flip_screen,unsigned char * sprite_ram,int interleave)437 static void draw_sprites(struct mame_bitmap *bitmap, const struct rectangle *cliprect, int color,
438 						int sprite_y_adjust, int sprite_y_adjust_flip_screen,
439 						unsigned char *sprite_ram, int interleave)
440 {
441 	int i,offs;
442 
443 	/* Draw the sprites */
444 	for (i = 0, offs = 0;i < 8; i++, offs += 4*interleave)
445 	{
446 		int sx,sy,flipx,flipy;
447 
448 		if (!(sprite_ram[offs + 0] & 0x01))
449 			continue;
450 
451 		sx = 240 - sprite_ram[offs + 3*interleave];
452 		sy = 240 - sprite_ram[offs + 2*interleave];
453 
454 		flipx = sprite_ram[offs + 0] & 0x04;
455 		flipy = sprite_ram[offs + 0] & 0x02;
456 
457 		if (flip_screen)
458 		{
459 			sx = 240 - sx;
460 			sy = 240 - sy + sprite_y_adjust_flip_screen;
461 
462 			flipx = !flipx;
463 			flipy = !flipy;
464 		}
465 
466 		sy -= sprite_y_adjust;
467 
468 		drawgfx(bitmap,Machine->gfx[1],
469 				sprite_ram[offs + interleave],
470 				color,
471 				flipx,flipy,
472 				sx,sy,
473 				cliprect, TRANSPARENCY_PEN, 0);
474 
475 		sy += (flip_screen ? -256 : 256);
476 
477 		/* Wrap around*/
478 		drawgfx(bitmap,Machine->gfx[1],
479 				sprite_ram[offs + interleave],
480 				color,
481 				flipx,flipy,
482 				sx,sy,
483 				cliprect, TRANSPARENCY_PEN, 0);
484 	}
485 }
486 
487 
draw_missiles(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int missile_y_adjust,int missile_y_adjust_flip_screen,unsigned char * missile_ram,int interleave)488 static void draw_missiles(struct mame_bitmap *bitmap, const struct rectangle *cliprect,
489 						int missile_y_adjust, int missile_y_adjust_flip_screen,
490 						unsigned char *missile_ram, int interleave)
491 {
492 	int i,offs;
493 
494 	/* Draw the missiles (16 of them) seemingly with alternating colors
495 	 * from the E302 latch (color_missiles) */
496 	for (i = 0, offs = 0; i < 8; i++, offs += 4*interleave)
497 	{
498 		int sx,sy;
499 
500 		sy = 255 - missile_ram[offs + 0*interleave];
501 		sx = 255 - missile_ram[offs + 2*interleave];
502 		if (flip_screen)
503 		{
504 			sx = 240 - sx;
505 			sy = 240 - sy + missile_y_adjust_flip_screen;
506 		}
507 		sy -= missile_y_adjust;
508 		drawgfx(bitmap,Machine->gfx[4],
509 				0,32 + ((color_missiles >> 4) & 7), 0,0, sx,sy,
510 				cliprect, TRANSPARENCY_PEN, 0);
511 
512 		sy = 255 - missile_ram[offs + 1*interleave];
513 		sx = 255 - missile_ram[offs + 3*interleave];
514 		if (flip_screen)
515 		{
516 			sx = 240 - sx;
517 			sy = 240 - sy + missile_y_adjust_flip_screen;
518 		}
519 		sy -= missile_y_adjust;
520 		drawgfx(bitmap,Machine->gfx[4],
521 				0,32 + (color_missiles & 7), 0,0, sx,sy,
522 				cliprect, TRANSPARENCY_PEN, 0);
523 	}
524 }
525 
526 
decode_modified(unsigned char * sprite_ram,int interleave)527 static void decode_modified(unsigned char *sprite_ram, int interleave)
528 {
529 	int i,offs;
530 
531 	/* decode dirty characters */
532 	for (offs = decocass_fgvideoram_size - 1;offs >= 0;offs--)
533 	{
534 		int code;
535 
536 		code = decocass_fgvideoram[offs] + 256 * (decocass_colorram[offs] & 3);
537 
538 		switch (char_dirty[code])
539 		{
540 		case 1:
541 			decodechar(Machine->gfx[0],code,decocass_charram,Machine->drv->gfxdecodeinfo[0].gfxlayout);
542 			char_dirty[code] = 2;
543 			/* fall through */
544 		case 2:
545 			tilemap_mark_tile_dirty(fg_tilemap, offs);
546 			break;
547 		default:
548 			break;
549 		}
550 	}
551 
552 	for (i = 0; i < 1024; i++)
553 	{
554 		if (char_dirty[i] == 2)
555 			char_dirty[i] = 0;
556 	}
557 
558 	/* decode dirty sprites */
559 	for (i = 0, offs = 0;i < 8; i++, offs += 4*interleave)
560 	{
561 		int code;
562 
563 		code  = sprite_ram[offs + interleave];
564 		if (sprite_dirty[code])
565 		{
566 			sprite_dirty[code] = 0;
567 
568 			decodechar(Machine->gfx[1],code,decocass_charram,Machine->drv->gfxdecodeinfo[1].gfxlayout);
569 		}
570 	}
571 
572 	/* decode dirty tiles */
573 	for (offs = 0; offs < decocass_bgvideoram_size; offs++)
574 	{
575 		int code = (decocass_tileram[offs] >> 4) & 15;
576 
577 		if (tile_dirty[code])
578 		{
579 			tile_dirty[code] = 0;
580 
581 			decodechar(Machine->gfx[2],code,decocass_tileram,Machine->drv->gfxdecodeinfo[2].gfxlayout);
582 
583 			/* mark all visible tiles dirty */
584 			for (i = offs; i < decocass_bgvideoram_size; i++)
585 				if (code == ((decocass_tileram[i] >> 4) & 15))
586 					mark_bg_tile_dirty(i);
587 		}
588 	}
589 
590 	/* decode object if it is dirty */
591 	if (object_dirty)
592 	{
593 		decodechar(Machine->gfx[3], 0, decocass_objectram, Machine->drv->gfxdecodeinfo[3].gfxlayout);
594 		decodechar(Machine->gfx[3], 1, decocass_objectram, Machine->drv->gfxdecodeinfo[3].gfxlayout);
595 		object_dirty = 0;
596 	}
597 }
598 
VIDEO_START(decocass)599 VIDEO_START( decocass )
600 {
601 	if (NULL == (sprite_dirty = auto_malloc(256)) ||
602 		NULL == (char_dirty = auto_malloc(1024)) ||
603 		NULL == (tile_dirty = auto_malloc(16)))
604 		return 1;
605 
606 	bg_tilemap_l = tilemap_create( get_bg_l_tile_info, bgvideoram_scan_cols, TILEMAP_TRANSPARENT, 16, 16, 32, 32 );
607 	bg_tilemap_r = tilemap_create( get_bg_r_tile_info, bgvideoram_scan_cols, TILEMAP_TRANSPARENT, 16, 16, 32, 32 );
608 	fg_tilemap = tilemap_create( get_fg_tile_info, fgvideoram_scan_cols, TILEMAP_TRANSPARENT,  8,  8, 32, 32 );
609 
610 	if (!bg_tilemap_l || !bg_tilemap_r || !fg_tilemap)
611 		return 1;
612 
613 	tilemap_set_transparent_pen( bg_tilemap_l, 0 );
614 	tilemap_set_transparent_pen( bg_tilemap_r, 0 );
615 	tilemap_set_transparent_pen( fg_tilemap, 0 );
616 
617 	bg_tilemap_l_clip = Machine->visible_area;
618 	bg_tilemap_l_clip.max_y = Machine->drv->screen_height / 2;
619 
620 	bg_tilemap_r_clip = Machine->visible_area;
621 	bg_tilemap_r_clip.min_y = Machine->drv->screen_height / 2;
622 
623 	/* background videroam bits D0-D3 are shared with the tileram */
624 	decocass_bgvideoram = decocass_tileram;
625 	decocass_bgvideoram_size = 0x0400;	/* d000-d3ff */
626 
627 	state_save_register_int("decocass", 0, "watchdog_count", &watchdog_count);
628 	state_save_register_int("decocass", 0, "watchdog_flip", &watchdog_flip);
629 	state_save_register_int("decocass", 0, "color_missiles", &color_missiles);
630 	state_save_register_int("decocass", 0, "color_center_bot", &color_center_bot);
631 	state_save_register_int("decocass", 0, "mode_set", &mode_set);
632 	state_save_register_int("decocass", 0, "back_h_shift", &back_h_shift);
633 	state_save_register_int("decocass", 0, "back_vl_shift", &back_vl_shift);
634 	state_save_register_int("decocass", 0, "back_vr_shift", &back_vr_shift);
635 	state_save_register_int("decocass", 0, "part_h_shift", &part_h_shift);
636 	state_save_register_int("decocass", 0, "part_v_shift", &part_v_shift);
637 	state_save_register_int("decocass", 0, "center_h_shift_space", &center_h_shift_space);
638 	state_save_register_int("decocass", 0, "center_v_shift", &center_v_shift);
639 
640 	return 0;
641 }
642 
VIDEO_UPDATE(decocass)643 VIDEO_UPDATE( decocass )
644 {
645 	int scrollx, scrolly_l, scrolly_r;
646 	struct rectangle clip;
647 
648 	if (0xc0 != (input_port_2_r(0) & 0xc0))  /* coin slots assert an NMI */
649 		cpu_set_nmi_line(0, ASSERT_LINE);
650 
651 	if (0 == (watchdog_flip & 0x04))
652 		watchdog_reset_w (0,0);
653 	else if (watchdog_count-- > 0)
654 		watchdog_reset_w (0,0);
655 
656 #if TAPE_UI_DISPLAY
657 	if (tape_timer)
658 	{
659 		double tape_time = tape_time0 + tape_dir * timer_timeelapsed(tape_timer);
660 		if (tape_time < 0.0)
661 			tape_time = 0.0;
662 		else if (tape_time > 999.9)
663 			tape_time = 999.9;
664 		usrintf_showmessage("%c%c [%05.1fs] %c%c",
665 			(tape_dir < 0 && tape_speed) ? '<' : ' ',
666 			(tape_dir < 0) ? '<' : ' ',
667 			tape_time,
668 			(tape_dir > 0) ? '>' : ' ',
669 			(tape_dir > 0 && tape_speed) ? '>' : ' ');
670 	}
671 #endif
672 #ifdef MAME_DEBUG
673 	{
674 		static int showmsg;
675 		if (code_pressed_memory(KEYCODE_I))
676 			showmsg ^= 1;
677 		if (showmsg)
678 			usrintf_showmessage_secs(1, "mode:$%02x cm:$%02x ccb:$%02x h:$%02x vl:$%02x vr:$%02x ph:$%02x pv:$%02x ch:$%02x cv:$%02x",
679 				mode_set,
680 				color_missiles,
681 				color_center_bot,
682 				back_h_shift,
683 				back_vl_shift,
684 				back_vr_shift,
685 				part_h_shift,
686 				part_v_shift,
687 				center_h_shift_space,
688 				center_v_shift);
689 	}
690 #endif
691 
692 	fillbitmap( bitmap, Machine->pens[0], cliprect );
693 
694 	decode_modified( decocass_fgvideoram, 0x20 );
695 
696 	scrolly_l = back_vl_shift;
697 	scrolly_r = 256 - back_vr_shift;
698 
699 	scrollx = 256 - back_h_shift;
700 	if (0 == (mode_set & 0x02))
701 		scrollx += 256;
702 
703 #if 0
704 /* this is wrong */
705 	if (0 != back_h_shift && 0 == ((mode_set ^ (mode_set >> 1)) & 1))
706 		scrollx += 256;
707 #endif
708 
709 	if (0 == (mode_set & 0x04))
710 		scrolly_r += 256;
711 	else
712 		scrolly_l += 256;
713 
714 	tilemap_set_scrollx( bg_tilemap_l, 0, scrollx );
715 	tilemap_set_scrolly( bg_tilemap_l, 0, scrolly_l );
716 
717 	tilemap_set_scrollx( bg_tilemap_r, 0, scrollx );
718 	tilemap_set_scrolly( bg_tilemap_r, 0, scrolly_r );
719 
720 	if (mode_set & 0x20)
721 	{
722 		if (mode_set & 0x08)	/* bkg_ena on ? */
723 		{
724 			clip = bg_tilemap_l_clip;
725 			sect_rect(&clip,cliprect);
726 			tilemap_draw(bitmap,&clip, bg_tilemap_l, 0, 0);
727 
728 			clip = bg_tilemap_r_clip;
729 			sect_rect(&clip,cliprect);
730 			tilemap_draw(bitmap,&clip, bg_tilemap_r, 0, 0);
731 		}
732 		draw_object(bitmap,cliprect);
733 		draw_center(bitmap,cliprect);
734 	}
735 	else
736 	{
737 		draw_object(bitmap,cliprect);
738 		draw_center(bitmap,cliprect);
739 		if (mode_set & 0x08)	/* bkg_ena on ? */
740 		{
741 			clip = bg_tilemap_l_clip;
742 			sect_rect(&clip,cliprect);
743 			tilemap_draw(bitmap,&clip, bg_tilemap_l, 0, 0);
744 
745 			clip = bg_tilemap_r_clip;
746 			sect_rect(&clip,cliprect);
747 			tilemap_draw(bitmap,&clip, bg_tilemap_r, 0, 0);
748 		}
749 	}
750 	tilemap_draw(bitmap,cliprect, fg_tilemap, 0, 0);
751 	draw_sprites(bitmap,cliprect, (color_center_bot >> 1) & 1, 0, 0, decocass_fgvideoram, 0x20);
752 	draw_missiles(bitmap,cliprect, 1, 0, decocass_colorram, 0x20);
753 }
754