mirror of
https://github.com/holub/mame
synced 2025-10-06 17:08:28 +03:00
Merge pull request #151 from Happy-yappH/master
(MESS)Adding support for the N64DD [Happy]
This commit is contained in:
commit
09ee79273f
@ -120,6 +120,8 @@ public:
|
||||
UINT32 cart_length;
|
||||
|
||||
bool dd_present;
|
||||
bool disk_present;
|
||||
bool cart_present;
|
||||
|
||||
void poll_reset_button(bool button);
|
||||
|
||||
@ -186,9 +188,14 @@ private:
|
||||
UINT32 sp_semaphore;
|
||||
|
||||
// Disk Drive (DD) registers and functions
|
||||
void dd_set_zone_and_track_offset();
|
||||
void dd_update_bm();
|
||||
void dd_write_sector();
|
||||
void dd_read_sector();
|
||||
void dd_read_C2();
|
||||
UINT32 dd_buffer[256];
|
||||
UINT32 dd_sector_data[32]; // ?
|
||||
UINT32 dd_ram_seq_data[32]; // ?
|
||||
UINT32 dd_sector_data[64];
|
||||
UINT32 dd_ram_seq_data[16];
|
||||
UINT32 dd_data_reg;
|
||||
UINT32 dd_status_reg;
|
||||
UINT32 dd_track_reg;
|
||||
@ -196,7 +203,18 @@ private:
|
||||
UINT32 dd_sector_err_reg;
|
||||
UINT32 dd_seq_status_reg;
|
||||
UINT32 dd_seq_ctrl_reg;
|
||||
UINT32 dd_sector_reg;
|
||||
UINT32 dd_reset_reg;
|
||||
UINT32 dd_current_reg;
|
||||
bool dd_bm_reset_held;
|
||||
bool dd_write;
|
||||
UINT8 dd_int;
|
||||
UINT8 dd_start_block;
|
||||
UINT8 dd_start_sector;
|
||||
UINT8 dd_sectors_per_block;
|
||||
UINT8 dd_sector_size;
|
||||
UINT8 dd_zone;
|
||||
UINT32 dd_track_offset;
|
||||
|
||||
// Peripheral Interface (PI) registers and functions
|
||||
void pi_dma();
|
||||
@ -275,6 +293,65 @@ extern const device_type N64PERIPH;
|
||||
#define DP_STATUS_FREEZE 0x02
|
||||
#define DP_STATUS_FLUSH 0x04
|
||||
|
||||
#define DD_ASIC_STATUS_DISK_CHANGE 0x00010000
|
||||
#define DD_ASIC_STATUS_MECHA_ERR 0x00020000
|
||||
#define DD_ASIC_STATUS_WRPROTECT_ERR 0x00040000
|
||||
#define DD_ASIC_STATUS_HEAD_RETRACT 0x00080000
|
||||
#define DD_ASIC_STATUS_MOTOR_OFF 0x00100000
|
||||
#define DD_ASIC_STATUS_RESET 0x00400000
|
||||
#define DD_ASIC_STATUS_BUSY 0x00800000
|
||||
#define DD_ASIC_STATUS_DISK 0x01000000
|
||||
#define DD_ASIC_STATUS_MECHA_INT 0x02000000
|
||||
#define DD_ASIC_STATUS_BM_INT 0x04000000
|
||||
#define DD_ASIC_STATUS_BM_ERROR 0x08000000
|
||||
#define DD_ASIC_STATUS_C2_XFER 0x10000000
|
||||
#define DD_ASIC_STATUS_DREQ 0x40000000
|
||||
|
||||
#define DD_TRACK_INDEX_LOCK 0x60000000
|
||||
|
||||
#define DD_BM_MECHA_INT_RESET 0x01000000
|
||||
#define DD_BM_XFERBLOCKS 0x02000000
|
||||
#define DD_BM_DISABLE_C1 0x04000000
|
||||
#define DD_BM_DISABLE_OR_CHK 0x08000000
|
||||
#define DD_BM_RESET 0x10000000
|
||||
#define DD_BM_INT_MASK 0x20000000
|
||||
#define DD_BM_MODE 0x40000000
|
||||
#define DD_BM_START 0x80000000
|
||||
|
||||
#define DD_BMST_RUNNING 0x80000000
|
||||
#define DD_BMST_ERROR 0x04000000
|
||||
#define DD_BMST_MICRO_STATUS 0x02000000
|
||||
#define DD_BMST_BLOCKS 0x01000000
|
||||
#define DD_BMST_C1_CORRECT 0x00800000
|
||||
#define DD_BMST_C1_DOUBLE 0x00400000
|
||||
#define DD_BMST_C1_SINGLE 0x00200000
|
||||
#define DD_BMST_C1_ERROR 0x00010000
|
||||
|
||||
#define DD_ASIC_ERR_AM_FAIL 0x80000000
|
||||
#define DD_ASIC_ERR_MICRO_FAIL 0x40000000
|
||||
#define DD_ASIC_ERR_SPINDLE_FAIL 0x20000000
|
||||
#define DD_ASIC_ERR_OVER_RUN 0x10000000
|
||||
#define DD_ASIC_ERR_OFFTRACK 0x08000000
|
||||
#define DD_ASIC_ERR_NO_DISK 0x04000000
|
||||
#define DD_ASIC_ERR_CLOCK_UNLOCK 0x02000000
|
||||
#define DD_ASIC_ERR_SELF_STOP 0x01000000
|
||||
|
||||
#define DD_SEQ_MICRO_INT_MASK 0x80000000
|
||||
#define DD_SEQ_MICRO_PC_ENABLE 0x40000000
|
||||
|
||||
#define SECTORS_PER_BLOCK 85
|
||||
#define BLOCKS_PER_TRACK 2
|
||||
|
||||
const unsigned int ddZoneSecSize[16] = {232,216,208,192,176,160,144,128,
|
||||
216,208,192,176,160,144,128,112};
|
||||
const unsigned int ddZoneTrackSize[16] = {158,158,149,149,149,149,149,114,
|
||||
158,158,149,149,149,149,149,114};
|
||||
const unsigned int ddStartOffset[16] =
|
||||
{0x0,0x5F15E0,0xB79D00,0x10801A0,0x1523720,0x1963D80,0x1D414C0,0x20BBCE0,
|
||||
0x23196E0,0x28A1E00,0x2DF5DC0,0x3299340,0x36D99A0,0x3AB70E0,0x3E31900,0x4149200};
|
||||
|
||||
|
||||
|
||||
extern UINT32 *n64_sram;
|
||||
extern UINT32 *rdram;
|
||||
extern UINT32 *rsp_imem;
|
||||
|
@ -23,6 +23,9 @@ n64_periphs::n64_periphs(const machine_config &mconfig, const char *tag, device_
|
||||
: device_t(mconfig, N64PERIPH, "N64 Periphal Chips", tag, owner, clock, "n64_periphs", __FILE__)
|
||||
, device_video_interface(mconfig, *this)
|
||||
, m_nvram_image(NULL)
|
||||
, dd_present(false)
|
||||
, disk_present(false)
|
||||
, cart_present(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -171,7 +174,6 @@ void n64_periphs::device_reset()
|
||||
pi_bsd_dom2_rls = 0;
|
||||
pi_dma_dir = 0;
|
||||
|
||||
dd_int = 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));
|
||||
@ -183,6 +185,10 @@ void n64_periphs::device_reset()
|
||||
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));
|
||||
|
||||
@ -217,7 +223,6 @@ void n64_periphs::device_reset()
|
||||
pif_ram[0x25] = 0x00;
|
||||
pif_ram[0x26] = 0x3f;
|
||||
pif_ram[0x27] = 0x3f;
|
||||
dd_present = false;
|
||||
cic_type=2;
|
||||
mem_map->write_dword(0x00000318, 0x800000);
|
||||
|
||||
@ -227,7 +232,6 @@ void n64_periphs::device_reset()
|
||||
pif_ram[0x25] = 0x08;
|
||||
pif_ram[0x26] = 0xdd;
|
||||
pif_ram[0x27] = 0x3f;
|
||||
dd_present = true;
|
||||
cic_type=0xd;
|
||||
}
|
||||
else if (boot_checksum == U64(0x000000cffb830843) || boot_checksum == U64(0x000000d0027fdf31))
|
||||
@ -1374,13 +1378,26 @@ TIMER_CALLBACK_MEMBER(n64_periphs::pi_dma_callback)
|
||||
|
||||
void n64_periphs::pi_dma_tick()
|
||||
{
|
||||
bool update_bm = false;
|
||||
UINT16 *cart16;
|
||||
UINT16 *dram16 = (UINT16*)rdram;
|
||||
|
||||
UINT32 cart_addr = (pi_cart_addr & 0x0fffffff) >> 1;
|
||||
UINT32 dram_addr = (pi_dram_addr & 0x007fffff) >> 1;
|
||||
|
||||
if((cart_addr & 0x04000000) == 0x04000000)
|
||||
if(pi_cart_addr == 0x05000000 && dd_present)
|
||||
{
|
||||
update_bm = true;
|
||||
cart16 = (UINT16*)dd_buffer;
|
||||
cart_addr = (pi_cart_addr & 0x000003ff) >> 1;
|
||||
}
|
||||
else if(pi_cart_addr == 0x05000400 && dd_present)
|
||||
{
|
||||
update_bm = true;
|
||||
cart16 = (UINT16*)dd_sector_data;
|
||||
cart_addr = (pi_cart_addr & 0x000000ff) >> 1;
|
||||
}
|
||||
else if((cart_addr & 0x04000000) == 0x04000000)
|
||||
{
|
||||
cart16 = (UINT16*)n64_sram;
|
||||
cart_addr = (pi_cart_addr & 0x0001ffff) >> 1;
|
||||
@ -1399,6 +1416,7 @@ void n64_periphs::pi_dma_tick()
|
||||
if(pi_dma_dir == 1)
|
||||
{
|
||||
UINT32 dma_length = pi_wr_len + 1;
|
||||
//logerror("PI Write, %X, %X, %X\n", pi_cart_addr, pi_dram_addr, pi_wr_len);
|
||||
if (dma_length & 7)
|
||||
{
|
||||
dma_length = (dma_length + 7) & ~7;
|
||||
@ -1418,6 +1436,7 @@ void n64_periphs::pi_dma_tick()
|
||||
else
|
||||
{
|
||||
UINT32 dma_length = pi_rd_len + 1;
|
||||
//logerror("PI Read, %X, %X, %X\n", pi_cart_addr, pi_dram_addr, pi_rd_len);
|
||||
if (dma_length & 7)
|
||||
{
|
||||
dma_length = (dma_length + 7) & ~7;
|
||||
@ -1436,7 +1455,10 @@ void n64_periphs::pi_dma_tick()
|
||||
}
|
||||
|
||||
pi_status &= ~1; // Clear DMA_BUSY
|
||||
pi_status |= 8; // Set INTERRUPT
|
||||
//pi_status |= 8; // Set INTERRUPT ?? Does this bit exist ??
|
||||
|
||||
if(update_bm)
|
||||
dd_update_bm();
|
||||
|
||||
signal_rcp_interrupt(PI_INTERRUPT);
|
||||
|
||||
@ -1513,11 +1535,26 @@ WRITE32_MEMBER( n64_periphs::pi_reg_w )
|
||||
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");
|
||||
machine().device("maincpu")->execute().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");
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x08/4: // PI_RD_LEN_REG
|
||||
{
|
||||
//logerror("Start PI Read\n");
|
||||
pi_rd_len = data;
|
||||
pi_dma_dir = 0;
|
||||
pi_status |= 1;
|
||||
@ -1530,6 +1567,7 @@ WRITE32_MEMBER( n64_periphs::pi_reg_w )
|
||||
|
||||
case 0x0c/4: // PI_WR_LEN_REG
|
||||
{
|
||||
//logerror("Start PI Write\n");
|
||||
pi_wr_len = data;
|
||||
pi_dma_dir = 1;
|
||||
pi_status |= 1;
|
||||
@ -1545,7 +1583,9 @@ WRITE32_MEMBER( n64_periphs::pi_reg_w )
|
||||
{
|
||||
if (data & 0x2)
|
||||
{
|
||||
pi_status &= ~8; // Clear INTERRUPT
|
||||
//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;
|
||||
@ -2049,7 +2089,193 @@ WRITE32_MEMBER( n64_periphs::si_reg_w )
|
||||
}
|
||||
}
|
||||
|
||||
#define DD_STATUS_INTR (1 << 25)
|
||||
void n64_periphs::dd_set_zone_and_track_offset()
|
||||
{
|
||||
UINT16 head = (dd_track_reg & 0x1000) >> 9; // Head * 8
|
||||
UINT16 track = dd_track_reg & 0xFFF;
|
||||
UINT16 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;
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
return;
|
||||
}
|
||||
else // dd read, BM Mode 1
|
||||
{
|
||||
if(((dd_track_reg & 0xFFF) == 6) && (dd_start_block == 0))
|
||||
{
|
||||
dd_status_reg &= ~DD_ASIC_STATUS_DREQ;
|
||||
}
|
||||
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;
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void n64_periphs::dd_write_sector()
|
||||
{
|
||||
UINT8* sector;
|
||||
|
||||
sector = (UINT8*)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* sector;
|
||||
|
||||
sector = (UINT8*)machine().root_device().memregion("disk")->base();
|
||||
sector += dd_track_offset;
|
||||
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||
sector += (dd_current_reg) * ddZoneSecSize[dd_zone];
|
||||
|
||||
//logerror("Read Block %d, Sector %d\n", dd_start_block, dd_current_reg);
|
||||
|
||||
for(int i = 0; i < ddZoneSecSize[dd_zone]/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;
|
||||
}
|
||||
|
||||
READ32_MEMBER( n64_periphs::dd_reg_r )
|
||||
{
|
||||
@ -2058,14 +2284,14 @@ READ32_MEMBER( n64_periphs::dd_reg_r )
|
||||
return dd_buffer[offset];
|
||||
}
|
||||
|
||||
if(offset < 0x480/4)
|
||||
{
|
||||
return dd_sector_data[(offset - 0x400/4) / 4];
|
||||
}
|
||||
|
||||
if(offset < 0x500/4)
|
||||
{
|
||||
return dd_ram_seq_data[(offset - 0x480/4) / 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;
|
||||
@ -2081,7 +2307,19 @@ READ32_MEMBER( n64_periphs::dd_reg_r )
|
||||
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");
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
|
||||
dd_update_bm();
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x0c/4: // Current Track
|
||||
@ -2103,6 +2341,9 @@ READ32_MEMBER( n64_periphs::dd_reg_r )
|
||||
case 0x1c/4: // Sequence Control
|
||||
ret = dd_seq_ctrl_reg;
|
||||
break;
|
||||
case 0x40/4: // ASIC ID
|
||||
ret = 0x00030000; // Japan Retail Drive
|
||||
break;
|
||||
}
|
||||
|
||||
//logerror("dd_reg_r: %08x (%08x)\n", offset << 2, ret);
|
||||
@ -2119,15 +2360,15 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
return;
|
||||
}
|
||||
|
||||
if(offset < 0x480/4)
|
||||
if(offset < 0x500/4)
|
||||
{
|
||||
COMBINE_DATA(&dd_sector_data[(offset - 0x400/4) / 4]);
|
||||
COMBINE_DATA(&dd_sector_data[(offset - 0x400/4)]);
|
||||
return;
|
||||
}
|
||||
|
||||
if(offset < 0x500/4)
|
||||
if((offset < 0x5C0/4) && (0x580/4 <= offset))
|
||||
{
|
||||
COMBINE_DATA(&dd_ram_seq_data[(offset - 0x480/4) / 4]);
|
||||
COMBINE_DATA(&dd_ram_seq_data[(offset - 0x580/4)]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2143,10 +2384,18 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
switch((data >> 16) & 0xff)
|
||||
{
|
||||
case 0x01: // Seek Read
|
||||
logerror("dd command: Seek Read\n");
|
||||
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
|
||||
logerror("dd command: Seek Write\n");
|
||||
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");
|
||||
@ -2157,29 +2406,29 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
case 0x05: // Start Motor
|
||||
logerror("dd command: Start Motor\n");
|
||||
break;
|
||||
case 0x06: // Standby
|
||||
logerror("dd command: Standby\n");
|
||||
case 0x06: // Set Standby Time
|
||||
logerror("dd command: Set Standby Time\n");
|
||||
break;
|
||||
case 0x07: // Set Sleep Mode
|
||||
logerror("dd command: Set Sleep Mode\n");
|
||||
case 0x07: // Set Sleep Time
|
||||
logerror("dd command: Set Sleep Time\n");
|
||||
break;
|
||||
case 0x08: // Unknown
|
||||
logerror("dd command: Unknown\n");
|
||||
case 0x08: // Clear Disk Change Flag
|
||||
logerror("dd command: Clear Disk Change Flag\n");
|
||||
break;
|
||||
case 0x09: // Initialize Drive(?)
|
||||
logerror("dd command: Initialize Drive\n");
|
||||
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 Commadn Inquiry\n");
|
||||
logerror("dd command: ASIC Command Inquiry\n");
|
||||
break;
|
||||
case 0x0D: // Standby Mode (?)
|
||||
logerror("dd command: Standby Mode(?)\n");
|
||||
break;
|
||||
case 0x0E: // Detect Disk Index
|
||||
logerror("dd command: Detect Disk Index\n");
|
||||
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");
|
||||
@ -2198,9 +2447,6 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
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);
|
||||
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
dd_status_reg |= DD_STATUS_INTR;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2212,9 +2458,6 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
machine().base_datetime(systime);
|
||||
|
||||
dd_data_reg = (convert_to_bcd(systime.local_time.mday) << 24) | (convert_to_bcd(systime.local_time.hour) << 16);
|
||||
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
dd_status_reg |= DD_STATUS_INTR;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2226,28 +2469,90 @@ WRITE32_MEMBER( n64_periphs::dd_reg_w )
|
||||
machine().base_datetime(systime);
|
||||
|
||||
dd_data_reg = (convert_to_bcd(systime.local_time.minute) << 24) | (convert_to_bcd(systime.local_time.second) << 16);
|
||||
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
dd_status_reg |= DD_STATUS_INTR;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x1B: // Disk Inquiry
|
||||
logerror("dd command: Disk Inquiry\n");
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Do something here
|
||||
//logerror("Sending MECHA Int\n");
|
||||
dd_status_reg |= DD_ASIC_STATUS_MECHA_INT;
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, ASSERT_LINE);
|
||||
break;
|
||||
|
||||
case 0x10/4: // Interrupt Clear
|
||||
logerror("dd interrupt clear\n");
|
||||
machine().device("maincpu")->execute().set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
|
||||
dd_status_reg &= ~DD_STATUS_INTR;
|
||||
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");
|
||||
machine().device("maincpu")->execute().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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "includes/n64.h"
|
||||
#include "bus/generic/slot.h"
|
||||
#include "bus/generic/carts.h"
|
||||
#include "imagedev/snapquik.h"
|
||||
|
||||
class n64_mess_state : public n64_state
|
||||
{
|
||||
@ -29,6 +30,8 @@ public:
|
||||
INTERRUPT_GEN_MEMBER(n64_reset_poll);
|
||||
DECLARE_DEVICE_IMAGE_LOAD_MEMBER(n64_cart);
|
||||
void mempak_format(UINT8* pak);
|
||||
int quickload(device_image_interface &image, const char *file_type, int quickload_size);
|
||||
DECLARE_QUICKLOAD_LOAD_MEMBER( n64dd );
|
||||
};
|
||||
|
||||
READ32_MEMBER(n64_mess_state::dd_null_r)
|
||||
@ -254,7 +257,7 @@ DEVICE_IMAGE_LOAD_MEMBER(n64_mess_state,n64_cart)
|
||||
MACHINE_START_MEMBER(n64_mess_state,n64dd)
|
||||
{
|
||||
machine_start();
|
||||
|
||||
machine().device<n64_periphs>("rcp")->dd_present = true;
|
||||
UINT8 *ipl = memregion("ddipl")->base();
|
||||
|
||||
for (int i = 0; i < 0x400000; i += 4)
|
||||
@ -270,6 +273,20 @@ MACHINE_START_MEMBER(n64_mess_state,n64dd)
|
||||
}
|
||||
}
|
||||
|
||||
QUICKLOAD_LOAD_MEMBER(n64_mess_state,n64dd)
|
||||
{
|
||||
return quickload(image, file_type, quickload_size);
|
||||
}
|
||||
|
||||
int n64_mess_state::quickload(device_image_interface &image, const char *file_type, int quickload_size)
|
||||
{
|
||||
image.fseek(0, SEEK_SET);
|
||||
image.fread(memregion("disk")->base(), quickload_size);
|
||||
machine().device<n64_periphs>("rcp")->disk_present = true;
|
||||
return IMAGE_INIT_PASS;
|
||||
}
|
||||
|
||||
|
||||
INTERRUPT_GEN_MEMBER(n64_mess_state::n64_reset_poll)
|
||||
{
|
||||
n64_periphs *periphs = machine().device<n64_periphs>("rcp");
|
||||
@ -336,6 +353,7 @@ static MACHINE_CONFIG_DERIVED( n64dd, n64 )
|
||||
MCFG_GENERIC_EXTENSIONS("v64,z64,rom,n64,bin")
|
||||
MCFG_GENERIC_LOAD(n64_mess_state, n64_cart)
|
||||
|
||||
MCFG_QUICKLOAD_ADD("quickload", n64_mess_state, n64dd, "bin,dsk", 0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START( n64 )
|
||||
@ -364,6 +382,8 @@ ROM_START( n64dd )
|
||||
ROM_REGION32_BE( 0x400000, "ddipl", ROMREGION_ERASEFF)
|
||||
ROM_LOAD( "64ddipl.bin", 0x000000, 0x400000, CRC(7f933ce2) SHA1(bf861922dcb78c316360e3e742f4f70ff63c9bc3) )
|
||||
|
||||
ROM_REGION32_LE( 0x4400000, "disk", ROMREGION_ERASEFF)
|
||||
|
||||
ROM_REGION16_BE( 0x80, "normpoint", 0 )
|
||||
ROM_LOAD( "normpnt.rom", 0x00, 0x80, CRC(e7f2a005) SHA1(c27b4a364a24daeee6e99fd286753fd6216362b4) )
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user