1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3
4 #include "emu.h"
5 #include "elan_eu3a14vid.h"
6
7 DEFINE_DEVICE_TYPE(ELAN_EU3A14_VID, elan_eu3a14vid_device, "elan_eu3a14vid", "Elan EU3A14 Video")
8
elan_eu3a14vid_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)9 elan_eu3a14vid_device::elan_eu3a14vid_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
10 : elan_eu3a05commonvid_device(mconfig, ELAN_EU3A14_VID, tag, owner, clock),
11 device_memory_interface(mconfig, *this),
12 m_cpu(*this, finder_base::DUMMY_TAG),
13 m_bank(*this, finder_base::DUMMY_TAG),
14 m_screen(*this, finder_base::DUMMY_TAG),
15 m_space_config("regs", ENDIANNESS_NATIVE, 8, 7, 0, address_map_constructor(FUNC(elan_eu3a14vid_device::map), this))
16 {
17 }
18
memory_space_config() const19 device_memory_interface::space_config_vector elan_eu3a14vid_device::memory_space_config() const
20 {
21 return space_config_vector {
22 std::make_pair(0, &m_space_config)
23 };
24 }
25
26 /* Windowing mode note
27
28 huntin'3 seems to use some registers for a windowing / highlight effect on the trophy room names and "Target Range" mode timer??
29 5100 - 0x0f when effect is enabled, 0x00 otherwise?
30 5101 - 0x0e in both modes
31 5102 - 0x86 in both modes
32 5103 - 0x0e in tropy room (left?) / 0x2a in "Target Range" mode (left position?)
33 5104 - trophy room window / highlight top, move with cursor / 0xbf in "Target Range" mode (top?)
34 5105 - 0x52 in trophy room (right?) / counts from 0xa1 to 0x2a in "Target Range" mode (right position?)
35 5106 - trophy room window / highlight bottom, move with cursor / 0xcb in "Target Range" mode (bottom?)
36 */
37
map(address_map & map)38 void elan_eu3a14vid_device::map(address_map &map)
39 {
40 map(0x00, 0x7f).rw(FUNC(elan_eu3a14vid_device::read_unmapped), FUNC(elan_eu3a14vid_device::write_unmapped));
41
42 map(0x00, 0x06).ram(); // see Windowing note above
43 map(0x07, 0x07).rw(FUNC(elan_eu3a14vid_device::reg5107_r), FUNC(elan_eu3a14vid_device::reg5107_w)); // writes on transitions, maybe layer disables?
44 map(0x08, 0x08).rw(FUNC(elan_eu3a14vid_device::reg5108_r), FUNC(elan_eu3a14vid_device::reg5108_w)); // 0x04 in both modes // hnt3, frequently rewrites same values TODO
45 map(0x09, 0x09).rw(FUNC(elan_eu3a14vid_device::reg5109_r), FUNC(elan_eu3a14vid_device::reg5109_w)); // related to above?
46 // 0x0a
47 // 0x0b
48 // 0x0c
49 // 0x0d
50 // 0x0e
51 // 0x0f
52 map(0x10, 0x15).rw(FUNC(elan_eu3a14vid_device::tilecfg_r), FUNC(elan_eu3a14vid_device::tilecfg_w));
53 map(0x16, 0x17).rw(FUNC(elan_eu3a14vid_device::rowscrollcfg_r), FUNC(elan_eu3a14vid_device::rowscrollcfg_w));
54 // 0x18
55 // 0x19
56 map(0x1a, 0x1e).rw(FUNC(elan_eu3a14vid_device::rowscrollsplit_r), FUNC(elan_eu3a14vid_device::rowscrollsplit_w));
57 // 0x1f
58 // 0x20
59 map(0x21, 0x24).rw(FUNC(elan_eu3a14vid_device::scrollregs_r), FUNC(elan_eu3a14vid_device::scrollregs_w)); // 0x21,0x22 = scroll reg 1, 0x23,0x24 = scroll reg 2
60 map(0x25, 0x2c).rw(FUNC(elan_eu3a14vid_device::rowscrollregs_r), FUNC(elan_eu3a14vid_device::rowscrollregs_w)); // 0x25,0x26 = rowscroll reg 1, 0x27,0x28 = rowscroll reg 2, 0x29,0x2a = rowscroll reg 3, 0x2b,0x2c = rowscroll reg 3
61 // 0x2d
62 // 0x2e
63 // 0x2f
64 // 0x30
65 // 0x31
66 // 0x32
67 // 0x33
68 // 0x34
69 // 0x35
70 // 0x36
71 // 0x37
72 // 0x38
73 // 0x39
74 // 0x3a
75 // 0x3b
76 // 0x3c
77 // 0x3d
78 // 0x3e
79 // 0x3f
80 map(0x40, 0x45).rw(FUNC(elan_eu3a14vid_device::ramtilecfg_r), FUNC(elan_eu3a14vid_device::ramtilecfg_w));
81 // 0x46
82 // 0x47
83 map(0x48, 0x4b).ram(); // hnt3 (always 0 tho?)
84 // 0x4c
85 // 0x4d
86 // 0x4e
87 // 0x4f
88 map(0x50, 0x50).rw(FUNC(elan_eu3a14vid_device::spriteaddr_r), FUNC(elan_eu3a14vid_device::spriteaddr_w));
89 map(0x51, 0x52).rw(FUNC(elan_eu3a14vid_device::spritebase_r), FUNC(elan_eu3a14vid_device::spritebase_w));
90 map(0x53, 0x53).ram(); // startup
91
92 // nothing else used?
93 }
94
device_start()95 void elan_eu3a14vid_device::device_start()
96 {
97 elan_eu3a05commonvid_device::device_start();
98
99 save_item(NAME(m_scrollregs));
100 save_item(NAME(m_tilecfg));
101 save_item(NAME(m_rowscrollregs));
102 save_item(NAME(m_rowscrollsplit));
103 save_item(NAME(m_rowscrollcfg));
104 save_item(NAME(m_ramtilecfg));
105 save_item(NAME(m_spritebase));
106
107 save_item(NAME(m_5107));
108 save_item(NAME(m_5108));
109 save_item(NAME(m_5109));
110
111 save_item(NAME(m_spriteaddr));
112 }
113
device_reset()114 void elan_eu3a14vid_device::device_reset()
115 {
116 elan_eu3a05commonvid_device::device_reset();
117
118 for (int i = 0; i < 4; i++)
119 m_scrollregs[i] = 0x00;
120
121 for (int i = 0; i < 6; i++)
122 m_tilecfg[i] = 0x00;
123
124 for (int i = 0; i < 8; i++)
125 m_rowscrollregs[i] = 0x00;
126
127 for (int i = 0; i < 5; i++)
128 m_rowscrollsplit[i] = 0x00;
129
130 for (int i = 0; i < 2; i++)
131 m_rowscrollcfg[i] = 0x00;
132
133 for (int i = 0; i < 6; i++)
134 m_ramtilecfg[i] = 0x00;
135
136 for (int i = 0; i < 2; i++)
137 m_spritebase[i] = 0x00;
138
139 m_5107 = 0x00;
140 m_5108 = 0x00;
141 m_5109 = 0x00;
142
143 m_spriteaddr = 0x14; // ?? rad_foot never writes, other games seem to use it to set sprite location
144 }
145
read_vram(int offset)146 uint8_t elan_eu3a14vid_device::read_vram(int offset)
147 {
148 address_space& cpuspace = m_cpu->space(AS_PROGRAM);
149 int realoffset = offset + 0x200;
150 if (realoffset < 0x4000)
151 {
152 return cpuspace.read_byte(realoffset);
153 }
154 else
155 return 0x00;
156 }
157
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)158 uint32_t elan_eu3a14vid_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
159 {
160 m_spriterambase = (m_spriteaddr * 0x200) - 0x200;
161
162 bitmap.fill(0, cliprect);
163 m_prioritybitmap.fill(0, cliprect);
164
165 draw_background(screen, bitmap, cliprect);
166
167 draw_sprites(screen, bitmap, cliprect);
168 return 0;
169 }
170
video_start()171 void elan_eu3a14vid_device::video_start()
172 {
173 m_screen->register_screen_bitmap(m_prioritybitmap);
174 }
175
176
read_gfxdata(int offset,int x)177 uint8_t elan_eu3a14vid_device::read_gfxdata(int offset, int x)
178 {
179 address_space& fullbankspace = m_bank->space(AS_PROGRAM);
180 return fullbankspace.read_byte((offset+x) & 0x3fffff);
181 }
182
readpix(int baseaddr,int count,int drawfromram)183 uint8_t elan_eu3a14vid_device::readpix(int baseaddr, int count, int drawfromram)
184 {
185 int pix;
186
187 if (drawfromram)
188 {
189 pix = read_vram((baseaddr + count) & 0x3fff);
190 }
191 else
192 {
193 address_space& fullbankspace = m_bank->space(AS_PROGRAM);
194 pix = fullbankspace.read_byte((baseaddr+count) & 0x3fffff);
195 }
196 return pix;
197 }
198
draw_background_tile(bitmap_ind16 & bitmap,const rectangle & cliprect,int bpp,int tileno,int palette,int priority,int flipx,int flipy,int xpos,int ypos,int transpen,int size,int base,int drawfromram)199 void elan_eu3a14vid_device::draw_background_tile(bitmap_ind16& bitmap, const rectangle& cliprect, int bpp, int tileno, int palette, int priority, int flipx, int flipy, int xpos, int ypos, int transpen, int size, int base, int drawfromram)
200 {
201 int baseaddr = base * 256;
202
203 int xstride = 8;
204
205 if (bpp == 8) // 8bpp selection
206 {
207 if (size == 8)
208 {
209 xstride = size / 1; baseaddr += tileno * 64; // 8x8 8bpp
210 }
211 else
212 {
213 xstride = size / 1; baseaddr += tileno * 256; // 16x16 8bpp
214 }
215
216 palette &= 0x100; // only top bit valid, as there are only 2 palettes?
217 }
218 else if (bpp == 4) // 4bpp selection
219 {
220 if (size == 8)
221 {
222 xstride = size / 2; baseaddr += tileno * 32; // 8x8 4bpp
223 }
224 else
225 {
226 xstride = size / 2; baseaddr += tileno * 128; // 16x16 4bpp
227 }
228 }
229 else if (bpp == 2) // 2bpp?
230 {
231 xstride = size / 4; baseaddr += tileno * 64; // 16x16 2bpp
232 }
233 else
234 {
235 popmessage("draw_background_tile unsupported bpp %d\n", bpp);
236 return;
237 }
238
239 int count = 0;
240 for (int y = 0; y < size; y++)
241 {
242 int realy = ypos + y;
243 int xposwithscroll = 0;
244
245 if (!drawfromram)
246 {
247 xposwithscroll = xpos - get_xscroll_for_screenypos(realy);
248 }
249 else
250 {
251 xposwithscroll = xpos;
252 // RAM tile layer has no scrolling? (or we've never seen it used / enabled)
253 }
254
255 uint16_t *const dst = &bitmap.pix(ypos + y);
256 uint8_t *const pridst = &m_prioritybitmap.pix(ypos + y);
257
258 for (int x = 0; x < xstride; x++)
259 {
260 if (realy >= cliprect.min_y && realy <= cliprect.max_y)
261 {
262 if (bpp == 8) // 8bpp
263 {
264 int realx = x + xposwithscroll;
265 if (realx >= cliprect.min_x && realx <= cliprect.max_x)
266 {
267 uint8_t pix = readpix(baseaddr, count, drawfromram);
268
269 if (pix)
270 {
271 if (pridst[realx] <= priority)
272 {
273 dst[realx] = pix | palette;
274 pridst[realx] = priority;
275 }
276
277 }
278 }
279 }
280 else if (bpp == 7)
281 {
282 popmessage("draw_background_tile bpp == 7");
283 }
284 else if (bpp == 6)
285 {
286 popmessage("draw_background_tile bpp == 6");
287 }
288 else if (bpp == 5)
289 {
290 popmessage("draw_background_tile bpp == 5");
291 }
292 else if (bpp == 4) // 4bpp
293 {
294 int realx = (x * 2) + xposwithscroll;
295
296 if (((realx + 1) >= cliprect.min_x) || (realx <= cliprect.max_x))
297 {
298 uint8_t pix = readpix(baseaddr, count, drawfromram);
299
300 int mask = 0xf0;
301 int shift = 4;
302
303 for (int i = 0; i < 4; i++)
304 {
305 if (realx >= cliprect.min_x && realx <= cliprect.max_x)
306 {
307 if (pix & mask)
308 {
309 if (pridst[realx] <= priority)
310 {
311 dst[realx] = ((pix & mask) >> shift) | palette;
312 pridst[realx] = priority;
313 }
314 }
315 }
316 mask >>= 4;
317 shift -= 4;
318 realx++;
319 }
320 }
321 }
322 else if (bpp == 3)
323 {
324 popmessage("draw_background_tile bpp == 3");
325 }
326 else if (bpp == 2) // 2bpp (hnt3 ram text)
327 {
328 int realx = (x * 4) + xposwithscroll;
329
330 if (((realx + 3) >= cliprect.min_x) || (realx <= cliprect.max_x))
331 {
332 uint8_t pix = readpix(baseaddr, count, drawfromram);
333
334 int mask = 0xc0;
335 int shift = 6;
336
337 for (int i = 0; i < 4; i++)
338 {
339 if (realx >= cliprect.min_x && realx <= cliprect.max_x)
340 {
341 if (pix & 0xc0)
342 {
343 if (pridst[realx] <= priority)
344 {
345 dst[realx] = ((pix & mask) >> shift) | palette;
346 pridst[realx] = priority;
347 }
348 }
349 }
350
351 realx++;
352 mask >>= 2;
353 shift -= 2;
354 }
355 }
356 }
357 else if (bpp == 1)
358 {
359 popmessage("draw_background_tile bpp == 1");
360 }
361 }
362 count++;
363 }
364 }
365 }
366
get_xscroll_for_screenypos(int ydraw)367 int elan_eu3a14vid_device::get_xscroll_for_screenypos(int ydraw)
368 {
369 if ((ydraw < 0) || (ydraw >= 224))
370 return 0;
371
372 int xscroll = m_scrollregs[0] | (m_scrollregs[1] << 8);
373
374 if (m_rowscrollcfg[1] == 0x01) // GUESS! could be anything, but this bit is set in Huntin'3
375 {
376 int split0 = m_rowscrollregs[0] | (m_rowscrollregs[1] << 8);
377 int split1 = m_rowscrollregs[2] | (m_rowscrollregs[3] << 8);
378 int split2 = m_rowscrollregs[4] | (m_rowscrollregs[5] << 8);
379 int split3 = m_rowscrollregs[6] | (m_rowscrollregs[7] << 8);
380
381 if (ydraw < m_rowscrollsplit[0])
382 {
383 return xscroll;
384 }
385 else if (ydraw < m_rowscrollsplit[1])
386 {
387 return split0;
388 }
389 else if (ydraw < m_rowscrollsplit[2])
390 {
391 return split1;
392 }
393 else if (ydraw < m_rowscrollsplit[3])
394 {
395 return split2;
396 }
397 else if (ydraw < m_rowscrollsplit[4])
398 {
399 return split3;
400 }
401 else
402 {
403 return 0;
404 }
405 }
406 else
407 {
408 return xscroll;
409 }
410 }
411
412
draw_background_page(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,int ramstart,int ramend,int xbase,int ybase,int size,int bpp,int base,int pagewidth,int pageheight,int bytespertile,int palettepri,int drawfromram)413 void elan_eu3a14vid_device::draw_background_page(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect, int ramstart, int ramend, int xbase, int ybase, int size, int bpp, int base, int pagewidth, int pageheight, int bytespertile, int palettepri, int drawfromram)
414 {
415
416 int palette = ((palettepri & 0xf0) >> 4) | ((palettepri & 0x08) << 1);
417 palette = palette << 4;
418 int priority = palettepri & 0x07;
419
420 int xdraw = xbase;
421 int ydraw = ybase;
422 int count = 0;
423
424 for (int i = ramstart; i < ramend; i += bytespertile)
425 {
426 int tile = 0;
427 int realpalette = palette;
428 int realpriority = priority;
429 int realbpp = bpp;
430
431 if (bytespertile == 2)
432 {
433 tile = read_vram(i + 0) | (read_vram(i + 1) << 8);
434 }
435 else if (bytespertile == 4) // rad_foot hidden test mode, rad_hnt3 "Target Range" (not yet correct)
436 {
437 tile = read_vram(i + 0) | (read_vram(i + 1) << 8);// | (read_vram(i + 2) << 16) | | (read_vram(i + 3) << 24);
438
439 // read_vram(i + 3) & 0x04 is set in both seen cases, maybe per-tile bpp?
440 // this would match up with this mode being inline replacements for m_tilecfg[1] (palettepri) and m_tilecfg[2] (bpp);
441
442 int newpalette = ((read_vram(i + 2) & 0xf0) >> 4) | ((read_vram(i + 2) & 0x08) << 1);
443 newpalette = newpalette << 4;
444 realpalette = newpalette;
445 realpriority = read_vram(i + 2) & 0x07;
446 realbpp = read_vram(i + 3) & 0x07;
447 if (realbpp == 0)
448 realbpp = 8;
449
450 }
451
452
453 draw_background_tile(bitmap, cliprect, realbpp, tile, realpalette, realpriority, 0, 0, xdraw, ydraw, 0, size, base, drawfromram);
454
455 xdraw += size;
456
457 count++;
458 if (((count % pagewidth) == 0))
459 {
460 xdraw -= size * pagewidth;
461 ydraw += size;
462 }
463 }
464 }
465
draw_background_ramlayer(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)466 void elan_eu3a14vid_device::draw_background_ramlayer(screen_device& screen, bitmap_ind16& bitmap, const rectangle& cliprect)
467 {
468 // this register use is questionable
469 if (m_ramtilecfg[0] & 0x80)
470 {
471 int rtm_size;
472 int rtm_pagewidth;
473 int rtm_pageheight;
474 int rtm_yscroll;
475 int rtm_bpp;
476 int rtm_bytespertile = 2;
477 uint8_t palettepri = m_ramtilecfg[1];
478
479 rtm_yscroll = 0;
480
481 // this is the gfxbase in ram for all cases seen
482 int rtm_base = (0x2000 - 0x200) / 256;
483
484 // same as regular layer?
485 if (m_ramtilecfg[0] & 0x10)
486 {
487 rtm_size = 8;
488 rtm_pagewidth = 32;
489 rtm_pageheight = 28;
490 }
491 else
492 {
493 rtm_size = 16;
494 rtm_pagewidth = 32 / 2;
495 rtm_pageheight = 28 / 2;
496 }
497
498 rtm_bpp = m_ramtilecfg[2] & 0x07;
499 if (rtm_bpp == 0)
500 rtm_bpp = 8;
501
502 // this is in the same place even when the first tilemap is in 16x16 mode, probably a base register somewhere
503 int ramstart = m_tilerambase + 0x700;
504 int ramend = m_tilerambase + 0x700 + 0x700;
505
506 // hack for "Target Range" mode
507 if (m_ramtilecfg[5] == 0x06)
508 {
509 ramstart = 0x3980-0x200;
510 ramend = 0x3980-0x200 + 0x700;
511 }
512
513 // normal
514 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, 0, 0 - rtm_yscroll, rtm_size, rtm_bpp, rtm_base, rtm_pagewidth, rtm_pageheight, rtm_bytespertile, palettepri, 1);
515 // wrap x
516 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, (rtm_size * rtm_pagewidth), 0 - rtm_yscroll, rtm_size, rtm_bpp, rtm_base, rtm_pagewidth, rtm_pageheight, rtm_bytespertile, palettepri, 1);
517 // wrap y
518 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, 0, (rtm_size * rtm_pageheight) + 0 - rtm_yscroll, rtm_size, rtm_bpp, rtm_base, rtm_pagewidth, rtm_pageheight, rtm_bytespertile, palettepri, 1);
519 // wrap x+y
520 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, (rtm_size * rtm_pagewidth), (rtm_size * rtm_pageheight) + 0 - rtm_yscroll, rtm_size, rtm_bpp, rtm_base, rtm_pagewidth, rtm_pageheight, rtm_bytespertile, palettepri, 1);
521 }
522 }
523
524
draw_background(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)525 void elan_eu3a14vid_device::draw_background(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
526 {
527 int yscroll = m_scrollregs[2] | (m_scrollregs[3] << 8);
528
529 int base = (m_tilecfg[5] << 8) | m_tilecfg[4];
530 uint8_t palettepri = m_tilecfg[1];
531
532 int pagewidth = 1, pageheight = 1;
533 int bytespertile = 2;
534 int size;
535
536 // m_tilecfg[0] b-as ?-hh b = bytes per tile s = tilesize / page size? a = always set when tilemaps are in use - check? h = related to page positions, when set uses 2x2 pages? ? = used
537 // m_tilecfg[1] pppp x--? ? = used foot x = used, huntin3 summary (palette bank?) p = palette (used for different stages in huntin3 and the hidden test modes in others)
538 // m_tilecfg[2] ---- bbbb b = bpp mode (0 = 8bpp)
539 // m_tilecfg[3] ---- ---- (unused or more gfxbase?)
540 // m_tilecfg[4] gggg gggg gfxbase (lower bits)
541 // m_tilecfg[5] gggg gggg gfxbase (upper bits)
542
543 // ramtilecfg appears to be a similar format, except for the other layer with ram base tiles
544 // however 'a' in m_tilecfg[0] is NOT set
545 // also m_tilecfg[0] has 0x80 set, which would be 4 bytes per tile, but it isn't?
546 // the layer seems to be disabled by setting m_tilecfg[0] to 0?
547
548 if (m_tilecfg[0] & 0x10)
549 {
550 size = 8;
551 pagewidth = 32;
552 pageheight = 28;
553 }
554 else
555 {
556 size = 16;
557 pagewidth = 16;
558 pageheight = 14;
559 }
560
561 if (m_tilecfg[0] & 0x80)
562 {
563 bytespertile = 4;
564 }
565 else
566 {
567 bytespertile = 2;
568 }
569
570 int bpp = (m_tilecfg[2] & 0x07);
571 if (bpp == 0)
572 bpp = 8;
573
574 int ramstart = 0;
575 int ramend = 0;
576
577 int pagesize = pagewidth * pageheight * 2;
578
579 if (bytespertile == 4)
580 {
581 pagesize <<= 1; // shift because we need twice as much ram for this mode
582 }
583
584 if ((m_tilecfg[0] & 0x03) == 0x00) // tilemaps arranged as 2x2 pages?
585 {
586 ramstart = m_tilerambase + pagesize * 0;
587 ramend = m_tilerambase + pagesize * 1;
588
589 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, 0, 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // normal
590 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 2), 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x
591 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, 0, (size * pageheight * 2) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap y
592 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 2), (size * pageheight * 2) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x+y
593
594 ramstart = m_tilerambase + pagesize * 1;
595 ramend = m_tilerambase + pagesize * 2;
596
597 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth), 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // normal
598 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 3), 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x
599 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth), (size * pageheight * 2) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap y
600 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 3), (size * pageheight * 2) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x+y
601
602 ramstart = m_tilerambase + pagesize * 2;
603 ramend = m_tilerambase + pagesize * 3;
604
605 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, 0, (size * pageheight) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // normal
606 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 2), (size * pageheight) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x
607 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, 0, (size * pageheight * 3) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap y
608 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 2), (size * pageheight * 3) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x+y
609
610 ramstart = m_tilerambase + pagesize * 3;
611 ramend = m_tilerambase + pagesize * 4;
612
613 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth), (size * pageheight) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // normal
614 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 3), (size * pageheight) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x
615 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth), (size * pageheight * 3) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0);// wrap y
616 draw_background_page(screen, bitmap, cliprect, ramstart,ramend, (size * pagewidth * 3), (size * pageheight * 3) - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0); // wrap x+y
617 }
618 else if ((m_tilecfg[0] & 0x03) == 0x03) // individual tilemaps? multiple layers?
619 {
620 // popmessage("m_tilecfg[0] & 0x03 multiple layers config %04x", base);
621 ramstart = m_tilerambase + pagesize * 0;
622 ramend = m_tilerambase + pagesize * 1;
623
624 // normal
625 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, 0, 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0);
626 // wrap x
627 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, (size * pagewidth), 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0);
628 // wrap y
629 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, 0, (size * pageheight) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0);
630 // wrap x+y
631 draw_background_page(screen, bitmap, cliprect, ramstart, ramend, (size * pagewidth), (size * pageheight) + 0 - yscroll, size, bpp, base, pagewidth,pageheight, bytespertile, palettepri, 0);
632
633 // RAM based tile layer
634 draw_background_ramlayer(screen, bitmap, cliprect);
635 }
636 else
637 {
638 popmessage("m_tilecfg[0] & 0x03 unknown config");
639 }
640
641 }
642
draw_sprite_pix(const rectangle & cliprect,uint16_t * dst,uint8_t * pridst,int realx,int priority,uint8_t pix,uint8_t mask,uint8_t shift,int palette)643 void elan_eu3a14vid_device::draw_sprite_pix(const rectangle& cliprect, uint16_t* dst, uint8_t* pridst, int realx, int priority, uint8_t pix, uint8_t mask, uint8_t shift, int palette)
644 {
645 if (realx >= cliprect.min_x && realx <= cliprect.max_x)
646 {
647 if (pridst[realx] <= priority)
648 {
649 if (pix & mask)
650 {
651 dst[realx] = ((pix & mask) >> shift) | palette;
652 pridst[realx] = priority;
653 }
654 }
655 }
656 }
657
draw_sprite_line(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,int offset,int line,int palette,int flipx,int priority,int xpos,int ypos,int bpp)658 void elan_eu3a14vid_device::draw_sprite_line(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int offset, int line, int palette, int flipx, int priority, int xpos, int ypos, int bpp)
659 {
660 offset = offset * 2;
661
662 int bppdiv = 0;
663
664 switch (bpp)
665 {
666 default:
667 case 0x8:
668 case 0x7:
669 case 0x6:
670 case 0x5:
671 offset += line * 8;
672 bppdiv = 1;
673 break;
674
675 case 0x4:
676 case 0x3:
677 offset += line * 4;
678 bppdiv = 2;
679 break;
680
681 case 0x2:
682 offset += line * 2;
683 bppdiv = 4;
684 break;
685
686 case 0x1:
687 offset += line * 1;
688 bppdiv = 8;
689 break;
690 }
691
692
693 if (ypos >= cliprect.min_y && ypos <= cliprect.max_y)
694 {
695 uint16_t *const dst = &bitmap.pix(ypos);
696 uint8_t *const pridst = &m_prioritybitmap.pix(ypos);
697
698 int count = 0;
699 for (int x = 0; x < 8/bppdiv;x++)
700 {
701 if (bpp == 8)
702 {
703 int pix,mask,shift;
704 if (flipx) { pix = read_gfxdata(offset, 7 - count); } else { pix = read_gfxdata(offset, count); }
705 int realx = xpos + x * 1;
706 if (flipx) { mask = 0xff; shift = 0; } else { mask = 0xff; shift = 0; }
707 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
708 }
709 else if (bpp == 7)
710 {
711 int pix,mask,shift;
712 if (flipx) { pix = read_gfxdata(offset, 7 - count); } else { pix = read_gfxdata(offset, count); }
713 int realx = xpos + x * 1;
714 // stride doesn't change, data isn't packed, just don't use top bit
715 if (flipx) { mask = 0x7f; shift = 0; } else { mask = 0x7f; shift = 0; }
716 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
717 }
718 else if (bpp == 6)
719 {
720 popmessage("6bpp sprite\n");
721 }
722 else if (bpp == 5)
723 {
724 popmessage("5bpp sprite\n");
725 }
726 else if (bpp == 4)
727 {
728 int pix,mask,shift;
729 if (flipx) { pix = read_gfxdata(offset, 3 - count); } else { pix = read_gfxdata(offset, count); }
730 int realx = xpos + x * 2;
731 if (flipx) { mask = 0x0f; shift = 0; } else { mask = 0xf0; shift = 4; }
732 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
733 realx++;
734 if (flipx) { mask = 0xf0; shift = 4; } else { mask = 0x0f; shift = 0; }
735 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
736 }
737 else if (bpp == 3)
738 {
739 popmessage("3bpp sprite\n");
740 }
741 else if (bpp == 2)
742 {
743 int pix,mask,shift;
744 if (flipx) { pix = read_gfxdata(offset, 1 - count); } else { pix = read_gfxdata(offset, count); }
745 int realx = xpos + x * 4;
746 if (flipx) { mask = 0x03; shift = 0; } else { mask = 0xc0; shift = 6; }
747 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
748 realx++;
749 if (flipx) { mask = 0x0c; shift = 2; } else { mask = 0x30; shift = 4; }
750 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
751 realx++;
752 if (flipx) { mask = 0x30; shift = 4; } else { mask = 0x0c; shift = 2; }
753 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
754 realx++;
755 if (flipx) { mask = 0xc0; shift = 6; } else { mask = 0x03; shift = 0; }
756 draw_sprite_pix(cliprect, dst, pridst, realx, priority, pix, mask, shift, palette);
757 }
758 else if (bpp == 1)
759 {
760 popmessage("1bpp sprite\n");
761 }
762
763 count++;
764 }
765 }
766
767 }
768
769
draw_sprites(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)770 void elan_eu3a14vid_device::draw_sprites(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
771 {
772 for (int i = m_spriterambase; i < m_spriterambase + 0x800; i += 8)
773 {
774 /*
775 +0 e-ff hhww flip yx, enable, height, width
776 +1 yyyy yyyy ypos
777 +2 xxxx xxxx xpos
778 +3 pppp Pzzz p = palette, P = upper palette bank, z = priority
779 +4 tttt tttt tile bits
780 +5 tttt tttt
781 +6 --TT TPPP TTT = tile bank PPP = bpp select (+more?)
782 +7 ---- ----
783
784 */
785
786 int attr = read_vram(i + 0);
787 int y = read_vram(i + 1);
788 int x = read_vram(i + 2);
789 int palettepri = read_vram(i + 3);
790
791 int h = attr & 0x0c;
792 int w = attr & 0x03;
793 int flipx = (attr & 0x10) >> 4;
794 int flipy = (attr & 0x20) >> 5;
795
796 int height = 0;
797 int width = 0;
798
799 int pri = palettepri & 0x07;
800
801 int palette = ((palettepri & 0xf0) >> 4) | ((palettepri & 0x08) << 1);
802 palette = palette << 4;
803
804 switch (h)
805 {
806 case 0x0:height = 2; break;
807 case 0x4:height = 4; break;
808 case 0x8:height = 8; break;
809 case 0xc:height = 16; break;
810 }
811
812 switch (w)
813 {
814 case 0x0:width = 1; break;
815 case 0x1:width = 2; break;
816 case 0x2:width = 4; break;
817 case 0x3:width = 8; break;
818 }
819
820 y -= ((height * 2) - 4);
821
822 x -= ((width * 4) - 4);
823
824 height *= 4;
825
826 x -= 6;
827 y -= 4;
828
829 int offset = ((read_vram(i + 5) << 8) + (read_vram(i + 4) << 0));
830 int extra = read_vram(i + 6);
831
832 int spritebase = (m_spritebase[1] << 8) | m_spritebase[0];
833
834 offset += (extra & 0xf8) << 13;
835 offset += spritebase << 7;
836
837 int bpp = extra & 0x07;
838 if (bpp == 0)
839 bpp = 8;
840
841 if (attr & 0x80)
842 {
843 int count = 0;
844 for (int yy = 0; yy < height; yy++)
845 {
846 int yoff = flipy ? height-1-yy : yy;
847
848 for (int xx = 0; xx < width; xx++)
849 {
850 int xoff = flipx ? (((width - 1) * 8) - (xx * 8)) : (xx * 8);
851
852 draw_sprite_line(screen, bitmap, cliprect, offset, count, palette, flipx, pri, x + xoff, y + yoff, bpp);
853 count++;
854 }
855 }
856 }
857 }
858 }
read_unmapped(offs_t offset)859 uint8_t elan_eu3a14vid_device::read_unmapped(offs_t offset)
860 {
861 logerror("%s: elan_eu3a14vid_device::read_unmapped (offset %02x)\n", machine().describe_context(), offset);
862 return 0x00;
863 }
864
write_unmapped(offs_t offset,uint8_t data)865 void elan_eu3a14vid_device::write_unmapped(offs_t offset, uint8_t data)
866 {
867 logerror("%s: elan_eu3a14vid_device::write_unmapped (offset %02x) (data %02x)\n", machine().describe_context(), offset, data);
868 }
869