Fix case where we could write off the end of a buffer if texture width == 1 and 4-bit color.

This commit is contained in:
Henrik Rydgård 2022-12-09 23:00:52 +01:00
parent 03433c42ce
commit e59b734b27
3 changed files with 32 additions and 11 deletions

View File

@ -282,7 +282,7 @@ public:
UI::Event OnChoice; UI::Event OnChoice;
protected: protected:
bool HasTitleBar() const { return false; } bool HasTitleBar() const override { return false; }
private: private:
const ContextMenuItem *items_; const ContextMenuItem *items_;

View File

@ -1673,7 +1673,9 @@ CheckAlphaResult TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, G
case GE_CMODE_16BIT_ABGR5551: case GE_CMODE_16BIT_ABGR5551:
case GE_CMODE_16BIT_ABGR4444: case GE_CMODE_16BIT_ABGR4444:
{ {
if (clutAlphaLinear_ && mipmapShareClut && !expandTo32bit) { // The w > 1 check is to not need a case that handles a single pixel
// in DeIndexTexture4Optimal<u16>.
if (clutAlphaLinear_ && mipmapShareClut && !expandTo32bit && w >= 4) {
// We don't bother with fullalpha here (clutAlphaLinear_) // We don't bother with fullalpha here (clutAlphaLinear_)
// Here, reverseColors means the CLUT is already reversed. // Here, reverseColors means the CLUT is already reversed.
if (reverseColors) { if (reverseColors) {

View File

@ -163,22 +163,36 @@ inline void DeIndexTexture4(/*WRITEONLY*/ ClutT *dest, const u8 *indexed, int le
ClutT alphaSum = (ClutT)(-1); ClutT alphaSum = (ClutT)(-1);
if (nakedIndex) { if (nakedIndex) {
for (int i = 0; i < length; i += 2) { while (length >= 2) {
u8 index = *indexed++; u8 index = *indexed++;
ClutT color0 = clut[index & 0xf]; ClutT color0 = clut[index & 0xf];
ClutT color1 = clut[index >> 4]; ClutT color1 = clut[index >> 4];
dest[i + 0] = color0; *dest++ = color0;
dest[i + 1] = color1; *dest++ = color1;
alphaSum &= color0 & color1; alphaSum &= color0 & color1;
length -= 2;
}
if (length) { // Last pixel. Can really only happen in 1xY textures, but making this work generically.
u8 index = *indexed++;
ClutT color0 = clut[index & 0xf];
*dest = color0;
alphaSum &= color0;
} }
} else { } else {
for (int i = 0; i < length; i += 2) { while (length >= 2) {
u8 index = *indexed++; u8 index = *indexed++;
ClutT color0 = clut[gstate.transformClutIndex((index >> 0) & 0xf)]; ClutT color0 = clut[gstate.transformClutIndex((index >> 0) & 0xf)];
ClutT color1 = clut[gstate.transformClutIndex((index >> 4) & 0xf)]; ClutT color1 = clut[gstate.transformClutIndex((index >> 4) & 0xf)];
dest[i + 0] = color0; *dest++ = color0;
dest[i + 1] = color1; *dest++ = color1;
alphaSum &= color0 & color1; alphaSum &= color0 & color1;
length -= 2;
}
if (length) {
u8 index = *indexed++;
ClutT color0 = clut[gstate.transformClutIndex((index >> 0) & 0xf)];
*dest = color0;
alphaSum &= color0;
} }
} }
@ -187,10 +201,15 @@ inline void DeIndexTexture4(/*WRITEONLY*/ ClutT *dest, const u8 *indexed, int le
template <typename ClutT> template <typename ClutT>
inline void DeIndexTexture4Optimal(ClutT *dest, const u8 *indexed, int length, ClutT color) { inline void DeIndexTexture4Optimal(ClutT *dest, const u8 *indexed, int length, ClutT color) {
for (int i = 0; i < length; i += 2) { while (length >= 2) {
u8 index = *indexed++; u8 index = *indexed++;
dest[i + 0] = color | ((index >> 0) & 0xf); *dest++ = color | ((index >> 0) & 0xf);
dest[i + 1] = color | ((index >> 4) & 0xf); *dest++ = color | ((index >> 4) & 0xf);
length -= 2;
}
if (length) {
u8 index = *indexed++;
*dest++ = color | ((index >> 0) & 0xf);
} }
} }