Fix vram corruption when using the cheat panel in vertical grid mode

The graphics of an animated nds icon are now not all uploaded to vram at the same time.
There are now 1024 bytes available for each icon (previously 4096).
Double buffering is used to upload the new icon frame every time it changes.
This commit is contained in:
Gericom
2026-03-08 11:32:48 +01:00
parent 12ebd482d4
commit 43b1bf7afa
8 changed files with 45 additions and 42 deletions

View File

@@ -5,7 +5,7 @@
class PaletteManager;
class GraphicsContext;
#define FILE_ICON_VRAM_SIZE 4096
#define FILE_ICON_VRAM_SIZE 1024
/// @brief Abstract base class representing a file icon.
class FileIcon
@@ -15,7 +15,7 @@ public:
/// @brief Uploads the graphics of this icon to the specified \p vram address.
/// @param vram The vram address to load the graphics to.
virtual void UploadGraphics(vu16* vram) const = 0;
virtual void UploadGraphics(vu16* vram) = 0;
/// @brief Updates this icon.
virtual void Update() { }

View File

@@ -1,5 +1,4 @@
#include "common.h"
#include <libtwl/math/mathDiv.h>
#include <libtwl/dma/dmaNitro.h>
#include "gui/PaletteManager.h"
#include "gui/OamManager.h"
@@ -30,25 +29,32 @@ NdsFileIcon::NdsFileIcon(const nds_banner_t* banner)
break;
}
else
{
length += token.duration;
}
}
_animLength = length;
_tokenStartTimes[NDS_BANNER_ANIM_TOKEN_COUNT] = _animLength;
}
}
void NdsFileIcon::UploadGraphics(vu16* vram) const
void NdsFileIcon::UploadGraphics(vu16* vram)
{
_vramAddress = vram;
_currentVramSlot = 0;
_currentGfxIdx = -1;
if (!_animated)
{
if (_animated)
dma_ntrCopy32(3, _banner->animation.iconGfx, vram, sizeof(_banner->animation.iconGfx));
else
dma_ntrCopy32(3, _banner->iconGfx, vram, sizeof(_banner->iconGfx));
}
}
void NdsFileIcon::Update()
{
if (!_animated)
{
return;
}
_frame %= _animLength;
@@ -71,48 +77,30 @@ void NdsFileIcon::Update()
break;
}
else if (_frame < midTime)
{
end = mid - 1;
}
else
{
start = mid + 1;
}
}
_animTokenIdx = start;
}
if (++_frame == _animLength)
{
_frame = 0;
// if (++_durationCounter < _banner->animation.animTokens[_animTokenIdx].duration)
// return;
// _durationCounter = 0;
// if (++_animTokenIdx >= NDS_BANNER_ANIM_TOKEN_COUNT)
// {
// _animTokenIdx = 0;
// return;
// }
// if (_banner->animation.animTokens[_animTokenIdx].duration == NDS_BANNER_ANIM_DURATION_CONTROL_FRAME)
// {
// switch (_banner->animation.animTokens[_animTokenIdx].control)
// {
// case NDS_BANNER_ANIM_CONTROL_LOOP:
// _animTokenIdx = 0;
// break;
// case NDS_BANNER_ANIM_CONTROL_STOP:
// _animTokenIdx--;
// break;
// }
// }
}
}
void NdsFileIcon::Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor)
{
if (!graphicsContext.IsVisible(Rectangle(_position, 32, 32)))
{
return;
}
const u16* palette = _animated
? _banner->animation.iconPltt[_banner->animation.animTokens[_animTokenIdx].plttIdx]
@@ -123,7 +111,17 @@ void NdsFileIcon::Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& bac
u32 vramOffset = _vramOffset;
if (_animated)
vramOffset += _banner->animation.animTokens[_animTokenIdx].gfxIdx * 512;
{
int gfxIdx = _banner->animation.animTokens[_animTokenIdx].gfxIdx;
if (gfxIdx != _currentGfxIdx)
{
_currentVramSlot = 1 - _currentVramSlot;
_currentGfxIdx = gfxIdx;
dma_ntrCopy32(3, &_banner->animation.iconGfx[gfxIdx][0], (u8*)_vramAddress + (_currentVramSlot * NDS_BANNER_ICON_SIZE), NDS_BANNER_ICON_SIZE);
}
vramOffset += _currentVramSlot * NDS_BANNER_ICON_SIZE;
}
auto builder = OamBuilder::OamWithSize<32, 32>(
_position, vramOffset >> 7)

View File

@@ -8,7 +8,7 @@ class NdsFileIcon : public FileIcon
public:
explicit NdsFileIcon(const nds_banner_t* banner);
void UploadGraphics(vu16* vram) const override;
void UploadGraphics(vu16* vram) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;
@@ -21,4 +21,8 @@ private:
u32 _animLength;
u16 _tokenStartTimes[65];
bool _loop;
vu16* _vramAddress = nullptr;
int _currentVramSlot = 0;
int _currentGfxIdx = -1;
};

View File

@@ -46,10 +46,11 @@ typedef struct
} nds_banner_anim_token_t;
#define NDS_BANNER_ANIM_TOKEN_COUNT 64
#define NDS_BANNER_ICON_SIZE 512
typedef struct
{
u8 iconGfx[8][0x200];
u8 iconGfx[8][NDS_BANNER_ICON_SIZE];
u16 iconPltt[8][16];
nds_banner_anim_token_t animTokens[NDS_BANNER_ANIM_TOKEN_COUNT];
} nds_banner_anim_t;
@@ -57,7 +58,7 @@ typedef struct
typedef struct
{
nds_banner_header_t header;
u8 iconGfx[0x200];
u8 iconGfx[NDS_BANNER_ICON_SIZE];
u16 iconPltt[16];
char16_t title[16][128];
nds_banner_anim_t animation;

View File

@@ -7,7 +7,7 @@
#include "gui/palette/DirectPalette.h"
#include "StaticIcon.h"
void StaticIcon::UploadGraphics(vu16* vram) const
void StaticIcon::UploadGraphics(vu16* vram)
{
dma_ntrCopy32(3, _tileData, vram, 512);
}

View File

@@ -7,7 +7,7 @@ public:
StaticIcon(const u8* tileData, const u16* paletteData)
: _tileData(tileData), _paletteData(paletteData) { }
void UploadGraphics(vu16* vram) const override;
void UploadGraphics(vu16* vram) override;
void Update() override;
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;

View File

@@ -24,7 +24,7 @@ MaterialFileIcon::MaterialFileIcon(const TCHAR* name, const MaterialColorScheme*
_displayName[i] = 0;
}
void MaterialFileIcon::UploadGraphics(vu16* vram) const
void MaterialFileIcon::UploadGraphics(vu16* vram)
{
dma_ntrCopy32(3, GetIconTiles(), vram, 32 * 32 / 2);

View File

@@ -11,7 +11,7 @@ public:
MaterialFileIcon(const TCHAR* name, const MaterialColorScheme* materialColorScheme,
const IFontRepository* fontRepository);
void UploadGraphics(vu16* vram) const override;
void UploadGraphics(vu16* vram) override;
void Draw(GraphicsContext& graphicsContext, const Rgb<8, 8, 8>& backgroundColor) override;
protected: