1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 ***************************************************************************/
8 
9 #include "driver.h"
10 #include "vidhrdw/generic.h"
11 
12 extern int ddrible_int_enable_0;
13 extern int ddrible_int_enable_1;
14 
15 unsigned char *ddrible_fg_videoram;
16 unsigned char *ddrible_bg_videoram;
17 unsigned char *ddrible_spriteram_1;
18 unsigned char *ddrible_spriteram_2;
19 
20 static int ddribble_vregs[2][5];
21 static int charbank[2];
22 
23 static struct tilemap *fg_tilemap,*bg_tilemap;
24 
25 
PALETTE_INIT(ddrible)26 PALETTE_INIT( ddrible )
27 {
28 	int i;
29 	#define TOTAL_COLORS(gfxn) (Machine->gfx[gfxn]->total_colors * Machine->gfx[gfxn]->color_granularity)
30 	#define COLOR(gfxn,offs) (colortable[Machine->drv->gfxdecodeinfo[gfxn].color_codes_start + offs])
31 
32 
33 	/* build the lookup table for sprites. Palette is dynamic. */
34 	for (i = 0;i < TOTAL_COLORS(3);i++)
35 		COLOR(3,i) = (*(color_prom++) & 0x0f);
36 }
37 
WRITE_HANDLER(K005885_0_w)38 WRITE_HANDLER( K005885_0_w )
39 {
40 	switch (offset){
41 		case 0x03:	/* char bank selection for set 1 */
42 			if ((data & 0x03) != charbank[0])
43 			{
44 				charbank[0] = data & 0x03;
45 				tilemap_mark_all_tiles_dirty( fg_tilemap );
46 			}
47 			break;
48 		case 0x04:	/* IRQ control, flipscreen */
49 			ddrible_int_enable_0 = data & 0x02;
50 			break;
51 	}
52 	ddribble_vregs[0][offset] = data;
53 }
54 
WRITE_HANDLER(K005885_1_w)55 WRITE_HANDLER( K005885_1_w )
56 {
57 	switch (offset){
58 		case 0x03:	/* char bank selection for set 2 */
59 			if ((data & 0x03) != charbank[1])
60 			{
61 				charbank[1] = data & 0x03;
62 				tilemap_mark_all_tiles_dirty( bg_tilemap );
63 			}
64 			break;
65 		case 0x04:	/* IRQ control, flipscreen */
66 			ddrible_int_enable_1 = data & 0x02;
67 			break;
68 	}
69 	ddribble_vregs[1][offset] = data;
70 }
71 
72 /***************************************************************************
73 
74 	Callbacks for the TileMap code
75 
76 ***************************************************************************/
77 
tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)78 static UINT32 tilemap_scan(UINT32 col,UINT32 row,UINT32 num_cols,UINT32 num_rows)
79 {
80 	/* logical (col,row) -> memory offset */
81 	return (col & 0x1f) + ((row & 0x1f) << 5) + ((col & 0x20) << 6);	/* skip 0x400 */
82 }
83 
get_fg_tile_info(int tile_index)84 static void get_fg_tile_info(int tile_index)
85 {
86 	unsigned char attr = ddrible_fg_videoram[tile_index];
87 	int num = ddrible_fg_videoram[tile_index + 0x400] +
88 			((attr & 0xc0) << 2) + ((attr & 0x20) << 5) + ((charbank[0] & 2) << 10);
89 	SET_TILE_INFO(
90 			0,
91 			num,
92 			0,
93 			TILE_FLIPYX((attr & 0x30) >> 4))
94 }
95 
get_bg_tile_info(int tile_index)96 static void get_bg_tile_info(int tile_index)
97 {
98 	unsigned char attr = ddrible_bg_videoram[tile_index];
99 	int num = ddrible_bg_videoram[tile_index + 0x400] +
100 			((attr & 0xc0) << 2) + ((attr & 0x20) << 5) + (charbank[1] << 11);
101 	SET_TILE_INFO(
102 			1,
103 			num,
104 			0,
105 			TILE_FLIPYX((attr & 0x30) >> 4))
106 }
107 
108 /***************************************************************************
109 
110 	Start the video hardware emulation.
111 
112 ***************************************************************************/
113 
VIDEO_START(ddrible)114 VIDEO_START( ddrible )
115 {
116 	fg_tilemap = tilemap_create(get_fg_tile_info,tilemap_scan,TILEMAP_TRANSPARENT,8,8,64,32);
117 	bg_tilemap = tilemap_create(get_bg_tile_info,tilemap_scan,TILEMAP_OPAQUE,     8,8,64,32);
118 
119 	if (!fg_tilemap || !bg_tilemap)
120 		return 1;
121 
122 	tilemap_set_transparent_pen(fg_tilemap,0);
123 
124 	return 0;
125 }
126 
127 /***************************************************************************
128 
129 	Memory handlers
130 
131 ***************************************************************************/
132 
WRITE_HANDLER(ddrible_fg_videoram_w)133 WRITE_HANDLER( ddrible_fg_videoram_w )
134 {
135 	if (ddrible_fg_videoram[offset] != data)
136 	{
137 		ddrible_fg_videoram[offset] = data;
138 		tilemap_mark_tile_dirty(fg_tilemap,offset & 0xbff);
139 	}
140 }
141 
WRITE_HANDLER(ddrible_bg_videoram_w)142 WRITE_HANDLER( ddrible_bg_videoram_w )
143 {
144 	if (ddrible_bg_videoram[offset] != data)
145 	{
146 		ddrible_bg_videoram[offset] = data;
147 		tilemap_mark_tile_dirty(bg_tilemap,offset & 0xbff);
148 	}
149 }
150 
151 /***************************************************************************
152 
153 	Double Dribble sprites
154 
155 Each sprite has 5 bytes:
156 byte #0:	sprite number
157 byte #1:
158 	bits 0..2:	sprite bank #
159 	bit 3:		not used?
160 	bits 4..7:	sprite color
161 byte #2:	y position
162 byte #3:	x position
163 byte #4:	attributes
164 	bit 0:		x position (high bit)
165 	bit 1:		???
166 	bits 2..4:	sprite size
167 	bit 5:		flip x
168 	bit 6:		flip y
169 	bit 7:		unused?
170 
171 ***************************************************************************/
172 
ddribble_draw_sprites(struct mame_bitmap * bitmap,const struct rectangle * cliprect,unsigned char * source,int lenght,int gfxset,int flipscreen)173 static void ddribble_draw_sprites( struct mame_bitmap *bitmap, const struct rectangle *cliprect, unsigned char* source, int lenght, int gfxset, int flipscreen )
174 {
175 	struct GfxElement *gfx = Machine->gfx[gfxset];
176 	const unsigned char *finish = source + lenght;
177 
178 	while( source < finish )
179 	{
180 		int number = source[0] | ((source[1] & 0x07) << 8);	/* sprite number */
181 		int attr = source[4];								/* attributes */
182 		int sx = source[3] | ((attr & 0x01) << 8);			/* vertical position */
183 		int sy = source[2];									/* horizontal position */
184 		int flipx = attr & 0x20;							/* flip x */
185 		int flipy = attr & 0x40;							/* flip y */
186 		int color = (source[1] & 0xf0) >> 4;				/* color */
187 		int width,height;
188 
189 		if (flipscreen){
190 				flipx = !flipx;
191 				flipy = !flipy;
192 				sx = 240 - sx;
193 				sy = 240 - sy;
194 
195 				if ((attr & 0x1c) == 0x10){	/* ???. needed for some sprites in flipped mode */
196 					sx -= 0x10;
197 					sy -= 0x10;
198 				}
199 		}
200 
201 		switch (attr & 0x1c){
202 			case 0x10:	/* 32x32 */
203 				width = height = 2; number &= (~3); break;
204 			case 0x08:	/* 16x32 */
205 				width = 1; height = 2; number &= (~2); break;
206 			case 0x04:	/* 32x16 */
207 				width = 2; height = 1; number &= (~1); break;
208 			/* the hardware allow more sprite sizes, but ddribble doesn't use them */
209 			default:	/* 16x16 */
210 				width = height = 1; break;
211 		}
212 
213 		{
214 			static int x_offset[2] = { 0x00, 0x01 };
215 			static int y_offset[2] = { 0x00, 0x02 };
216 			int x,y, ex, ey;
217 
218 			for( y=0; y < height; y++ ){
219 				for( x=0; x < width; x++ ){
220 					ex = flipx ? (width-1-x) : x;
221 					ey = flipy ? (height-1-y) : y;
222 
223 					drawgfx(bitmap,gfx,
224 						(number)+x_offset[ex]+y_offset[ey],
225 						color,
226 						flipx, flipy,
227 						sx+x*16,sy+y*16,
228 						cliprect,
229 						TRANSPARENCY_PEN, 0);
230 				}
231 			}
232 		}
233 		source += 5;
234 	}
235 }
236 
237 /***************************************************************************
238 
239 	Display Refresh
240 
241 ***************************************************************************/
242 
VIDEO_UPDATE(ddrible)243 VIDEO_UPDATE( ddrible )
244 {
245 	tilemap_set_flip(fg_tilemap, (ddribble_vregs[0][4] & 0x08) ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
246 	tilemap_set_flip(bg_tilemap, (ddribble_vregs[1][4] & 0x08) ? (TILEMAP_FLIPY | TILEMAP_FLIPX) : 0);
247 
248 	/* set scroll registers */
249 	tilemap_set_scrollx(fg_tilemap,0,ddribble_vregs[0][1] | ((ddribble_vregs[0][2] & 0x01) << 8));
250 	tilemap_set_scrollx(bg_tilemap,0,ddribble_vregs[1][1] | ((ddribble_vregs[1][2] & 0x01) << 8));
251 	tilemap_set_scrolly(fg_tilemap,0,ddribble_vregs[0][0]);
252 	tilemap_set_scrolly(bg_tilemap,0,ddribble_vregs[1][0]);
253 
254 	tilemap_draw(bitmap,cliprect,bg_tilemap,0,0);
255 	ddribble_draw_sprites(bitmap,cliprect,ddrible_spriteram_1,0x07d,2,ddribble_vregs[0][4] & 0x08);
256 	ddribble_draw_sprites(bitmap,cliprect,ddrible_spriteram_2,0x140,3,ddribble_vregs[1][4] & 0x08);
257 	tilemap_draw(bitmap,cliprect,fg_tilemap,0,0);
258 }
259