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 unsigned char *toypop_sharedram_2;
13 
14 unsigned char *bg_image;
15 static struct osd_bitmap *bgbitmap;
16 static unsigned char *dirtybackground;
17 static int flipscreen;
18 
19 /***************************************************************************
20 
21   Convert the color PROMs into a more useable format.
22 
23   toypop has three 256x4 palette PROM and two 256x8 color lookup table PROMs
24   (one for characters, one for sprites).
25 
26 
27 ***************************************************************************/
toypop_vh_convert_color_prom(unsigned char * palette,unsigned short * colortable,const unsigned char * color_prom)28 void toypop_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
29 {
30 	int i;
31 
32 	for (i = 0;i < 256;i++)
33 	{
34 		int bit0,bit1,bit2,bit3;
35 
36 		// red component
37 		bit0 = (color_prom[i] >> 0) & 0x01;
38 		bit1 = (color_prom[i] >> 1) & 0x01;
39 		bit2 = (color_prom[i] >> 2) & 0x01;
40 		bit3 = (color_prom[i] >> 3) & 0x01;
41 		palette[3*i] = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
42 		// green component
43 		bit0 = (color_prom[i+0x100] >> 0) & 0x01;
44 		bit1 = (color_prom[i+0x100] >> 1) & 0x01;
45 		bit2 = (color_prom[i+0x100] >> 2) & 0x01;
46 		bit3 = (color_prom[i+0x100] >> 3) & 0x01;
47 		palette[3*i + 1] = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
48 		// blue component
49 		bit0 = (color_prom[i+0x200] >> 0) & 0x01;
50 		bit1 = (color_prom[i+0x200] >> 1) & 0x01;
51 		bit2 = (color_prom[i+0x200] >> 2) & 0x01;
52 		bit3 = (color_prom[i+0x200] >> 3) & 0x01;
53 		palette[3*i + 2] = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
54 	}
55 
56 	// characters
57 	for (i = 0;i < 256;i++)
58 		colortable[i] = color_prom[i + 0x300] | 0xf0;
59 
60 	// sprites
61 	for (i = 256;i < Machine->drv->color_table_len;i++)
62 		colortable[i] = color_prom[i + 0x400];	// 0x500-5ff
63 }
64 
toypop_vh_start(void)65 int toypop_vh_start(void)
66 {
67 	if ((dirtybuffer = (unsigned char*)malloc(videoram_size)) == 0)
68 		return 1;
69 	memset(dirtybuffer, 1, videoram_size);
70 
71 	if ((dirtybackground = (unsigned char*)malloc(videoram_size)) == 0) {
72 		free(dirtybuffer);
73 		return 1;
74 	}
75 	memset(dirtybackground, 1, videoram_size);
76 
77 	if ((tmpbitmap = bitmap_alloc(36*8,28*8)) == 0) {
78 		free(dirtybuffer);
79 		free(dirtybackground);
80 		return 1;
81 	}
82 	if ((bgbitmap = bitmap_alloc(36*8,28*8)) == 0) {
83 		bitmap_free(tmpbitmap);
84 		free(dirtybuffer);
85 		free(dirtybackground);
86 		return 1;
87 	}
88 
89 	return 0;
90 }
91 
toypop_vh_stop(void)92 void toypop_vh_stop(void)
93 {
94 	free(dirtybuffer);
95 	free(dirtybackground);
96 	bitmap_free(tmpbitmap);
97 	bitmap_free(bgbitmap);
98 
99 	dirtybuffer = 0;
100 	dirtybackground = 0;
101 	tmpbitmap = 0;
102 	bgbitmap = 0;
103 }
104 
READ_HANDLER(toypop_background_r)105 READ_HANDLER( toypop_background_r )
106 {
107 	return READ_WORD(&bg_image[offset]);
108 }
109 
WRITE_HANDLER(toypop_background_w)110 WRITE_HANDLER( toypop_background_w )
111 {
112 	int oldword = READ_WORD(&bg_image[offset]);
113 	int newword = COMBINE_WORD(oldword,data);
114 
115 	if (oldword != newword) {
116 		WRITE_WORD(&bg_image[offset],newword);
117 		dirtybackground[((offset % 288) >> 3) + ((offset / 2304) * 36)] = 1;
118 	}
119 }
120 
WRITE_HANDLER(toypop_flipscreen_w)121 WRITE_HANDLER( toypop_flipscreen_w )
122 {
123 	flipscreen = offset ^ 2;
124 }
125 
toypop_draw_sprite(struct osd_bitmap * dest,unsigned int code,unsigned int color,int flipx,int flipy,int sx,int sy)126 void toypop_draw_sprite(struct osd_bitmap *dest,unsigned int code,unsigned int color,
127 	int flipx,int flipy,int sx,int sy)
128 {
129 	drawgfx(dest,Machine->gfx[1],code,color,flipx,flipy,sx,sy,&Machine->visible_area,
130 		TRANSPARENCY_PEN,0);
131 }
132 
toypop_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)133 void toypop_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
134 {
135 	register int offs;
136 	struct rectangle box;
137 
138 	/* check if the background image has been modified */
139 	/* since last time and update it accordingly. */
140 	// (The background image changes only few times, so this loop is very fast)
141 	for (offs = 0;offs < 1008;offs++) {
142 		if (dirtybackground[offs]) {
143 			int bx, by, palette_index;
144 
145 			dirtybackground[offs] = 0;
146 			box.min_x = (offs % 36) << 3;
147 			box.max_x = box.min_x + 7;
148 			box.min_y = (offs / 36) << 3;
149 			box.max_y = box.min_y + 7;
150 			// copy the background image from memory to bitmap
151 			palette_index = (toypop_sharedram_2[0x102] ? 0xe0 : 0x60);
152 			for (by = box.min_y;by <= box.max_y;by++)
153 				for (bx = box.min_x;bx <= box.max_x;bx++)
154 					bgbitmap->line[by][bx] = Machine->pens[bg_image[(bx + by * 288) ^ 1] | palette_index];
155 			// mark the matching character as dirty
156 			// so the next loop will draw everything right
157 			switch ((offs >> 1) % 18) {
158 				case 0:	// the 2 columns at left
159 					dirtybuffer[(((offs % 36) + 30) << 5) + (offs / 36 + 2)] = 1;
160 					break;
161 				case 17:	// the 2 columns at right
162 					dirtybuffer[(((offs % 36) - 34) << 5) + (offs / 36 + 2)] = 1;
163 					break;
164 				default:	// the rest of the screen
165 					dirtybuffer[(offs % 36) - 2 + ((offs / 36 + 2) << 5)] = 1;
166 			}
167 		}
168 	}
169 
170 	/* for every character in the Video RAM, check if it has been modified */
171 	/* since last time and update it accordingly. */
172 	for (offs = videoram_size - 1;offs >= 0;offs--) {
173 		if (dirtybuffer[offs]) {
174 			int sx,sy;
175 
176 			dirtybuffer[offs] = 0;
177 			if (offs >= videoram_size - 64) {
178 				// Draw the 2 columns at left
179 				sx = ((offs >> 5) - 30) << 3;
180 				sy = ((offs & 0x1f) - 2) << 3;
181 			} else if (offs < 64) {
182 				// Draw the 2 columns at right
183 				sx = ((offs >> 5) + 34) << 3;
184 				sy = ((offs & 0x1f) - 2) << 3;
185 			} else {
186 				// draw the rest of the screen
187 				sx = ((offs & 0x1f) + 2) << 3;
188 				sy = ((offs >> 5) - 2) << 3;
189 			}
190 			// draw the background
191 			box.min_x = sx;
192 			box.max_x = sx+7;
193 			box.min_y = sy;
194 			box.max_y = sy+7;
195 			copybitmap(tmpbitmap,bgbitmap,0,0,0,0,&box,TRANSPARENCY_NONE,0);
196 			// draw the character
197 			drawgfx(tmpbitmap,Machine->gfx[0],
198 					videoram[offs],
199 					colorram[offs],
200 					0,0,sx,sy,
201 					0,TRANSPARENCY_PEN,0);
202 		}
203 	}
204 
205 	/* copy the temporary bitmap to the screen */
206 	copybitmap(bitmap,tmpbitmap,flipscreen,flipscreen,0,0,&Machine->visible_area,TRANSPARENCY_NONE,0);
207 
208 	/* Draw the sprites. */
209 	for (offs = 0;offs < spriteram_size;offs += 2) {
210 		/* is it on? */
211 		if ((spriteram_2[offs]) != 0xe9) {
212 			int sprite = spriteram[offs];
213 			int color = spriteram[offs+1];
214 			int x = 343 - spriteram_2[offs+1] - 0x100 * (spriteram_3[offs+1] & 1);
215 			int y = spriteram_2[offs] - 9;
216 			int flipx = spriteram_3[offs] & 1;
217 			int flipy = spriteram_3[offs] & 2;
218 
219 			if (flipscreen) {
220 				flipx = !flipx;
221 				flipy = !flipy;
222 			}
223 
224 			switch (spriteram_3[offs] & 0x0c)
225 			{
226 				case 0:		/* normal size */
227 					toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,y);
228 					break;
229 
230 				case 4:		/* 2x vertical */
231 					sprite &= ~1;
232 					if (!flipy)
233 					{
234 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,y);
235 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x,16+y);
236 					}
237 					else
238 					{
239 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,16+y);
240 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x,y);
241 					}
242 					break;
243 
244 				case 8:		/* 2x horizontal */
245 					sprite &= ~2;
246 					if (!flipx)
247 					{
248 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,x,y);
249 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,16+x,y);
250 					}
251 					else
252 					{
253 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,y);
254 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,16+x,y);
255 					}
256 					break;
257 
258 				case 12:		/* 2x both ways */
259 					sprite &= ~3;
260 					if (!flipy && !flipx)
261 					{
262 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,x-16,y+16);
263 						toypop_draw_sprite(bitmap,3+sprite,color,flipx,flipy,x,16+y);
264 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x-16,y);
265 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x,y);
266 					}
267 					else if (flipy && flipx)
268 					{
269 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x-16,y+16);
270 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,16+y);
271 						toypop_draw_sprite(bitmap,3+sprite,color,flipx,flipy,x-16,y);
272 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,x,y);
273 					}
274 					else if (flipx)
275 					{
276 						toypop_draw_sprite(bitmap,3+sprite,color,flipx,flipy,x-16,y+16);
277 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,x,16+y);
278 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x-16,y);
279 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x,y);
280 					}
281 					else /* flipy */
282 					{
283 						toypop_draw_sprite(bitmap,sprite,color,flipx,flipy,x-16,y+16);
284 						toypop_draw_sprite(bitmap,1+sprite,color,flipx,flipy,x,16+y);
285 						toypop_draw_sprite(bitmap,2+sprite,color,flipx,flipy,x-16,y);
286 						toypop_draw_sprite(bitmap,3+sprite,color,flipx,flipy,x,y);
287 					}
288 					break;
289 			}
290 		}
291 	}
292 }
293