trunk/src/mame/video/amiga.c
| r30587 | r30588 | |
| 132 | 132 | m_genlock_color = 0xffff; |
| 133 | 133 | |
| 134 | 134 | m_sprite_ctl_written = 0; |
| 135 | |
| 136 | m_screen->register_screen_bitmap(m_flickerfixer); |
| 135 | 137 | } |
| 136 | 138 | |
| 137 | 139 | |
| r30587 | r30588 | |
| 618 | 620 | * |
| 619 | 621 | *************************************/ |
| 620 | 622 | |
| 621 | | void amiga_render_scanline(running_machine &machine, bitmap_ind16 &bitmap, int scanline) |
| 623 | void amiga_state::render_scanline(bitmap_ind16 &bitmap, int scanline) |
| 622 | 624 | { |
| 623 | | amiga_state *state = machine.driver_data<amiga_state>(); |
| 625 | amiga_state *state = this; |
| 624 | 626 | UINT16 save_color0 = CUSTOM_REG(REG_COLOR00); |
| 625 | 627 | int ddf_start_pixel = 0, ddf_stop_pixel = 0; |
| 626 | 628 | int hires = 0, dualpf = 0, ham = 0; |
| 627 | | //int lace = 0; |
| 629 | bool lace = CUSTOM_REG(REG_BPLCON0) & BPLCON0_LACE; |
| 628 | 630 | int hstart = 0, hstop = 0; |
| 629 | 631 | int vstart = 0, vstop = 0; |
| 630 | 632 | int pf1pri = 0, pf2pri = 0; |
| r30587 | r30588 | |
| 639 | 641 | int pl; |
| 640 | 642 | const int defbitoffs = 15; |
| 641 | 643 | |
| 642 | | state->m_last_scanline = scanline; |
| 644 | int save_scanline = scanline; |
| 643 | 645 | |
| 644 | | /* on the first scanline, reset the COPPER and HAM color */ |
| 646 | // we need to do a bit more work on the first scanline |
| 645 | 647 | if (scanline == 0) |
| 646 | 648 | { |
| 647 | | amiga_copper_setpc(machine, CUSTOM_REG_LONG(REG_COP1LCH)); |
| 648 | | state->m_ham_color = CUSTOM_REG(REG_COLOR00); |
| 649 | // toggle lof if interlaced |
| 650 | if (lace) |
| 651 | CUSTOM_REG(REG_VPOSR) ^= 0x8000; |
| 652 | |
| 653 | // reset copper and ham color |
| 654 | amiga_copper_setpc(machine(), CUSTOM_REG_LONG(REG_COP1LCH)); |
| 655 | m_ham_color = CUSTOM_REG(REG_COLOR00); |
| 649 | 656 | } |
| 650 | 657 | |
| 658 | // in visible area? |
| 659 | if (bitmap.valid()) |
| 660 | { |
| 661 | // if interlace is enabled and this is not our turn to draw, copy the previous scanline |
| 662 | if (lace && ((scanline & 1) ^ BIT(CUSTOM_REG(REG_VPOSR), 15)) == 0) |
| 663 | { |
| 664 | memcpy(&bitmap.pix16(scanline), &m_flickerfixer.pix16(scanline), amiga_state::SCREEN_WIDTH * 2); |
| 665 | return; |
| 666 | } |
| 667 | else |
| 668 | dst = &bitmap.pix16(scanline); |
| 669 | } |
| 670 | |
| 671 | if (lace) |
| 672 | scanline /= 2; |
| 673 | |
| 674 | m_last_scanline = scanline; |
| 675 | |
| 651 | 676 | /* update sprite data fetching */ |
| 652 | 677 | update_sprite_dma(state, scanline); |
| 653 | 678 | |
| 654 | | /* start of a new line, signal we're not done with it and fill up vars */ |
| 655 | | if (bitmap.valid()) |
| 656 | | dst = &bitmap.pix16(scanline); |
| 657 | | |
| 658 | 679 | /* all sprites off at the start of the line */ |
| 659 | | memset(state->m_sprite_remain, 0, sizeof(state->m_sprite_remain)); |
| 680 | memset(m_sprite_remain, 0, sizeof(m_sprite_remain)); |
| 660 | 681 | |
| 661 | 682 | /* temporary set color 0 to the genlock color */ |
| 662 | | if (state->m_genlock_color != 0xffff) |
| 663 | | CUSTOM_REG(REG_COLOR00) = state->m_genlock_color; |
| 683 | if (m_genlock_color != 0xffff) |
| 684 | CUSTOM_REG(REG_COLOR00) = m_genlock_color; |
| 664 | 685 | |
| 665 | 686 | /* loop over the line */ |
| 666 | 687 | next_copper_x = 0; |
| 667 | | for (x = 0; x < 227.5*2; x++) |
| 688 | for (x = 0; x < amiga_state::SCREEN_WIDTH / 2; x++) |
| 668 | 689 | { |
| 669 | 690 | int sprpix; |
| 670 | 691 | |
| r30587 | r30588 | |
| 673 | 694 | { |
| 674 | 695 | /* execute the next batch, restoring and re-saving color 0 around it */ |
| 675 | 696 | CUSTOM_REG(REG_COLOR00) = save_color0; |
| 676 | | next_copper_x = amiga_copper_execute_next(machine, x); |
| 697 | next_copper_x = amiga_copper_execute_next(machine(), x); |
| 677 | 698 | save_color0 = CUSTOM_REG(REG_COLOR00); |
| 678 | | if (state->m_genlock_color != 0xffff) |
| 679 | | CUSTOM_REG(REG_COLOR00) = state->m_genlock_color; |
| 699 | if (m_genlock_color != 0xffff) |
| 700 | CUSTOM_REG(REG_COLOR00) = m_genlock_color; |
| 680 | 701 | |
| 681 | 702 | /* compute update-related register values */ |
| 682 | 703 | planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12; |
| 683 | 704 | hires = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HIRES; |
| 684 | 705 | ham = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HOMOD; |
| 685 | 706 | dualpf = CUSTOM_REG(REG_BPLCON0) & BPLCON0_DBLPF; |
| 686 | | //lace = CUSTOM_REG(REG_BPLCON0) & BPLCON0_LACE; |
| 687 | 707 | |
| 688 | 708 | /* compute the pixel fetch parameters */ |
| 689 | 709 | ddf_start_pixel = (CUSTOM_REG(REG_DDFSTRT) & (hires ? 0xfc : 0xf8)) * 2; |
| r30587 | r30588 | |
| 902 | 922 | if (pix) |
| 903 | 923 | dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + pix); |
| 904 | 924 | else |
| 905 | | dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + state->m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]); |
| 925 | dst[x*2+0] = CUSTOM_REG(REG_COLOR00 + m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix0]); |
| 906 | 926 | |
| 907 | 927 | /* mask out the sprite if it doesn't have priority */ |
| 908 | 928 | pix = sprpix & 0x1f; |
| r30587 | r30588 | |
| 918 | 938 | if (pix) |
| 919 | 939 | dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + pix); |
| 920 | 940 | else |
| 921 | | dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + state->m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]); |
| 941 | dst[x*2+1] = CUSTOM_REG(REG_COLOR00 + m_separate_bitplanes[(CUSTOM_REG(REG_BPLCON2) >> 6) & 1][pfpix1]); |
| 922 | 942 | } |
| 923 | 943 | |
| 924 | 944 | /* single playfield mode */ |
| r30587 | r30588 | |
| 945 | 965 | } |
| 946 | 966 | } |
| 947 | 967 | |
| 948 | | #if 0 |
| 949 | | if ( machine.first_screen()->frame_number() % 64 == 0 && scanline == 100 ) |
| 950 | | { |
| 951 | | #if 0 |
| 952 | | const char *m_lores = "LORES"; |
| 953 | | const char *m_hires = "HIRES"; |
| 954 | | const char *m_ham = "HAM"; |
| 955 | | const char *m_dualpf = "DUALPF"; |
| 956 | | //const char *m_lace = "LACE"; |
| 957 | | //const char *m_hilace = "HI-LACE"; |
| 958 | | const char *p = m_lores; |
| 959 | | |
| 960 | | if ( hires ) p = m_hires; |
| 961 | | if ( ham ) p = m_ham; |
| 962 | | if ( dualpf ) p = m_dualpf; |
| 963 | | //if ( lace ) p = m_lace; |
| 964 | | |
| 965 | | //if ( hires && lace ) p = m_hilace; |
| 966 | | #endif |
| 967 | | //popmessage("%s(%d pl od=%04x ed=%04x start=%04x stop=%04x)", p, planes, odelay, edelay, CUSTOM_REG(REG_DDFSTRT), CUSTOM_REG(REG_DDFSTOP) ); |
| 968 | | //popmessage("%s(%d pl y=%d vstart=%04x vstop=%04x start=%04x stop=%04x)", p, planes, scanline, vstart, vstop, CUSTOM_REG(REG_DDFSTRT), CUSTOM_REG(REG_DDFSTOP) ); |
| 969 | | popmessage("DDFSTRT=%04x, DDFSTOP=%04x, DIWSTRT=%04x, DIWSTOP=%04x", CUSTOM_REG(REG_DDFSTRT), CUSTOM_REG(REG_DDFSTOP), CUSTOM_REG(REG_DIWSTRT), CUSTOM_REG(REG_DIWSTOP)); |
| 970 | | } |
| 971 | | #endif |
| 972 | | |
| 973 | | /* end of the line: time to add the modulos */ |
| 968 | // end of the line: time to add the modulos |
| 974 | 969 | if (scanline >= vstart && scanline < vstop) |
| 975 | 970 | { |
| 976 | | /* update odd planes */ |
| 971 | // update odd planes |
| 977 | 972 | for (pl = 0; pl < planes; pl += 2) |
| 978 | 973 | CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL1MOD); |
| 979 | 974 | |
| 980 | | /* update even planes */ |
| 975 | // update even planes |
| 981 | 976 | for (pl = 1; pl < planes; pl += 2) |
| 982 | 977 | CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL2MOD); |
| 983 | | |
| 984 | | if (machine.input().code_pressed(KEYCODE_Q)) |
| 985 | | printf("%03d BPL1MOD=%04x BPL2MOD=%04x BPLCON1=%04x\n", scanline, CUSTOM_REG(REG_BPL1MOD), CUSTOM_REG(REG_BPL2MOD), CUSTOM_REG(REG_BPLCON1)); |
| 986 | 978 | } |
| 987 | 979 | |
| 988 | | /* restore color00 */ |
| 980 | // restore color00 |
| 989 | 981 | CUSTOM_REG(REG_COLOR00) = save_color0; |
| 990 | 982 | |
| 983 | // save |
| 984 | if (dst != NULL) |
| 985 | memcpy(&m_flickerfixer.pix16(save_scanline), dst, amiga_state::SCREEN_WIDTH * 2); |
| 986 | |
| 991 | 987 | #if GUESS_COPPER_OFFSET |
| 992 | 988 | if (m_screen->frame_number() % 64 == 0 && scanline == 0) |
| 993 | 989 | { |
| 994 | 990 | if (machine.input().code_pressed(KEYCODE_Q)) |
| 995 | | popmessage("%d", state->m_wait_offset -= 1); |
| 991 | popmessage("%d", m_wait_offset -= 1); |
| 996 | 992 | if (machine.input().code_pressed(KEYCODE_W)) |
| 997 | | popmessage("%d", state->m_wait_offset += 1); |
| 993 | popmessage("%d", m_wait_offset += 1); |
| 998 | 994 | } |
| 999 | 995 | #endif |
| 1000 | 996 | } |
| r30587 | r30588 | |
| 1017 | 1013 | |
| 1018 | 1014 | // render each scanline in the visible region |
| 1019 | 1015 | for (int y = cliprect.min_y; y <= cliprect.max_y; y++) |
| 1020 | | amiga_render_scanline(machine(), bitmap, y); |
| 1016 | render_scanline(bitmap, y); |
| 1021 | 1017 | |
| 1022 | 1018 | return 0; |
| 1023 | 1019 | } |
| 1020 | |
| 1021 | void amiga_state::update_screenmode() |
| 1022 | { |
| 1023 | amiga_state *state = this; |
| 1024 | bool pal; |
| 1025 | |
| 1026 | // first let's see if we're PAL or NTSC |
| 1027 | if (m_agnus_id >= AGNUS_HR_PAL) |
| 1028 | // we support dynamic switching between PAL and NTSC, determine mode from register |
| 1029 | pal = CUSTOM_REG(REG_BEAMCON0) & 0x20; |
| 1030 | else |
| 1031 | // old agnus, agnus id determines PAL or NTSC |
| 1032 | pal = !(m_agnus_id & 0x10); |
| 1033 | |
| 1034 | // basic height & vblank length |
| 1035 | int height = pal ? SCREEN_HEIGHT_PAL : SCREEN_HEIGHT_NTSC; |
| 1036 | int vblank = pal ? VBLANK_PAL : VBLANK_NTSC; |
| 1037 | |
| 1038 | // frame period |
| 1039 | attoseconds_t period = HZ_TO_ATTOSECONDS(m_screen->clock()) * SCREEN_WIDTH * height; |
| 1040 | |
| 1041 | // interlace mode? |
| 1042 | bool lace = CUSTOM_REG(REG_BPLCON0) & BPLCON0_LACE; |
| 1043 | |
| 1044 | if (lace) |
| 1045 | { |
| 1046 | // this doubles our vertical resolution |
| 1047 | height *= 2; |
| 1048 | height++; |
| 1049 | vblank *= 2; |
| 1050 | } |
| 1051 | |
| 1052 | // adjust visible area |
| 1053 | rectangle visarea = m_screen->visible_area(); |
| 1054 | visarea.sety(vblank, height - 1); |
| 1055 | |
| 1056 | logerror("screenmode changed: %dx%d%s\n", SCREEN_WIDTH, height, lace ? " (interlace)" : ""); |
| 1057 | |
| 1058 | // finally set our new mode |
| 1059 | m_screen->configure(SCREEN_WIDTH, height, visarea, period); |
| 1060 | } |