1 // license:BSD-3-Clause
2 // copyright-holders:Couriersud
3 /*****************************************************************************
4 
5     resnet.cpp
6 
7     Compute weights for resistors networks.
8 
9 ******************************************************************************
10 
11     Function can evaluate from one to three networks at a time.
12 
13     The output weights can either be scaled with automatically calculated scaler
14     or scaled with a 'scaler' provided on entry.
15 
16     On entry
17     --------
18 
19     'minval','maxval' specify the range of output signals (sum of weights).
20     'scaler'          if negative, function will calculate proper scaler,
21                         otherwise it will use the one provided here.
22     'count_x'         is the number of resistors in this network
23     'resistances_x'   is the pointer to a table containing the resistances
24     'weights_x'       is the pointer to a table to be filled with the weights
25                         (it can contain negative values if 'minval' is below zero).
26     'pulldown_x'      is the resistance of a pulldown resistor (0 means there's no pulldown resistor)
27     'pullup_x'        is the resistance of a pullup resistor (0 means there's no pullup resistor)
28 
29 
30     Return value
31     ------------
32 
33     The value of the scaler that was used for fitting the output within the expected range.
34     Note that if you provide your own scaler on entry it will be returned here.
35 
36 
37     All resistances are expected in Ohms.
38 
39 
40     Hint
41     ----
42 
43     If there is no need to calculate all three networks at a time, just specify '0'
44     for the 'count_x' for unused network(s).
45 
46 *****************************************************************************/
47 
48 
49 #include "emu.h"
50 #include "resnet.h"
51 
52 #define VERBOSE 0
53 
54 
compute_resistor_weights(int minval,int maxval,double scaler,int count_1,const int * resistances_1,double * weights_1,int pulldown_1,int pullup_1,int count_2,const int * resistances_2,double * weights_2,int pulldown_2,int pullup_2,int count_3,const int * resistances_3,double * weights_3,int pulldown_3,int pullup_3)55 double compute_resistor_weights(
56 	int minval, int maxval, double scaler,
57 	int count_1, const int * resistances_1, double * weights_1, int pulldown_1, int pullup_1,
58 	int count_2, const int * resistances_2, double * weights_2, int pulldown_2, int pullup_2,
59 	int count_3, const int * resistances_3, double * weights_3, int pulldown_3, int pullup_3 )
60 {
61 	int networks_no;
62 
63 	int rescount[MAX_NETS];     /* number of resistors in each of the nets */
64 	double r[MAX_NETS][MAX_RES_PER_NET];        /* resistances */
65 	double w[MAX_NETS][MAX_RES_PER_NET];        /* calulated weights */
66 	double ws[MAX_NETS][MAX_RES_PER_NET];   /* calulated, scaled weights */
67 	int r_pd[MAX_NETS];         /* pulldown resistances */
68 	int r_pu[MAX_NETS];         /* pullup resistances */
69 
70 	double max_out[MAX_NETS];
71 	double * out[MAX_NETS];
72 
73 	int i,j,n;
74 	double scale;
75 	double max;
76 
77 	/* parse input parameters */
78 
79 	networks_no = 0;
80 	for (n = 0; n < MAX_NETS; n++)
81 	{
82 		int count, pd, pu;
83 		const int * resistances;
84 		double * weights;
85 
86 		switch(n){
87 		case 0:
88 				count       = count_1;
89 				resistances = resistances_1;
90 				weights     = weights_1;
91 				pd          = pulldown_1;
92 				pu          = pullup_1;
93 				break;
94 		case 1:
95 				count       = count_2;
96 				resistances = resistances_2;
97 				weights     = weights_2;
98 				pd          = pulldown_2;
99 				pu          = pullup_2;
100 				break;
101 		case 2:
102 		default:
103 				count       = count_3;
104 				resistances = resistances_3;
105 				weights     = weights_3;
106 				pd          = pulldown_3;
107 				pu          = pullup_3;
108 				break;
109 		}
110 
111 		/* parameters validity check */
112 		if (count > MAX_RES_PER_NET)
113 			fatalerror("compute_resistor_weights(): too many resistors in net #%i. The maximum allowed is %i, the number requested was: %i\n",n, MAX_RES_PER_NET, count);
114 
115 
116 		if (count > 0)
117 		{
118 			rescount[networks_no] = count;
119 			for (i=0; i < count; i++)
120 			{
121 				r[networks_no][i] = 1.0 * resistances[i];
122 			}
123 			out[networks_no] = weights;
124 			r_pd[networks_no] = pd;
125 			r_pu[networks_no] = pu;
126 			networks_no++;
127 		}
128 	}
129 	if (networks_no < 1)
130 		fatalerror("compute_resistor_weights(): no input data\n");
131 
132 	/* calculate outputs for all given networks */
133 	for( i = 0; i < networks_no; i++ )
134 	{
135 		double R0, R1, Vout, dst;
136 
137 		/* of n resistors */
138 		for(n = 0; n < rescount[i]; n++)
139 		{
140 			R0 = ( r_pd[i] == 0 ) ? 1.0/1e12 : 1.0/r_pd[i];
141 			R1 = ( r_pu[i] == 0 ) ? 1.0/1e12 : 1.0/r_pu[i];
142 
143 			for( j = 0; j < rescount[i]; j++ )
144 			{
145 				if( j==n )  /* only one resistance in the network connected to Vcc */
146 				{
147 					if (r[i][j] != 0.0)
148 						R1 += 1.0/r[i][j];
149 				}
150 				else
151 					if (r[i][j] != 0.0)
152 						R0 += 1.0/r[i][j];
153 			}
154 
155 			/* now determine the voltage */
156 			R0 = 1.0/R0;
157 			R1 = 1.0/R1;
158 			Vout = (maxval - minval) * R0 / (R1 + R0) + minval;
159 
160 			/* and convert it to a destination value */
161 			dst = (Vout < minval) ? minval : (Vout > maxval) ? maxval : Vout;
162 
163 			w[i][n] = dst;
164 		}
165 	}
166 
167 	/* calculate maximum outputs for all given networks */
168 	j = 0;
169 	max = 0.0;
170 	for( i = 0; i < networks_no; i++ )
171 	{
172 		double sum = 0.0;
173 
174 		/* of n resistors */
175 		for( n = 0; n < rescount[i]; n++ )
176 			sum += w[i][n]; /* maximum output, ie when each resistance is connected to Vcc */
177 
178 		max_out[i] = sum;
179 		if (max < sum)
180 		{
181 			max = sum;
182 			j = i;
183 		}
184 	}
185 
186 
187 	if (scaler < 0.0)   /* use autoscale ? */
188 		/* calculate the output scaler according to the network with the greatest output */
189 		scale = ((double)maxval) / max_out[j];
190 	else                /* use scaler provided on entry */
191 		scale = scaler;
192 
193 	/* calculate scaled output and fill the output table(s)*/
194 	for(i = 0; i < networks_no;i++)
195 	{
196 		for (n = 0; n < rescount[i]; n++)
197 		{
198 			ws[i][n] = w[i][n]*scale;   /* scale the result */
199 			(out[i])[n] = ws[i][n];     /* fill the output table */
200 		}
201 	}
202 
203 /* debug code */
204 if (VERBOSE)
205 {
206 	osd_printf_info("compute_resistor_weights():  scaler = %15.10f\n",scale);
207 	osd_printf_info("min val :%i  max val:%i  Total number of networks :%i\n", minval, maxval, networks_no );
208 
209 	for(i = 0; i < networks_no;i++)
210 	{
211 		double sum = 0.0;
212 
213 		osd_printf_info(" Network no.%i=>  resistances: %i", i, rescount[i] );
214 		if (r_pu[i] != 0)
215 			osd_printf_info(", pullup resistor: %i Ohms",r_pu[i]);
216 		if (r_pd[i] != 0)
217 			osd_printf_info(", pulldown resistor: %i Ohms",r_pd[i]);
218 		osd_printf_info("\n  maximum output of this network:%10.5f (scaled to %15.10f)\n", max_out[i], max_out[i]*scale );
219 		for (n = 0; n < rescount[i]; n++)
220 		{
221 			osd_printf_info("   res %2i:%9.1f Ohms  weight=%10.5f (scaled = %15.10f)\n", n, r[i][n], w[i][n], ws[i][n] );
222 			sum += ws[i][n];
223 		}
224 		osd_printf_info("                              sum of scaled weights = %15.10f\n", sum  );
225 	}
226 }
227 /* debug end */
228 
229 	return (scale);
230 
231 }
232 
233 
compute_resistor_net_outputs(int minval,int maxval,double scaler,int count_1,const int * resistances_1,double * outputs_1,int pulldown_1,int pullup_1,int count_2,const int * resistances_2,double * outputs_2,int pulldown_2,int pullup_2,int count_3,const int * resistances_3,double * outputs_3,int pulldown_3,int pullup_3)234 double compute_resistor_net_outputs(
235 	int minval, int maxval, double scaler,
236 	int count_1, const int * resistances_1, double * outputs_1, int pulldown_1, int pullup_1,
237 	int count_2, const int * resistances_2, double * outputs_2, int pulldown_2, int pullup_2,
238 	int count_3, const int * resistances_3, double * outputs_3, int pulldown_3, int pullup_3 )
239 {
240 	int networks_no;
241 
242 	int rescount[MAX_NETS];     /* number of resistors in each of the nets */
243 	double r[MAX_NETS][MAX_RES_PER_NET];        /* resistances */
244 	int r_pd[MAX_NETS];         /* pulldown resistances */
245 	int r_pu[MAX_NETS];         /* pullup resistances */
246 
247 	double max_out[MAX_NETS];
248 	double min_out[MAX_NETS];
249 	double * out[MAX_NETS];
250 
251 	int i,j,n;
252 	double scale;
253 	double min;
254 	double max;
255 
256 	/* parse input parameters */
257 
258 	std::vector<double> o((1<<MAX_RES_PER_NET) *  MAX_NETS);
259 	std::vector<double> os((1<<MAX_RES_PER_NET) *  MAX_NETS);
260 
261 	networks_no = 0;
262 	for (n = 0; n < MAX_NETS; n++)
263 	{
264 		int count, pd, pu;
265 		const int * resistances;
266 		double * weights;
267 
268 		switch(n){
269 		case 0:
270 				count       = count_1;
271 				resistances = resistances_1;
272 				weights     = outputs_1;
273 				pd          = pulldown_1;
274 				pu          = pullup_1;
275 				break;
276 		case 1:
277 				count       = count_2;
278 				resistances = resistances_2;
279 				weights     = outputs_2;
280 				pd          = pulldown_2;
281 				pu          = pullup_2;
282 				break;
283 		case 2:
284 		default:
285 				count       = count_3;
286 				resistances = resistances_3;
287 				weights     = outputs_3;
288 				pd          = pulldown_3;
289 				pu          = pullup_3;
290 				break;
291 		}
292 
293 		/* parameters validity check */
294 		if (count > MAX_RES_PER_NET)
295 			fatalerror("compute_resistor_net_outputs(): too many resistors in net #%i. The maximum allowed is %i, the number requested was: %i\n",n, MAX_RES_PER_NET, count);
296 
297 		if (count > 0)
298 		{
299 			rescount[networks_no] = count;
300 			for (i=0; i < count; i++)
301 			{
302 				r[networks_no][i] = 1.0 * resistances[i];
303 			}
304 			out[networks_no] = weights;
305 			r_pd[networks_no] = pd;
306 			r_pu[networks_no] = pu;
307 			networks_no++;
308 		}
309 	}
310 
311 	if (networks_no<1)
312 		fatalerror("compute_resistor_net_outputs(): no input data\n");
313 
314 	/* calculate outputs for all given networks */
315 	for( i = 0; i < networks_no; i++ )
316 	{
317 		double R0, R1, Vout, dst;
318 
319 		/* of n resistors, generating 1<<n possible outputs */
320 		for(n = 0; n < (1<<rescount[i]); n++)
321 		{
322 			R0 = ( r_pd[i] == 0 ) ? 1.0/1e12 : 1.0/r_pd[i];
323 			R1 = ( r_pu[i] == 0 ) ? 1.0/1e12 : 1.0/r_pu[i];
324 
325 			for( j = 0; j < rescount[i]; j++ )
326 			{
327 				if( (n & (1<<j)) == 0 )/* only when this resistance in the network connected to GND */
328 					if (r[i][j] != 0.0)
329 						R0 += 1.0/r[i][j];
330 			}
331 
332 			/* now determine the voltage */
333 			R0 = 1.0/R0;
334 			R1 = 1.0/R1;
335 			Vout = (maxval - minval) * R0 / (R1 + R0) + minval;
336 
337 			/* and convert it to a destination value */
338 			dst = (Vout < minval) ? minval : (Vout > maxval) ? maxval : Vout;
339 
340 			o[i*(1<<MAX_RES_PER_NET)+n] = dst;
341 		}
342 	}
343 
344 	/* calculate minimum outputs for all given networks */
345 	min = maxval;
346 	max = minval;
347 	for( i = 0; i < networks_no; i++ )
348 	{
349 		double val;
350 		double max_tmp = minval;
351 		double min_tmp = maxval;
352 
353 		for (n = 0; n < (1<<rescount[i]); n++)
354 		{
355 			if (min_tmp > o[i*(1<<MAX_RES_PER_NET)+n])
356 				min_tmp = o[i*(1<<MAX_RES_PER_NET)+n];
357 			if (max_tmp < o[i*(1<<MAX_RES_PER_NET)+n])
358 				max_tmp = o[i*(1<<MAX_RES_PER_NET)+n];
359 		}
360 
361 		max_out[i] = max_tmp;   /* maximum output */
362 		min_out[i] = min_tmp;   /* minimum output */
363 
364 		val = min_out[i];   /* minimum output of this network */
365 		if (min > val)
366 		{
367 			min = val;
368 		}
369 		val = max_out[i];   /* maximum output of this network */
370 		if (max < val)
371 		{
372 			max = val;
373 		}
374 	}
375 
376 
377 	if (scaler < 0.0)   /* use autoscale ? */
378 		/* calculate the output scaler according to the network with the smallest output */
379 		scale = ((double)maxval) / (max-min);
380 	else                /* use scaler provided on entry */
381 		scale = scaler;
382 
383 	/* calculate scaled output and fill the output table(s) */
384 	for(i = 0; i < networks_no; i++)
385 	{
386 		for (n = 0; n < (1<<rescount[i]); n++)
387 		{
388 			os[i*(1<<MAX_RES_PER_NET)+n] = (o[i*(1<<MAX_RES_PER_NET)+n] - min) * scale; /* scale the result */
389 			(out[i])[n] = os[i*(1<<MAX_RES_PER_NET)+n];     /* fill the output table */
390 		}
391 	}
392 
393 /* debug code */
394 if (VERBOSE)
395 {
396 	osd_printf_info("compute_resistor_net_outputs():  scaler = %15.10f\n",scale);
397 	osd_printf_info("min val :%i  max val:%i  Total number of networks :%i\n", minval, maxval, networks_no );
398 
399 	for(i = 0; i < networks_no;i++)
400 	{
401 		osd_printf_info(" Network no.%i=>  resistances: %i", i, rescount[i] );
402 		if (r_pu[i] != 0)
403 			osd_printf_info(", pullup resistor: %i Ohms",r_pu[i]);
404 		if (r_pd[i] != 0)
405 			osd_printf_info(", pulldown resistor: %i Ohms",r_pd[i]);
406 		osd_printf_info("\n  maximum output of this network:%10.5f", max_out[i] );
407 		osd_printf_info("\n  minimum output of this network:%10.5f\n", min_out[i] );
408 		for (n = 0; n < rescount[i]; n++)
409 		{
410 			osd_printf_info("   res %2i:%9.1f Ohms\n", n, r[i][n]);
411 		}
412 		for (n = 0; n < (1<<rescount[i]); n++)
413 		{
414 			osd_printf_info("   combination %2i  out=%10.5f (scaled = %15.10f)\n", n, o[i*(1<<MAX_RES_PER_NET)+n], os[i*(1<<MAX_RES_PER_NET)+n] );
415 		}
416 	}
417 }
418 /* debug end */
419 
420 	return (scale);
421 
422 }
423 
424 /*****************************************************************************
425 
426  New Interface
427 
428 *****************************************************************************/
429 
430 
431 /* Datasheets give a maximum of 0.4V to 0.5V
432  * However in the circuit simulated here this will only
433  * occur if (rBias + rOutn) = 50 Ohm, rBias exists.
434  * This is highly unlikely. With the resistor values used
435  * in such circuits VOL is likely to be around 50mV.
436  */
437 
438 #define TTL_VOL         (0.05)
439 
440 
441 /* Likely, datasheets give a typical value of 3.4V to 3.6V
442  * for VOH. Modelling the TTL circuit however backs a value
443  * of 4V for typical currents involved in resistor networks.
444  */
445 
446 #define TTL_VOH         (4.0)
447 
compute_res_net(int inputs,int channel,const res_net_info & di)448 int compute_res_net(int inputs, int channel, const res_net_info &di)
449 {
450 	double rTotal=0.0;
451 	double v = 0;
452 	int    i;
453 
454 	double vBias = di.rgb[channel].vBias;
455 	double vOH = di.vOH;
456 	double vOL = di.vOL;
457 	double minout = di.rgb[channel].minout;
458 	double cut = di.rgb[channel].cut;
459 	double vcc = di.vcc;
460 	double ttlHRes = 0;
461 	double rGnd = di.rgb[channel].rGnd;
462 	u8     OpenCol = di.OpenCol;
463 
464 	/* Global options */
465 
466 	switch (di.options & RES_NET_AMP_MASK)
467 	{
468 		case RES_NET_AMP_USE_GLOBAL:
469 			/* just ignore */
470 			break;
471 		case RES_NET_AMP_NONE:
472 			minout = 0.0;
473 			cut = 0.0;
474 			break;
475 		case RES_NET_AMP_DARLINGTON:
476 			minout = 0.9;
477 			cut = 0.0;
478 			break;
479 		case RES_NET_AMP_EMITTER:
480 			minout = 0.0;
481 			cut = 0.7;
482 			break;
483 		case RES_NET_AMP_CUSTOM:
484 			/* Fall through */
485 			break;
486 		default:
487 			fatalerror("compute_res_net: Unknown amplifier type\n");
488 	}
489 
490 	switch (di.options & RES_NET_VCC_MASK)
491 	{
492 		case RES_NET_VCC_5V:
493 			vcc = 5.0;
494 			break;
495 		case RES_NET_VCC_CUSTOM:
496 			/* Fall through */
497 			break;
498 		default:
499 			fatalerror("compute_res_net: Unknown vcc type\n");
500 	}
501 
502 	switch (di.options & RES_NET_VBIAS_MASK)
503 	{
504 		case RES_NET_VBIAS_USE_GLOBAL:
505 			/* just ignore */
506 			break;
507 		case RES_NET_VBIAS_5V:
508 			vBias = 5.0;
509 			break;
510 		case RES_NET_VBIAS_TTL:
511 			vBias = TTL_VOH;
512 			break;
513 		case RES_NET_VBIAS_CUSTOM:
514 			/* Fall through */
515 			break;
516 		default:
517 			fatalerror("compute_res_net: Unknown vcc type\n");
518 	}
519 
520 	switch (di.options & RES_NET_VIN_MASK)
521 	{
522 		case RES_NET_VIN_OPEN_COL:
523 			OpenCol = 1;
524 			vOL = TTL_VOL;
525 			break;
526 		case RES_NET_VIN_VCC:
527 			vOL = 0.0;
528 			vOH = vcc;
529 			OpenCol = 0;
530 			break;
531 		case RES_NET_VIN_TTL_OUT:
532 			vOL = TTL_VOL;
533 			vOH = TTL_VOH;
534 			/* rough estimation from 82s129 (7052) datasheet and from various sources
535 			 * 1.4k / 30
536 			 */
537 			ttlHRes = 50;
538 			OpenCol = 0;
539 			break;
540 		case RES_NET_VIN_CUSTOM:
541 			/* Fall through */
542 			break;
543 		default:
544 			fatalerror("compute_res_net: Unknown vin type\n");
545 	}
546 
547 	/* Per channel options */
548 
549 	switch (di.rgb[channel].options & RES_NET_AMP_MASK)
550 	{
551 		case RES_NET_AMP_USE_GLOBAL:
552 			/* use global defaults */
553 			break;
554 		case RES_NET_AMP_NONE:
555 			minout = 0.0;
556 			cut = 0.0;
557 			break;
558 		case RES_NET_AMP_DARLINGTON:
559 			minout = 0.7;
560 			cut = 0.0;
561 			break;
562 		case RES_NET_AMP_EMITTER:
563 			minout = 0.0;
564 			cut = 0.7;
565 			break;
566 		case RES_NET_AMP_CUSTOM:
567 			/* Fall through */
568 			break;
569 		default:
570 			fatalerror("compute_res_net: Unknown amplifier type\n");
571 	}
572 
573 	switch (di.rgb[channel].options & RES_NET_VBIAS_MASK)
574 	{
575 		case RES_NET_VBIAS_USE_GLOBAL:
576 			/* use global defaults */
577 			break;
578 		case RES_NET_VBIAS_5V:
579 			vBias = 5.0;
580 			break;
581 		case RES_NET_VBIAS_TTL:
582 			vBias = TTL_VOH;
583 			break;
584 		case RES_NET_VBIAS_CUSTOM:
585 			/* Fall through */
586 			break;
587 		default:
588 			fatalerror("compute_res_net: Unknown vcc type\n");
589 	}
590 
591 	/* Input impedances */
592 
593 	switch (di.options & RES_NET_MONITOR_MASK)
594 	{
595 		case RES_NET_MONITOR_INVERT:
596 		case RES_NET_MONITOR_SANYO_EZV20:
597 			/* Nothing */
598 			break;
599 		case RES_NET_MONITOR_ELECTROHOME_G07:
600 			if (rGnd != 0.0)
601 				rGnd = rGnd * 5600 / (rGnd + 5600);
602 			else
603 				rGnd = 5600;
604 			break;
605 	}
606 
607 	/* compute here - pass a / low inputs */
608 
609 	for (i=0; i<di.rgb[channel].num; i++)
610 	{
611 		int level = ((inputs >> i) & 1);
612 		if (di.rgb[channel].R[i] != 0.0 && !level)
613 		{
614 			// There is no difference in the calculation of the "low" input
615 			// (transistor conducting to ground) between TTL output and
616 			// open collector output. This is documented explicitly in the
617 			// code below (no difference if / else.
618 			if (OpenCol)
619 			{
620 				rTotal += 1.0 / di.rgb[channel].R[i];
621 				v += vOL / di.rgb[channel].R[i];
622 			}
623 			else
624 			{
625 				rTotal += 1.0 / di.rgb[channel].R[i];
626 				v += vOL / di.rgb[channel].R[i];
627 			}
628 		}
629 	}
630 
631 	/* Mix in rbias and rgnd */
632 	if ( di.rgb[channel].rBias != 0.0 )
633 	{
634 		rTotal += 1.0 / di.rgb[channel].rBias;
635 		v += vBias / di.rgb[channel].rBias;
636 	}
637 	if (rGnd != 0.0)
638 		rTotal += 1.0 / rGnd;
639 
640 	/* if the resulting voltage after application of all low inputs is
641 	 * greater than vOH, treat high inputs as open collector/high impedance
642 	 * There will be now current into/from the TTL gate
643 	 */
644 
645 	if ( (di.options & RES_NET_VIN_MASK)==RES_NET_VIN_TTL_OUT)
646 	{
647 		if (v / rTotal > vOH)
648 			OpenCol = 1;
649 	}
650 
651 	/* Second pass - high inputs */
652 
653 	for (i=0; i<di.rgb[channel].num; i++)
654 	{
655 		int level = ((inputs >> i) & 1);
656 		if (di.rgb[channel].R[i] != 0.0 && level)
657 		{
658 			if (OpenCol)
659 			{
660 				rTotal += 0;
661 				v += 0;
662 			}
663 			else
664 			{
665 				rTotal += 1.0 / (di.rgb[channel].R[i] + ttlHRes);
666 				v += vOH / (di.rgb[channel].R[i] + ttlHRes);
667 			}
668 		}
669 	}
670 
671 	rTotal = 1.0 / rTotal;
672 	v *= rTotal;
673 	v = std::max(minout, v - cut);
674 
675 	switch (di.options & RES_NET_MONITOR_MASK)
676 	{
677 		case RES_NET_MONITOR_INVERT:
678 			v = vcc - v;
679 			break;
680 		case RES_NET_MONITOR_SANYO_EZV20:
681 			v = vcc - v;
682 			v = std::max(double(0), v-0.7);
683 			v = std::min(v, vcc - 2 * 0.7);
684 			v = v / (vcc-1.4);
685 			v = v * vcc;
686 			break;
687 		case RES_NET_MONITOR_ELECTROHOME_G07:
688 			/* Nothing */
689 			break;
690 	}
691 
692 	return (int) (v * 255 / vcc + 0.4);
693 }
694 
compute_res_net_all(std::vector<rgb_t> & rgb,const u8 * prom,const res_net_decode_info & rdi,const res_net_info & di)695 void compute_res_net_all(std::vector<rgb_t> &rgb, const u8 *prom, const res_net_decode_info &rdi, const res_net_info &di)
696 {
697 	u8 r,g,b;
698 	int i,j,k;
699 
700 	rgb.resize(rdi.end - rdi.start + 1);
701 	for (i=rdi.start; i<=rdi.end; i++)
702 	{
703 		u8 t[3] = {0,0,0};
704 		int s;
705 		for (j=0;j<rdi.numcomp;j++)
706 			for (k=0; k<3; k++)
707 			{
708 				s = rdi.shift[3*j+k];
709 				if (s>0)
710 					t[k] = t[k] | ( (prom[i+rdi.offset[3*j+k]]>>s) & rdi.mask[3*j+k]);
711 				else
712 					t[k] = t[k] | ( (prom[i+rdi.offset[3*j+k]]<<(0-s)) & rdi.mask[3*j+k]);
713 			}
714 		r = compute_res_net(t[0], RES_NET_CHAN_RED, di);
715 		g = compute_res_net(t[1], RES_NET_CHAN_GREEN, di);
716 		b = compute_res_net(t[2], RES_NET_CHAN_BLUE, di);
717 		rgb[i-rdi.start] = rgb_t(r,g,b);
718 	}
719 }
720