trunk/src/mame/video/snes.c
| r17400 | r17401 | |
| 130 | 130 | SNES_COLOR_DEPTH_8BPP |
| 131 | 131 | }; |
| 132 | 132 | |
| 133 | | static UINT8 *snes_vram; /* Video RAM (Should be 16-bit, but it's easier this way) */ |
| 134 | | |
| 135 | 133 | /***************************************** |
| 136 | 134 | * snes_get_bgcolor() |
| 137 | 135 | * |
| r17400 | r17401 | |
| 313 | 311 | |
| 314 | 312 | for (ii = 0; ii < planes / 2; ii++) |
| 315 | 313 | { |
| 316 | | plane[2 * ii + 0] = snes_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 317 | | plane[2 * ii + 1] = snes_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 314 | plane[2 * ii + 0] = m_snes_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 315 | plane[2 * ii + 1] = m_snes_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 318 | 316 | } |
| 319 | 317 | |
| 320 | 318 | for (ii = x; ii < (x + 8); ii++) |
| r17400 | r17401 | |
| 371 | 369 | * BG drawing theory of each scanline is quite easy: depending on the graphics Mode (0-7), there |
| 372 | 370 | * are up to 4 background layers. Pixels for each BG layer can have two different priorities. |
| 373 | 371 | * Depending on the line and on the BGHOFS and BGVOFS PPU registers, we first determine the tile |
| 374 | | * address in snes_vram (by determining x,y coord and tile size and by calling snes_get_tmap_addr). |
| 372 | * address in m_snes_vram (by determining x,y coord and tile size and by calling snes_get_tmap_addr). |
| 375 | 373 | * Then, we load the correspondent data and we determine the tile properties: which priority to |
| 376 | 374 | * use, which palette etc. Finally, for each pixel of the tile appearing on screen, we check if |
| 377 | 375 | * the tile priority is higher than the BG/OAM already stored in that pixel for that line. If so |
| r17400 | r17401 | |
| 478 | 476 | case SNES_OPT_MODE6: |
| 479 | 477 | haddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff)); |
| 480 | 478 | vaddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff) + 8); |
| 481 | | hval = snes_vram[haddr % SNES_VRAM_SIZE] | (snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 482 | | vval = snes_vram[vaddr % SNES_VRAM_SIZE] | (snes_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 479 | hval = m_snes_vram[haddr % SNES_VRAM_SIZE] | (m_snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 480 | vval = m_snes_vram[vaddr % SNES_VRAM_SIZE] | (m_snes_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 483 | 481 | if (BIT(hval, opt_bit)) |
| 484 | 482 | xpos = opt_x + (hval & ~7); |
| 485 | 483 | if (BIT(vval, opt_bit)) |
| r17400 | r17401 | |
| 487 | 485 | break; |
| 488 | 486 | case SNES_OPT_MODE4: |
| 489 | 487 | haddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff)); |
| 490 | | hval = snes_vram[haddr % SNES_VRAM_SIZE] | (snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 488 | hval = m_snes_vram[haddr % SNES_VRAM_SIZE] | (m_snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 491 | 489 | if (BIT(hval, opt_bit)) |
| 492 | 490 | { |
| 493 | 491 | if (!BIT(hval, 15)) |
| r17400 | r17401 | |
| 511 | 509 | ppp = Tile palette. The number of entries in the palette depends on the Mode and the BG. |
| 512 | 510 | cccccccccc = Tile number. |
| 513 | 511 | */ |
| 514 | | tilemap = snes_vram[addr % SNES_VRAM_SIZE] | (snes_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 512 | tilemap = m_snes_vram[addr % SNES_VRAM_SIZE] | (m_snes_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 515 | 513 | vflip = BIT(tilemap, 15); |
| 516 | 514 | hflip = BIT(tilemap, 14); |
| 517 | 515 | priority = BIT(tilemap, 13) ? priority_a : priority_b; |
| r17400 | r17401 | |
| 693 | 691 | case 0x01: /* Repeat if outside screen area */ |
| 694 | 692 | tx &= 0x3ff; |
| 695 | 693 | ty &= 0x3ff; |
| 696 | | tiled = snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 697 | | colour = snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 694 | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 695 | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 698 | 696 | break; |
| 699 | 697 | case 0x02: /* Single colour backdrop screen if outside screen area */ |
| 700 | 698 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 701 | 699 | { |
| 702 | | tiled = snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 703 | | colour = snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 700 | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 701 | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 704 | 702 | } |
| 705 | 703 | else |
| 706 | 704 | colour = 0; |
| 707 | 705 | break; |
| 708 | 706 | case 0x03: /* Character 0x00 repeat if outside screen area */ |
| 709 | 707 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 710 | | tiled = snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 708 | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 711 | 709 | else |
| 712 | 710 | tiled = 0; |
| 713 | 711 | |
| 714 | | colour = snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 712 | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 715 | 713 | break; |
| 716 | 714 | } |
| 717 | 715 | |
| r17400 | r17401 | |
| 1663 | 1661 | memset(&debug_options, 0, sizeof(debug_options)); |
| 1664 | 1662 | #endif |
| 1665 | 1663 | |
| 1666 | | snes_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE); |
| 1664 | state->m_snes_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE); |
| 1667 | 1665 | state->m_snes_cgram = auto_alloc_array(machine, UINT16, SNES_CGRAM_SIZE/2); |
| 1668 | 1666 | state->m_snes_oam = auto_alloc_array(machine, UINT16, SNES_OAM_SIZE/2); |
| 1669 | 1667 | |
| r17400 | r17401 | |
| 1686 | 1684 | } |
| 1687 | 1685 | |
| 1688 | 1686 | /* Init VRAM */ |
| 1689 | | memset(snes_vram, 0, SNES_VRAM_SIZE); |
| 1687 | memset(state->m_snes_vram, 0, SNES_VRAM_SIZE); |
| 1690 | 1688 | |
| 1691 | | /* Init Character Graphics RAM */ |
| 1689 | /* Init Palette RAM */ |
| 1692 | 1690 | memset((UINT8 *)state->m_snes_cgram, 0, SNES_CGRAM_SIZE); |
| 1693 | 1691 | |
| 1694 | 1692 | /* Init oam RAM */ |
| 1695 | | memset(state->m_snes_oam, 0xff, SNES_OAM_SIZE); |
| 1693 | memset((UINT8 *)state->m_snes_oam, 0xff, SNES_OAM_SIZE); |
| 1696 | 1694 | |
| 1697 | 1695 | for (i = 0; i < 6; i++) |
| 1698 | 1696 | { |
| r17400 | r17401 | |
| 1782 | 1780 | state_save_register_global(machine, snes_ppu.color_modes); |
| 1783 | 1781 | state_save_register_global(machine, snes_ppu.stat77_flags); |
| 1784 | 1782 | |
| 1785 | | state_save_register_global_pointer(machine, snes_vram, SNES_VRAM_SIZE); |
| 1783 | state_save_register_global_pointer(machine, state->m_snes_vram, SNES_VRAM_SIZE); |
| 1786 | 1784 | state_save_register_global_pointer(machine, state->m_snes_cgram, SNES_CGRAM_SIZE/2); |
| 1787 | 1785 | state_save_register_global_pointer(machine, state->m_snes_oam, SNES_OAM_SIZE/2); |
| 1788 | 1786 | } |
| r17400 | r17401 | |
| 1881 | 1879 | return addr; |
| 1882 | 1880 | } |
| 1883 | 1881 | |
| 1884 | | static READ8_HANDLER( snes_vram_read ) |
| 1882 | READ8_MEMBER( snes_state::snes_vram_read ) |
| 1885 | 1883 | { |
| 1886 | 1884 | UINT8 res = 0; |
| 1887 | 1885 | offset &= 0x1ffff; |
| 1888 | 1886 | |
| 1889 | 1887 | if (snes_ppu.screen_disabled) |
| 1890 | | res = snes_vram[offset]; |
| 1888 | res = m_snes_vram[offset]; |
| 1891 | 1889 | else |
| 1892 | 1890 | { |
| 1893 | | UINT16 v = space->machine().primary_screen->vpos(); |
| 1894 | | UINT16 h = space->machine().primary_screen->hpos(); |
| 1891 | UINT16 v = machine().primary_screen->vpos(); |
| 1892 | UINT16 h = machine().primary_screen->hpos(); |
| 1895 | 1893 | UINT16 ls = (((snes_ram[STAT78] & 0x10) == SNES_NTSC ? 525 : 625) >> 1) - 1; |
| 1896 | 1894 | |
| 1897 | 1895 | if (snes_ppu.interlace == 2) |
| r17400 | r17401 | |
| 1904 | 1902 | else if (v == snes_ppu.beam.last_visible_line - 1) |
| 1905 | 1903 | { |
| 1906 | 1904 | if (h == 1362) |
| 1907 | | res = snes_vram[offset]; |
| 1905 | res = m_snes_vram[offset]; |
| 1908 | 1906 | else |
| 1909 | 1907 | res = 0; |
| 1910 | 1908 | } |
| 1911 | 1909 | else |
| 1912 | | res = snes_vram[offset]; |
| 1910 | res = m_snes_vram[offset]; |
| 1913 | 1911 | } |
| 1914 | 1912 | return res; |
| 1915 | 1913 | } |
| 1916 | 1914 | |
| 1917 | | static WRITE8_HANDLER( snes_vram_write ) |
| 1915 | WRITE8_MEMBER( snes_state::snes_vram_write ) |
| 1918 | 1916 | { |
| 1919 | 1917 | offset &= 0x1ffff; |
| 1920 | 1918 | |
| 1921 | 1919 | if (snes_ppu.screen_disabled) |
| 1922 | | snes_vram[offset] = data; |
| 1920 | m_snes_vram[offset] = data; |
| 1923 | 1921 | else |
| 1924 | 1922 | { |
| 1925 | | UINT16 v = space->machine().primary_screen->vpos(); |
| 1926 | | UINT16 h = space->machine().primary_screen->hpos(); |
| 1923 | UINT16 v = machine().primary_screen->vpos(); |
| 1924 | UINT16 h = machine().primary_screen->hpos(); |
| 1927 | 1925 | if (v == 0) |
| 1928 | 1926 | { |
| 1929 | 1927 | if (h <= 4) |
| 1930 | | snes_vram[offset] = data; |
| 1928 | m_snes_vram[offset] = data; |
| 1931 | 1929 | else if (h == 6) |
| 1932 | | snes_vram[offset] = snes_open_bus_r(space, 0); |
| 1930 | m_snes_vram[offset] = snes_open_bus_r(&space, 0); |
| 1933 | 1931 | else |
| 1934 | 1932 | { |
| 1935 | 1933 | //no write |
| r17400 | r17401 | |
| 1946 | 1944 | //no write |
| 1947 | 1945 | } |
| 1948 | 1946 | else |
| 1949 | | snes_vram[offset] = data; |
| 1947 | m_snes_vram[offset] = data; |
| 1950 | 1948 | } |
| 1951 | 1949 | else |
| 1952 | | snes_vram[offset] = data; |
| 1950 | m_snes_vram[offset] = data; |
| 1953 | 1951 | } |
| 1954 | 1952 | } |
| 1955 | 1953 | |
| r17400 | r17401 | |
| 2156 | 2154 | |
| 2157 | 2155 | if (!state->m_vram_fgr_high) |
| 2158 | 2156 | { |
| 2159 | | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2160 | | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2157 | state->m_vram_read_buffer = state->snes_vram_read(*space, addr); |
| 2158 | state->m_vram_read_buffer |= (state->snes_vram_read(*space, addr + 1) << 8); |
| 2161 | 2159 | |
| 2162 | 2160 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| 2163 | 2161 | } |
| r17400 | r17401 | |
| 2171 | 2169 | |
| 2172 | 2170 | if (state->m_vram_fgr_high) |
| 2173 | 2171 | { |
| 2174 | | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2175 | | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2172 | state->m_vram_read_buffer = state->snes_vram_read(*space, addr); |
| 2173 | state->m_vram_read_buffer |= (state->snes_vram_read(*space, addr + 1) << 8); |
| 2176 | 2174 | |
| 2177 | 2175 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| 2178 | 2176 | } |
| r17400 | r17401 | |
| 2402 | 2400 | UINT32 addr; |
| 2403 | 2401 | state->m_vmadd = (state->m_vmadd & 0xff00) | (data << 0); |
| 2404 | 2402 | addr = snes_get_vram_address(space->machine()) << 1; |
| 2405 | | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2406 | | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2403 | state->m_vram_read_buffer = state->snes_vram_read(*space, addr); |
| 2404 | state->m_vram_read_buffer |= (state->snes_vram_read(*space, addr + 1) << 8); |
| 2407 | 2405 | } |
| 2408 | 2406 | break; |
| 2409 | 2407 | case VMADDH: /* Address for VRAM read/write (high) */ |
| r17400 | r17401 | |
| 2411 | 2409 | UINT32 addr; |
| 2412 | 2410 | state->m_vmadd = (state->m_vmadd & 0x00ff) | (data << 8); |
| 2413 | 2411 | addr = snes_get_vram_address(space->machine()) << 1; |
| 2414 | | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2415 | | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2412 | state->m_vram_read_buffer = state->snes_vram_read(*space, addr); |
| 2413 | state->m_vram_read_buffer |= (state->snes_vram_read(*space, addr + 1) << 8); |
| 2416 | 2414 | } |
| 2417 | 2415 | break; |
| 2418 | 2416 | case VMDATAL: /* 2118: Data for VRAM write (low) */ |
| 2419 | 2417 | { |
| 2420 | 2418 | UINT32 addr = snes_get_vram_address(space->machine()) << 1; |
| 2421 | | snes_vram_write(space, addr, data); |
| 2419 | state->snes_vram_write(*space, addr, data); |
| 2422 | 2420 | |
| 2423 | 2421 | if (!state->m_vram_fgr_high) |
| 2424 | 2422 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| r17400 | r17401 | |
| 2427 | 2425 | case VMDATAH: /* 2119: Data for VRAM write (high) */ |
| 2428 | 2426 | { |
| 2429 | 2427 | UINT32 addr = snes_get_vram_address(space->machine()) << 1; |
| 2430 | | snes_vram_write(space, addr + 1, data); |
| 2428 | state->snes_vram_write(*space, addr + 1, data); |
| 2431 | 2429 | |
| 2432 | 2430 | if (state->m_vram_fgr_high) |
| 2433 | 2431 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |