commit
a86ba8db2d
|
@ -96,6 +96,7 @@
|
|||
#212# "Edit Game Settings"
|
||||
#213# "Edit Cheats"
|
||||
#214# "Graphics Plugin"
|
||||
#215# "Play Game with Disk"
|
||||
|
||||
//Alternate Name to save Slot
|
||||
#220# "Save Slot - Default"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <Project64-core/N64System/SystemGlobals.h>
|
||||
#include <Project64-core/Plugins/PluginClass.h>
|
||||
#include <Project64-core/N64System/N64RomClass.h>
|
||||
#include <Project64-core/N64System/N64DiskClass.h>
|
||||
#include "Settings/SettingType/SettingsType-Application.h"
|
||||
|
||||
static void FixDirectories(void);
|
||||
|
@ -152,8 +153,8 @@ void TraceDone(void)
|
|||
|
||||
const char * AppName ( void )
|
||||
{
|
||||
static stdstr_f ApplicationName("Project64 %s", VER_FILE_VERSION_STR);
|
||||
return ApplicationName.c_str();
|
||||
static stdstr_f ApplicationName("Project64 %s", VER_FILE_VERSION_STR);
|
||||
return ApplicationName.c_str();
|
||||
}
|
||||
|
||||
static bool ParseCommand(int32_t argc, char **argv)
|
||||
|
@ -168,8 +169,8 @@ static bool ParseCommand(int32_t argc, char **argv)
|
|||
if (strcmp(argv[i], "--basedir") == 0 && ArgsLeft >= 1)
|
||||
{
|
||||
g_Settings->SaveString(Cmd_BaseDirectory, argv[i + 1]);
|
||||
CSettingTypeApplication::Initialize(AppName());
|
||||
i++;
|
||||
CSettingTypeApplication::Initialize(AppName());
|
||||
i++;
|
||||
}
|
||||
else if (strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
|
@ -195,11 +196,11 @@ bool AppInit(CNotification * Notify, int argc, char **argv)
|
|||
{
|
||||
g_Notify = Notify;
|
||||
InitializeLog();
|
||||
if (Notify == NULL)
|
||||
{
|
||||
WriteTrace(TraceAppInit, TraceError, "No Notification class passed");
|
||||
return false;
|
||||
}
|
||||
if (Notify == NULL)
|
||||
{
|
||||
WriteTrace(TraceAppInit, TraceError, "No Notification class passed");
|
||||
return false;
|
||||
}
|
||||
g_Settings = new CSettings;
|
||||
g_Settings->Initialize(AppName());
|
||||
|
||||
|
@ -232,14 +233,14 @@ bool AppInit(CNotification * Notify, int argc, char **argv)
|
|||
g_Lang = new CLanguage();
|
||||
g_Lang->LoadCurrentStrings();
|
||||
g_Notify->AppInitDone();
|
||||
WriteTrace(TraceAppInit, TraceDebug, "Initialized Successfully");
|
||||
return true;
|
||||
WriteTrace(TraceAppInit, TraceDebug, "Initialized Successfully");
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
g_Notify->DisplayError(stdstr_f("Exception caught\nFile: %s\nLine: %d", __FILE__, __LINE__).c_str());
|
||||
WriteTrace(TraceAppInit, TraceError, "Exception caught, Init was not successfull");
|
||||
return false;
|
||||
WriteTrace(TraceAppInit, TraceError, "Exception caught, Init was not successfull");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,6 +250,8 @@ void AppCleanup(void)
|
|||
CleanupTrace();
|
||||
|
||||
if (g_Rom) { delete g_Rom; g_Rom = NULL; }
|
||||
if (g_DDRom) { delete g_DDRom; g_DDRom = NULL; }
|
||||
if (g_Disk) { delete g_Disk; g_Disk = NULL; }
|
||||
if (g_Plugins) { delete g_Plugins; g_Plugins = NULL; }
|
||||
if (g_Settings) { delete g_Settings; g_Settings = NULL; }
|
||||
if (g_Lang) { delete g_Lang; g_Lang = NULL; }
|
||||
|
|
|
@ -125,6 +125,7 @@ enum LanguageStringID{
|
|||
POPUP_SETTINGS = 212,
|
||||
POPUP_CHEATS = 213,
|
||||
POPUP_GFX_PLUGIN = 214,
|
||||
POPUP_PLAYDISK = 215,
|
||||
|
||||
//selecting save slot
|
||||
SAVE_SLOT_DEFAULT = 220,
|
||||
|
|
|
@ -133,6 +133,7 @@ void CLanguage::LoadDefaultStrings(void)
|
|||
DEF_STR(POPUP_SETTINGS, "Edit Game Settings");
|
||||
DEF_STR(POPUP_CHEATS, "Edit Cheats");
|
||||
DEF_STR(POPUP_GFX_PLUGIN, "Graphics Plugin");
|
||||
DEF_STR(POPUP_PLAYDISK, "Play Game with Disk");
|
||||
|
||||
//Alternate Name to save Slot
|
||||
DEF_STR(SAVE_SLOT_DEFAULT, "Save Slot - Default");
|
||||
|
|
|
@ -8,77 +8,316 @@
|
|||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
// Based from MAME's N64DD driver code by Happy_
|
||||
#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>
|
||||
#include <Project64-core/N64System/Mips/SystemTiming.h>
|
||||
|
||||
bool dd_write;
|
||||
bool dd_reset_hold;
|
||||
uint32_t dd_track_offset, dd_zone;
|
||||
uint32_t dd_start_block, dd_current;
|
||||
|
||||
void DiskCommand()
|
||||
{
|
||||
//ASIC_CMD_STATUS - Commands
|
||||
uint32_t cmd = g_Reg->ASIC_CMD;
|
||||
if (g_Disk != NULL)
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES;
|
||||
|
||||
//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);
|
||||
|
||||
//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());
|
||||
|
||||
//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;
|
||||
DiskSetOffset();
|
||||
dd_write = false;
|
||||
break;
|
||||
case 0x00020000:
|
||||
//Seek Write
|
||||
g_Reg->ASIC_CUR_TK = g_Reg->ASIC_DATA | 0x60000000;
|
||||
DiskSetOffset();
|
||||
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)
|
||||
{
|
||||
dd_start_block = 0;
|
||||
dd_current = 0;
|
||||
}
|
||||
else if ((g_Reg->ASIC_CUR_SECTOR >> 16) == 0x5A)
|
||||
{
|
||||
dd_start_block = 1;
|
||||
dd_current = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
dd_start_block = 0;
|
||||
dd_current = 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)
|
||||
{
|
||||
if (SECTORS_PER_BLOCK < dd_current)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_BM_INT;
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
g_Reg->CheckInterrupts();
|
||||
DiskBMUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiskBMUpdate()
|
||||
{
|
||||
if (!(g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_RUNNING))
|
||||
return;
|
||||
|
||||
if (dd_write)
|
||||
{
|
||||
//Write Data
|
||||
if (dd_current < SECTORS_PER_BLOCK)
|
||||
{
|
||||
DiskBMWrite();
|
||||
dd_current += 1;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else if (dd_current < SECTORS_PER_BLOCK + 1)
|
||||
{
|
||||
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
|
||||
{
|
||||
dd_start_block = 1 - dd_start_block;
|
||||
dd_current = 0;
|
||||
DiskBMWrite();
|
||||
dd_current += 1;
|
||||
g_Reg->ASIC_BM_STATUS &= ~DD_BM_STATUS_BLOCK;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
dd_current += 1;
|
||||
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 (dd_current < SECTORS_PER_BLOCK)
|
||||
{
|
||||
DiskBMRead();
|
||||
dd_current += 1;
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_DATA_RQ;
|
||||
}
|
||||
else if (dd_current < SECTORS_PER_BLOCK + 4)
|
||||
{
|
||||
//READ C2 (00!)
|
||||
dd_current += 1;
|
||||
if (dd_current == SECTORS_PER_BLOCK + 4)
|
||||
g_Reg->ASIC_STATUS |= DD_STATUS_C2_XFER;
|
||||
}
|
||||
else if (dd_current == SECTORS_PER_BLOCK + 4)
|
||||
{
|
||||
if (g_Reg->ASIC_BM_STATUS & DD_BM_STATUS_BLOCK)
|
||||
{
|
||||
dd_start_block = 1 - dd_start_block;
|
||||
dd_current = 0;
|
||||
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()
|
||||
{
|
||||
uint32_t sector = 0;
|
||||
sector += dd_track_offset;
|
||||
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||
sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1);
|
||||
WriteTrace(TraceN64System, TraceDebug, "READ Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector);
|
||||
g_Disk->SetDiskAddressBuffer(sector);
|
||||
return;
|
||||
}
|
||||
|
||||
void DiskBMWrite()
|
||||
{
|
||||
uint32_t sector = 0;
|
||||
sector += dd_track_offset;
|
||||
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||
sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1);
|
||||
WriteTrace(TraceN64System, TraceDebug, "WRITE Block %d Sector %02X - %08X", ((g_Reg->ASIC_CUR_TK & 0x0FFF0000) >> 15) | dd_start_block, dd_current, sector);
|
||||
g_Disk->SetDiskAddressBuffer(sector);
|
||||
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;
|
||||
}
|
||||
|
||||
void DiskDMACheck(void)
|
||||
{
|
||||
if (g_Reg->PI_CART_ADDR_REG == 0x05000000)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_C2_XFER);
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
g_Reg->CheckInterrupts();
|
||||
}
|
||||
else if (g_Reg->PI_CART_ADDR_REG == 0x05000400)
|
||||
{
|
||||
g_Reg->ASIC_STATUS &= ~(DD_STATUS_BM_INT | DD_STATUS_BM_ERR | DD_STATUS_DATA_RQ);
|
||||
g_Reg->FAKE_CAUSE_REGISTER &= ~CAUSE_IP3;
|
||||
g_Reg->CheckInterrupts();
|
||||
}
|
||||
}
|
|
@ -8,9 +8,33 @@
|
|||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
// Based from MAME's N64DD driver code by Happy_
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
|
||||
#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);
|
||||
void DiskDMACheck(void);
|
||||
|
||||
extern bool dd_write;
|
||||
extern bool dd_reset_hold;
|
||||
extern uint32_t dd_track_offset, dd_zone;
|
||||
extern uint32_t dd_start_block, dd_current;
|
||||
|
||||
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,8 @@
|
|||
#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/N64DiskClass.h>
|
||||
#include <Project64-core/N64System/N64Class.h>
|
||||
|
||||
CDMA::CDMA(CFlashram & FlashRam, CSram & Sram) :
|
||||
|
@ -69,6 +71,37 @@ 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_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_RD_LEN_REG * 63) / 25, false);
|
||||
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();
|
||||
uint8_t * DISK = g_Disk->GetDiskAddressBuffer();
|
||||
for (i = 0; i < PI_RD_LEN_REG; i++)
|
||||
{
|
||||
*(DISK + (i ^ 3)) = *(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3));
|
||||
}
|
||||
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_RD_LEN_REG * 63) / 25, false);
|
||||
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 +215,52 @@ 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;
|
||||
}
|
||||
|
||||
//Timer is needed for Track Read
|
||||
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_WR_LEN_REG * 63) / 25, false);
|
||||
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();
|
||||
uint8_t * DISK = g_Disk->GetDiskAddressBuffer();
|
||||
for (i = 0; i < PI_WR_LEN_REG; i++)
|
||||
{
|
||||
*(RDRAM + ((g_Reg->PI_DRAM_ADDR_REG + i) ^ 3)) = *(DISK + (i ^ 3));
|
||||
}
|
||||
|
||||
//Timer is needed for Track Read
|
||||
g_SystemTimer->SetTimer(g_SystemTimer->DDPiTimer, (PI_WR_LEN_REG * 63) / 25, false);
|
||||
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;
|
||||
|
|
|
@ -959,7 +959,12 @@ void CMipsMemoryVM::Compile_LW(x86Reg Reg, uint32_t VAddr)
|
|||
{
|
||||
case 0x05000500: MoveVariableToX86reg(&g_Reg->ASIC_DATA, "ASIC_DATA", Reg); break;
|
||||
case 0x05000504: MoveVariableToX86reg(&g_Reg->ASIC_MISC_REG, "ASIC_MISC_REG", Reg); break;
|
||||
case 0x05000508: MoveVariableToX86reg(&g_Reg->ASIC_STATUS, "ASIC_STATUS", Reg); break;
|
||||
case 0x05000508:
|
||||
MoveVariableToX86reg(&g_Reg->ASIC_STATUS, "ASIC_STATUS", Reg);
|
||||
BeforeCallDirect(m_RegWorkingSet);
|
||||
Call_Direct(AddressOf(&DiskGapSectorCheck), "DiskGapSectorCheck");
|
||||
AfterCallDirect(m_RegWorkingSet);
|
||||
break;
|
||||
case 0x0500050C: MoveVariableToX86reg(&g_Reg->ASIC_CUR_TK, "ASIC_CUR_TK", Reg); break;
|
||||
case 0x05000510: MoveVariableToX86reg(&g_Reg->ASIC_BM_STATUS, "ASIC_BM_STATUS", Reg); break;
|
||||
case 0x05000514: MoveVariableToX86reg(&g_Reg->ASIC_ERR_SECTOR, "ASIC_ERR_SECTOR", Reg); break;
|
||||
|
@ -1922,7 +1927,15 @@ void CMipsMemoryVM::Compile_SW_Register(x86Reg Reg, uint32_t VAddr)
|
|||
switch (PAddr)
|
||||
{
|
||||
case 0x04600000: MoveX86regToVariable(Reg, &g_Reg->PI_DRAM_ADDR_REG, "PI_DRAM_ADDR_REG"); break;
|
||||
case 0x04600004: MoveX86regToVariable(Reg, &g_Reg->PI_CART_ADDR_REG, "PI_CART_ADDR_REG"); break;
|
||||
case 0x04600004:
|
||||
MoveX86regToVariable(Reg, &g_Reg->PI_CART_ADDR_REG, "PI_CART_ADDR_REG");
|
||||
if (g_Settings->LoadBool(Setting_EnableDisk))
|
||||
{
|
||||
BeforeCallDirect(m_RegWorkingSet);
|
||||
Call_Direct(AddressOf(&DiskDMACheck), "DiskDMACheck");
|
||||
AfterCallDirect(m_RegWorkingSet);
|
||||
}
|
||||
break;
|
||||
case 0x04600008:
|
||||
MoveX86regToVariable(Reg, &g_Reg->PI_RD_LEN_REG, "PI_RD_LEN_REG");
|
||||
BeforeCallDirect(m_RegWorkingSet);
|
||||
|
@ -4827,7 +4840,10 @@ 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:
|
||||
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;
|
||||
|
@ -5407,7 +5423,11 @@ void CMipsMemoryVM::Write32PeripheralInterface(void)
|
|||
switch (m_MemLookupAddress & 0xFFFFFFF)
|
||||
{
|
||||
case 0x04600000: g_Reg->PI_DRAM_ADDR_REG = m_MemLookupValue.UW[0]; break;
|
||||
case 0x04600004: g_Reg->PI_CART_ADDR_REG = m_MemLookupValue.UW[0]; break;
|
||||
case 0x04600004:
|
||||
g_Reg->PI_CART_ADDR_REG = m_MemLookupValue.UW[0];
|
||||
if (g_Settings->LoadBool(Setting_EnableDisk))
|
||||
DiskDMACheck();
|
||||
break;
|
||||
case 0x04600008:
|
||||
g_Reg->PI_RD_LEN_REG = m_MemLookupValue.UW[0];
|
||||
g_MMU->PI_DMA_READ();
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <Project64-core/N64System/Mips/SystemTiming.h>
|
||||
#include <Project64-core/N64System/SystemGlobals.h>
|
||||
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
||||
#include <Project64-core/N64System/Mips/Disk.h>
|
||||
#include <Project64-core/N64System/N64Class.h>
|
||||
#include <Project64-core/3rdParty/zip.h>
|
||||
|
||||
|
@ -207,6 +208,13 @@ void CSystemTimer::TimerDone()
|
|||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
break;
|
||||
case CSystemTimer::DDPiTimer:
|
||||
g_SystemTimer->StopTimer(CSystemTimer::DDPiTimer);
|
||||
g_Reg->PI_STATUS_REG &= ~PI_STATUS_DMA_BUSY;
|
||||
DiskBMUpdate();
|
||||
g_Reg->MI_INTR_REG |= MI_INTR_PI;
|
||||
g_Reg->CheckInterrupts();
|
||||
break;
|
||||
case CSystemTimer::ViTimer:
|
||||
try
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ public:
|
|||
PiTimer,
|
||||
RspTimer,
|
||||
RSPTimerDlist,
|
||||
DDPiTimer,
|
||||
MaxTimer
|
||||
};
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
@ -188,6 +189,7 @@ void CN64System::ExternalEvent(SystemEvent action)
|
|||
bool CN64System::RunFileImage(const char * FileLoc)
|
||||
{
|
||||
CloseSystem();
|
||||
g_Settings->SaveBool(Setting_EnableDisk, false);
|
||||
if (g_Settings->LoadBool(GameRunning_LoadingInProgress))
|
||||
{
|
||||
return false;
|
||||
|
@ -216,6 +218,12 @@ bool CN64System::RunFileImage(const char * FileLoc)
|
|||
{
|
||||
//64DD IPL
|
||||
g_DDRom = g_Rom;
|
||||
g_Settings->SaveString(File_DiskIPLPath, FileLoc);
|
||||
}
|
||||
|
||||
if (g_DDRom != NULL)
|
||||
{
|
||||
g_Settings->SaveBool(Setting_EnableDisk, true);
|
||||
}
|
||||
|
||||
g_System->RefreshGameSettings();
|
||||
|
@ -244,6 +252,107 @@ bool CN64System::RunFileImage(const char * FileLoc)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CN64System::RunFileImageIPL(const char * FileLoc)
|
||||
{
|
||||
CloseSystem();
|
||||
if (g_Settings->LoadBool(GameRunning_LoadingInProgress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Mark the rom as loading
|
||||
WriteTrace(TraceN64System, TraceDebug, "Mark DDRom as loading");
|
||||
//g_Settings->SaveString(Game_File, "");
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, true);
|
||||
|
||||
//Try to load the passed N64 DDrom
|
||||
if (g_DDRom == NULL)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocating global DDrom object");
|
||||
g_DDRom = new CN64Rom();
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Use existing global DDrom object");
|
||||
}
|
||||
|
||||
WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc);
|
||||
if (g_DDRom->LoadN64ImageIPL(FileLoc))
|
||||
{
|
||||
if (g_DDRom->CicChipID() != CIC_NUS_8303)
|
||||
{
|
||||
//If not 64DD IPL then it's wrong
|
||||
WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc);
|
||||
g_Notify->DisplayError(g_DDRom->GetError());
|
||||
delete g_DDRom;
|
||||
g_DDRom = NULL;
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_System->RefreshGameSettings();
|
||||
|
||||
g_Settings->SaveString(File_DiskIPLPath, FileLoc);
|
||||
|
||||
//g_Settings->SaveString(Game_File, FileLoc);
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceError, "LoadN64ImageIPL failed (\"%s\")", FileLoc);
|
||||
g_Notify->DisplayError(g_DDRom->GetError());
|
||||
delete g_DDRom;
|
||||
g_DDRom = NULL;
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CN64System::RunDiskImage(const char * FileLoc)
|
||||
{
|
||||
CloseSystem();
|
||||
if (g_Settings->LoadBool(GameRunning_LoadingInProgress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Mark the rom as loading
|
||||
WriteTrace(TraceN64System, TraceDebug, "Mark Disk as loading");
|
||||
//g_Settings->SaveString(Game_File, "");
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, true);
|
||||
|
||||
//Try to load the passed N64 Disk
|
||||
if (g_Disk == NULL)
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Allocating global Disk object");
|
||||
g_Disk = new CN64Disk();
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceDebug, "Use existing global Disk object");
|
||||
}
|
||||
|
||||
WriteTrace(TraceN64System, TraceDebug, "Loading \"%s\"", FileLoc);
|
||||
if (g_Disk->LoadDiskImage(FileLoc))
|
||||
{
|
||||
g_System->RefreshGameSettings();
|
||||
|
||||
//g_Settings->SaveString(Game_File, FileLoc);
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteTrace(TraceN64System, TraceError, "LoadDiskImage failed (\"%s\")", FileLoc);
|
||||
g_Notify->DisplayError(g_Disk->GetError());
|
||||
delete g_Disk;
|
||||
g_Disk = NULL;
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CN64System::CloseSystem()
|
||||
{
|
||||
if (g_BaseSystem)
|
||||
|
|
|
@ -56,6 +56,8 @@ public:
|
|||
|
||||
//Methods
|
||||
static bool RunFileImage(const char * FileLoc);
|
||||
static bool RunFileImageIPL(const char * FileLoc);
|
||||
static bool RunDiskImage(const char * FileLoc);
|
||||
static void CloseSystem(void);
|
||||
|
||||
void CloseCpu();
|
||||
|
|
|
@ -0,0 +1,357 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include "stdafx.h"
|
||||
#include "N64DiskClass.h"
|
||||
#include "SystemGlobals.h"
|
||||
#include <Common/Platform.h>
|
||||
#include <Common/MemoryManagement.h>
|
||||
|
||||
CN64Disk::CN64Disk() :
|
||||
m_DiskImage(NULL),
|
||||
m_DiskImageBase(NULL),
|
||||
m_ErrorMsg(EMPTY_STRING),
|
||||
m_DiskBufAddress(0)
|
||||
{
|
||||
}
|
||||
|
||||
CN64Disk::~CN64Disk()
|
||||
{
|
||||
}
|
||||
|
||||
bool CN64Disk::LoadDiskImage(const char * FileLoc)
|
||||
{
|
||||
UnallocateDiskImage();
|
||||
|
||||
if (!AllocateAndLoadDiskImage(FileLoc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (g_Disk == this)
|
||||
{
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CN64Disk::IsValidDiskImage(uint8_t Test[4])
|
||||
{
|
||||
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);
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
//Check Disk File Format
|
||||
if (DiskFileSize == MameFormatSize)
|
||||
{
|
||||
//If Disk is MAME Format (size is constant, it should be the same for every file), then continue
|
||||
WriteTrace(TraceN64System, TraceDebug, "Disk File is MAME Format", );
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
|
||||
//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;
|
||||
}
|
||||
}
|
||||
else if (DiskFileSize == SDKFormatSize)
|
||||
{
|
||||
//If Disk is SDK format (made with SDK based dumpers like LuigiBlood's, or Nintendo's, size is also constant)
|
||||
//We need to convert it.
|
||||
g_Notify->DisplayMessage(5, MSG_LOADING);
|
||||
|
||||
//Allocate supported size
|
||||
if (!AllocateDiskImage(MameFormatSize))
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
return false;
|
||||
}
|
||||
|
||||
ConvertDiskFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Else the disk file is invalid
|
||||
m_DiskFile.Close();
|
||||
WriteTrace(TraceN64System, TraceError, "Disk File is invalid, unexpected size");
|
||||
return false;
|
||||
}
|
||||
|
||||
g_Notify->DisplayMessage(5, MSG_BYTESWAP);
|
||||
ByteSwapDisk();
|
||||
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CN64Disk::ByteSwapDisk()
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
void CN64Disk::SetError(LanguageStringID ErrorMsg)
|
||||
{
|
||||
m_ErrorMsg = ErrorMsg;
|
||||
}
|
||||
|
||||
void CN64Disk::UnallocateDiskImage()
|
||||
{
|
||||
m_DiskFile.Close();
|
||||
|
||||
if (m_DiskImageBase)
|
||||
{
|
||||
ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE);
|
||||
delete[] m_DiskImageBase;
|
||||
m_DiskImageBase = NULL;
|
||||
}
|
||||
m_DiskImage = NULL;
|
||||
}
|
||||
|
||||
void CN64Disk::ConvertDiskFormat()
|
||||
{
|
||||
//Original code by Happy_
|
||||
m_DiskFile.SeekToBegin();
|
||||
|
||||
const uint32_t ZoneSecSize[16] = { 232, 216, 208, 192, 176, 160, 144, 128,
|
||||
216, 208, 192, 176, 160, 144, 128, 112 };
|
||||
const uint32_t ZoneTracks[16] = { 158, 158, 149, 149, 149, 149, 149, 114,
|
||||
158, 158, 149, 149, 149, 149, 149, 114 };
|
||||
const uint32_t DiskTypeZones[7][16] = {
|
||||
{ 0, 1, 2, 9, 8, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10 },
|
||||
{ 0, 1, 2, 3, 10, 9, 8, 4, 5, 6, 7, 15, 14, 13, 12, 11 },
|
||||
{ 0, 1, 2, 3, 4, 11, 10, 9, 8, 5, 6, 7, 15, 14, 13, 12 },
|
||||
{ 0, 1, 2, 3, 4, 5, 12, 11, 10, 9, 8, 6, 7, 15, 14, 13 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 }
|
||||
};
|
||||
const uint32_t RevDiskTypeZones[7][16] = {
|
||||
{ 0, 1, 2, 5, 6, 7, 8, 9, 4, 3, 15, 14, 13, 12, 11, 10 },
|
||||
{ 0, 1, 2, 3, 7, 8, 9, 10, 6, 5, 4, 15, 14, 13, 12, 11 },
|
||||
{ 0, 1, 2, 3, 4, 9, 10, 11, 8, 7, 6, 5, 15, 14, 13, 12 },
|
||||
{ 0, 1, 2, 3, 4, 5, 11, 12, 10, 9, 8, 7, 6, 15, 14, 13 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 13, 12, 11, 10, 9, 8, 7, 15, 14 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 14, 13, 12, 11, 10, 9, 8, 15 },
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 15, 14, 13, 12, 11, 10, 9, 8 }
|
||||
};
|
||||
const uint32_t StartBlock[7][16] = {
|
||||
{ 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1 },
|
||||
{ 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1 },
|
||||
{ 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 },
|
||||
{ 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0 },
|
||||
{ 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1 }
|
||||
};
|
||||
|
||||
uint32_t disktype = 0;
|
||||
uint32_t zone, track = 0;
|
||||
int32_t atrack = 0;
|
||||
int32_t block = 0;
|
||||
uint8_t SystemData[0xE8];
|
||||
uint8_t BlockData0[0x100 * SECTORS_PER_BLOCK];
|
||||
uint8_t BlockData1[0x100 * SECTORS_PER_BLOCK];
|
||||
uint32_t InOffset, OutOffset = 0;
|
||||
uint32_t InStart[16];
|
||||
uint32_t OutStart[16];
|
||||
|
||||
InStart[0] = 0;
|
||||
OutStart[0] = 0;
|
||||
|
||||
//Read System Area
|
||||
m_DiskFile.Read(&SystemData, 0xE8);
|
||||
|
||||
disktype = SystemData[5] & 0xF;
|
||||
|
||||
//Prepare Input Offsets
|
||||
for (zone = 1; zone < 16; zone++)
|
||||
{
|
||||
InStart[zone] = InStart[zone - 1] +
|
||||
VZONESIZE(DiskTypeZones[disktype][zone - 1]);
|
||||
}
|
||||
|
||||
//Prepare Output Offsets
|
||||
for (zone = 1; zone < 16; zone++)
|
||||
{
|
||||
OutStart[zone] = OutStart[zone - 1] + ZONESIZE(zone - 1);
|
||||
}
|
||||
|
||||
//Copy Head 0
|
||||
for (zone = 0; zone < 8; zone++)
|
||||
{
|
||||
OutOffset = OutStart[zone];
|
||||
InOffset = InStart[RevDiskTypeZones[disktype][zone]];
|
||||
m_DiskFile.Seek(InOffset, CFileBase::SeekPosition::begin);
|
||||
block = StartBlock[disktype][zone];
|
||||
atrack = 0;
|
||||
for (track = 0; track < ZoneTracks[zone]; track++)
|
||||
{
|
||||
if (track == SystemData[0x20 + zone * 0xC + atrack])
|
||||
{
|
||||
memset((void *)(&BlockData0), 0, BLOCKSIZE(zone));
|
||||
memset((void *)(&BlockData1), 0, BLOCKSIZE(zone));
|
||||
atrack += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((block % 2) == 1)
|
||||
{
|
||||
m_DiskFile.Read(&BlockData1, BLOCKSIZE(zone));
|
||||
m_DiskFile.Read(&BlockData0, BLOCKSIZE(zone));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DiskFile.Read(&BlockData0, BLOCKSIZE(zone));
|
||||
m_DiskFile.Read(&BlockData1, BLOCKSIZE(zone));
|
||||
}
|
||||
block = 1 - block;
|
||||
}
|
||||
memcpy(m_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone));
|
||||
OutOffset += BLOCKSIZE(zone);
|
||||
memcpy(m_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone));
|
||||
OutOffset += BLOCKSIZE(zone);
|
||||
}
|
||||
}
|
||||
|
||||
//Copy Head 1
|
||||
for (zone = 8; zone < 16; zone++)
|
||||
{
|
||||
//OutOffset = OutStart[zone];
|
||||
InOffset = InStart[RevDiskTypeZones[disktype][zone]];
|
||||
m_DiskFile.Seek(InOffset, CFileBase::SeekPosition::begin);
|
||||
block = StartBlock[disktype][zone];
|
||||
atrack = 0xB;
|
||||
for (track = 1; track < ZoneTracks[zone] + 1; track++)
|
||||
{
|
||||
if ((ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack])
|
||||
{
|
||||
memset((void *)(&BlockData0), 0, BLOCKSIZE(zone));
|
||||
memset((void *)(&BlockData1), 0, BLOCKSIZE(zone));
|
||||
atrack -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((block % 2) == 1)
|
||||
{
|
||||
m_DiskFile.Read(&BlockData1, BLOCKSIZE(zone));
|
||||
m_DiskFile.Read(&BlockData0, BLOCKSIZE(zone));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_DiskFile.Read(&BlockData0, BLOCKSIZE(zone));
|
||||
m_DiskFile.Read(&BlockData1, BLOCKSIZE(zone));
|
||||
}
|
||||
block = 1 - block;
|
||||
}
|
||||
OutOffset = OutStart[zone] + (ZoneTracks[zone] - track) * TRACKSIZE(zone);
|
||||
memcpy(m_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone));
|
||||
OutOffset += BLOCKSIZE(zone);
|
||||
memcpy(m_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone));
|
||||
OutOffset += BLOCKSIZE(zone);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* Project64 - A Nintendo 64 emulator. *
|
||||
* http://www.pj64-emu.com/ *
|
||||
* Copyright (C) 2012 Project64. All rights reserved. *
|
||||
* *
|
||||
* License: *
|
||||
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
|
||||
* *
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#include <Common/stdtypes.h>
|
||||
|
||||
class CN64Disk
|
||||
{
|
||||
public:
|
||||
CN64Disk();
|
||||
~CN64Disk();
|
||||
|
||||
bool LoadDiskImage(const char * FileLoc);
|
||||
static bool IsValidDiskImage(uint8_t Test[4]);
|
||||
uint8_t * GetDiskAddress() { return m_DiskImage; }
|
||||
uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; }
|
||||
void SetDiskAddressBuffer(uint32_t address) { m_DiskBufAddress = address; }
|
||||
void UnallocateDiskImage();
|
||||
|
||||
LanguageStringID GetError() const { return m_ErrorMsg; }
|
||||
|
||||
private:
|
||||
bool AllocateDiskImage(uint32_t DiskFileSize);
|
||||
bool AllocateAndLoadDiskImage(const char * FileLoc);
|
||||
void ByteSwapDisk();
|
||||
void SetError(LanguageStringID ErrorMsg);
|
||||
void ConvertDiskFormat();
|
||||
|
||||
//constant values
|
||||
enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800 };
|
||||
|
||||
//class variables
|
||||
CFile m_DiskFile;
|
||||
uint8_t * m_DiskImage;
|
||||
uint8_t * m_DiskImageBase;
|
||||
uint32_t m_DiskFileSize;
|
||||
uint32_t m_DiskBufAddress;
|
||||
LanguageStringID m_ErrorMsg;
|
||||
stdstr m_FileName, m_DiskIdent;
|
||||
|
||||
//disk convert
|
||||
#define SECTORS_PER_BLOCK 85
|
||||
#define BLOCKS_PER_TRACK 2
|
||||
|
||||
#define BLOCKSIZE(_zone) ZoneSecSize[_zone] * SECTORS_PER_BLOCK
|
||||
#define TRACKSIZE(_zone) BLOCKSIZE(_zone) * BLOCKS_PER_TRACK
|
||||
#define ZONESIZE(_zone) TRACKSIZE(_zone) * ZoneTracks[_zone]
|
||||
#define VZONESIZE(_zone) TRACKSIZE(_zone) * (ZoneTracks[_zone] - 0xC)
|
||||
};
|
|
@ -579,6 +579,183 @@ bool CN64Rom::LoadN64Image(const char * FileLoc, bool LoadBootCodeOnly)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CN64Rom::LoadN64ImageIPL(const char * FileLoc, bool LoadBootCodeOnly)
|
||||
{
|
||||
UnallocateRomImage();
|
||||
m_ErrorMsg = EMPTY_STRING;
|
||||
|
||||
stdstr ext = CPath(FileLoc).GetExtension();
|
||||
bool Loaded7zFile = false;
|
||||
|
||||
if (strstr(FileLoc, "?") != NULL || _stricmp(ext.c_str(), "7z") == 0)
|
||||
{
|
||||
stdstr FullPath = FileLoc;
|
||||
|
||||
//this should be a 7zip file
|
||||
char * SubFile = strstr(const_cast<char*>(FullPath.c_str()), "?");
|
||||
if (SubFile == NULL)
|
||||
{
|
||||
//Pop up a dialog and select file
|
||||
//allocate memory for sub name and copy selected file name to var
|
||||
return false; //remove once dialog is done
|
||||
}
|
||||
else
|
||||
{
|
||||
*SubFile = '\0';
|
||||
SubFile += 1;
|
||||
}
|
||||
|
||||
C7zip ZipFile(FullPath.c_str());
|
||||
ZipFile.SetNotificationCallback((C7zip::LP7ZNOTIFICATION)NotificationCB, this);
|
||||
for (int i = 0; i < ZipFile.NumFiles(); i++)
|
||||
{
|
||||
CSzFileItem * f = ZipFile.FileItem(i);
|
||||
if (f->IsDir)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
stdstr ZipFileName;
|
||||
ZipFileName.FromUTF16(ZipFile.FileNameIndex(i).c_str());
|
||||
if (SubFile != NULL)
|
||||
{
|
||||
if (_stricmp(ZipFileName.c_str(), SubFile) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//Get the size of the rom and try to allocate the memory needed.
|
||||
uint32_t RomFileSize = (uint32_t)f->Size;
|
||||
//if loading boot code then just load the first 0x1000 bytes
|
||||
if (LoadBootCodeOnly) { RomFileSize = 0x1000; }
|
||||
|
||||
if (!AllocateRomImage(RomFileSize))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//Load the n64 rom to the allocated memory
|
||||
g_Notify->DisplayMessage(5, MSG_LOADING);
|
||||
if (!ZipFile.GetFile(i, m_ROMImage, RomFileSize))
|
||||
{
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidRomImage(m_ROMImage))
|
||||
{
|
||||
SetError(MSG_FAIL_IMAGE);
|
||||
return false;
|
||||
}
|
||||
g_Notify->DisplayMessage(5, MSG_BYTESWAP);
|
||||
ByteSwapRom();
|
||||
|
||||
//Protect the memory so that it can not be written to.
|
||||
ProtectMemory(m_ROMImage, m_RomFileSize, MEM_READONLY);
|
||||
Loaded7zFile = true;
|
||||
break;
|
||||
}
|
||||
if (!Loaded7zFile)
|
||||
{
|
||||
SetError(MSG_7Z_FILE_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Try to open the file as a zip file
|
||||
if (!Loaded7zFile)
|
||||
{
|
||||
if (!AllocateAndLoadZipImage(FileLoc, LoadBootCodeOnly))
|
||||
{
|
||||
if (m_ErrorMsg != EMPTY_STRING)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!AllocateAndLoadN64Image(FileLoc, LoadBootCodeOnly))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char RomName[260];
|
||||
int count;
|
||||
//Get the header from the rom image
|
||||
memcpy(&RomName[0], (void *)(m_ROMImage + 0x20), 20);
|
||||
for (count = 0; count < 20; count += 4)
|
||||
{
|
||||
RomName[count] ^= RomName[count + 3];
|
||||
RomName[count + 3] ^= RomName[count];
|
||||
RomName[count] ^= RomName[count + 3];
|
||||
RomName[count + 1] ^= RomName[count + 2];
|
||||
RomName[count + 2] ^= RomName[count + 1];
|
||||
RomName[count + 1] ^= RomName[count + 2];
|
||||
}
|
||||
|
||||
//truncate all the spaces at the end of the string
|
||||
for (count = 19; count >= 0; count--)
|
||||
{
|
||||
if (RomName[count] == ' ')
|
||||
{
|
||||
RomName[count] = '\0';
|
||||
}
|
||||
else if (RomName[count] == '\0')
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
count = -1;
|
||||
}
|
||||
}
|
||||
RomName[20] = '\0';
|
||||
if (strlen(RomName) == 0)
|
||||
{
|
||||
strcpy(RomName, CPath(FileLoc).GetName().c_str());
|
||||
}
|
||||
|
||||
//remove all /,\,: from the string
|
||||
for (count = 0; count < (int)strlen(RomName); count++)
|
||||
{
|
||||
switch (RomName[count])
|
||||
{
|
||||
case '/': case '\\': RomName[count] = '-'; break;
|
||||
case ':': RomName[count] = ';'; break;
|
||||
}
|
||||
}
|
||||
WriteTrace(TraceN64System, TraceDebug, "RomName %s", RomName);
|
||||
|
||||
m_RomName = RomName;
|
||||
m_FileName = FileLoc;
|
||||
m_MD5 = "";
|
||||
|
||||
if (!LoadBootCodeOnly)
|
||||
{
|
||||
//Calculate files MD5
|
||||
m_MD5 = MD5((const unsigned char *)m_ROMImage, m_RomFileSize).hex_digest();
|
||||
WriteTrace(TraceN64System, TraceDebug, "MD5: %s", m_MD5.c_str());
|
||||
}
|
||||
|
||||
m_Country = (Country)m_ROMImage[0x3D];
|
||||
m_RomIdent.Format("%08X-%08X-C:%X", *(uint32_t *)(&m_ROMImage[0x10]), *(uint32_t *)(&m_ROMImage[0x14]), m_ROMImage[0x3D]);
|
||||
WriteTrace(TraceN64System, TraceDebug, "Ident: %s", m_RomIdent.c_str());
|
||||
CalculateCicChip();
|
||||
|
||||
if (!LoadBootCodeOnly && g_DDRom == this)
|
||||
{
|
||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||
SaveRomSettingID(false);
|
||||
}
|
||||
|
||||
if (g_Settings->LoadBool(Game_CRC_Recalc))
|
||||
{
|
||||
//Calculate ROM Header CRC
|
||||
CalculateRomCrc();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//Save the settings of the loaded rom, so all loaded settings about rom will be identified with
|
||||
//this rom
|
||||
void CN64Rom::SaveRomSettingID(bool temp)
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
~CN64Rom();
|
||||
|
||||
bool LoadN64Image(const char * FileLoc, bool LoadBootCodeOnly = false);
|
||||
bool LoadN64ImageIPL(const char * FileLoc, bool LoadBootCodeOnly = false);
|
||||
static bool IsValidRomImage(uint8_t Test[4]);
|
||||
void SaveRomSettingID(bool temp);
|
||||
void ClearRomSettingID();
|
||||
|
|
|
@ -22,6 +22,7 @@ CNotification * g_Notify = NULL;
|
|||
CPlugins * g_Plugins = NULL;
|
||||
CN64Rom * g_Rom = NULL; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
CN64Rom * g_DDRom = NULL; //64DD IPL ROM
|
||||
CN64Disk * g_Disk = NULL; //64DD DISK
|
||||
CAudio * g_Audio = NULL;
|
||||
CSystemTimer * g_SystemTimer = NULL;
|
||||
CTransVaddr * g_TransVaddr = NULL;
|
||||
|
|
|
@ -37,6 +37,9 @@ class CN64Rom;
|
|||
extern CN64Rom * g_Rom; //The current rom that this system is executing.. it can only execute one file at the time
|
||||
extern CN64Rom * g_DDRom; //64DD IPL ROM
|
||||
|
||||
class CN64Disk;
|
||||
extern CN64Disk * g_Disk; //64DD DISK
|
||||
|
||||
class CAudio;
|
||||
extern CAudio * g_Audio;
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
<ClCompile Include="N64System\Mips\SystemTiming.cpp" />
|
||||
<ClCompile Include="N64System\Mips\TLBclass.cpp" />
|
||||
<ClCompile Include="N64System\N64Class.cpp" />
|
||||
<ClCompile Include="N64System\N64DiskClass.cpp" />
|
||||
<ClCompile Include="N64System\N64RomClass.cpp" />
|
||||
<ClCompile Include="N64System\ProfilingClass.cpp" />
|
||||
<ClCompile Include="N64System\Recompiler\CodeBlock.cpp" />
|
||||
|
@ -148,6 +149,7 @@
|
|||
<ClInclude Include="N64System\Mips\TLBClass.h" />
|
||||
<ClInclude Include="N64System\Mips\TranslateVaddr.h" />
|
||||
<ClInclude Include="N64System\N64Class.h" />
|
||||
<ClInclude Include="N64System\N64DiskClass.h" />
|
||||
<ClInclude Include="N64System\N64RomClass.h" />
|
||||
<ClInclude Include="N64System\N64Types.h" />
|
||||
<ClInclude Include="N64System\ProfilingClass.h" />
|
||||
|
|
|
@ -297,6 +297,9 @@
|
|||
<ClCompile Include="N64System\Mips\Disk.cpp">
|
||||
<Filter>Source Files\N64 System\Mips</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="N64System\N64DiskClass.cpp">
|
||||
<Filter>Source Files\N64 System</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
@ -578,5 +581,8 @@
|
|||
<ClInclude Include="N64System\Mips\Disk.h">
|
||||
<Filter>Header Files\N64 System\Mips</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64System\N64DiskClass.h">
|
||||
<Filter>Header Files\N64 System</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -224,6 +224,7 @@ enum SettingID
|
|||
//File Info
|
||||
File_RecentGameFileCount,
|
||||
File_RecentGameFileIndex,
|
||||
File_DiskIPLPath,
|
||||
|
||||
//Debugger
|
||||
Debugger_Enabled,
|
||||
|
|
|
@ -132,7 +132,7 @@ void CSettings::AddHowToHandleSetting()
|
|||
|
||||
AddHandler(Setting_RememberCheats, new CSettingTypeApplication("", "Remember Cheats", (uint32_t)false));
|
||||
AddHandler(Setting_CurrentLanguage, new CSettingTypeApplication("", "Current Language", ""));
|
||||
AddHandler(Setting_EnableDisk, new CSettingTypeApplication("", "Enable Disk", (uint32_t)false));
|
||||
AddHandler(Setting_EnableDisk, new CSettingTypeApplication("", "Enable Disk", (uint32_t)true));
|
||||
AddHandler(Setting_LanguageDirDefault, new CSettingTypeRelativePath("Lang", ""));
|
||||
AddHandler(Setting_LanguageDir, new CSettingTypeApplicationPath("Directory", "Lang", Setting_LanguageDirDefault));
|
||||
|
||||
|
@ -309,6 +309,7 @@ void CSettings::AddHowToHandleSetting()
|
|||
|
||||
AddHandler(File_RecentGameFileCount, new CSettingTypeApplication("", "Remembered Rom Files", (uint32_t)10));
|
||||
AddHandler(File_RecentGameFileIndex, new CSettingTypeApplicationIndex("Recent File", "Recent Rom", Default_None));
|
||||
AddHandler(File_DiskIPLPath, new CSettingTypeApplicationPath("", "Disk IPL ROM Path", Default_None));
|
||||
|
||||
AddHandler(Debugger_Enabled, new CSettingTypeApplication("Debugger", "Debugger", false));
|
||||
AddHandler(Debugger_ShowTLBMisses, new CSettingTypeApplication("Debugger", "Show TLB Misses", false));
|
||||
|
|
|
@ -979,6 +979,67 @@ LRESULT CALLBACK CMainGui::MainGui_Proc(HWND hWnd, DWORD uMsg, DWORD wParam, DWO
|
|||
|
||||
switch (LOWORD(wParam)) {
|
||||
case ID_POPUPMENU_PLAYGAME: g_BaseSystem->RunFileImage(_this->CurrentedSelectedRom()); break;
|
||||
case ID_POPUPMENU_PLAYGAMEWITHDISK:
|
||||
{
|
||||
stdstr IPLROM = g_Settings->LoadStringVal(File_DiskIPLPath);
|
||||
if ((IPLROM.length() <= 0) || (!g_BaseSystem->RunFileImageIPL(IPLROM.c_str())))
|
||||
{
|
||||
// Open DDROM
|
||||
OPENFILENAME openfilename;
|
||||
char FileName[_MAX_PATH], Directory[_MAX_PATH];
|
||||
|
||||
memset(&FileName, 0, sizeof(FileName));
|
||||
memset(&openfilename, 0, sizeof(openfilename));
|
||||
|
||||
strcpy(Directory, g_Settings->LoadStringVal(Directory_Game).c_str());
|
||||
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)hWnd;
|
||||
openfilename.lpstrFilter = "64DD IPL ROM Image (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFile = FileName;
|
||||
openfilename.lpstrInitialDir = Directory;
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
if (GetOpenFileName(&openfilename))
|
||||
{
|
||||
g_BaseSystem->RunFileImageIPL(FileName);
|
||||
// Open Disk
|
||||
openfilename.lpstrFilter = "N64DD Disk Image (*.ndd)\0*.ndd\0All files (*.*)\0*.*\0";
|
||||
if (GetOpenFileName(&openfilename))
|
||||
{
|
||||
if (g_BaseSystem->RunDiskImage(FileName))
|
||||
g_BaseSystem->RunFileImage(_this->CurrentedSelectedRom());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open Disk
|
||||
OPENFILENAME openfilename;
|
||||
char FileName[_MAX_PATH], Directory[_MAX_PATH];
|
||||
|
||||
memset(&FileName, 0, sizeof(FileName));
|
||||
memset(&openfilename, 0, sizeof(openfilename));
|
||||
|
||||
strcpy(Directory, g_Settings->LoadStringVal(Directory_Game).c_str());
|
||||
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)hWnd;
|
||||
openfilename.lpstrFilter = "N64DD Disk Image (*.ndd)\0*.ndd\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFile = FileName;
|
||||
openfilename.lpstrInitialDir = Directory;
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
if (GetOpenFileName(&openfilename))
|
||||
{
|
||||
if (g_BaseSystem->RunDiskImage(FileName))
|
||||
g_BaseSystem->RunFileImage(_this->CurrentedSelectedRom());
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ID_POPUPMENU_ROMDIRECTORY: _this->SelectRomDir(); break;
|
||||
case ID_POPUPMENU_REFRESHROMLIST: _this->RefreshRomBrowser(); break;
|
||||
case ID_POPUPMENU_ROMINFORMATION:
|
||||
|
@ -1081,7 +1142,43 @@ LRESULT CALLBACK CMainGui::MainGui_Proc(HWND hWnd, DWORD uMsg, DWORD wParam, DWO
|
|||
DragQueryFile(hDrop, 0, filename, sizeof(filename));
|
||||
DragFinish(hDrop);
|
||||
|
||||
CN64System::RunFileImage(filename);
|
||||
stdstr ext = CPath(filename).GetExtension();
|
||||
if (!(_stricmp(ext.c_str(), "ndd") == 0))
|
||||
{
|
||||
delete g_DDRom;
|
||||
g_DDRom = NULL;
|
||||
CN64System::RunFileImage(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open Disk
|
||||
if (CN64System::RunDiskImage(filename))
|
||||
{
|
||||
stdstr IPLROM = g_Settings->LoadStringVal(File_DiskIPLPath);
|
||||
if ((IPLROM.length() <= 0) || (!CN64System::RunFileImage(IPLROM.c_str())))
|
||||
{
|
||||
// Open DDROM
|
||||
OPENFILENAME openfilename;
|
||||
char FileName[_MAX_PATH], Directory[_MAX_PATH];
|
||||
memset(&FileName, 0, sizeof(FileName));
|
||||
memset(&openfilename, 0, sizeof(openfilename));
|
||||
|
||||
strcpy(Directory, g_Settings->LoadStringVal(Directory_Game).c_str());
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)hWnd;
|
||||
openfilename.lpstrFilter = "64DD IPL ROM Image (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFile = FileName;
|
||||
openfilename.lpstrInitialDir = Directory;
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
if (GetOpenFileName(&openfilename))
|
||||
{
|
||||
CN64System::RunFileImage(FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
|
|
|
@ -92,7 +92,7 @@ stdstr CMainMenu::ChooseFileToOpen(HWND hParent)
|
|||
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)hParent;
|
||||
openfilename.lpstrFilter = "N64 ROMs (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFilter = "N64 ROMs (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin, *.ndd)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal;*.ndd\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFile = FileName;
|
||||
openfilename.lpstrInitialDir = Directory;
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
|
@ -119,7 +119,44 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
|
|||
stdstr File = ChooseFileToOpen(hWnd);
|
||||
if (File.length() > 0)
|
||||
{
|
||||
g_BaseSystem->RunFileImage(File.c_str());
|
||||
stdstr ext = CPath(File).GetExtension();
|
||||
if (!(_stricmp(ext.c_str(), "ndd") == 0))
|
||||
{
|
||||
delete g_DDRom;
|
||||
g_DDRom = NULL;
|
||||
g_BaseSystem->RunFileImage(File.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open Disk
|
||||
if (g_BaseSystem->RunDiskImage(File.c_str()))
|
||||
{
|
||||
stdstr IPLROM = g_Settings->LoadStringVal(File_DiskIPLPath);
|
||||
if ((IPLROM.length() <= 0) || (!g_BaseSystem->RunFileImage(IPLROM.c_str())))
|
||||
{
|
||||
// Open DDROM
|
||||
OPENFILENAME openfilename;
|
||||
char FileName[_MAX_PATH], Directory[_MAX_PATH];
|
||||
memset(&FileName, 0, sizeof(FileName));
|
||||
memset(&openfilename, 0, sizeof(openfilename));
|
||||
|
||||
strcpy(Directory, g_Settings->LoadStringVal(Directory_Game).c_str());
|
||||
openfilename.lStructSize = sizeof(openfilename);
|
||||
openfilename.hwndOwner = (HWND)hWnd;
|
||||
openfilename.lpstrFilter = "64DD IPL ROM Image (*.zip, *.7z, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.7z;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0";
|
||||
openfilename.lpstrFile = FileName;
|
||||
openfilename.lpstrInitialDir = Directory;
|
||||
openfilename.nMaxFile = MAX_PATH;
|
||||
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
if (GetOpenFileName(&openfilename))
|
||||
{
|
||||
g_BaseSystem->RunFileImage(FileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1472,6 +1472,10 @@ void CRomBrowser::RomList_OpenRom(uint32_t /*pnmh*/)
|
|||
|
||||
if (!pRomInfo) { return; }
|
||||
m_StopRefresh = true;
|
||||
|
||||
delete g_DDRom;
|
||||
g_DDRom = NULL;
|
||||
|
||||
CN64System::RunFileImage(pRomInfo->szFullFileName);
|
||||
}
|
||||
|
||||
|
@ -1502,21 +1506,23 @@ void CRomBrowser::RomList_PopupMenu(uint32_t /*pnmh*/)
|
|||
|
||||
//Fix up menu
|
||||
MenuSetText(hPopupMenu, 0, wGS(POPUP_PLAY).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 2, wGS(MENU_REFRESH).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 3, wGS(MENU_CHOOSE_ROM).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 5, wGS(POPUP_INFO).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 6, wGS(POPUP_GFX_PLUGIN).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 8, wGS(POPUP_SETTINGS).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 9, wGS(POPUP_CHEATS).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 1, wGS(POPUP_PLAYDISK).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 3, wGS(MENU_REFRESH).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 4, wGS(MENU_CHOOSE_ROM).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 6, wGS(POPUP_INFO).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 7, wGS(POPUP_GFX_PLUGIN).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 9, wGS(POPUP_SETTINGS).c_str(), NULL);
|
||||
MenuSetText(hPopupMenu, 10, wGS(POPUP_CHEATS).c_str(), NULL);
|
||||
|
||||
if (m_SelectedRom.size() == 0)
|
||||
{
|
||||
DeleteMenu(hPopupMenu, 10, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 9, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 8, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 7, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 6, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 5, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 4, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 2, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 1, MF_BYPOSITION);
|
||||
DeleteMenu(hPopupMenu, 0, MF_BYPOSITION);
|
||||
}
|
||||
|
@ -1524,17 +1530,17 @@ void CRomBrowser::RomList_PopupMenu(uint32_t /*pnmh*/)
|
|||
{
|
||||
bool inBasicMode = g_Settings->LoadDword(UserInterface_BasicMode) != 0;
|
||||
bool CheatsRemembered = g_Settings->LoadDword(Setting_RememberCheats) != 0;
|
||||
if (!CheatsRemembered) { DeleteMenu(hPopupMenu, 9, MF_BYPOSITION); }
|
||||
if (inBasicMode) { DeleteMenu(hPopupMenu, 8, MF_BYPOSITION); }
|
||||
if (inBasicMode && !CheatsRemembered) { DeleteMenu(hPopupMenu, 7, MF_BYPOSITION); }
|
||||
DeleteMenu(hPopupMenu, 6, MF_BYPOSITION);
|
||||
if (!CheatsRemembered) { DeleteMenu(hPopupMenu, 10, MF_BYPOSITION); }
|
||||
if (inBasicMode) { DeleteMenu(hPopupMenu, 9, MF_BYPOSITION); }
|
||||
if (inBasicMode && !CheatsRemembered) { DeleteMenu(hPopupMenu, 8, MF_BYPOSITION); }
|
||||
DeleteMenu(hPopupMenu, 7, MF_BYPOSITION);
|
||||
if (!inBasicMode && g_Plugins && g_Plugins->Gfx() && g_Plugins->Gfx()->GetRomBrowserMenu != NULL)
|
||||
{
|
||||
HMENU GfxMenu = (HMENU)g_Plugins->Gfx()->GetRomBrowserMenu();
|
||||
if (GfxMenu)
|
||||
{
|
||||
MENUITEMINFO lpmii;
|
||||
InsertMenuW(hPopupMenu, 6, MF_POPUP | MF_BYPOSITION, (uint32_t)GfxMenu, wGS(POPUP_GFX_PLUGIN).c_str());
|
||||
InsertMenuW(hPopupMenu, 7, MF_POPUP | MF_BYPOSITION, (uint32_t)GfxMenu, wGS(POPUP_GFX_PLUGIN).c_str());
|
||||
lpmii.cbSize = sizeof(MENUITEMINFO);
|
||||
lpmii.fMask = MIIM_STATE;
|
||||
lpmii.fState = 0;
|
||||
|
|
|
@ -895,6 +895,7 @@ BEGIN
|
|||
POPUP "PopupMenu"
|
||||
BEGIN
|
||||
MENUITEM "Play Game", ID_POPUPMENU_PLAYGAME
|
||||
MENUITEM "Play Game with Disk", ID_POPUPMENU_PLAYGAMEWITHDISK
|
||||
MENUITEM SEPARATOR
|
||||
MENUITEM "Refresh Rom List", ID_POPUPMENU_REFRESHROMLIST
|
||||
MENUITEM "Choose Rom Directory...", ID_POPUPMENU_ROMDIRECTORY
|
||||
|
|
|
@ -329,6 +329,7 @@
|
|||
#define IDC_NOTES_TEXT 1208
|
||||
#define IDC_LANG_SEL 1219
|
||||
#define ID_POPUP_SHOWINMEMORYVIEWER 40005
|
||||
#define ID_POPUPMENU_PLAYGAMEWITHDISK 40008
|
||||
#define ID_POPUPMENU_ROMDIRECTORY 40137
|
||||
#define ID_POPUPMENU_REFRESHROMLIST 40138
|
||||
#define ID_POPUPMENU_PLAYGAME 40152
|
||||
|
@ -344,7 +345,7 @@
|
|||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 150
|
||||
#define _APS_NEXT_COMMAND_VALUE 40008
|
||||
#define _APS_NEXT_COMMAND_VALUE 40009
|
||||
#define _APS_NEXT_CONTROL_VALUE 1100
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue