trunk/src/mame/video/decocass.c
| r19804 | r19805 | |
| 2 | 2 | |
| 3 | 3 | DECO Cassette System video |
| 4 | 4 | |
| 5 | The video system has clearly been designed for Highway Chase, |
| 6 | which unsurprisingly is the first game on the system. The |
| 7 | background 'tilemap' is very much like the road layer on the |
| 8 | standalone Highway Chase with a concept of left/right edges |
| 9 | with semi-independent scrolling, and the ability to transition |
| 10 | between scrolling different sections. |
| 11 | |
| 12 | Additionally it supports the headlight effect also needed for |
| 13 | a Highway Chase style game. |
| 14 | |
| 5 | 15 | ***********************************************************************/ |
| 6 | 16 | |
| 7 | 17 | #include "emu.h" |
| r19804 | r19805 | |
| 460 | 470 | } |
| 461 | 471 | } |
| 462 | 472 | |
| 473 | // we could still massively clean up the background tilemap handling, I have a feeling the |
| 474 | // code to ignore tiles with 0x80 set on the left tilemap etc. is just a convenient hack |
| 475 | // to stop garbage tiles appearing when scrolling due to the weird ram layout and clipping rules |
| 463 | 476 | |
| 477 | // 0 is left edge, 1 is right edge |
| 478 | void decocass_state::draw_edge(bitmap_ind16 &bitmap, const rectangle &cliprect, int which, bool opaque) |
| 479 | { |
| 480 | rectangle clip; |
| 481 | bitmap_ind16* srcbitmap; |
| 482 | |
| 483 | int scrolly_l = m_back_vl_shift; |
| 484 | int scrolly_r = 256 - m_back_vr_shift; |
| 485 | |
| 486 | // bit 0x04 of the mode select effectively selects between two banks of data |
| 487 | if (0 == (m_mode_set & 0x04)) |
| 488 | scrolly_r += 256; |
| 489 | else |
| 490 | scrolly_l += 256; |
| 491 | |
| 492 | int scrollx = 256 - m_back_h_shift; |
| 493 | int scrolly; |
| 494 | |
| 495 | if (which==0) |
| 496 | { |
| 497 | clip = m_bg_tilemap_l_clip; |
| 498 | clip &= cliprect; |
| 499 | scrolly = scrolly_l; |
| 500 | srcbitmap = &m_bg_tilemap_l->pixmap(); |
| 501 | } |
| 502 | else |
| 503 | { |
| 504 | clip = m_bg_tilemap_r_clip; |
| 505 | clip &= cliprect; |
| 506 | scrolly = scrolly_r; |
| 507 | srcbitmap = &m_bg_tilemap_r->pixmap(); |
| 508 | } |
| 509 | |
| 510 | int y,x; |
| 511 | |
| 512 | // printf("m_mode_set %d\n", m_mode_set & 0x3); |
| 513 | |
| 514 | // technically our y drawing probably shouldn't wrap / mask, but simply draw the 128pixel high 'edge' at the requested position |
| 515 | // see note above this funciton |
| 516 | for (y=clip.min_y; y<=clip.max_y;y++) |
| 517 | { |
| 518 | int srcline = (y + scrolly) & 0x1ff; |
| 519 | UINT16* src = &srcbitmap->pix16(srcline); |
| 520 | UINT16* dst = &bitmap.pix16(y); |
| 521 | |
| 522 | for (x=clip.min_x; x<=clip.max_x;x++) |
| 523 | { |
| 524 | int srccol; |
| 525 | |
| 526 | // 2 bits control the x scroll mode, allowing it to wrap either half of the tilemap, or transition one way or the other between the two halves |
| 527 | |
| 528 | switch (m_mode_set & 3) |
| 529 | { |
| 530 | case 0x00: srccol = ((x + scrollx) & 0xff); break; // hwy normal case |
| 531 | case 0x01: srccol = (x + scrollx + 0x100) & 0x1ff; break; // manhattan building top |
| 532 | case 0x02: srccol = ((x + scrollx) & 0xff) + 0x100; break; // manhattan normal case |
| 533 | case 0x03: srccol = (x + scrollx) & 0x1ff; break; // hwy, burnrub etc. |
| 534 | } |
| 535 | |
| 536 | UINT16 pix = src[srccol]; |
| 537 | |
| 538 | if ((pix & 0x3) || opaque) |
| 539 | { |
| 540 | dst[x] = pix; |
| 541 | } |
| 542 | } |
| 543 | } |
| 544 | |
| 545 | } |
| 546 | |
| 547 | |
| 464 | 548 | void decocass_state::video_start() |
| 465 | 549 | { |
| 466 | 550 | m_bg_tilemap_l = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(decocass_state::get_bg_l_tile_info),this), tilemap_mapper_delegate(FUNC(decocass_state::bgvideoram_scan_cols),this), 16, 16, 32, 32); |
| r19804 | r19805 | |
| 477 | 561 | m_bg_tilemap_r_clip = machine().primary_screen->visible_area(); |
| 478 | 562 | m_bg_tilemap_r_clip.min_y = 256 / 2; |
| 479 | 563 | |
| 480 | | /* background videroam bits D0-D3 are shared with the tileram */ |
| 564 | /* background videoram bits D0-D3 are shared with the tileram */ |
| 481 | 565 | m_bgvideoram = m_tileram; |
| 482 | 566 | m_bgvideoram_size = 0x0400; /* d000-d3ff */ |
| 483 | 567 | |
| r19804 | r19805 | |
| 493 | 577 | |
| 494 | 578 | UINT32 decocass_state::screen_update_decocass(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 495 | 579 | { |
| 496 | | int scrollx, scrolly_l, scrolly_r; |
| 497 | | rectangle clip; |
| 580 | /* THIS CODE SHOULD NOT BE IN SCREEN UPDATE !! */ |
| 498 | 581 | |
| 499 | 582 | if (0xc0 != (machine().root_device().ioport("IN2")->read() & 0xc0)) /* coin slots assert an NMI */ |
| 500 | 583 | m_maincpu->set_input_line(INPUT_LINE_NMI, ASSERT_LINE); |
| r19804 | r19805 | |
| 504 | 587 | else if (m_watchdog_count-- > 0) |
| 505 | 588 | machine().watchdog_reset(); |
| 506 | 589 | |
| 590 | /* (end) THIS CODE SHOULD NOT BE IN SCREEN UPDATE !! */ |
| 591 | |
| 592 | |
| 507 | 593 | #ifdef MAME_DEBUG |
| 508 | 594 | { |
| 509 | 595 | if (machine().input().code_pressed_once(KEYCODE_I)) |
| r19804 | r19805 | |
| 525 | 611 | |
| 526 | 612 | bitmap.fill(0, cliprect); |
| 527 | 613 | |
| 528 | | scrolly_l = m_back_vl_shift; |
| 529 | | scrolly_r = 256 - m_back_vr_shift; |
| 530 | | |
| 531 | | scrollx = 256 - m_back_h_shift; |
| 532 | | if (0 == (m_mode_set & 0x02)) |
| 533 | | scrollx += 256; |
| 534 | | |
| 535 | | #if 0 |
| 536 | | /* this is wrong */ |
| 537 | | if (0 != m_back_h_shift && 0 == ((m_mode_set ^ (m_mode_set >> 1)) & 1)) |
| 538 | | scrollx += 256; |
| 539 | | #endif |
| 540 | | |
| 541 | | if (0 == (m_mode_set & 0x04)) |
| 542 | | scrolly_r += 256; |
| 543 | | else |
| 544 | | scrolly_l += 256; |
| 545 | | |
| 546 | | m_bg_tilemap_l->set_scrollx(0, scrollx); |
| 547 | | m_bg_tilemap_l->set_scrolly(0, scrolly_l); |
| 548 | | |
| 549 | | m_bg_tilemap_r->set_scrollx(0, scrollx); |
| 550 | | m_bg_tilemap_r->set_scrolly(0, scrolly_r); |
| 551 | | |
| 552 | 614 | if (m_mode_set & 0x08) /* bkg_ena on ? */ |
| 553 | 615 | { |
| 554 | | clip = m_bg_tilemap_l_clip; |
| 555 | | clip &= cliprect; |
| 556 | | m_bg_tilemap_l->draw(bitmap, clip, TILEMAP_DRAW_OPAQUE, 0); |
| 557 | | |
| 558 | | clip = m_bg_tilemap_r_clip; |
| 559 | | clip &= cliprect; |
| 560 | | m_bg_tilemap_r->draw(bitmap, clip, TILEMAP_DRAW_OPAQUE, 0); |
| 616 | draw_edge(bitmap,cliprect,0,true); |
| 617 | draw_edge(bitmap,cliprect,1,true); |
| 561 | 618 | } |
| 562 | 619 | |
| 563 | 620 | if (m_mode_set & 0x20) |
| r19804 | r19805 | |
| 571 | 628 | draw_center(bitmap, cliprect); |
| 572 | 629 | if (m_mode_set & 0x08) /* bkg_ena on ? */ |
| 573 | 630 | { |
| 574 | | clip = m_bg_tilemap_l_clip; |
| 575 | | clip &= cliprect; |
| 576 | | m_bg_tilemap_l->draw(bitmap, clip, 0, 0); |
| 577 | | |
| 578 | | clip = m_bg_tilemap_r_clip; |
| 579 | | clip &= cliprect; |
| 580 | | m_bg_tilemap_r->draw(bitmap, clip, 0, 0); |
| 631 | draw_edge(bitmap,cliprect,0,false); |
| 632 | draw_edge(bitmap,cliprect,1,false); |
| 581 | 633 | } |
| 582 | 634 | } |
| 583 | 635 | m_fg_tilemap->draw(bitmap, cliprect, 0, 0); |
trunk/src/mame/drivers/decocass.c
| r19804 | r19805 | |
| 110 | 110 | AM_RANGE(0xe400, 0xe400) AM_WRITE(decocass_reset_w) |
| 111 | 111 | |
| 112 | 112 | /* BIO-3 board */ |
| 113 | | AM_RANGE(0xe402, 0xe402) AM_WRITE(decocass_mode_set_w) |
| 114 | | AM_RANGE(0xe403, 0xe403) AM_WRITE(decocass_back_h_shift_w) |
| 115 | | AM_RANGE(0xe404, 0xe404) AM_WRITE(decocass_back_vl_shift_w) |
| 116 | | AM_RANGE(0xe405, 0xe405) AM_WRITE(decocass_back_vr_shift_w) |
| 117 | | AM_RANGE(0xe406, 0xe406) AM_WRITE(decocass_part_h_shift_w) |
| 118 | | AM_RANGE(0xe407, 0xe407) AM_WRITE(decocass_part_v_shift_w) |
| 113 | AM_RANGE(0xe402, 0xe402) AM_WRITE(decocass_mode_set_w) /* scroll mode regs + various enable regs */ |
| 114 | AM_RANGE(0xe403, 0xe403) AM_WRITE(decocass_back_h_shift_w) /* back (both) tilemap x scroll */ |
| 115 | AM_RANGE(0xe404, 0xe404) AM_WRITE(decocass_back_vl_shift_w) /* back (left) (top@rot0) tilemap y scroll */ |
| 116 | AM_RANGE(0xe405, 0xe405) AM_WRITE(decocass_back_vr_shift_w) /* back (right) (bot@rot0) tilemap y scroll */ |
| 117 | AM_RANGE(0xe406, 0xe406) AM_WRITE(decocass_part_h_shift_w) /* headlight */ |
| 118 | AM_RANGE(0xe407, 0xe407) AM_WRITE(decocass_part_v_shift_w) /* headlight */ |
| 119 | 119 | |
| 120 | 120 | AM_RANGE(0xe410, 0xe410) AM_WRITE(decocass_color_center_bot_w) |
| 121 | 121 | AM_RANGE(0xe411, 0xe411) AM_WRITE(decocass_center_h_shift_space_w) |