From caf50e42101d9ec5572bf553f0ce4e228c0698a6 Mon Sep 17 00:00:00 2001 From: YohannDR Date: Tue, 15 Nov 2022 22:28:24 +0100 Subject: [PATCH] Increase matching % of SpriteDraw --- include/data/generic_data.h | 2 +- include/macros.h | 3 + include/oam.h | 25 +++++- include/sprite.h | 2 +- src/particle.c | 14 +-- src/sprite.c | 163 ++++++++++++++++++++-------------- src/sprites_AI/acid_worm.c | 4 +- src/sprites_AI/imago_cocoon.c | 4 +- src/sprites_AI/ruins_test.c | 8 +- 9 files changed, 137 insertions(+), 88 deletions(-) diff --git a/include/data/generic_data.h b/include/data/generic_data.h index b069ae77..adb36cf0 100644 --- a/include/data/generic_data.h +++ b/include/data/generic_data.h @@ -4,7 +4,7 @@ #include "types.h" #include "callbacks.h" -static const i16 sSineYValues[320] = { +static const i16 sSineTable[320] = { 0, 6, 12, 18, 25, 31, 37, 43, 49, 56, 62, 68, 74, 80, 86, 92, 97, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176, 181, 185, 189, 193, diff --git a/include/macros.h b/include/macros.h index 4291cfac..001b822f 100644 --- a/include/macros.h +++ b/include/macros.h @@ -7,6 +7,9 @@ #define check_samus_turning() ((pData->direction ^ (KEY_RIGHT | KEY_LEFT)) & gButtonInput) +#define sin(a) (sSineTable[(a)]) +#define cos(a) (sSineTable[(a) + 64]) + #define INCBIN(...) {0} #define INCBIN_U8 INCBIN #define INCBIN_U16 INCBIN diff --git a/include/oam.h b/include/oam.h index aca61e89..48765544 100644 --- a/include/oam.h +++ b/include/oam.h @@ -51,7 +51,7 @@ union OamData { u32 shape:2; // 0x40, 0x80 -> 0xC0 /*0x01*/ u32 x:9; - u32 matrixNum:3; // bits 3/4 are h-flip/v-flip if not in affine mode + u32 matrixNum:3; u32 xFlip:1; u32 yFlip:1; u32 size:2; // 0x4000, 0x8000 -> 0xC000 @@ -63,7 +63,28 @@ union OamData { /*0x03*/ u16 fractional:8; u16 integer:7; u16 sign:1; - } split; + } splitFlip; + + struct { + /*0x00*/ u32 y:8; + u32 affineMode:2; // 0x1, 0x2 -> 0x4 + u32 objMode:2; // 0x4, 0x8 -> 0xC + u32 mosaic:1; // 0x10 + u32 bpp:1; // 0x20 + u32 shape:2; // 0x40, 0x80 -> 0xC0 + + /*0x01*/ u32 x:9; + u32 matrixNum:5; + u32 size:2; // 0x4000, 0x8000 -> 0xC000 + + /*0x02*/ u16 tileNum:10; // 0x3FF + u16 priority:2; // 0x400, 0x800 -> 0xC00 + u16 paletteNum:4; + + /*0x03*/ u16 fractional:8; + u16 integer:7; + u16 sign:1; + } splitMatrix; struct { u16 attr0; diff --git a/include/sprite.h b/include/sprite.h index b4a74e16..c7d92745 100644 --- a/include/sprite.h +++ b/include/sprite.h @@ -10,7 +10,7 @@ void SpriteUpdateAnimation(struct SpriteData* pSprite); void SpriteDrawAll_2(void); void SpriteDrawAll(void); void SpriteDrawAll_Upper(void); -void SpriteDraw(struct SpriteData* pSprite, u32 slot); +void SpriteDraw(struct SpriteData* pSprite, i32 slot); void SpriteCheckOnScreen(struct SpriteData* pSprite); void SpriteLoadAllData(void); void SpriteLoadSpriteset(void); diff --git a/src/particle.c b/src/particle.c index cf8cb86e..41318f61 100644 --- a/src/particle.c +++ b/src/particle.c @@ -129,21 +129,21 @@ void ParticleDraw(struct ParticleEffect* pParticle) { part = *src++; *dst++ = part; - gOamData[currSlot + i].split.y = part + yPosition; + gOamData[currSlot + i].splitFlip.y = part + yPosition; part = *src++; *dst++ = part; - gOamData[currSlot + i].split.x = part + xPosition; + gOamData[currSlot + i].splitFlip.x = part + xPosition; *dst++ = *src++; - gOamData[currSlot + i].split.priority = bgPriority; + gOamData[currSlot + i].splitFlip.priority = bgPriority; if (flipped) { - gOamData[currSlot + i].split.xFlip ^= 0x1; - shape = gOamData[currSlot + i].split.shape; - size = gOamData[currSlot + i].split.size; - gOamData[currSlot + i].split.x = xPosition - (part + sOamXFlipOffsets[shape][size] * 8); + gOamData[currSlot + i].splitFlip.xFlip ^= TRUE; + shape = gOamData[currSlot + i].splitFlip.shape; + size = gOamData[currSlot + i].splitFlip.size; + gOamData[currSlot + i].splitFlip.x = xPosition - (part + sOamXFlipOffsets[shape][size] * 8); } dst++; diff --git a/src/sprite.c b/src/sprite.c index 94577248..3512d3e5 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -300,19 +300,18 @@ void SpriteDrawAll_Upper(void) } } -void SpriteDraw(struct SpriteData* pSprite, u32 slot) +void SpriteDraw(struct SpriteData* pSprite, i32 slot) { // https://decomp.me/scratch/7FvMo const u16* src; u16* dst; + i32 i; u16 partCount; - u32 currSlot; u8 prevSlot; u16 part1; u16 part2; u8 part3; - u32 i; u16 xFlip; u16 yFlip; @@ -321,17 +320,17 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) u16 facingDown; u16 mosaic; + u32 gfxOffset; + u32 paletteRow; + u32 bgPriority; u16 yPosition; u16 xPosition; - u32 paletteRow; - u32 gfxOffset; - u32 bgPriority; + u32 shape; u32 size; u16 rotation; u16 scaling; - i16 sine; u16 dy; u16 dmy; @@ -350,7 +349,7 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) src = pSprite->pOam[pSprite->currentAnimationFrame].pFrame; partCount = *src++; - if (prevSlot + partCount >= 0x80) + if (partCount + prevSlot >= 0x80) return; dst = (u16*)(gOamData + prevSlot); @@ -386,46 +385,47 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) *dst++ = part2; *dst = *src++; // Copy source and save part 1 and 2 - currSlot = prevSlot + i; - gOamData[currSlot].split.y = part1 + yPosition; - gOamData[currSlot].split.x = part2 + xPosition; - gOamData[currSlot].split.priority = bgPriority; - gOamData[currSlot].split.paletteNum = paletteRow; - gOamData[currSlot].split.tileNum += gfxOffset; + gOamData[prevSlot + i].splitFlip.y = part1 + yPosition; + gOamData[prevSlot + i].splitFlip.x = part2 + xPosition; + gOamData[prevSlot + i].splitFlip.priority = bgPriority; + gOamData[prevSlot + i].splitFlip.paletteNum = paletteRow; + gOamData[prevSlot + i].splitFlip.tileNum += gfxOffset; if (xFlip) { - gOamData[currSlot].split.xFlip ^= TRUE; - shape = gOamData[currSlot].split.shape; - size = gOamData[currSlot].split.size; - gOamData[currSlot].split.x = xPosition - (part1 + sOamXFlipOffsets[shape][size] * 8); + gOamData[prevSlot + i].splitFlip.xFlip ^= TRUE; + shape = gOamData[prevSlot + i].splitFlip.shape; + size = gOamData[prevSlot + i].splitFlip.size; + gOamData[prevSlot + i].splitFlip.x = xPosition - (part1 + sOamXFlipOffsets[shape][size] * 8); } if (facingDown) { - gOamData[currSlot].split.yFlip ^= TRUE; - shape = gOamData[currSlot].split.shape; - size = gOamData[currSlot].split.size; - gOamData[currSlot].split.y = yPosition - (part2 + sOamYFlipOffsets[shape][size] * 8); + gOamData[prevSlot + i].splitFlip.yFlip ^= TRUE; + shape = gOamData[prevSlot + i].splitFlip.shape; + size = gOamData[prevSlot + i].splitFlip.size; + gOamData[prevSlot + i].splitFlip.y = yPosition - (part2 + sOamYFlipOffsets[shape][size] * 8); } if (yFlip) { if (doubleSize) - gOamData[currSlot].split.affineMode = 3; + gOamData[prevSlot + i].splitFlip.affineMode = 3; else - gOamData[currSlot].split.affineMode = 1; + gOamData[prevSlot + i].splitFlip.affineMode = 1; - // . + gOamData[prevSlot + i].splitFlip.yFlip = slot >> 4; + gOamData[prevSlot + i].splitFlip.xFlip = slot >> 3; + gOamData[prevSlot + i].splitFlip.matrixNum = slot; } if (alphaBlending) - gOamData[currSlot].split.objMode = 1; // Semi transparent + gOamData[prevSlot + i].splitFlip.objMode = 1; // Semi transparent dst++; } - gNextOAMSlot = prevSlot + partCount; + gNextOAMSlot = partCount + prevSlot; if (yFlip) { @@ -434,23 +434,17 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) if (xFlip) { - sine = sSineYValues[rotation + 0x40]; - gOamData[slot * 4].all.affineParam = FixedMultiplication(sine, FixedInverse(scaling)); - sine = sSineYValues[rotation]; - gOamData[slot * 4 + 1].all.affineParam = FixedMultiplication(sine, FixedInverse(scaling)); + gOamData[slot * 4].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(scaling)); + gOamData[slot * 4 + 1].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(scaling)); } else { - sine = sSineYValues[rotation + 0x40]; - gOamData[slot * 4].all.affineParam = FixedMultiplication(sine, FixedInverse(-scaling)); - sine = sSineYValues[rotation]; - gOamData[slot * 4 + 1].all.affineParam = FixedMultiplication(sine, FixedInverse(-scaling)); + gOamData[slot * 4].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(-scaling)); + gOamData[slot * 4 + 1].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(-scaling)); } - sine = sSineYValues[rotation]; - gOamData[slot * 4 + 2].all.affineParam = FixedMultiplication(-sine, FixedInverse(scaling)); - sine = sSineYValues[rotation + 0x40]; - gOamData[slot * 4 + 3].all.affineParam = FixedMultiplication(sine, FixedInverse(scaling)); + gOamData[slot * 4 + 2].all.affineParam = FixedMultiplication(-sin(rotation), FixedInverse(scaling)); + gOamData[slot * 4 + 3].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(scaling)); } } else @@ -471,13 +465,13 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) *dst++ = part2; part3 = *dst = *src++; // Copy source and save part 1, 2 and 3 - gOamData[currSlot].split.priority = bgPriority; - gOamData[currSlot].split.paletteNum = paletteRow; + gOamData[prevSlot + i].splitFlip.priority = bgPriority; + gOamData[prevSlot + i].splitFlip.paletteNum = paletteRow; - gOamData[currSlot].split.tileNum += gfxOffset; + gOamData[prevSlot + i].splitFlip.tileNum += gfxOffset; - shape = gOamData[currSlot].split.shape; - size = gOamData[currSlot].split.size; + shape = gOamData[prevSlot + i].splitFlip.shape; + size = gOamData[prevSlot + i].splitFlip.size; yOffset = sOamYFlipOffsets[shape][size] * 4; xOffset = sOamXFlipOffsets[shape][size]; @@ -491,64 +485,95 @@ void SpriteDraw(struct SpriteData* pSprite, u32 slot) yParam = tempY + (yParam * scaling - yParam); xParam = tempX + (xParam * scaling - xParam); - m11 = sSineYValues[rotation + 0x40] * xParam; - m12 = sSineYValues[rotation] * yParam; - m21 = sSineYValues[rotation + 0x40] * yParam; - m22 = sSineYValues[rotation] * xParam; + m11 = cos(rotation) * xParam; + m12 = sin(rotation) * yParam; + m21 = cos(rotation) * yParam; + m22 = sin(rotation) * xParam; if (doubleSize) { - + xOffset *= -0x8; + yOffset *= -0x8; } else { - + xOffset *= -0x4; + yOffset *= -0x4; } - gOamData[currSlot].split.y = m11 - m12 - yOffset + (yPosition - BLOCK_SIZE); - gOamData[currSlot].split.x = m21 - m22 - xOffset + (xPosition - BLOCK_SIZE); + gOamData[prevSlot + i].splitFlip.y = m11 + m12 - yOffset + (yPosition - BLOCK_SIZE); + gOamData[prevSlot + i].splitFlip.x = m21 - m22 - xOffset + (xPosition - BLOCK_SIZE); if (doubleSize) - gOamData[currSlot].split.affineMode = 3; + gOamData[prevSlot + i].splitFlip.affineMode = 3; else - gOamData[currSlot].split.affineMode = 1; + gOamData[prevSlot + i].splitFlip.affineMode = 1; - // . Mosaic + if (mosaic) + { + if (gOamData[prevSlot + i].splitFlip.xFlip) + { + gOamData[prevSlot + i].splitFlip.x--; + gOamData[prevSlot + i].splitFlip.yFlip = TRUE; + gOamData[prevSlot + i].splitFlip.xFlip = TRUE; + gOamData[prevSlot + i].splitFlip.matrixNum = 5; + } + else + { + gOamData[prevSlot + i].splitFlip.yFlip = TRUE; + gOamData[prevSlot + i].splitFlip.xFlip = TRUE; + gOamData[prevSlot + i].splitFlip.matrixNum = 4; + } + } + else + { + if (gOamData[prevSlot + i].splitFlip.xFlip) + { + gOamData[prevSlot + i].splitFlip.x--; + gOamData[prevSlot + i].splitFlip.yFlip = TRUE; + gOamData[prevSlot + i].splitFlip.xFlip = TRUE; + gOamData[prevSlot + i].splitFlip.matrixNum = 7; + } + else + { + gOamData[prevSlot + i].splitFlip.yFlip = TRUE; + gOamData[prevSlot + i].splitFlip.xFlip = TRUE; + gOamData[prevSlot + i].splitFlip.matrixNum = 6; + } + } if (alphaBlending) - gOamData[currSlot].split.objMode = 1; // Semi transparent + gOamData[prevSlot + i].splitFlip.objMode = 1; // Semi transparent dst++; } - gNextOAMSlot = prevSlot + partCount; + gNextOAMSlot = partCount + prevSlot; - sine = sSineYValues[rotation]; - dy = FixedMultiplication(-sine, FixedInverse(scaling)); - sine = sSineYValues[rotation + 0x40]; - dmy = FixedMultiplication(sine, FixedInverse(scaling)); + dy = FixedMultiplication(-sin(rotation), FixedInverse(scaling)); + dmy = FixedMultiplication(cos(rotation), FixedInverse(scaling)); if (mosaic) { - gOamData[112].all.affineParam = FixedMultiplication(sine, FixedInverse(scaling)); - gOamData[113].all.affineParam = FixedMultiplication(sSineYValues[rotation], FixedInverse(scaling)); + gOamData[112].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(scaling)); + gOamData[113].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(scaling)); gOamData[114].all.affineParam = dy; gOamData[115].all.affineParam = dmy; - gOamData[116].all.affineParam = FixedMultiplication(sine, FixedInverse(-scaling)); - gOamData[117].all.affineParam = FixedMultiplication(sSineYValues[rotation], FixedInverse(-scaling)); + gOamData[116].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(-scaling)); + gOamData[117].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(-scaling)); gOamData[118].all.affineParam = dy; gOamData[119].all.affineParam = dmy; } else { - gOamData[120].all.affineParam = FixedMultiplication(sine, FixedInverse(scaling)); - gOamData[121].all.affineParam = FixedMultiplication(sSineYValues[rotation], FixedInverse(scaling)); + gOamData[120].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(scaling)); + gOamData[121].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(scaling)); gOamData[122].all.affineParam = dy; gOamData[123].all.affineParam = dmy; - gOamData[124].all.affineParam = FixedMultiplication(sine, FixedInverse(-scaling)); - gOamData[125].all.affineParam = FixedMultiplication(sSineYValues[rotation], FixedInverse(-scaling)); + gOamData[124].all.affineParam = FixedMultiplication(cos(rotation), FixedInverse(-scaling)); + gOamData[125].all.affineParam = FixedMultiplication(sin(rotation), FixedInverse(-scaling)); gOamData[126].all.affineParam = dy; gOamData[127].all.affineParam = dmy; } diff --git a/src/sprites_AI/acid_worm.c b/src/sprites_AI/acid_worm.c index 6956acac..529d3fb9 100644 --- a/src/sprites_AI/acid_worm.c +++ b/src/sprites_AI/acid_worm.c @@ -63,7 +63,7 @@ void AcidWormSyncHeadPosition(void) else posOffset = (i16)(offset + (sine << 0x4)); - sine = r0 = sSineYValues[rotation]; + sine = r0 = sSineTable[rotation]; if (sine < 0x0) { sine = (i16)(-sine * posOffset >> 0x8); @@ -75,7 +75,7 @@ void AcidWormSyncHeadPosition(void) gCurrentSprite.yPosition = gSubSpriteData1.yPosition + sine; } - sine = sSineYValues[rotation + 0x40]; + sine = sSineTable[rotation + 0x40]; position = (i16)gSubSpriteData1.xPosition; if (gCurrentSprite.status & SPRITE_STATUS_FACING_RIGHT) position = (i16)(position + offset); diff --git a/src/sprites_AI/imago_cocoon.c b/src/sprites_AI/imago_cocoon.c index 6f011b25..dbee54b2 100644 --- a/src/sprites_AI/imago_cocoon.c +++ b/src/sprites_AI/imago_cocoon.c @@ -1249,7 +1249,7 @@ void WingedRipperMove(void) offset = gCurrentSprite.workVariable; // Update Y position - currentY = sSineYValues[offset]; + currentY = sSineTable[offset]; previousY = (i16)gCurrentSprite.yPosition; if (currentY < 0x0) @@ -1264,7 +1264,7 @@ void WingedRipperMove(void) } // Update X position - currentX = sSineYValues[offset + 0x40]; + currentX = sSineTable[offset + 0x40]; previousX = (i16)gCurrentSprite.xPosition; if (currentX < 0x0) diff --git a/src/sprites_AI/ruins_test.c b/src/sprites_AI/ruins_test.c index f42b7880..ef88de31 100644 --- a/src/sprites_AI/ruins_test.c +++ b/src/sprites_AI/ruins_test.c @@ -392,9 +392,9 @@ void RuinsTestGhostMove(u8 speed) multiplier = (i16)gCurrentSprite.oamScaling; offset = gCurrentSprite.workVariable; - sine = sSineYValues[offset]; + sine = sSineTable[offset]; - if (sSineYValues[offset] < 0x0) + if (sSineTable[offset] < 0x0) { sine = (i16)(-sine * multiplier >> 0x8); gCurrentSprite.yPosition = gCurrentSprite.yPositionSpawn - sine; @@ -405,9 +405,9 @@ void RuinsTestGhostMove(u8 speed) gCurrentSprite.yPosition = gCurrentSprite.yPositionSpawn + sine; } - sine = sSineYValues[offset + 0x40]; + sine = sSineTable[offset + 0x40]; - if (sSineYValues[offset + 0x40] < 0x0) + if (sSineTable[offset + 0x40] < 0x0) { sine = (i16)(-sine * multiplier >> 0x8); gCurrentSprite.xPosition = gCurrentSprite.xPositionSpawn - sine;