Merge pull request #1098 from LuigiBlood/64ddsave
[64DD] Add disk saving support & swapping
This commit is contained in:
commit
6256e44ce4
|
@ -81,6 +81,7 @@ enum LanguageStringID
|
||||||
MENU_RESUME = 132,
|
MENU_RESUME = 132,
|
||||||
MENU_RESET_SOFT = 133, //added in build 1.7.50
|
MENU_RESET_SOFT = 133, //added in build 1.7.50
|
||||||
MENU_RESET_HARD = 134, //added in build 1.7.50
|
MENU_RESET_HARD = 134, //added in build 1.7.50
|
||||||
|
MENU_SWAPDISK = 135, //added in build 2.2.????
|
||||||
|
|
||||||
//Options Menu
|
//Options Menu
|
||||||
MENU_OPTIONS = 140,
|
MENU_OPTIONS = 140,
|
||||||
|
|
|
@ -88,6 +88,7 @@ void CLanguage::LoadDefaultStrings(void)
|
||||||
DEF_STR(MENU_RESUME, "R&esume");
|
DEF_STR(MENU_RESUME, "R&esume");
|
||||||
DEF_STR(MENU_RESET_SOFT, "&Soft Reset");
|
DEF_STR(MENU_RESET_SOFT, "&Soft Reset");
|
||||||
DEF_STR(MENU_RESET_HARD, "&Hard Reset");
|
DEF_STR(MENU_RESET_HARD, "&Hard Reset");
|
||||||
|
DEF_STR(MENU_SWAPDISK, "Swap &Disk");
|
||||||
|
|
||||||
//Options Menu
|
//Options Menu
|
||||||
DEF_STR(MENU_OPTIONS, "&Options");
|
DEF_STR(MENU_OPTIONS, "&Options");
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint8_t dd_swapdelay;
|
||||||
|
|
||||||
bool dd_write;
|
bool dd_write;
|
||||||
bool dd_reset_hold;
|
bool dd_reset_hold;
|
||||||
uint32_t dd_track_offset, dd_zone;
|
uint32_t dd_track_offset, dd_zone;
|
||||||
|
@ -29,11 +31,9 @@ uint32_t dd_start_block, dd_current;
|
||||||
|
|
||||||
void DiskCommand()
|
void DiskCommand()
|
||||||
{
|
{
|
||||||
if (g_Disk != NULL)
|
|
||||||
g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES;
|
|
||||||
|
|
||||||
//ASIC_CMD_STATUS - Commands
|
//ASIC_CMD_STATUS - Commands
|
||||||
uint32_t cmd = g_Reg->ASIC_CMD;
|
uint32_t cmd = g_Reg->ASIC_CMD;
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "DD CMD %08X", cmd);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SYSTEMTIME sysTime;
|
SYSTEMTIME sysTime;
|
||||||
|
@ -81,7 +81,9 @@ void DiskCommand()
|
||||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break;
|
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG; break;
|
||||||
case 0x00090000:
|
case 0x00090000:
|
||||||
//Unset Reset Bit
|
//Unset Reset Bit
|
||||||
g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE; break;
|
g_Reg->ASIC_STATUS &= ~DD_STATUS_RST_STATE;
|
||||||
|
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_CHNG;
|
||||||
|
break;
|
||||||
case 0x00120000:
|
case 0x00120000:
|
||||||
//RTC Get Year & Month
|
//RTC Get Year & Month
|
||||||
g_Reg->ASIC_DATA = (year << 24) | (month << 16); break;
|
g_Reg->ASIC_DATA = (year << 24) | (month << 16); break;
|
||||||
|
@ -100,7 +102,11 @@ void DiskCommand()
|
||||||
void DiskReset(void)
|
void DiskReset(void)
|
||||||
{
|
{
|
||||||
//ASIC_HARD_RESET 0xAAAA0000
|
//ASIC_HARD_RESET 0xAAAA0000
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "DD RESET");
|
||||||
g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE;
|
g_Reg->ASIC_STATUS |= DD_STATUS_RST_STATE;
|
||||||
|
dd_swapdelay = 0;
|
||||||
|
if (g_Disk != NULL)
|
||||||
|
g_Reg->ASIC_STATUS |= DD_STATUS_DISK_PRES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskBMControl(void)
|
void DiskBMControl(void)
|
||||||
|
@ -159,6 +165,17 @@ void DiskGapSectorCheck()
|
||||||
DiskBMUpdate();
|
DiskBMUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(g_Reg->ASIC_STATUS & DD_STATUS_DISK_PRES) && g_Disk != NULL && g_Settings->LoadBool(GameRunning_LoadingInProgress) == false)
|
||||||
|
{
|
||||||
|
dd_swapdelay++;
|
||||||
|
if (dd_swapdelay >= 50)
|
||||||
|
{
|
||||||
|
g_Reg->ASIC_STATUS |= (DD_STATUS_DISK_PRES | DD_STATUS_DISK_CHNG);
|
||||||
|
dd_swapdelay = 0;
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "DD SWAP DONE");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiskBMUpdate()
|
void DiskBMUpdate()
|
||||||
|
@ -245,7 +262,7 @@ void DiskBMRead()
|
||||||
sector += dd_track_offset;
|
sector += dd_track_offset;
|
||||||
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||||
sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1);
|
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);
|
//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);
|
g_Disk->SetDiskAddressBuffer(sector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +273,7 @@ void DiskBMWrite()
|
||||||
sector += dd_track_offset;
|
sector += dd_track_offset;
|
||||||
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
sector += dd_start_block * SECTORS_PER_BLOCK * ddZoneSecSize[dd_zone];
|
||||||
sector += (dd_current) * (((g_Reg->ASIC_HOST_SECBYTE & 0x00FF0000) >> 16) + 1);
|
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);
|
//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);
|
g_Disk->SetDiskAddressBuffer(sector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,6 +385,13 @@ bool CN64System::EmulationStarting(CThread * thread)
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Game starting");
|
WriteTrace(TraceN64System, TraceDebug, "Game starting");
|
||||||
g_BaseSystem->StartEmulation2(false);
|
g_BaseSystem->StartEmulation2(false);
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Game Done");
|
WriteTrace(TraceN64System, TraceDebug, "Game Done");
|
||||||
|
//PLACE TO ADD 64DD SAVING CODE
|
||||||
|
if (g_Disk != NULL)
|
||||||
|
{
|
||||||
|
g_Disk->SaveDiskImage();
|
||||||
|
//g_Notify->DisplayError(g_Disk->GetError());
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "64DD Save Done");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
@ -411,11 +418,11 @@ void CN64System::StartEmulation2(bool NewThread)
|
||||||
StartLog();
|
StartLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Setting up system");
|
WriteTrace(TraceN64System, TraceDebug, "Setting up system");
|
||||||
CInterpreterCPU::BuildCPU();
|
CInterpreterCPU::BuildCPU();
|
||||||
|
|
||||||
uint32_t CpuType = g_Settings->LoadDword(Game_CpuType);
|
uint32_t CpuType = g_Settings->LoadDword(Game_CpuType);
|
||||||
WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType);
|
WriteTrace(TraceN64System, TraceDebug, "CpuType = %d",CpuType);
|
||||||
if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled))
|
if (CpuType == CPU_SyncCores && !g_Settings->LoadBool(Debugger_Enabled))
|
||||||
{
|
{
|
||||||
g_Settings->SaveDword(Game_CpuType, CPU_Recompiler);
|
g_Settings->SaveDword(Game_CpuType, CPU_Recompiler);
|
||||||
|
@ -440,7 +447,7 @@ void CN64System::StartEmulation2(bool NewThread)
|
||||||
m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation);
|
m_Recomp = new CRecompiler(m_Reg, m_Profile, m_EndEmulation);
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Setting system as active");
|
WriteTrace(TraceN64System, TraceDebug, "Setting system as active");
|
||||||
bool bSetActive = true;
|
bool bSetActive = true;
|
||||||
if (m_SyncCPU)
|
if (m_SyncCPU)
|
||||||
{
|
{
|
||||||
|
@ -454,13 +461,13 @@ void CN64System::StartEmulation2(bool NewThread)
|
||||||
|
|
||||||
if (!bSetActive)
|
if (!bSetActive)
|
||||||
{
|
{
|
||||||
WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active");
|
WriteTrace(TraceN64System, TraceWarning, "Failed to set system as active");
|
||||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||||
g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT);
|
g_Notify->DisplayError(MSG_PLUGIN_NOT_INIT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread");
|
WriteTrace(TraceN64System, TraceDebug, "Starting emulation thread");
|
||||||
StartEmulationThead();
|
StartEmulationThead();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -468,10 +475,10 @@ void CN64System::StartEmulation2(bool NewThread)
|
||||||
{
|
{
|
||||||
//mark the emulation as starting and fix up menus
|
//mark the emulation as starting and fix up menus
|
||||||
g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED);
|
g_Notify->DisplayMessage(5, MSG_EMULATION_STARTED);
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU");
|
WriteTrace(TraceN64System, TraceDebug, "Start Executing CPU");
|
||||||
ExecuteCPU();
|
ExecuteCPU();
|
||||||
}
|
}
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Done");
|
WriteTrace(TraceN64System, TraceDebug, "Done");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CN64System::StartEmulation(bool NewThread)
|
void CN64System::StartEmulation(bool NewThread)
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "SystemGlobals.h"
|
#include "SystemGlobals.h"
|
||||||
#include <Common/Platform.h>
|
#include <Common/Platform.h>
|
||||||
#include <Common/MemoryManagement.h>
|
#include <Common/MemoryManagement.h>
|
||||||
|
#include <Project64-core/N64System/Mips/RegisterClass.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
CN64Disk::CN64Disk() :
|
CN64Disk::CN64Disk() :
|
||||||
|
@ -31,9 +32,21 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc)
|
||||||
{
|
{
|
||||||
UnallocateDiskImage();
|
UnallocateDiskImage();
|
||||||
|
|
||||||
if (!AllocateAndLoadDiskImage(FileLoc))
|
//Assume the file extension is *.ndd (it is the only case where it is loaded)
|
||||||
|
stdstr ShadowFile = FileLoc;
|
||||||
|
ShadowFile[ShadowFile.length() - 1] = 'r';
|
||||||
|
|
||||||
|
g_Settings->SaveBool(GameRunning_LoadingInProgress, true);
|
||||||
|
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Attempt to load shadow file.");
|
||||||
|
if (!AllocateAndLoadDiskImage(ShadowFile.c_str()))
|
||||||
{
|
{
|
||||||
return false;
|
WriteTrace(TraceN64System, TraceDebug, "Loading Shadow file failed");
|
||||||
|
UnallocateDiskImage();
|
||||||
|
if (!AllocateAndLoadDiskImage(FileLoc))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_Disk == this)
|
if (g_Disk == this)
|
||||||
|
@ -41,9 +54,64 @@ bool CN64Disk::LoadDiskImage(const char * FileLoc)
|
||||||
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
g_Settings->SaveBool(GameRunning_LoadingInProgress, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_FileName = FileLoc;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CN64Disk::SaveDiskImage()
|
||||||
|
{
|
||||||
|
//NO NEED TO SAVE IF DISK TYPE IS 6
|
||||||
|
uint8_t disktype = m_DiskImage[5] & 0xF;
|
||||||
|
if (disktype == 0x6)
|
||||||
|
{
|
||||||
|
m_DiskFile.Close();
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Loaded Disk Type is 0x7. No RAM area. Shadow file is not needed.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Assume the file extension is *.ndd (it is the only case where it is loaded)
|
||||||
|
stdstr ShadowFile = m_FileName;
|
||||||
|
ShadowFile[ShadowFile.length() - 1] = 'r';
|
||||||
|
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Trying to open %s (Shadow File)", ShadowFile.c_str());
|
||||||
|
m_DiskFile.Close();
|
||||||
|
if (!m_DiskFile.Open(ShadowFile.c_str(), CFileBase::modeWrite | CFileBase::modeCreate))
|
||||||
|
{
|
||||||
|
WriteTrace(TraceN64System, TraceError, "Failed to open %s (Shadow File)", ShadowFile.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_DiskFile.SeekToBegin();
|
||||||
|
ForceByteSwapDisk();
|
||||||
|
|
||||||
|
if (m_DiskFormat == DiskFormatMAME)
|
||||||
|
{
|
||||||
|
//If original file was MAME format, just copy
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "64DD disk is MAME format");
|
||||||
|
if (!m_DiskFile.Write(m_DiskImage, MameFormatSize))
|
||||||
|
{
|
||||||
|
m_DiskFile.Close();
|
||||||
|
WriteTrace(TraceN64System, TraceError, "Failed to write file");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_DiskFormat == DiskFormatSDK)
|
||||||
|
{
|
||||||
|
//If original file was SDK format, we need to convert it back
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "64DD disk is SDK format");
|
||||||
|
ConvertDiskFormatBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_DiskFile.Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CN64Disk::SwapDiskImage(const char * FileLoc)
|
||||||
|
{
|
||||||
|
g_Reg->ASIC_STATUS &= ~DD_STATUS_DISK_PRES;
|
||||||
|
LoadDiskImage(FileLoc);
|
||||||
|
}
|
||||||
|
|
||||||
bool CN64Disk::IsValidDiskImage(uint8_t Test[4])
|
bool CN64Disk::IsValidDiskImage(uint8_t Test[4])
|
||||||
{
|
{
|
||||||
if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; }
|
if (*((uint32_t *)&Test[0]) == 0x16D348E8) { return true; }
|
||||||
|
@ -101,6 +169,7 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
|
||||||
if (DiskFileSize == MameFormatSize)
|
if (DiskFileSize == MameFormatSize)
|
||||||
{
|
{
|
||||||
//If Disk is MAME Format (size is constant, it should be the same for every file), then continue
|
//If Disk is MAME Format (size is constant, it should be the same for every file), then continue
|
||||||
|
m_DiskFormat = DiskFormatMAME;
|
||||||
WriteTrace(TraceN64System, TraceDebug, "Disk File is MAME Format");
|
WriteTrace(TraceN64System, TraceDebug, "Disk File is MAME Format");
|
||||||
|
|
||||||
if (!AllocateDiskImage(DiskFileSize))
|
if (!AllocateDiskImage(DiskFileSize))
|
||||||
|
@ -144,6 +213,8 @@ bool CN64Disk::AllocateAndLoadDiskImage(const char * FileLoc)
|
||||||
{
|
{
|
||||||
//If Disk is SDK format (made with SDK based dumpers like LuigiBlood's, or Nintendo's, size is also constant)
|
//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.
|
//We need to convert it.
|
||||||
|
m_DiskFormat = DiskFormatSDK;
|
||||||
|
|
||||||
g_Notify->DisplayMessage(5, MSG_LOADING);
|
g_Notify->DisplayMessage(5, MSG_LOADING);
|
||||||
|
|
||||||
//Allocate supported size
|
//Allocate supported size
|
||||||
|
@ -193,6 +264,21 @@ void CN64Disk::ByteSwapDisk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CN64Disk::ForceByteSwapDisk()
|
||||||
|
{
|
||||||
|
uint32_t count;
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CN64Disk::SetError(LanguageStringID ErrorMsg)
|
void CN64Disk::SetError(LanguageStringID ErrorMsg)
|
||||||
{
|
{
|
||||||
m_ErrorMsg = ErrorMsg;
|
m_ErrorMsg = ErrorMsg;
|
||||||
|
@ -354,4 +440,178 @@ void CN64Disk::ConvertDiskFormat()
|
||||||
OutOffset += BLOCKSIZE(zone);
|
OutOffset += BLOCKSIZE(zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CN64Disk::ConvertDiskFormatBack()
|
||||||
|
{
|
||||||
|
//Original code by Happy_
|
||||||
|
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];
|
||||||
|
|
||||||
|
//SDK DISK RAM
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Allocating memory for disk SDK format");
|
||||||
|
std::auto_ptr<uint8_t> ImageBase(new uint8_t[SDKFormatSize + 0x1000]);
|
||||||
|
if (ImageBase.get() == NULL)
|
||||||
|
{
|
||||||
|
SetError(MSG_MEM_ALLOC_ERROR);
|
||||||
|
WriteTrace(TraceN64System, TraceError, "Failed to allocate memory for disk SDK format (size: 0x%X)", SDKFormatSize);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint8_t * Image = (uint8_t *)(((uint64_t)ImageBase.get() + 0xFFF) & ~0xFFF); // start at begining of memory page
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Allocated disk SDK format memory (%p)", Image);
|
||||||
|
|
||||||
|
//save information about the disk loaded
|
||||||
|
uint8_t * s_DiskImageBase = ImageBase.release();
|
||||||
|
uint8_t * s_DiskImage = Image;
|
||||||
|
//END
|
||||||
|
|
||||||
|
InStart[0] = 0;
|
||||||
|
OutStart[0] = 0;
|
||||||
|
|
||||||
|
//Read System Area
|
||||||
|
memcpy(&SystemData, m_DiskImage, 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++)
|
||||||
|
{
|
||||||
|
block = StartBlock[disktype][zone];
|
||||||
|
atrack = 0;
|
||||||
|
for (track = 0; track < ZoneTracks[zone]; track++)
|
||||||
|
{
|
||||||
|
InOffset = OutStart[zone] + (track)* TRACKSIZE(zone);
|
||||||
|
OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - atrack) * TRACKSIZE(zone);
|
||||||
|
|
||||||
|
if (atrack < 0xC && track == SystemData[0x20 + zone * 0xC + atrack])
|
||||||
|
{
|
||||||
|
atrack += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((block % 2) == 1)
|
||||||
|
{
|
||||||
|
memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
block = 1 - block;
|
||||||
|
memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone));
|
||||||
|
OutOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone));
|
||||||
|
OutOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Copy Head 1
|
||||||
|
for (zone = 8; zone < 16; zone++)
|
||||||
|
{
|
||||||
|
block = StartBlock[disktype][zone];
|
||||||
|
atrack = 0xB;
|
||||||
|
for (track = 1; track < ZoneTracks[zone] + 1; track++)
|
||||||
|
{
|
||||||
|
InOffset = OutStart[zone] + (ZoneTracks[zone] - track) * TRACKSIZE(zone);
|
||||||
|
OutOffset = InStart[RevDiskTypeZones[disktype][zone]] + (track - (0xB - atrack) - 1) * TRACKSIZE(zone);
|
||||||
|
|
||||||
|
if (atrack > -1 && (ZoneTracks[zone] - track) == SystemData[0x20 + (zone)* 0xC + atrack])
|
||||||
|
{
|
||||||
|
atrack -= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((block % 2) == 1)
|
||||||
|
{
|
||||||
|
memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(&BlockData0, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(&BlockData1, m_DiskImage + InOffset, BLOCKSIZE(zone));
|
||||||
|
InOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
block = 1 - block;
|
||||||
|
memcpy(s_DiskImage + OutOffset, &BlockData0, BLOCKSIZE(zone));
|
||||||
|
OutOffset += BLOCKSIZE(zone);
|
||||||
|
memcpy(s_DiskImage + OutOffset, &BlockData1, BLOCKSIZE(zone));
|
||||||
|
OutOffset += BLOCKSIZE(zone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_DiskFile.Write(s_DiskImage, SDKFormatSize))
|
||||||
|
{
|
||||||
|
m_DiskFile.Close();
|
||||||
|
WriteTrace(TraceN64System, TraceError, "Failed to write file");
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteTrace(TraceN64System, TraceDebug, "Unallocating disk SDK format memory");
|
||||||
|
delete[] s_DiskImageBase;
|
||||||
|
s_DiskImageBase = NULL;
|
||||||
|
s_DiskImage = NULL;
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@ public:
|
||||||
~CN64Disk();
|
~CN64Disk();
|
||||||
|
|
||||||
bool LoadDiskImage(const char * FileLoc);
|
bool LoadDiskImage(const char * FileLoc);
|
||||||
|
bool SaveDiskImage();
|
||||||
|
void SwapDiskImage(const char * FileLoc);
|
||||||
static bool IsValidDiskImage(uint8_t Test[4]);
|
static bool IsValidDiskImage(uint8_t Test[4]);
|
||||||
uint8_t * GetDiskAddress() { return m_DiskImage; }
|
uint8_t * GetDiskAddress() { return m_DiskImage; }
|
||||||
uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; }
|
uint8_t * GetDiskAddressBuffer() { return m_DiskImage + m_DiskBufAddress; }
|
||||||
|
@ -30,11 +32,14 @@ private:
|
||||||
bool AllocateDiskImage(uint32_t DiskFileSize);
|
bool AllocateDiskImage(uint32_t DiskFileSize);
|
||||||
bool AllocateAndLoadDiskImage(const char * FileLoc);
|
bool AllocateAndLoadDiskImage(const char * FileLoc);
|
||||||
void ByteSwapDisk();
|
void ByteSwapDisk();
|
||||||
|
void ForceByteSwapDisk();
|
||||||
void SetError(LanguageStringID ErrorMsg);
|
void SetError(LanguageStringID ErrorMsg);
|
||||||
void ConvertDiskFormat();
|
void ConvertDiskFormat();
|
||||||
|
void ConvertDiskFormatBack();
|
||||||
|
|
||||||
//constant values
|
//constant values
|
||||||
enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800 };
|
enum { ReadFromRomSection = 0x400000, MameFormatSize = 0x0435B0C0, SDKFormatSize = 0x03DEC800,
|
||||||
|
DiskFormatMAME = 0x0, DiskFormatSDK = 0x1 };
|
||||||
|
|
||||||
//class variables
|
//class variables
|
||||||
CFile m_DiskFile;
|
CFile m_DiskFile;
|
||||||
|
@ -44,6 +49,7 @@ private:
|
||||||
uint32_t m_DiskBufAddress;
|
uint32_t m_DiskBufAddress;
|
||||||
LanguageStringID m_ErrorMsg;
|
LanguageStringID m_ErrorMsg;
|
||||||
stdstr m_FileName, m_DiskIdent;
|
stdstr m_FileName, m_DiskIdent;
|
||||||
|
uint8_t m_DiskFormat; //0 = MAME, 1 = SDK
|
||||||
|
|
||||||
//disk convert
|
//disk convert
|
||||||
#define SECTORS_PER_BLOCK 85
|
#define SECTORS_PER_BLOCK 85
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "RomInformationClass.h"
|
#include "RomInformationClass.h"
|
||||||
|
#include <Project64-core/N64System/N64DiskClass.h>
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commdlg.h>
|
#include <commdlg.h>
|
||||||
|
@ -229,6 +230,31 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
|
||||||
g_Settings->SaveBool(GameRunning_LimitFPS, !g_Settings->LoadBool(GameRunning_LimitFPS));
|
g_Settings->SaveBool(GameRunning_LimitFPS, !g_Settings->LoadBool(GameRunning_LimitFPS));
|
||||||
WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_LIMITFPS 1");
|
WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_LIMITFPS 1");
|
||||||
break;
|
break;
|
||||||
|
case ID_SYSTEM_SWAPDISK:
|
||||||
|
WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SWAPDISK");
|
||||||
|
// 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(RomList_GameDir).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))
|
||||||
|
{
|
||||||
|
g_Disk->SaveDiskImage();
|
||||||
|
g_Disk->SwapDiskImage(FileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ID_SYSTEM_SAVE:
|
case ID_SYSTEM_SAVE:
|
||||||
WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SAVE");
|
WriteTrace(TraceUserInterface, TraceDebug, "ID_SYSTEM_SAVE");
|
||||||
g_BaseSystem->ExternalEvent(SysEvent_SaveMachineState);
|
g_BaseSystem->ExternalEvent(SysEvent_SaveMachineState);
|
||||||
|
@ -868,6 +894,10 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
|
||||||
SystemMenu.push_back(Item);
|
SystemMenu.push_back(Item);
|
||||||
SystemMenu.push_back(MENU_ITEM(SPLITER));
|
SystemMenu.push_back(MENU_ITEM(SPLITER));
|
||||||
}
|
}
|
||||||
|
Item.Reset(ID_SYSTEM_SWAPDISK, MENU_SWAPDISK, m_ShortCuts.ShortCutString(ID_SYSTEM_SWAPDISK, AccessLevel));
|
||||||
|
if (g_Disk == NULL) { Item.SetItemEnabled(false); }
|
||||||
|
SystemMenu.push_back(Item);
|
||||||
|
SystemMenu.push_back(MENU_ITEM(SPLITER));
|
||||||
SystemMenu.push_back(MENU_ITEM(ID_SYSTEM_SAVE, MENU_SAVE, m_ShortCuts.ShortCutString(ID_SYSTEM_SAVE, AccessLevel)));
|
SystemMenu.push_back(MENU_ITEM(ID_SYSTEM_SAVE, MENU_SAVE, m_ShortCuts.ShortCutString(ID_SYSTEM_SAVE, AccessLevel)));
|
||||||
if (!inBasicMode)
|
if (!inBasicMode)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@ enum MainMenuID
|
||||||
|
|
||||||
//System Menu
|
//System Menu
|
||||||
ID_SYSTEM_RESET_SOFT, ID_SYSTEM_RESET_HARD, ID_SYSTEM_PAUSE, ID_SYSTEM_BITMAP,
|
ID_SYSTEM_RESET_SOFT, ID_SYSTEM_RESET_HARD, ID_SYSTEM_PAUSE, ID_SYSTEM_BITMAP,
|
||||||
ID_SYSTEM_LIMITFPS, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE,
|
ID_SYSTEM_LIMITFPS, ID_SYSTEM_SWAPDISK, ID_SYSTEM_RESTORE, ID_SYSTEM_LOAD, ID_SYSTEM_SAVE,
|
||||||
ID_SYSTEM_SAVEAS, ID_SYSTEM_CHEAT, ID_SYSTEM_GSBUTTON,
|
ID_SYSTEM_SAVEAS, ID_SYSTEM_CHEAT, ID_SYSTEM_GSBUTTON,
|
||||||
|
|
||||||
//Current Save Slot
|
//Current Save Slot
|
||||||
|
|
|
@ -316,6 +316,7 @@ void CShortCuts::Load(bool InitialValues)
|
||||||
AddShortCut(ID_SYSTEM_PAUSE, STR_SHORTCUT_SYSTEMMENU, MENU_PAUSE, CMenuShortCutKey::GAME_RUNNING);
|
AddShortCut(ID_SYSTEM_PAUSE, STR_SHORTCUT_SYSTEMMENU, MENU_PAUSE, CMenuShortCutKey::GAME_RUNNING);
|
||||||
AddShortCut(ID_SYSTEM_BITMAP, STR_SHORTCUT_SYSTEMMENU, MENU_BITMAP, CMenuShortCutKey::GAME_RUNNING);
|
AddShortCut(ID_SYSTEM_BITMAP, STR_SHORTCUT_SYSTEMMENU, MENU_BITMAP, CMenuShortCutKey::GAME_RUNNING);
|
||||||
AddShortCut(ID_SYSTEM_LIMITFPS, STR_SHORTCUT_SYSTEMMENU, MENU_LIMIT_FPS, CMenuShortCutKey::GAME_RUNNING);
|
AddShortCut(ID_SYSTEM_LIMITFPS, STR_SHORTCUT_SYSTEMMENU, MENU_LIMIT_FPS, CMenuShortCutKey::GAME_RUNNING);
|
||||||
|
AddShortCut(ID_SYSTEM_SWAPDISK, STR_SHORTCUT_SYSTEMMENU, MENU_SWAPDISK, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
||||||
AddShortCut(ID_SYSTEM_SAVE, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE, CMenuShortCutKey::GAME_RUNNING);
|
AddShortCut(ID_SYSTEM_SAVE, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE, CMenuShortCutKey::GAME_RUNNING);
|
||||||
AddShortCut(ID_SYSTEM_SAVEAS, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE_AS, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
AddShortCut(ID_SYSTEM_SAVEAS, STR_SHORTCUT_SYSTEMMENU, MENU_SAVE_AS, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
||||||
AddShortCut(ID_SYSTEM_RESTORE, STR_SHORTCUT_SYSTEMMENU, MENU_RESTORE, CMenuShortCutKey::GAME_RUNNING);
|
AddShortCut(ID_SYSTEM_RESTORE, STR_SHORTCUT_SYSTEMMENU, MENU_RESTORE, CMenuShortCutKey::GAME_RUNNING);
|
||||||
|
@ -383,6 +384,7 @@ void CShortCuts::Load(bool InitialValues)
|
||||||
m_ShortCuts.find(ID_SYSTEM_PAUSE)->second.AddShortCut(VK_PAUSE, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
m_ShortCuts.find(ID_SYSTEM_PAUSE)->second.AddShortCut(VK_PAUSE, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
||||||
m_ShortCuts.find(ID_SYSTEM_BITMAP)->second.AddShortCut(VK_F3, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
m_ShortCuts.find(ID_SYSTEM_BITMAP)->second.AddShortCut(VK_F3, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
||||||
m_ShortCuts.find(ID_SYSTEM_LIMITFPS)->second.AddShortCut(VK_F4, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
m_ShortCuts.find(ID_SYSTEM_LIMITFPS)->second.AddShortCut(VK_F4, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
||||||
|
m_ShortCuts.find(ID_SYSTEM_SWAPDISK)->second.AddShortCut('D', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
||||||
m_ShortCuts.find(ID_SYSTEM_SAVE)->second.AddShortCut(VK_F5, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
m_ShortCuts.find(ID_SYSTEM_SAVE)->second.AddShortCut(VK_F5, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
||||||
m_ShortCuts.find(ID_SYSTEM_RESTORE)->second.AddShortCut(VK_F7, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
m_ShortCuts.find(ID_SYSTEM_RESTORE)->second.AddShortCut(VK_F7, false, false, false, CMenuShortCutKey::GAME_RUNNING);
|
||||||
m_ShortCuts.find(ID_SYSTEM_LOAD)->second.AddShortCut('L', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
m_ShortCuts.find(ID_SYSTEM_LOAD)->second.AddShortCut('L', true, false, false, CMenuShortCutKey::GAME_RUNNING_WINDOW);
|
||||||
|
|
Loading…
Reference in New Issue