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 "common.h"
11 #include "vidhrdw/generic.h"
12
13
14
15 unsigned char *gottlieb_characterram;
16 #define MAX_CHARS 256
17 static unsigned char *dirtycharacter;
18 static int background_priority=0;
19 static unsigned char hflip=0;
20 static unsigned char vflip=0;
21 static int spritebank;
22
23
24
25 /***************************************************************************
26
27 Gottlieb games dosn't have a color PROM. They use 32 bytes of RAM to
28 dynamically create the palette. Each couple of bytes defines one
29 color (4 bits per pixel; the high 4 bits of the second byte are unused).
30
31 The RAM is conected to the RGB output this way:
32
33 bit 7 -- 240 ohm resistor -- GREEN
34 -- 470 ohm resistor -- GREEN
35 -- 1 kohm resistor -- GREEN
36 -- 2 kohm resistor -- GREEN
37 -- 240 ohm resistor -- RED
38 -- 470 ohm resistor -- RED
39 -- 1 kohm resistor -- RED
40 bit 0 -- 2 kohm resistor -- RED
41
42 bit 7 -- unused
43 -- unused
44 -- unused
45 -- unused
46 -- 240 ohm resistor -- BLUE
47 -- 470 ohm resistor -- BLUE
48 -- 1 kohm resistor -- BLUE
49 bit 0 -- 2 kohm resistor -- BLUE
50
51 ***************************************************************************/
WRITE_HANDLER(gottlieb_paletteram_w)52 WRITE_HANDLER( gottlieb_paletteram_w )
53 {
54 int bit0,bit1,bit2,bit3;
55 int r,g,b,val;
56
57
58 paletteram[offset] = data;
59
60 /* red component */
61 val = paletteram[offset | 1];
62 bit0 = (val >> 0) & 0x01;
63 bit1 = (val >> 1) & 0x01;
64 bit2 = (val >> 2) & 0x01;
65 bit3 = (val >> 3) & 0x01;
66 r = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
67
68 /* green component */
69 val = paletteram[offset & ~1];
70 bit0 = (val >> 4) & 0x01;
71 bit1 = (val >> 5) & 0x01;
72 bit2 = (val >> 6) & 0x01;
73 bit3 = (val >> 7) & 0x01;
74 g = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
75
76 /* blue component */
77 val = paletteram[offset & ~1];
78 bit0 = (val >> 0) & 0x01;
79 bit1 = (val >> 1) & 0x01;
80 bit2 = (val >> 2) & 0x01;
81 bit3 = (val >> 3) & 0x01;
82 b = 0x10 * bit0 + 0x21 * bit1 + 0x46 * bit2 + 0x88 * bit3;
83
84 palette_change_color(offset / 2,r,g,b);
85 }
86
87
88
89 /***************************************************************************
90
91 Start the video hardware emulation.
92
93 ***************************************************************************/
94
gottlieb_vh_start(void)95 int gottlieb_vh_start(void)
96 {
97 if (generic_vh_start() != 0)
98 return 1;
99
100 if ((dirtycharacter = (unsigned char*)malloc(MAX_CHARS)) == 0)
101 {
102 generic_vh_stop();
103 return 1;
104 }
105 /* Some games have character gfx data in ROM, some others in RAM. We don't */
106 /* want to recalculate chars if data is in ROM, so let's start with the array */
107 /* initialized to 0. */
108 memset(dirtycharacter,0,MAX_CHARS);
109
110 return 0;
111 }
112
113 /***************************************************************************
114
115 Stop the video hardware emulation.
116
117 ***************************************************************************/
gottlieb_vh_stop(void)118 void gottlieb_vh_stop(void)
119 {
120 free(dirtycharacter);
121 generic_vh_stop();
122 }
123
124
125
WRITE_HANDLER(gottlieb_video_outputs_w)126 WRITE_HANDLER( gottlieb_video_outputs_w )
127 {
128 extern void gottlieb_knocker(void);
129 static int last = 0;
130
131
132 background_priority = data & 1;
133
134 hflip = data & 2;
135 vflip = data & 4;
136 if ((data & 6) != (last & 6))
137 memset(dirtybuffer,1,videoram_size);
138
139 /* in Q*Bert Qubes only, bit 4 controls the sprite bank */
140 spritebank = (data & 0x10) >> 4;
141
142 if ((last&0x20) && !(data&0x20)) gottlieb_knocker();
143
144 last = data;
145 }
146
WRITE_HANDLER(usvsthem_video_outputs_w)147 WRITE_HANDLER( usvsthem_video_outputs_w )
148 {
149 background_priority = data & 1;
150
151 /* in most games, bits 1 and 2 flip screen, however in the laser */
152 /* disc games they are different. */
153
154 /* bit 1 controls the sprite bank. */
155 spritebank = (data & 0x02) >> 1;
156
157 /* bit 2 video enable (0 = black screen) */
158
159 /* bit 3 genlock control (1 = show laserdisc image) */
160 }
161
162
163
WRITE_HANDLER(gottlieb_characterram_w)164 WRITE_HANDLER( gottlieb_characterram_w )
165 {
166 if (gottlieb_characterram[offset] != data)
167 {
168 dirtycharacter[offset / 32] = 1;
169 gottlieb_characterram[offset] = data;
170 }
171 }
172
173
174
175 /***************************************************************************
176
177 Draw the game screen in the given osd_bitmap.
178 Do NOT call osd_update_display() from this function, it will be called by
179 the main emulation engine.
180
181 ***************************************************************************/
gottlieb_vh_screenrefresh(struct osd_bitmap * bitmap,int full_refresh)182 void gottlieb_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
183 {
184 int offs;
185
186
187 /* update palette */
188 if (palette_recalc())
189 memset(dirtybuffer, 1, videoram_size);
190
191 /* recompute character graphics */
192 for (offs = 0;offs < Machine->drv->gfxdecodeinfo[0].gfxlayout->total;offs++)
193 {
194 if (dirtycharacter[offs])
195 decodechar(Machine->gfx[0],offs,gottlieb_characterram,Machine->drv->gfxdecodeinfo[0].gfxlayout);
196 }
197
198
199 /* for every character in the Video RAM, check if it has been modified */
200 /* since last time and update it accordingly. */
201 for (offs = videoram_size - 1;offs >= 0;offs--)
202 {
203 if (dirtybuffer[offs] || dirtycharacter[videoram[offs]])
204 {
205 int sx,sy;
206
207
208 dirtybuffer[offs] = 0;
209
210 sx = offs % 32;
211 sy = offs / 32;
212 if (hflip) sx = 31 - sx;
213 if (vflip) sy = 29 - sy;
214
215 drawgfx(tmpbitmap,Machine->gfx[0],
216 videoram[offs],
217 0,
218 hflip,vflip,
219 8*sx,8*sy,
220 &Machine->visible_area,TRANSPARENCY_NONE,0);
221 }
222 }
223
224 memset(dirtycharacter,0,MAX_CHARS);
225
226
227 /* copy the character mapped graphics */
228 copybitmap(bitmap,tmpbitmap,0,0,0,0,&Machine->visible_area,TRANSPARENCY_NONE,0);
229
230
231 /* Draw the sprites. Note that it is important to draw them exactly in this */
232 /* order, to have the correct priorities. */
233 for (offs = 0;offs < spriteram_size - 8;offs += 4) /* it seems there's something strange with sprites #62 and #63 */
234 {
235 int sx,sy;
236
237
238 /* coordinates hand tuned to make the position correct in Q*Bert Qubes start */
239 /* of level animation. */
240 sx = (spriteram[offs + 1]) - 4;
241 if (hflip) sx = 233 - sx;
242 sy = (spriteram[offs]) - 13;
243 if (vflip) sy = 228 - sy;
244
245 if (spriteram[offs] || spriteram[offs + 1]) /* needed to avoid garbage on screen */
246 drawgfx(bitmap,Machine->gfx[1],
247 (255 ^ spriteram[offs + 2]) + 256 * spritebank,
248 0,
249 hflip,vflip,
250 sx,sy,
251 &Machine->visible_area,
252 background_priority ? TRANSPARENCY_THROUGH : TRANSPARENCY_PEN,
253 background_priority ? Machine->pens[0] : 0);
254 }
255 }
256