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