diff --git a/src/mame/includes/n64.h b/src/mame/includes/n64.h index e6102b3a5ba..fed6fe4fef9 100644 --- a/src/mame/includes/n64.h +++ b/src/mame/includes/n64.h @@ -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; diff --git a/src/mame/machine/n64.c b/src/mame/machine/n64.c index 81a3662b0b4..b7bf5164cda 100644 --- a/src/mame/machine/n64.c +++ b/src/mame/machine/n64.c @@ -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); } } diff --git a/src/mess/drivers/n64.c b/src/mess/drivers/n64.c index a25a2780689..fd0f65cb425 100644 --- a/src/mess/drivers/n64.c +++ b/src/mess/drivers/n64.c @@ -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("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("rcp")->disk_present = true; + return IMAGE_INIT_PASS; +} + + INTERRUPT_GEN_MEMBER(n64_mess_state::n64_reset_poll) { n64_periphs *periphs = machine().device("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) )