trunk/src/mame/machine/snes.c
| r21562 | r21563 | |
| 31 | 31 | /* -- Globals -- */ |
| 32 | 32 | UINT8 *snes_ram = NULL; /* 65816 ram */ |
| 33 | 33 | |
| 34 | | static void snes_dma(address_space &space, UINT8 channels); |
| 35 | | static void snes_hdma_init(address_space &space); |
| 36 | | static void snes_hdma(address_space &space); |
| 37 | | |
| 38 | 34 | static DECLARE_READ8_HANDLER(snes_io_dma_r); |
| 39 | 35 | static DECLARE_WRITE8_HANDLER(snes_io_dma_w); |
| 40 | 36 | |
| r21562 | r21563 | |
| 102 | 98 | state->m_ppu.ppu_start(machine); |
| 103 | 99 | } |
| 104 | 100 | |
| 105 | | UINT32 snes_state::snes_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 101 | UINT32 snes_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 106 | 102 | { |
| 107 | 103 | /* NTSC SNES draw range is 1-225. */ |
| 108 | 104 | for (int y = cliprect.min_y; y <= cliprect.max_y; y++) |
| r21562 | r21563 | |
| 127 | 123 | m_nmi_timer->adjust(attotime::never); |
| 128 | 124 | } |
| 129 | 125 | |
| 130 | | static void snes_hirq_tick( running_machine &machine ) |
| 126 | void snes_state::hirq_tick() |
| 131 | 127 | { |
| 132 | | snes_state *state = machine.driver_data<snes_state>(); |
| 133 | | |
| 134 | 128 | // latch the counters and pull IRQ |
| 135 | 129 | // (don't need to switch to the 65816 context, we don't do anything dependant on it) |
| 136 | | state->m_ppu.latch_counters(machine); |
| 130 | m_ppu.latch_counters(machine()); |
| 137 | 131 | snes_ram[TIMEUP] = 0x80; /* Indicate that irq occurred */ |
| 138 | | state->m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE); |
| 132 | m_maincpu->set_input_line(G65816_LINE_IRQ, ASSERT_LINE); |
| 139 | 133 | |
| 140 | 134 | // don't happen again |
| 141 | | state->m_hirq_timer->adjust(attotime::never); |
| 135 | m_hirq_timer->adjust(attotime::never); |
| 142 | 136 | } |
| 143 | 137 | |
| 144 | 138 | TIMER_CALLBACK_MEMBER(snes_state::snes_hirq_tick_callback) |
| 145 | 139 | { |
| 146 | | snes_hirq_tick(machine()); |
| 140 | hirq_tick(); |
| 147 | 141 | } |
| 148 | 142 | |
| 149 | 143 | TIMER_CALLBACK_MEMBER(snes_state::snes_reset_oam_address) |
| r21562 | r21563 | |
| 162 | 156 | TIMER_CALLBACK_MEMBER(snes_state::snes_reset_hdma) |
| 163 | 157 | { |
| 164 | 158 | address_space &cpu0space = m_maincpu->space(AS_PROGRAM); |
| 165 | | snes_hdma_init(cpu0space); |
| 159 | hdma_init(cpu0space); |
| 166 | 160 | } |
| 167 | 161 | |
| 168 | 162 | TIMER_CALLBACK_MEMBER(snes_state::snes_update_io) |
| r21562 | r21563 | |
| 213 | 207 | // printf("HIRQ @ %d, %d\n", pixel * m_ppu.m_htmult, m_ppu.m_beam.current_vert); |
| 214 | 208 | if (pixel == 0) |
| 215 | 209 | { |
| 216 | | snes_hirq_tick(machine()); |
| 210 | hirq_tick(); |
| 217 | 211 | } |
| 218 | 212 | else |
| 219 | 213 | { |
| r21562 | r21563 | |
| 244 | 238 | if (m_ppu.m_beam.current_vert == 0) |
| 245 | 239 | { |
| 246 | 240 | address_space &cpu0space = m_maincpu->space(AS_PROGRAM); |
| 247 | | snes_hdma_init(cpu0space); |
| 241 | hdma_init(cpu0space); |
| 248 | 242 | } |
| 249 | 243 | |
| 250 | 244 | if (m_ppu.m_beam.current_vert == 0) |
| r21562 | r21563 | |
| 281 | 275 | { |
| 282 | 276 | /* Do HDMA */ |
| 283 | 277 | if (snes_ram[HDMAEN]) |
| 284 | | snes_hdma(cpu0space); |
| 278 | hdma(cpu0space); |
| 285 | 279 | |
| 286 | 280 | machine().primary_screen->update_partial((m_ppu.m_interlace == 2) ? (m_ppu.m_beam.current_vert * m_ppu.m_interlace) : m_ppu.m_beam.current_vert - 1); |
| 287 | 281 | } |
| r21562 | r21563 | |
| 727 | 721 | state->m_vtime &= 0x1ff; |
| 728 | 722 | return; |
| 729 | 723 | case MDMAEN: /* DMA channel designation and trigger */ |
| 730 | | snes_dma(space, data); |
| 724 | state->dma(space, data); |
| 731 | 725 | data = 0; /* Once DMA is done we need to reset all bits to 0 */ |
| 732 | 726 | break; |
| 733 | 727 | case HDMAEN: /* HDMA channel designation */ |
| r21562 | r21563 | |
| 1949 | 1943 | |
| 1950 | 1944 | *************************************/ |
| 1951 | 1945 | |
| 1952 | | INLINE int dma_abus_valid( UINT32 address ) |
| 1946 | inline int snes_state::dma_abus_valid( UINT32 address ) |
| 1953 | 1947 | { |
| 1954 | 1948 | if((address & 0x40ff00) == 0x2100) return 0; //$[00-3f|80-bf]:[2100-21ff] |
| 1955 | 1949 | if((address & 0x40fe00) == 0x4000) return 0; //$[00-3f|80-bf]:[4000-41ff] |
| r21562 | r21563 | |
| 1959 | 1953 | return 1; |
| 1960 | 1954 | } |
| 1961 | 1955 | |
| 1962 | | INLINE UINT8 snes_abus_read( address_space &space, UINT32 abus ) |
| 1956 | inline UINT8 snes_state::abus_read( address_space &space, UINT32 abus ) |
| 1963 | 1957 | { |
| 1964 | 1958 | if (!dma_abus_valid(abus)) |
| 1965 | 1959 | return 0; |
| r21562 | r21563 | |
| 1967 | 1961 | return space.read_byte(abus); |
| 1968 | 1962 | } |
| 1969 | 1963 | |
| 1970 | | INLINE void snes_dma_transfer( address_space &space, UINT8 dma, UINT32 abus, UINT16 bbus ) |
| 1964 | inline void snes_state::dma_transfer( address_space &space, UINT8 dma, UINT32 abus, UINT16 bbus ) |
| 1971 | 1965 | { |
| 1972 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 1973 | | |
| 1974 | | if (state->m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */ |
| 1966 | if (m_dma_channel[dma].dmap & 0x80) /* PPU->CPU */ |
| 1975 | 1967 | { |
| 1976 | 1968 | if (bbus == 0x2180 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) |
| 1977 | 1969 | { |
| r21562 | r21563 | |
| 2000 | 1992 | } |
| 2001 | 1993 | else |
| 2002 | 1994 | { |
| 2003 | | space.write_byte(bbus, snes_abus_read(space, abus)); |
| 1995 | space.write_byte(bbus, abus_read(space, abus)); |
| 2004 | 1996 | return; |
| 2005 | 1997 | } |
| 2006 | 1998 | } |
| r21562 | r21563 | |
| 2008 | 2000 | |
| 2009 | 2001 | /* WIP: These have the advantage to automatically update the address, but then we would need to |
| 2010 | 2002 | check again if the transfer is direct/indirect at each step... is it worth? */ |
| 2011 | | INLINE UINT32 snes_get_hdma_addr( running_machine &machine, int dma ) |
| 2003 | inline UINT32 snes_state::get_hdma_addr( int dma ) |
| 2012 | 2004 | { |
| 2013 | | snes_state *state = machine.driver_data<snes_state>(); |
| 2014 | | return (state->m_dma_channel[dma].bank << 16) | (state->m_dma_channel[dma].hdma_addr++); |
| 2005 | return (m_dma_channel[dma].bank << 16) | (m_dma_channel[dma].hdma_addr++); |
| 2015 | 2006 | } |
| 2016 | 2007 | |
| 2017 | | INLINE UINT32 snes_get_hdma_iaddr( running_machine &machine, int dma ) |
| 2008 | inline UINT32 snes_state::get_hdma_iaddr( int dma ) |
| 2018 | 2009 | { |
| 2019 | | snes_state *state = machine.driver_data<snes_state>(); |
| 2020 | | return (state->m_dma_channel[dma].ibank << 16) | (state->m_dma_channel[dma].trans_size++); |
| 2010 | return (m_dma_channel[dma].ibank << 16) | (m_dma_channel[dma].trans_size++); |
| 2021 | 2011 | } |
| 2022 | 2012 | |
| 2023 | | INLINE int is_last_active_channel( running_machine &machine, int dma ) |
| 2013 | inline int snes_state::is_last_active_channel( int dma ) |
| 2024 | 2014 | { |
| 2025 | | snes_state *state = machine.driver_data<snes_state>(); |
| 2026 | | int i; |
| 2027 | | |
| 2028 | | for (i = dma + 1; i < 8; i++) |
| 2015 | for (int i = dma + 1; i < 8; i++) |
| 2029 | 2016 | { |
| 2030 | | if (BIT(state->m_hdmaen, i) && state->m_dma_channel[i].hdma_line_counter) |
| 2017 | if (BIT(m_hdmaen, i) && m_dma_channel[i].hdma_line_counter) |
| 2031 | 2018 | return 0; // there is still at least another channel with incomplete HDMA |
| 2032 | 2019 | } |
| 2033 | 2020 | |
| r21562 | r21563 | |
| 2035 | 2022 | return 1; |
| 2036 | 2023 | } |
| 2037 | 2024 | |
| 2038 | | static void snes_hdma_update( address_space &space, int dma ) |
| 2025 | void snes_state::hdma_update( address_space &space, int dma ) |
| 2039 | 2026 | { |
| 2040 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2041 | | UINT32 abus = snes_get_hdma_addr(space.machine(), dma); |
| 2027 | UINT32 abus = get_hdma_addr(dma); |
| 2042 | 2028 | |
| 2043 | | state->m_dma_channel[dma].hdma_line_counter = snes_abus_read(space, abus); |
| 2029 | m_dma_channel[dma].hdma_line_counter = abus_read(space, abus); |
| 2044 | 2030 | |
| 2045 | | if (state->m_dma_channel[dma].dmap & 0x40) |
| 2031 | if (m_dma_channel[dma].dmap & 0x40) |
| 2046 | 2032 | { |
| 2047 | 2033 | /* One oddity: if $43xA is 0 and this is the last active HDMA channel for this scanline, only load |
| 2048 | 2034 | one byte for Address, and use the $00 for the low byte. So Address ends up incremented one less than |
| 2049 | 2035 | otherwise expected */ |
| 2050 | 2036 | |
| 2051 | | abus = snes_get_hdma_addr(space.machine(), dma); |
| 2052 | | state->m_dma_channel[dma].trans_size = snes_abus_read(space, abus) << 8; |
| 2037 | abus = get_hdma_addr(dma); |
| 2038 | m_dma_channel[dma].trans_size = abus_read(space, abus) << 8; |
| 2053 | 2039 | |
| 2054 | | if (state->m_dma_channel[dma].hdma_line_counter || !is_last_active_channel(space.machine(), dma)) |
| 2040 | if (m_dma_channel[dma].hdma_line_counter || !is_last_active_channel(dma)) |
| 2055 | 2041 | { |
| 2056 | 2042 | // we enter here if we have more transfers to be done or if there are other active channels after this one |
| 2057 | | abus = snes_get_hdma_addr(space.machine(), dma); |
| 2058 | | state->m_dma_channel[dma].trans_size >>= 8; |
| 2059 | | state->m_dma_channel[dma].trans_size |= snes_abus_read(space, abus) << 8; |
| 2043 | abus = get_hdma_addr(dma); |
| 2044 | m_dma_channel[dma].trans_size >>= 8; |
| 2045 | m_dma_channel[dma].trans_size |= abus_read(space, abus) << 8; |
| 2060 | 2046 | } |
| 2061 | 2047 | } |
| 2062 | 2048 | |
| 2063 | | if (!state->m_dma_channel[dma].hdma_line_counter) |
| 2064 | | state->m_hdmaen &= ~(1 << dma); |
| 2049 | if (!m_dma_channel[dma].hdma_line_counter) |
| 2050 | m_hdmaen &= ~(1 << dma); |
| 2065 | 2051 | |
| 2066 | | state->m_dma_channel[dma].do_transfer = 1; |
| 2052 | m_dma_channel[dma].do_transfer = 1; |
| 2067 | 2053 | } |
| 2068 | 2054 | |
| 2069 | | static void snes_hdma_init( address_space &space ) |
| 2055 | void snes_state::hdma_init( address_space &space ) |
| 2070 | 2056 | { |
| 2071 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2072 | | int i; |
| 2073 | | |
| 2074 | | state->m_hdmaen = snes_ram[HDMAEN]; |
| 2075 | | for (i = 0; i < 8; i++) |
| 2057 | m_hdmaen = snes_ram[HDMAEN]; |
| 2058 | for (int i = 0; i < 8; i++) |
| 2076 | 2059 | { |
| 2077 | | if (BIT(state->m_hdmaen, i)) |
| 2060 | if (BIT(m_hdmaen, i)) |
| 2078 | 2061 | { |
| 2079 | | state->m_dma_channel[i].hdma_addr = state->m_dma_channel[i].src_addr; |
| 2080 | | snes_hdma_update(space, i); |
| 2062 | m_dma_channel[i].hdma_addr = m_dma_channel[i].src_addr; |
| 2063 | hdma_update(space, i); |
| 2081 | 2064 | } |
| 2082 | 2065 | } |
| 2083 | 2066 | } |
| 2084 | 2067 | |
| 2085 | | static void snes_hdma( address_space &space ) |
| 2068 | void snes_state::hdma( address_space &space ) |
| 2086 | 2069 | { |
| 2087 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2088 | 2070 | UINT16 bbus; |
| 2089 | 2071 | UINT32 abus; |
| 2090 | | int i; |
| 2091 | 2072 | |
| 2092 | | for (i = 0; i < 8; i++) |
| 2073 | for (int i = 0; i < 8; i++) |
| 2093 | 2074 | { |
| 2094 | | if (BIT(state->m_hdmaen, i)) |
| 2075 | if (BIT(m_hdmaen, i)) |
| 2095 | 2076 | { |
| 2096 | | if (state->m_dma_channel[i].do_transfer) |
| 2077 | if (m_dma_channel[i].do_transfer) |
| 2097 | 2078 | { |
| 2098 | 2079 | /* Get transfer addresses */ |
| 2099 | | if (state->m_dma_channel[i].dmap & 0x40) /* Indirect */ |
| 2100 | | abus = (state->m_dma_channel[i].ibank << 16) + state->m_dma_channel[i].trans_size; |
| 2080 | if (m_dma_channel[i].dmap & 0x40) /* Indirect */ |
| 2081 | abus = (m_dma_channel[i].ibank << 16) + m_dma_channel[i].trans_size; |
| 2101 | 2082 | else /* Absolute */ |
| 2102 | | abus = (state->m_dma_channel[i].bank << 16) + state->m_dma_channel[i].hdma_addr; |
| 2083 | abus = (m_dma_channel[i].bank << 16) + m_dma_channel[i].hdma_addr; |
| 2103 | 2084 | |
| 2104 | | bbus = state->m_dma_channel[i].dest_addr + 0x2100; |
| 2085 | bbus = m_dma_channel[i].dest_addr + 0x2100; |
| 2105 | 2086 | |
| 2106 | 2087 | |
| 2107 | 2088 | |
| 2108 | | switch (state->m_dma_channel[i].dmap & 0x07) |
| 2089 | switch (m_dma_channel[i].dmap & 0x07) |
| 2109 | 2090 | { |
| 2110 | 2091 | case 0: /* 1 register write once (1 byte: p ) */ |
| 2111 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2092 | dma_transfer(space, i, abus++, bbus); |
| 2112 | 2093 | break; |
| 2113 | 2094 | case 5: /* 2 registers write twice alternate (4 bytes: p, p+1, p, p+1) */ |
| 2114 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2115 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2116 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2117 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2095 | dma_transfer(space, i, abus++, bbus); |
| 2096 | dma_transfer(space, i, abus++, bbus + 1); |
| 2097 | dma_transfer(space, i, abus++, bbus); |
| 2098 | dma_transfer(space, i, abus++, bbus + 1); |
| 2118 | 2099 | break; |
| 2119 | 2100 | case 1: /* 2 registers write once (2 bytes: p, p+1 ) */ |
| 2120 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2121 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2101 | dma_transfer(space, i, abus++, bbus); |
| 2102 | dma_transfer(space, i, abus++, bbus + 1); |
| 2122 | 2103 | break; |
| 2123 | 2104 | case 2: /* 1 register write twice (2 bytes: p, p ) */ |
| 2124 | 2105 | case 6: |
| 2125 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2126 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2106 | dma_transfer(space, i, abus++, bbus); |
| 2107 | dma_transfer(space, i, abus++, bbus); |
| 2127 | 2108 | break; |
| 2128 | 2109 | case 3: /* 2 registers write twice each (4 bytes: p, p, p+1, p+1) */ |
| 2129 | 2110 | case 7: |
| 2130 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2131 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2132 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2133 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2111 | dma_transfer(space, i, abus++, bbus); |
| 2112 | dma_transfer(space, i, abus++, bbus); |
| 2113 | dma_transfer(space, i, abus++, bbus + 1); |
| 2114 | dma_transfer(space, i, abus++, bbus + 1); |
| 2134 | 2115 | break; |
| 2135 | 2116 | case 4: /* 4 registers write once (4 bytes: p, p+1, p+2, p+3) */ |
| 2136 | | snes_dma_transfer(space, i, abus++, bbus); |
| 2137 | | snes_dma_transfer(space, i, abus++, bbus + 1); |
| 2138 | | snes_dma_transfer(space, i, abus++, bbus + 2); |
| 2139 | | snes_dma_transfer(space, i, abus++, bbus + 3); |
| 2117 | dma_transfer(space, i, abus++, bbus); |
| 2118 | dma_transfer(space, i, abus++, bbus + 1); |
| 2119 | dma_transfer(space, i, abus++, bbus + 2); |
| 2120 | dma_transfer(space, i, abus++, bbus + 3); |
| 2140 | 2121 | break; |
| 2141 | 2122 | default: |
| 2142 | 2123 | #ifdef MAME_DEBUG |
| 2143 | | mame_printf_debug( " HDMA of unsupported type: %d\n", state->m_dma_channel[i].dmap & 0x07); |
| 2124 | mame_printf_debug( " HDMA of unsupported type: %d\n", m_dma_channel[i].dmap & 0x07); |
| 2144 | 2125 | #endif |
| 2145 | 2126 | break; |
| 2146 | 2127 | } |
| 2147 | 2128 | |
| 2148 | | if (state->m_dma_channel[i].dmap & 0x40) /* Indirect */ |
| 2149 | | state->m_dma_channel[i].trans_size = abus; |
| 2129 | if (m_dma_channel[i].dmap & 0x40) /* Indirect */ |
| 2130 | m_dma_channel[i].trans_size = abus; |
| 2150 | 2131 | else /* Absolute */ |
| 2151 | | state->m_dma_channel[i].hdma_addr = abus; |
| 2132 | m_dma_channel[i].hdma_addr = abus; |
| 2152 | 2133 | |
| 2153 | 2134 | } |
| 2154 | 2135 | } |
| 2155 | 2136 | } |
| 2156 | 2137 | |
| 2157 | | for (i = 0; i < 8; i++) |
| 2138 | for (int i = 0; i < 8; i++) |
| 2158 | 2139 | { |
| 2159 | | if (BIT(state->m_hdmaen, i)) |
| 2140 | if (BIT(m_hdmaen, i)) |
| 2160 | 2141 | { |
| 2161 | | state->m_dma_channel[i].do_transfer = (--state->m_dma_channel[i].hdma_line_counter) & 0x80; |
| 2142 | m_dma_channel[i].do_transfer = (--m_dma_channel[i].hdma_line_counter) & 0x80; |
| 2162 | 2143 | |
| 2163 | | if (!(state->m_dma_channel[i].hdma_line_counter & 0x7f)) |
| 2164 | | snes_hdma_update(space, i); |
| 2144 | if (!(m_dma_channel[i].hdma_line_counter & 0x7f)) |
| 2145 | hdma_update(space, i); |
| 2165 | 2146 | } |
| 2166 | 2147 | } |
| 2167 | 2148 | } |
| 2168 | 2149 | |
| 2169 | | static void snes_dma( address_space &space, UINT8 channels ) |
| 2150 | void snes_state::dma( address_space &space, UINT8 channels ) |
| 2170 | 2151 | { |
| 2171 | | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2172 | | int i; |
| 2173 | 2152 | INT8 increment; |
| 2174 | 2153 | UINT16 bbus; |
| 2175 | 2154 | UINT32 abus, abus_bank; |
| r21562 | r21563 | |
| 2178 | 2157 | /* FIXME: we also need to round to the nearest 8 master cycles */ |
| 2179 | 2158 | |
| 2180 | 2159 | /* Assume priority of the 8 DMA channels is 0-7 */ |
| 2181 | | for (i = 0; i < 8; i++) |
| 2160 | for (int i = 0; i < 8; i++) |
| 2182 | 2161 | { |
| 2183 | 2162 | if (BIT(channels, i)) |
| 2184 | 2163 | { |
| 2185 | 2164 | /* FIXME: the following should be used to stop DMA if the same channel is used by HDMA (being set to 1 in snes_hdma) |
| 2186 | 2165 | However, this cannot be implemented as is atm, because currently DMA transfers always happen as soon as they are enabled... */ |
| 2187 | | state->m_dma_channel[i].dma_disabled = 0; |
| 2166 | m_dma_channel[i].dma_disabled = 0; |
| 2188 | 2167 | |
| 2189 | 2168 | //printf( "Making a transfer on channel %d\n", i ); |
| 2190 | 2169 | /* Find transfer addresses */ |
| 2191 | | abus = state->m_dma_channel[i].src_addr; |
| 2192 | | abus_bank = state->m_dma_channel[i].bank << 16; |
| 2193 | | bbus = state->m_dma_channel[i].dest_addr + 0x2100; |
| 2170 | abus = m_dma_channel[i].src_addr; |
| 2171 | abus_bank = m_dma_channel[i].bank << 16; |
| 2172 | bbus = m_dma_channel[i].dest_addr + 0x2100; |
| 2194 | 2173 | |
| 2195 | 2174 | //printf("Address: %06x\n", abus | abus_bank); |
| 2196 | 2175 | /* Auto increment */ |
| 2197 | | if (state->m_dma_channel[i].dmap & 0x8) |
| 2176 | if (m_dma_channel[i].dmap & 0x8) |
| 2198 | 2177 | increment = 0; |
| 2199 | 2178 | else |
| 2200 | 2179 | { |
| 2201 | | if (state->m_dma_channel[i].dmap & 0x10) |
| 2180 | if (m_dma_channel[i].dmap & 0x10) |
| 2202 | 2181 | increment = -1; |
| 2203 | 2182 | else |
| 2204 | 2183 | increment = 1; |
| 2205 | 2184 | } |
| 2206 | 2185 | |
| 2207 | 2186 | /* Number of bytes to transfer */ |
| 2208 | | length = state->m_dma_channel[i].trans_size; |
| 2187 | length = m_dma_channel[i].trans_size; |
| 2209 | 2188 | |
| 2210 | | // printf( "DMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus | abus_bank, bbus, increment, state->m_dma_channel[i].dmap & 0x80 ? "PPU->CPU" : "CPU->PPU", state->m_dma_channel[i].dmap & 0x07); |
| 2189 | // printf( "DMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus | abus_bank, bbus, increment, m_dma_channel[i].dmap & 0x80 ? "PPU->CPU" : "CPU->PPU", m_dma_channel[i].dmap & 0x07); |
| 2211 | 2190 | |
| 2212 | 2191 | #ifdef SNES_DBG_DMA |
| 2213 | | mame_printf_debug( "DMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus | abus_bank, bbus, increment, state->m_dma_channel[i].dmap & 0x80 ? "PPU->CPU" : "CPU->PPU", state->m_dma_channel[i].dmap & 0x07); |
| 2192 | mame_printf_debug( "DMA-Ch %d: len: %X, abus: %X, bbus: %X, incr: %d, dir: %s, type: %d\n", i, length, abus | abus_bank, bbus, increment, m_dma_channel[i].dmap & 0x80 ? "PPU->CPU" : "CPU->PPU", m_dma_channel[i].dmap & 0x07); |
| 2214 | 2193 | #endif |
| 2215 | 2194 | |
| 2216 | | switch (state->m_dma_channel[i].dmap & 0x07) |
| 2195 | switch (m_dma_channel[i].dmap & 0x07) |
| 2217 | 2196 | { |
| 2218 | 2197 | case 0: /* 1 register write once */ |
| 2219 | 2198 | case 2: /* 1 register write twice */ |
| 2220 | 2199 | case 6: /* 1 register write twice */ |
| 2221 | 2200 | do |
| 2222 | 2201 | { |
| 2223 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2202 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2224 | 2203 | abus += increment; |
| 2225 | | } while (--length && !state->m_dma_channel[i].dma_disabled); |
| 2204 | } while (--length && !m_dma_channel[i].dma_disabled); |
| 2226 | 2205 | break; |
| 2227 | 2206 | case 1: /* 2 registers write once */ |
| 2228 | 2207 | case 5: /* 2 registers write twice alternate */ |
| 2229 | 2208 | do |
| 2230 | 2209 | { |
| 2231 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2210 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2232 | 2211 | abus += increment; |
| 2233 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2212 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2234 | 2213 | break; |
| 2235 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2214 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2236 | 2215 | abus += increment; |
| 2237 | | } while (--length && !state->m_dma_channel[i].dma_disabled); |
| 2216 | } while (--length && !m_dma_channel[i].dma_disabled); |
| 2238 | 2217 | break; |
| 2239 | 2218 | case 3: /* 2 registers write twice each */ |
| 2240 | 2219 | case 7: /* 2 registers write twice each */ |
| 2241 | 2220 | do |
| 2242 | 2221 | { |
| 2243 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2222 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2244 | 2223 | abus += increment; |
| 2245 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2224 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2246 | 2225 | break; |
| 2247 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2226 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2248 | 2227 | abus += increment; |
| 2249 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2228 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2250 | 2229 | break; |
| 2251 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2230 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2252 | 2231 | abus += increment; |
| 2253 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2232 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2254 | 2233 | break; |
| 2255 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2234 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2256 | 2235 | abus += increment; |
| 2257 | | } while (--length && !state->m_dma_channel[i].dma_disabled); |
| 2236 | } while (--length && !m_dma_channel[i].dma_disabled); |
| 2258 | 2237 | break; |
| 2259 | 2238 | case 4: /* 4 registers write once */ |
| 2260 | 2239 | do |
| 2261 | 2240 | { |
| 2262 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2241 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus); |
| 2263 | 2242 | abus += increment; |
| 2264 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2243 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2265 | 2244 | break; |
| 2266 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2245 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 1); |
| 2267 | 2246 | abus += increment; |
| 2268 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2247 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2269 | 2248 | break; |
| 2270 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 2); |
| 2249 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 2); |
| 2271 | 2250 | abus += increment; |
| 2272 | | if (!(--length) || state->m_dma_channel[i].dma_disabled) |
| 2251 | if (!(--length) || m_dma_channel[i].dma_disabled) |
| 2273 | 2252 | break; |
| 2274 | | snes_dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 3); |
| 2253 | dma_transfer(space, i, (abus & 0xffff) | abus_bank, bbus + 3); |
| 2275 | 2254 | abus += increment; |
| 2276 | | } while (--length && !state->m_dma_channel[i].dma_disabled); |
| 2255 | } while (--length && !m_dma_channel[i].dma_disabled); |
| 2277 | 2256 | break; |
| 2278 | 2257 | default: |
| 2279 | 2258 | #ifdef MAME_DEBUG |
| 2280 | | mame_printf_debug(" DMA of unsupported type: %d\n", state->m_dma_channel[i].dmap & 0x07); |
| 2259 | mame_printf_debug(" DMA of unsupported type: %d\n", m_dma_channel[i].dmap & 0x07); |
| 2281 | 2260 | #endif |
| 2282 | 2261 | break; |
| 2283 | 2262 | } |
| 2284 | 2263 | |
| 2285 | 2264 | /* We're done, so write the new abus back to the registers */ |
| 2286 | | state->m_dma_channel[i].src_addr = abus; |
| 2287 | | state->m_dma_channel[i].trans_size = 0; |
| 2265 | m_dma_channel[i].src_addr = abus; |
| 2266 | m_dma_channel[i].trans_size = 0; |
| 2288 | 2267 | } |
| 2289 | 2268 | } |
| 2290 | 2269 | |