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