1 // license:BSD-3-Clause
2 // copyright-holders:Couriersud
3 /***************************************************************************
4 
5   video.c
6 
7   Functions to emulate the video hardware of the machine.
8 
9 
10 ***************************************************************************/
11 
12 #include "emu.h"
13 #include "video/resnet.h"
14 #include "includes/dkong.h"
15 
16 #define RADARSCP_BCK_COL_OFFSET         256
17 #define RADARSCP_GRID_COL_OFFSET        (RADARSCP_BCK_COL_OFFSET + 256)
18 #define RADARSCP_STAR_COL               (RADARSCP_GRID_COL_OFFSET + 8)
19 
20 static const double cd4049_vl = 1.5/5.0;
21 static const double cd4049_vh = 3.5/5.0;
22 static const double cd4049_al = 0.01;
23 
24 /***************************************************************************
25 
26   Convert the color PROMs into a more useable format.
27 
28   Donkey Kong has two 256x4 palette PROMs and one 256x4 PROM which contains
29   the color codes to use for characters on a per row/column basis (groups of
30   of 4 characters in the same column - actually row, since the display is
31   rotated)
32   The palette PROMs are connected to the RGB output this way:
33 
34     5V  -- 470 ohm resistor -- inverter  -- RED
35   bit 3 -- 220 ohm resistor -- inverter  -- RED
36         -- 470 ohm resistor -- inverter  -- RED
37         -- 1  kohm resistor -- inverter  -- RED
38 
39    5V  -- 470 ohm resistor -- inverter  -- GREEN
40   bit 0 -- 220 ohm resistor -- inverter  -- GREEN
41   bit 3 -- 470 ohm resistor -- inverter  -- GREEN
42         -- 1  kohm resistor -- inverter  -- GREEN
43     5V  -- 680 ohm resistor -- inverter  -- BLUE
44         -- 220 ohm resistor -- inverter  -- BLUE
45   bit 0 -- 470 ohm resistor -- inverter  -- BLUE
46 
47   After the mixing stage there is a darlington circuit with approx. linear
48   transfer function for red and green. Minimum output voltage is 0.9 Volt.
49   Blue is transferred through just one transistor. Here we have to
50   substract 0.7 Volts. This signal (0..5V) is inverted by a amplifier
51   circuit with an emitter lowpass RC. The R is a variable resistor.
52   So any calculations done here may be void in reality ...
53 ***************************************************************************/
54 
55 /*
56     dkong color interface:
57 
58     All outputs are open-collector and pullup resistors are connected to 5V.
59     Red and Green outputs are routed through a complimentary darlington
60     whereas blue is routed through a 1:1 stage leading to a 0.7V cutoff.
61 */
62 
63 static const res_net_decode_info dkong_decode_info =
64 {
65 	2,      /*  there may be two proms needed to construct color */
66 	0,      /*  start at 0 */
67 	255,    /*  end at 255 */
68 	/*  R,   G,   B,   R,   G,   B */
69 	{ 256, 256,   0,   0,   0,   0},        /*  offsets */
70 	{   1,  -2,   0,   0,   2,   0},        /*  shifts */
71 	{0x07,0x04,0x03,0x00,0x03,0x00}         /*  masks */
72 };
73 
74 static const res_net_info dkong_net_info =
75 {
76 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
77 	{
78 		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
79 		{ RES_NET_AMP_DARLINGTON, 470, 0, 3, { 1000, 470, 220 } },
80 		{ RES_NET_AMP_EMITTER,    680, 0, 2, {  470, 220,   0 } }  /*  dkong */
81 	}
82 };
83 
84 static const res_net_info dkong_net_bck_info =
85 {
86 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
87 	{
88 		{ RES_NET_AMP_DARLINGTON, 470, 0, 0, { 0 } },
89 		{ RES_NET_AMP_DARLINGTON, 470, 0, 0, { 0 } },
90 		{ RES_NET_AMP_EMITTER,    680, 0, 0, { 0 } }
91 	}
92 };
93 
94 static const res_net_decode_info dkong3_decode_info =
95 {
96 	1,      /*  one prom needed to contruct color */
97 	0,      /*  start at 0 */
98 	255,    /*  end at 255 */
99 	/*   R,   G,   B */
100 	{   0,   0, 512 },      /*  offsets */
101 	{   4,   0,   0 },      /*  shifts */
102 	{0x0F,0x0F,0x0F }           /*  masks */
103 };
104 
105 static const res_net_info dkong3_net_info =
106 {
107 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
108 	{
109 		{ RES_NET_AMP_DARLINGTON, 470,      0, 4, { 2200, 1000, 470, 220 } },
110 		{ RES_NET_AMP_DARLINGTON, 470,      0, 4, { 2200, 1000, 470, 220 } },
111 		{ RES_NET_AMP_DARLINGTON, 470,      0, 4, { 2200, 1000, 470, 220 } }
112 	}
113 };
114 
115 /*
116     radarscp interface
117 
118     All outputs are open-collector. The pullup resistors are connected to
119     inverters (TTL). All outputs are routed through a complimentary
120     darlington. The blue channel has a pulldown resistor (R8, 0M15) as well.
121 */
122 
123 
124 #define TRS_J1  (1)         // (1) = Closed (0) = Open
125 
126 
127 static const res_net_info radarscp_net_info =
128 {
129 	RES_NET_VCC_5V | RES_NET_VBIAS_TTL | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
130 	{
131 		{ RES_NET_AMP_DARLINGTON, 470 * TRS_J1, 470*(1-TRS_J1), 3, { 1000, 470, 220 } },
132 		{ RES_NET_AMP_DARLINGTON, 470 * TRS_J1, 470*(1-TRS_J1), 3, { 1000, 470, 220 } },
133 		{ RES_NET_AMP_EMITTER,    680 * TRS_J1, 680*(1-TRS_J1), 2, {  470, 220,   0 } }    /*  radarscp */
134 	}
135 };
136 
137 static const res_net_info radarscp_net_bck_info =
138 {
139 	RES_NET_VCC_5V | RES_NET_VBIAS_TTL | RES_NET_VIN_MB7052 |  RES_NET_MONITOR_SANYO_EZV20,
140 	{
141 		{ RES_NET_AMP_DARLINGTON, 470, 4700, 0, { 0 } },
142 		{ RES_NET_AMP_DARLINGTON, 470, 4700, 0, { 0 } },
143 		{ RES_NET_AMP_EMITTER,    470, 4700, 0, { 0 } }    /*  radarscp */
144 	}
145 };
146 
147 /*
148     radarscp1 interface
149 
150     All outputs are open-collector. They are followed by inverters which
151     drive the resistor network. All outputs are routed through a complimentary
152     darlington.
153 */
154 
155 static const res_net_info radarscp1_net_info =
156 {
157 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT | RES_NET_MONITOR_SANYO_EZV20,
158 	{
159 		{ RES_NET_AMP_DARLINGTON, 0,      0, 4, { 39000, 20000, 10000, 4990 } },
160 		{ RES_NET_AMP_DARLINGTON, 0,      0, 4, { 39000, 20000, 10000, 4990 } },
161 		{ RES_NET_AMP_EMITTER,    0,      0, 4, { 39000, 20000, 10000, 4990 } }
162 	}
163 };
164 
165 /* Radarscp star color */
166 
167 static const res_net_info radarscp_stars_net_info =
168 {
169 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT | RES_NET_MONITOR_SANYO_EZV20,
170 	{
171 		{ RES_NET_AMP_DARLINGTON, 4700, 470, 0, { 0 } },
172 		{ RES_NET_AMP_DARLINGTON,    1,   0, 0, { 0 } },    /*  dummy */
173 		{ RES_NET_AMP_EMITTER,       1,   0, 0, { 0 } },    /*  dummy */
174 	}
175 };
176 
177 /* Dummy struct to generate background palette entries */
178 
179 static const res_net_info radarscp_blue_net_info =
180 {
181 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_VCC | RES_NET_MONITOR_SANYO_EZV20,
182 	{
183 		{ RES_NET_AMP_DARLINGTON,  470, 4700, 0, { 0 } },   /*  bias/gnd exist in schematics, readable in TKG3 schematics */
184 		{ RES_NET_AMP_DARLINGTON,  470, 4700, 0, { 0 } },   /*  bias/gnd exist in schematics, readable in TKG3 schematics */
185 		{ RES_NET_AMP_EMITTER,       0,    0, 8, { 128,64,32,16,8,4,2,1 } },    /*  dummy */
186 	}
187 };
188 
189 /* Dummy struct to generate grid palette entries */
190 
191 static const res_net_info radarscp_grid_net_info =
192 {
193 	RES_NET_VCC_5V | RES_NET_VBIAS_5V | RES_NET_VIN_TTL_OUT | RES_NET_MONITOR_SANYO_EZV20,
194 	{
195 		{ RES_NET_AMP_DARLINGTON,    0,   0, 1, { 1 } },    /*  dummy */
196 		{ RES_NET_AMP_DARLINGTON,    0,   0, 1, { 1 } },    /*  dummy */
197 		{ RES_NET_AMP_EMITTER,       0,   0, 1, { 1 } },    /*  dummy */
198 	}
199 };
200 
dkong2b_palette(palette_device & palette)201 void dkong_state::dkong2b_palette(palette_device &palette)
202 {
203 	const uint8_t *color_prom = memregion("proms")->base();
204 
205 	std::vector<rgb_t> rgb;
206 	compute_res_net_all(rgb, color_prom, dkong_decode_info, dkong_net_info);
207 	palette.set_pen_colors(0, rgb);
208 
209 	// Now treat tri-state black background generation
210 	for (int i = 0; i < 256; i++)
211 		if ((i & 0x03) == 0x00)  // NOR => CS=1 => Tristate => real black
212 		{
213 			int const r = compute_res_net(1, 0, dkong_net_bck_info);
214 			int const g = compute_res_net(1, 1, dkong_net_bck_info);
215 			int const b = compute_res_net(1, 2, dkong_net_bck_info);
216 			palette.set_pen_color(i, r, g, b);
217 		}
218 
219 	palette.palette()->normalize_range(0, 255);
220 
221 	color_prom += 512;
222 	// color_prom now points to the beginning of the character color codes
223 	m_color_codes = color_prom; // we'll need it later
224 }
225 
226 #ifdef UNUSED_FUNCTION
dkong4b_palette(palette_device & palette)227 void dkong_state::dkong4b_palette(palette_device &palette)
228 {
229 	const uint8_t *color_prom = memregion("proms")->base();
230 
231 	for (int i = 0; i < 256; i++)
232 	{
233 		// red component
234 		int const r = compute_res_net((color_prom[256] >> 1) & 0x07, 0, radarscp_net_info);
235 		// green component
236 		int const g = compute_res_net(((color_prom[256] << 2) & 0x04) | ((color_prom[0] >> 2) & 0x03), 1, radarscp_net_info);
237 		// blue component
238 		int const b = compute_res_net((color_prom[0] >> 0) & 0x03, 2, radarscp_net_info);
239 
240 		palette.set_pen_color(i, r, g, b);
241 		color_prom++;
242 	}
243 
244 	// Now treat tri-state black background generation
245 
246 	for (int i = 0; i < 256; i++)
247 		if ((i & 0x03) == 0x00)  // NOR => CS=1 => Tristate => real black
248 		{
249 			int const r = compute_res_net(1, 0, radarscp_net_bck_info);
250 			int const g = compute_res_net(1, 1, radarscp_net_bck_info);
251 			int const b = compute_res_net(1, 2, radarscp_net_bck_info);
252 			palette.set_pen_color(i, r, g, b);
253 		}
254 
255 	palette.palette()->normalize_range(0, 255);
256 
257 	color_prom += 256;
258 	// color_prom now points to the beginning of the character color codes
259 	m_color_codes = color_prom; // we'll need it later
260 }
261 #endif
262 
radarscp_palette(palette_device & palette)263 void dkong_state::radarscp_palette(palette_device &palette)
264 {
265 	const uint8_t *color_prom = memregion("proms")->base();
266 
267 	for (int i = 0; i < 256; i++)
268 	{
269 		// red component
270 		int const r = compute_res_net((color_prom[256] >> 1) & 0x07, 0, radarscp_net_info);
271 		// green component
272 		int const g = compute_res_net(((color_prom[256] << 2) & 0x04) | ((color_prom[0] >> 2) & 0x03), 1, radarscp_net_info);
273 		// blue component
274 		int const b = compute_res_net((color_prom[0] >> 0) & 0x03, 2, radarscp_net_info);
275 
276 		palette.set_pen_color(i, r, g, b);
277 		color_prom++;
278 	}
279 
280 	// Now treat tri-state black background generation
281 	for (int i = 0; i < 256; i++)
282 		if ((m_vidhw != DKONG_RADARSCP_CONVERSION) && ((i & 0x03) == 0x00)) // NOR => CS=1 => Tristate => real black
283 		{
284 			int const r = compute_res_net(1, 0, radarscp_net_bck_info);
285 			int const g = compute_res_net(1, 1, radarscp_net_bck_info);
286 			int const b = compute_res_net(1, 2, radarscp_net_bck_info);
287 			palette.set_pen_color(i,r,g,b);
288 		}
289 
290 	// Star color
291 	palette.set_pen_color(RADARSCP_STAR_COL,
292 			compute_res_net(1, 0, radarscp_stars_net_info),
293 			compute_res_net(0, 1, radarscp_stars_net_info),
294 			compute_res_net(0, 2, radarscp_stars_net_info));
295 
296 	// Oscillating background
297 	for (int i = 0; i < 256; i++)
298 	{
299 		int const r = compute_res_net(0, 0, radarscp_blue_net_info);
300 		int const g = compute_res_net(0, 1, radarscp_blue_net_info);
301 		int const b = compute_res_net(i, 2, radarscp_blue_net_info);
302 
303 		palette.set_pen_color(RADARSCP_BCK_COL_OFFSET + i, r, g, b);
304 	}
305 
306 	// Grid
307 	for (int i = 0; i < 8; i++)
308 	{
309 		int const r = compute_res_net(BIT(i, 0), 0, radarscp_grid_net_info);
310 		int const g = compute_res_net(BIT(i, 1), 1, radarscp_grid_net_info);
311 		int const b = compute_res_net(BIT(i, 2), 2, radarscp_grid_net_info);
312 
313 		palette.set_pen_color(RADARSCP_GRID_COL_OFFSET + i, r, g, b);
314 	}
315 
316 	palette.palette()->normalize_range(0, RADARSCP_GRID_COL_OFFSET + 7);
317 
318 	color_prom += 256;
319 	// color_prom now points to the beginning of the character color codes
320 	m_color_codes = color_prom; // we'll need it later
321 }
322 
radarscp1_palette(palette_device & palette)323 void dkong_state::radarscp1_palette(palette_device &palette)
324 {
325 	const uint8_t *color_prom = memregion("proms")->base();
326 
327 	for (int i = 0; i < 256; i++)
328 	{
329 		// red component
330 		int const r = compute_res_net(color_prom[512], 0, radarscp1_net_info);
331 		// green component
332 		int const g = compute_res_net(color_prom[256], 1, radarscp1_net_info);
333 		// blue component
334 		int const b = compute_res_net(color_prom[0], 2, radarscp1_net_info);
335 
336 		palette.set_pen_color(i, r, g, b);
337 		color_prom++;
338 	}
339 
340 	// Now treat tri-state black background generation
341 	for (int i = 0; i < 256; i++)
342 		if ((i & 0x03) == 0x00)  // NOR => CS=1 => Tristate => real black
343 		{
344 			int const r = compute_res_net(0, 0, radarscp1_net_info);
345 			int const g = compute_res_net(0, 1, radarscp1_net_info);
346 			int const b = compute_res_net(0, 2, radarscp1_net_info);
347 			palette.set_pen_color(i, r, g, b);
348 		}
349 
350 	// Star color
351 	palette.set_pen_color(RADARSCP_STAR_COL,
352 			compute_res_net(1, 0, radarscp_stars_net_info),
353 			compute_res_net(0, 1, radarscp_stars_net_info),
354 			compute_res_net(0, 2, radarscp_stars_net_info));
355 
356 	/* Oscillating background */
357 	for (int i = 0; i < 256; i++)
358 	{
359 		int const r = compute_res_net(0, 0, radarscp_blue_net_info);
360 		int const g = compute_res_net(0, 1, radarscp_blue_net_info);
361 		int const b = compute_res_net(i, 2, radarscp_blue_net_info);
362 
363 		palette.set_pen_color(RADARSCP_BCK_COL_OFFSET + i, r, g, b);
364 	}
365 
366 	// Grid
367 	for (int i = 0; i < 8; i++)
368 	{
369 		int const r = compute_res_net(BIT(i, 0), 0, radarscp_grid_net_info);
370 		int const g = compute_res_net(BIT(i, 1), 1, radarscp_grid_net_info);
371 		int const b = compute_res_net(BIT(i, 2), 2, radarscp_grid_net_info);
372 
373 		palette.set_pen_color(RADARSCP_GRID_COL_OFFSET + i, r, g, b);
374 	}
375 	palette.palette()->normalize_range(0, RADARSCP_GRID_COL_OFFSET + 7);
376 
377 	color_prom += 512;
378 	// color_prom now points to the beginning of the character color codes
379 	m_color_codes = color_prom; // we'll need it later
380 }
381 
382 
383 
384 /***************************************************************************
385 
386   Convert the color PROMs into a more useable format.
387 
388   Donkey Kong 3 has two 512x8 palette PROMs and one 256x4 PROM which contains
389   the color codes to use for characters on a per row/column basis (groups of
390   of 4 characters in the same column - actually row, since the display is
391   rotated)
392   Interstingly, bytes 0-255 of the palette PROMs contain an inverted palette,
393   as other Nintendo games like Donkey Kong, while bytes 256-511 contain a non
394   inverted palette. This was probably done to allow connection to both the
395   special Nintendo and a standard monitor.
396   I don't know the exact values of the resistors between the PROMs and the
397   RGB output, but they are probably the usual:
398 
399   Couriersud: Checked against the schematics.
400               The proms are open collector proms and there is a pullup to
401               +5V of 470 ohm.
402 
403   bit 7 -- 220 ohm resistor -- inverter  -- RED
404         -- 470 ohm resistor -- inverter  -- RED
405         -- 1  kohm resistor -- inverter  -- RED
406         -- 2.2kohm resistor -- inverter  -- RED
407         -- 220 ohm resistor -- inverter  -- GREEN
408         -- 470 ohm resistor -- inverter  -- GREEN
409         -- 1  kohm resistor -- inverter  -- GREEN
410   bit 0 -- 2.2kohm resistor -- inverter  -- GREEN
411 
412   bit 3 -- 220 ohm resistor -- inverter  -- BLUE
413         -- 470 ohm resistor -- inverter  -- BLUE
414         -- 1  kohm resistor -- inverter  -- BLUE
415   bit 0 -- 2.2kohm resistor -- inverter  -- BLUE
416 
417 ***************************************************************************/
418 
dkong3_palette(palette_device & palette)419 void dkong_state::dkong3_palette(palette_device &palette)
420 {
421 	const uint8_t *color_prom = memregion("proms")->base();
422 
423 	std::vector<rgb_t> rgb;
424 	compute_res_net_all(rgb, color_prom, dkong3_decode_info, dkong3_net_info);
425 	palette.set_pen_colors(0, rgb);
426 	palette.palette()->normalize_range(0, 255);
427 
428 	color_prom += 1024;
429 	// color_prom now points to the beginning of the character color codes
430 	m_color_codes = color_prom; // we'll need it later
431 }
432 
TILE_GET_INFO_MEMBER(dkong_state::dkong_bg_tile_info)433 TILE_GET_INFO_MEMBER(dkong_state::dkong_bg_tile_info)
434 {
435 	int code = m_video_ram[tile_index] + 256 * m_gfx_bank;
436 	int color = (m_color_codes[tile_index % 32 + 32 * (tile_index / 32 / 4)] & 0x0f) + 0x10 * m_palette_bank;
437 
438 	tileinfo.set(0, code, color, 0);
439 }
440 
TILE_GET_INFO_MEMBER(dkong_state::radarscp1_bg_tile_info)441 TILE_GET_INFO_MEMBER(dkong_state::radarscp1_bg_tile_info)
442 {
443 	int code = m_video_ram[tile_index] + 256 * m_gfx_bank;
444 	int color = (m_color_codes[tile_index % 32] & 0x0f);
445 	color = color | (m_palette_bank<<4);
446 
447 	tileinfo.set(0, code, color, 0);
448 }
449 
450 /***************************************************************************
451 
452   I/O Handling
453 
454 ***************************************************************************/
455 
dkong_videoram_w(offs_t offset,uint8_t data)456 void dkong_state::dkong_videoram_w(offs_t offset, uint8_t data)
457 {
458 	if (m_video_ram[offset] != data)
459 	{
460 		m_video_ram[offset] = data;
461 		m_bg_tilemap->mark_tile_dirty(offset);
462 	}
463 }
464 
dkongjr_gfxbank_w(uint8_t data)465 void dkong_state::dkongjr_gfxbank_w(uint8_t data)
466 {
467 	if (m_gfx_bank != (data & 0x01))
468 	{
469 		m_gfx_bank = data & 0x01;
470 		m_bg_tilemap->mark_all_dirty();
471 	}
472 }
473 
dkong3_gfxbank_w(uint8_t data)474 void dkong_state::dkong3_gfxbank_w(uint8_t data)
475 {
476 	if (m_gfx_bank != (~data & 0x01))
477 	{
478 		m_gfx_bank = ~data & 0x01;
479 		m_bg_tilemap->mark_all_dirty();
480 	}
481 }
482 
dkong_palettebank_w(offs_t offset,uint8_t data)483 void dkong_state::dkong_palettebank_w(offs_t offset, uint8_t data)
484 {
485 	int newbank;
486 
487 	newbank = m_palette_bank;
488 
489 	if (data & 1)
490 		newbank |= 1 << offset;
491 	else
492 		newbank &= ~(1 << offset);
493 
494 	if (m_palette_bank != newbank)
495 	{
496 		m_palette_bank = newbank;
497 		m_bg_tilemap->mark_all_dirty();
498 	}
499 }
500 
radarscp_grid_enable_w(uint8_t data)501 void dkong_state::radarscp_grid_enable_w(uint8_t data)
502 {
503 	m_grid_on = data & 0x01;
504 }
505 
radarscp_grid_color_w(uint8_t data)506 void dkong_state::radarscp_grid_color_w(uint8_t data)
507 {
508 	m_grid_col = (data & 0x07) ^ 0x07;
509 	/* popmessage("Gridcol: %d", m_grid_col); */
510 }
511 
dkong_flipscreen_w(uint8_t data)512 void dkong_state::dkong_flipscreen_w(uint8_t data)
513 {
514 	m_flip = data & 0x01;
515 }
516 
dkong_spritebank_w(uint8_t data)517 void dkong_state::dkong_spritebank_w(uint8_t data)
518 {
519 	m_sprite_bank = data & 0x01;
520 }
521 
522 /***************************************************************************
523 
524   Draw the game screen in the given bitmap_ind16.
525 
526 ***************************************************************************/
527 
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect,uint32_t mask_bank,uint32_t shift_bits)528 void dkong_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect, uint32_t mask_bank, uint32_t shift_bits)
529 {
530 	int offs;
531 	int scanline_vf;    /* buffering scanline including flip */
532 	int scanline_vfc;   /* line buffering scanline including flip - this is the cached scanline_vf */
533 	int scanline;       /* current scanline */
534 	int add_y;
535 	int add_x;
536 	int num_sprt;
537 
538 	/* Draw the sprites. There are two pecularities which have been mentioned by
539 	 * a Donkey Kong II author at CAX 2008:
540 	 * 1) On real hardware, sprites wrap around from the right to the left instead
541 	 *    of clipping.
542 	 * 2) On real hardware, there is a limit of 16 sprites per scanline.
543 	 *    Sprites after the 16th (starting from the left) simply don't show.
544 	 *
545 	 * 2) is in line with the real hardware which buffers the sprite data
546 	 * for one scanline. The ram is 64x9 and a sprite takes 4 bytes.
547 	 * ==> 16 sprites per scanline.
548 	 *
549 	 * TODO: 9th bit is not understood right now.
550 	 *
551 	 * 1) is due to limitation of signals to 8 bit.
552 	 *
553 	 * This is quite different from galaxian. The dkong hardware updates sprites
554 	 * only once every frame by dma. The number of sprites can not be processed
555 	 * directly, Thus the preselection. The buffering takes place during the
556 	 * active phase of the video signal. The scanline is than rendered into the linebuffer
557 	 * during HBLANK.
558 	 *
559 	 * A sprite will be drawn:
560 	 * a) FlipQ = 1 : (sprite_y + 0xF9 + scanline) & 0xF0 == 0xF0
561 	 * b) FlipQ = 0 : (sprite_y + 0xF7 + (scanline ^ 0xFF)) & 0xF0 == 0xF0
562 	 *
563 	 * FlipQ = 1 ("Normal Play"):
564 	 *
565 	 * sprite_y = 0x20
566 	 *
567 	 * scanline
568 	 * 0x10, 0xEF, 0x208, 0x00
569 	 * 0x18, 0xE7, 0x200, 0x00
570 	 * 0x19, 0xE6, 0x1FF, 0xF0
571 	 * 0x20, 0xDF, 0x1F8, 0xF0
572 	 *
573 	 */
574 
575 	scanline_vf = (cliprect.max_y - 1) & 0xFF;
576 	scanline_vfc = (cliprect.max_y - 1) & 0xFF;
577 	scanline = cliprect.max_y & 0xFF;
578 
579 	if (m_flip)
580 	{
581 		scanline_vf ^= 0xFF;
582 		scanline_vfc ^= 0xFF;
583 		add_y = 0xF7;
584 		add_x = 0xF7;
585 	}
586 	else
587 	{
588 		add_y = 0xF9;
589 		add_x = 0xF7;
590 	}
591 
592 	for (offs = m_sprite_bank<<9, num_sprt=0; (num_sprt < 16) && (offs < (m_sprite_bank<<9) + 0x200) /* sprite_ram_size */; offs += 4)
593 	{
594 		int y = m_sprite_ram[offs];
595 		int do_draw = (((y + add_y + 1 + scanline_vf) & 0xF0) == 0xF0) ? 1 : 0;
596 
597 		if (do_draw)
598 		{
599 			/* sprite_ram[offs + 2] & 0x40 is used by Donkey Kong 3 only */
600 			/* sprite_ram[offs + 2] & 0x30 don't seem to be used (they are */
601 			/* probably not part of the color code, since Mario Bros, which */
602 			/* has similar hardware, uses a memory mapped port to change */
603 			/* palette bank, so it's limited to 16 color codes) */
604 
605 			int code = (m_sprite_ram[offs + 1] & 0x7f) + ((m_sprite_ram[offs + 2] & mask_bank) << shift_bits);
606 			int color = (m_sprite_ram[offs + 2] & 0x0f) + 16 * m_palette_bank;
607 			int flipx = m_sprite_ram[offs + 2] & 0x80;
608 			int flipy = m_sprite_ram[offs + 1] & 0x80;
609 
610 			/* On the real board, the x and y are read inverted after the first
611 			 * buffer stage. This due to the fact that the 82S09 delivers complements
612 			 * of stored data on read!
613 			 */
614 
615 			int x = (m_sprite_ram[offs + 3] + add_x + 1) & 0xFF;
616 			if (m_flip)
617 			{
618 				x = (x ^ 0xFF) - 15;
619 				flipx = !flipx;
620 			}
621 			y = scanline - ((y + add_y + 1 + scanline_vfc) & 0x0F);
622 
623 			m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, code, color, flipx, flipy, x, y, 0);
624 
625 			// wraparound
626 			m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, code, color, flipx, flipy, m_flip ? x + 256 : x - 256, y, 0);
627 			m_gfxdecode->gfx(1)->transpen(bitmap,cliprect, code, color, flipx, flipy, x, y - 256, 0);
628 
629 			num_sprt++;
630 		}
631 	}
632 }
633 
634 /* The hardware designer must have been a real CD4049 fan
635  * The blue signal is created by "abusing" the 4049
636  * as an amplifier by operating it in the undefined area
637  * between roughly 1.5 and 3.5V. The transfer function
638  * below is an approximation but datasheets state
639  * a wide range for the transfer function.
640  *
641  * SwitcherCad was not a real help since it can not
642  * adequately model the 4049
643  *
644  * Sound02 will mix in noise into the periodic fluctuation
645  * of the background: The 30Hz signal is used
646  * to generate noise with an LS164. This signal is going
647  * through a NAND (Signal RFLIP to video) and then XOR with 128V.
648  * This should really be emulated using the discrete sound interface.
649  * TODO: This should be part of the vblank routine
650  */
651 
CD4049(double x)652 inline double dkong_state::CD4049(double x)
653 {
654 	if (x>0)
655 		return exp(-m_cd4049_a * pow(x,m_cd4049_b));
656 	else
657 		return 1.0;
658 }
659 
660 /* Actually the sound noise is a multivibrator with
661  * a period of roughly 4.4 ms
662  */
663 
664 #define RC1     (2.2e3 * 22e-6) /*  22e-6; */
665 #define RC2     (10e3 * 33e-6)
666 #define RC31    (18e3 * 33e-6)
667 #define RC32    ((18e3 + 68e3) * 33e-6)
668 #define RC4     (90e3 * 0.47e-6)
669 #define dt      (1./60./(double) VTOTAL)
670 #define period2 (((int64_t)(PIXEL_CLOCK.value()) * ( 33L * 68L )) / (int32_t)10000000L / 3)  /*  period/2 in pixel ... */
671 
radarscp_step(int line_cnt)672 void dkong_state::radarscp_step(int line_cnt)
673 {
674 	/* Condensator is illegible in schematics for TRS2 board.
675 	 * TRS1 board states 3.3u.
676 	 */
677 
678 	double vg3i;
679 	double diff;
680 	int sig;
681 
682 	/* vsync is divided by 2 by a LS161
683 	 * The resulting 30 Hz signal clocks a LFSR (LS164) operating as a
684 	 * random number generator.
685 	 */
686 
687 	if ( line_cnt == 0)
688 	{
689 		m_sig30Hz = (1-m_sig30Hz);
690 		if (m_sig30Hz)
691 			m_lfsr_5I = (machine().rand() > RAND_MAX/2);
692 	}
693 
694 	/* sound2 mixes in a 30Hz noise signal.
695 	 * With the current model this has no real effect
696 	 * Included for completeness
697 	 */
698 
699 	/* Now mix with SND02 (sound 2) line - on 74ls259, bit2 */
700 	m_rflip_sig = m_dev_6h->bit2_r() & m_lfsr_5I;
701 
702 	/* blue background generation */
703 
704 	line_cnt += (256 - 8) + 1; // offset 8 needed to match monitor pictures
705 	if (line_cnt>511)
706 		line_cnt -= VTOTAL;
707 
708 	sig = m_rflip_sig ^ ((line_cnt & 0x80)>>7);
709 
710 	if (m_hardware_type == HARDWARE_TRS01)
711 		m_rflip_sig = !m_rflip_sig;
712 
713 	if  (sig) /*  128VF */
714 		diff = (0.0 - m_cv1);
715 	else
716 		diff = (4.8 - m_cv1);
717 	diff = diff - diff*exp(0.0 - (1.0/RC1 * dt) );
718 	m_cv1 += diff;
719 
720 	diff = (m_cv1 - m_cv2 - m_vg1);
721 	diff = diff - diff*exp(0.0 - (1.0/RC2 * dt) );
722 	m_cv2 += diff;
723 
724 	// FIXME: use the inverse function
725 	// Solve the amplifier by iteration
726 	for (int j=1; j<=11; j++)// 11% = 1/75 / (1/75+1/10)
727 	{
728 		double f = (double) j / 100.0;
729 		m_vg1 = (m_cv1 - m_cv2)*(1-f) + f * m_vg2;
730 		m_vg2 = 5*CD4049(m_vg1/5);
731 	}
732 	// FIXME: use the inverse function
733 	// Solve the amplifier by iteration 50% = both resistors equal
734 	for (int j=10; j<=20; j++)
735 	{
736 		double f = (double) j / 40.0;
737 		vg3i = (1.0-f) * m_vg2 + f * m_vg3;
738 		m_vg3 = 5*CD4049(vg3i/5);
739 	}
740 
741 #define RC17 (33e-6 * 1e3 * (0*4.7+1.0/(1.0/10.0+1.0/20.0+0.0/0.3)))
742 	diff = (m_vg3 - m_vc17);
743 	diff = diff - diff*exp(0.0 - (1.0/RC17 * dt) );
744 	m_vc17 += diff;
745 
746 	double vo = (m_vg3 - m_vc17);
747 	vo = vo + 20.0 / (20.0+10.0) * 5;
748 
749 	// Transistor is marked as OMIT in TRS-02 schems.
750 	//vo = vo - 0.7;
751 
752 
753 	//double vo = (vg3o - vg3)/4.7 + 5.0/16.0;
754 	//vo = vo / (1.0 / 4.7 + 1.0 / 16.0 + 1.0 / 30.0 );
755 	//printf("%f %f\n", vg3, vc17);
756 
757 	m_blue_level = (int)(vo/5.0*255);
758 	//printf("%d\n", m_blue_level);
759 
760 	/*
761 	 * Grid signal
762 	 *
763 	 * Mixed with ANS line (bit 5) from Port B of 8039
764 	 */
765 	if (m_grid_on && m_dev_vp2->bit5_r())
766 	{
767 		diff = (0.0 - m_cv3);
768 		diff = diff - diff*exp(0.0 - (1.0/RC32 * dt) );
769 	}
770 	else
771 	{
772 		diff = (5.0 - m_cv3);
773 		diff = diff - diff*exp(0.0 - (1.0/RC31 * dt) );
774 	}
775 	m_cv3 += diff;
776 
777 	diff = (m_vg2 - 0.8 * m_cv3 - m_cv4);
778 	diff = diff - diff*exp(0.0 - (1.0/RC4 * dt) );
779 	m_cv4 += diff;
780 
781 	if (CD4049(CD4049((m_vg2 - m_cv4)/5.0))>2.4/5.0) /* TTL - Level */
782 		m_grid_sig = 0;
783 	else
784 		m_grid_sig = 1;
785 
786 	/* stars */
787 	m_pixelcnt += HTOTAL;
788 	if (m_pixelcnt > period2 )
789 	{
790 		m_star_ff = !m_star_ff;
791 		m_pixelcnt = m_pixelcnt - period2;
792 	}
793 
794 }
795 
radarscp_draw_background(bitmap_ind16 & bitmap,const rectangle & cliprect)796 void dkong_state::radarscp_draw_background(bitmap_ind16 &bitmap, const rectangle &cliprect)
797 {
798 	const uint8_t     *htable = nullptr;
799 
800 	if (m_hardware_type == HARDWARE_TRS01)
801 		htable = m_gfx4;
802 
803 	int y = cliprect.min_y;
804 	while (y <= cliprect.max_y)
805 	{
806 		int x = cliprect.min_x;
807 		while (x <= cliprect.max_x)
808 		{
809 			uint16_t *const pixel = &bitmap.pix(y, x);
810 			uint8_t draw_ok = !(*pixel & 0x01) && !(*pixel & 0x02);
811 			if (m_hardware_type == HARDWARE_TRS01) /*  Check again from schematics */
812 				draw_ok = draw_ok  && !((htable[ (!m_rflip_sig<<7) | (x>>2)] >>2) & 0x01);
813 			if (draw_ok)
814 				*pixel = m_bg_bits.pix(y, x);
815 			x++;
816 		}
817 		y++;
818 	}
819 }
820 
radarscp_scanline(int scanline)821 void dkong_state::radarscp_scanline(int scanline)
822 {
823 	uint8_t const *const table = m_gfx3;
824 	int         table_len = m_gfx3_len;
825 	const rectangle &visarea = m_screen->visible_area();
826 
827 	int y = scanline;
828 	radarscp_step(y);
829 	if (y <= visarea.min_y || y > visarea.max_y)
830 		m_counter = 0;
831 	int offset = (m_flip ^ m_rflip_sig) ? 0x000 : 0x400;
832 	int x = 0;
833 	while (x < m_screen->width())
834 	{
835 		uint16_t *const pixel = &m_bg_bits.pix(y, x);
836 		if ((m_counter < table_len) && (x == 4 * (table[m_counter|offset] & 0x7f)))
837 		{
838 			if ( m_star_ff && (table[m_counter|offset] & 0x80) )    /* star */
839 				*pixel = RADARSCP_STAR_COL;
840 			else if (m_grid_sig && !(table[m_counter|offset] & 0x80))           /* radar */
841 				*pixel = RADARSCP_GRID_COL_OFFSET+m_grid_col;
842 			else
843 				*pixel = RADARSCP_BCK_COL_OFFSET + m_blue_level;
844 			m_counter++;
845 		}
846 		else
847 			*pixel = RADARSCP_BCK_COL_OFFSET + m_blue_level;
848 		x++;
849 	}
850 	while ((m_counter < table_len) && (x < 4 * (table[m_counter|offset] & 0x7f)))
851 		m_counter++;
852 }
853 
TIMER_CALLBACK_MEMBER(dkong_state::scanline_callback)854 TIMER_CALLBACK_MEMBER(dkong_state::scanline_callback)
855 {
856 	int scanline = param;
857 
858 	if ((m_hardware_type == HARDWARE_TRS02) || (m_hardware_type == HARDWARE_TRS01))
859 		radarscp_scanline(scanline);
860 
861 	/* update any video up to the current scanline */
862 //  m_screen->update_now();
863 	m_screen->update_partial(m_screen->vpos());
864 
865 	scanline = (scanline+1) % VTOTAL;
866 	/* come back at the next appropriate scanline */
867 	m_scanline_timer->adjust(m_screen->time_until_pos(scanline), scanline);
868 }
869 
check_palette()870 void dkong_state::check_palette()
871 {
872 	ioport_port *port;
873 	int newset;
874 
875 	port = ioport("VIDHW");
876 	if (port != nullptr)
877 	{
878 		newset = port->read();
879 		if (newset != m_vidhw)
880 		{
881 			m_vidhw = newset;
882 			switch (newset)
883 			{
884 				case DKONG_RADARSCP_CONVERSION:
885 					radarscp_palette(*m_palette);
886 					break;
887 				case DKONG_BOARD:
888 					dkong2b_palette(*m_palette);
889 					break;
890 			}
891 		}
892 	}
893 }
894 
VIDEO_START_MEMBER(dkong_state,dkong_base)895 VIDEO_START_MEMBER(dkong_state,dkong_base)
896 {
897 	m_cd4049_b = (log(0.0 - log(cd4049_al)) - log(0.0 - log((1.0-cd4049_al))) ) / log(cd4049_vh/cd4049_vl);
898 	m_cd4049_a = log(0.0 - log(cd4049_al)) - m_cd4049_b * log(cd4049_vh);
899 
900 	m_gfx_bank = 0;
901 	m_palette_bank = 0;
902 	m_sprite_bank = 0;
903 	m_vidhw = -1;
904 
905 	save_item(NAME(m_vidhw));
906 	save_item(NAME(m_gfx_bank));
907 	save_item(NAME(m_palette_bank));
908 	save_item(NAME(m_sprite_bank));
909 	save_item(NAME(m_grid_on));
910 
911 	save_item(NAME(m_grid_col));
912 	save_item(NAME(m_flip));
913 
914 	// TRS01 TRS02
915 	save_item(NAME(m_sig30Hz));
916 	save_item(NAME(m_blue_level));
917 	save_item(NAME(m_cv1));
918 	save_item(NAME(m_cv2));
919 	save_item(NAME(m_vg1));
920 	save_item(NAME(m_vg2));
921 	save_item(NAME(m_vg3));
922 	save_item(NAME(m_cv3));
923 	save_item(NAME(m_cv4));
924 
925 	save_item(NAME(m_lfsr_5I));
926 	save_item(NAME(m_grid_sig));
927 	save_item(NAME(m_rflip_sig));
928 	save_item(NAME(m_star_ff));
929 	save_item(NAME(m_counter));
930 	save_item(NAME(m_pixelcnt));
931 	save_item(NAME(m_bg_bits));
932 
933 }
934 
VIDEO_START_MEMBER(dkong_state,dkong)935 VIDEO_START_MEMBER(dkong_state,dkong)
936 {
937 	VIDEO_START_CALL_MEMBER(dkong_base);
938 
939 	m_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dkong_state::scanline_callback),this));
940 	m_scanline_timer->adjust(m_screen->time_until_pos(0));
941 
942 	switch (m_hardware_type)
943 	{
944 		case HARDWARE_TRS02:
945 			m_screen->register_screen_bitmap(m_bg_bits);
946 			m_gfx3 = memregion("gfx3")->base();
947 			m_gfx3_len = memregion("gfx3")->bytes();
948 			/* fall through */
949 		case HARDWARE_TKG04:
950 		case HARDWARE_TKG02:
951 			m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dkong_state::dkong_bg_tile_info)), TILEMAP_SCAN_ROWS,  8, 8, 32, 32);
952 			break;
953 		case HARDWARE_TRS01:
954 			m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(dkong_state::radarscp1_bg_tile_info)), TILEMAP_SCAN_ROWS,  8, 8, 32, 32);
955 
956 			m_screen->register_screen_bitmap(m_bg_bits);
957 			m_gfx4 = memregion("gfx4")->base();
958 			m_gfx3 = memregion("gfx3")->base();
959 			m_gfx3_len = memregion("gfx3")->bytes();
960 
961 			break;
962 		default:
963 			fatalerror("Invalid hardware type in dkong_video_start\n");
964 	}
965 }
966 
screen_update_dkong(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)967 uint32_t dkong_state::screen_update_dkong(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
968 {
969 	machine().tilemap().set_flip_all(m_flip ? TILEMAP_FLIPX | TILEMAP_FLIPY : 0);
970 
971 	switch (m_hardware_type)
972 	{
973 		case HARDWARE_TKG02:
974 		case HARDWARE_TKG04:
975 			check_palette();
976 			m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
977 			draw_sprites(bitmap, cliprect, 0x40, 1);
978 			break;
979 		case HARDWARE_TRS01:
980 		case HARDWARE_TRS02:
981 			m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
982 			draw_sprites(bitmap, cliprect, 0x40, 1);
983 			radarscp_draw_background(bitmap, cliprect);
984 			break;
985 		default:
986 			fatalerror("Invalid hardware type in dkong_video_update\n");
987 	}
988 	return 0;
989 }
990 
screen_update_pestplce(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)991 uint32_t dkong_state::screen_update_pestplce(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
992 {
993 	int offs;
994 
995 	machine().tilemap().set_flip_all(m_flip ? TILEMAP_FLIPX | TILEMAP_FLIPY : 0);
996 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
997 
998 	/* Draw the sprites. */
999 	for (offs = 0;offs < m_sprite_ram.bytes();offs += 4)
1000 	{
1001 		if (m_sprite_ram[offs])
1002 		{
1003 			if (m_flip)
1004 				m_gfxdecode->gfx(1)->transpen(bitmap, cliprect,
1005 					m_sprite_ram[offs + 2],
1006 					(m_sprite_ram[offs + 1] & 0x0f) + 16 * m_palette_bank,
1007 					~m_sprite_ram[offs + 1] & 0x80,~m_sprite_ram[offs + 1] & 0x40,
1008 					240 - m_sprite_ram[offs + 3] + 8,m_sprite_ram[offs] - 8, 0);
1009 			else
1010 				m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
1011 					m_sprite_ram[offs + 2],
1012 					(m_sprite_ram[offs + 1] & 0x0f) + 16 * m_palette_bank,
1013 					m_sprite_ram[offs + 1] & 0x80,m_sprite_ram[offs + 1] & 0x40,
1014 					m_sprite_ram[offs + 3] - 8,240 - m_sprite_ram[offs] + 8,0);
1015 		}
1016 	}
1017 	return 0;
1018 }
1019 
screen_update_spclforc(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)1020 uint32_t dkong_state::screen_update_spclforc(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
1021 {
1022 	machine().tilemap().set_flip_all(m_flip ? TILEMAP_FLIPX | TILEMAP_FLIPY : 0);
1023 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
1024 
1025 	/* it uses sprite_ram[offs + 2] & 0x10 for sprite bank */
1026 	draw_sprites(bitmap, cliprect, 0x10, 3);
1027 	return 0;
1028 }
1029