1 // license:BSD-3-Clause
2 // copyright-holders:Aaron Giles
3 /***************************************************************************
4 
5     Sega 16-bit common hardware
6 
7 ****************************************************************************
8 
9     Hang On
10     -------
11         Control Board (834-5668):
12             315-5011       -- sprite line comparitor
13             315-5012       -- sprite generator control
14             315-5049 (x2)  -- tilemaps
15             315-5107 (PAL x2) -- horizontal timing control
16             315-5108       -- vertical timing control
17             315-5122 (PAL) -- timing
18 
19     Enduro Racer
20     ------------
21         CPU Side (171-5319):
22             315-5164 (PAL)
23             315-5165 (PAL)
24             315-5166 (PAL)
25             315-5167 (PAL)
26 
27         Video Side (171-5320):
28             315-5049 (x2)  -- tilemaps
29             315-5011       -- sprite line comparitor
30             315-5012       -- sprite generator control
31             315-5106 (PAL)
32             315-5107 (PAL)
33             315-5108 (PAL)
34             315-5168 (PAL)
35             315-5170 (PAL)
36             315-5171 (PAL)
37             315-5172 (PAL)
38 
39     Pre-System 16
40     -------------
41         Main Board (171-5335):
42             315-5011       -- sprite line comparitor
43             315-5012       -- sprite generator control
44             315-5049 (x2)  -- tilemaps
45             315-5107 (PAL) -- display timing
46             315-5108 (PAL) -- display timing
47             315-5141 (PAL) -- Z80 address decoding
48             315-5143 (PAL) -- sprite-related?
49             315-5144 (PAL) -- sprite-related?
50             315-5147 (PAL) -- unknown, DTACK-related
51             315-5149 (PAL) -- video mixing
52             315-5193 (PAL) -- 68000/MCU interface & address decoding
53             315-5202 (PAL) -- 68000/MCU interface & address decoding
54 
55     Sega System 16A
56     ---------------
57         Bottom Board (171-5307):
58             315-5011       -- sprite line comparitor
59             315-5012       -- sprite generator control
60             315-5049 (x2)  -- tilemaps
61             315-5107 (PAL) -- display timing
62             315-5108 (PAL) -- display timing
63             315-5143 (PAL) -- sprite-related?
64             315-5144 (PAL) -- sprite-related?
65             315-5145 (PAL)
66 
67         Top Board (171-5306):
68             315-5141 (PAL) -- Z80 address decoding
69             315-5142 (PAL)
70             315-5149 (PAL) -- video mixing
71             315-5150 (PAL)
72 
73     Sega System 16B
74     ---------------
75         Main Board (171-5357):
76             315-5195       -- memory mapper
77             315-5196       -- sprite generator
78             315-5197       -- tilemap generator
79             315-5213 (PAL) -- sprite-related
80             315-5214 (PAL) -- unknown
81 
82         ROM Board (171-5521):
83             315-5298 (PAL)
84 
85         ROM Board (171-5704):
86             315-5298 (PAL)
87 
88         ROM Board (171-5797):
89             315-5248       -- hardware multiplier
90             315-5250       -- compare/timer
91             315-5298 (PAL)
92 
93     Sega System 18
94     --------------
95         Main Board (171-5873B):
96             315-5242       -- color encoder
97             315-5296       -- I/O chip
98             315-5313       -- VDP
99             315-5360       -- memory mapper?
100             315-5361       -- sprite generator
101             315-5362       -- tilemap generator
102             315-5373 (PAL) -- video mixing
103             315-5374 (PAL) -- sprite timing
104             315-5375 (PAL) -- system timing
105             315-5389 (PAL) -- VDP sync
106             315-5390 (PAL)
107             315-5391 (PAL) -- Z80 address decoding
108 
109         Main Board (171-5873-02B):
110             315-5242       -- color encoder
111             315-5296       -- I/O chip
112             315-5313       -- VDP
113             315-5360       -- memory mapper?
114             315-5361       -- sprite generator
115             315-5362       -- tilemap generator
116             315-5374 (PAL) -- sprite timing
117             315-5375 (PAL) -- system timing
118             315-5389 (PAL) -- VDP sync
119             315-5391 (PAL) -- Z80 address decoding
120             315-5430 (PAL) -- video mixing
121 
122         ROM Board (171-5987A):
123             315-5436       -- tile/sprite banking
124 
125     Sega System C
126     -------------
127         Main Board:
128             315-5242       -- color encoder
129             315-5296       -- I/O chip
130             315-5313       -- VDP
131             315-5393 (PAL)
132             315-5394 (PAL)
133             315-5395 (PAL)
134 
135     Super Hang On
136     -------------
137         CPU Board 171-5376-01:
138             315-5195       -- memory mapper
139             315-5218       -- PCM sound controller
140             315-5155 (PAL x2) -- road bit extraction
141             315-5222 (PAL) -- road mixing
142             315-5223a (PAL)
143             315-5224 (PAL)
144             315-5225 (PAL)
145             315-5226 (PAL)
146 
147         VIDEO Board: (not the same as out run !) 171-5480
148             315-5196       -- sprite generator
149             315-5197       -- tilemap generator
150             315-5213 (PAL) -- sprite-related
151             315-5242       -- color encoder
152             315-5251 (PAL)
153 
154     Out Run
155     -------
156         CPU Board 837-6063-01:
157             315-5195       -- memory mapper
158             315-5218       -- PCM sound controller
159             315-5155 (PAL x2) -- road bit extraction
160             315-5222 (PAL) -- road mixing
161             315-5223a (PAL)
162             315-5224 (PAL)
163             315-5225 (PAL)
164             315-5226 (PAL)
165 
166         VIDEO Board: 837-6064, 171-5377-01
167             315-5197       -- tilemap generator
168             315-5211       -- sprite generator
169             315-5227a (PAL)
170             315-5228 (PAL)
171             315-5242       -- color encoder
172 
173     Sega System 32
174     --------------
175         Main Board (317-5964):
176             315-5242       -- color encoder
177             315-5296       -- I/O chip
178             315-5385
179             315-5386       -- tilemap generator
180             315-5387       -- sprite generator
181             315-5388       -- video mixing
182             315-5441 (PAL)
183             315-5476
184 
185     X-Board
186     -------
187         Main Board:
188             315-5197       -- tilemap generator
189             315-5211A      -- sprite generator
190             315-5218       -- PCM sound controller
191             315-5242       -- color encoder
192             315-5248 (x2)  -- hardware multiplier
193             315-5249 (x2)  -- hardware divider
194             315-5250 (x2)  -- compare/timer
195             315-5275       -- road generator
196             315-5278 (PAL) -- sprite ROM bank control
197             315-5279 (PAL) -- video mixing (Afterburner)
198             315-5280 (PAL) -- Z80 address decoding
199             315-5290 (PAL) -- main CPU address decoding
200             315-5291 (PAL) -- main CPU address decoding
201             315-5304 (PAL) -- video mixing (Line of Fire)
202 
203     Y-Board
204     -------
205         Main Board (837-6565):
206             315-5218       -- PCM sound controller
207             315-5248 (x3)  -- hardware multiplier
208             315-5249 (x3)  -- hardware divider
209             315-5280 (PAL) -- Z80 address decoding
210             315-5296       -- I/O chip
211             315-5314 (PAL)
212             315-5315 (PAL)
213             315-5316 (PAL)
214             315-5317 (PAL)
215             315-5318 (PAL)
216             315-5328 (PAL)
217 
218         Video Board (837-6566):
219             315-5196       -- sprite generator
220             315-5213 (PAL) -- sprite-related
221             315-5242       -- color encoder
222             315-5305       -- sprite generator
223             315-5306 (x2)  -- video sync and rotation
224             315-5312       -- video mixing
225             315-5319 (PAL)
226             315-5325 (PAL)
227 
228 
229     Custom parts
230     ------------
231                    SYS1  SYS2  HANG  ENDU  PR16  S16A  S16B  SY18  SHNG  ORUN  XBRD  YBRD  SYSC  SY24  SY32
232         315-5011:   xx    xx    xx    xx    xx    xx                                                         -- sprite line comparitor
233         315-5012:   xx    xx    xx    xx    xx    xx                                                         -- sprite generator control
234         315-5049:         xx    x2    x2    x2    x2                                                         -- tilemap generator
235         315-5195:                                       xx          xx    xx                                 -- memory mapper
236         315-5196:                                       xx          xx                xx                     -- sprite genereator
237         315-5197:                                       xx          xx    xx    xx                           -- tilemap generator
238         315-5211:                                                         xx                                 -- sprite generator
239         315-5211A:                                                              xx                           -- sprite generator
240         315-5218:                                                   xx    xx    xx    xx                     -- PCM sound controller
241         315-5242:                                             xx    xx    xx    xx    xx    xx    xx    xx   -- color encoder
242         315-5248:                                       xx                      x2    x3                     -- hardware multiplier
243         315-5249:                                                               x2    x3                     -- hardware divider
244         315-5250:                                       xx                      x2                           -- compare/timer
245         315-5275:                                                               xx                           -- road generator
246         315-5296:                                             xx                      xx    xx          xx   -- I/O chip
247         315-5305:                                                                     xx                     --
248         315-5312:                                                                     xx                     -- video mixing
249         315-5313:                                             xx                            xx               -- VDP
250         315-5360:                                             xx                                             -- memory mapper
251         315-5361:                                             xx                                             -- sprite generator
252         315-5362:                                             xx                                             -- tilemap generator
253         315-5385:                                                                                       xx   -- ???
254         315-5386:                                                                                       xx   -- tilemap generator
255         315-5387:                                                                                       xx   -- sprite generator
256         315-5388:                                                                                       xx   -- video mixing
257         315-5436:                                             xx                                             -- sprite/tile banking
258         315-5476:                                                                                       xx   -- ????
259 
260 ****************************************************************************
261 
262   Sega system16 and friends hardware
263 
264                CPU      Tiles      Sprites   Priority  Color     SCPU  Sound                Other
265 System C       68000    315-5313                       315-5242  z80   ym3438               315-5296(IO)
266 Space Harrier  68000x2                                 (c)       z80   ym2203 pcm(b)
267 System 16B     68000    315-5197   315-5196  GAL       (c)       z80   ym2151 upd7759       315-5195
268 After Burner   68000x2  315-5197   315-5211A GAL       315-5242  z80   ym2151 315-5218      315-5250(a) 315-5248(x2) 315-5249(x2) 315-5275(road)
269 System 18      68000    315-536x   315-536x            315-5242  z80   ym3834(x2) RF5c68(d) 315-3296(IO) 315-5313(vdp)
270 System 24      68000x2  315-5292   315-5293  315-5294  315-5242        ym2151 dac           315-5195(x3) 315-5296(IO)
271 Galaxy Force   68000x3             315-5296+ 315-5312  315-5242  z80   ym2151 315-5218      315-5296(IO)
272 System 32      V60      315-5386A  315-5387  315-5388  315-5242  z80   ym3834(x2) RF5c68(d) 315-5296(IO)
273 
274 a) 315-5250: 68000 glue and address decoding
275 
276 b) 8x8-bit voices entirely in TTL.  The 315-5218 is believed to be the
277    integrated version of that
278 
279 c) Resistor network and latches believed to be equivalent to the 315-5242
280 
281 d) Also seen as 315-5476A and ASSP 5c105 and ASSP 5c68a
282 
283 Quick review of the system16 hardware:
284 
285   Hang-on hardware:
286     The first one.  Two tilemap planes, one sprite plane, one road
287     plane.  The shadow capability doesn't seem to be used, the
288     highlight/shadow switch in the 5242-equivalent is global for all
289     colors.
290 
291   Space harrier hardware:
292     Similar to hang-on, with per-color highlight/shadow selection, and
293     the shadows are used.
294 
295   System16a / Pre-system16:
296     Space harrier without the road generator.
297 
298   System16b:
299     4-layer tilemap hardware in two pairs, with selection between each
300     members on the pairs on a 8-lines basis.  Slightly better sprites.
301 
302   System18
303     System 16b plus a genesis vdp.
304 
305   Outrun:
306     System 16b tilemaps, frame buffered sprites with better zooming
307     capabilities, and a road generator able to handle two roads
308     simultaneously.
309 
310   Super hang-on:
311     Outrun lite, with System 16b sprites instead of the frame buffered
312     sprites, and only one of the two roads is actually used.
313 
314   X-Board:
315     Outrun with a better fillrate and an even more flexible road
316     generator.
317 
318   Y-Board:
319     New design, with two sprite planes and no tilemaps.  The back
320     sprite plane has a huge fillrate and the capability to have its
321     frame buffer completely rotated.  Also, it has a palette
322     indirection capability to allows for easier palette rotations.
323     The front sprite plane is System 16b.
324 
325   System24:
326     The odd one out.  Medium resolution.  Entirely ram-based, no
327     graphics roms.  4-layer tilemap hardware in two pairs, selection
328     on a 8-pixels basis.  Tile-based sprites(!) organised as a linked
329     list.  The tilemap chip has been reused for model1 and model2,
330     probably because they had it handy and it handles medium res.
331 
332   System32:
333     5-layer tilemap hardware consisting of 4 independent rom-based
334     layers with linescroll, lineselection, linezoom and window
335     clipping capability and one simpler ram-based text plane.  Mixed
336     ram/rom sprite engine with palette indirection, per-color priority
337     (thankfully not actually used).  The sprite list includes jumping
338     and clipping capabilities, and advanced hot-spot positioning.  The
339     mixer chip adds totally dynamic priorities, alpha-blending of the
340     tilemaps, per-component color control, and some other funnies we
341     have not been able to decipher.
342 
343   ST-V (also know as Titan or the Saturn console):
344     The ultimate 2D system.  Even more advanced tilemaps, with 6-dof
345     roz support, alpha up to the wazoo and other niceties, known as
346     the vdp2.  The sprite engine, vdp1, allows for any 4-point
347     stretching of the sprites, actually giving polygonal 3D
348     capabilities.  Interestingly, the mixer capabilities took a hit,
349     with no real per-sprite mixer priority, which could be considered
350     annoying for a 2D system.  It still allowed some beauties like
351     Radiant Silvergun.
352 
353 ***************************************************************************/
354 
355 #include "emu.h"
356 #include "segaic16.h"
357 
358 #include "video/resnet.h"
359 #include "screen.h"
360 
361 
362 
363 /*************************************
364  *
365  *  Debugging
366  *
367  *************************************/
368 
369 #define PRINT_UNUSUAL_MODES     (0)
370 
371 
372 
373 
374 
375 
376 //**************************************************************************
377 //  PALETTE HELPERS
378 //**************************************************************************
379 
380 //-------------------------------------------------
381 //  sega_16bit_common_base - constructor
382 //-------------------------------------------------
383 
sega_16bit_common_base(const machine_config & mconfig,device_type type,const char * tag)384 sega_16bit_common_base::sega_16bit_common_base(const machine_config &mconfig, device_type type, const char *tag)
385 	: driver_device(mconfig, type, tag)
386 	, m_paletteram(*this, "paletteram")
387 	, m_palette_entries(0)
388 	, m_palette(*this, "palette")
389 {
390 	palette_init();
391 }
392 
393 
394 //-------------------------------------------------
395 //  palette_init - precompute weighted RGB values
396 //  for each input value 0-31
397 //-------------------------------------------------
398 
palette_init()399 void sega_16bit_common_base::palette_init()
400 {
401 	//
402 	//  Color generation details
403 	//
404 	//  Each color is made up of 5 bits, connected through one or more resistors like so:
405 	//
406 	//  Bit 0 = 1 x 3.9K ohm
407 	//  Bit 1 = 1 x 2.0K ohm
408 	//  Bit 2 = 1 x 1.0K ohm
409 	//  Bit 3 = 2 x 1.0K ohm
410 	//  Bit 4 = 4 x 1.0K ohm
411 	//
412 	//  Another data bit is connected by a tristate buffer to the color output through a
413 	//  470 ohm resistor. The buffer allows the resistor to have no effect (tristate),
414 	//  halve brightness (pull-down) or double brightness (pull-up). The data bit source
415 	//  is bit 15 of each color RAM entry.
416 	//
417 
418 	// compute weight table for regular palette entries
419 	static const int resistances_normal[6] = { 3900, 2000, 1000, 1000/2, 1000/4, 0   };
420 	double weights_normal[6];
421 	compute_resistor_weights(0, 255, -1.0,
422 		6, resistances_normal, weights_normal, 0, 0,
423 		0, nullptr, nullptr, 0, 0,
424 		0, nullptr, nullptr, 0, 0);
425 
426 	// compute weight table for shadow/hilight palette entries
427 	static const int resistances_sh[6]     = { 3900, 2000, 1000, 1000/2, 1000/4, 470 };
428 	double weights_sh[6];
429 	compute_resistor_weights(0, 255, -1.0,
430 		6, resistances_sh, weights_sh, 0, 0,
431 		0, nullptr, nullptr, 0, 0,
432 		0, nullptr, nullptr, 0, 0);
433 
434 	// compute R, G, B for each weight
435 	for (int value = 0; value < 32; value++)
436 	{
437 		const u8 i4 = (value >> 4) & 1;
438 		const u8 i3 = (value >> 3) & 1;
439 		const u8 i2 = (value >> 2) & 1;
440 		const u8 i1 = (value >> 1) & 1;
441 		const u8 i0 = (value >> 0) & 1;
442 		m_palette_normal[value] = combine_weights(weights_normal, i0, i1, i2, i3, i4, 0);
443 		m_palette_shadow[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 0);
444 		m_palette_hilight[value] = combine_weights(weights_sh, i0, i1, i2, i3, i4, 1);
445 	}
446 }
447 
448 
449 //-------------------------------------------------
450 //  paletteram_w - handle writes to palette RAM
451 //-------------------------------------------------
452 
paletteram_w(address_space & space,offs_t offset,uint16_t data,uint16_t mem_mask)453 void sega_16bit_common_base::paletteram_w(address_space &space, offs_t offset, uint16_t data, uint16_t mem_mask)
454 {
455 	// compute the number of entries
456 	if (m_palette_entries == 0)
457 		m_palette_entries = memshare("paletteram")->bytes() / 2;
458 
459 	// get the new value
460 	u16 newval = m_paletteram[offset];
461 	COMBINE_DATA(&newval);
462 	m_paletteram[offset] = newval;
463 
464 	//     byte 0    byte 1
465 	//  sBGR BBBB GGGG RRRR
466 	//  x000 4321 4321 4321
467 	const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e);
468 	const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e);
469 	const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e);
470 
471 	// shadow / hilight toggle bit in palette RAM
472 	rgb_t effects = (newval & 0x8000) ?
473 				rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) :
474 				rgb_t(m_palette_shadow[r],  m_palette_shadow[g],  m_palette_shadow[b]);
475 	m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r],  m_palette_normal[g],  m_palette_normal[b]);
476 	m_palette->set_pen_color(offset + 1 * m_palette_entries, effects);
477 }
478 
hangon_paletteram_w(offs_t offset,uint16_t data,uint16_t mem_mask)479 void sega_16bit_common_base::hangon_paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
480 {
481 	// compute the number of entries
482 	if (m_palette_entries == 0)
483 		m_palette_entries = memshare("paletteram")->bytes() / 2;
484 
485 	// get the new value
486 	u16 newval = m_paletteram[offset];
487 	COMBINE_DATA(&newval);
488 	m_paletteram[offset] = newval;
489 
490 	//     byte 0    byte 1
491 	//  xBGR BBBB GGGG RRRR
492 	//  x000 4321 4321 4321
493 	const u8 r = ((newval >> 12) & 0x01) | ((newval << 1) & 0x1e);
494 	const u8 g = ((newval >> 13) & 0x01) | ((newval >> 3) & 0x1e);
495 	const u8 b = ((newval >> 14) & 0x01) | ((newval >> 7) & 0x1e);
496 
497 	// hangon has external shadow / hilight toggle bit
498 	m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r],  m_palette_normal[g],  m_palette_normal[b]);
499 	m_palette->set_pen_color(offset + 1 * m_palette_entries, m_palette_shadow[r],  m_palette_shadow[g],  m_palette_shadow[b]);
500 	m_palette->set_pen_color(offset + 2 * m_palette_entries, m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]);
501 }
502 
philko_paletteram_w(offs_t offset,uint16_t data,uint16_t mem_mask)503 void sega_16bit_common_base::philko_paletteram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
504 {
505 	// compute the number of entries
506 	if (m_palette_entries == 0)
507 		m_palette_entries = memshare("paletteram")->bytes() / 2;
508 
509 	// get the new value
510 	u16 newval = m_paletteram[offset];
511 	COMBINE_DATA(&newval);
512 	m_paletteram[offset] = newval;
513 
514 	//     byte 0    byte 1
515 	//  sRRR RRGG GGGB BBBB
516 	//  x432 1043 2104 3210
517 	const u8 b = (newval >> 0) & 0x1f;
518 	const u8 g = (newval >> 5) & 0x1f;
519 	const u8 r = (newval >> 10) & 0x1f;
520 
521 	// shadow / hilight toggle bit in palette RAM
522 	rgb_t effects = (newval & 0x8000) ?
523 				rgb_t(m_palette_hilight[r], m_palette_hilight[g], m_palette_hilight[b]) :
524 				rgb_t(m_palette_shadow[r],  m_palette_shadow[g],  m_palette_shadow[b]);
525 	m_palette->set_pen_color(offset + 0 * m_palette_entries, m_palette_normal[r],  m_palette_normal[g],  m_palette_normal[b]);
526 	m_palette->set_pen_color(offset + 1 * m_palette_entries, effects);
527 }
528 
529 
530 
531 DEFINE_DEVICE_TYPE(SEGAIC16VID, segaic16_video_device, "segaic16_video", "Sega 16-bit Video")
532 
segaic16_video_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)533 segaic16_video_device::segaic16_video_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
534 	: device_t(mconfig, SEGAIC16VID, tag, owner, clock)
535 	, device_video_interface(mconfig, *this)
536 	, m_display_enable(0)
537 	, m_tileram(*this, "^tileram")
538 	, m_textram(*this, "^textram")
539 	, m_rotateram(*this, "^rotateram")
540 	, m_pagelatch_cb(*this, DEVICE_SELF, FUNC(segaic16_video_device::tilemap_16b_fill_latch))
541 	, m_gfxdecode(*this, finder_base::DUMMY_TAG)
542 {
543 	memset(m_rotate, 0, sizeof(m_rotate));
544 	memset(m_bg_tilemap, 0, sizeof(m_bg_tilemap));
545 }
546 
device_start()547 void segaic16_video_device::device_start()
548 {
549 	if(!m_gfxdecode->started())
550 		throw device_missing_dependencies();
551 
552 	save_item(NAME(m_display_enable));
553 
554 	m_pagelatch_cb.resolve();
555 }
556 
device_reset()557 void segaic16_video_device::device_reset()
558 {
559 }
560 
561 
562 /*************************************
563  *
564  *  Misc functions
565  *
566  *************************************/
567 
set_display_enable(int enable)568 void segaic16_video_device::set_display_enable(int enable)
569 {
570 	enable = (enable != 0);
571 	if (m_display_enable != enable)
572 	{
573 		screen().update_partial(screen().vpos());
574 		m_display_enable = enable;
575 	}
576 }
577 
578 
579 
580 /*************************************
581  *
582  *  Draw a split tilemap in up to
583  *  four pieces
584  *
585  *************************************/
586 
draw_virtual_tilemap(screen_device & screen,segaic16_video_device::tilemap_info * info,bitmap_ind16 & bitmap,const rectangle & cliprect,uint16_t pages,uint16_t xscroll,uint16_t yscroll,uint32_t flags,uint32_t priority)587 void draw_virtual_tilemap(screen_device &screen, segaic16_video_device::tilemap_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, uint16_t pages, uint16_t xscroll, uint16_t yscroll, uint32_t flags, uint32_t priority)
588 {
589 	int leftmin = -1, leftmax = -1, rightmin = -1, rightmax = -1;
590 	int topmin = -1, topmax = -1, bottommin = -1, bottommax = -1;
591 	rectangle pageclip;
592 	int page;
593 
594 
595 	if (info->flip)
596 	{
597 		pages = bitswap<16>(pages,
598 			3, 2, 1, 0,
599 			7, 6, 5, 4,
600 			11, 10, 9, 8,
601 			15, 14, 13, 12
602 			);
603 
604 	}
605 
606 	int width = screen.visible_area().max_x+1;
607 	int height = screen.visible_area().max_y+1;
608 
609 	/* which half/halves of the virtual tilemap do we intersect in the X direction? */
610 	if (xscroll < 64*8 - width)
611 	{
612 		leftmin = 0;
613 		leftmax = width - 1;
614 		rightmin = -1;
615 	}
616 	else if (xscroll < 64*8)
617 	{
618 		leftmin = 0;
619 		leftmax = 64*8 - xscroll - 1;
620 		rightmin = leftmax + 1;
621 		rightmax = width - 1;
622 	}
623 	else if (xscroll < 128*8 - width)
624 	{
625 		rightmin = 0;
626 		rightmax = width - 1;
627 		leftmin = -1;
628 	}
629 	else
630 	{
631 		rightmin = 0;
632 		rightmax = 128*8 - xscroll - 1;
633 		leftmin = rightmax + 1;
634 		leftmax = width - 1;
635 	}
636 
637 	/* which half/halves of the virtual tilemap do we intersect in the Y direction? */
638 	if (yscroll < 32*8 - height)
639 	{
640 		topmin = 0;
641 		topmax = height - 1;
642 		bottommin = -1;
643 	}
644 	else if (yscroll < 32*8)
645 	{
646 		topmin = 0;
647 		topmax = 32*8 - yscroll - 1;
648 		bottommin = topmax + 1;
649 		bottommax = height - 1;
650 	}
651 	else if (yscroll < 64*8 - height)
652 	{
653 		bottommin = 0;
654 		bottommax = height - 1;
655 		topmin = -1;
656 	}
657 	else
658 	{
659 		bottommin = 0;
660 		bottommax = 64*8 - yscroll - 1;
661 		topmin = bottommax + 1;
662 		topmax = height - 1;
663 	}
664 
665 	// adjust split positions to compensate for flipping
666 	if (info->flip)
667 	{
668 		int temp;
669 		if (bottommin != -1) bottommin = height - 1 - bottommin;
670 		if (bottommax != -1) bottommax = height - 1 - bottommax;
671 		if (topmin != -1) topmin = height - 1 - topmin;
672 		if (topmax != -1) topmax = height - 1 - topmax;
673 
674 		temp = bottommin;
675 		bottommin = topmax;
676 		topmax = temp;
677 
678 		temp = bottommax;
679 		bottommax = topmin;
680 		topmin = temp;
681 
682 		if (leftmin != -1) leftmin = width - 1 - leftmin;
683 		if (leftmax != -1) leftmax = width - 1 - leftmax;
684 		if (rightmin != -1) rightmin = width - 1 - rightmin;
685 		if (rightmax != -1) rightmax = width - 1 - rightmax;
686 
687 		temp = leftmin;
688 		leftmin = rightmax;
689 		rightmax = temp;
690 
691 		temp = leftmax;
692 		leftmax = rightmin;
693 		rightmin = temp;
694 
695 	}
696 
697 	/* draw the upper-left chunk */
698 	if (leftmin != -1 && topmin != -1)
699 	{
700 		pageclip.min_x = (leftmin < cliprect.min_x) ? cliprect.min_x : leftmin;
701 		pageclip.max_x = (leftmax > cliprect.max_x) ? cliprect.max_x : leftmax;
702 		pageclip.min_y = (topmin < cliprect.min_y) ? cliprect.min_y : topmin;
703 		pageclip.max_y = (topmax > cliprect.max_y) ? cliprect.max_y : topmax;
704 		if (pageclip.min_x <= pageclip.max_x && pageclip.min_y <= pageclip.max_y)
705 		{
706 			page = (pages >> 0) & 0xf;
707 			info->tilemaps[page]->set_scrollx(0, xscroll);
708 			info->tilemaps[page]->set_scrolly(0, yscroll);
709 			info->tilemaps[page]->draw(screen, bitmap, pageclip, flags, priority);
710 		}
711 	}
712 
713 	/* draw the upper-right chunk */
714 	if (rightmin != -1 && topmin != -1)
715 	{
716 		pageclip.min_x = (rightmin < cliprect.min_x) ? cliprect.min_x : rightmin;
717 		pageclip.max_x = (rightmax > cliprect.max_x) ? cliprect.max_x : rightmax;
718 		pageclip.min_y = (topmin < cliprect.min_y) ? cliprect.min_y : topmin;
719 		pageclip.max_y = (topmax > cliprect.max_y) ? cliprect.max_y : topmax;
720 		if (pageclip.min_x <= pageclip.max_x && pageclip.min_y <= pageclip.max_y)
721 		{
722 			page = (pages >> 4) & 0xf;
723 			info->tilemaps[page]->set_scrollx(0, xscroll);
724 			info->tilemaps[page]->set_scrolly(0, yscroll);
725 			info->tilemaps[page]->draw(screen, bitmap, pageclip, flags, priority);
726 		}
727 	}
728 
729 	/* draw the lower-left chunk */
730 	if (leftmin != -1 && bottommin != -1)
731 	{
732 		pageclip.min_x = (leftmin < cliprect.min_x) ? cliprect.min_x : leftmin;
733 		pageclip.max_x = (leftmax > cliprect.max_x) ? cliprect.max_x : leftmax;
734 		pageclip.min_y = (bottommin < cliprect.min_y) ? cliprect.min_y : bottommin;
735 		pageclip.max_y = (bottommax > cliprect.max_y) ? cliprect.max_y : bottommax;
736 		if (pageclip.min_x <= pageclip.max_x && pageclip.min_y <= pageclip.max_y)
737 		{
738 			page = (pages >> 8) & 0xf;
739 			info->tilemaps[page]->set_scrollx(0, xscroll);
740 			info->tilemaps[page]->set_scrolly(0, yscroll);
741 			info->tilemaps[page]->draw(screen, bitmap, pageclip, flags, priority);
742 		}
743 	}
744 
745 	/* draw the lower-right chunk */
746 	if (rightmin != -1 && bottommin != -1)
747 	{
748 		pageclip.min_x = (rightmin < cliprect.min_x) ? cliprect.min_x : rightmin;
749 		pageclip.max_x = (rightmax > cliprect.max_x) ? cliprect.max_x : rightmax;
750 		pageclip.min_y = (bottommin < cliprect.min_y) ? cliprect.min_y : bottommin;
751 		pageclip.max_y = (bottommax > cliprect.max_y) ? cliprect.max_y : bottommax;
752 		if (pageclip.min_x <= pageclip.max_x && pageclip.min_y <= pageclip.max_y)
753 		{
754 			page = (pages >> 12) & 0xf;
755 			info->tilemaps[page]->set_scrollx(0, xscroll);
756 			info->tilemaps[page]->set_scrolly(0, yscroll);
757 			info->tilemaps[page]->draw(screen, bitmap, pageclip, flags, priority);
758 		}
759 	}
760 }
761 
762 
763 
764 /*******************************************************************************************
765  *
766  *  Hang On/System 16A-style tilemaps
767  *
768  *  4 total pages (Hang On)
769  *  8 total pages (System 16A)
770  *  Column/rowscroll enabled via external signals
771  *
772  *  Tile format:
773  *      Bits               Usage
774  *      ??------ --------  Unknown
775  *      --b----- --------  Tile bank select
776  *      ---p---- --------  Tile priority versus sprites
777  *      ----cccc ccc-----  Tile color palette
778  *      ----nnnn nnnnnnnn  Tile index
779  *
780  *  Text format:
781  *      Bits               Usage
782  *      ????---- --------  Unknown
783  *      ----p--- --------  Priority
784  *      -----ccc --------  Tile color palette
785  *      -------- nnnnnnnn  Tile index
786  *
787  *  Text RAM:
788  *      Offset   Bits               Usage
789  *      E8C      -aaa-bbb -ccc-ddd  Background tilemap page select (screen flipped)
790  *      E8E      -aaa-bbb -ccc-ddd  Foreground tilemap page select (screen flipped)
791  *      E9C      -aaa-bbb -ccc-ddd  Background tilemap page select
792  *      E9E      -aaa-bbb -ccc-ddd  Foreground tilemap page select
793  *      F24      -------- vvvvvvvv  Foreground tilemap vertical scroll
794  *      F26      -------- vvvvvvvv  Background tilemap vertical scroll
795  *      F30-F7D  -------- vvvvvvvv  Foreground tilemap per-16-pixel-column vertical scroll (every 2 words)
796  *      F32-F7F  -------- vvvvvvvv  Background tilemap per-16-pixel-column vertical scroll (every 2 words)
797  *      F80-FED  -------h hhhhhhhh  Foreground tilemap per-8-pixel-row horizontal scroll (every 2 words)
798  *      F82-FEF  -------h hhhhhhhh  Background tilemap per-8-pixel-row horizontal scroll (every 2 words)
799  *      FF8      -------h hhhhhhhh  Foreground tilemap horizontal scroll
800  *      FFA      -------h hhhhhhhh  Background tilemap horizontal scroll
801  *
802  *******************************************************************************************/
803 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16a_tile_info)804 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16a_tile_info )
805 {
806 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
807 	uint16_t data = info->rambase[tile_index];
808 	int code = ((data >> 1) & 0x1000) | (data & 0xfff);
809 	int color = (data >> 5) & 0x7f;
810 
811 	tileinfo.set(0, code, color, 0);
812 	tileinfo.category = (data >> 12) & 1;
813 }
814 
815 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16a_text_info)816 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16a_text_info )
817 {
818 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
819 	uint16_t data = info->rambase[tile_index];
820 	int color = (data >> 8) & 0x07;
821 	int code = data & 0xff;
822 
823 	tileinfo.set(0, code, color, 0);
824 	tileinfo.category = (data >> 11) & 1;
825 }
826 
827 
tilemap_16a_draw_layer(screen_device & screen,segaic16_video_device::tilemap_info * info,bitmap_ind16 & bitmap,const rectangle & cliprect,int which,int flags,int priority)828 static void tilemap_16a_draw_layer(screen_device &screen, segaic16_video_device::tilemap_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int flags, int priority)
829 {
830 	uint16_t *textram = info->textram;
831 
832 	/* note that the scrolling for these games can only scroll as much as the top-left */
833 	/* page; in order to scroll beyond that they swap pages and reset the scroll value */
834 	uint16_t xscroll = textram[0xff8/2 + which] & 0x1ff;
835 	uint16_t yscroll = textram[0xf24/2 + which] & 0x0ff;
836 	uint16_t pages = textram[(info->flip ? 0xe8e/2 : 0xe9e/2) - which];
837 	int x, y;
838 
839 	/* pages are swapped along the X direction, and there are only 8 of them */
840 	pages = ((pages >> 4) & 0x0707) | ((pages << 4) & 0x7070);
841 	if (info->numpages == 4)
842 		pages &= 0x3333;
843 
844 	/* column AND row scroll */
845 	if (info->colscroll && info->rowscroll)
846 	{
847 		if (PRINT_UNUSUAL_MODES) osd_printf_debug("Column AND row scroll\n");
848 
849 		/* loop over row chunks */
850 		for (y = cliprect.min_y & ~7; y <= cliprect.max_y; y += 8)
851 		{
852 			int rowscrollindex = (info->flip ? (216 - y) : y) / 8;
853 			rectangle rowcolclip;
854 
855 			/* adjust to clip this row only */
856 			rowcolclip.min_y = (y < cliprect.min_y) ? cliprect.min_y : y;
857 			rowcolclip.max_y = (y + 7 > cliprect.max_y) ? cliprect.max_y : y + 7;
858 
859 			/* loop over column chunks */
860 			for (x = cliprect.min_x & ~15; x <= cliprect.max_x; x += 16)
861 			{
862 				uint16_t effxscroll, effyscroll;
863 
864 				/* adjust to clip this column only */
865 				rowcolclip.min_x = (x < cliprect.min_x) ? cliprect.min_x : x;
866 				rowcolclip.max_x = (x + 15 > cliprect.max_x) ? cliprect.max_x : x + 15;
867 
868 				/* get the effective scroll values */
869 				effxscroll = textram[0xf80/2 + rowscrollindex * 2 + which] & 0x1ff;
870 				effyscroll = textram[0xf30/2 + (x/16) * 2 + which] & 0x0ff;
871 
872 				/* adjust the xscroll for flipped screen */
873 				if (info->flip)
874 					effxscroll += 17;
875 
876 				/* draw the chunk */
877 				effxscroll = (0xc8 - effxscroll + info->xoffs) & 0x3ff;
878 				effyscroll = effyscroll & 0x1ff;
879 				draw_virtual_tilemap(screen, info, bitmap, rowcolclip, pages, effxscroll, effyscroll, flags, priority);
880 			}
881 		}
882 	}
883 	else if (info->colscroll)
884 	{
885 		if (PRINT_UNUSUAL_MODES) osd_printf_debug("Column scroll\n");
886 
887 		/* loop over column chunks */
888 		for (x = cliprect.min_x & ~15; x <= cliprect.max_x; x += 16)
889 		{
890 			rectangle colclip = cliprect;
891 			uint16_t effxscroll, effyscroll;
892 
893 			/* adjust to clip this row only */
894 			colclip.min_x = (x < cliprect.min_x) ? cliprect.min_x : x;
895 			colclip.max_x = (x + 15 > cliprect.max_x) ? cliprect.max_x : x + 15;
896 
897 			/* get the effective scroll values */
898 			effxscroll = xscroll;
899 			effyscroll = textram[0xf30/2 + (x/16) * 2 + which] & 0x0ff;
900 
901 			/* adjust the xscroll for flipped screen */
902 			if (info->flip)
903 				effxscroll += 17;
904 
905 			/* draw the chunk */
906 			effxscroll = (0xc8 - effxscroll + info->xoffs) & 0x3ff;
907 			effyscroll = effyscroll & 0x1ff;
908 			draw_virtual_tilemap(screen, info, bitmap, colclip, pages, effxscroll, effyscroll, flags, priority);
909 		}
910 	}
911 	else if (info->rowscroll)
912 	{
913 		if (PRINT_UNUSUAL_MODES) osd_printf_debug("Row scroll\n");
914 
915 		/* loop over row chunks */
916 		for (y = cliprect.min_y & ~7; y <= cliprect.max_y; y += 8)
917 		{
918 			int rowscrollindex = (info->flip ? (216 - y) : y) / 8;
919 			rectangle rowclip = cliprect;
920 			uint16_t effxscroll, effyscroll;
921 
922 			/* adjust to clip this row only */
923 			rowclip.min_y = (y < cliprect.min_y) ? cliprect.min_y : y;
924 			rowclip.max_y = (y + 7 > cliprect.max_y) ? cliprect.max_y : y + 7;
925 
926 			/* get the effective scroll values */
927 			effxscroll = textram[0xf80/2 + rowscrollindex * 2 + which] & 0x1ff;
928 			effyscroll = yscroll;
929 
930 			/* adjust the xscroll for flipped screen */
931 			if (info->flip)
932 				effxscroll += 17;
933 
934 			/* draw the chunk */
935 			effxscroll = (0xc8 - effxscroll + info->xoffs) & 0x3ff;
936 			effyscroll = effyscroll & 0x1ff;
937 			draw_virtual_tilemap(screen, info, bitmap, rowclip, pages, effxscroll, effyscroll, flags, priority);
938 		}
939 	}
940 	else
941 	{
942 		/* adjust the xscroll for flipped screen */
943 		if (info->flip)
944 			xscroll += 17;
945 		xscroll = (0xc8 - xscroll + info->xoffs) & 0x3ff;
946 		yscroll = yscroll & 0x1ff;
947 		draw_virtual_tilemap(screen, info, bitmap, cliprect, pages, xscroll, yscroll, flags, priority);
948 	}
949 }
950 
951 
952 
953 /*******************************************************************************************
954  *
955  *  System 16B-style tilemaps
956  *
957  *  16 total pages
958  *  Column/rowscroll enabled via bits in text layer
959  *  Alternate tilemap support
960  *
961  *  Tile format:
962  *      Bits               Usage
963  *      p------- --------  Tile priority versus sprites
964  *      -??----- --------  Unknown
965  *      ---ccccc cc------  Tile color palette
966  *      ---nnnnn nnnnnnnn  Tile index
967  *
968  *  Text format:
969  *      Bits               Usage
970  *      p------- --------  Tile priority versus sprites
971  *      -???---- --------  Unknown
972  *      ----ccc- --------  Tile color palette
973  *      -------n nnnnnnnn  Tile index
974  *
975  *  Alternate tile format:
976  *      Bits               Usage
977  *      p------- --------  Tile priority versus sprites
978  *      -??----- --------  Unknown
979  *      ----cccc ccc-----  Tile color palette
980  *      ---nnnnn nnnnnnnn  Tile index
981  *
982  *  Alternate text format:
983  *      Bits               Usage
984  *      p------- --------  Tile priority versus sprites
985  *      -???---- --------  Unknown
986  *      -----ccc --------  Tile color palette
987  *      -------- nnnnnnnn  Tile index
988  *
989  *  Text RAM:
990  *      Offset   Bits               Usage
991  *      E80      aaaabbbb ccccdddd  Foreground tilemap page select
992  *      E82      aaaabbbb ccccdddd  Background tilemap page select
993  *      E84      aaaabbbb ccccdddd  Alternate foreground tilemap page select
994  *      E86      aaaabbbb ccccdddd  Alternate background tilemap page select
995  *      E90      c------- --------  Foreground tilemap column scroll enable
996  *               -------v vvvvvvvv  Foreground tilemap vertical scroll
997  *      E92      c------- --------  Background tilemap column scroll enable
998  *               -------v vvvvvvvv  Background tilemap vertical scroll
999  *      E94      -------v vvvvvvvv  Alternate foreground tilemap vertical scroll
1000  *      E96      -------v vvvvvvvv  Alternate background tilemap vertical scroll
1001  *      E98      r------- --------  Foreground tilemap row scroll enable
1002  *               ------hh hhhhhhhh  Foreground tilemap horizontal scroll
1003  *      E9A      r------- --------  Background tilemap row scroll enable
1004  *               ------hh hhhhhhhh  Background tilemap horizontal scroll
1005  *      E9C      ------hh hhhhhhhh  Alternate foreground tilemap horizontal scroll
1006  *      E9E      ------hh hhhhhhhh  Alternate background tilemap horizontal scroll
1007  *      F16-F3F  -------- vvvvvvvv  Foreground tilemap per-16-pixel-column vertical scroll
1008  *      F56-F7F  -------- vvvvvvvv  Background tilemap per-16-pixel-column vertical scroll
1009  *      F80-FB7  a------- --------  Foreground tilemap per-8-pixel-row alternate tilemap enable
1010  *               -------h hhhhhhhh  Foreground tilemap per-8-pixel-row horizontal scroll
1011  *      FC0-FF7  a------- --------  Background tilemap per-8-pixel-row alternate tilemap enable
1012  *               -------h hhhhhhhh  Background tilemap per-8-pixel-row horizontal scroll
1013  *
1014  *******************************************************************************************/
1015 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16b_tile_info)1016 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16b_tile_info )
1017 {
1018 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
1019 	uint16_t data = info->rambase[tile_index];
1020 	int color = (data >> 6) & 0x7f;
1021 	int code = data & 0x1fff;
1022 
1023 	code = info->bank[code / info->banksize] * info->banksize + code % info->banksize;
1024 
1025 	tileinfo.set(0, code, color, 0);
1026 	tileinfo.category = (data >> 15) & 1;
1027 }
1028 
1029 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16b_text_info)1030 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16b_text_info )
1031 {
1032 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
1033 	uint16_t data = info->rambase[tile_index];
1034 	int bank = info->bank[0];
1035 	int color = (data >> 9) & 0x07;
1036 	int code = data & 0x1ff;
1037 
1038 	tileinfo.set(0, bank * info->banksize + code, color, 0);
1039 	tileinfo.category = (data >> 15) & 1;
1040 }
1041 
1042 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16b_alt_tile_info)1043 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16b_alt_tile_info )
1044 {
1045 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
1046 	uint16_t data = info->rambase[tile_index];
1047 	int color = (data >> 5) & 0x7f;
1048 	int code = data & 0x1fff;
1049 
1050 	code = info->bank[code / info->banksize] * info->banksize + code % info->banksize;
1051 
1052 	tileinfo.set(0, code, color, 0);
1053 	tileinfo.category = (data >> 15) & 1;
1054 }
1055 
1056 
TILE_GET_INFO_MEMBER(segaic16_video_device::tilemap_16b_alt_text_info)1057 TILE_GET_INFO_MEMBER( segaic16_video_device::tilemap_16b_alt_text_info )
1058 {
1059 	const struct tilemap_callback_info *info = (const struct tilemap_callback_info *)tilemap.user_data();
1060 	uint16_t data = info->rambase[tile_index];
1061 	int bank = info->bank[0];
1062 	int color = (data >> 8) & 0x07;
1063 	int code = data & 0xff;
1064 
1065 	tileinfo.set(0, bank * info->banksize + code, color, 0);
1066 	tileinfo.category = (data >> 15) & 1;
1067 }
1068 
1069 
tilemap_16b_draw_layer(screen_device & screen,segaic16_video_device::tilemap_info * info,bitmap_ind16 & bitmap,const rectangle & cliprect,int which,int flags,int priority)1070 static void tilemap_16b_draw_layer(screen_device &screen, segaic16_video_device::tilemap_info *info, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int flags, int priority)
1071 {
1072 	uint16_t *textram = info->textram;
1073 	uint16_t xscroll, yscroll, pages;
1074 	int x, y;
1075 
1076 	/* get global values */
1077 	xscroll = info->latched_xscroll[which];
1078 	yscroll = info->latched_yscroll[which];
1079 	pages = info->latched_pageselect[which];
1080 
1081 	/* column scroll? */
1082 	if (yscroll & 0x8000)
1083 	{
1084 		if (PRINT_UNUSUAL_MODES) osd_printf_debug("Column AND row scroll\n");
1085 
1086 		/* loop over row chunks */
1087 		for (y = cliprect.min_y & ~7; y <= cliprect.max_y; y += 8)
1088 		{
1089 			int rowscrollindex = (info->flip ? (216 - y) : y) / 8;
1090 			rectangle rowcolclip;
1091 
1092 			/* adjust to clip this row only */
1093 			rowcolclip.min_y = (y < cliprect.min_y) ? cliprect.min_y : y;
1094 			rowcolclip.max_y = (y + 7 > cliprect.max_y) ? cliprect.max_y : y + 7;
1095 
1096 			/* loop over column chunks */
1097 			for (x = ((cliprect.min_x + 8) & ~15) - 8; x <= cliprect.max_x; x += 16)
1098 			{
1099 				uint16_t effxscroll, effyscroll, rowscroll;
1100 				uint16_t effpages = pages;
1101 
1102 				/* adjust to clip this column only */
1103 				rowcolclip.min_x = (x < cliprect.min_x) ? cliprect.min_x : x;
1104 				rowcolclip.max_x = (x + 15 > cliprect.max_x) ? cliprect.max_x : x + 15;
1105 
1106 				/* get the effective scroll values */
1107 				rowscroll = textram[0xf80/2 + 0x40/2 * which + rowscrollindex];
1108 				effxscroll = (xscroll & 0x8000) ? rowscroll : xscroll;
1109 				effyscroll = textram[0xf16/2 + 0x40/2 * which + (x+8)/16];
1110 
1111 				/* are we using an alternate? */
1112 				if (rowscroll & 0x8000)
1113 				{
1114 					effxscroll = info->latched_xscroll[which + 2];
1115 					effyscroll = info->latched_yscroll[which + 2];
1116 					effpages = info->latched_pageselect[which + 2];
1117 				}
1118 
1119 				/* draw the chunk */
1120 				effxscroll = (0xc0 - effxscroll + info->xoffs) & 0x3ff;
1121 				effyscroll = effyscroll & 0x1ff;
1122 				draw_virtual_tilemap(screen, info, bitmap, rowcolclip, effpages, effxscroll, effyscroll, flags, priority);
1123 			}
1124 		}
1125 	}
1126 	else
1127 	{
1128 		if (PRINT_UNUSUAL_MODES) osd_printf_debug("Row scroll\n");
1129 
1130 		/* loop over row chunks */
1131 		for (y = cliprect.min_y & ~7; y <= cliprect.max_y; y += 8)
1132 		{
1133 			int rowscrollindex = (info->flip ? (216 - y) : y) / 8;
1134 			rectangle rowclip = cliprect;
1135 			uint16_t effxscroll, effyscroll, rowscroll;
1136 			uint16_t effpages = pages;
1137 
1138 			/* adjust to clip this row only */
1139 			rowclip.min_y = (y < cliprect.min_y) ? cliprect.min_y : y;
1140 			rowclip.max_y = (y + 7 > cliprect.max_y) ? cliprect.max_y : y + 7;
1141 
1142 			/* get the effective scroll values */
1143 			rowscroll = textram[0xf80/2 + 0x40/2 * which + rowscrollindex];
1144 			effxscroll = (xscroll & 0x8000) ? rowscroll : xscroll;
1145 			effyscroll = yscroll;
1146 
1147 			/* are we using an alternate? */
1148 			if (rowscroll & 0x8000)
1149 			{
1150 				effxscroll = info->latched_xscroll[which + 2];
1151 				effyscroll = info->latched_yscroll[which + 2];
1152 				effpages = info->latched_pageselect[which + 2];
1153 			}
1154 
1155 			/* draw the chunk */
1156 			effxscroll = (0xc0 - effxscroll + info->xoffs) & 0x3ff;
1157 			effyscroll = effyscroll & 0x1ff;
1158 			draw_virtual_tilemap(screen, info, bitmap, rowclip, effpages, effxscroll, effyscroll, flags, priority);
1159 		}
1160 	}
1161 }
1162 
1163 
1164 
1165 
tilemap_16b_fill_latch(int i,uint16_t * latched_pageselect,uint16_t * latched_yscroll,uint16_t * latched_xscroll,uint16_t * textram)1166 void segaic16_video_device::tilemap_16b_fill_latch(int i, uint16_t* latched_pageselect, uint16_t* latched_yscroll, uint16_t* latched_xscroll, uint16_t* textram)
1167 {
1168 	latched_pageselect[i] = textram[0xe80 / 2 + i];
1169 	latched_yscroll[i] = textram[0xe90/2 + i];
1170 	latched_xscroll[i] = textram[0xe98/2 + i];
1171 //  printf("%02x returning latched page select %04x scrollx %04x scrolly %04x\n", i, latched_pageselect[i], latched_xscroll[i], latched_yscroll[i]);
1172 }
1173 
TIMER_CALLBACK_MEMBER(segaic16_video_device::tilemap_16b_latch_values)1174 TIMER_CALLBACK_MEMBER( segaic16_video_device::tilemap_16b_latch_values )
1175 {
1176 	struct tilemap_info *info = &m_bg_tilemap[param];
1177 	uint16_t *textram = info->textram;
1178 	int i;
1179 
1180 	/* latch the scroll and page select values */
1181 	for (i = 0; i < 4; i++)
1182 	{
1183 		m_pagelatch_cb(i, info->latched_pageselect, info->latched_yscroll, info->latched_xscroll, textram);
1184 	}
1185 
1186 	/* set a timer to do this again next frame */
1187 	info->latch_timer->adjust(screen().time_until_pos(261), param);
1188 }
1189 
1190 
tilemap_16b_reset(screen_device & screen,segaic16_video_device::tilemap_info * info)1191 static void tilemap_16b_reset(screen_device &screen, segaic16_video_device::tilemap_info *info)
1192 {
1193 	/* set a timer to latch values on scanline 261 */
1194 	info->latch_timer->adjust(screen.time_until_pos(261), info->index);
1195 }
1196 
1197 
1198 
1199 /*************************************
1200  *
1201  *  General tilemap initialization
1202  *
1203  *************************************/
1204 
tilemap_init(int which,int type,int colorbase,int xoffs,int numbanks)1205 void segaic16_video_device::tilemap_init(int which, int type, int colorbase, int xoffs, int numbanks)
1206 {
1207 	struct tilemap_info *info = &m_bg_tilemap[which];
1208 	tilemap_get_info_delegate get_text_info(*this);
1209 	tilemap_get_info_delegate get_tile_info(*this);
1210 	int pagenum;
1211 	int i;
1212 
1213 	/* reset the tilemap info */
1214 	memset(info, 0, sizeof(*info));
1215 	info->index = which;
1216 	info->type = type;
1217 	for (i = 0; i < numbanks; i++)
1218 		info->bank[i] = i;
1219 	info->banksize = 0x2000 / numbanks;
1220 	info->xoffs = xoffs;
1221 
1222 	/* set up based on which tilemap */
1223 	switch (which)
1224 	{
1225 		case 0:
1226 			info->textram = m_textram;
1227 			info->tileram = m_tileram;
1228 			break;
1229 
1230 		default:
1231 			fatalerror("Invalid tilemap index specified in tilemap_init\n");
1232 	}
1233 
1234 	/* determine the parameters of the tilemaps */
1235 	switch (type)
1236 	{
1237 		case TILEMAP_HANGON:
1238 			get_text_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16a_text_info));
1239 			get_tile_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16a_tile_info));
1240 			info->numpages = 4;
1241 			info->draw_layer = tilemap_16a_draw_layer;
1242 			info->reset = nullptr;
1243 			info->latch_timer = nullptr;
1244 			break;
1245 
1246 		case TILEMAP_16A:
1247 			get_text_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16a_text_info));
1248 			get_tile_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16a_tile_info));
1249 			info->numpages = 8;
1250 			info->draw_layer = tilemap_16a_draw_layer;
1251 			info->reset = nullptr;
1252 			info->latch_timer = nullptr;
1253 			break;
1254 
1255 		case TILEMAP_16B:
1256 			get_text_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16b_text_info));
1257 			get_tile_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16b_tile_info));
1258 			info->numpages = 16;
1259 			info->draw_layer = tilemap_16b_draw_layer;
1260 			info->reset = tilemap_16b_reset;
1261 			info->latch_timer = machine().scheduler().timer_alloc( timer_expired_delegate(FUNC(segaic16_video_device::tilemap_16b_latch_values),this) );
1262 			break;
1263 
1264 		case TILEMAP_16B_ALT:
1265 			get_text_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16b_alt_text_info));
1266 			get_tile_info = tilemap_get_info_delegate(*this, FUNC(segaic16_video_device::tilemap_16b_alt_tile_info));
1267 			info->numpages = 16;
1268 			info->draw_layer = tilemap_16b_draw_layer;
1269 			info->reset = tilemap_16b_reset;
1270 			info->latch_timer = machine().scheduler().timer_alloc( timer_expired_delegate(FUNC(segaic16_video_device::tilemap_16b_latch_values),this) );
1271 			break;
1272 
1273 		default:
1274 			fatalerror("Invalid tilemap type specified in tilemap_init\n");
1275 	}
1276 
1277 	/* create the tilemap for the text layer */
1278 	info->textmap = &machine().tilemap().create(*m_gfxdecode, get_text_info, TILEMAP_SCAN_ROWS, 8,8, 64,28);
1279 
1280 	/* configure it */
1281 	info->textmap_info.rambase = info->textram;
1282 	info->textmap_info.bank = info->bank;
1283 	info->textmap_info.banksize = info->banksize;
1284 	info->textmap->set_user_data(&info->textmap_info);
1285 	info->textmap->set_palette_offset(colorbase);
1286 	info->textmap->set_transparent_pen(0);
1287 	info->textmap->set_scrolldx(-192 + xoffs, -192 + xoffs);
1288 	info->textmap->set_scrolldy(0, 0);
1289 
1290 	/* create the tilemaps for the tile pages */
1291 	for (pagenum = 0; pagenum < info->numpages; pagenum++)
1292 	{
1293 		/* each page is 64x32 */
1294 		info->tilemaps[pagenum] = &machine().tilemap().create(*m_gfxdecode, get_tile_info, TILEMAP_SCAN_ROWS, 8,8, 64,32);
1295 
1296 		/* configure the tilemap */
1297 		info->tmap_info[pagenum].rambase = info->tileram + pagenum * 64*32;
1298 		info->tmap_info[pagenum].bank = info->bank;
1299 		info->tmap_info[pagenum].banksize = info->banksize;
1300 		info->tilemaps[pagenum]->set_user_data(&info->tmap_info[pagenum]);
1301 		info->tilemaps[pagenum]->set_palette_offset(colorbase);
1302 		info->tilemaps[pagenum]->set_transparent_pen(0);
1303 		info->tilemaps[pagenum]->set_scrolldx(0, 0);
1304 		info->tilemaps[pagenum]->set_scrolldy(0, 0);
1305 	}
1306 
1307 	save_item(NAME(info->flip), which);
1308 	save_item(NAME(info->rowscroll), which);
1309 	save_item(NAME(info->colscroll), which);
1310 	save_item(NAME(info->bank), which);
1311 	save_item(NAME(info->latched_xscroll), which);
1312 	save_item(NAME(info->latched_yscroll), which);
1313 	save_item(NAME(info->latched_pageselect), which);
1314 }
1315 
1316 
1317 
1318 /*************************************
1319  *
1320  *  General tilemap rendering
1321  *
1322  *************************************/
1323 
tilemap_draw(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,int which,int map,int priority,int priority_mark)1324 void segaic16_video_device::tilemap_draw(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int which, int map, int priority, int priority_mark)
1325 {
1326 	struct tilemap_info *info = &m_bg_tilemap[which];
1327 
1328 	/* text layer is a special common case */
1329 	if (map == TILEMAP_TEXT)
1330 		info->textmap->draw(screen, bitmap, cliprect, priority, priority_mark);
1331 
1332 	/* other layers are handled differently per-system */
1333 	else
1334 		(*info->draw_layer)(screen, info, bitmap, cliprect, map, priority, priority_mark);
1335 }
1336 
1337 
1338 
1339 /*************************************
1340  *
1341  *  General tilemap reset
1342  *
1343  *************************************/
1344 
tilemap_reset(screen_device & screen)1345 void segaic16_video_device::tilemap_reset(screen_device &screen)
1346 {
1347 	struct tilemap_info *info = &m_bg_tilemap[0];
1348 
1349 	if (info->reset)
1350 		(*info->reset)(screen, info);
1351 }
1352 
1353 
1354 
1355 /*************************************
1356  *
1357  *  General tilemap banking
1358  *
1359  *************************************/
1360 
tilemap_set_bank(int which,int banknum,int offset)1361 void segaic16_video_device::tilemap_set_bank(int which, int banknum, int offset)
1362 {
1363 	struct tilemap_info *info = &m_bg_tilemap[which];
1364 
1365 	if (info->bank[banknum] != offset)
1366 	{
1367 		screen().update_partial(screen().vpos());
1368 		info->bank[banknum] = offset;
1369 		machine().tilemap().mark_all_dirty();
1370 	}
1371 }
1372 
1373 
1374 
1375 /*************************************
1376  *
1377  *  General tilemap screen flipping
1378  *
1379  *************************************/
1380 
tilemap_set_flip(int which,int flip)1381 void segaic16_video_device::tilemap_set_flip(int which, int flip)
1382 {
1383 	struct tilemap_info *info = &m_bg_tilemap[which];
1384 	int pagenum;
1385 
1386 	flip = (flip != 0);
1387 	if (info->flip != flip)
1388 	{
1389 		screen().update_partial(screen().vpos());
1390 		info->flip = flip;
1391 		info->textmap->set_flip(flip ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0);
1392 		for (pagenum = 0; pagenum < info->numpages; pagenum++)
1393 			info->tilemaps[pagenum]->set_flip(flip ? (TILEMAP_FLIPX | TILEMAP_FLIPY) : 0);
1394 	}
1395 }
1396 
1397 
1398 
1399 /*************************************
1400  *
1401  *  General tilemap row scroll enable
1402  *
1403  *************************************/
1404 
tilemap_set_rowscroll(int which,int enable)1405 void segaic16_video_device::tilemap_set_rowscroll(int which, int enable)
1406 {
1407 	struct tilemap_info *info = &m_bg_tilemap[which];
1408 
1409 	enable = (enable != 0);
1410 	if (info->rowscroll != enable)
1411 	{
1412 		screen().update_partial(screen().vpos());
1413 		info->rowscroll = enable;
1414 	}
1415 }
1416 
1417 
1418 
1419 /*************************************
1420  *
1421  *  General tilemap column scroll enable
1422  *
1423  *************************************/
1424 
tilemap_set_colscroll(int which,int enable)1425 void segaic16_video_device::tilemap_set_colscroll(int which, int enable)
1426 {
1427 	struct tilemap_info *info = &m_bg_tilemap[which];
1428 
1429 	enable = (enable != 0);
1430 	if (info->colscroll != enable)
1431 	{
1432 		screen().update_partial(screen().vpos());
1433 		info->colscroll = enable;
1434 	}
1435 }
1436 
1437 
1438 
1439 /*************************************
1440  *
1441  *  General tilemap write handlers
1442  *
1443  *************************************/
1444 
tileram_r(offs_t offset)1445 uint16_t segaic16_video_device::tileram_r(offs_t offset)
1446 {
1447 	return m_tileram[offset];
1448 }
1449 
1450 
tileram_w(offs_t offset,uint16_t data,uint16_t mem_mask)1451 void segaic16_video_device::tileram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
1452 {
1453 	COMBINE_DATA(&m_tileram[offset]);
1454 	m_bg_tilemap[0].tilemaps[offset / (64*32)]->mark_tile_dirty(offset % (64*32));
1455 }
1456 
1457 
textram_r(offs_t offset)1458 uint16_t segaic16_video_device::textram_r(offs_t offset)
1459 {
1460 	return m_textram[offset];
1461 }
1462 
1463 
textram_w(offs_t offset,uint16_t data,uint16_t mem_mask)1464 void segaic16_video_device::textram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
1465 {
1466 	/* certain ranges need immediate updates */
1467 	if (offset >= 0xe80/2)
1468 		screen().update_partial(screen().vpos());
1469 
1470 	COMBINE_DATA(&m_textram[offset]);
1471 	m_bg_tilemap[0].textmap->mark_tile_dirty(offset);
1472 }
1473 
1474 
1475 
1476 
1477 
1478 
1479 
1480 /*************************************
1481  *
1482  *  General rotation initialization
1483  *
1484  *************************************/
1485 
rotate_init(int which,int type,int colorbase)1486 void segaic16_video_device::rotate_init(int which, int type, int colorbase)
1487 {
1488 	struct rotate_info *info = &m_rotate[which];
1489 
1490 	/* reset the tilemap info */
1491 	memset(info, 0, sizeof(*info));
1492 	info->index = which;
1493 	info->type = type;
1494 	info->colorbase = colorbase;
1495 
1496 	/* set up based on which road generator */
1497 	switch (which)
1498 	{
1499 		case 0:
1500 			info->rotateram = m_rotateram;
1501 			break;
1502 
1503 		default:
1504 			fatalerror("Invalid rotate index specified in rotate_init\n");
1505 	}
1506 
1507 	/* determine the parameters of the rotate */
1508 	switch (type)
1509 	{
1510 		case ROTATE_YBOARD:
1511 			info->ramsize = 0x800;
1512 			break;
1513 
1514 		default:
1515 			fatalerror("Invalid rotate system specified in rotate_init\n");
1516 	}
1517 
1518 	/* allocate a buffer for swapping */
1519 	info->buffer = std::make_unique<uint16_t[]>(info->ramsize/2);
1520 
1521 	save_item(NAME(info->colorbase), which);
1522 	save_pointer(NAME(info->buffer), info->ramsize/2, which);
1523 }
1524 
1525 
1526 
1527 /*************************************
1528  *
1529  *  General rotation drawing
1530  *
1531  *************************************/
1532 
rotate_draw(int which,bitmap_ind16 & bitmap,const rectangle & cliprect,bitmap_ind8 & priority_bitmap,bitmap_ind16 & srcbitmap)1533 void segaic16_video_device::rotate_draw(int which, bitmap_ind16 &bitmap, const rectangle &cliprect, bitmap_ind8 &priority_bitmap, bitmap_ind16 &srcbitmap)
1534 {
1535 	struct rotate_info *info = &m_rotate[which];
1536 	int32_t currx = (info->buffer[0x3f0] << 16) | info->buffer[0x3f1];
1537 	int32_t curry = (info->buffer[0x3f2] << 16) | info->buffer[0x3f3];
1538 	int32_t dyy = (info->buffer[0x3f4] << 16) | info->buffer[0x3f5];
1539 	int32_t dxx = (info->buffer[0x3f6] << 16) | info->buffer[0x3f7];
1540 	int32_t dxy = (info->buffer[0x3f8] << 16) | info->buffer[0x3f9];
1541 	int32_t dyx = (info->buffer[0x3fa] << 16) | info->buffer[0x3fb];
1542 
1543 	/* advance forward based on the clip rect */
1544 	currx += dxx * (cliprect.min_x + 27) + dxy * cliprect.min_y;
1545 	curry += dyx * (cliprect.min_x + 27) + dyy * cliprect.min_y;
1546 
1547 	/* loop over screen Y coordinates */
1548 	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
1549 	{
1550 		uint16_t *dest = &bitmap.pix(y);
1551 		uint16_t const *const src = &srcbitmap.pix(0);
1552 		uint8_t *pri = &priority_bitmap.pix(y);
1553 		int32_t tx = currx;
1554 		int32_t ty = curry;
1555 
1556 		/* loop over screen X coordinates */
1557 		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
1558 		{
1559 			/* fetch the pixel from the source bitmap */
1560 			int sx = (tx >> 14) & 0x1ff;
1561 			int sy = (ty >> 14) & 0x1ff;
1562 			int pix = src[sy * srcbitmap.rowpixels() + sx];
1563 
1564 			/* non-zero pixels get written; everything else is the scanline color */
1565 			if (pix != 0xffff)
1566 			{
1567 				*dest++ = (pix & 0x1ff) | ((pix >> 6) & 0x200) | ((pix >> 3) & 0xc00) | 0x1000;
1568 				*pri++ = (pix >> 8) | 1;
1569 			}
1570 			else
1571 			{
1572 				*dest++ = info->colorbase + sy;
1573 				*pri++ = 0xff;
1574 			}
1575 
1576 			/* advance the source X/Y pointers */
1577 			tx += dxx;
1578 			ty += dyx;
1579 		}
1580 
1581 		/* advance the source X/Y pointers */
1582 		currx += dxy;
1583 		curry += dyy;
1584 	}
1585 }
1586 
1587 
1588 
1589 /*************************************
1590  *
1591  *  General road control read/write
1592  *
1593  *************************************/
1594 
rotate_control_r()1595 uint16_t segaic16_video_device::rotate_control_r()
1596 {
1597 	struct rotate_info *info = &m_rotate[0];
1598 
1599 	if (info->buffer)
1600 	{
1601 		uint32_t *src = (uint32_t *)info->rotateram;
1602 		uint32_t *dst = (uint32_t *)info->buffer.get();
1603 		int i;
1604 
1605 		/* swap the halves of the rotation RAM */
1606 		for (i = 0; i < info->ramsize/4; i++)
1607 		{
1608 			uint32_t temp = *src;
1609 			*src++ = *dst;
1610 			*dst++ = temp;
1611 		}
1612 	}
1613 
1614 	return 0xffff;
1615 }
1616