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