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 unsigned char *route16_sharedram;
13 unsigned char *route16_videoram1;
14 unsigned char *route16_videoram2;
15 size_t route16_videoram_size;
16 int route16_hardware;
17 
18 static struct mame_bitmap *tmpbitmap1;
19 static struct mame_bitmap *tmpbitmap2;
20 
21 static int video_flip;
22 static int video_color_select_1;
23 static int video_color_select_2;
24 static int video_disable_1 = 0;
25 static int video_disable_2 = 0;
26 static int video_remap_1;
27 static int video_remap_2;
28 static const unsigned char *route16_color_prom;
29 
30 /* Local functions */
31 static void modify_pen(int pen, int colorindex);
32 static void common_videoram_w(int offset,int data,
33                               int coloroffset, struct mame_bitmap *bitmap);
34 
35 
36 
PALETTE_INIT(route16)37 PALETTE_INIT( route16 )
38 {
39 	route16_color_prom = color_prom;	/* we'll need this later */
40 }
41 
42 
43 /***************************************************************************
44 
45   Start the video hardware emulation.
46 
47 ***************************************************************************/
VIDEO_START(route16)48 VIDEO_START( route16 )
49 {
50 	if ((tmpbitmap1 = auto_bitmap_alloc(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
51 		return 1;
52 
53 	if ((tmpbitmap2 = auto_bitmap_alloc(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
54 		return 1;
55 
56 	video_flip = 0;
57 	video_color_select_1 = 0;
58 	video_color_select_2 = 0;
59 	video_disable_1 = 0;
60 	video_disable_2 = 0;
61 	video_remap_1 = 1;
62 	video_remap_2 = 1;
63 
64 	return 0;
65 }
66 
67 
68 /***************************************************************************
69   route16_out0_w
70 ***************************************************************************/
WRITE_HANDLER(route16_out0_w)71 WRITE_HANDLER( route16_out0_w )
72 {
73 	static int last_write = 0;
74 
75 	if (data == last_write) return;
76 
77 	video_disable_1 = ((data & 0x02) << 6) && route16_hardware;
78 	video_color_select_1 = ((data & 0x1f) << 2);
79 
80 	/* Bit 5 is the coin counter. */
81 	coin_counter_w(0, data & 0x20);
82 
83 	video_remap_1 = 1;
84 	last_write = data;
85 }
86 
87 /***************************************************************************
88   route16_out1_w
89 ***************************************************************************/
WRITE_HANDLER(route16_out1_w)90 WRITE_HANDLER( route16_out1_w )
91 {
92 	static int last_write = 0;
93 
94 	if (data == last_write) return;
95 
96 	video_disable_2 = ((data & 0x02) << 6 ) && route16_hardware;
97 	video_color_select_2 = ((data & 0x1f) << 2);
98 
99 	if (video_flip != ((data & 0x20) >> 5))
100 	{
101 		video_flip = (data & 0x20) >> 5;
102 	}
103 
104 	video_remap_2 = 1;
105 	last_write = data;
106 }
107 
108 /***************************************************************************
109 
110   Handle Stratovox's extra sound effects.
111 
112 ***************************************************************************/
WRITE_HANDLER(stratvox_sn76477_w)113 WRITE_HANDLER( stratvox_sn76477_w )
114 {
115 	/* get out for Route 16 */
116 	if (route16_hardware) return;
117 
118     /***************************************************************
119      * AY8910 output bits are connected to...
120      * 7    - direct: 5V * 30k/(100+30k) = 1.15V - via DAC??
121      * 6    - SN76477 mixer a
122      * 5    - SN76477 mixer b
123      * 4    - SN76477 mixer c
124      * 3    - SN76477 envelope 1
125 	 * 2	- SN76477 envelope 2
126      * 1    - SN76477 vco
127      * 0    - SN76477 enable
128      ***************************************************************/
129     SN76477_mixer_w(0,(data >> 4) & 7);
130 	SN76477_envelope_w(0,(data >> 2) & 3);
131     SN76477_vco_w(0,(data >> 1) & 1);
132     SN76477_enable_w(0,data & 1);
133 }
134 
135 /***************************************************************************
136   route16_sharedram_r
137 ***************************************************************************/
READ_HANDLER(route16_sharedram_r)138 READ_HANDLER( route16_sharedram_r )
139 {
140 	return route16_sharedram[offset];
141 }
142 
143 /***************************************************************************
144   route16_sharedram_w
145 ***************************************************************************/
WRITE_HANDLER(route16_sharedram_w)146 WRITE_HANDLER( route16_sharedram_w )
147 {
148 	route16_sharedram[offset] = data;
149 
150 	// 4313-4319 are used in Route 16 as triggers to wake the other CPU
151 	if (offset >= 0x0313 && offset <= 0x0319 && data == 0xff && route16_hardware)
152 	{
153 		// Let the other CPU run
154 		cpu_yield();
155 	}
156 }
157 
158 /***************************************************************************
159   guessing that the unconnected IN3 and OUT2 on the stratvox schematic
160   are hooked up for speakres and spacecho to somehow read the variable
161   resistors (eg a voltage ramp), using a write to OUT2 as a trigger
162   and then bits 0-2 of IN3 going low when each pot "matches". the VRx
163   values can be seen when IN0=0x55 and p1b1 is held during power on.
164   this would then be checking that the sounds are mixed correctly.
165 ***************************************************************************/
166 static int speakres_vrx;
167 
READ_HANDLER(speakres_in3_r)168 READ_HANDLER ( speakres_in3_r )
169 {
170 	int bit2=4, bit1=2, bit0=1;
171 
172 	/* just using a counter, the constants are the number of reads
173 	   before going low, each read is 40 cycles apart. the constants
174 	   were chosen based on the startup tests and for vr0=vr2 */
175 	speakres_vrx++;
176 	if(speakres_vrx>0x300) bit0=0;		/* VR0 100k ohm - speech */
177 	if(speakres_vrx>0x200) bit1=0;		/* VR1  50k ohm - main volume */
178 	if(speakres_vrx>0x300) bit2=0;		/* VR2 100k ohm - explosion */
179 
180 	return 0xf8|bit2|bit1|bit0;
181 }
182 
WRITE_HANDLER(speakres_out2_w)183 WRITE_HANDLER ( speakres_out2_w )
184 {
185 	speakres_vrx=0;
186 }
187 
188 
189 /***************************************************************************
190   route16_videoram1_r
191 ***************************************************************************/
READ_HANDLER(route16_videoram1_r)192 READ_HANDLER( route16_videoram1_r )
193 {
194 	return route16_videoram1[offset];
195 }
196 
197 /***************************************************************************
198   route16_videoram2_r
199 ***************************************************************************/
READ_HANDLER(route16_videoram2_r)200 READ_HANDLER( route16_videoram2_r )
201 {
202 	return route16_videoram1[offset];
203 }
204 
205 /***************************************************************************
206   route16_videoram1_w
207 ***************************************************************************/
WRITE_HANDLER(route16_videoram1_w)208 WRITE_HANDLER( route16_videoram1_w )
209 {
210 	route16_videoram1[offset] = data;
211 
212 	common_videoram_w(offset, data, 0, tmpbitmap1);
213 }
214 
215 /***************************************************************************
216   route16_videoram2_w
217 ***************************************************************************/
WRITE_HANDLER(route16_videoram2_w)218 WRITE_HANDLER( route16_videoram2_w )
219 {
220 	route16_videoram2[offset] = data;
221 
222 	common_videoram_w(offset, data, 4, tmpbitmap2);
223 }
224 
225 /***************************************************************************
226   common_videoram_w
227 ***************************************************************************/
common_videoram_w(int offset,int data,int coloroffset,struct mame_bitmap * bitmap)228 static void common_videoram_w(int offset,int data,
229                               int coloroffset, struct mame_bitmap *bitmap)
230 {
231 	int x, y, color1, color2, color3, color4;
232 
233 	x = ((offset & 0x3f) << 2);
234 	y = (offset & 0xffc0) >> 6;
235 
236 	if (video_flip)
237 	{
238 		x = 255 - x;
239 		y = 255 - y;
240 	}
241 
242 	color4 = ((data & 0x80) >> 6) | ((data & 0x08) >> 3);
243 	color3 = ((data & 0x40) >> 5) | ((data & 0x04) >> 2);
244 	color2 = ((data & 0x20) >> 4) | ((data & 0x02) >> 1);
245 	color1 = ((data & 0x10) >> 3) | ((data & 0x01)     );
246 
247 	if (video_flip)
248 	{
249 		plot_pixel(bitmap, x  , y, Machine->pens[color1 | coloroffset]);
250 		plot_pixel(bitmap, x-1, y, Machine->pens[color2 | coloroffset]);
251 		plot_pixel(bitmap, x-2, y, Machine->pens[color3 | coloroffset]);
252 		plot_pixel(bitmap, x-3, y, Machine->pens[color4 | coloroffset]);
253 	}
254 	else
255 	{
256 		plot_pixel(bitmap, x  , y, Machine->pens[color1 | coloroffset]);
257 		plot_pixel(bitmap, x+1, y, Machine->pens[color2 | coloroffset]);
258 		plot_pixel(bitmap, x+2, y, Machine->pens[color3 | coloroffset]);
259 		plot_pixel(bitmap, x+3, y, Machine->pens[color4 | coloroffset]);
260 	}
261 }
262 
263 /***************************************************************************
264 
265   Draw the game screen in the given mame_bitmap.
266   Do NOT call osd_update_display() from this function, it will be called by
267   the main emulation engine.
268 
269 ***************************************************************************/
VIDEO_UPDATE(route16)270 VIDEO_UPDATE( route16 )
271 {
272     if (video_remap_1)
273 	{
274 		modify_pen(0, video_color_select_1 + 0);
275 		modify_pen(1, video_color_select_1 + 1);
276 		modify_pen(2, video_color_select_1 + 2);
277 		modify_pen(3, video_color_select_1 + 3);
278 	}
279 
280 	if (video_remap_2)
281 	{
282 		modify_pen(4, video_color_select_2 + 0);
283 		modify_pen(5, video_color_select_2 + 1);
284 		modify_pen(6, video_color_select_2 + 2);
285 		modify_pen(7, video_color_select_2 + 3);
286 	}
287 
288 
289 	if (get_vh_global_attribute_changed() || video_remap_1 || video_remap_2)
290 	{
291 		int offs;
292 
293 		// redraw bitmaps
294 		for (offs = 0; offs < route16_videoram_size; offs++)
295 		{
296 			route16_videoram1_w(offs, route16_videoram1[offs]);
297 			route16_videoram2_w(offs, route16_videoram2[offs]);
298 		}
299 	}
300 
301 	video_remap_1 = 0;
302 	video_remap_2 = 0;
303 
304 
305 	if (!video_disable_2)
306 	{
307 		copybitmap(bitmap,tmpbitmap2,0,0,0,0,&Machine->visible_area,TRANSPARENCY_NONE,0);
308 	}
309 
310 	if (!video_disable_1)
311 	{
312 		if (video_disable_2)
313 			copybitmap(bitmap,tmpbitmap1,0,0,0,0,&Machine->visible_area,TRANSPARENCY_NONE,0);
314 		else
315 			copybitmap(bitmap,tmpbitmap1,0,0,0,0,&Machine->visible_area,TRANSPARENCY_COLOR,0);
316 	}
317 }
318 
319 /***************************************************************************
320   mofify_pen
321  ***************************************************************************/
modify_pen(int pen,int colorindex)322 static void modify_pen(int pen, int colorindex)
323 {
324 	int r,g,b,color;
325 
326 	color = route16_color_prom[colorindex];
327 
328 	r = ((color & 1) ? 0xff : 0x00);
329 	g = ((color & 2) ? 0xff : 0x00);
330 	b = ((color & 4) ? 0xff : 0x00);
331 
332 	palette_set_color(pen,r,g,b);
333 }
334