Skip to content

Commit

Permalink
[SFCX] Better comment SFCX, and improve NAND
Browse files Browse the repository at this point in the history
Add debug prints as well
  • Loading branch information
Vali0004 committed Mar 4, 2025
1 parent 9f57571 commit 7dda557
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 17 deletions.
45 changes: 30 additions & 15 deletions Xenon/Core/NAND/NAND.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,17 @@ NAND::NAND(const char* deviceName, const std::string filePath,

rawFileSize = std::filesystem::file_size(filePath);

if (rawFileSize > 0x4000000) {
LOG_ERROR(System, "NAND: Nand size exceeds 64MB! This may cause unintended behaviour");
SYSTEM_PAUSE();
rawNANDData.resize(rawFileSize);
}

LOG_INFO(System, "NAND: File size = {:#x} bytes.", rawFileSize);

if (!CheckMagic()) {
LOG_ERROR(System, "NAND: Wrong magic found, Xbox 360 Retail NAND magic is 0xFF4F and Devkit NAND magic 0x0F4F.");
u8 magic[2]{};
if (!CheckMagic(magic)) {
LOG_ERROR(System, "NAND: Wrong magic found! Your nand contained {:#x} while the expected is 0xFF4F (retail) or 0x0F4F (devkit)", magic);
SYSTEM_PAUSE();
}

Expand All @@ -34,7 +41,7 @@ NAND::NAND(const char* deviceName, const std::string filePath,
inputFile.read(reinterpret_cast<char*>(rawNANDData.data() + currentBlock), blockSize);
}

inputFile.seekg(0, std::ios_base::beg);
inputFile.close();

CheckSpare();

Expand All @@ -44,8 +51,6 @@ NAND::NAND(const char* deviceName, const std::string filePath,
// Check Meta Type
imageMetaType = DetectSpareType();
}

inputFile.close();
}

NAND::~NAND() {
Expand All @@ -56,13 +61,15 @@ NAND::~NAND() {
void NAND::Read(u64 readAddress, u64 *data, u8 byteCount) {
u32 offset = (u32)readAddress & 0xFFFFFF;
offset = 1 ? ((offset / 0x200) * 0x210) + offset % 0x200 : offset;
LOG_DEBUG(SFCX, "Reading raw data at {:#x} (offset {:#x}) for {:#x} bytes", readAddress, offset, byteCount);
memcpy(data, rawNANDData.data() + offset, byteCount);
}

/************Responsible for writing the NAND************/
void NAND::Write(u64 writeAddress, u64 data, u8 byteCount) {
u32 offset = (u32)writeAddress & 0xFFFFFF;
offset = 1 ? ((offset / 0x200) * 0x210) + offset % 0x200 : offset;
LOG_DEBUG(SFCX, "Writing raw data at {:#x} (offset {:#x}) for {:#x} bytes", writeAddress, offset, byteCount);
u8* NANDData = rawNANDData.data();
memcpy(rawNANDData.data() + offset, &data, byteCount);
}
Expand All @@ -72,9 +79,10 @@ bool NAND::CheckPageECD(u8 *data, s32 offset) {
u8 actualData[4]{};
u8 calculatedECD[4]{};

inputFile.seekg(offset + 524);
inputFile.read(reinterpret_cast<char*>(actualData), sizeof(actualData));
inputFile.seekg(0, std::ios::beg);
// This directly takes the NAND block's metadata
// and skips to the last 4 ECC bytes, calculates the error corrrecting data on it,
// and checks against what the nand provided
memcpy(actualData, rawNANDData.data() + (offset + 0x200 + 0xC), sizeof(actualData));

CalculateECD(data, offset, calculatedECD);

Expand Down Expand Up @@ -110,12 +118,15 @@ void NAND::CalculateECD(u8 *data, int offset, u8 ret[]) {
ret[3] = (val >> 18) & 0xFF;
}

//*Checks Magic.
bool NAND::CheckMagic() {
// Check if the nand provided to us contains a valid metadata or not
bool NAND::CheckMagic(u8 magicOut[2]) {
u8 magic[2]{};

inputFile.read(reinterpret_cast<char*>(magic), sizeof(magic));
inputFile.seekg(0, std::ios::beg);
if (magicOut) {
memcpy(magicOut, magic, sizeof(magic));
}

if ((magic[0] == 0xFF || magic[0] == 0x0F) &&
(magic[1] == 0x3F || magic[1] == 0x4F)) {
Expand All @@ -126,9 +137,15 @@ bool NAND::CheckMagic() {

//*Checks Spare.
void NAND::CheckSpare() {
// Each sectors of data is 512 bytes of data,
// and 16 bytes of space (0x210)
// We are taking those 16 bytes, which is the NAND's metadata structure,
// and checking the ECD on it
//
// We take 3 blocks, and verify that they all have no invalid data
// If we have no invalid data, then we do not have any spare
u8 data[0x630]{};
inputFile.seekg(0, std::ios::beg);
inputFile.read(reinterpret_cast<char*>(data), sizeof(data));
memcpy(data, rawNANDData.data(), sizeof(data));
hasSpare = true;
u8 *spare = nullptr;

Expand All @@ -145,10 +162,8 @@ MetaType NAND::DetectSpareType(bool firstTry) {
return metaTypeNone;
}

inputFile.seekg(firstTry ? 0x4400 : (u32)rawFileSize - 0x4400, std::ios::beg);

u8 tmp[0x10]{};
inputFile.read(reinterpret_cast<char*>(tmp), sizeof(tmp));
memcpy(tmp, rawNANDData.data() + (firstTry ? 0x4400 : (u32)rawFileSize - 0x4400), sizeof(tmp));

return metaTypeNone;
}
2 changes: 1 addition & 1 deletion Xenon/Core/NAND/NAND.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class NAND : public SystemDevice {
// 64 Mb NAND Data
std::vector<u8> rawNANDData{};

bool CheckMagic();
bool CheckMagic(u8 magicOut[2] = nullptr);
void CheckSpare();
bool CheckPageECD(u8 *data, s32 offset);
void CalculateECD(u8 *data, int offset, u8 ret[]);
Expand Down
3 changes: 2 additions & 1 deletion Xenon/Core/RootBus/HostBridge/PCIBridge/SFCX/SFCX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,8 @@ void SFCX::sfcxMainLoop() {
case PHY_PAGE_TO_BUF:
// Read Phyisical page into page buffer.
// Physical pages are 0x210 bytes long, logical page (0x200) + meta data
// (0x10).
// (0x10).
LOG_DEBUG(SFCX, "Reading from address {:#x} (reading {:#x} bytes)", sfcxState.addressReg, sizeof(sfcxState.pageBuffer));
nandFile.seekg(sfcxState.addressReg);
nandFile.read(reinterpret_cast<char*>(sfcxState.pageBuffer), sizeof(sfcxState.pageBuffer));
// Issue Interrupt.
Expand Down

0 comments on commit 7dda557

Please sign in to comment.