Improve error handling for parsing banners. Fixes #18

This commit is contained in:
Gericom
2026-03-29 11:47:08 +02:00
parent 7c06abf224
commit 3f780fdd69
2 changed files with 40 additions and 39 deletions

View File

@@ -2,52 +2,60 @@
#include <string.h> #include <string.h>
#include <nds/arm9/cache.h> #include <nds/arm9/cache.h>
#include "fat/File.h" #include "fat/File.h"
#include "romBrowser/ICoverRepository.h"
#include "NdsInternalFileInfo.h" #include "NdsInternalFileInfo.h"
NdsInternalFileInfo::NdsInternalFileInfo(const FastFileRef& fastFileRef) NdsInternalFileInfo::NdsInternalFileInfo(const FastFileRef& fastFileRef)
{ {
const auto file = std::make_unique<File>(); const auto file = std::make_unique<File>();
_hasBanner = false;
memset(_gameCode, 0, sizeof(_gameCode)); memset(_gameCode, 0, sizeof(_gameCode));
file->Open(fastFileRef, FA_READ); file->Open(fastFileRef, FA_READ);
if (file->Seek(0xC) != FR_OK)
return;
u32 bytesRead;
if (file->Read(_gameCode, 4, bytesRead) != FR_OK)
return;
if (file->Seek(0x68) != FR_OK)
return;
u32 bannerOffset; u32 bannerOffset;
if (file->Read(&bannerOffset, 4, bytesRead) != FR_OK) if (file->Seek(0xC) != FR_OK ||
return; !file->ReadExact(_gameCode, 4) ||
file->Seek(0x68) != FR_OK ||
if (bannerOffset == 0) !file->ReadExact(&bannerOffset, 4) ||
return; bannerOffset == 0 ||
bannerOffset >= file->GetSize() ||
if (file->Seek(bannerOffset) != FR_OK) file->Seek(bannerOffset) != FR_OK ||
return; !file->ReadExact(&_banner, 0x840))
if (file->Read(&_banner, 0xA00, bytesRead) != FR_OK)
return;
if (_banner.header.version >= NDS_BANNER_VERSION_103)
{ {
if (file->Read(((u8*)&_banner) + 0xA00, 0x19C0, bytesRead) != FR_OK)
return; return;
} }
if (_banner.header.version >= NDS_BANNER_VERSION_2 &&
!file->ReadExact(((u8*)&_banner) + 0x840, 0x100))
{
return;
}
if (_banner.header.version >= NDS_BANNER_VERSION_3 &&
!file->ReadExact(((u8*)&_banner) + 0x940, 0x100))
{
return;
}
if (_banner.header.version >= NDS_BANNER_VERSION_103 &&
!file->ReadExact(((u8*)&_banner) + 0xA40, 0x1980))
{
return;
}
_hasBanner = true; _hasBanner = true;
DC_FlushRange(&_banner, sizeof(_banner)); DC_FlushRange(&_banner, sizeof(_banner));
} }
const char16_t* NdsInternalFileInfo::GetGameTitle() const const char16_t* NdsInternalFileInfo::GetGameTitle() const
{ {
if (!_hasBanner) return _hasBanner
return nullptr; ? _banner.title[NDS_BANNER_TITLE_LANGUAGE_ENGLISH]
return _banner.title[NDS_BANNER_TITLE_LANGUAGE_ENGLISH]; : nullptr;
}
std::unique_ptr<FileIcon> NdsInternalFileInfo::CreateGameIcon() const
{
return _hasBanner
? std::make_unique<NdsFileIcon>(&_banner)
: nullptr;
} }

View File

@@ -12,18 +12,11 @@ public:
constexpr const char* GetGameCode() const override { return _gameCode; } constexpr const char* GetGameCode() const override { return _gameCode; }
const char16_t* GetGameTitle() const override; const char16_t* GetGameTitle() const override;
std::unique_ptr<FileIcon> CreateGameIcon() const override;
std::unique_ptr<FileIcon> CreateGameIcon() const override
{
if (!_hasBanner)
return nullptr;
return std::make_unique<NdsFileIcon>(&_banner);
}
const nds_banner_t& GetBanner() const { return _banner; } const nds_banner_t& GetBanner() const { return _banner; }
private: private:
nds_banner_t _banner alignas(32); nds_banner_t _banner alignas(32);
bool _hasBanner; bool _hasBanner = false;
char _gameCode[5]; char _gameCode[5];
}; };