src/mame/machine/snes.c
| r7300 | r7301 | |
| 120 | 120 | // make sure we're in the 65816's context since we're messing with the OAM and stuff |
| 121 | 121 | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| 122 | 122 | |
| 123 | | if(!(snes_ram[INIDISP]&0x80)) //Reset OAM address, byuu says it happens at H=10 |
| 123 | if (!(snes_ppu.screen_disabled)) //Reset OAM address, byuu says it happens at H=10 |
| 124 | 124 | { |
| 125 | 125 | memory_write_byte(space, OAMADDL, snes_ppu.oam.saved_address_low ); /* Reset oam address */ |
| 126 | 126 | memory_write_byte(space, OAMADDH, snes_ppu.oam.saved_address_high ); |
| r7300 | r7301 | |
| 152 | 152 | } |
| 153 | 153 | } |
| 154 | 154 | /* Horizontal IRQ timer */ |
| 155 | | if( snes_ram[NMITIMEN] & 0x10 ) |
| 155 | if (snes_ram[NMITIMEN] & 0x10) |
| 156 | 156 | { |
| 157 | 157 | int setirq = 1; |
| 158 | 158 | int pixel = ((snes_ram[HTIMEH] << 8) | snes_ram[HTIMEL]) & 0x1ff; |
| r7300 | r7301 | |
| 181 | 181 | } |
| 182 | 182 | |
| 183 | 183 | /* Start of VBlank */ |
| 184 | | if( snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line ) |
| 184 | if (snes_ppu.beam.current_vert == snes_ppu.beam.last_visible_line) |
| 185 | 185 | { |
| 186 | 186 | timer_set(machine, video_screen_get_time_until_pos(machine->primary_screen, snes_ppu.beam.current_vert, 10), NULL, 0, snes_reset_oam_address); |
| 187 | 187 | |
| 188 | 188 | snes_ram[HVBJOY] |= 0x81; /* Set vblank bit to on & indicate controllers being read */ |
| 189 | 189 | snes_ram[RDNMI] |= 0x80; /* Set NMI occured bit */ |
| 190 | 190 | |
| 191 | | if( snes_ram[NMITIMEN] & 0x80 ) /* NMI only signaled if this bit set */ |
| 191 | if (snes_ram[NMITIMEN] & 0x80) /* NMI only signaled if this bit set */ |
| 192 | 192 | { |
| 193 | 193 | // NMI goes off about 12 cycles after this (otherwise Chrono Trigger, NFL QB Club, etc. lock up) |
| 194 | 194 | timer_adjust_oneshot(snes_nmi_timer, cputag_clocks_to_attotime(machine, "maincpu", 12), 0); |
| r7300 | r7301 | |
| 244 | 244 | snes_ram[HVBJOY] &= 0xfe; /* Clear busy bit */ |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | | if( snes_ppu.beam.current_vert == 0 ) |
| 247 | if (snes_ppu.beam.current_vert == 0) |
| 248 | 248 | { /* VBlank is over, time for a new frame */ |
| 249 | 249 | snes_ram[HVBJOY] &= 0x7f; /* Clear vblank bit */ |
| 250 | 250 | snes_ram[RDNMI] &= 0x7f; /* Clear nmi occured bit */ |
| 251 | | snes_ram[STAT77] &= 0x3f; /* Clear Time Over and Range Over bits */ |
| 252 | 251 | snes_ram[STAT78] ^= 0x80; /* Toggle field flag */ |
| 252 | snes_ppu.stat77_flags &= 0x3f; /* Clear Time Over and Range Over bits */ |
| 253 | 253 | |
| 254 | 254 | cputag_set_input_line(machine, "maincpu", G65816_LINE_NMI, CLEAR_LINE ); |
| 255 | 255 | } |
| r7300 | r7301 | |
| 275 | 275 | if (video_screen_get_vpos(machine->primary_screen) > 0) |
| 276 | 276 | { |
| 277 | 277 | /* Do HDMA */ |
| 278 | | if( snes_ram[HDMAEN] ) |
| 278 | if (snes_ram[HDMAEN]) |
| 279 | 279 | snes_hdma(cpu0space); |
| 280 | 280 | |
| 281 | 281 | video_screen_update_partial(machine->primary_screen, (snes_ppu.interlace == 2) ? (snes_ppu.beam.current_vert*snes_ppu.interlace) : snes_ppu.beam.current_vert-1); |
| r7300 | r7301 | |
| 301 | 301 | UINT16 value, dividend, remainder; |
| 302 | 302 | dividend = remainder = 0; |
| 303 | 303 | value = (snes_ram[WRDIVH] << 8) + snes_ram[WRDIVL]; |
| 304 | | if( snes_ram[WRDVDD] > 0 ) |
| 304 | if (snes_ram[WRDVDD] > 0) |
| 305 | 305 | { |
| 306 | 306 | dividend = value / snes_ram[WRDVDD]; |
| 307 | 307 | remainder = value % snes_ram[WRDVDD]; |
| r7300 | r7301 | |
| 342 | 342 | visarea.max_x = (SNES_SCR_WIDTH * 2) - 1; |
| 343 | 343 | |
| 344 | 344 | // fixme: should compensate for SNES_DBG_video |
| 345 | | if( snes_ppu.mode == 5 || snes_ppu.mode == 6 ) |
| 345 | if (snes_ram[SETINI] & 0x08 || snes_ppu.mode == 5 || snes_ppu.mode == 6 ) |
| 346 | 346 | snes_htmult = 2; |
| 347 | 347 | else |
| 348 | 348 | snes_htmult = 1; |
| r7300 | r7301 | |
| 390 | 390 | return spc_port_out[offset & 0x3]; |
| 391 | 391 | } |
| 392 | 392 | |
| 393 | | if(snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 393 | if (snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 394 | 394 | { |
| 395 | | if(offset >= 0x3000 && offset < 0x3300) |
| 395 | if (offset >= 0x3000 && offset < 0x3300) |
| 396 | 396 | { |
| 397 | 397 | return superfx_mmio_read(devtag_get_device(space->machine, "superfx"), offset); |
| 398 | 398 | } |
| 399 | 399 | } |
| 400 | | else if(snes_has_addon_chip == HAS_RTC) |
| 400 | else if (snes_has_addon_chip == HAS_RTC) |
| 401 | 401 | { |
| 402 | | if(offset == 0x2800 || offset == 0x2801) |
| 402 | if (offset == 0x2800 || offset == 0x2801) |
| 403 | 403 | { |
| 404 | 404 | return srtc_mmio_read(space->machine, offset); |
| 405 | 405 | } |
| 406 | 406 | } |
| 407 | | else if(snes_has_addon_chip == HAS_SDD1) |
| 407 | else if (snes_has_addon_chip == HAS_SDD1) |
| 408 | 408 | { |
| 409 | | if(offset >= 0x4800 && offset < 0x4808) |
| 409 | if (offset >= 0x4800 && offset < 0x4808) |
| 410 | 410 | { |
| 411 | 411 | return sdd1_mmio_read(space, (UINT32)offset); |
| 412 | 412 | } |
| 413 | | if(offset < 0x80) |
| 413 | if (offset < 0x80) |
| 414 | 414 | { |
| 415 | 415 | offset += 0x4300; |
| 416 | 416 | } |
| 417 | 417 | } |
| 418 | | else if(snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) |
| 418 | else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) |
| 419 | 419 | { |
| 420 | 420 | UINT16 limit = (snes_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f; |
| 421 | | if(offset >= 0x4800 && offset < limit) |
| 421 | if (offset >= 0x4800 && offset < limit) |
| 422 | 422 | { |
| 423 | 423 | return spc7110_mmio_read(space->machine, offset); |
| 424 | 424 | } |
| 425 | 425 | } |
| 426 | 426 | |
| 427 | 427 | /* offset is from 0x000000 */ |
| 428 | | switch( offset ) |
| 428 | switch (offset) |
| 429 | 429 | { |
| 430 | 430 | case OAMDATA: /* 21xy for x=0,1,2 and y=4,5,6,8,9,a returns PPU1 open bus*/ |
| 431 | 431 | case BGMODE: |
| r7300 | r7301 | |
| 493 | 493 | |
| 494 | 494 | snes_ppu.ppu1_open_bus = (snes_oam[oam_addr] >> (snes_ram[OAMDATA] << 3)) & 0xff; |
| 495 | 495 | snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2; |
| 496 | | if( snes_ram[OAMDATA] == 0 ) |
| 496 | if (snes_ram[OAMDATA] == 0) |
| 497 | 497 | { |
| 498 | 498 | snes_ppu.oam.address++; |
| 499 | 499 | snes_ppu.oam.address_low = snes_ram[OAMADDL] = snes_ppu.oam.address & 0xff; |
| r7300 | r7301 | |
| 597 | 597 | return snes_ppu.ppu2_open_bus; |
| 598 | 598 | } |
| 599 | 599 | case STAT77: /* PPU status flag and version number */ |
| 600 | | value = snes_ram[offset] & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 600 | value = snes_ppu.stat77_flags & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 601 | 601 | // 0x20 - Master/slave mode select. Little is known about this bit. We always seem to read back 0 here. |
| 602 | 602 | value |= (snes_ppu.ppu1_open_bus & 0x10); |
| 603 | 603 | value |= (snes_ppu.ppu1_version & 0x0f); |
| 604 | | snes_ram[offset] = value; // not sure if this is needed... |
| 604 | snes_ppu.stat77_flags = value; // not sure if this is needed... |
| 605 | 605 | snes_ppu.ppu1_open_bus = value; |
| 606 | 606 | return snes_ppu.ppu1_open_bus; |
| 607 | 607 | case STAT78: /* PPU status flag and version number */ |
| r7300 | r7301 | |
| 631 | 631 | return snes_ram[offset]; |
| 632 | 632 | case OLDJOY1: /* Data for old NES controllers (JOYSER1) */ |
| 633 | 633 | { |
| 634 | | if( snes_ram[offset] & 0x1 ) |
| 634 | if (snes_ram[offset] & 0x1) |
| 635 | 635 | { |
| 636 | 636 | return 0 | (snes_open_bus_r(space,0) & 0xfc); //correct? |
| 637 | 637 | } |
| 638 | 638 | value = ((joy1l | (joy1h << 8) | 0x10000) >> (16 - (joypad[0].oldrol & 0xf))) & 0x1; |
| 639 | 639 | joypad[0].oldrol++; |
| 640 | 640 | joypad[0].oldrol&=0xf; |
| 641 | | if( !(joypad[0].oldrol % 17) ) |
| 641 | if (!(joypad[0].oldrol % 17)) |
| 642 | 642 | value = 0x1; |
| 643 | 643 | return (value & 0x03) | (snes_open_bus_r(space,0) & 0xfc); //correct? |
| 644 | 644 | } |
| 645 | 645 | case OLDJOY2: /* Data for old NES controllers (JOYSER2) */ |
| 646 | 646 | { |
| 647 | | if( snes_ram[OLDJOY1] & 0x1 ) |
| 647 | if (snes_ram[OLDJOY1] & 0x1) |
| 648 | 648 | { |
| 649 | 649 | return 0 | 0x1c | (snes_open_bus_r(space,0) & 0xe0); //correct? |
| 650 | 650 | } |
| 651 | 651 | value = ((joy2l | (joy2h << 8) | 0x10000) >> (16 - (joypad[1].oldrol & 0xf))) & 0x1; |
| 652 | 652 | joypad[1].oldrol++; |
| 653 | 653 | joypad[1].oldrol&=0xf; |
| 654 | | if( !(joypad[1].oldrol % 17) ) |
| 654 | if (!(joypad[1].oldrol % 17)) |
| 655 | 655 | value = 0x1; |
| 656 | 656 | //value |= 0x1c; // bits 4, 3, and 2 are always set |
| 657 | 657 | return value | 0x1c | (snes_open_bus_r(space,0) & 0xe0); //correct? |
| r7300 | r7301 | |
| 765 | 765 | return; |
| 766 | 766 | } |
| 767 | 767 | |
| 768 | | if(snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 768 | if (snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 769 | 769 | { |
| 770 | | if(offset >= 0x3000 && offset < 0x3300) |
| 770 | if (offset >= 0x3000 && offset < 0x3300) |
| 771 | 771 | { |
| 772 | 772 | superfx_mmio_write(devtag_get_device(space->machine, "superfx"), offset, data); |
| 773 | 773 | return; |
| 774 | 774 | } |
| 775 | 775 | } |
| 776 | | else if(snes_has_addon_chip == HAS_RTC) |
| 776 | else if (snes_has_addon_chip == HAS_RTC) |
| 777 | 777 | { |
| 778 | | if(offset == 0x2800 || offset == 0x2801) |
| 778 | if (offset == 0x2800 || offset == 0x2801) |
| 779 | 779 | { |
| 780 | 780 | srtc_mmio_write(space->machine, offset, data); |
| 781 | 781 | return; |
| 782 | 782 | } |
| 783 | 783 | } |
| 784 | | else if(snes_has_addon_chip == HAS_SDD1) |
| 784 | else if (snes_has_addon_chip == HAS_SDD1) |
| 785 | 785 | { |
| 786 | | if((offset >= 0x4300 && offset < 0x4380) || |
| 786 | if ((offset >= 0x4300 && offset < 0x4380) || |
| 787 | 787 | (offset >= 0x4800 && offset < 0x4808)) |
| 788 | 788 | { |
| 789 | 789 | sdd1_mmio_write(space, (UINT32)offset, data); |
| 790 | 790 | return; |
| 791 | 791 | } |
| 792 | | if(offset < 0x80) |
| 792 | if (offset < 0x80) |
| 793 | 793 | { |
| 794 | 794 | offset += 0x4300; |
| 795 | 795 | } |
| 796 | 796 | } |
| 797 | | else if(snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) |
| 797 | else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) |
| 798 | 798 | { |
| 799 | 799 | UINT16 limit = (snes_has_addon_chip == HAS_SPC7110_RTC) ? 0x4842 : 0x483f; |
| 800 | | if(offset >= 0x4800 && offset < limit) |
| 800 | if (offset >= 0x4800 && offset < limit) |
| 801 | 801 | { |
| 802 | 802 | spc7110_mmio_write(space->machine, (UINT32)offset, data); |
| 803 | 803 | return; |
| r7300 | r7301 | |
| 805 | 805 | } |
| 806 | 806 | |
| 807 | 807 | /* offset is from 0x000000 */ |
| 808 | | switch( offset ) |
| 808 | switch (offset) |
| 809 | 809 | { |
| 810 | 810 | case INIDISP: /* Initial settings for screen */ |
| 811 | | if((snes_ram[INIDISP] & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 811 | if ((snes_ppu.screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 812 | 812 | { |
| 813 | | memory_write_byte(space, OAMADDL, snes_ppu.oam.saved_address_low ); |
| 814 | | memory_write_byte(space, OAMADDH, snes_ppu.oam.saved_address_high ); |
| 813 | memory_write_byte(space, OAMADDL, snes_ppu.oam.saved_address_low); |
| 814 | memory_write_byte(space, OAMADDH, snes_ppu.oam.saved_address_high); |
| 815 | 815 | } |
| 816 | snes_ppu.screen_disabled = data & 0x80; |
| 817 | snes_ppu.screen_brightness = (data & 0x0f) + 1; |
| 816 | 818 | break; |
| 817 | 819 | case OBSEL: /* Object size and data area designation */ |
| 818 | | snes_ppu.layer[4].data = ((data & 0x3) * 0x2000) << 1; |
| 819 | | snes_ppu.oam.name_select = (((data & 0x18)>>3) * 0x1000) << 1; |
| 820 | snes_ppu.layer[SNES_OAM].data = ((data & 0x3) * 0x2000) << 1; |
| 821 | snes_ppu.oam.name_select = (((data & 0x18) >> 3) * 0x1000) << 1; |
| 820 | 822 | /* Determine object size */ |
| 821 | | switch( (data & 0xe0) >> 5 ) |
| 823 | switch ((data & 0xe0) >> 5) |
| 822 | 824 | { |
| 823 | 825 | case 0: /* 8 & 16 */ |
| 824 | 826 | snes_ppu.oam.size[0] = 1; |
| r7300 | r7301 | |
| 846 | 848 | break; |
| 847 | 849 | default: |
| 848 | 850 | /* Unknown size so default to 8 & 16 */ |
| 849 | | logerror( "Object size unsupported: %d\n", (data & 0xe0) >> 5 ); |
| 851 | logerror("Object size unsupported: %d\n", (data & 0xe0) >> 5); |
| 850 | 852 | |
| 851 | 853 | snes_ppu.oam.size[0] = 1; |
| 852 | 854 | snes_ppu.oam.size[1] = 2; |
| 853 | 855 | #ifdef SNES_DBG_REG_W |
| 854 | | mame_printf_debug( "Object size unsupported: %d\n", (data & 0xe0) >> 5 ); |
| 856 | mame_printf_debug("Object size unsupported: %d\n", (data & 0xe0) >> 5); |
| 855 | 857 | #endif |
| 856 | 858 | } |
| 857 | 859 | break; |
| r7300 | r7301 | |
| 899 | 901 | } |
| 900 | 902 | } |
| 901 | 903 | snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2; |
| 902 | | if( snes_ram[OAMDATA] == 0 ) |
| 904 | if (snes_ram[OAMDATA] == 0) |
| 903 | 905 | { |
| 904 | 906 | snes_ram[OAMDATA] = 0; |
| 905 | 907 | snes_ppu.oam.address++; |
| r7300 | r7301 | |
| 912 | 914 | snes_ppu.mode = data & 0x07; |
| 913 | 915 | snes_dynamic_res_change(space->machine); |
| 914 | 916 | snes_ppu.bg3_priority_bit = data & 0x08; |
| 915 | | snes_ppu.layer[0].tile_size = (data >> 4) & 0x1; |
| 916 | | snes_ppu.layer[1].tile_size = (data >> 5) & 0x1; |
| 917 | | snes_ppu.layer[2].tile_size = (data >> 6) & 0x1; |
| 918 | | snes_ppu.layer[3].tile_size = (data >> 7) & 0x1; |
| 917 | snes_ppu.layer[SNES_BG1].tile_size = (data >> 4) & 0x1; |
| 918 | snes_ppu.layer[SNES_BG2].tile_size = (data >> 5) & 0x1; |
| 919 | snes_ppu.layer[SNES_BG3].tile_size = (data >> 6) & 0x1; |
| 920 | snes_ppu.layer[SNES_BG4].tile_size = (data >> 7) & 0x1; |
| 919 | 921 | snes_ppu.update_offsets = 1; |
| 920 | 922 | break; |
| 921 | 923 | case MOSAIC: /* Size and screen designation for mosaic */ |
| 922 | 924 | /* FIXME: We support horizontal mosaic only partially */ |
| 923 | 925 | snes_ppu.mosaic_size = (data & 0xf0) >> 4; |
| 924 | | snes_ppu.layer[0].mosaic_enabled = data & 0x01; |
| 925 | | snes_ppu.layer[1].mosaic_enabled = data & 0x02; |
| 926 | | snes_ppu.layer[2].mosaic_enabled = data & 0x04; |
| 927 | | snes_ppu.layer[3].mosaic_enabled = data & 0x08; |
| 926 | snes_ppu.layer[SNES_BG1].mosaic_enabled = data & 0x01; |
| 927 | snes_ppu.layer[SNES_BG2].mosaic_enabled = data & 0x02; |
| 928 | snes_ppu.layer[SNES_BG3].mosaic_enabled = data & 0x04; |
| 929 | snes_ppu.layer[SNES_BG4].mosaic_enabled = data & 0x08; |
| 928 | 930 | break; |
| 929 | 931 | case BG1SC: /* Address for storing SC data BG1 SC size designation */ |
| 930 | 932 | case BG2SC: /* Address for storing SC data BG2 SC size designation */ |
| r7300 | r7301 | |
| 934 | 936 | snes_ppu.layer[offset - BG1SC].map_size = data & 0x3; |
| 935 | 937 | break; |
| 936 | 938 | case BG12NBA: /* Address for BG 1 and 2 character data */ |
| 937 | | snes_ppu.layer[0].data = (data & 0xf) << 13; |
| 938 | | snes_ppu.layer[1].data = (data & 0xf0) << 9; |
| 939 | snes_ppu.layer[SNES_BG1].data = (data & 0xf) << 13; |
| 940 | snes_ppu.layer[SNES_BG2].data = (data & 0xf0) << 9; |
| 939 | 941 | break; |
| 940 | 942 | case BG34NBA: /* Address for BG 3 and 4 character data */ |
| 941 | | snes_ppu.layer[2].data = (data & 0xf) << 13; |
| 942 | | snes_ppu.layer[3].data = (data & 0xf0) << 9; |
| 943 | snes_ppu.layer[SNES_BG3].data = (data & 0xf) << 13; |
| 944 | snes_ppu.layer[SNES_BG4].data = (data & 0xf0) << 9; |
| 943 | 945 | break; |
| 944 | 946 | |
| 945 | 947 | // Anomie says "H Current = (Byte<<8) | (Prev&~7) | ((Current>>8)&7); V Current = (Current<<8) | Prev;" and Prev is shared by all scrolls but in Mode 7! |
| 946 | 948 | case BG1HOFS: /* BG1 - horizontal scroll (DW) */ |
| 947 | 949 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 948 | | snes_ppu.layer[0].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[0].offset.horizontal >> 8) & 7); |
| 950 | snes_ppu.layer[SNES_BG1].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG1].offset.horizontal >> 8) & 7); |
| 949 | 951 | snes_ppu.ppu_last_scroll = data; |
| 950 | 952 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 951 | 953 | snes_ppu.mode7.hor_offset = (data << 8) | (snes_ppu.mode7_last_scroll & ~7) | ((snes_ppu.mode7.hor_offset >> 8) & 7); |
| r7300 | r7301 | |
| 954 | 956 | return; |
| 955 | 957 | case BG1VOFS: /* BG1 - vertical scroll (DW) */ |
| 956 | 958 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 957 | | snes_ppu.layer[0].offset.vertical = (data << 8) | snes_ppu.ppu_last_scroll; |
| 959 | snes_ppu.layer[SNES_BG1].offset.vertical = (data << 8) | snes_ppu.ppu_last_scroll; |
| 958 | 960 | snes_ppu.ppu_last_scroll = data; |
| 959 | 961 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 960 | 962 | snes_ppu.mode7.ver_offset = (data << 8) | snes_ppu.mode7_last_scroll; |
| r7300 | r7301 | |
| 962 | 964 | snes_ppu.update_offsets = 1; |
| 963 | 965 | return; |
| 964 | 966 | case BG2HOFS: /* BG2 - horizontal scroll (DW) */ |
| 965 | | snes_ppu.layer[1].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[1].offset.horizontal >> 8) & 7); |
| 967 | snes_ppu.layer[SNES_BG2].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG2].offset.horizontal >> 8) & 7); |
| 966 | 968 | snes_ppu.ppu_last_scroll = data; |
| 967 | 969 | snes_ppu.update_offsets = 1; |
| 968 | 970 | return; |
| 969 | 971 | case BG2VOFS: /* BG2 - vertical scroll (DW) */ |
| 970 | | snes_ppu.layer[1].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 972 | snes_ppu.layer[SNES_BG2].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 971 | 973 | snes_ppu.ppu_last_scroll = data; |
| 972 | 974 | snes_ppu.update_offsets = 1; |
| 973 | 975 | return; |
| 974 | 976 | case BG3HOFS: /* BG3 - horizontal scroll (DW) */ |
| 975 | | snes_ppu.layer[2].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[2].offset.horizontal >> 8) & 7); |
| 977 | snes_ppu.layer[SNES_BG3].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG3].offset.horizontal >> 8) & 7); |
| 976 | 978 | snes_ppu.ppu_last_scroll = data; |
| 977 | 979 | snes_ppu.update_offsets = 1; |
| 978 | 980 | return; |
| 979 | 981 | case BG3VOFS: /* BG3 - vertical scroll (DW) */ |
| 980 | | snes_ppu.layer[2].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 982 | snes_ppu.layer[SNES_BG3].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 981 | 983 | snes_ppu.ppu_last_scroll = data; |
| 982 | 984 | snes_ppu.update_offsets = 1; |
| 983 | 985 | return; |
| 984 | 986 | case BG4HOFS: /* BG4 - horizontal scroll (DW) */ |
| 985 | | snes_ppu.layer[3].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[3].offset.horizontal >> 8) & 7); |
| 987 | snes_ppu.layer[SNES_BG4].offset.horizontal = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG4].offset.horizontal >> 8) & 7); |
| 986 | 988 | snes_ppu.ppu_last_scroll = data; |
| 987 | 989 | snes_ppu.update_offsets = 1; |
| 988 | 990 | return; |
| 989 | 991 | case BG4VOFS: /* BG4 - vertical scroll (DW) */ |
| 990 | | snes_ppu.layer[3].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 992 | snes_ppu.layer[SNES_BG4].offset.vertical = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 991 | 993 | snes_ppu.ppu_last_scroll = data; |
| 992 | 994 | snes_ppu.update_offsets = 1; |
| 993 | 995 | return; |
| r7300 | r7301 | |
| 1124 | 1126 | case W12SEL: /* Window mask settings for BG1-2 */ |
| 1125 | 1127 | if (data != snes_ram[offset]) |
| 1126 | 1128 | { |
| 1127 | | snes_ppu.layer[0].window1_invert = data & 0x01; |
| 1128 | | snes_ppu.layer[0].window1_enabled = data & 0x02; |
| 1129 | | snes_ppu.layer[0].window2_invert = data & 0x04; |
| 1130 | | snes_ppu.layer[0].window2_enabled = data & 0x08; |
| 1131 | | snes_ppu.layer[1].window1_invert = data & 0x10; |
| 1132 | | snes_ppu.layer[1].window1_enabled = data & 0x20; |
| 1133 | | snes_ppu.layer[1].window2_invert = data & 0x40; |
| 1134 | | snes_ppu.layer[1].window2_enabled = data & 0x80; |
| 1129 | snes_ppu.layer[SNES_BG1].window1_invert = data & 0x01; |
| 1130 | snes_ppu.layer[SNES_BG1].window1_enabled = data & 0x02; |
| 1131 | snes_ppu.layer[SNES_BG1].window2_invert = data & 0x04; |
| 1132 | snes_ppu.layer[SNES_BG1].window2_enabled = data & 0x08; |
| 1133 | snes_ppu.layer[SNES_BG2].window1_invert = data & 0x10; |
| 1134 | snes_ppu.layer[SNES_BG2].window1_enabled = data & 0x20; |
| 1135 | snes_ppu.layer[SNES_BG2].window2_invert = data & 0x40; |
| 1136 | snes_ppu.layer[SNES_BG2].window2_enabled = data & 0x80; |
| 1135 | 1137 | snes_ppu.update_windows = 1; |
| 1136 | 1138 | } |
| 1137 | 1139 | break; |
| 1138 | 1140 | case W34SEL: /* Window mask settings for BG3-4 */ |
| 1139 | 1141 | if (data != snes_ram[offset]) |
| 1140 | 1142 | { |
| 1141 | | snes_ppu.layer[2].window1_invert = data & 0x01; |
| 1142 | | snes_ppu.layer[2].window1_enabled = data & 0x02; |
| 1143 | | snes_ppu.layer[2].window2_invert = data & 0x04; |
| 1144 | | snes_ppu.layer[2].window2_enabled = data & 0x08; |
| 1145 | | snes_ppu.layer[3].window1_invert = data & 0x10; |
| 1146 | | snes_ppu.layer[3].window1_enabled = data & 0x20; |
| 1147 | | snes_ppu.layer[3].window2_invert = data & 0x40; |
| 1148 | | snes_ppu.layer[3].window2_enabled = data & 0x80; |
| 1143 | snes_ppu.layer[SNES_BG3].window1_invert = data & 0x01; |
| 1144 | snes_ppu.layer[SNES_BG3].window1_enabled = data & 0x02; |
| 1145 | snes_ppu.layer[SNES_BG3].window2_invert = data & 0x04; |
| 1146 | snes_ppu.layer[SNES_BG3].window2_enabled = data & 0x08; |
| 1147 | snes_ppu.layer[SNES_BG4].window1_invert = data & 0x10; |
| 1148 | snes_ppu.layer[SNES_BG4].window1_enabled = data & 0x20; |
| 1149 | snes_ppu.layer[SNES_BG4].window2_invert = data & 0x40; |
| 1150 | snes_ppu.layer[SNES_BG4].window2_enabled = data & 0x80; |
| 1149 | 1151 | snes_ppu.update_windows = 1; |
| 1150 | 1152 | } |
| 1151 | 1153 | break; |
| 1152 | 1154 | case WOBJSEL: /* Window mask settings for objects */ |
| 1153 | 1155 | if (data != snes_ram[offset]) |
| 1154 | 1156 | { |
| 1155 | | snes_ppu.layer[4].window1_invert = data & 0x01; |
| 1156 | | snes_ppu.layer[4].window1_enabled = data & 0x02; |
| 1157 | | snes_ppu.layer[4].window2_invert = data & 0x04; |
| 1158 | | snes_ppu.layer[4].window2_enabled = data & 0x08; |
| 1157 | snes_ppu.layer[SNES_OAM].window1_invert = data & 0x01; |
| 1158 | snes_ppu.layer[SNES_OAM].window1_enabled = data & 0x02; |
| 1159 | snes_ppu.layer[SNES_OAM].window2_invert = data & 0x04; |
| 1160 | snes_ppu.layer[SNES_OAM].window2_enabled = data & 0x08; |
| 1159 | 1161 | snes_ppu.colour.window1_invert = data & 0x10; |
| 1160 | 1162 | snes_ppu.colour.window1_enabled = data & 0x20; |
| 1161 | 1163 | snes_ppu.colour.window2_invert = data & 0x40; |
| r7300 | r7301 | |
| 1194 | 1196 | case WBGLOG: /* Window mask logic for BG's */ |
| 1195 | 1197 | if (data != snes_ram[offset]) |
| 1196 | 1198 | { |
| 1197 | | snes_ppu.layer[0].wlog_mask = data & 0x03; |
| 1198 | | snes_ppu.layer[1].wlog_mask = (data & 0x0c) >> 2; |
| 1199 | | snes_ppu.layer[2].wlog_mask = (data & 0x30) >> 4; |
| 1200 | | snes_ppu.layer[3].wlog_mask = (data & 0xc0) >> 6; |
| 1199 | snes_ppu.layer[SNES_BG1].wlog_mask = data & 0x03; |
| 1200 | snes_ppu.layer[SNES_BG2].wlog_mask = (data & 0x0c) >> 2; |
| 1201 | snes_ppu.layer[SNES_BG3].wlog_mask = (data & 0x30) >> 4; |
| 1202 | snes_ppu.layer[SNES_BG4].wlog_mask = (data & 0xc0) >> 6; |
| 1201 | 1203 | snes_ppu.update_windows = 1; |
| 1202 | 1204 | } |
| 1203 | 1205 | break; |
| 1204 | 1206 | case WOBJLOG: /* Window mask logic for objects */ |
| 1205 | 1207 | if (data != snes_ram[offset]) |
| 1206 | 1208 | { |
| 1207 | | snes_ppu.layer[4].wlog_mask = data & 0x03; |
| 1209 | snes_ppu.layer[SNES_OAM].wlog_mask = data & 0x03; |
| 1208 | 1210 | snes_ppu.colour.wlog_mask = (data & 0x0c) >> 2; |
| 1209 | 1211 | snes_ppu.update_windows = 1; |
| 1210 | 1212 | } |
| r7300 | r7301 | |
| 1224 | 1226 | snes_ppu.sub_bg_enabled[4] = data & 0x10; |
| 1225 | 1227 | break; |
| 1226 | 1228 | case TMW: /* Window mask for main screen designation */ |
| 1227 | | snes_ppu.layer[0].main_window_enabled = data & 0x01; |
| 1228 | | snes_ppu.layer[1].main_window_enabled = data & 0x02; |
| 1229 | | snes_ppu.layer[2].main_window_enabled = data & 0x04; |
| 1230 | | snes_ppu.layer[3].main_window_enabled = data & 0x08; |
| 1231 | | snes_ppu.layer[4].main_window_enabled = data & 0x10; |
| 1229 | snes_ppu.layer[SNES_BG1].main_window_enabled = data & 0x01; |
| 1230 | snes_ppu.layer[SNES_BG2].main_window_enabled = data & 0x02; |
| 1231 | snes_ppu.layer[SNES_BG3].main_window_enabled = data & 0x04; |
| 1232 | snes_ppu.layer[SNES_BG4].main_window_enabled = data & 0x08; |
| 1233 | snes_ppu.layer[SNES_OAM].main_window_enabled = data & 0x10; |
| 1232 | 1234 | break; |
| 1233 | 1235 | case TSW: /* Window mask for subscreen designation */ |
| 1234 | | snes_ppu.layer[0].sub_window_enabled = data & 0x01; |
| 1235 | | snes_ppu.layer[1].sub_window_enabled = data & 0x02; |
| 1236 | | snes_ppu.layer[2].sub_window_enabled = data & 0x04; |
| 1237 | | snes_ppu.layer[3].sub_window_enabled = data & 0x08; |
| 1238 | | snes_ppu.layer[4].sub_window_enabled = data & 0x10; |
| 1236 | snes_ppu.layer[SNES_BG1].sub_window_enabled = data & 0x01; |
| 1237 | snes_ppu.layer[SNES_BG2].sub_window_enabled = data & 0x02; |
| 1238 | snes_ppu.layer[SNES_BG3].sub_window_enabled = data & 0x04; |
| 1239 | snes_ppu.layer[SNES_BG4].sub_window_enabled = data & 0x08; |
| 1240 | snes_ppu.layer[SNES_OAM].sub_window_enabled = data & 0x10; |
| 1239 | 1241 | break; |
| 1240 | 1242 | case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */ |
| 1241 | 1243 | /* FIXME: We don't support direct select for modes 3 & 4 or subscreen window stuff */ |
| r7300 | r7301 | |
| 1244 | 1246 | snes_ppu.sub_add_mode = data & 0x02; |
| 1245 | 1247 | snes_ppu.direct_color = data & 0x01; |
| 1246 | 1248 | #ifdef SNES_DBG_REG_W |
| 1247 | | if( (data & 0x2) != (snes_ram[CGWSEL] & 0x2) ) |
| 1249 | if ((data & 0x2) != (snes_ram[CGWSEL] & 0x2)) |
| 1248 | 1250 | mame_printf_debug( "Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour" ); |
| 1249 | 1251 | #endif |
| 1250 | 1252 | break; |
| 1251 | 1253 | case CGADSUB: /* Addition/Subtraction designation for each screen */ |
| 1254 | snes_ppu.color_modes = data & 0xc0; |
| 1252 | 1255 | { |
| 1253 | 1256 | UINT8 sub = (data & 0x80) >> 7; |
| 1254 | | snes_ppu.layer[0].blend = (data & 0x1) << sub; |
| 1255 | | snes_ppu.layer[1].blend = ((data & 0x2) >> 1) << sub; |
| 1256 | | snes_ppu.layer[2].blend = ((data & 0x4) >> 2) << sub; |
| 1257 | | snes_ppu.layer[3].blend = ((data & 0x8) >> 3) << sub; |
| 1258 | | snes_ppu.layer[4].blend = ((data & 0x10) >> 4) << sub; |
| 1257 | snes_ppu.layer[SNES_BG1].blend = (data & 0x1) << sub; |
| 1258 | snes_ppu.layer[SNES_BG2].blend = ((data & 0x2) >> 1) << sub; |
| 1259 | snes_ppu.layer[SNES_BG3].blend = ((data & 0x4) >> 2) << sub; |
| 1260 | snes_ppu.layer[SNES_BG4].blend = ((data & 0x8) >> 3) << sub; |
| 1261 | snes_ppu.layer[SNES_OAM].blend = ((data & 0x10) >> 4) << sub; |
| 1259 | 1262 | } break; |
| 1260 | 1263 | case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */ |
| 1261 | 1264 | { |
| 1262 | | /* Store it in the extra space we made in the CGRAM |
| 1263 | | * It doesn't really go there, but it's as good a place as any. */ |
| 1264 | | UINT8 r,g,b; |
| 1265 | /* Store it in the extra space we made in the CGRAM. It doesn't really go there, but it's as good a place as any. */ |
| 1266 | UINT8 r, g, b; |
| 1265 | 1267 | |
| 1266 | 1268 | /* Get existing value. */ |
| 1267 | 1269 | r = snes_cgram[FIXED_COLOUR] & 0x1f; |
| 1268 | 1270 | g = (snes_cgram[FIXED_COLOUR] & 0x3e0) >> 5; |
| 1269 | 1271 | b = (snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10; |
| 1270 | 1272 | /* Set new value */ |
| 1271 | | if( data & 0x20 ) |
| 1273 | if (data & 0x20) |
| 1272 | 1274 | r = data & 0x1f; |
| 1273 | | if( data & 0x40 ) |
| 1275 | if (data & 0x40) |
| 1274 | 1276 | g = data & 0x1f; |
| 1275 | | if( data & 0x80 ) |
| 1277 | if (data & 0x80) |
| 1276 | 1278 | b = data & 0x1f; |
| 1277 | 1279 | snes_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10)); |
| 1278 | 1280 | } break; |
| 1279 | 1281 | case SETINI: /* Screen mode/video select */ |
| 1280 | 1282 | /* FIXME: We only support line count and interlace here */ |
| 1281 | | snes_ppu.interlace = (data & 1) ? 2 : 1; |
| 1282 | | snes_ppu.obj_interlace = (data & 2) ? 2 : 1; |
| 1283 | | snes_ppu.beam.last_visible_line = (data & 0x4) ? 240 : 225; |
| 1283 | snes_ppu.interlace = (data & 0x01) ? 2 : 1; |
| 1284 | snes_ppu.obj_interlace = (data & 0x02) ? 2 : 1; |
| 1285 | snes_ppu.beam.last_visible_line = (data & 0x04) ? 240 : 225; |
| 1286 | snes_ppu.pseudo_hires = data & 0x08; |
| 1287 | snes_ppu.mode7.extbg = data & 0x40; |
| 1284 | 1288 | snes_dynamic_res_change(space->machine); |
| 1285 | 1289 | #ifdef SNES_DBG_REG_W |
| 1286 | | if( (data & 0x8) != (snes_ram[SETINI] & 0x8) ) |
| 1290 | if ((data & 0x8) != (snes_ram[SETINI] & 0x8)) |
| 1287 | 1291 | mame_printf_debug( "Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off" ); |
| 1288 | 1292 | #endif |
| 1289 | 1293 | break; |
| r7300 | r7301 | |
| 1302 | 1306 | case WMADDH: /* Address to read/write to wram (high) */ |
| 1303 | 1307 | break; |
| 1304 | 1308 | case OLDJOY1: /* Old NES joystick support */ |
| 1305 | | if( ((data & 0x1) && !(snes_ram[offset] & 0x1)) || ((!(data & 0x1)) && (snes_ram[offset] & 0x1)) ) |
| 1309 | if (((data & 0x1) && !(snes_ram[offset] & 0x1)) || ((!(data & 0x1)) && (snes_ram[offset] & 0x1))) |
| 1306 | 1310 | { |
| 1307 | 1311 | joypad[0].oldrol = 0; |
| 1308 | 1312 | joypad[1].oldrol = 0; |
| r7300 | r7301 | |
| 1341 | 1345 | data = 0; /* Once DMA is done we need to reset all bits to 0 */ |
| 1342 | 1346 | break; |
| 1343 | 1347 | case HDMAEN: /* HDMA channel designation */ |
| 1344 | | if(data) //if a HDMA is enabled, data is inited at the next scanline |
| 1348 | if (data) //if a HDMA is enabled, data is inited at the next scanline |
| 1345 | 1349 | timer_set(space->machine, video_screen_get_time_until_pos(space->machine->primary_screen, snes_ppu.beam.current_vert+1, 0), NULL, 0, snes_reset_hdma); |
| 1346 | 1350 | break; |
| 1347 | 1351 | case MEMSEL: /* Access cycle designation in memory (2) area */ |
| r7300 | r7301 | |
| 1349 | 1353 | * Currently we are just increasing it no matter what */ |
| 1350 | 1354 | // cpu_set_clockscale(devtag_get_device(space->machine, "maincpu"), (data & 0x1) ? 1.335820896 : 1.0 ); |
| 1351 | 1355 | #ifdef SNES_DBG_REG_W |
| 1352 | | if( (data & 0x1) != (snes_ram[MEMSEL] & 0x1) ) |
| 1356 | if ((data & 0x1) != (snes_ram[MEMSEL] & 0x1)) |
| 1353 | 1357 | mame_printf_debug( "CPU speed: %f Mhz\n", (data & 0x1) ? 3.58 : 2.68 ); |
| 1354 | 1358 | #endif |
| 1355 | 1359 | break; |
| r7300 | r7301 | |
| 1586 | 1590 | else if (snes_cart.mode & 5) /* Mode 20 & 22 */ |
| 1587 | 1591 | { |
| 1588 | 1592 | if ((address < 0x8000) && (snes_cart.mode == SNES_MODE_20)) //FIXME: check this |
| 1589 | | value = snes_ram[0x200000 + ((offset & ~0x8000) | 0x8000)]; /* Reserved */ |
| 1593 | { |
| 1594 | value = 0xff; /* Reserved */ |
| 1595 | //value = snes_ram[0x200000 + ((offset & ~0x8000) | 0x8000)]; // is this hack still needed? /* Reserved */ |
| 1596 | } |
| 1590 | 1597 | else |
| 1591 | 1598 | value = snes_ram[0x400000 + offset]; |
| 1592 | 1599 | } |
| r7300 | r7301 | |
| 1668 | 1675 | |
| 1669 | 1676 | if (address < 0x8000) |
| 1670 | 1677 | { |
| 1671 | | if(address >= 0x6000 && snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 1678 | if (address >= 0x6000 && snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 1672 | 1679 | logerror( "snes_r_bank6 hit in Super FX mode, please fix me\n" ); |
| 1673 | 1680 | else if (snes_cart.mode != SNES_MODE_25) |
| 1674 | 1681 | value = memory_read_byte(space, offset); |
| r7300 | r7301 | |
| 1713 | 1720 | UINT8 value = 0; |
| 1714 | 1721 | UINT16 address = offset & 0xffff; |
| 1715 | 1722 | |
| 1716 | | if(snes_has_addon_chip == HAS_SDD1) |
| 1723 | if (snes_has_addon_chip == HAS_SDD1) |
| 1717 | 1724 | { |
| 1718 | 1725 | return sdd1_read(space->machine, offset); |
| 1719 | 1726 | } |
| 1720 | | else if(snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 1727 | else if (snes_has_addon_chip == HAS_SUPERFX && devtag_get_device(space->machine, "superfx") != NULL) |
| 1721 | 1728 | { |
| 1722 | 1729 | logerror( "snes_r_bank7 hit in Super FX mode, please fix me\n" ); |
| 1723 | 1730 | } |
| r7300 | r7301 | |
| 1894 | 1901 | { |
| 1895 | 1902 | logerror( "snes_w_bank6 hit (RAM) in Super FX mode, please fix me\n" ); |
| 1896 | 1903 | } |
| 1897 | | else if(snes_has_addon_chip == HAS_CX4) |
| 1904 | else if (snes_has_addon_chip == HAS_CX4) |
| 1898 | 1905 | { |
| 1899 | 1906 | //printf( "R: CX4 hit from 0x800000\n" ); |
| 1900 | 1907 | } |
| r7300 | r7301 | |
| 2094 | 2101 | } |
| 2095 | 2102 | |
| 2096 | 2103 | // init frame counter so first line is 0 |
| 2097 | | if( ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) >= 59 ) |
| 2104 | if (ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) >= 59) |
| 2098 | 2105 | { |
| 2099 | 2106 | snes_ppu.beam.current_vert = SNES_VTOTAL_NTSC; |
| 2100 | 2107 | } |
| r7300 | r7301 | |
| 2109 | 2116 | UINT8 mask = 1, dma = 0, i; |
| 2110 | 2117 | |
| 2111 | 2118 | snes_hdma_chnl = snes_ram[HDMAEN]; |
| 2112 | | for( i = 0; i < 8; i++ ) |
| 2119 | for (i = 0; i < 8; i++) |
| 2113 | 2120 | { |
| 2114 | | if( snes_ram[HDMAEN] & mask ) |
| 2121 | if (snes_ram[HDMAEN] & mask) |
| 2115 | 2122 | { |
| 2116 | 2123 | snes_ram[SNES_DMA_BASE + dma + 8] = snes_ram[SNES_DMA_BASE + dma + 2]; |
| 2117 | 2124 | snes_ram[SNES_DMA_BASE + dma + 9] = snes_ram[SNES_DMA_BASE + dma + 3]; |
| r7300 | r7301 | |
| 2150 | 2157 | snes_ram[WRDIVL] = 0xff; |
| 2151 | 2158 | snes_ram[WRDIVH] = 0xff; |
| 2152 | 2159 | |
| 2153 | | switch(snes_has_addon_chip) |
| 2160 | switch (snes_has_addon_chip) |
| 2154 | 2161 | { |
| 2155 | 2162 | case HAS_SDD1: |
| 2156 | 2163 | sdd1_init(machine); |
| r7300 | r7301 | |
| 2172 | 2179 | snes_init_ram(machine); |
| 2173 | 2180 | |
| 2174 | 2181 | /* Set STAT78 to NTSC or PAL */ |
| 2175 | | if( ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) >= 59.0f ) |
| 2182 | if (ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) >= 59.0f) |
| 2176 | 2183 | snes_ram[STAT78] = SNES_NTSC; |
| 2177 | | else /* if( ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) == 50.0f ) */ |
| 2184 | else /* if (ATTOSECONDS_TO_HZ(video_screen_get_frame_period(machine->primary_screen).attoseconds) == 50.0f) */ |
| 2178 | 2185 | snes_ram[STAT78] = SNES_PAL; |
| 2179 | 2186 | |
| 2180 | 2187 | // reset does this to these registers |
| r7300 | r7301 | |
| 2331 | 2338 | UINT32 abus; |
| 2332 | 2339 | |
| 2333 | 2340 | /* Assume priority of the 8 DMA channels is 0-7 */ |
| 2334 | | for( i = 0; i < 8; i++ ) |
| 2341 | for (i = 0; i < 8; i++) |
| 2335 | 2342 | { |
| 2336 | | if( snes_hdma_chnl & mask ) |
| 2343 | if (snes_hdma_chnl & mask) |
| 2337 | 2344 | { |
| 2338 | 2345 | /* Check if we need to read a new line from the table */ |
| 2339 | | if( !(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f ) ) |
| 2346 | if (!(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f)) |
| 2340 | 2347 | { |
| 2341 | 2348 | abus = (snes_ram[SNES_DMA_BASE + dma + 4] << 16) + (snes_ram[SNES_DMA_BASE + dma + 9] << 8) + snes_ram[SNES_DMA_BASE + dma + 8]; |
| 2342 | 2349 | |
| 2343 | 2350 | /* Get the number of lines */ |
| 2344 | 2351 | snes_ram[SNES_DMA_BASE + dma + 0xa] = memory_read_byte(space, abus); |
| 2345 | | if( !snes_ram[SNES_DMA_BASE + dma + 0xa] ) |
| 2352 | if (!snes_ram[SNES_DMA_BASE + dma + 0xa]) |
| 2346 | 2353 | { |
| 2347 | 2354 | /* No more lines so clear HDMA */ |
| 2348 | 2355 | snes_hdma_chnl &= ~mask; |
| r7300 | r7301 | |
| 2351 | 2358 | abus++; |
| 2352 | 2359 | snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff; |
| 2353 | 2360 | snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff; |
| 2354 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x40 ) |
| 2361 | if (snes_ram[SNES_DMA_BASE + dma] & 0x40) |
| 2355 | 2362 | { |
| 2356 | 2363 | snes_ram[SNES_DMA_BASE + dma + 5] = memory_read_byte(space, abus++); |
| 2357 | 2364 | snes_ram[SNES_DMA_BASE + dma + 6] = memory_read_byte(space, abus++); |
| r7300 | r7301 | |
| 2363 | 2370 | contmode = (--snes_ram[SNES_DMA_BASE + dma + 0xa]) & 0x80; |
| 2364 | 2371 | |
| 2365 | 2372 | /* Transfer addresses */ |
| 2366 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x40 ) /* Indirect */ |
| 2373 | if (snes_ram[SNES_DMA_BASE + dma] & 0x40) /* Indirect */ |
| 2367 | 2374 | abus = (snes_ram[SNES_DMA_BASE + dma + 7] << 16) + (snes_ram[SNES_DMA_BASE + dma + 6] << 8) + snes_ram[SNES_DMA_BASE + dma + 5]; |
| 2368 | 2375 | else /* Absolute */ |
| 2369 | 2376 | abus = (snes_ram[SNES_DMA_BASE + dma + 4] << 16) + (snes_ram[SNES_DMA_BASE + dma + 9] << 8) + snes_ram[SNES_DMA_BASE + dma + 8]; |
| r7300 | r7301 | |
| 2373 | 2380 | mame_printf_debug( "HDMA-Ch: %d(%s) abus: %X bbus: %X type: %d(%X %X)\n", i, snes_ram[SNES_DMA_BASE + dma] & 0x40 ? "Indirect" : "Absolute", abus, bbus, snes_ram[SNES_DMA_BASE + dma] & 0x7, snes_ram[SNES_DMA_BASE + dma + 8],snes_ram[SNES_DMA_BASE + dma + 9] ); |
| 2374 | 2381 | #endif |
| 2375 | 2382 | |
| 2376 | | switch( snes_ram[SNES_DMA_BASE + dma] & 0x7 ) |
| 2383 | switch (snes_ram[SNES_DMA_BASE + dma] & 0x7) |
| 2377 | 2384 | { |
| 2378 | 2385 | case 0: /* 1 address */ |
| 2379 | 2386 | { |
| r7300 | r7301 | |
| 2420 | 2427 | } |
| 2421 | 2428 | |
| 2422 | 2429 | /* Update address */ |
| 2423 | | if( contmode ) |
| 2430 | if (contmode) |
| 2424 | 2431 | { |
| 2425 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x40 ) /* Indirect */ |
| 2432 | if (snes_ram[SNES_DMA_BASE + dma] & 0x40) /* Indirect */ |
| 2426 | 2433 | { |
| 2427 | 2434 | snes_ram[SNES_DMA_BASE + dma + 5] = abus & 0xff; |
| 2428 | 2435 | snes_ram[SNES_DMA_BASE + dma + 6] = (abus >> 8) & 0xff; |
| r7300 | r7301 | |
| 2434 | 2441 | } |
| 2435 | 2442 | } |
| 2436 | 2443 | |
| 2437 | | if( !(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f) ) |
| 2444 | if (!(snes_ram[SNES_DMA_BASE + dma + 0xa] & 0x7f)) |
| 2438 | 2445 | { |
| 2439 | | if( !(snes_ram[SNES_DMA_BASE + dma] & 0x40) ) /* Absolute */ |
| 2446 | if (!(snes_ram[SNES_DMA_BASE + dma] & 0x40)) /* Absolute */ |
| 2440 | 2447 | { |
| 2441 | | if( !contmode ) |
| 2448 | if (!contmode) |
| 2442 | 2449 | { |
| 2443 | 2450 | snes_ram[SNES_DMA_BASE + dma + 8] = abus & 0xff; |
| 2444 | 2451 | snes_ram[SNES_DMA_BASE + dma + 9] = (abus >> 8) & 0xff; |
| r7300 | r7301 | |
| 2459 | 2466 | UINT32 abus, abus_bank, length; |
| 2460 | 2467 | |
| 2461 | 2468 | /* Assume priority of the 8 DMA channels is 0-7 */ |
| 2462 | | for( i = 0; i < 8; i++ ) |
| 2469 | for (i = 0; i < 8; i++) |
| 2463 | 2470 | { |
| 2464 | | if( channels & mask ) |
| 2471 | if (channels & mask) |
| 2465 | 2472 | { |
| 2466 | 2473 | //printf( "Making a transfer on channel %d\n", i ); |
| 2467 | 2474 | /* Find transfer addresses */ |
| r7300 | r7301 | |
| 2471 | 2478 | |
| 2472 | 2479 | //printf( "Address: %06x\n", abus | abus_bank ); |
| 2473 | 2480 | /* Auto increment */ |
| 2474 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x8 ) |
| 2481 | if (snes_ram[SNES_DMA_BASE + dma] & 0x8) |
| 2475 | 2482 | { |
| 2476 | 2483 | increment = 0; |
| 2477 | 2484 | } |
| 2478 | 2485 | else |
| 2479 | 2486 | { |
| 2480 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x10 ) |
| 2487 | if (snes_ram[SNES_DMA_BASE + dma] & 0x10) |
| 2481 | 2488 | increment = -1; |
| 2482 | 2489 | else |
| 2483 | 2490 | increment = 1; |
| r7300 | r7301 | |
| 2485 | 2492 | |
| 2486 | 2493 | /* Number of bytes to transfer */ |
| 2487 | 2494 | length = (snes_ram[SNES_DMA_BASE + dma + 6] << 8) + snes_ram[SNES_DMA_BASE + dma + 5]; |
| 2488 | | if( !length ) |
| 2495 | if (!length) |
| 2489 | 2496 | length = 0x10000; /* 0x0000 really means 0x10000 */ |
| 2490 | 2497 | |
| 2491 | 2498 | // printf( "GDMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus, bbus, increment, snes_ram[SNES_DMA_BASE + dma] & 0x80 ? "PPU->CPU" : "CPU->PPU", snes_ram[SNES_DMA_BASE + dma] & 0x7 ); |
| r7300 | r7301 | |
| 2494 | 2501 | mame_printf_debug( "GDMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus, bbus, increment, snes_ram[SNES_DMA_BASE + dma] & 0x80 ? "PPU->CPU" : "CPU->PPU", snes_ram[SNES_DMA_BASE + dma] & 0x7 ); |
| 2495 | 2502 | #endif |
| 2496 | 2503 | |
| 2497 | | switch( snes_ram[SNES_DMA_BASE + dma] & 0x7 ) |
| 2504 | switch (snes_ram[SNES_DMA_BASE + dma] & 0x7) |
| 2498 | 2505 | { |
| 2499 | 2506 | case 0: /* 1 address */ |
| 2500 | 2507 | case 2: /* 1 address ?? */ |
| 2501 | 2508 | case 6: |
| 2502 | 2509 | { |
| 2503 | | while( length-- ) |
| 2510 | while (length--) |
| 2504 | 2511 | { |
| 2505 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2512 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2506 | 2513 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus) ); |
| 2507 | 2514 | else /* CPU->PPU */ |
| 2508 | 2515 | memory_write_byte(space, bbus, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| r7300 | r7301 | |
| 2512 | 2519 | case 1: /* 2 addresses (l,h) */ |
| 2513 | 2520 | case 5: |
| 2514 | 2521 | { |
| 2515 | | while( length-- ) |
| 2522 | while (length--) |
| 2516 | 2523 | { |
| 2517 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2524 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2518 | 2525 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus) ); |
| 2519 | 2526 | else /* CPU->PPU */ |
| 2520 | 2527 | memory_write_byte(space, bbus, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2521 | 2528 | abus += increment; |
| 2522 | | if( !(length--) ) |
| 2529 | if (!(length--)) |
| 2523 | 2530 | break; |
| 2524 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2531 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2525 | 2532 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 1) ); |
| 2526 | 2533 | else /* CPU->PPU */ |
| 2527 | 2534 | memory_write_byte(space, bbus + 1, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| r7300 | r7301 | |
| 2531 | 2538 | case 3: /* 2 addresses/write twice (l,l,h,h) */ |
| 2532 | 2539 | case 7: |
| 2533 | 2540 | { |
| 2534 | | while( length-- ) |
| 2541 | while (length--) |
| 2535 | 2542 | { |
| 2536 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2543 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2537 | 2544 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus) ); |
| 2538 | 2545 | else /* CPU->PPU */ |
| 2539 | 2546 | memory_write_byte(space, bbus, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2540 | 2547 | abus += increment; |
| 2541 | | if( !(length--) ) |
| 2548 | if (!(length--)) |
| 2542 | 2549 | break; |
| 2543 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2550 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2544 | 2551 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus) ); |
| 2545 | 2552 | else /* CPU->PPU */ |
| 2546 | 2553 | memory_write_byte(space, bbus, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2547 | 2554 | abus += increment; |
| 2548 | | if( !(length--) ) |
| 2555 | if (!(length--)) |
| 2549 | 2556 | break; |
| 2550 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2557 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2551 | 2558 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 1) ); |
| 2552 | 2559 | else /* CPU->PPU */ |
| 2553 | 2560 | memory_write_byte(space, bbus + 1, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2554 | 2561 | abus += increment; |
| 2555 | | if( !(length--) ) |
| 2562 | if (!(length--)) |
| 2556 | 2563 | break; |
| 2557 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2564 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2558 | 2565 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 1) ); |
| 2559 | 2566 | else /* CPU->PPU */ |
| 2560 | 2567 | memory_write_byte(space, bbus + 1, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| r7300 | r7301 | |
| 2563 | 2570 | } break; |
| 2564 | 2571 | case 4: /* 4 addresses (l,h,l,h) */ |
| 2565 | 2572 | { |
| 2566 | | while( length-- ) |
| 2573 | while (length--) |
| 2567 | 2574 | { |
| 2568 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2575 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2569 | 2576 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus) ); |
| 2570 | 2577 | else /* CPU->PPU */ |
| 2571 | 2578 | memory_write_byte(space, bbus, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2572 | 2579 | abus += increment; |
| 2573 | | if( !(length--) ) |
| 2580 | if (!(length--)) |
| 2574 | 2581 | break; |
| 2575 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2582 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2576 | 2583 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 1) ); |
| 2577 | 2584 | else /* CPU->PPU */ |
| 2578 | 2585 | memory_write_byte(space, bbus + 1, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2579 | 2586 | abus += increment; |
| 2580 | | if( !(length--) ) |
| 2587 | if (!(length--)) |
| 2581 | 2588 | break; |
| 2582 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2589 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2583 | 2590 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 2) ); |
| 2584 | 2591 | else /* CPU->PPU */ |
| 2585 | 2592 | memory_write_byte(space, bbus + 2, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
| 2586 | 2593 | abus += increment; |
| 2587 | | if( !(length--) ) |
| 2594 | if (!(length--)) |
| 2588 | 2595 | break; |
| 2589 | | if( snes_ram[SNES_DMA_BASE + dma] & 0x80 ) /* PPU->CPU */ |
| 2596 | if (snes_ram[SNES_DMA_BASE + dma] & 0x80) /* PPU->CPU */ |
| 2590 | 2597 | memory_write_byte(space, ((abus & 0xffff) | (abus_bank)), memory_read_byte(space, bbus + 3) ); |
| 2591 | 2598 | else /* CPU->PPU */ |
| 2592 | 2599 | memory_write_byte(space, bbus + 3, memory_read_byte(space, ((abus & 0xffff) | (abus_bank))) ); |
src/mame/video/snes.c
| r7300 | r7301 | |
| 140 | 140 | INLINE void snes_draw_blend(UINT16 offset, UINT16 *colour, UINT8 mode, UINT8 clip, UINT8 black_pen_clip ) |
| 141 | 141 | { |
| 142 | 142 | if( (black_pen_clip == SNES_CLIP_ALL2) || |
| 143 | | (black_pen_clip == SNES_CLIP_IN && snes_ppu.clipmasks[5][offset]) || |
| 144 | | (black_pen_clip == SNES_CLIP_OUT && !snes_ppu.clipmasks[5][offset])) |
| 143 | (black_pen_clip == SNES_CLIP_IN && snes_ppu.clipmasks[SNES_COLOR][offset]) || |
| 144 | (black_pen_clip == SNES_CLIP_OUT && !snes_ppu.clipmasks[SNES_COLOR][offset])) |
| 145 | 145 | *colour = 0; //clip to black before color math |
| 146 | 146 | |
| 147 | 147 | if (clip == SNES_CLIP_ALL2) // blending mode 3 == always OFF |
| r7300 | r7301 | |
| 151 | 151 | if( !debug_options.transparency_disabled ) |
| 152 | 152 | #endif /* MAME_DEBUG */ |
| 153 | 153 | if( (clip == SNES_CLIP_ALL) || |
| 154 | | (clip == SNES_CLIP_IN && !snes_ppu.clipmasks[5][offset]) || |
| 155 | | (clip == SNES_CLIP_OUT && snes_ppu.clipmasks[5][offset]) ) |
| 154 | (clip == SNES_CLIP_IN && !snes_ppu.clipmasks[SNES_COLOR][offset]) || |
| 155 | (clip == SNES_CLIP_OUT && snes_ppu.clipmasks[SNES_COLOR][offset]) ) |
| 156 | 156 | { |
| 157 | 157 | UINT16 r, g, b; |
| 158 | 158 | |
| r7300 | r7301 | |
| 165 | 165 | b = ((*colour & 0x7c00) >> 10) + ((scanlines[SUBSCREEN].buffer[offset] & 0x7c00) >> 10); |
| 166 | 166 | |
| 167 | 167 | /* don't halve for the back colour */ |
| 168 | | if( (snes_ram[CGADSUB] & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR]) ) |
| 168 | if ((snes_ppu.color_modes & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR])) |
| 169 | 169 | { |
| 170 | 170 | r >>= 1; |
| 171 | 171 | g >>= 1; |
| r7300 | r7301 | |
| 179 | 179 | b = ((*colour & 0x7c00) >> 10) + ((snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 180 | 180 | |
| 181 | 181 | /* don't halve for the back colour */ |
| 182 | | if( (snes_ram[CGADSUB] & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR]) ) |
| 182 | if ((snes_ppu.color_modes & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR])) |
| 183 | 183 | { |
| 184 | 184 | r >>= 1; |
| 185 | 185 | g >>= 1; |
| r7300 | r7301 | |
| 203 | 203 | if( b > 0x1f ) b = 0; |
| 204 | 204 | |
| 205 | 205 | /* don't halve for the back colour */ |
| 206 | | if( (snes_ram[CGADSUB] & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR]) ) |
| 206 | if ((snes_ppu.color_modes & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR])) |
| 207 | 207 | { |
| 208 | 208 | r >>= 1; |
| 209 | 209 | g >>= 1; |
| r7300 | r7301 | |
| 220 | 220 | if( b > 0x1f ) b = 0; |
| 221 | 221 | |
| 222 | 222 | /* don't halve for the back colour */ |
| 223 | | if( (snes_ram[CGADSUB] & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR]) ) |
| 223 | if ((snes_ppu.color_modes & 0x40) && (scanlines[SUBSCREEN].zbuf[offset] || scanlines[SUBSCREEN].buffer[offset] != snes_cgram[FIXED_COLOUR])) |
| 224 | 224 | { |
| 225 | 225 | r >>= 1; |
| 226 | 226 | g >>= 1; |
| r7300 | r7301 | |
| 385 | 385 | if (!debug_options.windows_disabled) |
| 386 | 386 | #endif /* MAME_DEBUG */ |
| 387 | 387 | /* Clip to windows */ |
| 388 | | window_enabled = (screen == MAINSCREEN) ? snes_ppu.layer[4].main_window_enabled : snes_ppu.layer[4].sub_window_enabled; |
| 388 | window_enabled = (screen == MAINSCREEN) ? snes_ppu.layer[4].main_window_enabled : snes_ppu.layer[SNES_OAM].sub_window_enabled; |
| 389 | 389 | if (window_enabled) |
| 390 | | colour &= snes_ppu.clipmasks[4][ii]; |
| 390 | colour &= snes_ppu.clipmasks[SNES_OAM][ii]; |
| 391 | 391 | |
| 392 | 392 | /* Only draw if we have a colour (0 == transparent) */ |
| 393 | 393 | if (colour) |
| r7300 | r7301 | |
| 396 | 396 | { |
| 397 | 397 | c = snes_cgram[pal + colour]; |
| 398 | 398 | if (blend && screen == MAINSCREEN) /* Only blend main screens */ |
| 399 | | snes_draw_blend(ii/snes_htmult, &c, snes_ppu.layer[4].blend, snes_ppu.sub_color_mask, snes_ppu.main_color_mask); |
| 399 | snes_draw_blend(ii/snes_htmult, &c, snes_ppu.layer[SNES_OAM].blend, snes_ppu.sub_color_mask, snes_ppu.main_color_mask); |
| 400 | 400 | |
| 401 | 401 | scanlines[screen].buffer[ii] = c; |
| 402 | 402 | scanlines[screen].zbuf[ii] = priority; |
| r7300 | r7301 | |
| 654 | 654 | /* MOSAIC - to be verified */ |
| 655 | 655 | if (layer == 1) // BG2 use two different bits for horizontal and vertical mosaic |
| 656 | 656 | { |
| 657 | | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 658 | | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[0].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 657 | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG2].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 658 | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 659 | 659 | } |
| 660 | 660 | else // BG1 works as usual |
| 661 | 661 | { |
| 662 | | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[0].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 663 | | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[0].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 662 | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 663 | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 664 | 664 | } |
| 665 | 665 | |
| 666 | 666 | /* Let's do some mode7 drawing huh? */ |
| r7300 | r7301 | |
| 830 | 830 | if( (x + (count << 3) < SNES_SCR_WIDTH + 8) ) |
| 831 | 831 | { |
| 832 | 832 | if( widemode ) |
| 833 | | snes_draw_tile_object(screen, snes_ppu.layer[4].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (count++ << 3), priority, hflip, pal, blend, 1); |
| 833 | snes_draw_tile_object(screen, snes_ppu.layer[SNES_OAM].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (count++ << 3), priority, hflip, pal, blend, 1); |
| 834 | 834 | else |
| 835 | | snes_draw_tile_object(screen, snes_ppu.layer[4].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (count++ << 3), priority, hflip, pal, blend, 0); |
| 835 | snes_draw_tile_object(screen, snes_ppu.layer[SNES_OAM].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (count++ << 3), priority, hflip, pal, blend, 0); |
| 836 | 836 | } |
| 837 | 837 | time_over++; /* Increase time_over. Should we stop drawing if exceeded 34 tiles? */ |
| 838 | 838 | } |
| r7300 | r7301 | |
| 844 | 844 | if( (x + (xs << 3) < SNES_SCR_WIDTH + 8) ) |
| 845 | 845 | { |
| 846 | 846 | if( widemode ) |
| 847 | | snes_draw_tile_object(screen, snes_ppu.layer[4].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (xs << 3), priority, hflip, pal, blend, 1); |
| 847 | snes_draw_tile_object(screen, snes_ppu.layer[SNES_OAM].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (xs << 3), priority, hflip, pal, blend, 1); |
| 848 | 848 | else |
| 849 | | snes_draw_tile_object(screen, snes_ppu.layer[4].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (xs << 3), priority, hflip, pal, blend, 0); |
| 849 | snes_draw_tile_object(screen, snes_ppu.layer[SNES_OAM].data + name_sel + tile + table_obj_offset[ys][xs] + line, x + (xs << 3), priority, hflip, pal, blend, 0); |
| 850 | 850 | } |
| 851 | 851 | time_over++; /* Increase time_over. Should we stop drawing if exceeded 34 tiles? */ |
| 852 | 852 | } |
| 853 | 853 | } |
| 854 | 854 | |
| 855 | | /* Increase range_over. |
| 856 | | * Stop drawing if exceeded 32 objects and |
| 857 | | * enforcing that limit is enabled */ |
| 855 | /* Increase range_over. Stop drawing if exceeded 32 objects and enforcing that limit is enabled */ |
| 858 | 856 | range_over++; |
| 859 | | if( range_over == 32 ) //&& (input_port_read(machine, "INTERNAL") & 0x01) ) |
| 857 | if (range_over == 32) //&& (input_port_read(machine, "INTERNAL") & 0x01) ) |
| 860 | 858 | { |
| 861 | 859 | /* Set the flag in STAT77 register */ |
| 862 | | snes_ram[STAT77] |= 0x40; |
| 863 | | /* FIXME: This stops the SNESTest rom from drawing the object |
| 864 | | * test properly. Maybe we shouldn't stop drawing? */ |
| 860 | snes_ppu.stat77_flags |= 0x40; |
| 861 | /* FIXME: This stops the SNESTest rom from drawing the object test properly. Maybe we shouldn't stop drawing? */ |
| 865 | 862 | /* return; */ |
| 866 | 863 | } |
| 867 | 864 | } |
| 868 | 865 | } |
| 869 | 866 | |
| 870 | | if( time_over >= 34 ) |
| 867 | if (time_over >= 34) |
| 871 | 868 | { |
| 872 | 869 | /* Set the flag in STAT77 register */ |
| 873 | | snes_ram[STAT77] |= 0x80; |
| 870 | snes_ppu.stat77_flags |= 0x80; |
| 874 | 871 | } |
| 875 | 872 | } |
| 876 | 873 | |
| r7300 | r7301 | |
| 964 | 961 | |
| 965 | 962 | static void snes_update_mode_7( UINT8 screen, UINT16 curline ) |
| 966 | 963 | { |
| 967 | | UINT8 extbg_mode = snes_ram[SETINI] & 0x40; |
| 968 | 964 | UINT8 *bg_enabled; |
| 969 | 965 | bg_enabled = (screen == MAINSCREEN) ? snes_ppu.main_bg_enabled : snes_ppu.sub_bg_enabled; |
| 970 | 966 | |
| 971 | | if (!extbg_mode) |
| 967 | if (!snes_ppu.mode7.extbg) |
| 972 | 968 | { |
| 973 | 969 | if (bg_enabled[4]) snes_update_objects(screen, 7, curline); |
| 974 | 970 | if (bg_enabled[0]) snes_update_line_mode7(screen, 1, 1, 0, curline); |
| r7300 | r7301 | |
| 1071 | 1067 | } |
| 1072 | 1068 | |
| 1073 | 1069 | /* update colour window */ |
| 1074 | | snes_ppu.clipmasks[5][ii] = 0xff; |
| 1070 | snes_ppu.clipmasks[SNES_COLOR][ii] = 0xff; |
| 1075 | 1071 | w1 = w2 = -1; |
| 1076 | 1072 | if (snes_ppu.colour.window1_enabled) |
| 1077 | 1073 | { |
| r7300 | r7301 | |
| 1093 | 1089 | if (snes_ppu.colour.window2_invert) |
| 1094 | 1090 | w2 = !w2; |
| 1095 | 1091 | } |
| 1096 | | if( w1 >= 0 && w2 >= 0 ) |
| 1092 | if (w1 >= 0 && w2 >= 0) |
| 1097 | 1093 | { |
| 1098 | 1094 | switch (snes_ppu.colour.wlog_mask) |
| 1099 | 1095 | { |
| 1100 | 1096 | case 0x0: /* OR */ |
| 1101 | | snes_ppu.clipmasks[5][ii] = w1 | w2 ? 0x00 : 0xff; |
| 1097 | snes_ppu.clipmasks[SNES_COLOR][ii] = w1 | w2 ? 0x00 : 0xff; |
| 1102 | 1098 | break; |
| 1103 | 1099 | case 0x4: /* AND */ |
| 1104 | | snes_ppu.clipmasks[5][ii] = w1 & w2 ? 0x00 : 0xff; |
| 1100 | snes_ppu.clipmasks[SNES_COLOR][ii] = w1 & w2 ? 0x00 : 0xff; |
| 1105 | 1101 | break; |
| 1106 | 1102 | case 0x8: /* XOR */ |
| 1107 | | snes_ppu.clipmasks[5][ii] = w1 ^ w2 ? 0x00 : 0xff; |
| 1103 | snes_ppu.clipmasks[SNES_COLOR][ii] = w1 ^ w2 ? 0x00 : 0xff; |
| 1108 | 1104 | break; |
| 1109 | 1105 | case 0xc: /* XNOR */ |
| 1110 | | snes_ppu.clipmasks[5][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1106 | snes_ppu.clipmasks[SNES_COLOR][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1111 | 1107 | break; |
| 1112 | 1108 | } |
| 1113 | 1109 | } |
| 1114 | | else if( w1 >= 0 ) |
| 1115 | | snes_ppu.clipmasks[5][ii] = w1 ? 0x00 : 0xff; |
| 1116 | | else if( w2 >= 0 ) |
| 1117 | | snes_ppu.clipmasks[5][ii] = w2 ? 0x00 : 0xff; |
| 1110 | else if (w1 >= 0) |
| 1111 | snes_ppu.clipmasks[SNES_COLOR][ii] = w1 ? 0x00 : 0xff; |
| 1112 | else if (w2 >= 0) |
| 1113 | snes_ppu.clipmasks[SNES_COLOR][ii] = w2 ? 0x00 : 0xff; |
| 1118 | 1114 | } |
| 1119 | 1115 | } |
| 1120 | 1116 | |
| r7300 | r7301 | |
| 1135 | 1131 | } |
| 1136 | 1132 | #if 0 |
| 1137 | 1133 | popmessage("%04x %04x|%04x %04x|%04x %04x|%04x %04x", |
| 1138 | | snes_ppu.layer[0].offset.tile_horz, |
| 1139 | | snes_ppu.layer[0].offset.tile_vert, |
| 1140 | | snes_ppu.layer[1].offset.tile_horz, |
| 1141 | | snes_ppu.layer[1].offset.tile_vert, |
| 1142 | | snes_ppu.layer[2].offset.tile_horz, |
| 1143 | | snes_ppu.layer[2].offset.tile_vert, |
| 1144 | | snes_ppu.layer[3].offset.tile_horz, |
| 1145 | | snes_ppu.layer[3].offset.tile_vert |
| 1134 | snes_ppu.layer[SNES_BG1].offset.tile_horz, |
| 1135 | snes_ppu.layer[SNES_BG1].offset.tile_vert, |
| 1136 | snes_ppu.layer[SNES_BG2].offset.tile_horz, |
| 1137 | snes_ppu.layer[SNES_BG2].offset.tile_vert, |
| 1138 | snes_ppu.layer[SNES_BG3].offset.tile_horz, |
| 1139 | snes_ppu.layer[SNES_BG3].offset.tile_vert, |
| 1140 | snes_ppu.layer[SNES_BG4].offset.tile_horz, |
| 1141 | snes_ppu.layer[SNES_BG4].offset.tile_vert |
| 1146 | 1142 | ); |
| 1147 | 1143 | #endif |
| 1148 | 1144 | snes_ppu.update_offsets = 0; |
| r7300 | r7301 | |
| 1162 | 1158 | |
| 1163 | 1159 | profiler_mark_start(PROFILER_VIDEO); |
| 1164 | 1160 | |
| 1165 | | if (snes_ram[INIDISP] & 0x80) /* screen is forced blank */ |
| 1161 | if (snes_ppu.screen_disabled) /* screen is forced blank */ |
| 1166 | 1162 | for (x = 0; x < SNES_SCR_WIDTH * 2; x++) |
| 1167 | 1163 | *BITMAP_ADDR32(bitmap, curline, x) = RGB_BLACK; |
| 1168 | 1164 | else |
| r7300 | r7301 | |
| 1199 | 1195 | { |
| 1200 | 1196 | for(ii = 0; ii < SNES_SCR_WIDTH * snes_htmult; ii++) |
| 1201 | 1197 | { |
| 1202 | | snes_draw_blend(ii/snes_htmult, &scanlines[MAINSCREEN].buffer[ii], (snes_ram[CGADSUB] & 0x80) ? SNES_BLEND_SUB : SNES_BLEND_ADD, snes_ppu.sub_color_mask, snes_ppu.main_color_mask); |
| 1198 | snes_draw_blend(ii/snes_htmult, &scanlines[MAINSCREEN].buffer[ii], (snes_ppu.color_modes & 0x80) ? SNES_BLEND_SUB : SNES_BLEND_ADD, snes_ppu.sub_color_mask, snes_ppu.main_color_mask); |
| 1203 | 1199 | } |
| 1204 | 1200 | } |
| 1205 | 1201 | |
| r7300 | r7301 | |
| 1221 | 1217 | scanline = &scanlines[MAINSCREEN]; |
| 1222 | 1218 | |
| 1223 | 1219 | /* Phew! Draw the line to screen */ |
| 1224 | | fade = (snes_ram[INIDISP] & 0xf) + 1; |
| 1220 | fade = snes_ppu.screen_brightness; |
| 1225 | 1221 | |
| 1226 | 1222 | for (x = 0; x < SNES_SCR_WIDTH * 2; x++) |
| 1227 | 1223 | { |
| r7300 | r7301 | |
| 1417 | 1413 | WINLOGIC[(snes_ram[WBGLOG] & 0x3)], |
| 1418 | 1414 | (snes_ram[W12SEL] & 0x2)?((snes_ram[W12SEL] & 0x1)?"o":"i"):" ", |
| 1419 | 1415 | (snes_ram[W12SEL] & 0x8)?((snes_ram[W12SEL] & 0x4)?"o":"i"):" ", |
| 1420 | | snes_ppu.layer[0].tile_size + 1, |
| 1416 | snes_ppu.layer[SNES_BG1].tile_size + 1, |
| 1421 | 1417 | (snes_ram[MOSAIC] & 0x1)?"m":" ", |
| 1422 | 1418 | snes_ram[BG1SC] & 0x3, |
| 1423 | 1419 | (snes_ram[BG1SC] & 0xfc) << 9, |
| 1424 | | snes_ppu.layer[0].data ); |
| 1420 | snes_ppu.layer[SNES_BG1].data ); |
| 1425 | 1421 | //ui_draw_text( t, SNES_DBG_HORZ_POS, y++ * 9 ); |
| 1426 | 1422 | logerror("%s2 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 1427 | 1423 | debug_options.bg_disabled[1]?" ":"*", |
| r7300 | r7301 | |
| 1433 | 1429 | WINLOGIC[(snes_ram[WBGLOG] & 0xc) >> 2], |
| 1434 | 1430 | (snes_ram[W12SEL] & 0x20)?((snes_ram[W12SEL] & 0x10)?"o":"i"):" ", |
| 1435 | 1431 | (snes_ram[W12SEL] & 0x80)?((snes_ram[W12SEL] & 0x40)?"o":"i"):" ", |
| 1436 | | snes_ppu.layer[1].tile_size + 1, |
| 1432 | snes_ppu.layer[SNES_BG2].tile_size + 1, |
| 1437 | 1433 | (snes_ram[MOSAIC] & 0x2)?"m":" ", |
| 1438 | 1434 | snes_ram[BG2SC] & 0x3, |
| 1439 | 1435 | (snes_ram[BG2SC] & 0xfc) << 9, |
| 1440 | | snes_ppu.layer[1].data ); |
| 1436 | snes_ppu.layer[SNES_BG2].data ); |
| 1441 | 1437 | //ui_draw_text( t, SNES_DBG_HORZ_POS, y++ * 9 ); |
| 1442 | 1438 | logerror("%s3 %s%s%s%s%s%c%s%s%d%s%s%d %4X %4X", |
| 1443 | 1439 | debug_options.bg_disabled[2]?" ":"*", |
| r7300 | r7301 | |
| 1449 | 1445 | WINLOGIC[(snes_ram[WBGLOG] & 0x30)>>4], |
| 1450 | 1446 | (snes_ram[W34SEL] & 0x2)?((snes_ram[W34SEL] & 0x1)?"o":"i"):" ", |
| 1451 | 1447 | (snes_ram[W34SEL] & 0x8)?((snes_ram[W34SEL] & 0x4)?"o":"i"):" ", |
| 1452 | | snes_ppu.layer[2].tile_size + 1, |
| 1448 | snes_ppu.layer[SNES_BG3].tile_size + 1, |
| 1453 | 1449 | (snes_ram[MOSAIC] & 0x4)?"m":" ", |
| 1454 | 1450 | (snes_ram[BGMODE] & 0x8)?"P":" ", |
| 1455 | 1451 | snes_ram[BG3SC] & 0x3, |
| 1456 | 1452 | (snes_ram[BG3SC] & 0xfc) << 9, |
| 1457 | | snes_ppu.layer[2].data ); |
| 1453 | snes_ppu.layer[SNES_BG3].data ); |
| 1458 | 1454 | //ui_draw_text( t, SNES_DBG_HORZ_POS, y++ * 9 ); |
| 1459 | 1455 | logerror("%s4 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 1460 | 1456 | debug_options.bg_disabled[3]?" ":"*", |
| r7300 | r7301 | |
| 1466 | 1462 | WINLOGIC[(snes_ram[WBGLOG] & 0xc0)>>6], |
| 1467 | 1463 | (snes_ram[W34SEL] & 0x20)?((snes_ram[W34SEL] & 0x10)?"o":"i"):" ", |
| 1468 | 1464 | (snes_ram[W34SEL] & 0x80)?((snes_ram[W34SEL] & 0x40)?"o":"i"):" ", |
| 1469 | | snes_ppu.layer[3].tile_size + 1, |
| 1465 | snes_ppu.layer[SNES_BG4].tile_size + 1, |
| 1470 | 1466 | (snes_ram[MOSAIC] & 0x8)?"m":" ", |
| 1471 | 1467 | snes_ram[BG4SC] & 0x3, |
| 1472 | 1468 | (snes_ram[BG4SC] & 0xfc) << 9, |
| 1473 | | snes_ppu.layer[3].data ); |
| 1469 | snes_ppu.layer[SNES_BG4].data ); |
| 1474 | 1470 | //ui_draw_text( t, SNES_DBG_HORZ_POS, y++ * 9 ); |
| 1475 | 1471 | logerror("%sO %s%s%s%s%s%c%s%s%d%d %4X", |
| 1476 | 1472 | debug_options.bg_disabled[4]?" ":"*", |
| r7300 | r7301 | |
| 1483 | 1479 | (snes_ram[WOBJSEL] & 0x2)?((snes_ram[WOBJSEL] & 0x1)?"o":"i"):" ", |
| 1484 | 1480 | (snes_ram[WOBJSEL] & 0x8)?((snes_ram[WOBJSEL] & 0x4)?"o":"i"):" ", |
| 1485 | 1481 | snes_ppu.oam.size[0], snes_ppu.oam.size[1], |
| 1486 | | snes_ppu.layer[4].data ); |
| 1482 | snes_ppu.layer[SNES_OAM].data ); |
| 1487 | 1483 | //ui_draw_text( t, SNES_DBG_HORZ_POS, y++ * 9 ); |
| 1488 | 1484 | logerror("%sB %s %c%s%s", |
| 1489 | 1485 | debug_options.bg_disabled[5]?" ":"*", |