1 /***************************************************************************
2 
3   vidhrdw/balsente.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 #include "balsente.h"
12 
13 
14 /*************************************
15  *
16  *	Statics
17  *
18  *************************************/
19 
20 static UINT8 *local_videoram;
21 static UINT8 *scanline_dirty;
22 static UINT8 *scanline_palette;
23 static UINT8 *sprite_data;
24 static UINT32 sprite_mask;
25 
26 static UINT8 last_scanline_palette;
27 static UINT8 screen_refresh_counter;
28 static UINT8 palettebank_vis;
29 
30 
31 
32 /*************************************
33  *
34  *	Video system start
35  *
36  *************************************/
37 
VIDEO_START(balsente)38 VIDEO_START( balsente )
39 {
40 	/* reset the system */
41 	palettebank_vis = 0;
42 
43 	/* allocate a bitmap */
44 	tmpbitmap = auto_bitmap_alloc(Machine->drv->screen_width, Machine->drv->screen_height);
45 	if (!tmpbitmap)
46 		return 1;
47 
48 	/* allocate a local copy of video RAM */
49 	local_videoram = auto_malloc(256 * 256);
50 	if (!local_videoram)
51 		return 1;
52 
53 	/* allocate a scanline dirty array */
54 	scanline_dirty = auto_malloc(256);
55 	if (!scanline_dirty)
56 		return 1;
57 
58 	/* allocate a scanline palette array */
59 	scanline_palette = auto_malloc(256);
60 	if (!scanline_palette)
61 		return 1;
62 
63 	/* mark everything dirty to start */
64 	memset(scanline_dirty, 1, 256);
65 
66 	/* reset the scanline palette */
67 	memset(scanline_palette, 0, 256);
68 	last_scanline_palette = 0;
69 
70 	/* determine sprite size */
71 	sprite_data = memory_region(REGION_GFX1);
72 	sprite_mask = memory_region_length(REGION_GFX1) - 1;
73 
74 	return 0;
75 }
76 
77 
78 
79 /*************************************
80  *
81  *	Video RAM write
82  *
83  *************************************/
84 
WRITE_HANDLER(balsente_videoram_w)85 WRITE_HANDLER( balsente_videoram_w )
86 {
87 	videoram[offset] = data;
88 
89 	/* expand the two pixel values into two bytes */
90 	local_videoram[offset * 2 + 0] = data >> 4;
91 	local_videoram[offset * 2 + 1] = data & 15;
92 
93 	/* mark the scanline dirty */
94 	scanline_dirty[offset / 128] = 1;
95 }
96 
97 
98 
99 /*************************************
100  *
101  *	Palette banking
102  *
103  *************************************/
104 
update_palette(void)105 static void update_palette(void)
106 {
107 	int scanline = cpu_getscanline(), i;
108 	if (scanline > 255) scanline = 0;
109 
110 	/* special case: the scanline is the same as last time, but a screen refresh has occurred */
111 	if (scanline == last_scanline_palette && screen_refresh_counter)
112 	{
113 		for (i = 0; i < 256; i++)
114 		{
115 			/* mark the scanline dirty if it was a different palette */
116 			if (scanline_palette[i] != palettebank_vis)
117 				scanline_dirty[i] = 1;
118 			scanline_palette[i] = palettebank_vis;
119 		}
120 	}
121 
122 	/* fill in the scanlines up till now */
123 	else
124 	{
125 		for (i = last_scanline_palette; i != scanline; i = (i + 1) & 255)
126 		{
127 			/* mark the scanline dirty if it was a different palette */
128 			if (scanline_palette[i] != palettebank_vis)
129 				scanline_dirty[i] = 1;
130 			scanline_palette[i] = palettebank_vis;
131 		}
132 
133 		/* remember where we left off */
134 		last_scanline_palette = scanline;
135 	}
136 
137 	/* reset the screen refresh counter */
138 	screen_refresh_counter = 0;
139 }
140 
141 
WRITE_HANDLER(balsente_palette_select_w)142 WRITE_HANDLER( balsente_palette_select_w )
143 {
144 	/* only update if changed */
145 	if (palettebank_vis != (data & 3))
146 	{
147 		/* update the scanline palette */
148 		update_palette();
149 		palettebank_vis = data & 3;
150 	}
151 
152 	logerror("balsente_palette_select_w(%d) scanline=%d\n", data & 3, cpu_getscanline());
153 }
154 
155 
156 
157 /*************************************
158  *
159  *	Palette RAM write
160  *
161  *************************************/
162 
WRITE_HANDLER(balsente_paletteram_w)163 WRITE_HANDLER( balsente_paletteram_w )
164 {
165 	int r, g, b;
166 
167 	paletteram[offset] = data & 0x0f;
168 
169 	r = paletteram[(offset & ~3) + 0];
170 	g = paletteram[(offset & ~3) + 1];
171 	b = paletteram[(offset & ~3) + 2];
172 	palette_set_color(offset / 4, (r << 4) | r, (g << 4) | g, (b << 4) | b);
173 }
174 
175 
176 
177 /*************************************
178  *
179  *	Sprite drawing
180  *
181  *************************************/
182 
draw_one_sprite(struct mame_bitmap * bitmap,const struct rectangle * cliprect,UINT8 * sprite)183 static void draw_one_sprite(struct mame_bitmap *bitmap, const struct rectangle *cliprect, UINT8 *sprite)
184 {
185 	struct rectangle finalclip = *cliprect;
186 	int flags = sprite[0];
187 	int image = sprite[1] | ((flags & 7) << 8);
188 	int ypos = sprite[2] + 17;
189 	int xpos = sprite[3];
190 	UINT8 *src;
191 	int x, y;
192 
193 	if (finalclip.min_y < 16)
194 		finalclip.min_y = 16;
195 	if (finalclip.max_y > 240)
196 		finalclip.max_y = 240;
197 
198 	/* get a pointer to the source image */
199 	src = &sprite_data[(64 * image) & sprite_mask];
200 	if (flags & 0x80) src += 4 * 15;
201 
202 	/* loop over y */
203 	for (y = 0; y < 16; y++, ypos = (ypos + 1) & 255)
204 	{
205 		if (ypos >= finalclip.min_y && ypos <= finalclip.max_y)
206 		{
207 			UINT32 *pens = &Machine->pens[scanline_palette[y] * 256];
208 			UINT8 *old = &local_videoram[ypos * 256 + xpos];
209 			int currx = xpos;
210 
211 			/* standard case */
212 			if (!(flags & 0x40))
213 			{
214 				/* loop over x */
215 				for (x = 0; x < 4; x++, old += 2)
216 				{
217 					int ipixel = *src++;
218 					int left = ipixel & 0xf0;
219 					int right = (ipixel << 4) & 0xf0;
220 
221 					/* left pixel, combine with the background */
222 					if (left && currx >= finalclip.min_x && currx <= finalclip.max_x)
223 						plot_pixel(bitmap, currx, ypos, pens[left | old[0]]);
224 					currx++;
225 
226 					/* right pixel, combine with the background */
227 					if (right && currx >= finalclip.min_x && currx <= finalclip.max_x)
228 						plot_pixel(bitmap, currx, ypos, pens[right | old[1]]);
229 					currx++;
230 				}
231 			}
232 
233 			/* hflip case */
234 			else
235 			{
236 				src += 4;
237 
238 				/* loop over x */
239 				for (x = 0; x < 4; x++, old += 2)
240 				{
241 					int ipixel = *--src;
242 					int left = (ipixel << 4) & 0xf0;
243 					int right = ipixel & 0xf0;
244 
245 					/* left pixel, combine with the background */
246 					if (left && currx >= finalclip.min_x && currx <= finalclip.max_x)
247 						plot_pixel(bitmap, currx, ypos, pens[left | old[0]]);
248 					currx++;
249 
250 					/* right pixel, combine with the background */
251 					if (right && currx >= finalclip.min_x && currx <= finalclip.max_x)
252 						plot_pixel(bitmap, currx, ypos, pens[right | old[1]]);
253 					currx++;
254 				}
255 				src += 4;
256 			}
257 		}
258 		else
259 			src += 4;
260 		if (flags & 0x80) src -= 2 * 4;
261 	}
262 }
263 
264 
265 
266 /*************************************
267  *
268  *	Main screen refresh
269  *
270  *************************************/
271 
VIDEO_UPDATE(balsente)272 VIDEO_UPDATE( balsente )
273 {
274 	int update_all = get_vh_global_attribute_changed();
275 	int y, i;
276 
277 	/* update the remaining scanlines */
278 	screen_refresh_counter++;
279 	update_palette();
280 
281 	/* make sure color 1024 is white for our crosshair */
282 	palette_set_color(1024, 0xff, 0xff, 0xff);
283 
284 	/* draw any dirty scanlines from the VRAM directly */
285 	for (y = 0; y < 240; y++)
286 		if (scanline_dirty[y] || update_all)
287 		{
288 			pen_t *pens = &Machine->pens[scanline_palette[y] * 256];
289 			draw_scanline8(tmpbitmap, 0, y, 256, &local_videoram[y * 256], pens, -1);
290 			scanline_dirty[y] = 0;
291 		}
292 	copybitmap(bitmap,tmpbitmap,0,0,0,0,cliprect,TRANSPARENCY_NONE,0);
293 
294 	/* draw the sprite images */
295 	for (i = 0; i < 40; i++)
296 		draw_one_sprite(bitmap, cliprect, &spriteram[(0xe0 + i * 4) & 0xff]);
297 
298 	/* draw a crosshair */
299 	if (balsente_shooter)
300 	{
301 		int beamx = balsente_shooter_x;
302 		int beamy = balsente_shooter_y - 10;
303 
304 		draw_crosshair(bitmap,beamx,beamy,cliprect);
305 	}
306 }
307