1 /***************************************************************************
2 
3 First version of the Dynax blitter.
4 
5 Can handle up to 8 256x256 bitmaps; in the games supported, every pair of
6 bitmaps is interleaved horizontally to form 4 higher res 512x256 layer.
7 
8 The blitter reads compressed data from ROM and copies it to the bitmap RAM.
9 
10 ***************************************************************************/
11 
12 #include "driver.h"
13 
14 
15 static UINT8 *pixmap[8];
16 static int palbank;
17 static int total_pixmaps;
18 
19 
common_vh_start(int num_pixmaps)20 static int common_vh_start(int num_pixmaps)
21 {
22 	int i;
23 
24 	total_pixmaps = num_pixmaps;
25 
26 	for (i = 0;i < 8;i++)
27 	{
28 		if (i < total_pixmaps)
29 		{
30 			if (!(pixmap[i] = auto_malloc(256*256))) return 1;
31 		}
32 		else
33 			pixmap[i] = NULL;
34 	}
35 
36 	return 0;
37 }
38 
VIDEO_START(hnayayoi)39 VIDEO_START( hnayayoi )
40 {
41 	return common_vh_start(4);	/* 4 bitmaps -> 2 layers */
42 }
43 
VIDEO_START(untoucha)44 VIDEO_START( untoucha )
45 {
46 	return common_vh_start(8);	/* 8 bitmaps -> 4 layers */
47 }
48 
49 
50 
51 /***************************************************************************
52 
53 Blitter support
54 
55 three parameters:
56 blit_layer: mask of the bitmaps to write to (can write to multiple bitmaps
57             at the same time)
58 blit_dest:  position in the destination bitmap where to start blitting
59 blit_src:   address of source data in the gfx ROM
60 
61 additional parameters specify the palette base, but this is handled while rendering
62 the screen, not during blitting (games change the palette base without redrawing
63 the screen).
64 
65 It is not known whether the palette base control registers are part of the blitter
66 hardware or latched somewhere else. Since they are mapped in memory immediately
67 before the bitter parameters, they probably are part of the blitter, but I'm
68 handling them separately anyway.
69 
70 
71 The format of the blitter data stored in ROM is very simple:
72 
73 7654 ----	Pen to draw with
74 ---- 3210	Command
75 
76 Commands:
77 
78 0		Stop
79 1-b		Draw 1-b pixels along X.
80 c		Followed by 1 byte (N): draw N pixels along X.
81 d		Followed by 2 bytes (X,N): move on the line to pixel (start+X), draw N pixels
82 		along X.
83 e		Followed by 1 byte (N): set blit_layer = N. Used to draw interleaved graphics
84 		with a single blitter run.
85 f		Move to next line.
86 
87 At the end of the blit, blit_src is left pointing to the next data in the gfx ROM.
88 This is used to draw interleaved graphics with two blitter runs without having to set
89 up blit_src for the second call.
90 
91 ***************************************************************************/
92 
93 static UINT8 blit_layer;
94 static UINT16 blit_dest;
95 static UINT32 blit_src;
96 
WRITE_HANDLER(dynax_blitter_rev1_param_w)97 WRITE_HANDLER( dynax_blitter_rev1_param_w )
98 {
99 	switch (offset)
100 	{
101 		case 0: blit_dest = (blit_dest & 0xff00) | (data << 0); break;
102 		case 1: blit_dest = (blit_dest & 0x00ff) | (data << 8); break;
103 		case 2: blit_layer = data; break;
104 		case 3: blit_src = (blit_src & 0xffff00) | (data << 0); break;
105 		case 4: blit_src = (blit_src & 0xff00ff) | (data << 8); break;
106 		case 5: blit_src = (blit_src & 0x00ffff) | (data <<16); break;
107 	}
108 }
109 
copy_pixel(int x,int y,int pen)110 static void copy_pixel(int x,int y,int pen)
111 {
112 	if (x >= 0 && x <= 255 && y >= 0 && y <= 255)
113 	{
114 		int i;
115 
116 		for (i = 0;i < 8;i++)
117 		{
118 			if ((~blit_layer & (1 << i)) && (pixmap[i]))
119 				pixmap[i][256*y+x] = pen;
120 		}
121 	}
122 }
123 
WRITE_HANDLER(dynax_blitter_rev1_start_w)124 WRITE_HANDLER( dynax_blitter_rev1_start_w )
125 {
126 	data8_t *rom = memory_region(REGION_GFX1);
127 	int romlen = memory_region_length(REGION_GFX1);
128 	int sx = blit_dest & 0xff;
129 	int sy = blit_dest >> 8;
130 	int x,y;
131 
132 	x = sx;
133 	y = sy;
134 	while (blit_src < romlen)
135 	{
136 		int cmd = rom[blit_src] & 0x0f;
137 		int pen = rom[blit_src] >> 4;
138 
139 		blit_src++;
140 
141 		switch (cmd)
142 		{
143 			case 0xf:
144 				y++;
145 				x = sx;
146 				break;
147 
148 			case 0xe:
149 				if (blit_src >= romlen)
150 				{
151 					usrintf_showmessage("GFXROM OVER %06x",blit_src);
152 					return;
153 				}
154 				x = sx;
155 				blit_layer = rom[blit_src++];
156 				break;
157 
158 			case 0xd:
159 				if (blit_src >= romlen)
160 				{
161 					usrintf_showmessage("GFXROM OVER %06x",blit_src);
162 					return;
163 				}
164 				x = sx + rom[blit_src++];
165 				/* fall through into next case */
166 
167 			case 0xc:
168 				if (blit_src >= romlen)
169 				{
170 					usrintf_showmessage("GFXROM OVER %06x",blit_src);
171 					return;
172 				}
173 				cmd = rom[blit_src++];
174 				/* fall through into next case */
175 
176 			case 0xb:
177 			case 0xa:
178 			case 0x9:
179 			case 0x8:
180 			case 0x7:
181 			case 0x6:
182 			case 0x5:
183 			case 0x4:
184 			case 0x3:
185 			case 0x2:
186 			case 0x1:
187 				while (cmd--)
188 					copy_pixel(x++,y,pen);
189 				break;
190 
191 			case 0x0:
192 				return;
193 		}
194 	}
195 
196 	usrintf_showmessage("GFXROM OVER %06x",blit_src);
197 }
198 
WRITE_HANDLER(dynax_blitter_rev1_clear_w)199 WRITE_HANDLER( dynax_blitter_rev1_clear_w )
200 {
201 	int pen = data >> 4;
202 	int i;
203 
204 	for (i = 0;i < 8;i++)
205 	{
206 		if ((~blit_layer & (1 << i)) && (pixmap[i]))
207 			memset(pixmap[i] + blit_dest, pen, 0x10000 - blit_dest);
208 	}
209 }
210 
211 
WRITE_HANDLER(hnayayoi_palbank_w)212 WRITE_HANDLER( hnayayoi_palbank_w )
213 {
214 	offset *= 8;
215 	palbank = (palbank & (0xff00 >> offset)) | (data << offset);
216 }
217 
218 
draw_layer_interleaved(struct mame_bitmap * bitmap,const struct rectangle * cliprect,int left_pixmap,int right_pixmap,int palbase,int transp)219 static void draw_layer_interleaved(struct mame_bitmap *bitmap, const struct rectangle *cliprect,
220 		int left_pixmap, int right_pixmap, int palbase, int transp)
221 {
222 	int county,countx,pen,offs;
223 	UINT8 *src1 = pixmap[left_pixmap];
224 	UINT8 *src2 = pixmap[right_pixmap];
225 	UINT16 *dstbase = (UINT16 *)bitmap->base;
226 
227 	palbase *= 16;
228 	offs = 0;
229 
230 	for (county = 255; county >= 0; county--, dstbase += bitmap->rowpixels)
231 	{
232 		UINT16 *dst = dstbase;
233 
234 		if (transp)
235 		{
236 			for (countx = 255; countx >= 0; countx--, dst += 2)
237 			{
238 				pen = *(src1++);
239 				if (pen) *dst     = palbase + pen;
240 				pen = *(src2++);
241 				if (pen) *(dst+1) = palbase + pen;
242 			}
243 		}
244 		else
245 		{
246 			for (countx = 255; countx >= 0; countx--, dst += 2)
247 			{
248 				*dst     = palbase + *(src1++);
249 				*(dst+1) = palbase + *(src2++);
250 			}
251 		}
252 	}
253 }
254 
255 
VIDEO_UPDATE(hnayayoi)256 VIDEO_UPDATE( hnayayoi )
257 {
258 	int col0 = (palbank >>  0) & 0x0f;
259 	int col1 = (palbank >>  4) & 0x0f;
260 	int col2 = (palbank >>  8) & 0x0f;
261 	int col3 = (palbank >> 12) & 0x0f;
262 
263 	if (total_pixmaps == 4)
264 	{
265 		draw_layer_interleaved(bitmap,cliprect,3,2,col1,0);
266 		draw_layer_interleaved(bitmap,cliprect,1,0,col0,1);
267 	}
268 	else	/* total_pixmaps == 8 */
269 	{
270 		draw_layer_interleaved(bitmap,cliprect,7,6,col3,0);
271 		draw_layer_interleaved(bitmap,cliprect,5,4,col2,1);
272 		draw_layer_interleaved(bitmap,cliprect,3,2,col1,1);
273 		draw_layer_interleaved(bitmap,cliprect,1,0,col0,1);
274 	}
275 }
276