1 /***************************************************************************
2 
3   vidhrdw.c
4 
5   Functions to emulate the video hardware of the machine.
6 
7 ***************************************************************************/
8 
9 #define JEDI_PLAYFIELD
10 
11 #include "driver.h"
12 #include "vidhrdw/generic.h"
13 
14 unsigned char *jedi_backgroundram;
15 size_t jedi_backgroundram_size;
16 unsigned char *jedi_PIXIRAM;
17 static unsigned int jedi_vscroll;
18 static unsigned int jedi_hscroll;
19 static unsigned int jedi_alpha_bank;
20 static int video_off,smooth_table;
21 static unsigned char *dirtybuffer2;
22 static struct osd_bitmap *tmpbitmap2,*tmpbitmap3;
23 
24 
25 
26 /* Color RAM format
27    Color RAM is 1024x12
28    RAM address: A0..A3 = Playfield color code
29                 A4..A7 = Motion object color code
30                 A8..A9 = Alphanumeric color code
31    RAM data:
32                 0..2 = Blue
33                 3..5 = Green
34                 6..8 = Blue
35                 9..11 = Intesnsity
36     Output resistor values:
37                bit 0 = 22K
38                bit 1 = 10K
39                bit 2 = 4.7K
40 */
41 
42 
WRITE_HANDLER(jedi_paletteram_w)43 WRITE_HANDLER( jedi_paletteram_w )
44 {
45     int r,g,b;
46 	int bits,intensity;
47     unsigned int color;
48 
49 
50 	paletteram[offset] = data;
51 	color = paletteram[offset & 0x3FF] | (paletteram[offset | 0x400] << 8);
52 	intensity = (color >> 9) & 0x07;
53 	bits = (color >> 6) & 0x07;
54 	r = 5 * bits * intensity;
55 	bits = (color >> 3) & 0x07;
56 	g = 5 * bits * intensity;
57 	bits = (color >> 0) & 0x07;
58 	b = 5 * bits * intensity;
59 
60 	palette_change_color (offset & 0x3ff,r,g,b);
61 }
62 
63 
64 
65 /***************************************************************************
66 
67   Start the video hardware emulation.
68 
69 ***************************************************************************/
jedi_vh_start(void)70 int jedi_vh_start(void)
71 {
72 	if ((dirtybuffer = (unsigned char*)malloc(videoram_size)) == 0)
73 	{
74 		return 1;
75 	}
76 	memset(dirtybuffer,1,videoram_size);
77 
78 	if ((tmpbitmap = bitmap_alloc_depth(Machine->drv->screen_width,Machine->drv->screen_height,8)) == 0)
79 	{
80 		free(dirtybuffer);
81 		return 1;
82 	}
83 
84 	if ((dirtybuffer2 = (unsigned char*)malloc(jedi_backgroundram_size)) == 0)
85 	{
86 		bitmap_free(tmpbitmap);
87 		free(dirtybuffer);
88 		return 1;
89 	}
90 	memset(dirtybuffer2,1,jedi_backgroundram_size);
91 
92 	if ((tmpbitmap2 = bitmap_alloc_depth(Machine->drv->screen_width,Machine->drv->screen_height,8)) == 0)
93 	{
94 		bitmap_free(tmpbitmap);
95 		free(dirtybuffer);
96 		free(dirtybuffer2);
97 		return 1;
98 	}
99 
100 	/* the background area is 256x256, doubled by the hardware*/
101 	if ((tmpbitmap3 = bitmap_alloc_depth(256,256,8)) == 0)
102 	{
103 		bitmap_free(tmpbitmap);
104 		bitmap_free(tmpbitmap2);
105 		free(dirtybuffer);
106 		free(dirtybuffer2);
107 		return 1;
108 	}
109 
110 	/* reserve color 1024 for black (disabled display) */
111 	palette_change_color(1024,0,0,0);
112 
113 	return 0;
114 }
115 
jedi_vh_stop(void)116 void jedi_vh_stop(void)
117 {
118 	bitmap_free(tmpbitmap);
119 	bitmap_free(tmpbitmap2);
120 	bitmap_free(tmpbitmap3);
121 	free(dirtybuffer);
122 	free(dirtybuffer2);
123 }
124 
125 
126 
WRITE_HANDLER(jedi_backgroundram_w)127 WRITE_HANDLER( jedi_backgroundram_w )
128 {
129 	if (jedi_backgroundram[offset] != data)
130 	{
131 		dirtybuffer2[offset] = 1;
132 
133 		jedi_backgroundram[offset] = data;
134 	}
135 }
136 
WRITE_HANDLER(jedi_vscroll_w)137 WRITE_HANDLER( jedi_vscroll_w )
138 {
139     jedi_vscroll = data | (offset << 8);
140 }
141 
WRITE_HANDLER(jedi_hscroll_w)142 WRITE_HANDLER( jedi_hscroll_w )
143 {
144     jedi_hscroll = data | (offset << 8);
145 }
146 
WRITE_HANDLER(jedi_alpha_banksel_w)147 WRITE_HANDLER( jedi_alpha_banksel_w )
148 {
149 	if (jedi_alpha_bank != 2*(data & 0x80))
150 	{
151 		jedi_alpha_bank = 2*(data & 0x80);
152 		memset(dirtybuffer,1,videoram_size);
153 	}
154 }
155 
WRITE_HANDLER(jedi_video_off_w)156 WRITE_HANDLER( jedi_video_off_w )
157 {
158 	video_off = data;
159 }
160 
WRITE_HANDLER(jedi_PIXIRAM_w)161 WRITE_HANDLER( jedi_PIXIRAM_w )
162 {
163 	smooth_table = data & 0x03;
164 }
165 
166 
167 
168 /***************************************************************************
169 
170   Draw the game screen in the given osd_bitmap.
171   Do NOT call osd_update_display() from this function, it will be called by
172   the main emulation engine.
173 
174 ***************************************************************************/
jedi_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)175 void jedi_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
176 {
177 	int offs;
178 
179 
180 	if (palette_recalc())
181 	{
182 		memset(dirtybuffer,1,videoram_size);
183 		memset(dirtybuffer2,1,jedi_backgroundram_size);
184 	}
185 
186 	if (video_off)
187 	{
188 		fillbitmap(bitmap,Machine->pens[1024],&Machine->visible_area);
189 		return;
190 	}
191 
192 
193 	/* Return of the Jedi has a peculiar playfield/sprite priority system. That */
194 	/* is, there is no priority system ;-) The color of the pixel which appears on */
195 	/* screen depends on all three of the foreground, background and sprites. The */
196 	/* 1024 colors palette is appropriately set up by the program to "emulate" a */
197 	/* priority system, but it can also be used to display completely different */
198 	/* colors (see the palette test in service mode) */
199 
200     /* foreground */
201     for (offs = videoram_size - 1;offs >= 0;offs--)
202 	{
203 		if (dirtybuffer[offs])
204 		{
205 			int sx,sy;
206 
207 
208 			dirtybuffer[offs] = 0;
209 
210 			sx = offs % 64;
211 			sy = offs / 64;
212 
213 			drawgfx(tmpbitmap,Machine->gfx[0],
214 					videoram[offs] + jedi_alpha_bank,
215 					0,
216 					0,0,
217 					8*sx,8*sy,
218 					&Machine->visible_area,TRANSPARENCY_NONE_RAW,0);
219 		}
220     }
221 
222 
223 	/* background */
224 	for (offs = jedi_backgroundram_size/2 - 1;offs >= 0;offs--)
225 	{
226 		if (dirtybuffer2[offs] != 0 || dirtybuffer2[offs + 0x400] != 0)
227 		{
228 			int sx,sy,b,c;
229 
230 
231 			dirtybuffer2[offs] = dirtybuffer2[offs + 0x400] = 0;
232 
233 			sx = offs % 32;
234 			sy = offs / 32;
235 			c = (jedi_backgroundram[offs] & 0xFF);
236 			b = (jedi_backgroundram[offs + 0x400] & 0x0F);
237 			c |= (b & 0x01) << 8;
238 			c |= (b & 0x08) << 6;
239 			c |= (b & 0x02) << 9;
240 
241 			drawgfx(tmpbitmap3,Machine->gfx[1],
242 					c,
243 					0,
244 					b & 0x04,0,
245 					8*sx,8*sy,
246 					0,TRANSPARENCY_NONE_RAW,0);
247 		}
248 	}
249 
250 
251 	/* Draw the sprites. Note that it is important to draw them exactly in this */
252 	/* order, to have the correct priorities. */
253 	fillbitmap(tmpbitmap2,0,&Machine->visible_area);
254 
255     for (offs = 0;offs < 0x30;offs++)
256 	{
257 		int x,y,flipx,flipy;
258 		int b,c;
259 
260 
261 		b = ((spriteram[offs+0x40] & 0x02) >> 1);
262 		b = b | ((spriteram[offs+0x40] & 0x40) >> 5);
263 		b = b | (spriteram[offs+0x40] & 0x04);
264 
265 		c = spriteram[offs] + (b * 256);
266 		if (spriteram[offs+0x40] & 0x08) c |= 1;	/* double height */
267 
268 		/* coordinates adjustments made to match screenshot */
269 		x = spriteram[offs+0x100] + ((spriteram[offs+0x40] & 0x01) << 8) - 2;
270 		y = 240-spriteram[offs+0x80] + 1;
271 		flipx = spriteram[offs+0x40] & 0x10;
272 		flipy = spriteram[offs+0x40] & 0x20;
273 
274 		drawgfx(tmpbitmap2,Machine->gfx[2],
275 				c,
276 				0,
277 				flipx,flipy,
278 				x,y,
279 				&Machine->visible_area,TRANSPARENCY_PEN_RAW,0);
280 
281 		if (spriteram[offs+0x40] & 0x08)	/* double height */
282 			drawgfx(tmpbitmap2,Machine->gfx[2],
283 					c-1,
284 					0,
285 					flipx,flipy,
286 					x,y-16,
287 					&Machine->visible_area,TRANSPARENCY_PEN_RAW,0);
288     }
289 
290 
291 	/* compose the three layers */
292 	{
293 		int x,y;
294 		UINT8 *s1,*s2,*s3,*s3b;
295 		UINT8 *prom = memory_region(REGION_PROMS) + smooth_table * 0x100;
296 
297 
298 		if (bitmap->depth == 16)
299 		{
300 			for (y = 0;y < bitmap->height;y++)
301 			{
302 				UINT16 *d = (UINT16 *)bitmap->line[y];
303 
304 				s1 = tmpbitmap->line[y];
305 				s2 = tmpbitmap2->line[y];
306 				s3 = tmpbitmap3->line[((y + jedi_vscroll) & 0x1ff) / 2];
307 				s3b = tmpbitmap3->line[((y + jedi_vscroll - 1) & 0x1ff) / 2];
308 
309 				for (x = 0;x < bitmap->width;x++)
310 				{
311 					int tl,tr,bl,br,mixt,mixb,mix;
312 
313 					tr = s3b[((x + jedi_hscroll + 1) & 0x1ff) / 2];
314 					br = s3 [((x + jedi_hscroll + 1) & 0x1ff) / 2];
315 
316 					if ((x + jedi_hscroll) & 1)
317 					{
318 						tl = s3b[((x + jedi_hscroll) & 0x1ff) / 2];
319 						bl = s3 [((x + jedi_hscroll) & 0x1ff) / 2];
320 						mixt = prom[16 * tl + tr];
321 						mixb = prom[16 * bl + br];
322 						mix = prom[0x400 + 16 * mixt + mixb];
323 					}
324 					else
325 						mix = prom[0x400 + 16 * tr + br];
326 
327 					*(d++) = Machine->pens[(*(s1++) << 8) | (*(s2++) << 4) | mix ];
328 				}
329 			}
330 		}
331 		else
332 		{
333 			for (y = 0;y < bitmap->height;y++)
334 			{
335 				UINT8 *d = bitmap->line[y];
336 
337 				s1 = tmpbitmap->line[y];
338 				s2 = tmpbitmap2->line[y];
339 				s3 = tmpbitmap3->line[((y + jedi_vscroll) & 0x1ff) / 2];
340 				s3b = tmpbitmap3->line[((y + jedi_vscroll - 1) & 0x1ff) / 2];
341 
342 				for (x = 0;x < bitmap->width;x++)
343 				{
344 					int tl,tr,bl,br,mixt,mixb,mix;
345 
346 					tr = s3b[((x + jedi_hscroll + 1) & 0x1ff) / 2];
347 					br = s3 [((x + jedi_hscroll + 1) & 0x1ff) / 2];
348 
349 					if ((x + jedi_hscroll) & 1)
350 					{
351 						tl = s3b[((x + jedi_hscroll) & 0x1ff) / 2];
352 						bl = s3 [((x + jedi_hscroll) & 0x1ff) / 2];
353 						mixt = prom[16 * tl + tr];
354 						mixb = prom[16 * bl + br];
355 						mix = prom[0x400 + 16 * mixt + mixb];
356 					}
357 					else
358 						mix = prom[0x400 + 16 * tr + br];
359 
360 					*(d++) = Machine->pens[(*(s1++) << 8) | (*(s2++) << 4) | mix ];
361 				}
362 			}
363 		}
364 	}
365 }
366