diff options
Diffstat (limited to 'src/mame/machine/n64.cpp')
-rw-r--r-- | src/mame/machine/n64.cpp | 2782 |
1 files changed, 0 insertions, 2782 deletions
diff --git a/src/mame/machine/n64.cpp b/src/mame/machine/n64.cpp deleted file mode 100644 index 376a3b6162f..00000000000 --- a/src/mame/machine/n64.cpp +++ /dev/null @@ -1,2782 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/* machine/n64.c - contains N64 hardware emulation shared between MAME and MESS */ - -#include "emu.h" -#include "debugger.h" -#include "screen.h" -#include "cpu/mips/mips3.h" -#include "cpu/mips/mips3com.h" -#include "includes/n64.h" -#include "video/n64.h" - -// device type definition -DEFINE_DEVICE_TYPE(N64PERIPH, n64_periphs, "n64_periphs", "N64 Peripheral Chips") - -n64_periphs::n64_periphs(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, N64PERIPH, tag, owner, clock) - , device_video_interface(mconfig, *this) - , m_nvram_image(nullptr) - , dd_present(false) - , disk_present(false) - , cart_present(false) - , m_vr4300(*this, "^maincpu") - , m_rsp(*this, "^rsp") - , m_rsp_imem(*this, "^rsp_imem") - , m_rsp_dmem(*this, "^rsp_dmem") - , ai_dac(*this, "^dac%u", 1U) -{ - for (int32_t i = 0; i < 256; i++) - { - m_gamma_table[i] = sqrt((float)(i << 6)); - m_gamma_table[i] <<= 1; - } - - for (int32_t i = 0; i < 0x4000; i++) - { - m_gamma_dither_table[i] = sqrt((float)i); - m_gamma_dither_table[i] <<= 1; - } -} - -TIMER_CALLBACK_MEMBER(n64_periphs::reset_timer_callback) -{ - reset_tick(); -} - -void n64_periphs::reset_tick() -{ - reset_timer->adjust(attotime::never); - m_vr4300->reset(); - m_vr4300->set_input_line(INPUT_LINE_IRQ2, CLEAR_LINE); - m_rsp->reset(); - m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_HALT); - reset_held = false; - cic_status = 0; - memset(pif_ram, 0, sizeof(pif_ram)); - switch(cic_type) - { - case 1: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x06; - pif_ram[0x26] = 0x3f; - pif_ram[0x27] = 0x3f; - break; - case 3: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x02; - pif_ram[0x26] = 0x78; - pif_ram[0x27] = 0x3f; - break; - case 5: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x02; - pif_ram[0x26] = 0x91; - pif_ram[0x27] = 0x3f; - break; - case 6: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x02; - pif_ram[0x26] = 0x85; - pif_ram[0x27] = 0x3f; - break; - case 0xd: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x0a; - pif_ram[0x26] = 0xdd; - pif_ram[0x27] = 0x3f; - break; - default: - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x02; - pif_ram[0x26] = 0x3f; - pif_ram[0x27] = 0x3f; - break; - } -} - -void n64_periphs::poll_reset_button(bool button) -{ - bool old_held = reset_held; - reset_held = button; - if(!old_held && reset_held) - { - m_vr4300->set_input_line(INPUT_LINE_IRQ2, ASSERT_LINE); - } - else if(old_held && reset_held) - { - reset_timer->adjust(attotime::never); - } - else if(old_held && !reset_held) - { - reset_timer->adjust(attotime::from_hz(1)); - } -} - -void n64_periphs::device_start() -{ - ai_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::ai_timer_callback),this)); - pi_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::pi_dma_callback),this)); - si_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::si_dma_callback),this)); - vi_scanline_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::vi_scanline_callback),this)); - dp_delay_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::dp_delay_callback),this)); - reset_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(n64_periphs::reset_timer_callback),this)); - m_n64 = machine().driver_data<n64_state>(); -} - -void n64_periphs::device_reset() -{ - uint32_t *cart = (uint32_t*)machine().root_device().memregion("user2")->base(); - - m_mem_map = &m_vr4300->space(AS_PROGRAM); - - m_rdram = m_n64->rdram(); - m_sram = m_n64->sram(); - - mi_version = 0x01010101; - mi_interrupt = 0; - mi_intr_mask = 0; - mi_mode = 0x80; // Skip RDRAM initialization - - sp_mem_addr = 0; - sp_dram_addr = 0; - sp_mem_addr_start = 0; - sp_dram_addr_start = 0; - sp_dma_length = 0; - sp_dma_count = 0; - sp_dma_skip = 0; - sp_semaphore = 0; - - vi_width = 0; - vi_origin = 0; - vi_control = 0; - vi_burst = 0; - vi_vsync = 0; - vi_hsync = 0; - vi_leap = 0; - vi_hstart = 0; - vi_vstart = 0; - vi_intr = 0; - vi_vburst = 0; - vi_xscale = 0; - vi_yscale = 0; - field = 0; - - ai_timer->adjust(attotime::never); - memset(ai_fifo, 0, sizeof(ai_fifo)); - ai_fifo_wpos = 0; - ai_fifo_rpos = 0; - ai_fifo_num = 0; - ai_dram_addr = 0; - ai_len = 0 ; - ai_control = 0; - ai_dacrate = 0; - ai_bitrate = 0; - ai_status = 0; - ai_delayed_carry = false; - - pi_dma_timer->adjust(attotime::never); - pi_rd_len = 0; - pi_wr_len = 0; - pi_status = 0; - pi_bsd_dom1_lat = 0; - pi_bsd_dom1_pwd = 0; - pi_bsd_dom1_pgs = 0; - pi_bsd_dom1_rls = 0; - pi_bsd_dom2_lat = 0; - pi_bsd_dom2_pwd = 0; - pi_bsd_dom2_pgs = 0; - pi_bsd_dom2_rls = 0; - pi_dma_dir = 0; - - memset(dd_buffer, 0, sizeof(dd_buffer)); - memset(dd_sector_data, 0, sizeof(dd_sector_data)); - memset(dd_ram_seq_data, 0, sizeof(dd_ram_seq_data)); - dd_data_reg = 0; - dd_status_reg = 0; - dd_track_reg = 0; - dd_buf_status_reg = 0; - dd_sector_err_reg = 0; - dd_seq_status_reg = 0; - dd_seq_ctrl_reg = 0; - dd_int = 0; - dd_bm_reset_held = false; - dd_write = false; - dd_zone = 0; - dd_track_offset = 0; - - memset(ri_regs, 0, sizeof(ri_regs)); - - ri_regs[0] = 0xe; // Skip RDRAM initialization - ri_regs[1] = 0x40; // - ri_regs[3] = 0x14; // - ri_regs[4] = 0x63634; // - memset(pif_ram, 0, sizeof(pif_ram)); - memset(pif_cmd, 0, sizeof(pif_cmd)); - si_dram_addr = 0; - si_pif_addr = 0; - si_status_val = 0; - si_dma_dir = 0; - si_dma_timer->adjust(attotime::never); - - dp_clock = 0; - - dp_delay_timer->adjust(attotime::never); - - cic_status = 0; - - reset_held = false; - reset_timer->adjust(attotime::never); - - // bootcode differs between CIC-chips, so we can use its checksum to detect the CIC-chip - uint64_t boot_checksum = 0; - for(int i = 0x40; i < 0x1000; i+=4) - { - boot_checksum += cart[i/4]+i; - } - - // CIC-NUS-6102 (default) - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x00; - pif_ram[0x26] = 0x3f; - pif_ram[0x27] = 0x3f; - cic_type=2; - m_mem_map->write_dword(0x00000318, 0x800000); /* RDRAM Size */ - - if (boot_checksum == 0x00000000001ff230U) - { - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x08; - pif_ram[0x26] = 0xdd; - pif_ram[0x27] = 0x3f; - cic_type=0xd; - } - else if (boot_checksum == 0x000000cffb830843U || boot_checksum == 0x000000d0027fdf31U) - { - // CIC-NUS-6101 - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x04; - pif_ram[0x26] = 0x3f; - pif_ram[0x27] = 0x3f; - cic_type=1; - } - else if (boot_checksum == 0x000000d6499e376bU) - { - // CIC-NUS-6103 - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x00; - pif_ram[0x26] = 0x78; - pif_ram[0x27] = 0x3f; - cic_type=3; - } - else if (boot_checksum == 0x0000011a4a1604b6U) - { - // CIC-NUS-6105 - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x00; - pif_ram[0x26] = 0x91; - pif_ram[0x27] = 0x3f; - cic_type=5; - m_mem_map->write_dword(0x000003f0, 0x800000); - } - else if (boot_checksum == 0x000000d6d5de4ba0U) - { - // CIC-NUS-6106 - pif_ram[0x24] = 0x00; - pif_ram[0x25] = 0x00; - pif_ram[0x26] = 0x85; - pif_ram[0x27] = 0x3f; - cic_type=6; - } - - // Mouse X2/Y2 for delta - for (int i = 0; i < 4; i++) - { - mouse_x2[i] = 0; - mouse_y2[i] = 0; - } -} - -// Memory Interface (MI) - -#define MI_CLR_INIT 0x0080 /* Bit 7: clear init mode */ -#define MI_SET_INIT 0x0100 /* Bit 8: set init mode */ -#define MI_CLR_EBUS 0x0200 /* Bit 9: clear ebus test */ -#define MI_SET_EBUS 0x0400 /* Bit 10: set ebus test mode */ -#define MI_CLR_DP_INTR 0x0800 /* Bit 11: clear dp interrupt */ -#define MI_CLR_RDRAM 0x1000 /* Bit 12: clear RDRAM reg */ -#define MI_SET_RDRAM 0x2000 /* Bit 13: set RDRAM reg mode */ -#define MI_MODE_INIT 0x0080 /* Bit 7: init mode */ -#define MI_MODE_EBUS 0x0100 /* Bit 8: ebus test mode */ -#define MI_MODE_RDRAM 0x0200 /* Bit 9: RDRAM reg mode */ - -uint32_t n64_periphs::mi_reg_r(offs_t offset, uint32_t mem_mask) -{ - uint32_t ret = 0; - switch (offset) - { - case 0x00/4: // MI_MODE_REG - ret = mi_mode; - break; - - case 0x04/4: // MI_VERSION_REG - ret = mi_version; - break; - - case 0x08/4: // MI_INTR_REG - ret = mi_interrupt; - break; - - case 0x0c/4: // MI_INTR_MASK_REG - ret = mi_intr_mask; - break; - - default: - logerror("mi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - break; - } - - return ret; -} - -void n64_periphs::mi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch (offset) - { - case 0x00/4: // MI_INIT_MODE_REG - if (data & MI_CLR_INIT) mi_mode &= ~MI_MODE_INIT; - if (data & MI_SET_INIT) mi_mode |= MI_MODE_INIT; - if (data & MI_CLR_EBUS) mi_mode &= ~MI_MODE_EBUS; - if (data & MI_SET_EBUS) mi_mode |= MI_MODE_EBUS; - if (data & MI_CLR_RDRAM) mi_mode &= ~MI_MODE_RDRAM; - if (data & MI_SET_RDRAM) mi_mode |= MI_MODE_RDRAM; - if (data & MI_CLR_DP_INTR) - { - clear_rcp_interrupt(DP_INTERRUPT); - } - mi_mode &= ~0x7f; - mi_mode |= data & 0x7f; - break; - - case 0x04/4: // MI_VERSION_REG - mi_version = data; - break; - - case 0x0c/4: // MI_INTR_MASK_REG - { - if (data & 0x0001) - { - mi_intr_mask &= ~0x1; // clear SP mask - } - if (data & 0x0002) - { - mi_intr_mask |= 0x1; // set SP mask - } - if (data & 0x0004) - { - mi_intr_mask &= ~0x2; // clear SI mask - } - if (data & 0x0008) - { - mi_intr_mask |= 0x2; // set SI mask - } - if (data & 0x0010) - { - mi_intr_mask &= ~0x4; // clear AI mask - } - if (data & 0x0020) - { - mi_intr_mask |= 0x4; // set AI mask - } - if (data & 0x0040) - { - mi_intr_mask &= ~0x8; // clear VI mask - } - if (data & 0x0080) - { - mi_intr_mask |= 0x8; // set VI mask - } - if (data & 0x0100) - { - mi_intr_mask &= ~0x10; // clear PI mask - } - if (data & 0x0200) - { - mi_intr_mask |= 0x10; // set PI mask - } - if (data & 0x0400) - { - mi_intr_mask &= ~0x20; // clear DP mask - } - if (data & 0x0800) - { - mi_intr_mask |= 0x20; // set DP mask - } - check_interrupts(); - break; - } - - default: - logerror("mi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } -} - -void n64_periphs::check_interrupts() -{ - if (mi_intr_mask & mi_interrupt) - { - m_vr4300->set_input_line(INPUT_LINE_IRQ0, ASSERT_LINE); - } - else - { - m_vr4300->set_input_line(INPUT_LINE_IRQ0, CLEAR_LINE); - } -} - -void n64_periphs::signal_rcp_interrupt(int interrupt) -{ - mi_interrupt |= interrupt; - - check_interrupts(); -} - -void n64_periphs::clear_rcp_interrupt(int interrupt) -{ - mi_interrupt &= ~interrupt; - - check_interrupts(); -} - -uint32_t n64_periphs::is64_r(offs_t offset) -{ - switch(offset) - { - case 0x0000/4: - return 0x49533634; - - case 0x0004/4: - case 0x0008/4: - case 0x000c/4: - case 0x0010/4: - case 0x0014/4: - case 0x0018/4: - case 0x001c/4: - return 0; - - default: - return ( is64_buffer[(offset << 2) + 0] << 24 ) | - ( is64_buffer[(offset << 2) + 1] << 16 ) | - ( is64_buffer[(offset << 2) + 2] << 8 ) | - ( is64_buffer[(offset << 2) + 3] << 0 ); - } -} - -void n64_periphs::is64_w(offs_t offset, uint32_t data) -{ - int i = 0; - - switch(offset) - { - case 0x0014/4: - for(i = 0x20; i < (0x20 + data); i++) - { - if(is64_buffer[i] == 0x0a) - { - printf( "%c", 0x0d ); - } - is64_buffer[i] = 0; - } - break; - - default: - is64_buffer[(offset << 2) + 0] = (data >> 24) & 0x000000ff; - is64_buffer[(offset << 2) + 1] = (data >> 16) & 0x000000ff; - is64_buffer[(offset << 2) + 2] = (data >> 8) & 0x000000ff; - is64_buffer[(offset << 2) + 3] = (data >> 0) & 0x000000ff; - break; - } -} - -uint32_t n64_periphs::open_r(offs_t offset) -{ - uint32_t retval = (offset << 2) & 0x0000ffff; - retval = ((retval + 2) << 16) | retval; - return retval; -} - -void n64_periphs::open_w(uint32_t data) -{ - // Do nothing -} - -// RDRAM Interface (RI) - -#define RDRAM_CONFIG (0) -#define RDRAM_DEVICE_ID (1) -#define RDRAM_DELAY (2) -#define RDRAM_MODE (3) -#define RDRAM_REF_INTERVAL (4) -#define RDRAM_REF_ROW (5) -#define RDRAM_RAS_INTERVAL (6) -#define RDRAM_MIN_INTERVAL (7) -#define RDRAM_ADDR_SELECT (8) -#define RDRAM_DEVICE_MANUF (9) - -uint32_t n64_periphs::rdram_reg_r(offs_t offset, uint32_t mem_mask) -{ - if(offset > 0x24/4) - { - logerror("rdram_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - return 0; - } - return rdram_regs[offset]; -} - -void n64_periphs::rdram_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if(offset > 0x24/4) - { - logerror("rdram_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - return; - } - COMBINE_DATA(&rdram_regs[offset]); -} - -// RSP Interface - -void n64_periphs::sp_dma(int direction) -{ - sp_mem_addr = sp_mem_addr_start; - sp_dram_addr = sp_dram_addr_start; - - uint32_t length = sp_dma_length + 1; - - if ((length & 7) != 0) - { - length = (length + 7) & ~7; - } - - if (sp_mem_addr & 0x7) - { - sp_mem_addr = sp_mem_addr & ~7; - } - if (sp_dram_addr & 0x7) - { - sp_dram_addr = sp_dram_addr & ~7; - } - - if ((sp_mem_addr & 0xfff) + (length) > 0x1000) - { - length = 0x1000 - (sp_mem_addr & 0xfff); - } - - uint32_t *sp_mem[2] = { m_rsp_dmem, m_rsp_imem }; - - int sp_mem_page = (sp_mem_addr >> 12) & 1; - - //printf("DMA %s RSP: mem %08x, dram %08x, sp_dma_length: %03x, length: %04x, count: %02x, skip: %03x\n", direction ? "from" : "to", sp_mem_addr, sp_dram_addr, sp_dma_length, length, sp_dma_count, sp_dma_skip); - - if (direction == 0)// RDRAM -> I/DMEM - { - for (int c = 0; c <= sp_dma_count; c++) - { - uint32_t src = sp_dram_addr >> 2; - uint32_t dst = (sp_mem_addr & 0xfff) >> 2; - - for (int i = 0; i < length / 4; i++) - { - sp_mem[sp_mem_page][(dst + i) & 0x3ff] = m_rdram[src + i]; - } - - sp_mem_addr += length; - sp_dram_addr += length; - - if (c != sp_dma_count) - sp_dram_addr += sp_dma_skip; - } - } - else // I/DMEM -> RDRAM - { - for (int c = 0; c <= sp_dma_count; c++) - { - uint32_t src = (sp_mem_addr & 0xfff) >> 2; - uint32_t dst = sp_dram_addr >> 2; - - for (int i = 0; i < length / 4; i++) - { - m_rdram[dst + i] = sp_mem[sp_mem_page][(src + i) & 0x3ff]; - } - - sp_mem_addr += length; - sp_dram_addr += length; - - if (c != sp_dma_count) - sp_dram_addr += sp_dma_skip; - } - } - - sp_dma_count = 0; - sp_dma_length = 0xff8; -} - -void n64_periphs::sp_set_status(uint32_t data) -{ - if (data & 0x1) - { - m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_HALT); - } - - if (data & 0x2) - { - m_rsp->set_state_int(RSP_SR, m_rsp->state_int(RSP_SR) | RSP_STATUS_BROKE); - - if (m_rsp->state_int(RSP_SR) & RSP_STATUS_INTR_BREAK) - { - signal_rcp_interrupt(SP_INTERRUPT); - } - } -} - -uint32_t n64_periphs::sp_reg_r(offs_t offset) -{ - switch (offset) - { - case 0x00/4: // SP_MEM_ADDR_REG - return sp_mem_addr; - - case 0x04/4: // SP_DRAM_ADDR_REG - return sp_dram_addr; - - case 0x08/4: // SP_RD_LEN_REG - case 0x0c/4: // SP_WR_LEN_REG - return (sp_dma_skip << 20) | (sp_dma_count << 12) | sp_dma_length; - - case 0x10/4: // SP_STATUS_REG - return m_rsp->state_int(RSP_SR); - - case 0x14/4: // SP_DMA_FULL_REG - return 0; - - case 0x18/4: // SP_DMA_BUSY_REG - return 0; - - case 0x1c/4: // SP_SEMAPHORE_REG - //m_vr4300->yield(); - if( sp_semaphore ) - { - return 1; - } - else - { - sp_semaphore = 1; - return 0; - } - break; - - case 0x20/4: // DP_CMD_START - return m_n64->rdp()->get_start(); - - case 0x24/4: // DP_CMD_END - return m_n64->rdp()->get_end(); - - case 0x28/4: // DP_CMD_CURRENT - return m_n64->rdp()->get_current(); - - case 0x34/4: // DP_CMD_BUSY - case 0x38/4: // DP_CMD_PIPE_BUSY - case 0x3c/4: // DP_CMD_TMEM_BUSY - return 0; - - case 0x2c/4: // DP_CMD_STATUS - return m_n64->rdp()->get_status(); - - case 0x30/4: // DP_CMD_CLOCK - if(!(m_n64->rdp()->get_status() & DP_STATUS_FREEZE)) - { - dp_clock += 13; - return dp_clock; - } - break; - - case 0x40000/4: // PC - return m_rsp->state_int(RSP_PC) & 0x00000fff; - - default: - logerror("sp_reg_r: %08X at %08X\n", offset, m_vr4300->pc()); - break; - } - - return 0; -} - - -void n64_periphs::sp_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if ((offset & 0x10000) == 0) - { - switch (offset & 0xffff) - { - case 0x00/4: // SP_MEM_ADDR_REG - sp_mem_addr_start = data & 0x00001fff; - break; - - case 0x04/4: // SP_DRAM_ADDR_REG - sp_dram_addr_start = data & 0x007fffff; - break; - - case 0x08/4: // SP_RD_LEN_REG - sp_dma_length = data & 0xfff; - sp_dma_count = (data >> 12) & 0xff; - sp_dma_skip = (data >> 20) & 0xff8; - sp_dma(0); - break; - - case 0x0c/4: // SP_WR_LEN_REG - sp_dma_length = data & 0xfff; - sp_dma_count = (data >> 12) & 0xff; - sp_dma_skip = (data >> 20) & 0xff8; - sp_dma(1); - break; - - case 0x10/4: // RSP_STATUS_REG - { - uint32_t oldstatus = m_rsp->state_int(RSP_SR); - uint32_t newstatus = oldstatus; - - if (data & 0x00000001) // clear halt - { - m_rsp->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); - newstatus &= ~RSP_STATUS_HALT; - } - if (data & 0x00000002) // set halt - { - m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - newstatus |= RSP_STATUS_HALT; - } - if (data & 0x00000004) - { - newstatus &= ~RSP_STATUS_BROKE; - } - if (data & 0x00000008) // clear interrupt - { - clear_rcp_interrupt(SP_INTERRUPT); - } - if (data & 0x00000010) // set interrupt - { - signal_rcp_interrupt(SP_INTERRUPT); - } - if (data & 0x00000020) - { - newstatus &= ~RSP_STATUS_SSTEP; - } - if (data & 0x00000040) - { - newstatus |= RSP_STATUS_SSTEP; // set single step - if(!(oldstatus & (RSP_STATUS_BROKE | RSP_STATUS_HALT))) - { - m_rsp->set_state_int(RSP_STEPCNT, 1 ); - m_rsp->yield(); - } - } - if (data & 0x00000080) - { - newstatus &= ~RSP_STATUS_INTR_BREAK; // clear interrupt on break - } - if (data & 0x00000100) - { - newstatus |= RSP_STATUS_INTR_BREAK; // set interrupt on break - } - if (data & 0x00000200) - { - newstatus &= ~RSP_STATUS_SIGNAL0; // clear signal 0 - } - if (data & 0x00000400) - { - newstatus |= RSP_STATUS_SIGNAL0; // set signal 0 - } - if (data & 0x00000800) - { - newstatus &= ~RSP_STATUS_SIGNAL1; // clear signal 1 - } - if (data & 0x00001000) - { - newstatus |= RSP_STATUS_SIGNAL1; // set signal 1 - } - if (data & 0x00002000) - { - newstatus &= ~RSP_STATUS_SIGNAL2 ; // clear signal 2 - } - if (data & 0x00004000) - { - newstatus |= RSP_STATUS_SIGNAL2; // set signal 2 - } - if (data & 0x00008000) - { - newstatus &= ~RSP_STATUS_SIGNAL3; // clear signal 3 - } - if (data & 0x00010000) - { - newstatus |= RSP_STATUS_SIGNAL3; // set signal 3 - } - if (data & 0x00020000) - { - newstatus &= ~RSP_STATUS_SIGNAL4; // clear signal 4 - } - if (data & 0x00040000) - { - newstatus |= RSP_STATUS_SIGNAL4; // set signal 4 - } - if (data & 0x00080000) - { - newstatus &= ~RSP_STATUS_SIGNAL5; // clear signal 5 - } - if (data & 0x00100000) - { - newstatus |= RSP_STATUS_SIGNAL5; // set signal 5 - } - if (data & 0x00200000) - { - newstatus &= ~RSP_STATUS_SIGNAL6; // clear signal 6 - } - if (data & 0x00400000) - { - newstatus |= RSP_STATUS_SIGNAL6; // set signal 6 - } - if (data & 0x00800000) - { - newstatus &= ~RSP_STATUS_SIGNAL7; // clear signal 7 - } - if (data & 0x01000000) - { - newstatus |= RSP_STATUS_SIGNAL7; // set signal 7 - } - m_rsp->set_state_int(RSP_SR, newstatus); - break; - } - - case 0x1c/4: // SP_SEMAPHORE_REG - if(data == 0) - { - sp_semaphore = 0; - } - break; - - default: - logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } - } - else - { - switch (offset & 0xffff) - { - case 0x00/4: // SP_PC_REG - if (m_rsp->state_int(RSP_NEXTPC) != 0xffff) - { - m_rsp->set_state_int(RSP_NEXTPC, data & 0xfff); - } - else - { - m_rsp->set_state_int(RSP_PC, data & 0xfff); - } - break; - - default: - logerror("sp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } - } -} - - -// RDP Interface - -void n64_periphs::dp_full_sync() -{ - dp_delay_timer->adjust(attotime::from_hz(62500000 / 100)); -} - -TIMER_CALLBACK_MEMBER(n64_periphs::dp_delay_callback) -{ - dp_delay_timer->adjust(attotime::never); - signal_rcp_interrupt(DP_INTERRUPT); -} - -uint32_t n64_periphs::dp_reg_r(offs_t offset, uint32_t mem_mask) -{ - switch (offset) - { - case 0x00/4: // DP_START_REG - return m_n64->rdp()->get_start(); - - case 0x04/4: // DP_END_REG - return m_n64->rdp()->get_end(); - - case 0x08/4: // DP_CURRENT_REG - return m_n64->rdp()->get_current(); - - case 0x0c/4: // DP_STATUS_REG - return m_n64->rdp()->get_status(); - - case 0x10/4: // DP_CLOCK_REG - if(!(m_n64->rdp()->get_status() & DP_STATUS_FREEZE)) - { - dp_clock += 13; - return dp_clock; - } - break; - - default: - logerror("dp_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - break; - } - - return 0; -} - -void n64_periphs::dp_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - uint32_t status = m_n64->rdp()->get_status(); - - switch (offset) - { - case 0x00/4: // DP_START_REG - if(status & DP_STATUS_START_VALID) - { - break; - } - else - { - m_n64->rdp()->set_status(status | DP_STATUS_START_VALID); - m_n64->rdp()->set_start(data & ~7); - } - break; - - case 0x04/4: // DP_END_REG - if(status & DP_STATUS_START_VALID) - { - m_n64->rdp()->set_status(status & ~DP_STATUS_START_VALID); - m_n64->rdp()->set_current(m_n64->rdp()->get_start()); - m_n64->rdp()->set_end(data & ~7); - g_profiler.start(PROFILER_USER1); - m_n64->rdp()->process_command_list(); - g_profiler.stop(); - break; - } - else - { - m_n64->rdp()->set_end(data & ~7); - g_profiler.start(PROFILER_USER1); - m_n64->rdp()->process_command_list(); - g_profiler.stop(); - break; - } - - case 0x0c/4: // DP_STATUS_REG - { - uint32_t current_status = m_n64->rdp()->get_status(); - if (data & 0x00000001) current_status &= ~DP_STATUS_XBUS_DMA; - if (data & 0x00000002) current_status |= DP_STATUS_XBUS_DMA; - if (data & 0x00000004) current_status &= ~DP_STATUS_FREEZE; - //if (data & 0x00000008) current_status |= DP_STATUS_FREEZE; // Temp: Do nothing for now - if (data & 0x00000010) current_status &= ~DP_STATUS_FLUSH; - if (data & 0x00000020) current_status |= DP_STATUS_FLUSH; - if (data & 0x00000200) dp_clock = 0; - m_n64->rdp()->set_status(current_status); - break; - } - - default: - logerror("dp_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } -} - -TIMER_CALLBACK_MEMBER(n64_periphs::vi_scanline_callback) -{ - signal_rcp_interrupt(VI_INTERRUPT); - vi_scanline_timer->adjust(screen().time_until_pos(vi_intr)); -} - -// Video Interface -void n64_periphs::vi_recalculate_resolution() -{ - int x_start = (vi_hstart & 0x03ff0000) >> 16; - int x_end = vi_hstart & 0x000003ff; - int y_start = ((vi_vstart & 0x03ff0000) >> 16) >> 1; - int y_end = (vi_vstart & 0x000003ff) >> 1; - const float hcoeff = ((float)(vi_xscale & 0xfff) / (1 << 10)); - const float vcoeff = ((float)(vi_yscale & 0xfff) / (1 << 10)); - int width = (x_end - x_start) * hcoeff; - int height = (y_end - y_start) * vcoeff; - - rectangle visarea = screen().visible_area(); - // DACRATE is the quarter pixel clock and period will be for a field, not a frame - attoseconds_t period = (vi_hsync & 0xfff) * (vi_vsync & 0xfff) * HZ_TO_ATTOSECONDS(DACRATE_NTSC) / 2; - - if (width <= 0 || height <= 0 || (vi_control & 3) == 0) - { - vi_blank = 1; - /* - FIXME: MAME doesn't handle well a h/w res of zero (otherwise it hardlocks the emu, seen especially in Aleck 64 games - that sets the res after a longer delay than n64), guess that this just disables drawing? - */ - return; - } - else - { - vi_blank = 0; - } - - if (width > 640) - width = 640; - - if (height > 480) - height = 480; - - visarea.max_x = width - 1; - visarea.max_y = height - 1; - screen().configure((vi_hsync & 0x00000fff)>>2, (vi_vsync & 0x00000fff), visarea, period); -} - -uint32_t n64_periphs::vi_reg_r(offs_t offset, uint32_t mem_mask) -{ - uint32_t ret = 0; - switch (offset) - { - case 0x00/4: // VI_CONTROL_REG - ret = vi_control; - break; - - case 0x04/4: // VI_ORIGIN_REG - ret = vi_origin; - break; - - case 0x08/4: // VI_WIDTH_REG - ret = vi_width; - break; - - case 0x0c/4: - ret = vi_intr; - break; - - case 0x10/4: // VI_CURRENT_REG - ret = (screen().vpos() & 0x3FE) + field; - break; - - case 0x14/4: // VI_BURST_REG - ret = vi_burst; - break; - - case 0x18/4: // VI_V_SYNC_REG - ret = vi_vsync; - break; - - case 0x1c/4: // VI_H_SYNC_REG - ret = vi_hsync; - break; - - case 0x20/4: // VI_LEAP_REG - ret = vi_leap; - break; - - case 0x24/4: // VI_H_START_REG - ret = vi_hstart; - break; - - case 0x28/4: // VI_V_START_REG - ret = vi_vstart; - break; - - case 0x2c/4: // VI_V_BURST_REG - ret = vi_vburst; - break; - - case 0x30/4: // VI_X_SCALE_REG - ret = vi_xscale; - break; - - case 0x34/4: // VI_Y_SCALE_REG - ret = vi_yscale; - break; - - default: - logerror("vi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - break; - } - - return ret; -} - -void n64_periphs::vi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - //n64_state *state = machine().driver_data<n64_state>(); - - switch (offset) - { - case 0x00/4: // VI_CONTROL_REG - vi_control = data; - vi_recalculate_resolution(); - break; - - case 0x04/4: // VI_ORIGIN_REG - vi_origin = data & 0xffffff; - break; - - case 0x08/4: // VI_WIDTH_REG - { - uint32_t old_width = vi_width; - vi_width = data; - if (old_width != data && data > 0) - { - vi_recalculate_resolution(); - } - break; - } - - case 0x0c/4: // VI_INTR_REG - vi_intr = data; - vi_scanline_timer->adjust(screen().time_until_pos(vi_intr)); - break; - - case 0x10/4: // VI_CURRENT_REG - clear_rcp_interrupt(VI_INTERRUPT); - break; - - case 0x14/4: // VI_BURST_REG - vi_burst = data; - break; - - case 0x18/4: // VI_V_SYNC_REG - vi_vsync = data; - vi_recalculate_resolution(); - break; - - case 0x1c/4: // VI_H_SYNC_REG - vi_hsync = data; - vi_recalculate_resolution(); - break; - - case 0x20/4: // VI_LEAP_REG - vi_leap = data; - break; - - case 0x24/4: // VI_H_START_REG - vi_hstart = data; - vi_recalculate_resolution(); - break; - - case 0x28/4: // VI_V_START_REG - vi_vstart = data; - vi_recalculate_resolution(); - break; - - case 0x2c/4: // VI_V_BURST_REG - vi_vburst = data; - break; - - case 0x30/4: // VI_X_SCALE_REG - vi_xscale = data; - vi_recalculate_resolution(); - break; - - case 0x34/4: // VI_Y_SCALE_REG - vi_yscale = data; - vi_recalculate_resolution(); - break; - - /* - Uncomment this for convenient homebrew debugging - case 0x44/4: // TEMP DEBUG - printf( "E Ping: %08x\n", data ); - break; - */ - - default: - logerror("vi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } -} - - -// Audio Interface -void n64_periphs::ai_fifo_push(uint32_t address, uint32_t length) -{ - if (ai_fifo_num == AUDIO_DMA_DEPTH) - { - osd_printf_debug("ai_fifo_push: tried to push to full DMA FIFO!!!\n"); - } - - ai_fifo[ai_fifo_wpos].address = address; - ai_fifo[ai_fifo_wpos].length = length; - - ai_fifo_wpos++; - ai_fifo_num++; - - if (ai_fifo_wpos >= AUDIO_DMA_DEPTH) - { - ai_fifo_wpos = 0; - } - - if (ai_fifo_num >= AUDIO_DMA_DEPTH) - { - ai_status |= 0x80000001; // FIFO full - } - - if (! (ai_status & 0x40000000)) - { - ai_dma(); - } -} - -void n64_periphs::ai_fifo_pop() -{ - ai_fifo_rpos++; - ai_fifo_num--; - - if (ai_fifo_num < 0) - { - fatalerror("ai_fifo_pop: FIFO underflow!\n"); - } - - if (ai_fifo_rpos >= AUDIO_DMA_DEPTH) - { - ai_fifo_rpos = 0; - } - - if (ai_fifo_num < AUDIO_DMA_DEPTH) - { - ai_status &= ~0x80000001; // FIFO not full - } -} - -n64_periphs::AUDIO_DMA *n64_periphs::ai_fifo_get_top() -{ - if (ai_fifo_num > 0) - { - return &ai_fifo[ai_fifo_rpos]; - } - else - { - return nullptr; - } -} - -#define N64_ATTOTIME_NORMALIZE(a) do { while ((a).attoseconds >= ATTOSECONDS_PER_SECOND) { (a).seconds++; (a).attoseconds -= ATTOSECONDS_PER_SECOND; } } while (0) - -void n64_periphs::ai_dma() -{ - int16_t *ram = (int16_t*)m_rdram; - AUDIO_DMA *current = ai_fifo_get_top(); - attotime period; - - //static FILE * audio_dump = nullptr; - // - //if (audio_dump == nullptr) - // audio_dump = fopen("audio_dump.raw","wb"); - // - //fwrite(&ram[current->address/2],current->length,1,audio_dump); - - if (ai_delayed_carry) - current->address += 0x2000; - - ram = &ram[current->address/2]; - - //osd_printf_debug("DACDMA: %x for %x bytes\n", current->address, current->length); - - ai_dac[0]->transfer(0, 1, 2, current->length/4, ram); - ai_dac[1]->transfer(1, 1, 2, current->length/4, ram); - - ai_status |= 0x40000000; - - // adjust the timer - period = attotime::from_hz(DACRATE_NTSC) * (ai_dacrate + 1) * (current->length / 4); - ai_timer->adjust(period); - - if (((current->address + current->length) & 0x1FFF) == 0) - ai_delayed_carry = true; - else - ai_delayed_carry = false; -} - -TIMER_CALLBACK_MEMBER(n64_periphs::ai_timer_callback) -{ - ai_timer_tick(); -} - -void n64_periphs::ai_timer_tick() -{ - ai_fifo_pop(); - signal_rcp_interrupt(AI_INTERRUPT); - - // keep playing if there's another DMA queued - if (ai_fifo_get_top() != nullptr) - { - ai_dma(); - } - else - { - ai_status &= ~0x40000000; - ai_delayed_carry = false; - } -} - -uint32_t n64_periphs::ai_reg_r(offs_t offset, uint32_t mem_mask) -{ - uint32_t ret = 0; - switch (offset) - { - case 0x04/4: // AI_LEN_REG - { - if (ai_status & 0x40000000) - { - ret = 4 * (uint32_t)(ai_timer->remaining().as_double() * (double)DACRATE_NTSC / (double)(ai_dacrate + 1)); - } - else if (ai_status & 0x80000001) - { - ret = ai_len; - } - else - { - ret = 0; - } - break; - } - case 0x08/4: - ret = ai_control; - break; - case 0x0c/4: // AI_STATUS_REG - ret = ai_status; - break; - - default: - logerror("ai_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - break; - } - - return ret; -} - -void n64_periphs::ai_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch (offset) - { - case 0x00/4: // AI_DRAM_ADDR_REG - ai_dram_addr = data & 0xfffff8; - break; - - case 0x04/4: // AI_LEN_REG - ai_len = data & 0x3ffff; // Hardware v2.0 has 18 bits, v1.0 has 15 bits - ai_fifo_push(ai_dram_addr, ai_len); - break; - - case 0x08/4: // AI_CONTROL_REG - ai_control = data; - break; - - case 0x0c/4: - clear_rcp_interrupt(AI_INTERRUPT); - break; - - case 0x10/4: // AI_DACRATE_REG - { - ai_dacrate = data & 0x3fff; - const double frequency = (double)DACRATE_NTSC / (double)(ai_dacrate+1); - - ai_dac[0]->set_frequency(frequency); - ai_dac[0]->enable(1); - - ai_dac[1]->set_frequency(frequency); - ai_dac[1]->enable(1); - break; - } - - case 0x14/4: // AI_BITRATE_REG - ai_bitrate = data & 0xf; - break; - - default: - logerror("ai_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } -} - - -// Peripheral Interface - -TIMER_CALLBACK_MEMBER(n64_periphs::pi_dma_callback) -{ - pi_dma_tick(); -} - -void n64_periphs::pi_dma_tick() -{ - bool update_bm = false; - uint16_t *cart16; - uint16_t *dram16 = (uint16_t*)m_rdram; - - uint32_t cart_addr = (pi_cart_addr & 0x0fffffff) >> 1; - uint32_t dram_addr = (pi_dram_addr & 0x007fffff) >> 1; - - if(pi_cart_addr == 0x05000000 && dd_present) - { - update_bm = true; - cart16 = (uint16_t*)dd_buffer; - cart_addr = (pi_cart_addr & 0x000003ff) >> 1; - } - else if(pi_cart_addr == 0x05000400 && dd_present) - { - update_bm = true; - cart16 = (uint16_t*)dd_sector_data; - cart_addr = (pi_cart_addr & 0x000000ff) >> 1; - } - else if((cart_addr & 0x04000000) == 0x04000000) - { - cart16 = (uint16_t*)m_sram; - cart_addr = (pi_cart_addr & 0x0001ffff) >> 1; - } - else if((cart_addr & 0x03000000) == 0x03000000 && dd_present) - { - cart16 = (uint16_t*)machine().root_device().memregion("ddipl")->base(); - cart_addr = (pi_cart_addr & 0x003fffff) >> 1; - } - else - { - cart16 = (uint16_t*)machine().root_device().memregion("user2")->base(); - cart_addr &= ((machine().root_device().memregion("user2")->bytes() >> 1) - 1); - } - - if(pi_dma_dir == 1) - { - uint32_t dma_length = pi_wr_len + 1 + 1; //Round Up Nearest 2 - //logerror("PI Write, %X, %X, %X\n", pi_cart_addr, pi_dram_addr, pi_wr_len); - - if (pi_dram_addr != 0xffffffff) - { - for(int i = 0; i < dma_length / 2; i++) - { - dram16[BYTE_XOR_BE(dram_addr + i)] = cart16[BYTE_XOR_BE(cart_addr + i)]; - } - - pi_cart_addr += dma_length; - pi_dram_addr += dma_length; - } - } - else - { - uint32_t dma_length = pi_rd_len + 1 + 1; //Round Up Nearest 2 - //logerror("PI Read, %X, %X, %X\n", pi_cart_addr, pi_dram_addr, pi_rd_len); - - if (pi_dram_addr != 0xffffffff) - { - for(int i = 0; i < dma_length / 2; i++) - { - cart16[BYTE_XOR_BE(cart_addr + i)] = dram16[BYTE_XOR_BE(dram_addr + i)]; - } - - pi_cart_addr += dma_length; - pi_dram_addr += dma_length; - } - } - - pi_status &= ~1; // Clear DMA_BUSY - //pi_status |= 8; // Set INTERRUPT ?? Does this bit exist ?? - - if(update_bm) - dd_update_bm(); - - signal_rcp_interrupt(PI_INTERRUPT); - - pi_dma_timer->adjust(attotime::never); -} - -uint32_t n64_periphs::pi_reg_r(offs_t offset, uint32_t mem_mask) -{ - uint32_t ret = 0; - switch (offset) - { - case 0x00/4: // PI_DRAM_ADDR_REG - ret = pi_dram_addr; - break; - - case 0x04/4: // PI_CART_ADDR_REG - ret = pi_cart_addr; - break; - - case 0x08/4: // PI_RD_LEN_REG - ret = pi_rd_len; - break; - - case 0x0c/4: // PI_WR_LEN_REG - ret = pi_wr_len; - break; - - case 0x10/4: // PI_STATUS_REG - ret = pi_status; - break; - - case 0x14/4: // PI_BSD_DOM1_LAT - ret = pi_bsd_dom1_lat; - break; - - case 0x18/4: // PI_BSD_DOM1_PWD - ret = pi_bsd_dom1_pwd; - break; - - case 0x1c/4: // PI_BSD_DOM1_PGS - ret = pi_bsd_dom1_pgs; - break; - - case 0x20/4: // PI_BSD_DOM1_RLS - ret = pi_bsd_dom1_rls; - break; - - case 0x24/4: // PI_BSD_DOM2_LAT - ret = pi_bsd_dom2_lat; - break; - - case 0x28/4: // PI_BSD_DOM2_PWD - ret = pi_bsd_dom2_pwd; - break; - - case 0x2c/4: // PI_BSD_DOM2_PGS - ret = pi_bsd_dom2_pgs; - break; - - case 0x30/4: // PI_BSD_DOM2_RLS - ret = pi_bsd_dom2_rls; - break; - - default: - logerror("pi_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - break; - } - - return ret; -} - -void n64_periphs::pi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch (offset) - { - case 0x00/4: // PI_DRAM_ADDR_REG - pi_dram_addr = data; - break; - - case 0x04/4: // PI_CART_ADDR_REG - pi_cart_addr = data; - if(pi_cart_addr == 0x05000400 && dd_present) - { - dd_status_reg &= ~DD_ASIC_STATUS_DREQ; - dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; - //logerror("Clearing DREQ, INT\n"); - m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); - } - if(pi_cart_addr == 0x05000000 && dd_present) - { - dd_status_reg &= ~DD_ASIC_STATUS_C2_XFER; - dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; - //logerror("Clearing C2, INT\n"); - m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); - } - break; - - case 0x08/4: // PI_RD_LEN_REG - { - //printf("pi_rd_len_reg: %08x\n", data); - //logerror("Start PI Read\n"); - pi_rd_len = data; - pi_dma_dir = 0; - pi_status |= 1; - //pi_dma_tick(); - attotime dma_period = attotime::from_hz(93750000) * (int)((float)(pi_rd_len + 1) * 5.08f); // Measured as between 2.53 cycles per byte and 2.55 cycles per byte - pi_dma_timer->adjust(dma_period); - break; - } - - case 0x0c/4: // PI_WR_LEN_REG - { - //printf("pi_wr_len_reg: %08x\n", data); - //logerror("Start PI Write\n"); - pi_wr_len = data; - pi_dma_dir = 1; - pi_status |= 1; - //pi_dma_tick(); - attotime dma_period = attotime::from_hz(93750000) * (int)((float)(pi_wr_len + 1) * 5.08f); // Measured as between 2.53 cycles per byte and 2.55 cycles per byte - pi_dma_timer->adjust(dma_period); - break; - } - - case 0x10/4: // PI_STATUS_REG - { - if (data & 0x2) - { - //pi_status &= ~8; // Clear INTERRUPT ?? Does this bit exist ?? - pi_status = 0; // Reset all bits - pi_dma_timer->adjust(attotime::never); // Cancel Pending Transfer - clear_rcp_interrupt(PI_INTERRUPT); - } - break; - } - - case 0x14/4: // PI_BSD_DOM1_LAT - pi_bsd_dom1_lat = data; - break; - - case 0x18/4: // PI_BSD_DOM1_PWD - pi_bsd_dom1_pwd = data; - break; - - case 0x1c/4: // PI_BSD_DOM1_PGS - pi_bsd_dom1_pgs = data; - break; - - case 0x20/4: // PI_BSD_DOM1_RLS - pi_bsd_dom1_rls = data; - break; - - case 0x24/4: // PI_BSD_DOM2_LAT - pi_bsd_dom2_lat = data; - break; - - case 0x28/4: // PI_BSD_DOM2_PWD - pi_bsd_dom2_pwd = data; - break; - - case 0x2c/4: // PI_BSD_DOM2_PGS - pi_bsd_dom2_pgs = data; - break; - - case 0x30/4: // PI_BSD_DOM2_RLS - pi_bsd_dom2_rls = data; - break; - - default: - logerror("pi_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - break; - } -} - -// RDRAM Interface - -uint32_t n64_periphs::ri_reg_r(offs_t offset, uint32_t mem_mask) -{ - if(offset == 0x0C/4) // RI_SELECT - { - /* This is to 'simulate' the time that RDRAM initialization - would take if the RI registers were not set to skip the RDRAM - testing during device reset. Proper simulation would require - emulating the RDRAM modules and bus stalls for the mips cpu. - The cycle amount chosen represents 1/2 second, which is not - necessarily the time for RDRAM initialization, but rather the - time recommended for letting the SI devices settle after startup. - This allows the initialization routines for the SI to see that a - proper amount of time has passed since system startup. */ - m_vr4300->adjust_icount(-93750000/2); - } - - if(offset > 0x1c/4) - { - logerror("ri_reg_r: %08X, %08X at %08X\n", offset, mem_mask, m_vr4300->pc()); - return 0; - } - return ri_regs[offset]; -} - -void n64_periphs::ri_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if(offset > 0x1c/4) - { - logerror("ri_reg_w: %08X, %08X, %08X at %08X\n", data, offset, mem_mask, m_vr4300->pc()); - return; - } - COMBINE_DATA(&ri_regs[offset]); -} - -// Serial Interface -uint8_t n64_periphs::calc_mempak_crc(uint8_t *buffer, int length) -{ - uint32_t crc = 0; - uint32_t temp2 = 0; - - for(int i = 0; i <= length; i++) - { - for(int j = 7; j >= 0; j--) - { - if ((crc & 0x80) != 0) - { - temp2 = 0x85; - } - else - { - temp2 = 0; - } - - crc <<= 1; - - if (i == length) - { - crc &= 0xff; - } - else - { - if ((buffer[i] & (1 << j)) != 0) - { - crc |= 0x1; - } - } - - crc ^= temp2; - } - } - - return crc; -} - -static inline uint8_t convert_to_bcd(int val) -{ - return ((val / 10) << 4) | (val % 10); -} - -int n64_periphs::pif_channel_handle_command(int channel, int slength, uint8_t *sdata, int rlength, uint8_t *rdata) -{ - uint8_t command = sdata[0]; - - switch (command) - { - case 0x00: // Read status - case 0xff: // Reset - { - switch (channel) - { - case 0: - case 1: - case 2: - case 3: - { - // Read status - switch ((machine().root_device().ioport("input")->read() >> (2 * channel)) & 3) - { - case 0: //NONE (unconnected) - case 3: //Invalid - return 1; - - case 1: //JOYPAD - rdata[0] = 0x05; - rdata[1] = 0x00; - rdata[2] = 0x01; - return 0; - - case 2: //MOUSE - rdata[0] = 0x02; - rdata[1] = 0x00; - rdata[2] = 0x01; - return 0; - } - break; - } - case 4: - { - //printf("Read EEPROM status, type: %02x\n", (machine().root_device().ioport("input")->read() >> 8) & 0xC0); - // Read EEPROM status - rdata[0] = 0x00; - rdata[1] = (machine().root_device().ioport("input")->read() >> 8) & 0xC0; - rdata[2] = 0x00; - - return 0; - } - case 5: - { - osd_printf_debug("EEPROM2? read status\n"); - return 1; - } - } - - break; - } - - case 0x01: // Read button values - { - uint16_t buttons = 0; - int x = 0, y = 0; - static const char *const portnames[] = { "P1", "P1_ANALOG_X", "P1_ANALOG_Y", "P1_MOUSE_X", "P1_MOUSE_Y", - "P2", "P2_ANALOG_X", "P2_ANALOG_Y", "P2_MOUSE_X", "P2_MOUSE_Y", - "P3", "P3_ANALOG_X", "P3_ANALOG_Y", "P3_MOUSE_X", "P3_MOUSE_Y", - "P4", "P4_ANALOG_X", "P4_ANALOG_Y", "P4_MOUSE_X", "P4_MOUSE_Y" }; - - if (slength != 1 || rlength != 4) - { - fatalerror("handle_pif: read button values (bytes to send %d, bytes to receive %d)\n", slength, rlength); - } - - switch (channel) - { - case 0: // P1 Inputs - case 1: // P2 Inputs - case 2: // P3 Inputs - case 3: // P4 Inputs - { - switch ((machine().root_device().ioport("input")->read() >> (2 * channel)) & 3) - { - case 0: //NONE - case 3: //Invalid - return 1; - - case 1: //JOYPAD - buttons = machine().root_device().ioport(portnames[(channel*5) + 0])->read(); - x = machine().root_device().ioport(portnames[(channel*5) + 1])->read() - 128; - y = machine().root_device().ioport(portnames[(channel*5) + 2])->read() - 128; - - rdata[0] = (buttons >> 8) & 0xff; - rdata[1] = (buttons >> 0) & 0xff; - rdata[2] = (uint8_t)(x); - rdata[3] = (uint8_t)(y); - return 0; - - case 2: //MOUSE - buttons = machine().root_device().ioport(portnames[(channel*5) + 0])->read(); - x = (int16_t)machine().root_device().ioport(portnames[(channel*5) + 1 + 2])->read();// - 128; - y = (int16_t)machine().root_device().ioport(portnames[(channel*5) + 2 + 2])->read();// - 128; - - int mouse_dx = 0; - int mouse_dy = 0; - - if (x != mouse_x2[channel]) - { - mouse_dx = x - mouse_x2[channel]; - - if (mouse_dx > 0x40) - mouse_dx = (0x80) - (mouse_dx - ((mouse_dx / 0x80) * 0x80)); - else if (mouse_dx < -0x40) - mouse_dx = -(0x80) - (mouse_dx - ((mouse_dx / 0x80) * 0x80)); - - mouse_x2[channel] = x; - } - - if (y != mouse_y2[channel]) - { - mouse_dy = y - mouse_y2[channel]; - - if (mouse_dy > 0x40) - mouse_dy = (0x80) - (mouse_dy - ((mouse_dy / 0x80) * 0x80)); - else if (mouse_dy < -0x40) - mouse_dy = -(0x80) - (mouse_dy - ((mouse_dy / 0x80) * 0x80)); - - mouse_y2[channel] = y; - } - - if (mouse_dx) - { - if(mouse_dx < 0) - mouse_dx++; - else - mouse_dx--; - } - - if (mouse_dy) - { - if(mouse_dy < 0) - mouse_dy++; - else - mouse_dy--; - } - - rdata[0] = (buttons >> 8) & 0xff; - rdata[1] = (buttons >> 0) & 0xff; - rdata[2] = (uint8_t)(mouse_dx); - rdata[3] = (uint8_t)(mouse_dy); - return 0; - - } - } - } - - break; - } - - case 0x02: // Read mempak - { - uint32_t address; - - address = (sdata[1] << 8) | (sdata[2]); - address &= ~0x1f; - - if(address == 0x8000) - { - for(int i = 0; i < rlength-1; i++) - { - rdata[i] = 0x00; - } - - rdata[rlength-1] = calc_mempak_crc(rdata, rlength-1); - return 0; - } - else if(address < 0x7fe0) - { - for(int i = 0; i < rlength-1; i++) - { - rdata[i] = m_save_data.mempak[channel & 1][address+i]; - } - - rdata[rlength-1] = calc_mempak_crc(rdata, rlength-1); - return 0; - } - - return 1; - } - case 0x03: // Write mempak - { - uint32_t address = (sdata[1] << 8) | (sdata[2]); - address &= ~0x1f; - - if (address < 0x8000) - { - for(int i = 3; i < slength; i++) - { - m_save_data.mempak[channel & 1][address++] = sdata[i]; - } - } - - rdata[0] = calc_mempak_crc(&sdata[3], slength-3); - - return 0; - } - - case 0x04: // Read from EEPROM - { - //printf("Read from EEPROM, channel %d: slength %d, rlength %d, sdata[1] %02x\n", channel, slength, rlength, sdata[1]); - if (channel != 4) - { - return 1; - } - - if (slength != 2 || rlength != 8) - { - fatalerror("handle_pif: write EEPROM (bytes to send %d, bytes to receive %d)\n", slength, rlength); - } - - uint16_t block_offset = sdata[1] * 8; - - for(int i=0; i < 8; i++) - { - rdata[i] = m_save_data.eeprom[block_offset+i]; - } - - return 0; - } - - case 0x05: // Write to EEPROM - { - if (channel != 4) - { - return 1; - } - - if (slength != 10 || rlength != 1) - { - fatalerror("handle_pif: write EEPROM (bytes to send %d, bytes to receive %d)\n", slength, rlength); - } - - uint16_t block_offset = sdata[1] * 8; - - for(int i = 0; i < 8; i++) - { - m_save_data.eeprom[block_offset+i] = sdata[2+i]; - } - - return 0; - } - - case 0x06: // Read RTC Status - { - rdata[0] = 0x00; - rdata[1] = 0x10; - rdata[2] = 0x00; - return 0; - } - - case 0x07: // Read RTC Block - { - switch(sdata[1]) - { - case 0: - rdata[0] = 0x00; - rdata[1] = 0x02; - rdata[8] = 0x00; - return 0; - - case 1: - return 0; - - case 2: - system_time systime; - machine().base_datetime(systime); - rdata[0] = convert_to_bcd(systime.local_time.second); // Seconds - rdata[1] = convert_to_bcd(systime.local_time.minute); // Minutes - rdata[2] = 0x80 | convert_to_bcd(systime.local_time.hour); // Hours - rdata[3] = convert_to_bcd(systime.local_time.mday); // Day of month - rdata[4] = convert_to_bcd(systime.local_time.weekday); // Day of week - rdata[5] = convert_to_bcd(systime.local_time.month + 1); // Month - rdata[6] = convert_to_bcd(systime.local_time.year % 100); // Year - rdata[7] = convert_to_bcd(systime.local_time.year / 100); // Century - rdata[8] = 0x00; - return 0; - } - return 1; - } - - default: - { - osd_printf_debug("handle_pif: unknown/unimplemented command %02X\n", command); - return 1; - } - } - - return 0; -} - -void n64_periphs::handle_pif() -{ - uint8_t *ram = (uint8_t*)pif_ram; - if(pif_cmd[0x3f] == 0x1) // only handle the command if the last byte is 1 - { - int channel = 0; - int end = 0; - int cmd_ptr = 0; - - while(cmd_ptr < 0x3f && !end) - { - int8_t bytes_to_send = (int8_t)pif_cmd[cmd_ptr++]; - - if (bytes_to_send == -2) - { - end = 1; - } - else if (bytes_to_send < 0) - { - // do nothing - } - else - { - if(bytes_to_send > 0 && (bytes_to_send & 0xc0) == 0) - { - uint8_t recv_buffer[0x40]; - uint8_t send_buffer[0x40]; - - int8_t bytes_to_recv = pif_cmd[cmd_ptr++]; - - if (bytes_to_recv == -2) - { - break; // Hack, shouldn't need to do this - } - - for(int j = 0; j < bytes_to_send; j++) - { - send_buffer[j] = pif_cmd[cmd_ptr++]; - } - - int res = pif_channel_handle_command(channel, bytes_to_send, send_buffer, bytes_to_recv, recv_buffer); - - if (res == 0) - { - if (cmd_ptr + bytes_to_recv > 0x3f) - { - fatalerror("cmd_ptr overflow\n"); - } - for(int j = 0; j < bytes_to_recv; j++) - { - pif_ram[cmd_ptr++] = recv_buffer[j]; - } - } - else if (res == 1) - { - int offset = 0;//bytes_to_send; - pif_ram[cmd_ptr - offset - 2] |= 0x80; - } - } - - channel++; - } - } - - ram[0x3f ^ BYTE4_XOR_BE(0)] &= ~0x80; - } - - /*printf("After:\n"); fflush(stdout); - for(int i = 0; i < 0x40; i++) - { - printf("%02x ", pif_ram[i]); fflush(stdout); - if((i & 0xf) == 0xf) - { - printf("\n"); fflush(stdout); - } - }*/ -} - -TIMER_CALLBACK_MEMBER(n64_periphs::si_dma_callback) -{ - si_dma_tick(); -} - -void n64_periphs::si_dma_tick() -{ - si_dma_timer->adjust(attotime::never); - pif_dma(si_dma_dir); - si_status_val = 0; - si_status_val |= 0x1000; - signal_rcp_interrupt(SI_INTERRUPT); -} - -void n64_periphs::pif_dma(int direction) -{ - if (!DWORD_ALIGNED(si_dram_addr)) - { - fatalerror("pif_dma: si_dram_addr unaligned: %08X\n", si_dram_addr); - } - - if (direction) // RDRAM -> PIF RAM - { - uint32_t *src = m_rdram + ((si_dram_addr & 0x1fffffff) / 4); - - for(int i = 0; i < 64; i+=4) - { - uint32_t d = *src++; - pif_ram[i+0] = (d >> 24) & 0xff; - pif_ram[i+1] = (d >> 16) & 0xff; - pif_ram[i+2] = (d >> 8) & 0xff; - pif_ram[i+3] = (d >> 0) & 0xff; - } - - memcpy(pif_cmd, pif_ram, 0x40); - } - else // PIF RAM -> RDRAM - { - handle_pif(); - - uint32_t *dst = m_rdram + ((si_dram_addr & 0x1fffffff) / 4); - - for(int i = 0; i < 64; i+=4) - { - uint32_t d = 0; - d |= pif_ram[i+0] << 24; - d |= pif_ram[i+1] << 16; - d |= pif_ram[i+2] << 8; - d |= pif_ram[i+3] << 0; - - *dst++ = d; - } - } -} - -uint32_t n64_periphs::si_reg_r(offs_t offset) -{ - uint32_t ret = 0; - switch (offset) - { - //case 0x00/4: // SI_DRAM_ADDR_REG - //return si_dram_addr; - - case 0x18/4: // SI_STATUS_REG - ret = si_status_val; - } - - return ret; -} - -void n64_periphs::si_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - switch (offset) - { - case 0x00/4: // SI_DRAM_ADDR_REG - si_dram_addr = data; - break; - - case 0x04/4: // SI_PIF_ADDR_RD64B_REG - // PIF RAM -> RDRAM - if(si_status_val & 1) - { - si_status_val |= 8; //DMA Error, overlapping request - return; // SI Busy, ignore request - } - si_pif_addr = data; - si_pif_addr_rd64b = data; - si_dma_dir = 0; - si_status_val |= 1; - si_dma_timer->adjust(attotime::from_hz(50000)); - break; - - case 0x10/4: // SI_PIF_ADDR_WR64B_REG - // RDRAM -> PIF RAM - if(si_status_val & 1) - { - si_status_val |= 8; //DMA Error, overlapping request - return; // SI Busy, ignore request - } - si_pif_addr = data; - si_pif_addr_wr64b = data; - si_dma_dir = 1; - si_dma_timer->adjust(attotime::from_hz(50000)); - break; - - case 0x18/4: // SI_STATUS_REG - si_status_val = 0; - si_dma_timer->adjust(attotime::never); - clear_rcp_interrupt(SI_INTERRUPT); - break; - - default: - logerror("si_reg_w: %08X, %08X, %08X\n", data, offset, mem_mask); - break; - } -} - -void n64_periphs::dd_set_zone_and_track_offset() -{ - uint16_t head = (dd_track_reg & 0x1000) >> 9; // Head * 8 - uint16_t track = dd_track_reg & 0xFFF; - uint16_t tr_off = 0; - - if(track >= 0x425) - { - dd_zone = 7 + head; - tr_off = track - 0x425; - } - else if (track >= 0x390) - { - dd_zone = 6 + head; - tr_off = track - 0x390; - } - else if (track >= 0x2FB) - { - dd_zone = 5 + head; - tr_off = track - 0x2FB; - } - else if (track >= 0x266) - { - dd_zone = 4 + head; - tr_off = track - 0x266; - } - else if (track >= 0x1D1) - { - dd_zone = 3 + head; - tr_off = track - 0x1D1; - } - else if (track >= 0x13C) - { - dd_zone = 2 + head; - tr_off = track - 0x13C; - } - else if (track >= 0x9E) - { - dd_zone = 1 + head; - tr_off = track - 0x9E; - } - else - { - dd_zone = 0 + head; - tr_off = track; - } - - dd_track_offset = ddStartOffset[dd_zone] + tr_off*ddZoneSecSize[dd_zone]*SECTORS_PER_BLOCK*BLOCKS_PER_TRACK; - //logerror("Zone %d, Head %d, Offset %x\n", dd_zone, head/8, dd_track_offset); -} - -void n64_periphs::dd_update_bm() -{ - if(!(dd_buf_status_reg & DD_BMST_RUNNING)) - return; - if(dd_write) // dd write, BM Mode 0 - { - if(dd_current_reg == 0) - { - dd_current_reg += 1; - dd_status_reg |= DD_ASIC_STATUS_DREQ; - } - else if(dd_current_reg < SECTORS_PER_BLOCK) - { - dd_write_sector(); - dd_current_reg += 1; - dd_status_reg |= DD_ASIC_STATUS_DREQ; - } - else if(dd_current_reg < SECTORS_PER_BLOCK + 1) - { - if(dd_buf_status_reg & DD_BMST_BLOCKS) - { - dd_write_sector(); - dd_current_reg += 1; - //logerror("DD Write, Start Next Block\n"); - dd_start_block = 1 - dd_start_block; - dd_current_reg = 1; - dd_buf_status_reg &= ~DD_BMST_BLOCKS; - dd_status_reg |= DD_ASIC_STATUS_DREQ; - } - else - { - dd_write_sector(); - dd_current_reg += 1; - dd_buf_status_reg &= ~DD_BMST_RUNNING; - } - } - else - { - logerror("DD Write, Sector Overrun\n"); - } - //logerror("DD Write, Sending Interrupt\n"); - dd_status_reg |= DD_ASIC_STATUS_BM_INT; - m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); - return; - } - else // dd read, BM Mode 1 - { - if(((dd_track_reg & 0x1FFF) == 6) && (dd_start_block == 0) && ((machine().root_device().ioport("input")->read() & 0x0100) == 0x0000)) - { - //only fail read LBA 12 if retail disk drive - dd_status_reg &= ~DD_ASIC_STATUS_DREQ; - dd_buf_status_reg |= DD_BMST_MICRO_STATUS; - } - else if(dd_current_reg < SECTORS_PER_BLOCK) - { - dd_read_sector(); - dd_current_reg += 1; - dd_status_reg |= DD_ASIC_STATUS_DREQ; - } - else if(dd_current_reg < SECTORS_PER_BLOCK + 4) - { - dd_read_C2(); - dd_current_reg += 1; - if(dd_current_reg == SECTORS_PER_BLOCK + 4) - dd_status_reg |= DD_ASIC_STATUS_C2_XFER; - } - else if(dd_current_reg == SECTORS_PER_BLOCK + 4) // Gap Sector - { - if(dd_buf_status_reg & DD_BMST_BLOCKS) - { - //logerror("DD Read, Start Next Block\n"); - dd_start_block = 1 - dd_start_block; - dd_current_reg = 0; - dd_buf_status_reg &= ~DD_BMST_BLOCKS; - } - else - { - dd_buf_status_reg &= ~DD_BMST_RUNNING; - } - } - else - { - logerror("DD Read, Sector Overrun\n"); - } - //logerror("DD Read, Sending Interrupt\n"); - dd_status_reg |= DD_ASIC_STATUS_BM_INT; - m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); - return; - } -} - -void n64_periphs::dd_write_sector() -{ - uint8_t* sector; - - sector = (uint8_t*)machine().root_device().memregion("disk")->base(); - sector += dd_track_offset; - sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; - sector += (dd_current_reg - 1) * ddZoneSecSize[dd_zone]; - - //logerror("Write Block %d, Sector %d\n", dd_start_block, dd_current_reg - 1); - - for(int i = 0; i < ddZoneSecSize[dd_zone]/4; i++) - { - sector[i*4 + 0] = (dd_sector_data[i] >> 24) & 0xFF; - sector[i*4 + 1] = (dd_sector_data[i] >> 16) & 0xFF; - sector[i*4 + 2] = (dd_sector_data[i] >> 8) & 0xFF; - sector[i*4 + 3] = (dd_sector_data[i] >> 0) & 0xFF; - } - return; -} - -void n64_periphs::dd_read_sector() -{ - uint8_t* sector; - - sector = (uint8_t*)machine().root_device().memregion("disk")->base(); - sector += dd_track_offset; - sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone]; - sector += (dd_current_reg) * (dd_sector_size + 1); - - //logerror("Read Block %d, Sector %d\n", dd_start_block, dd_current_reg); - - for(int i = 0; i < (dd_sector_size + 1)/4; i++) - { - dd_sector_data[i] = sector[(i*4 + 0)] << 24 | sector[(i*4 + 1)] << 16 | - sector[(i*4 + 2)] << 8 | sector[(i*4 + 3)]; - } - return; -} - -void n64_periphs::dd_read_C2() -{ - for(int i = 0; i < ddZoneSecSize[dd_zone]/4; i++) - dd_buffer[(dd_current_reg - SECTORS_PER_BLOCK)*0x40 + i] = 0; - //logerror("Read C2, Sector %d", dd_current_reg); - return; -} - -uint32_t n64_periphs::dd_reg_r(offs_t offset) -{ - if(offset < 0x400/4) - { - return dd_buffer[offset]; - } - - if(offset < 0x500/4) - { - return dd_sector_data[(offset - 0x400/4)]; - } - - if((offset < 0x5C0/4) && (0x580/4 <= offset)) - { - return dd_ram_seq_data[(offset - 0x580/4)]; - } - - offset -= 0x500/4; - - uint32_t ret = 0; - switch(offset) - { - case 0x00/4: // DD Data - ret = dd_data_reg; - break; - - case 0x04/4: // ?? - break; - - case 0x08/4: // DD Status - if(disk_present) - dd_status_reg |= DD_ASIC_STATUS_DISK; - else - dd_status_reg &= ~DD_ASIC_STATUS_DISK; - ret = dd_status_reg; - // For Read, Gap Sector - if((dd_status_reg & DD_ASIC_STATUS_BM_INT) && (SECTORS_PER_BLOCK < dd_current_reg)) - { - dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; - //logerror("DD Read Gap, Clearing INT\n"); - m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); - dd_update_bm(); - } - break; - - case 0x0c/4: // Current Track - ret = dd_track_reg; - break; - - case 0x10/4: // Transfer Buffer Status - ret = dd_buf_status_reg; - break; - - case 0x14/4: // Sector Error - ret = dd_sector_err_reg; - break; - - case 0x18/4: // Sequence Status - ret = dd_seq_status_reg; - break; - - case 0x1c/4: // Sequence Control - ret = dd_seq_ctrl_reg; - break; - case 0x40/4: // ASIC ID - if ((machine().root_device().ioport("input")->read() & 0x0100) == 0x0000) - ret = 0x00030000; // Japan Retail Drive - else - ret = 0x00040000; // Development Drive - break; - } - - //logerror("dd_reg_r: %08x (%08x)\n", offset << 2, ret); - return ret; -} - -void n64_periphs::dd_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - //logerror("dd_reg_w: %08X, %08X, %08X\n", data, offset << 2, mem_mask); - - if(offset < 0x400/4) - { - COMBINE_DATA(&dd_buffer[offset]); - return; - } - - if(offset < 0x500/4) - { - COMBINE_DATA(&dd_sector_data[(offset - 0x400/4)]); - return; - } - - if((offset < 0x5C0/4) && (0x580/4 <= offset)) - { - COMBINE_DATA(&dd_ram_seq_data[(offset - 0x580/4)]); - return; - } - - offset -= 0x500/4; - - switch(offset) - { - case 0x00/4: // DD Data - dd_data_reg = data; - break; - - case 0x08/4: // DD Command - switch((data >> 16) & 0xff) - { - case 0x01: // Seek Read - dd_track_reg = dd_data_reg >> 16; - //logerror("dd command: Seek Read %d\n", dd_track_reg); - dd_set_zone_and_track_offset(); - dd_track_reg |= DD_TRACK_INDEX_LOCK; - dd_write = false; - break; - case 0x02: // Seek Write - dd_track_reg = dd_data_reg >> 16; - //logerror("dd command: Seek Write %d\n", dd_track_reg); - dd_set_zone_and_track_offset(); - dd_track_reg |= DD_TRACK_INDEX_LOCK; - dd_write = true; - break; - case 0x03: // Re-Zero / Recalibrate - //logerror("dd command: Re-Zero\n"); - break; - case 0x04: // Engage Brake - //logerror("dd command: Engage Brake\n"); - break; - case 0x05: // Start Motor - //logerror("dd command: Start Motor\n"); - break; - case 0x06: // Set Standby Time - //logerror("dd command: Set Standby Time\n"); - break; - case 0x07: // Set Sleep Time - //logerror("dd command: Set Sleep Time\n"); - break; - case 0x08: // Clear Disk Change Flag - //logerror("dd command: Clear Disk Change Flag\n"); - break; - case 0x09: // Clear Reset Flag - //logerror("dd command: Clear Reset Flag\n"); - break; - case 0x0B: // Select Disk Type - //logerror("dd command: Select Disk Type\n"); - break; - case 0x0C: // ASIC Command Inquiry - //logerror("dd command: ASIC Command Inquiry\n"); - break; - case 0x0D: // Standby Mode (?) - //logerror("dd command: Standby Mode(?)\n"); - break; - case 0x0E: // (Track Seek) Index Lock Retry - //logerror("dd command: Index Lock Retry\n"); - break; - case 0x0F: // Set RTC Year / Month - //logerror("dd command: Set RTC Year / Month\n"); - break; - case 0x10: // Set RTC Day / Hour - //logerror("dd command: Set RTC Day / Hour\n"); - break; - case 0x11: // Set RTC Minute / Second - //logerror("dd command: Set RTC Minute / Second\n"); - break; - case 0x12: // Read RTC Month / Year - { - //logerror("dd command: Read RTC Month / Year\n"); - - system_time systime; - machine().base_datetime(systime); - - dd_data_reg = (convert_to_bcd(systime.local_time.year % 100) << 24) | (convert_to_bcd(systime.local_time.month + 1) << 16); - break; - } - - case 0x13: // Read RTC Hour / Day - { - //logerror("dd command: Read RTC Hour / Day\n"); - - system_time systime; - machine().base_datetime(systime); - - dd_data_reg = (convert_to_bcd(systime.local_time.mday) << 24) | (convert_to_bcd(systime.local_time.hour) << 16); - break; - } - - case 0x14: // Read RTC Minute / Second - { - //logerror("dd command: Read RTC Minute / Second\n"); - - system_time systime; - machine().base_datetime(systime); - - dd_data_reg = (convert_to_bcd(systime.local_time.minute) << 24) | (convert_to_bcd(systime.local_time.second) << 16); - break; - } - case 0x15: // Set LED On/Off Time - { - //logerror("dd command: Set LED On/Off Time\n"); - break; - } - case 0x1B: // Disk Inquiry - { - //logerror("dd command: Disk Inquiry\n"); - dd_data_reg = 0x00000000; - break; - } - } - //logerror("Sending MECHA Int\n"); - dd_status_reg |= DD_ASIC_STATUS_MECHA_INT; - m_vr4300->set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE); - break; - - case 0x10/4: // BM Status - //logerror("dd BM Status write\n"); - dd_start_sector = (data >> 16) & 0xFF; - if(dd_start_sector == 0x00) - { - dd_start_block = 0; - dd_current_reg = 0; - } - else if (dd_start_sector == 0x5A) - { - dd_start_block = 1; - dd_current_reg = 0; - } - else - { - logerror("dd: start sector not aligned\n"); - } - if(data & DD_BM_XFERBLOCKS) - dd_buf_status_reg |= DD_BMST_BLOCKS; - if(data & DD_BM_MECHA_INT_RESET) - dd_status_reg &= ~DD_ASIC_STATUS_MECHA_INT; - if(data & DD_BM_RESET) - dd_bm_reset_held = true; - if(!(data & DD_BM_RESET) && dd_bm_reset_held) - { - dd_bm_reset_held = false; - dd_status_reg &= ~DD_ASIC_STATUS_BM_INT; - dd_status_reg &= ~DD_ASIC_STATUS_BM_ERROR; - dd_status_reg &= ~DD_ASIC_STATUS_DREQ; - dd_status_reg &= ~DD_ASIC_STATUS_C2_XFER; - dd_buf_status_reg = 0; - dd_current_reg = 0; - dd_start_block = 0; - //logerror("dd: BM RESET\n"); - } - if(!(dd_status_reg & DD_ASIC_STATUS_BM_INT) && !(dd_status_reg & DD_ASIC_STATUS_MECHA_INT)) - { - //logerror("DD Status, Clearing INT\n"); - m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE); - } - if(data & DD_BM_START) - { - if(dd_write && (data & DD_BM_MODE)) - popmessage("Attempt to write disk with BM Mode 1\n"); - if(!dd_write && !(data & DD_BM_MODE)) - popmessage("Attempt to read disk with BM Mode 0\n"); - dd_buf_status_reg |= DD_BMST_RUNNING; - //logerror("dd: Start BM\n"); - dd_update_bm(); - } - - break; - - case 0x1c/4: // Sequence Control - dd_seq_ctrl_reg = data; - break; - case 0x28/4: // Host Sector Byte - dd_sector_size = (data >> 16) & 0xFF; - if((dd_sector_size + 1) != ddZoneSecSize[dd_zone]) - popmessage("Sector size %d set different than expected %d\n", dd_sector_size + 1, ddZoneSecSize[dd_zone]); - break; - case 0x30/4: // Sector Byte - dd_sectors_per_block = (data >> 24) & 0xFF; - if(dd_sectors_per_block != SECTORS_PER_BLOCK + 4) - popmessage("Sectors per block %d set different than expected %d\n", dd_sectors_per_block, SECTORS_PER_BLOCK + 4); - } -} - -uint32_t n64_periphs::pif_ram_r(offs_t offset, uint32_t mem_mask) -{ - if(!machine().side_effects_disabled()) - { - if( offset == ( 0x24 / 4 ) ) - { - cic_status = 0x00000080; - } - if( offset == ( 0x3C / 4 ) ) - { - return cic_status; - } - } - return ( ( pif_ram[offset*4+0] << 24 ) | ( pif_ram[offset*4+1] << 16 ) | ( pif_ram[offset*4+2] << 8 ) | ( pif_ram[offset*4+3] << 0 ) ) & mem_mask; -} - -void n64_periphs::pif_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask) -{ - if( ACCESSING_BITS_24_31 ) - { - pif_ram[offset*4+0] = ( data >> 24 ) & 0x000000ff; - } - if( ACCESSING_BITS_16_23 ) - { - pif_ram[offset*4+1] = ( data >> 16 ) & 0x000000ff; - } - if( ACCESSING_BITS_8_15 ) - { - pif_ram[offset*4+2] = ( data >> 8 ) & 0x000000ff; - } - if( ACCESSING_BITS_0_7 ) - { - pif_ram[offset*4+3] = ( data >> 0 ) & 0x000000ff; - } - - signal_rcp_interrupt(SI_INTERRUPT); -} - -void n64_state::n64_machine_stop() -{ - if (m_rcp_periphs->m_nvram_image == nullptr) - return; - - device_image_interface *image = dynamic_cast<device_image_interface *>(m_rcp_periphs->m_nvram_image); - - uint8_t data[0x30800]; - if (m_sram == nullptr) - { - memset(data, 0, 0x20000); - } - else - { - memcpy(data, m_sram, 0x20000); - } - memcpy(data + 0x20000, m_rcp_periphs->m_save_data.eeprom, 0x800); - memcpy(data + 0x20800, m_rcp_periphs->m_save_data.mempak[0], 0x8000); - memcpy(data + 0x28800, m_rcp_periphs->m_save_data.mempak[1], 0x8000); - image->battery_save(data, 0x30800); -} - -void n64_state::machine_start() -{ - m_vr4300->mips3drc_set_options(MIPS3DRC_COMPATIBLE_OPTIONS); - - /* configure fast RAM regions */ - //m_vr4300->add_fastram(0x00000000, 0x007fffff, false, m_rdram); - - /* add a hook for battery save */ - machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&n64_state::n64_machine_stop,this)); -} - -void n64_state::machine_reset() -{ - m_rsp->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); -} |