diff --git a/Source/Project64-core/N64System/Mips/Disk.h b/Source/Project64-core/N64System/Mips/Disk.h index 04cd43dd1..dc591c807 100644 --- a/Source/Project64-core/N64System/Mips/Disk.h +++ b/Source/Project64-core/N64System/Mips/Disk.h @@ -9,7 +9,6 @@ * * ****************************************************************************/ #pragma once -#include "stdafx.h" void DiskCommand(void); void DiskReset(void); diff --git a/Source/Project64-core/N64System/N64DiskClass.cpp b/Source/Project64-core/N64System/N64DiskClass.cpp new file mode 100644 index 000000000..ab0cfa921 --- /dev/null +++ b/Source/Project64-core/N64System/N64DiskClass.cpp @@ -0,0 +1,182 @@ +/**************************************************************************** +* * +* 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 +#include + +CN64Disk::CN64Disk() : +m_DiskImage(NULL), +m_DiskImageBase(NULL), +m_ErrorMsg(EMPTY_STRING) +{ +} + +CN64Disk::~CN64Disk() +{ +} + +bool CN64Disk::LoadDiskImage(const char * FileLoc) +{ + UnallocateRomImage(); + + if (!AllocateAndLoadDiskImage(FileLoc)) + { + return false; + } + + if (g_Disk == this) + { + g_Settings->SaveBool(GameRunning_LoadingInProgress, false); + } + + return true; +} + +bool CN64Disk::IsValidRomImage(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 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 (!IsValidRomImage(Test)) + { + m_DiskFile.Close(); + WriteTrace(TraceN64System, TraceError, "invalid image file %X %X %X %X", Test[0], Test[1], Test[2], Test[3]); + return false; + } + uint32_t DiskFileSize = m_DiskFile.GetLength(); + WriteTrace(TraceN64System, TraceDebug, "Successfully Opened, size: 0x%X", DiskFileSize); + + 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; + } + + 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::UnallocateRomImage() +{ + m_DiskFile.Close(); + + if (m_DiskImageBase) + { + ProtectMemory(m_DiskImage, m_DiskFileSize, MEM_READWRITE); + delete[] m_DiskImageBase; + m_DiskImageBase = NULL; + } + m_DiskImage = NULL; +} \ No newline at end of file diff --git a/Source/Project64-core/N64System/N64DiskClass.h b/Source/Project64-core/N64System/N64DiskClass.h new file mode 100644 index 000000000..ed71edce6 --- /dev/null +++ b/Source/Project64-core/N64System/N64DiskClass.h @@ -0,0 +1,41 @@ +/**************************************************************************** +* * +* 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 + +class CN64Disk +{ +public: + CN64Disk(); + ~CN64Disk(); + + bool LoadDiskImage(const char * FileLoc); + static bool IsValidRomImage(uint8_t Test[4]); + uint8_t * GetDiskAddress() { return m_DiskImage; } + void UnallocateRomImage(); + +private: + bool AllocateDiskImage(uint32_t DiskFileSize); + bool AllocateAndLoadDiskImage(const char * FileLoc); + void ByteSwapDisk(); + void SetError(LanguageStringID ErrorMsg); + + //constant values + enum { ReadFromRomSection = 0x400000 }; + + //class variables + CFile m_DiskFile; + uint8_t * m_DiskImage; + uint8_t * m_DiskImageBase; + uint32_t m_DiskFileSize; + LanguageStringID m_ErrorMsg; + stdstr m_FileName, m_DiskIdent; +}; \ No newline at end of file diff --git a/Source/Project64-core/N64System/SystemGlobals.cpp b/Source/Project64-core/N64System/SystemGlobals.cpp index 6ab72f809..f46c5a754 100644 --- a/Source/Project64-core/N64System/SystemGlobals.cpp +++ b/Source/Project64-core/N64System/SystemGlobals.cpp @@ -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; diff --git a/Source/Project64-core/N64System/SystemGlobals.h b/Source/Project64-core/N64System/SystemGlobals.h index cd279afaf..de4086076 100644 --- a/Source/Project64-core/N64System/SystemGlobals.h +++ b/Source/Project64-core/N64System/SystemGlobals.h @@ -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; diff --git a/Source/Project64-core/Project64-core.vcxproj b/Source/Project64-core/Project64-core.vcxproj index 5dd24c683..3c5e643be 100644 --- a/Source/Project64-core/Project64-core.vcxproj +++ b/Source/Project64-core/Project64-core.vcxproj @@ -61,6 +61,7 @@ + @@ -148,6 +149,7 @@ + diff --git a/Source/Project64-core/Project64-core.vcxproj.filters b/Source/Project64-core/Project64-core.vcxproj.filters index 0bac0a923..207c34c9a 100644 --- a/Source/Project64-core/Project64-core.vcxproj.filters +++ b/Source/Project64-core/Project64-core.vcxproj.filters @@ -297,6 +297,9 @@ Source Files\N64 System\Mips + + Source Files\N64 System + @@ -578,5 +581,8 @@ Header Files\N64 System\Mips + + Header Files\N64 System + \ No newline at end of file