mirror of https://github.com/AxioDL/kabufuda.git
Fix checksum handling
This commit is contained in:
parent
65ecd15219
commit
4cd0330e22
|
@ -220,8 +220,10 @@ class Card
|
||||||
|
|
||||||
void swapEndian();
|
void swapEndian();
|
||||||
void updateDirAndBat();
|
void updateDirAndBat();
|
||||||
|
void updateChecksum();
|
||||||
public:
|
public:
|
||||||
Card();
|
Card();
|
||||||
|
Card(const Card& other);
|
||||||
Card(const SystemString& filepath, const char* game = nullptr, const char* maker=nullptr);
|
Card(const SystemString& filepath, const char* game = nullptr, const char* maker=nullptr);
|
||||||
~Card();
|
~Card();
|
||||||
|
|
||||||
|
@ -299,7 +301,7 @@ public:
|
||||||
* @param checksum
|
* @param checksum
|
||||||
* @param checksumInv
|
* @param checksumInv
|
||||||
*/
|
*/
|
||||||
void calculateChecksum(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv);
|
void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __CARD_HPP__
|
#endif // __CARD_HPP__
|
||||||
|
|
63
lib/Card.cpp
63
lib/Card.cpp
|
@ -52,6 +52,17 @@ Card::Card()
|
||||||
memset(__raw, 0xFF, BlockSize);
|
memset(__raw, 0xFF, BlockSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Card::Card(const Card& other)
|
||||||
|
{
|
||||||
|
memcpy(__raw, other.__raw, BlockSize);
|
||||||
|
m_dir = other.m_dir;
|
||||||
|
m_dirBackup = other.m_dirBackup;
|
||||||
|
m_bat = other.m_bat;
|
||||||
|
m_batBackup = other.m_batBackup;
|
||||||
|
memcpy(m_game, other.m_game, 4);
|
||||||
|
memcpy(m_maker, other.m_maker, 2);
|
||||||
|
}
|
||||||
|
|
||||||
Card::Card(const SystemString& filename, const char* game, const char* maker)
|
Card::Card(const SystemString& filename, const char* game, const char* maker)
|
||||||
: m_filename(filename)
|
: m_filename(filename)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +122,9 @@ Card::Card(const SystemString& filename, const char* game, const char* maker)
|
||||||
|
|
||||||
/* Close and reopen in read/write mode */
|
/* Close and reopen in read/write mode */
|
||||||
fclose(m_fileHandle);
|
fclose(m_fileHandle);
|
||||||
|
m_fileHandle = nullptr;
|
||||||
m_fileHandle = Fopen(m_filename.c_str(), _S("r+"));
|
m_fileHandle = Fopen(m_filename.c_str(), _S("r+"));
|
||||||
|
rewind(m_fileHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +157,13 @@ void Card::updateDirAndBat()
|
||||||
std::swap(m_currentBat, m_previousBat);
|
std::swap(m_currentBat, m_previousBat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Card::updateChecksum()
|
||||||
|
{
|
||||||
|
swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFE, &m_checksum, &m_checksumInv);
|
||||||
|
swapEndian();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<IFileHandle> Card::createFile(const char* filename, size_t size)
|
std::unique_ptr<IFileHandle> Card::createFile(const char* filename, size_t size)
|
||||||
{
|
{
|
||||||
updateDirAndBat();
|
updateDirAndBat();
|
||||||
|
@ -379,7 +399,7 @@ void Card::format(EDeviceId id, ECardSize size, EEncoding encoding)
|
||||||
m_sizeMb = uint16_t(size);
|
m_sizeMb = uint16_t(size);
|
||||||
m_maxBlock = m_sizeMb * MbitToBlocks;
|
m_maxBlock = m_sizeMb * MbitToBlocks;
|
||||||
m_encoding = uint16_t(encoding);
|
m_encoding = uint16_t(encoding);
|
||||||
calculateChecksum(reinterpret_cast<uint16_t*>(__raw), 0xFE, &m_checksum, &m_checksumInv);
|
updateChecksum();
|
||||||
m_dir = Directory();
|
m_dir = Directory();
|
||||||
m_dirBackup = m_dir;
|
m_dirBackup = m_dir;
|
||||||
m_bat = BlockAllocationTable(uint32_t(size) * MbitToBlocks);
|
m_bat = BlockAllocationTable(uint32_t(size) * MbitToBlocks);
|
||||||
|
@ -389,7 +409,9 @@ void Card::format(EDeviceId id, ECardSize size, EEncoding encoding)
|
||||||
m_currentBat = &m_batBackup;
|
m_currentBat = &m_batBackup;
|
||||||
m_previousBat = &m_bat;
|
m_previousBat = &m_bat;
|
||||||
|
|
||||||
if (!m_fileHandle)
|
if (m_fileHandle)
|
||||||
|
fclose(m_fileHandle);
|
||||||
|
|
||||||
m_fileHandle = Fopen(m_filename.c_str(), _S("wb"));
|
m_fileHandle = Fopen(m_filename.c_str(), _S("wb"));
|
||||||
|
|
||||||
if (m_fileHandle)
|
if (m_fileHandle)
|
||||||
|
@ -459,8 +481,10 @@ Card::operator bool() const
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint16_t ckSum, ckSumInv;
|
uint16_t ckSum, ckSumInv;
|
||||||
calculateChecksum(reinterpret_cast<const uint16_t*>(__raw), 0xFE, &ckSum, &ckSumInv);
|
Card tmp = *this;
|
||||||
if (ckSum != m_checksum || ckSumInv != m_checksumInv)
|
tmp.swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw), 0xFE, &ckSum, &ckSumInv);
|
||||||
|
if (SBig(ckSum) != m_checksum || SBig(ckSumInv) != m_checksumInv)
|
||||||
return false;
|
return false;
|
||||||
if (!m_dir.valid() && !m_dirBackup.valid())
|
if (!m_dir.valid() && !m_dirBackup.valid())
|
||||||
return false;
|
return false;
|
||||||
|
@ -514,14 +538,18 @@ void BlockAllocationTable::swapEndian()
|
||||||
|
|
||||||
void BlockAllocationTable::updateChecksum()
|
void BlockAllocationTable::updateChecksum()
|
||||||
{
|
{
|
||||||
calculateChecksum(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv);
|
swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv);
|
||||||
|
swapEndian();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockAllocationTable::valid() const
|
bool BlockAllocationTable::valid() const
|
||||||
{
|
{
|
||||||
uint16_t ckSum, ckSumInv;
|
uint16_t ckSum, ckSumInv;
|
||||||
calculateChecksum(reinterpret_cast<const uint16_t*>(__raw + 4), 0xFFE, &ckSum, &ckSumInv);
|
BlockAllocationTable tmp = *this;
|
||||||
return (ckSum == m_checksum && ckSumInv == m_checksumInv);
|
tmp.swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw + 4), 0xFFE, &ckSum, &ckSumInv);
|
||||||
|
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
|
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
|
||||||
|
@ -615,14 +643,18 @@ void Directory::swapEndian()
|
||||||
|
|
||||||
void Directory::updateChecksum()
|
void Directory::updateChecksum()
|
||||||
{
|
{
|
||||||
calculateChecksum(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv);
|
swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv);
|
||||||
|
swapEndian();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Directory::valid() const
|
bool Directory::valid() const
|
||||||
{
|
{
|
||||||
uint16_t ckSum, ckSumInv;
|
uint16_t ckSum, ckSumInv;
|
||||||
calculateChecksum(reinterpret_cast<const uint16_t*>(__raw), 0xFFE, &ckSum, &ckSumInv);
|
Directory tmp = *this;
|
||||||
return (ckSum == m_checksum && ckSumInv == m_checksumInv);
|
tmp.swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw), 0xFFE, &ckSum, &ckSumInv);
|
||||||
|
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
||||||
}
|
}
|
||||||
|
|
||||||
Directory::Directory()
|
Directory::Directory()
|
||||||
|
@ -681,17 +713,18 @@ File* Directory::getFile(const char* game, const char* maker, const char* filena
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateChecksum(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv)
|
void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv)
|
||||||
{
|
{
|
||||||
*checksum = 0;
|
*checksum = 0;
|
||||||
*checksumInv = 0;
|
*checksumInv = 0;
|
||||||
for (size_t i = 0; i < len; ++i)
|
for (size_t i = 0; i < len; ++i)
|
||||||
{
|
{
|
||||||
*checksum += data[i];
|
*checksum += SBig(data[i]);
|
||||||
*checksumInv += data[i] ^ 0xFFFF;
|
*checksumInv += SBig(uint16_t(data[i] ^ 0xFFFF));
|
||||||
}
|
}
|
||||||
*checksum = *checksum;
|
|
||||||
*checksumInv = *checksumInv;
|
*checksum = SBig(*checksum);
|
||||||
|
*checksumInv = SBig(*checksumInv);
|
||||||
if (*checksum == 0xFFFF)
|
if (*checksum == 0xFFFF)
|
||||||
*checksum = 0;
|
*checksum = 0;
|
||||||
if (*checksumInv == 0xFFFF)
|
if (*checksumInv == 0xFFFF)
|
||||||
|
|
|
@ -6,13 +6,13 @@ int main()
|
||||||
kabufuda::Card mc{_S("test.USA.raw"), "GM8E", "01"};
|
kabufuda::Card mc{_S("test.USA.raw"), "GM8E", "01"};
|
||||||
if (!mc)
|
if (!mc)
|
||||||
mc.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card2043Mb);
|
mc.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card2043Mb);
|
||||||
std::unique_ptr<kabufuda::IFileHandle> f = mc.openFile("MetroidPrime A");
|
std::unique_ptr<kabufuda::IFileHandle> f = mc.openFile("MetroidPrime B");
|
||||||
if (!f)
|
if (!f)
|
||||||
f = mc.createFile("MetroidPrime A", kabufuda::BlockSize);
|
f = mc.createFile("MetroidPrime B", kabufuda::BlockSize);
|
||||||
|
|
||||||
if (f)
|
if (f)
|
||||||
{
|
{
|
||||||
const char* test = "Metroid Prime A is Cool";
|
const char* test = "Metroid Prime B is Cool";
|
||||||
size_t len = strlen(test);
|
size_t len = strlen(test);
|
||||||
uint8_t data[kabufuda::BlockSize] = {};
|
uint8_t data[kabufuda::BlockSize] = {};
|
||||||
mc.write(f, data, kabufuda::BlockSize);
|
mc.write(f, data, kabufuda::BlockSize);
|
||||||
|
@ -24,7 +24,7 @@ int main()
|
||||||
mc.seek(f, -2, kabufuda::SeekOrigin::Current);
|
mc.seek(f, -2, kabufuda::SeekOrigin::Current);
|
||||||
mc.read(f, &derp, 2);
|
mc.read(f, &derp, 2);
|
||||||
std::cout << derp << std::endl;
|
std::cout << derp << std::endl;
|
||||||
//mc.deleteFile(f);
|
mc.deleteFile(f);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue