64DD support tentative
This commit is contained in:
parent
25f56e6887
commit
002cb7f5ce
|
@ -10,75 +10,330 @@
|
|||
****************************************************************************/
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "Disk.h"
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include <Project64-core/N64System/SystemGlobals.h>
|
||||
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
||||
|
||||
bool dd_write;
|
||||
bool dd_reset_hold;
|
||||
uint32_t dd_track_offset, dd_zone;
|
||||
|
||||
uint8_t dd_buffer[0x100];
|
||||
|
||||
void DiskCommand()
|
||||
{
|
||||
//ASIC_CMD_STATUS - Commands
|
||||
uint32_t cmd = g_Reg->ASIC_CMD;
|
||||
//ASIC_CMD_STATUS - Commands
|
||||
uint32_t cmd = g_Reg->ASIC_CMD;
|
||||
|
||||
#ifdef _WIN32
|
||||
SYSTEMTIME sysTime;
|
||||
::GetLocalTime(&sysTime);
|
||||
//stdstr_f timestamp("%04d/%02d/%02d %02d:%02d:%02d.%03d %05d,", sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds, GetCurrentThreadId());
|
||||
SYSTEMTIME sysTime;
|
||||
::GetLocalTime(&sysTime);
|
||||
//stdstr_f timestamp("%04d/%02d/%02d %02d:%02d:%02d.%03d %05d,", sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds, GetCurrentThreadId());
|
||||
|
||||
//BCD format needed for 64DD RTC
|
||||
uint8_t year = (uint8_t)(((sysTime.wYear / 10) << 4) | (sysTime.wYear % 10));
|
||||
uint8_t month = (uint8_t)(((sysTime.wMonth / 10) << 4) | (sysTime.wMonth % 10));
|
||||
uint8_t day = (uint8_t)(((sysTime.wDay / 10) << 4) | (sysTime.wDay % 10));
|
||||
uint8_t hour = (uint8_t)(((sysTime.wHour / 10) << 4) | (sysTime.wHour % 10));
|
||||
uint8_t minute = (uint8_t)(((sysTime.wMinute / 10) << 4) | (sysTime.wMinute % 10));
|
||||
uint8_t second = (uint8_t)(((sysTime.wSecond / 10) << 4) | (sysTime.wSecond % 10));
|
||||
//BCD format needed for 64DD RTC
|
||||
uint8_t year = (uint8_t)(((sysTime.wYear / 10) << 4) | (sysTime.wYear % 10));
|
||||
uint8_t month = (uint8_t)(((sysTime.wMonth / 10) << 4) | (sysTime.wMonth % 10));
|
||||
uint8_t day = (uint8_t)(((sysTime.wDay / 10) << 4) | (sysTime.wDay % 10));
|
||||
uint8_t hour = (uint8_t)(((sysTime.wHour / 10) << 4) | (sysTime.wHour % 10));
|
||||
uint8_t minute = (uint8_t)(((sysTime.wMinute / 10) << 4) | (sysTime.wMinute % 10));
|
||||
uint8_t second = (uint8_t)(((sysTime.wSecond / 10) << 4) | (sysTime.wSecond % 10));
|
||||
#else
|
||||
time_t ltime;
|
||||
ltime = time(<ime);
|
||||
|
||||
struct tm result = { 0 };
|
||||
localtime_r(<ime, &result);
|
||||
time_t ltime;
|
||||
ltime = time(<ime);
|
||||
|
||||
struct tm result = { 0 };
|
||||
localtime_r(<ime, &result);
|
||||
|
||||
//stdstr_f timestamp("%04d/%02d/%02d %02d:%02d:%02d.%03d %05d,", result.tm_year + 1900, result.tm_mon + 1, result.tm_mday, result.tm_hour, result.tm_min, result.tm_sec, milliseconds, GetCurrentThreadId());
|
||||
//stdstr_f timestamp("%04d/%02d/%02d %02d:%02d:%02d.%03d %05d,", result.tm_year + 1900, result.tm_mon + 1, result.tm_mday, result.tm_hour, result.tm_min, result.tm_sec, milliseconds, GetCurrentThreadId());
|
||||
|
||||
//BCD format needed for 64DD RTC
|
||||
uint8_t year = (uint8_t)(((result.tm_year / 10) << 4) | (result.tm_year % 10));
|
||||
uint8_t month = (uint8_t)(((result.tm_mon / 10) << 4) | (result.tm_mon % 10));
|
||||
uint8_t day = (uint8_t)(((result.tm_mday / 10) << 4) | (result.tm_mday % 10));
|
||||
uint8_t hour = (uint8_t)(((result.tm_hour / 10) << 4) | (result.tm_hour % 10));
|
||||
uint8_t minute = (uint8_t)(((result.tm_min / 10) << 4) | (result.tm_min % 10));
|
||||
uint8_t second = (uint8_t)(((result.tm_sec / 10) << 4) | (result.tm_sec % 10));
|
||||
//BCD format needed for 64DD RTC
|
||||
uint8_t year = (uint8_t)(((result.tm_year / 10) << 4) | (result.tm_year % 10));
|
||||
uint8_t month = (uint8_t)(((result.tm_mon / 10) << 4) | (result.tm_mon % 10));
|
||||
uint8_t day = (uint8_t)(((result.tm_mday / 10) << 4) | (result.tm_mday % 10));
|
||||
uint8_t hour = (uint8_t)(((result.tm_hour / 10) << 4) | (result.tm_hour % 10));
|
||||
uint8_t minute = (uint8_t)(((result.tm_min / 10) << 4) | (result.tm_min % 10));
|
||||
uint8_t second = (uint8_t)(((result.tm_sec / 10) << 4) | (result.tm_sec % 10));
|
||||
#endif
|
||||
|
||||
switch (cmd & 0xFFFF0000)
|
||||
{
|
||||
case 0x00080000:
|
||||
//Unset Disk Changed Bit
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break;
|
||||
case 0x00090000:
|
||||
//Unset Reset Bit
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; break;
|
||||
case 0x00120000:
|
||||
//RTC Get Year & Month
|
||||
g_Reg->ASIC_DATA = (year << 24) | (month << 16); break;
|
||||
case 0x00130000:
|
||||
//RTC Get Day & Hour
|
||||
g_Reg->ASIC_DATA = (day << 24) | (hour << 16); break;
|
||||
case 0x00140000:
|
||||
//RTC Get Minute & Second
|
||||
g_Reg->ASIC_DATA = (minute << 24) | (second << 16); break;
|
||||
}
|
||||
switch (cmd & 0xFFFF0000)
|
||||
{
|
||||
case 0x00010000:
|
||||
//Seek Read
|
||||
g_Reg->ASIC_CUR_TK = g_Reg->ASIC_DATA | 0x60000000;
|
||||
dd_write = false;
|
||||
break;
|
||||
case 0x00020000:
|
||||
//Seek Write
|
||||
g_Reg->ASIC_CUR_TK = g_Reg->ASIC_DATA | 0x60000000;
|
||||
dd_write = true;
|
||||
break;
|
||||
case 0x00080000:
|
||||
//Unset Disk Changed Bit
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break;
|
||||
case 0x00090000:
|
||||
//Unset Reset Bit
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; break;
|
||||
case 0x00120000:
|
||||
//RTC Get Year & Month
|
||||
g_Reg->ASIC_DATA = (year << 24) | (month << 16); break;
|
||||
case 0x00130000:
|
||||
//RTC Get Day & Hour
|
||||
g_Reg->ASIC_DATA = (day << 24) | (hour << 16); break;
|
||||
case 0x00140000:
|
||||
//RTC Get Minute & Second
|
||||
g_Reg->ASIC_DATA = (minute << 24) | (second << 16); break;
|
||||
case 0x001B0000:
|
||||
//Disk Inquiry
|
||||
g_Reg->ASIC_DATA = 0x00000000; break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiskReset(void)
|
||||
{
|
||||
//ASIC_HARD_RESET 0xAAAA0000
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE;
|
||||
//ASIC_HARD_RESET 0xAAAA0000
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE;
|
||||
}
|
||||
|
||||
void DiskBMControl(void)
|
||||
{
|
||||
if (g_Reg->ASIC_BM_CTL & DD_BM_CTL_MECHA_RST)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_MECHA_INT;
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
}
|
||||
g_Reg->ASIC_CUR_SECTOR = g_Reg->ASIC_BM_CTL & 0x00FF0000;
|
||||
/*
|
||||
if ((g_Reg->ASIC_CUR_SECTOR >> 16) == 0x00)
|
||||
{
|
||||
|
||||
}
|
||||
else if ((g_Reg->ASIC_CUR_SECTOR >> 16) == 0x5A)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
if (g_Reg->ASIC_BM_CTL & DD_BM_CTL_BLK_TRANS)
|
||||
g_Reg->ASIC_BM_STATUS |= DD_BM_STATUS_BLOCK;
|
||||
|
||||
if (g_Reg->ASIC_BM_CTL & DD_BM_CTL_MECHA_RST)
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_MECHA_INT;
|
||||
|
||||
if (g_Reg->ASIC_BM_CTL & DD_BM_CTL_RESET)
|
||||
dd_reset_hold = true;
|
||||
|
||||
if (!(g_Reg->ASIC_BM_CTL & DD_BM_CTL_RESET) && dd_reset_hold)
|
||||
{
|
||||
dd_reset_hold = false;
|
||||
g_Reg->ASIC_STATUS &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ | DD_STATUS_C2_XFER);
|
||||
g_Reg->ASIC_BM_STATUS = 0;
|
||||
g_Reg->ASIC_CUR_SECTOR = 0;
|
||||
}
|
||||
|
||||
if (!(g_Reg->ASIC_STATUS & DD_STATUS_MECHA_INT) && !(g_Reg->ASIC_STATUS & DD_STATUS_BM_INT))
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
|
||||
if (g_Reg->ASIC_BM_CTL & DD_BM_CTL_START)
|
||||
{
|
||||
g_Reg->ASIC_BM_STATUS |= DD_BM_STATUS_RUNNING;
|
||||
DiskBMUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void DiskGapSectorCheck()
|
||||
{
|
||||
if (g_Reg->ASIC_STATUS & DD_STATUS_BM_INT)
|
||||
{
|
||||
uint16_t testsector = (uint16_t)(g_Reg->ASIC_CUR_SECTOR >> 16);
|
||||
if (testsector >= 0x5A)
|
||||
testsector -= 0x5A;
|
||||
|
||||
if (SECTORS_PER_BLOCK < testsector)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_BM_INT;
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
DiskBMUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiskBMUpdate()
|
||||
{
|
||||
if (!(g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_RUNNING))
|
||||
return;
|
||||
|
||||
uint16_t testsector = (uint16_t)(g_Reg->ASIC_CUR_SECTOR >> 16);
|
||||
if (testsector >= 0x5A)
|
||||
testsector -= 0x5A;
|
||||
|
||||
if (dd_write)
|
||||
{
|
||||
//Write Data
|
||||
if (testsector == 0)
|
||||
{
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else if (testsector < SECTORS_PER_BLOCK)
|
||||
{
|
||||
DiskBMWrite();
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else if (testsector < SECTORS_PER_BLOCK + 1)
|
||||
{
|
||||
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
|
||||
{
|
||||
DiskBMWrite();
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
if (g_Reg->ASIC_CUR_SECTOR >> 16 >= 0xB4)
|
||||
g_Reg->ASIC_CUR_SECTOR = 0x00010000;
|
||||
g_Reg->ASIC_BM_STATUS &= ~DD_BM_STATUS_BLOCK;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
DiskBMWrite();
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
g_Reg->ASIC_BM_STATUS &= ~DD_BM_STATUS_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_BM_INT;
|
||||
g_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP3;
|
||||
g_Reg->CheckInterrupts();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Read Data
|
||||
if (((g_Reg->ASIC_CUR_TK >> 16) & 0xFFF) == 6 && g_Reg->ASIC_CUR_SECTOR == 0)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_DATA_RQ;
|
||||
g_Reg->ASIC_BM_STATUS |= DD_BM_STATUS_MICRO;
|
||||
}
|
||||
else if (testsector == 0)
|
||||
{
|
||||
DiskBMRead();
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else if (testsector < SECTORS_PER_BLOCK + 4)
|
||||
{
|
||||
//READ C2 (00!)
|
||||
g_Reg->ASIC_CUR_SECTOR += 0x00010000;
|
||||
if ((g_Reg->ASIC_CUR_SECTOR >> 16) == SECTORS_PER_BLOCK + 4)
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_C2_XFER;
|
||||
}
|
||||
else if (testsector == SECTORS_PER_BLOCK + 4)
|
||||
{
|
||||
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
|
||||
{
|
||||
if (g_Reg->ASIC_CUR_SECTOR >> 16 >= 0xB4)
|
||||
g_Reg->ASIC_CUR_SECTOR = 0x00000000;
|
||||
g_Reg->ASIC_BM_STATUS &= ~DD_BM_STATUS_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Reg->ASIC_BM_STATUS &= ~DD_BM_STATUS_RUNNING;
|
||||
}
|
||||
}
|
||||
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_BM_INT;
|
||||
g_Reg->FAKE_CAUSE_REGISTER |= CAUSE_IP3;
|
||||
g_Reg->CheckInterrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void DiskBMRead()
|
||||
{
|
||||
uint8_t * sector;
|
||||
sector = (uint8_t*)g_Disk->GetDiskAddress();
|
||||
sector += dd_track_offset;
|
||||
uint16_t block = 0;
|
||||
if (g_Reg->ASIC_CUR_SECTOR >= 0x005A0000)
|
||||
block = 1;
|
||||
sector += block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||
uint16_t block2 = (uint16_t)(g_Reg->ASIC_CUR_SECTOR >> 16);
|
||||
if (block2 >= 0x5A)
|
||||
block -= 0x5A;
|
||||
sector += block * ((g_Reg->ASIC_SEC_BYTE >> 16) + 1);
|
||||
|
||||
for (int i = 0; i < ((g_Reg->ASIC_SEC_BYTE >> 16) + 1) / 4; i++)
|
||||
{
|
||||
dd_buffer[i] = sector[(i * 4 + 0)] << 24 | sector[(i * 4 + 1)] << 16 |
|
||||
sector[(i * 4 + 2)] << 8 | sector[(i * 4 + 3)];
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DiskBMWrite()
|
||||
{
|
||||
uint8_t * sector;
|
||||
sector = (uint8_t*)g_Disk->GetDiskAddress();
|
||||
sector += dd_track_offset;
|
||||
uint16_t block = 0;
|
||||
if (g_Reg->ASIC_CUR_SECTOR >= 0x005A0000)
|
||||
block = 1;
|
||||
sector += block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||
uint16_t block2 = (uint16_t)(g_Reg->ASIC_CUR_SECTOR >> 16);
|
||||
if (block2 >= 0x5A)
|
||||
block -= 0x5A;
|
||||
sector += block * ((g_Reg->ASIC_SEC_BYTE >> 16) + 1);
|
||||
|
||||
for (int i = 0; i < ddZoneSecSize[dd_zone] / 4; i++)
|
||||
{
|
||||
sector[i * 4 + 0] = (dd_buffer[i] >> 24) & 0xFF;
|
||||
sector[i * 4 + 1] = (dd_buffer[i] >> 16) & 0xFF;
|
||||
sector[i * 4 + 2] = (dd_buffer[i] >> 8) & 0xFF;
|
||||
sector[i * 4 + 3] = (dd_buffer[i] >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void DiskSetOffset()
|
||||
{
|
||||
uint16_t head = ((g_Reg->ASIC_CUR_TK >> 16) & 0x1000) >> 9; // Head * 8
|
||||
uint16_t track = (g_Reg->ASIC_CUR_TK >> 16) & 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;
|
||||
}
|
|
@ -10,6 +10,30 @@
|
|||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <Common/stdtypes.h>
|
||||
|
||||
void DiskCommand(void);
|
||||
void DiskReset(void);
|
||||
void DiskBMControl(void);
|
||||
void DiskGapSectorCheck(void);
|
||||
void DiskBMUpdate(void);
|
||||
void DiskBMRead(void);
|
||||
void DiskBMWrite(void);
|
||||
void DiskSetOffset(void);
|
||||
|
||||
extern bool dd_write;
|
||||
extern bool dd_reset_hold;
|
||||
extern uint32_t dd_track_offset, dd_zone;
|
||||
|
||||
extern uint8_t dd_buffer[0x100];
|
||||
|
||||
const uint32_t ddZoneSecSize[16] = { 232, 216, 208, 192, 176, 160, 144, 128,
|
||||
216, 208, 192, 176, 160, 144, 128, 112 };
|
||||
const uint32_t ddZoneTrackSize[16] = { 158, 158, 149, 149, 149, 149, 149, 114,
|
||||
158, 158, 149, 149, 149, 149, 149, 114 };
|
||||
const uint32_t ddStartOffset[16] =
|
||||
{ 0x0, 0x5F15E0, 0xB79D00, 0x10801A0, 0x1523720, 0x1963D80, 0x1D414C0, 0x20BBCE0,
|
||||
0x23196E0, 0x28A1E00, 0x2DF5DC0, 0x3299340, 0x36D99A0, 0x3AB70E0, 0x3E31900, 0x4149200 };
|
||||
|
||||
#define SECTORS_PER_BLOCK 85
|
||||
#define BLOCKS_PER_TRACK 2
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include <Project64-core/N64System/Mips/MemoryVirtualMem.h>
|
||||
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
||||
#include <Project64-core/N64System/Mips/Disk.h>
|
||||
#include <Project64-core/N64System/N64Class.h>
|
||||
|
||||
CDMA::CDMA(CFlashram & FlashRam, CSram & Sram) :
|
||||
|
@ -69,6 +70,40 @@ void CDMA::PI_DMA_READ()
|
|||
return;
|
||||
}
|
||||
|
||||
//64DD Buffers Write
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000000 && g_Reg->PI_CART_ADDR_REG <= 0x050003FF)
|
||||
{
|
||||
//64DD C2 Sectors (don't care)
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
DiskBMUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000400 && g_Reg->PI_CART_ADDR_REG <= 0x050004FF)
|
||||
{
|
||||
//64DD User Sector
|
||||
uint32_t i;
|
||||
uint8_t * RDRAM = g_MMU->Rdram();
|
||||
for (i = 0; i < PI_RD_LEN_REG; i++)
|
||||
{
|
||||
dd_buffer[i ^ 3] = * (RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3));
|
||||
}
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
DiskBMUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000580 && g_Reg->PI_CART_ADDR_REG <= 0x050005BF)
|
||||
{
|
||||
//64DD MSEQ (don't care)
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
return;
|
||||
}
|
||||
|
||||
//Write ROM Area (for 64DD Convert)
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x10000000 && g_Reg->PI_CART_ADDR_REG <= 0x1FBFFFFF && g_Settings->LoadBool(Game_AllowROMWrites))
|
||||
{
|
||||
|
@ -182,21 +217,51 @@ void CDMA::PI_DMA_WRITE()
|
|||
return;
|
||||
}
|
||||
|
||||
//64DD Buffers Read
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000000 && g_Reg->PI_CART_ADDR_REG <= 0x050003FF)
|
||||
{
|
||||
//64DD C2 Sectors (just read 0)
|
||||
uint32_t i;
|
||||
uint8_t * RDRAM = g_MMU->Rdram();
|
||||
for (i = 0; i < PI_WR_LEN_REG; i++)
|
||||
{
|
||||
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = 0;
|
||||
}
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000400 && g_Reg->PI_CART_ADDR_REG <= 0x050004FF)
|
||||
{
|
||||
//64DD User Sector
|
||||
uint32_t i;
|
||||
uint8_t * RDRAM = g_MMU->Rdram();
|
||||
for (i = 0; i < PI_WR_LEN_REG; i++)
|
||||
{
|
||||
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = dd_buffer[i ^ 3];
|
||||
}
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x05000580 && g_Reg->PI_CART_ADDR_REG <= 0x050005BF)
|
||||
{
|
||||
//64DD MSEQ (don't care)
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
return;
|
||||
}
|
||||
|
||||
//64DD IPL ROM
|
||||
if (g_Reg->PI_CART_ADDR_REG >= 0x06000000 && g_Reg->PI_CART_ADDR_REG <= 0x063FFFFF)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
#ifdef legacycode
|
||||
#ifdef ROM_IN_MAPSPACE
|
||||
if (WrittenToRom)
|
||||
{
|
||||
uint32_t OldProtect;
|
||||
VirtualProtect(ROM, m_RomFileSize, PAGE_READONLY, &OldProtect);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint8_t * ROM = g_DDRom->GetRomAddress();
|
||||
uint8_t * RDRAM = g_MMU->Rdram();
|
||||
g_Reg->PI_CART_ADDR_REG -= 0x06000000;
|
||||
|
|
|
@ -4827,7 +4827,12 @@ void CMipsMemoryVM::Load32CartridgeDomain2Address1(void)
|
|||
{
|
||||
case 0x05000500: m_MemLookupValue.UW[0] = g_Reg->ASIC_DATA; break;
|
||||
case 0x05000504: m_MemLookupValue.UW[0] = g_Reg->ASIC_MISC_REG; break;
|
||||
case 0x05000508: m_MemLookupValue.UW[0] = g_Reg->ASIC_STATUS; break;
|
||||
case 0x05000508:
|
||||
if (g_Disk != NULL)
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES;
|
||||
m_MemLookupValue.UW[0] = g_Reg->ASIC_STATUS;
|
||||
DiskGapSectorCheck();
|
||||
break;
|
||||
case 0x0500050C: m_MemLookupValue.UW[0] = g_Reg->ASIC_CUR_TK; break;
|
||||
case 0x05000510: m_MemLookupValue.UW[0] = g_Reg->ASIC_BM_STATUS; break;
|
||||
case 0x05000514: m_MemLookupValue.UW[0] = g_Reg->ASIC_ERR_SECTOR; break;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Project64-core/N64System/Mips/Mempak.H>
|
||||
#include <Project64-core/N64System/Interpreter/InterpreterCPU.h>
|
||||
#include <Project64-core/N64System/Mips/OpcodeName.h>
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include <Project64-core/ExceptionHandler.h>
|
||||
#include <Project64-core/Logging.h>
|
||||
#include <Project64-core/Debugger.h>
|
||||
|
@ -216,6 +217,17 @@ bool CN64System::RunFileImage(const char * FileLoc)
|
|||
{
|
||||
//64DD IPL
|
||||
g_DDRom = g_Rom;
|
||||
|
||||
if (g_Disk == NULL)
|
||||
{
|
||||
g_Disk = new CN64Disk();
|
||||
}
|
||||
|
||||
if (!g_Disk->LoadDiskImage(g_Settings->LoadStringVal(SupportFile_DiskTest).c_str()));
|
||||
{
|
||||
delete g_Disk;
|
||||
g_Disk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_System->RefreshGameSettings();
|
||||
|
|
|
@ -28,155 +28,155 @@ CN64Disk::~CN64Disk()
|
|||
|
||||
bool CN64Disk::LoadDiskImage(const char * FileLoc)
|
||||
{
|
||||
UnallocateRomImage();
|
||||
UnallocateDiskImage();
|
||||
|
||||
if (!AllocateAndLoadDiskImage(FileLoc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!AllocateAndLoadDiskImage(FileLoc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_Disk == this)
|
||||
{
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
}
|
||||
if (g_Disk == this)
|
||||
{
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CN64Disk::IsValidRomImage(uint8_t Test[4])
|
||||
bool CN64Disk::IsValidDiskImage(uint8_t Test[4])
|
||||
{
|
||||
if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; }
|
||||
return false;
|
||||
if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CN64Disk::AllocateDiskImage(uint32_t DiskFileSize)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocating memory for disk");
|
||||
std::auto_ptr<uint8_t> ImageBase(new uint8_t[DiskFileSize + 0x1000]);
|
||||
if (ImageBase.get() == NULL)
|
||||
{
|
||||
SetError(MSG_MEM_ALLOC_ERROR);
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to allocate memory for disk (size: 0x%X)", DiskFileSize);
|
||||
return false;
|
||||
}
|
||||
uint8_t * Image = (uint8_t *)(((uint64_t)ImageBase.get() + 0xFFF) & ~0xFFF); // start at begining of memory page
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocated disk memory (%p)", Image);
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocating memory for disk");
|
||||
std::auto_ptr<uint8_t> ImageBase(new uint8_t[DiskFileSize + 0x1000]);
|
||||
if (ImageBase.get() == NULL)
|
||||
{
|
||||
SetError(MSG_MEM_ALLOC_ERROR);
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to allocate memory for disk (size: 0x%X)", DiskFileSize);
|
||||
return false;
|
||||
}
|
||||
uint8_t * Image = (uint8_t *)(((uint64_t)ImageBase.get() + 0xFFF) & ~0xFFF); // start at begining of memory page
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocated disk memory (%p)", Image);
|
||||
|
||||
//save information about the disk loaded
|
||||
m_DiskImageBase = ImageBase.release();
|
||||
m_DiskImage = Image;
|
||||
m_DiskFileSize = DiskFileSize;
|
||||
return true;
|
||||
//save information about the disk loaded
|
||||
m_DiskImageBase = ImageBase.release();
|
||||
m_DiskImage = Image;
|
||||
m_DiskFileSize = DiskFileSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Trying to open %s", FileLoc);
|
||||
if (!m_DiskFile.Open(FileLoc, CFileBase::modeRead))
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to open %s", FileLoc);
|
||||
return false;
|
||||
}
|
||||
WriteTrace(TraceN64System, TraceDebug, "Trying to open %s", FileLoc);
|
||||
if (!m_DiskFile.Open(FileLoc, CFileBase::modeRead))
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to open %s", FileLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Read the first 4 bytes and make sure it is a valid disk image
|
||||
uint8_t Test[4];
|
||||
m_DiskFile.SeekToBegin();
|
||||
if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes");
|
||||
return false;
|
||||
}
|
||||
if (!IsValidRomImage(Test))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
WriteTrace(TraceN64System, TraceError, "invalid image file %X %X %X %X", Test[0], Test[1], Test[2], Test[3]);
|
||||
return false;
|
||||
}
|
||||
uint32_t DiskFileSize = m_DiskFile.GetLength();
|
||||
WriteTrace(TraceN64System, TraceDebug, "Successfully Opened, size: 0x%X", DiskFileSize);
|
||||
//Read the first 4 bytes and make sure it is a valid disk image
|
||||
uint8_t Test[4];
|
||||
m_DiskFile.SeekToBegin();
|
||||
if (m_DiskFile.Read(Test, sizeof(Test)) != sizeof(Test))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to read ident bytes");
|
||||
return false;
|
||||
}
|
||||
if (!IsValidDiskImage(Test))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
WriteTrace(TraceN64System, TraceError, "invalid image file %X %X %X %X", Test[0], Test[1], Test[2], Test[3]);
|
||||
return false;
|
||||
}
|
||||
uint32_t DiskFileSize = m_DiskFile.GetLength();
|
||||
WriteTrace(TraceN64System, TraceDebug, "Successfully Opened, size: 0x%X", DiskFileSize);
|
||||
|
||||
if (!AllocateDiskImage(DiskFileSize))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
return false;
|
||||
}
|
||||
if (!AllocateDiskImage(DiskFileSize))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
//Load the n64 disk to the allocated memory
|
||||
g_Notify->DisplayMessage(5, MSG_LOADING);
|
||||
m_DiskFile.SeekToBegin();
|
||||
//Load the n64 disk to the allocated memory
|
||||
g_Notify->DisplayMessage(5, MSG_LOADING);
|
||||
m_DiskFile.SeekToBegin();
|
||||
|
||||
uint32_t count, TotalRead = 0;
|
||||
for (count = 0; count < (int)DiskFileSize; count += ReadFromRomSection)
|
||||
{
|
||||
uint32_t dwToRead = DiskFileSize - count;
|
||||
if (dwToRead > ReadFromRomSection) { dwToRead = ReadFromRomSection; }
|
||||
uint32_t count, TotalRead = 0;
|
||||
for (count = 0; count < (int)DiskFileSize; count += ReadFromRomSection)
|
||||
{
|
||||
uint32_t dwToRead = DiskFileSize - count;
|
||||
if (dwToRead > ReadFromRomSection) { dwToRead = ReadFromRomSection; }
|
||||
|
||||
if (m_DiskFile.Read(&m_DiskImage[count], dwToRead) != dwToRead)
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to read file (TotalRead: 0x%X)", TotalRead);
|
||||
return false;
|
||||
}
|
||||
TotalRead += dwToRead;
|
||||
if (m_DiskFile.Read(&m_DiskImage[count], dwToRead) != dwToRead)
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
WriteTrace(TraceN64System, TraceError, "Failed to read file (TotalRead: 0x%X)", TotalRead);
|
||||
return false;
|
||||
}
|
||||
TotalRead += dwToRead;
|
||||
|
||||
//Show Message of how much % wise of the rom has been loaded
|
||||
g_Notify->DisplayMessage(0, stdstr_f("%s: %.2f%c", GS(MSG_LOADED), ((float)TotalRead / (float)DiskFileSize) * 100.0f, '%').c_str());
|
||||
}
|
||||
//Show Message of how much % wise of the rom has been loaded
|
||||
g_Notify->DisplayMessage(0, stdstr_f("%s: %.2f%c", GS(MSG_LOADED), ((float)TotalRead / (float)DiskFileSize) * 100.0f, '%').c_str());
|
||||
}
|
||||
|
||||
if (DiskFileSize != TotalRead)
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
WriteTrace(TraceN64System, TraceError, "Expected to read: 0x%X, read: 0x%X", TotalRead, DiskFileSize);
|
||||
return false;
|
||||
}
|
||||
if (DiskFileSize != TotalRead)
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
WriteTrace(TraceN64System, TraceError, "Expected to read: 0x%X, read: 0x%X", TotalRead, DiskFileSize);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_Notify->DisplayMessage(5, MSG_BYTESWAP);
|
||||
ByteSwapDisk();
|
||||
g_Notify->DisplayMessage(5, MSG_BYTESWAP);
|
||||
ByteSwapDisk();
|
||||
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
return true;
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CN64Disk::ByteSwapDisk()
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t count;
|
||||
|
||||
switch (*((uint32_t *)&m_DiskImage[0]))
|
||||
{
|
||||
case 0x16D348E8:
|
||||
for (count = 0; count < m_DiskFileSize; count += 4)
|
||||
{
|
||||
m_DiskImage[count] ^= m_DiskImage[count + 3];
|
||||
m_DiskImage[count + 3] ^= m_DiskImage[count];
|
||||
m_DiskImage[count] ^= m_DiskImage[count + 3];
|
||||
m_DiskImage[count + 1] ^= m_DiskImage[count + 2];
|
||||
m_DiskImage[count + 2] ^= m_DiskImage[count + 1];
|
||||
m_DiskImage[count + 1] ^= m_DiskImage[count + 2];
|
||||
}
|
||||
break;
|
||||
case 0xE848D316: break;
|
||||
default:
|
||||
g_Notify->DisplayError(stdstr_f("ByteSwapDisk: %X", m_DiskImage[0]).c_str());
|
||||
}
|
||||
switch (*((uint32_t *)&m_DiskImage[0]))
|
||||
{
|
||||
case 0x16D348E8:
|
||||
for (count = 0; count < m_DiskFileSize; count += 4)
|
||||
{
|
||||
m_DiskImage[count] ^= m_DiskImage[count + 3];
|
||||
m_DiskImage[count + 3] ^= m_DiskImage[count];
|
||||
m_DiskImage[count] ^= m_DiskImage[count + 3];
|
||||
m_DiskImage[count + 1] ^= m_DiskImage[count + 2];
|
||||
m_DiskImage[count + 2] ^= m_DiskImage[count + 1];
|
||||
m_DiskImage[count + 1] ^= m_DiskImage[count + 2];
|
||||
}
|
||||
break;
|
||||
case 0xE848D316: break;
|
||||
default:
|
||||
g_Notify->DisplayError(stdstr_f("ByteSwapDisk: %X", m_DiskImage[0]).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void CN64Disk::SetError(LanguageStringID ErrorMsg)
|
||||
{
|
||||
m_ErrorMsg = ErrorMsg;
|
||||
m_ErrorMsg = ErrorMsg;
|
||||
}
|
||||
|
||||
void CN64Disk::UnallocateRomImage()
|
||||
void CN64Disk::UnallocateDiskImage()
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
m_DiskFile.Close();
|
||||
|
||||
if (m_DiskImageBase)
|
||||
{
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
delete[] m_DiskImageBase;
|
||||
m_DiskImageBase = NULL;
|
||||
}
|
||||
m_DiskImage = NULL;
|
||||
if (m_DiskImageBase)
|
||||
{
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
delete[] m_DiskImageBase;
|
||||
m_DiskImageBase = NULL;
|
||||
}
|
||||
m_DiskImage = NULL;
|
||||
}
|
|
@ -14,28 +14,28 @@
|
|||
class CN64Disk
|
||||
{
|
||||
public:
|
||||
CN64Disk();
|
||||
~CN64Disk();
|
||||
CN64Disk();
|
||||
~CN64Disk();
|
||||
|
||||
bool LoadDiskImage(const char * FileLoc);
|
||||
static bool IsValidRomImage(uint8_t Test[4]);
|
||||
uint8_t * GetDiskAddress() { return m_DiskImage; }
|
||||
void UnallocateRomImage();
|
||||
bool LoadDiskImage(const char * FileLoc);
|
||||
static bool IsValidDiskImage(uint8_t Test[4]);
|
||||
uint8_t * GetDiskAddress() { return m_DiskImage; }
|
||||
void UnallocateDiskImage();
|
||||
|
||||
private:
|
||||
bool AllocateDiskImage(uint32_t DiskFileSize);
|
||||
bool AllocateAndLoadDiskImage(const char * FileLoc);
|
||||
void ByteSwapDisk();
|
||||
void SetError(LanguageStringID ErrorMsg);
|
||||
bool AllocateDiskImage(uint32_t DiskFileSize);
|
||||
bool AllocateAndLoadDiskImage(const char * FileLoc);
|
||||
void ByteSwapDisk();
|
||||
void SetError(LanguageStringID ErrorMsg);
|
||||
|
||||
//constant values
|
||||
enum { ReadFromRomSection = 0x400000 };
|
||||
//constant values
|
||||
enum { ReadFromRomSection = 0x400000 };
|
||||
|
||||
//class variables
|
||||
CFile m_DiskFile;
|
||||
uint8_t * m_DiskImage;
|
||||
uint8_t * m_DiskImageBase;
|
||||
uint32_t m_DiskFileSize;
|
||||
LanguageStringID m_ErrorMsg;
|
||||
stdstr m_FileName, m_DiskIdent;
|
||||
//class variables
|
||||
CFile m_DiskFile;
|
||||
uint8_t * m_DiskImage;
|
||||
uint8_t * m_DiskImageBase;
|
||||
uint32_t m_DiskFileSize;
|
||||
LanguageStringID m_ErrorMsg;
|
||||
stdstr m_FileName, m_DiskIdent;
|
||||
};
|
|
@ -48,6 +48,8 @@ enum SettingID
|
|||
SupportFile_RomListCacheDefault,
|
||||
SupportFile_7zipCache,
|
||||
SupportFile_7zipCacheDefault,
|
||||
//64DD TEST
|
||||
SupportFile_DiskTest,
|
||||
|
||||
//Settings
|
||||
Setting_ApplicationName,
|
||||
|
|
|
@ -114,6 +114,8 @@ void CSettings::AddHowToHandleSetting()
|
|||
AddHandler(SupportFile_7zipCache, new CSettingTypeApplicationPath("", "7zipCache", SupportFile_7zipCacheDefault));
|
||||
AddHandler(SupportFile_7zipCacheDefault, new CSettingTypeRelativePath("Config", "Project64.zcache"));
|
||||
|
||||
AddHandler(SupportFile_DiskTest, new CSettingTypeRelativePath("Config", "DMPJ.ndd"));
|
||||
|
||||
//AddHandler(SyncPluginDir, new CSettingTypeRelativePath("SyncPlugin",""));
|
||||
|
||||
//Settings location
|
||||
|
|
Loading…
Reference in New Issue