From f415c743587f2d8a76882f0557ce80d71aa61003 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 24 Dec 2015 14:31:43 -0800 Subject: [PATCH] Also fix padding for DisplayList on iOS. Fixes #8199. --- GPU/GPUCommon.cpp | 61 +++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 9d62079d04..051cd378a3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1069,29 +1069,6 @@ struct DisplayList_v2 { bool bboxResult; }; -struct DisplayList_v3_no_padding { - int id; - u32 startpc; - u32 pc; - u32 stall; - DisplayListState state; - SignalBehavior signal; - int subIntrBase; - u16 subIntrToken; - DisplayListStackEntry stack[32]; - int stackptr; - bool interrupted; - u64 waitTicks; - bool interruptsEnabled; - bool pendingInterrupt; - bool started; - PSPPointer context; - u32 offsetAddr; - bool bboxResult; - u32 stackAddr; - // See the header -}; - void GPUCommon::DoState(PointerWrap &p) { easy_guard guard(listLock); @@ -1103,21 +1080,33 @@ void GPUCommon::DoState(PointerWrap &p) { if (s >= 4) { p.DoArray(dls, ARRAY_SIZE(dls)); } else if (s >= 3) { -#if defined(ANDROID) && defined(_M_IX86) - // If this starts failing, we'll need to put some alignment attributes on the Displaylist_v3_no_padding struct above. - static_assert(sizeof(DisplayList_v3_no_padding) == 452, "Not the old DisplayList size anymore, see comment"); - for (size_t i = 0; i < ARRAY_SIZE(dls); ++i) { - DisplayList_v3_no_padding oldDL; - p.Do(oldDL); - // Copy over everything except the new padding bytes to make the struct size - // equal to other platforms. - memcpy(&dls[i], &oldDL, sizeof(DisplayList_v3_no_padding)); + // This may have been saved with or without padding, depending on platform. + // We need to upconvert it to our consistently-padded struct. + static const size_t DisplayList_v3_size = 452; + static const size_t DisplayList_v4_size = 456; + static_assert(DisplayList_v4_size == sizeof(DisplayList), "Make sure to change here when updating DisplayList"); + + p.DoVoid(&dls[0], DisplayList_v3_size); + dls[0].padding = 0; + + const u8 *savedPtr = *p.GetPPtr(); + const u32 *savedPtr32 = (const u32 *)savedPtr; + // Here's the trick: the first member (id) is always the same as the index. + // The second member (startpc) is always an address, or 0, never 1. So we can see the padding. + const bool hasPadding = savedPtr32[1] == 1; + if (hasPadding) { + u32 padding; + p.Do(padding); + } + + for (size_t i = 1; i < ARRAY_SIZE(dls); ++i) { + p.DoVoid(&dls[i], DisplayList_v3_size); dls[i].padding = 0; + if (hasPadding) { + u32 padding; + p.Do(padding); + } } -#else - // Android-x86 used to write badly padded data structures. - p.DoArray(dls, ARRAY_SIZE(dls)); -#endif } else if (s >= 2) { for (size_t i = 0; i < ARRAY_SIZE(dls); ++i) { DisplayList_v2 oldDL;