diff options
Diffstat (limited to 'src/mame/drivers/nds.cpp')
-rw-r--r-- | src/mame/drivers/nds.cpp | 1000 |
1 files changed, 0 insertions, 1000 deletions
diff --git a/src/mame/drivers/nds.cpp b/src/mame/drivers/nds.cpp deleted file mode 100644 index da6acaaa177..00000000000 --- a/src/mame/drivers/nds.cpp +++ /dev/null @@ -1,1000 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz, R. Belmont -/*************************************************************************** - - nds.cpp - - Preliminary driver for first-generation Nintendo DS. - - Tech info: http://problemkaputt.de/gbatek.htm - - Notes: - Timers and DMAs 0-3 are ARM9's, 4-7 are ARM7's. - Interrupt registers [0] is ARM9, [1] is ARM7. - -***************************************************************************/ - -#include "emu.h" -#include "includes/nds.h" - -#define VERBOSE_LEVEL (0) - -// Measured value from GBATEK. Actual crystal unknown. -#define MASTER_CLOCK (33513982) - -#define INT_VBL 0x00000001 -#define INT_HBL 0x00000002 -#define INT_VCNT 0x00000004 -#define INT_TM0_OVERFLOW 0x00000008 -#define INT_TM1_OVERFLOW 0x00000010 -#define INT_TM2_OVERFLOW 0x00000020 -#define INT_TM3_OVERFLOW 0x00000040 -#define INT_SIO 0x00000080 // also RCNT/RTC (arm7 only) -#define INT_DMA0 0x00000100 -#define INT_DMA1 0x00000200 -#define INT_DMA2 0x00000400 -#define INT_DMA3 0x00000800 -#define INT_KEYPAD 0x00001000 -#define INT_GAMEPAK 0x00002000 // GBA slot IRQ line (never used?) -#define INT_NA1 0x00004000 // unused -#define INT_NA2 0x00008000 // unused -#define INT_IPCSYNC 0x00010000 -#define INT_IPCSENDEMPTY 0x00020000 -#define INT_IPCRECVNOTEMPTY 0x00040000 -#define INT_CARDXFERCOMPLETE 0x00080000 -#define INT_CARDIREQ 0x00100000 -#define INT_GEOCMDFIFO 0x00200000 // arm9 only -#define INT_SCREENUNFOLD 0x00400000 // arm7 only -#define INT_SPIBUS 0x00800000 // arm7 only -#define INT_WIFI 0x01000000 // arm7 only - also DSP on DSi -#define INT_CAMERA 0x02000000 // DSi only -#define INT_NA3 0x04000000 -#define INT_NA4 0x08000000 -#define INT_NEWDMA0 0x10000000 // DSi only -#define INT_NEWDMA1 0x20000000 // DSi only -#define INT_NEWDMA2 0x40000000 // DSi only -#define INT_NEWDMA3 0x80000000 // DSi only - -static const uint32_t timer_clks[4] = { MASTER_CLOCK, MASTER_CLOCK / 64, MASTER_CLOCK / 256, MASTER_CLOCK / 1024 }; - -static inline void ATTR_PRINTF(3,4) verboselog(device_t &device, int n_level, const char *s_fmt, ...) -{ - if( VERBOSE_LEVEL >= n_level ) - { - va_list v; - char buf[ 32768 ]; - va_start( v, s_fmt ); - vsprintf( buf, s_fmt, v ); - va_end( v ); - device.logerror( "%08x: %s", device.machine().describe_context(), buf ); - } -} - -uint32_t nds_state::arm7_io_r(offs_t offset, uint32_t mem_mask) -{ - uint8_t temp1, temp2; - switch(offset) - { - case TIMER_OFFSET: - case TIMER_OFFSET+1: - case TIMER_OFFSET+2: - case TIMER_OFFSET+3: - { - uint32_t elapsed; - double time, ticks; - int timer = (offset - TIMER_OFFSET) + 4; - - printf("Read timer reg %x (PC=%x)\n", timer, m_arm7->pc()); - - // update times for - if (m_timer_regs[timer] & 0x800000) - { - if (m_timer_regs[timer] & 0x00040000) - { - elapsed = m_timer_regs[timer] & 0xffff; - } - else - { - time = 0.1; //m_tmr_timer[timer]->elapsed().as_double(); - - ticks = (double)(0x10000 - (m_timer_regs[timer] & 0xffff)); - - // printf("time %f ticks %f 1/hz %f\n", time, ticks, 1.0 / m_timer_hz[timer]); - - time *= ticks; - time /= (1.0 / m_timer_hz[timer]); - - elapsed = (uint32_t)time; - } - -// printf("elapsed = %x\n", elapsed); - } - else - { -// printf("Reading inactive timer!\n"); - elapsed = 0; - } - - return (m_timer_regs[timer] & 0xffff0000) | (elapsed & 0xffff); - } - break; - - case IME_OFFSET: - return m_ime[1]; - - case IE_OFFSET: - return m_ie[1]; - - case IF_OFFSET: - return m_if[1]; - - case IPCSYNC_OFFSET: - return m_arm7_ipcsync; - - case AUX_SPI_CNT_OFFSET: - printf("arm7: read AUX_SPI_CNT mask %08x\n", mem_mask); - return 0; - break; - - case GAMECARD_BUS_CTRL_OFFSET: - //printf("arm7: read GAMECARD_BUS_CTRL (%08x) mask %08x\n", m_gamecard_ctrl, mem_mask); - return m_gamecard_ctrl; - break; - - case GAMECARD_DATA_OFFSET: - printf("arm7: read to GAMECARD_DATA mask %08x\n", mem_mask); - return 0xffffffff; - break; - - case GAMECARD_DATA_2_OFFSET: - printf("arm7: read to GAMECARD_DATA2 mask %08x\n", mem_mask); - return 0xffffffff; - break; - - case GAMECARD_DATA_IN_OFFSET: - //printf("arm7: read to GAMECARD_DATA_IN mask %08x (len = %x)\n", mem_mask, m_cartdata_len); - if (m_cartdata_len >= 4) - { - m_cartdata_len -= 4; - } - else - { - m_cartdata_len = 0; - } - - if (m_cartdata_len == 0) - { - printf("NDS: xfer over\n"); - m_gamecard_ctrl &= ~GAMECARD_DATA_READY; - m_gamecard_ctrl &= ~GAMECARD_BLOCK_BUSY; - } - return 0xffffffff; - break; - - case SPI_CTRL_OFFSET: - //printf("arm7: read SPI_CTRL mask %08x\n", mem_mask); - return 0; - break; - - case POSTFLG_OFFSET: - /* Bit Use - * 0 0=Booting, 1=Booted (set by BIOS/firmware) - */ - return m_arm7_postflg; - - case WRAMSTAT_OFFSET: - temp1 = (((m_vramcntc & 3) == 2) && (m_vramcntc & 0x80)) ? 1 : 0; - temp2 = (((m_vramcntd & 3) == 2) && (m_vramcntd & 0x80)) ? 2 : 0; - return (m_wramcnt << 8) | temp1 | temp2; - - default: - verboselog(*this, 0, "[ARM7] [IO] Unknown read: %08x (%08x)\n", offset*4, mem_mask); - break; - } - - return 0; -} - -void nds_state::arm7_io_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch(offset) - { - case TIMER_OFFSET: - case TIMER_OFFSET+1: - case TIMER_OFFSET+2: - case TIMER_OFFSET+3: - { - double rate, clocksel; - uint32_t old_timer_regs; - - int timer = (offset - TIMER_OFFSET)+4; - - old_timer_regs = m_timer_regs[timer]; - - m_timer_regs[timer] = (m_timer_regs[timer] & ~(mem_mask & 0xFFFF0000)) | (data & (mem_mask & 0xFFFF0000)); - - printf("%08x to timer %d (mask %08x PC %x)\n", data, timer, ~mem_mask, m_arm7->pc()); - - if (ACCESSING_BITS_0_15) - { - m_timer_reload[timer] = ((m_timer_reload[timer] & ~mem_mask) | (data & mem_mask)) & 0x0000FFFF; - m_timer_recalc[timer] = 1; - } - - // enabling this timer? - if ((ACCESSING_BITS_16_31) && (data & 0x800000)) - { - double final; - - if ((old_timer_regs & 0x00800000) == 0) // start bit 0 -> 1 - { - m_timer_regs[timer] = (m_timer_regs[timer] & 0xFFFF0000) | (m_timer_reload[timer] & 0x0000FFFF); - } - - rate = 0x10000 - (m_timer_regs[timer] & 0xffff); - - clocksel = timer_clks[(m_timer_regs[timer] >> 16) & 3]; - - final = clocksel / rate; - - m_timer_hz[timer] = final; - - m_timer_recalc[timer] = 0; - - printf("Enabling timer %d @ %f Hz regs %08x\n", timer, final, m_timer_regs[timer]); - - // enable the timer - if( !(data & 0x40000) ) // if we're not in Count-Up mode - { - attotime time = attotime::from_hz(final); - m_tmr_timer[timer]->adjust(time, timer, time); - } - } - } - break; - - case IME_OFFSET: - printf("ARM7: %08x to IME\n", data); - COMBINE_DATA(&m_ime[1]); - break; - - case IE_OFFSET: - printf("ARM7: %08x to IE\n", data); - COMBINE_DATA(&m_ie[1]); - break; - - case IF_OFFSET: - COMBINE_DATA(&m_if[1]); - break; - - case IPCSYNC_OFFSET: - //printf("ARM7: %x to IPCSYNC\n", data); - m_arm9_ipcsync &= ~0xf; - m_arm9_ipcsync |= ((data >> 8) & 0xf); - m_arm7_ipcsync &= 0xf; - m_arm7_ipcsync |= (data & ~0xf); - break; - - case AUX_SPI_CNT_OFFSET: - //printf("arm7: %08x to AUX_SPI_CNT mask %08x\n", data, mem_mask); - m_spicnt &= 0x0080; - m_spicnt |= (data & 0xe043); - - break; - - case GAMECARD_BUS_CTRL_OFFSET: - //printf("arm7: %08x to GAMECARD_BUS_CTRL mask %08x\n", data, mem_mask); - m_gamecard_ctrl &= GAMECARD_DATA_READY; - m_gamecard_ctrl |= (data & ~GAMECARD_DATA_READY); - - if (!(m_spicnt & (1<<15))) - { - return; - } - - if (!(m_gamecard_ctrl & GAMECARD_BLOCK_BUSY)) - { - return; - } - - m_cartdata_len = (m_gamecard_ctrl >> 24) & 7; - if (m_cartdata_len == 7) - { - m_cartdata_len = 4; - } - else if (m_cartdata_len != 0) - { - m_cartdata_len = 256 << m_cartdata_len; - } - printf("nds: cartdata for transfer = %x\n", m_cartdata_len); - - if (m_cartdata_len > 0) - { - m_gamecard_ctrl |= GAMECARD_DATA_READY; - } - else - { - printf("NDS: xfer over\n"); - m_gamecard_ctrl &= ~GAMECARD_DATA_READY; - m_gamecard_ctrl &= ~GAMECARD_BLOCK_BUSY; - } - break; - - case GAMECARD_DATA_OFFSET: - //printf("arm7: %08x to GAMECARD_DATA mask %08x\n", data, mem_mask); - break; - - case GAMECARD_DATA_2_OFFSET: - //printf("arm7: %08x to GAMECARD_DATA2 mask %08x\n", data, mem_mask); - break; - - case SPI_CTRL_OFFSET: - //printf("arm7: %08x to SPI_CTRL mask %08x\n", data, mem_mask); - break; - - case POSTFLG_OFFSET: - /* Bit Use - * 0 0=Booting, 1=Booted (set by BIOS/firmware) - */ - if (!(m_arm7_postflg & POSTFLG_PBF_MASK) && m_arm7->pc() < 0x4000) - { - m_arm7_postflg &= ~POSTFLG_PBF_MASK; - m_arm7_postflg |= data & POSTFLG_PBF_MASK; - } - - if (ACCESSING_BITS_8_15) - { - if ((data>>8) & 0x80) - { - printf("arm7: HALT\n"); // halts the arm7 until an interrupt occurs - m_arm7->suspend(SUSPEND_REASON_HALT, 1); - m_arm7halted = true; - } - } - break; - default: - verboselog(*this, 0, "[ARM7] [IO] Unknown write: %08x = %08x (%08x)\n", offset*4, data, mem_mask); - break; - } -} - -uint32_t nds_state::arm9_io_r(offs_t offset, uint32_t mem_mask) -{ - switch(offset) - { - case TIMER_OFFSET: - case TIMER_OFFSET+1: - case TIMER_OFFSET+2: - case TIMER_OFFSET+3: - { - uint32_t elapsed; - double time, ticks; - int timer = (offset - TIMER_OFFSET); - - //printf("Read timer reg %x (PC=%x)\n", timer, m_arm9->pc()); - - // update times for - if (m_timer_regs[timer] & 0x800000) - { - if (m_timer_regs[timer] & 0x00040000) - { - elapsed = m_timer_regs[timer] & 0xffff; - } - else - { - time = 0.1; //m_tmr_timer[timer]->elapsed().as_double(); - - ticks = (double)(0x10000 - (m_timer_regs[timer] & 0xffff)); - - // printf("time %f ticks %f 1/hz %f\n", time, ticks, 1.0 / m_timer_hz[timer]); - - time *= ticks; - time /= (1.0 / m_timer_hz[timer]); - - elapsed = (uint32_t)time; - } - -// printf("elapsed = %x\n", elapsed); - } - else - { -// printf("Reading inactive timer!\n"); - elapsed = 0; - } - - return (m_timer_regs[timer] & 0xffff0000) | (elapsed & 0xffff); - } - break; - - case IME_OFFSET: - return m_ime[0]; - - case IE_OFFSET: - return m_ie[0]; - - case IF_OFFSET: - return m_if[0]; - - case IPCSYNC_OFFSET: - return m_arm9_ipcsync; - - case POSTFLG_OFFSET: - /* Bit Use - * 0 0=Booting, 1=Booted (set by BIOS/firmware) - * 1 RAM - */ - return m_arm9_postflg; - default: - verboselog(*this, 0, "[ARM9] [IO] Unknown read: %08x (%08x)\n", offset*4, mem_mask); - break; - } - - return 0; -} - -void nds_state::arm9_io_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch(offset) - { - case TIMER_OFFSET: - case TIMER_OFFSET+1: - case TIMER_OFFSET+2: - case TIMER_OFFSET+3: - { - double rate, clocksel; - uint32_t old_timer_regs; - - int timer = (offset - TIMER_OFFSET)+4; - - old_timer_regs = m_timer_regs[timer]; - - m_timer_regs[timer] = (m_timer_regs[timer] & ~(mem_mask & 0xFFFF0000)) | (data & (mem_mask & 0xFFFF0000)); - - printf("%x to timer %d (mask %x PC %x)\n", data, timer, ~mem_mask, m_arm9->pc()); - - if (ACCESSING_BITS_0_15) - { - m_timer_reload[timer] = ((m_timer_reload[timer] & ~mem_mask) | (data & mem_mask)) & 0x0000FFFF; - m_timer_recalc[timer] = 1; - } - - // enabling this timer? - if ((ACCESSING_BITS_16_31) && (data & 0x800000)) - { - double final; - - if ((old_timer_regs & 0x00800000) == 0) // start bit 0 -> 1 - { - m_timer_regs[timer] = (m_timer_regs[timer] & 0xFFFF0000) | (m_timer_reload[timer] & 0x0000FFFF); - } - - rate = 0x10000 - (m_timer_regs[timer] & 0xffff); - - clocksel = timer_clks[(m_timer_regs[timer] >> 16) & 3]; - - final = clocksel / rate; - - m_timer_hz[timer] = final; - - m_timer_recalc[timer] = 0; - - printf("Enabling timer %d @ %f Hz\n", timer, final); - - // enable the timer - if( !(data & 0x40000) ) // if we're not in Count-Up mode - { - attotime time = attotime::from_hz(final); - m_tmr_timer[timer]->adjust(time, timer, time); - } - } - } - break; - - case IME_OFFSET: - printf("ARM9: %08x to IME\n", data); - COMBINE_DATA(&m_ime[0]); - break; - - case IE_OFFSET: - printf("ARM9: %08x to IE\n", data); - COMBINE_DATA(&m_ie[0]); - break; - - case IF_OFFSET: - COMBINE_DATA(&m_if[0]); - break; - - case IPCSYNC_OFFSET: - printf("ARM9: %x to IPCSYNC\n", data); - m_arm7_ipcsync &= ~0xf; - m_arm7_ipcsync |= ((data >> 8) & 0xf); - m_arm9_ipcsync &= 0xf; - m_arm9_ipcsync |= (data & ~0xf); - break; - - case VRAMCNT_A_OFFSET: - if (ACCESSING_BITS_0_7) // VRAMCNT_A - { - m_vramcnta = data & 0xff; - } - if (ACCESSING_BITS_8_15) // VRAMCNT_B - { - m_vramcntb = (data >> 8) & 0xff; - } - if (ACCESSING_BITS_16_23) // VRAMCNT_C - { - m_vramcntc = (data >> 16) & 0xff; - } - if (ACCESSING_BITS_24_31) // VRAMCNT_D - { - m_vramcntd = (data >> 24) & 0xff; - } - break; - - case WRAMCNT_OFFSET: - if (ACCESSING_BITS_0_7) // VRAMCNT_E - { - m_vramcnte = data & 0xff; - } - if (ACCESSING_BITS_8_15) // VRAMCNT_F - { - m_vramcntf = (data >> 8) & 0xff; - } - if (ACCESSING_BITS_16_23) // VRAMCNT_G - { - m_vramcntg = (data >> 16) & 0xff; - } - if (ACCESSING_BITS_24_31) // WRAMCNT - { - m_wramcnt = (data>>24) & 0x3; - m_arm7wrambnk->set_bank(m_wramcnt); - m_arm9wrambnk->set_bank(m_wramcnt); - } - break; - - case VRAMCNT_H_OFFSET: - if (ACCESSING_BITS_0_7) // VRAMCNT_H - { - m_vramcnth = data & 0xff; - } - if (ACCESSING_BITS_8_15) // VRAMCNT_I - { - m_vramcnti = (data >> 8) & 0xff; - } - break; - - case POSTFLG_OFFSET: - /* Bit Use - * 0 0=Booting, 1=Booted (set by BIOS/firmware) - * 1 RAM - */ - if (!(m_arm9_postflg & POSTFLG_PBF_MASK)) - { - m_arm9_postflg &= ~POSTFLG_PBF_MASK; - m_arm9_postflg |= data & POSTFLG_PBF_MASK; - } - m_arm9_postflg &= ~POSTFLG_RAM_MASK; - m_arm9_postflg |= data & POSTFLG_RAM_MASK; - break; - default: - verboselog(*this, 0, "[ARM7] [IO] Unknown write: %08x = %08x (%08x)\n", offset*4, data, mem_mask); - break; - } -} - -void nds_state::nds_arm7_map(address_map &map) -{ - map(0x00000000, 0x00003fff).rom().region("arm7", 0); - map(0x02000000, 0x023fffff).ram().mirror(0x00400000).share("mainram"); - map(0x03000000, 0x03007fff).mirror(0x007f8000).m(m_arm7wrambnk, FUNC(address_map_bank_device::amap32)); - map(0x03800000, 0x0380ffff).ram().mirror(0x007f0000).share("arm7ram"); - map(0x04000000, 0x0410ffff).rw(FUNC(nds_state::arm7_io_r), FUNC(nds_state::arm7_io_w)); -} - -void nds_state::nds_arm9_map(address_map &map) -{ - map(0x02000000, 0x023fffff).ram().mirror(0x00400000).share("mainram"); - map(0x03000000, 0x03007fff).mirror(0x00ff8000).m("nds9wram", FUNC(address_map_bank_device::amap32)); - map(0x04000000, 0x0410ffff).rw(FUNC(nds_state::arm9_io_r), FUNC(nds_state::arm9_io_w)); - map(0xffff0000, 0xffff0fff).rom().mirror(0x1000).region("arm9", 0); -} - -// ARM7 views of WRAM -void nds_state::nds7_wram_map(address_map &map) -{ - map(0x00000, 0x07fff).rw(FUNC(nds_state::wram_arm7mirror_r), FUNC(nds_state::wram_arm7mirror_w)); - map(0x08000, 0x0bfff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); - map(0x0c000, 0x0ffff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); - map(0x10000, 0x13fff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w)); - map(0x14000, 0x17fff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w)); - map(0x18000, 0x1ffff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); -} - -// ARM9 views of WRAM -void nds_state::nds9_wram_map(address_map &map) -{ - map(0x00000, 0x07fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); - map(0x08000, 0x0bfff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w)); - map(0x0c000, 0x0ffff).rw(FUNC(nds_state::wram_second_half_r), FUNC(nds_state::wram_second_half_w)); - map(0x10000, 0x13fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); - map(0x14000, 0x17fff).rw(FUNC(nds_state::wram_first_half_r), FUNC(nds_state::wram_first_half_w)); - map(0x18000, 0x1ffff).noprw().nopw(); // probably actually open bus? GBATEK describes as "random" -} - -uint32_t nds_state::wram_first_half_r(offs_t offset) { return m_WRAM[offset]; } -uint32_t nds_state::wram_second_half_r(offs_t offset) { return m_WRAM[offset+0x4000]; } -void nds_state::wram_first_half_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_WRAM[offset]); } -void nds_state::wram_second_half_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_WRAM[offset+0x4000]); } -uint32_t nds_state::wram_arm7mirror_r(offs_t offset) { return m_arm7ram[offset]; } -void nds_state::wram_arm7mirror_w(offs_t offset, uint32_t data, uint32_t mem_mask) { COMBINE_DATA(&m_arm7ram[offset]); } - -static INPUT_PORTS_START( nds ) -INPUT_PORTS_END - -void nds_state::machine_reset() -{ - m_arm7_postflg = 0; - m_arm9_postflg = 0; - m_wramcnt = 0; - m_arm7wrambnk->set_bank(0); - m_arm9wrambnk->set_bank(0); - m_arm7halted = false; -} - -void nds_state::machine_start() -{ - int i; - - for (i = 0; i < 8; i++) - { - m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::dma_complete),this)); - m_dma_timer[i]->adjust(attotime::never, i); - - m_tmr_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::timer_expire),this)); - m_tmr_timer[i]->adjust(attotime::never, i); - } - - m_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(nds_state::handle_irq),this)); - m_irq_timer->adjust(attotime::never); -} - -TIMER_CALLBACK_MEMBER(nds_state::dma_complete) -{ - #if 0 - static const uint32_t ch_int[8] = { INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3, INT_DMA0, INT_DMA1, INT_DMA2, INT_DMA3 }; - - uintptr_t ch = param; - -// printf("dma complete: ch %d\n", ch); - - m_dma_timer[ch]->adjust(attotime::never); - - int ctrl = DMACNT_H(ch); - - // IRQ - if (ctrl & 0x4000) - { - request_irq(ch_int[ch]); - } - - // if we're supposed to repeat, don't clear "active" and then the next vbl/hbl will retrigger us - // always clear active for immediate DMAs though - if (!((ctrl>>9) & 1) || ((ctrl & 0x3000) == 0)) - { - DMACNT_H_RESET(ch, 0x8000); // clear "active" bit - } - else - { - // if repeat, reload the count - if ((ctrl>>9) & 1) - { - m_dma_cnt[ch] = DMACNT_L(ch); - - // if increment & reload mode, reload the destination - if (((ctrl>>5)&3) == 3) - { - m_dma_dst[ch] = DMADAD(ch); - } - } - } - #endif -} - -void nds_state::dma_exec(int ch) -{ - #if 0 - address_space &space; - uint32_t src = m_dma_src[ch]; - uint32_t dst = m_dma_dst[ch]; - uint16_t ctrl = DMACNT_H(ch); - int srcadd = (ctrl >> 7) & 3; - int dstadd = (ctrl >> 5) & 3; - - if (ch > 4) - { - space = m_arm7->space(AS_PROGRAM); - } - else - { - space = m_arm9->space(AS_PROGRAM); - } - - int cnt = m_dma_cnt[ch]; - if (cnt == 0) - { - if (ch == 3) - cnt = 0x10000; - else - cnt = 0x4000; - } - -// if (dst >= 0x6000000 && dst <= 0x6017fff) -// printf("DMA exec: ch %d from %08x to %08x, mode %04x, count %04x (%s)\n", (int)ch, src, dst, ctrl, cnt, ((ctrl>>10) & 1) ? "32" : "16"); - - for (int i = 0; i < cnt; i++) - { - if ((ctrl>>10) & 1) - { - src &= 0xfffffffc; - dst &= 0xfffffffc; - - // 32-bit - space.write_dword(dst, space.read_dword(src)); - switch (dstadd) - { - case 0: // increment - dst += 4; - break; - case 1: // decrement - dst -= 4; - break; - case 2: // don't move - break; - case 3: // increment and reload - dst += 4; - break; - } - switch (srcadd) - { - case 0: // increment - src += 4; - break; - case 1: // decrement - src -= 4; - break; - case 2: // don't move - break; - case 3: // not used ("Metal Max 2 Kai" expects no increment/decrement) - break; - } - } - else - { - src &= 0xfffffffe; - dst &= 0xfffffffe; - - // 16-bit - space.write_word(dst, space.read_word(src)); - switch (dstadd) - { - case 0: // increment - dst += 2; - break; - case 1: // decrement - dst -= 2; - break; - case 2: // don't move - break; - case 3: // increment and reload - dst += 2; - break; - } - switch (srcadd) - { - case 0: // increment - src += 2; - break; - case 1: // decrement - src -= 2; - break; - case 2: // don't move - break; - case 3: // not used (see note in 32-bit version above) - break; - } - } - } - - m_dma_src[ch] = src; - m_dma_dst[ch] = dst; -#endif -// printf("settng DMA timer %d for %d cycs (tmr %x)\n", ch, cnt, (uint32_t)m_dma_timer[ch]); -// m_dma_timer[ch]->adjust(ATTOTIME_IN_CYCLES(0, cnt), ch); - dma_complete(nullptr, ch); -} - -TIMER_CALLBACK_MEMBER(nds_state::handle_irq) -{ - request_irq(0, m_if[0]); - request_irq(1, m_if[1]); - - m_irq_timer->adjust(attotime::never); -} - -void nds_state::request_irq(int cpu, uint32_t int_type) -{ - // set flag for later recovery - m_if[cpu] |= int_type; - - printf("request IRQ %08x on CPU %d\n", int_type, cpu); - - // is this specific interrupt enabled? - int_type &= m_ie[cpu]; - if (int_type != 0) - { - // master enable? - if (m_ime[cpu] & 1) - { - if (cpu == 0) - { - m_arm9->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); - m_arm9->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE); - } - else - { - if (m_arm7halted) - { - printf("ARM7 unhalting\n"); - m_arm7->resume(SUSPEND_REASON_HALT); - m_arm7halted = false; - } - - m_arm7->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE); - m_arm7->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE); - } - } - } -} - -TIMER_CALLBACK_MEMBER(nds_state::timer_expire) -{ - static const uint32_t tmr_ints[8] = { INT_TM0_OVERFLOW, INT_TM1_OVERFLOW, INT_TM2_OVERFLOW, INT_TM3_OVERFLOW }; - uintptr_t tmr = (uintptr_t) param; - int cpu = (tmr > 4) ? 1 : 0; - - verboselog(*this, 1, "Timer %d expired\n", (int)tmr); - - // "The reload value is copied into the counter only upon following two situations: Automatically upon timer overflows," - // "or when the timer start bit becomes changed from 0 to 1." - if (m_timer_recalc[tmr] != 0) - { - double rate, clocksel, final; - attotime time; - m_timer_recalc[tmr] = 0; - m_timer_regs[tmr] = (m_timer_regs[tmr] & 0xFFFF0000) | (m_timer_reload[tmr] & 0x0000FFFF); - rate = 0x10000 - (m_timer_regs[tmr] & 0xffff); - clocksel = timer_clks[(m_timer_regs[tmr] >> 16) & 3]; - final = clocksel / rate; - m_timer_hz[tmr] = final; - time = attotime::from_hz(final); - m_tmr_timer[tmr]->adjust(time, tmr, time); - } - - // Handle count-up timing - switch (tmr) - { - case 0: - if (m_timer_regs[1] & 0x40000) - { - m_timer_regs[1] = (( ( m_timer_regs[1] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[1] & 0xffff0000); - if( ( m_timer_regs[1] & 0x0000ffff ) == 0 ) - { - m_timer_regs[1] |= m_timer_reload[1]; - if( ( m_timer_regs[1] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[1]); - } - if( ( m_timer_regs[2] & 0x40000 ) ) - { - m_timer_regs[2] = (( ( m_timer_regs[2] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[2] & 0xffff0000); - if( ( m_timer_regs[2] & 0x0000ffff ) == 0 ) - { - m_timer_regs[2] |= m_timer_reload[2]; - if( ( m_timer_regs[2] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[2]); - } - if( ( m_timer_regs[3] & 0x40000 ) ) - { - m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000); - if( ( m_timer_regs[3] & 0x0000ffff ) == 0 ) - { - m_timer_regs[3] |= m_timer_reload[3]; - if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[3]); - } - } - } - } - } - } - } - break; - case 1: - if (m_timer_regs[2] & 0x40000) - { - m_timer_regs[2] = (( ( m_timer_regs[2] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[2] & 0xffff0000); - if( ( m_timer_regs[2] & 0x0000ffff ) == 0 ) - { - m_timer_regs[2] |= m_timer_reload[2]; - if( ( m_timer_regs[2] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[2]); - } - if( ( m_timer_regs[3] & 0x40000 ) ) - { - m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000); - if( ( m_timer_regs[3] & 0x0000ffff ) == 0 ) - { - m_timer_regs[3] |= m_timer_reload[3]; - if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[3]); - } - } - } - } - } - break; - case 2: - if (m_timer_regs[3] & 0x40000) - { - m_timer_regs[3] = (( ( m_timer_regs[3] & 0x0000ffff ) + 1 ) & 0x0000ffff) | (m_timer_regs[3] & 0xffff0000); - if( ( m_timer_regs[3] & 0x0000ffff ) == 0 ) - { - m_timer_regs[3] |= m_timer_reload[3]; - if( ( m_timer_regs[3] & 0x400000 ) && ( m_ime[cpu] != 0 ) ) - { - request_irq(cpu, tmr_ints[3]); - } - } - } - break; - } - - // are we supposed to IRQ? - if ((m_timer_regs[tmr] & 0x400000) && (m_ime[cpu] != 0)) - { - request_irq(cpu, tmr_ints[tmr & 3]); - } -} - -void nds_state::nds(machine_config &config) -{ - ARM7(config, m_arm7, MASTER_CLOCK); - m_arm7->set_addrmap(AS_PROGRAM, &nds_state::nds_arm7_map); - - ARM946ES(config, m_arm9, MASTER_CLOCK*2); - m_arm9->set_high_vectors(); - m_arm9->set_addrmap(AS_PROGRAM, &nds_state::nds_arm9_map); - - // WRAM - ADDRESS_MAP_BANK(config, "nds7wram").set_map(&nds_state::nds7_wram_map).set_options(ENDIANNESS_LITTLE, 32, 32, 0x8000); - ADDRESS_MAP_BANK(config, "nds9wram").set_map(&nds_state::nds9_wram_map).set_options(ENDIANNESS_LITTLE, 32, 32, 0x8000); -} - -/* Help identifying the region and revisions of the set would be greatly appreciated! */ -ROM_START( nds ) - ROM_REGION( 0x1000, "arm9", 0 ) - ROM_LOAD( "biosnds9.rom", 0x0000, 0x1000, CRC(2ab23573) SHA1(bfaac75f101c135e32e2aaf541de6b1be4c8c62d) ) - - ROM_REGION( 0x4000, "arm7", 0 ) - ROM_LOAD( "biosnds7.rom", 0x0000, 0x4000, CRC(1280f0d5) SHA1(24f67bdea115a2c847c8813a262502ee1607b7df) ) - - ROM_REGION32_LE( 0x40000, "firmware", 0 ) - ROM_LOAD( "firmware.bin", 0x0000, 0x40000, CRC(945f9dc9) SHA1(cfe072921ee3fb93f688743f8beef89043c3e9ad) ) -ROM_END - -// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS -CONS( 2004, nds, 0, 0, nds, nds, nds_state, empty_init, "Nintendo", "DS", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) |