| 902 | // |
| 903 | |
| 904 | void GSLocalMemoryFunctions::ReadImageX(const GSLocalMemory& mem, int& tx, int& ty, u8* dst, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG) |
| 905 | { |
| 906 | if (len <= 0) |
| 907 | return; |
| 908 | |
| 909 | u8* RESTRICT pb = (u8*)dst; |
| 910 | u16* RESTRICT pw = (u16*)dst; |
| 911 | u32* RESTRICT pd = (u32*)dst; |
| 912 | const u32* vm32 = mem.vm32(); |
| 913 | const u16* vm16 = mem.vm16(); |
| 914 | const u8* vm8 = mem.vm8(); |
| 915 | |
| 916 | u32 bp = BITBLTBUF.SBP; |
| 917 | u32 bw = BITBLTBUF.SBW; |
| 918 | |
| 919 | int sx = TRXPOS.SSAX; |
| 920 | int w = TRXREG.RRW; |
| 921 | |
| 922 | GSOffset off = mem.GetOffset(bp, bw, BITBLTBUF.SPSM); |
| 923 | |
| 924 | // printf("spsm=%d x=%d ex=%d y=%d len=%d\n", BITBLTBUF.SPSM, x, ex, y, len); |
| 925 | |
| 926 | switch (BITBLTBUF.SPSM) |
| 927 | { |
| 928 | case PSMCT32: |
| 929 | case PSMZ32: |
| 930 | { |
| 931 | // MGS1 intro, fade effect between two scenes (airplane outside-inside transition) |
| 932 | |
| 933 | int x = tx; |
| 934 | int y = ty; |
| 935 | int ex = sx + w; |
| 936 | |
| 937 | len /= 4; |
| 938 | |
| 939 | u32* vm = mem.vm32(); |
| 940 | GSOffset::PAHelper pa = off.assertSizesMatch(GSLocalMemory::swizzle32).paMulti(0, y); |
| 941 | |
| 942 | while (len > 0) |
| 943 | { |
| 944 | for (; len > 0 && x < ex && (x & 7); len--, x++, pd++) |
| 945 | { |
| 946 | *pd = vm[pa.value(x)]; |
| 947 | } |
| 948 | |
| 949 | // aligned to a column |
| 950 | |
| 951 | for (int ex8 = ex - 8; len >= 8 && x <= ex8; len -= 8, x += 8, pd += 8) |
| 952 | { |
| 953 | u32* ps = &vm[pa.value(x)]; |
| 954 | |
| 955 | GSVector4i::store<false>(&pd[0], GSVector4i::load(ps + 0, ps + 4)); |
| 956 | GSVector4i::store<false>(&pd[4], GSVector4i::load(ps + 8, ps + 12)); |
| 957 | |
| 958 | for (int i = 0; i < 8; i++) |
| 959 | pxAssert(pd[i] == vm[pa.value(x + i)]); |
| 960 | } |
| 961 |
no test coverage detected