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