diff --git a/RSDKv4/Drawing.cpp b/RSDKv4/Drawing.cpp index 7228c11e7..916209c01 100644 --- a/RSDKv4/Drawing.cpp +++ b/RSDKv4/Drawing.cpp @@ -3846,6 +3846,394 @@ void DrawSpriteRotozoom(int direction, int XPos, int YPos, int pivotX, int pivot #endif } +void DrawSpriteAllEffect(int direction, int XPos, int YPos, int pivotX, int pivotY, int sprX, int sprY, int width, int height, int rotation, int scale, + int sheetID, int alpha, int ink, int flags) +{ +#if RETRO_SOFTWARE_RENDER + //check flags + if ((flags & FX_INK) == 0) + ink = INK_NONE; + if ((flags & FX_SCALE) == 0) + scale = 0x200; + if ((flags & FX_ROTATE) == 0) + rotation = 0; + if ((flags & 3) == 0) + direction = FLIP_NONE; + + if ((ink > INK_NONE) && (alpha == 0)) + return; + + if (alpha > 0xFF) + alpha = 0xFF; + + if (scale == 0) + return; + + int sprXPos = (pivotX + sprX) << 9; + int sprYPos = (pivotY + sprY) << 9; + int fullwidth = width + sprX; + int fullheight = height + sprY; + int angle = rotation & 0x1FF; + if (angle < 0) + angle += 0x200; + if (angle) + angle = 0x200 - angle; + int sine = scale * sin512LookupTable[angle] >> 9; + int cosine = scale * cos512LookupTable[angle] >> 9; + int xPositions[4]; + int yPositions[4]; + + if (direction == FLIP_X) { + xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX + 2)) >> 9); + yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX + 2)) >> 9); + xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (pivotX - width - 2)) >> 9); + yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (pivotX - width - 2)) >> 9); + xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (pivotX + 2)) >> 9); + yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (pivotX + 2)) >> 9); + int a = pivotX - width - 2; + int b = height - pivotY + 2; + xPositions[3] = XPos + ((sine * b + cosine * a) >> 9); + yPositions[3] = YPos + ((cosine * b - sine * a) >> 9); + } + else if (direction == FLIP_Y) { + xPositions[0] = XPos + ((sine * (pivotY + 2) + cosine * (-pivotX - 2)) >> 9); + yPositions[0] = YPos + ((cosine * (pivotY + 2) - sine * (-pivotX - 2)) >> 9); + xPositions[1] = XPos + ((sine * (pivotY + 2) + cosine * (width - pivotX + 2)) >> 9); + yPositions[1] = YPos + ((cosine * (pivotY + 2) - sine * (width - pivotX + 2)) >> 9); + xPositions[2] = XPos + ((sine * (pivotY - height - 2) + cosine * (-pivotX - 2)) >> 9); + yPositions[2] = YPos + ((cosine * (pivotY - height - 2) - sine * (-pivotX - 2)) >> 9); + int a = width - pivotX + 2; + int b = pivotY - height - 2; + xPositions[3] = XPos + ((sine * b + cosine * a) >> 9); + yPositions[3] = YPos + ((cosine * b - sine * a) >> 9); + } + else if (direction == FLIP_XY) { + xPositions[0] = XPos + ((sine * (pivotY + 2) + cosine * (pivotX + 2)) >> 9); + yPositions[0] = YPos + ((cosine * (pivotY + 2) - sine * (pivotX + 2)) >> 9); + xPositions[1] = XPos + ((sine * (pivotY + 2) + cosine * (pivotX - width - 2)) >> 9); + yPositions[1] = YPos + ((cosine * (pivotY + 2) - sine * (pivotX - width - 2)) >> 9); + xPositions[2] = XPos + ((sine * (pivotY - height - 2) + cosine * (pivotX + 2)) >> 9); + yPositions[2] = YPos + ((cosine * (pivotY - height - 2) - sine * (pivotX + 2)) >> 9); + int a = pivotX - width - 2; + int b = pivotY - height - 2; + xPositions[3] = XPos + ((sine * b + cosine * a) >> 9); + yPositions[3] = YPos + ((cosine * b - sine * a) >> 9); + } + else { + xPositions[0] = XPos + ((sine * (-pivotY - 2) + cosine * (-pivotX - 2)) >> 9); + yPositions[0] = YPos + ((cosine * (-pivotY - 2) - sine * (-pivotX - 2)) >> 9); + xPositions[1] = XPos + ((sine * (-pivotY - 2) + cosine * (width - pivotX + 2)) >> 9); + yPositions[1] = YPos + ((cosine * (-pivotY - 2) - sine * (width - pivotX + 2)) >> 9); + xPositions[2] = XPos + ((sine * (height - pivotY + 2) + cosine * (-pivotX - 2)) >> 9); + yPositions[2] = YPos + ((cosine * (height - pivotY + 2) - sine * (-pivotX - 2)) >> 9); + int a = width - pivotX + 2; + int b = height - pivotY + 2; + xPositions[3] = XPos + ((sine * b + cosine * a) >> 9); + yPositions[3] = YPos + ((cosine * b - sine * a) >> 9); + } + int truescale = (signed int)(float)((float)(512.0 / (float)scale) * 512.0); + sine = truescale * sin512LookupTable[angle] >> 9; + cosine = truescale * cos512LookupTable[angle] >> 9; + + int left = GFX_LINESIZE; + for (int i = 0; i < 4; ++i) { + if (xPositions[i] < left) + left = xPositions[i]; + } + if (left < 0) + left = 0; + + int right = 0; + for (int i = 0; i < 4; ++i) { + if (xPositions[i] > right) + right = xPositions[i]; + } + if (right > GFX_LINESIZE) + right = GFX_LINESIZE; + int maxX = right - left; + + int top = SCREEN_YSIZE; + for (int i = 0; i < 4; ++i) { + if (yPositions[i] < top) + top = yPositions[i]; + } + if (top < 0) + top = 0; + + int bottom = 0; + for (int i = 0; i < 4; ++i) { + if (yPositions[i] > bottom) + bottom = yPositions[i]; + } + if (bottom > SCREEN_YSIZE) + bottom = SCREEN_YSIZE; + int maxY = bottom - top; + + if (maxX <= 0 || maxY <= 0) + return; + + //ink tables here + ushort *fbufferBlend = &blendLookupTable[0x20 * (0xFF - alpha)]; + ushort *pixelBlend = &blendLookupTable[0x20 * alpha]; + ushort *blendTablePtr = &blendLookupTable[0x20 * alpha]; + ushort *subBlendTable = &subtractLookupTable[0x20 * alpha]; + + GFXSurface *surface = &gfxSurface[sheetID]; + int pitch = GFX_LINESIZE - maxX; + int lineSize = surface->widthShift; + ushort *frameBufferPtr = &Engine.frameBuffer[left + GFX_LINESIZE * top]; + byte *lineBuffer = &gfxLineBuffer[top]; + int startX = left - XPos; + int startY = top - YPos; + int shiftPivot = (sprX << 9) - 1; + fullwidth <<= 9; + int shiftheight = (sprY << 9) - 1; + fullheight <<= 9; + byte *gfxData = &graphicData[surface->dataPosition]; + if (cosine < 0 || sine < 0) + sprYPos += sine + cosine; + + if (direction == FLIP_X) { + int drawX = sprXPos - (cosine * startX - sine * startY) - (truescale >> 1); + int drawY = cosine * startY + sprYPos + sine * startX; + while (maxY--) { + activePalette = fullPalette[*lineBuffer]; + activePalette32 = fullPalette32[*lineBuffer]; + lineBuffer++; + int finalX = drawX; + int finalY = drawY; + int w = maxX; + while (w--) { + if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) { + byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)]; + if (index > 0) { + + ushort color = activePalette[index]; + int R; + int G; + int B; + switch (ink) { + case INK_NONE: + *frameBufferPtr = activePalette[index]; + break; + case INK_BLEND: + *frameBufferPtr = ((activePalette[index] & 0xF7DE) >> 1) + ((*frameBufferPtr & 0xF7DE) >> 1); + break; + case INK_ALPHA: + R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11; + G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6; + B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[color & 0x1F]; + + *frameBufferPtr = R | G | B; + break; + case INK_ADD: + R = minVal((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBufferPtr & 0xF800), 0xF800); + G = minVal((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBufferPtr & 0x7E0), 0x7E0); + B = minVal(blendTablePtr[color & 0x1F] + (*frameBufferPtr & 0x1F), 0x1F); + + *frameBufferPtr = R | G | B; + break; + case INK_SUB: + R = maxVal((*frameBufferPtr & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0); + G = maxVal((*frameBufferPtr & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0); + B = maxVal((*frameBufferPtr & 0x1F) - subBlendTable[color & 0x1F], 0); + + *frameBufferPtr = R | G | B; + break; + } + } + } + ++frameBufferPtr; + finalX -= cosine; + finalY += sine; + } + drawX += sine; + drawY += cosine; + frameBufferPtr += pitch; + } + } + else if (direction == FLIP_Y) { + int drawX = sprXPos + cosine * startX - sine * startY; + int drawY = sprYPos - (cosine * startY + sine * startX); + while (maxY--) { + activePalette = fullPalette[*lineBuffer]; + activePalette32 = fullPalette32[*lineBuffer]; + lineBuffer++; + int finalX = drawX; + int finalY = drawY; + int w = maxX; + while (w--) { + if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) { + byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)]; + if (index > 0) { + + ushort color = activePalette[index]; + int R; + int G; + int B; + switch (ink) { + case INK_NONE: + *frameBufferPtr = activePalette[index]; + break; + case INK_BLEND: + *frameBufferPtr = ((activePalette[index] & 0xF7DE) >> 1) + ((*frameBufferPtr & 0xF7DE) >> 1); + break; + case INK_ALPHA: + R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11; + G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6; + B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[color & 0x1F]; + + *frameBufferPtr = R | G | B; + break; + case INK_ADD: + R = minVal((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBufferPtr & 0xF800), 0xF800); + G = minVal((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBufferPtr & 0x7E0), 0x7E0); + B = minVal(blendTablePtr[color & 0x1F] + (*frameBufferPtr & 0x1F), 0x1F); + + *frameBufferPtr = R | G | B; + break; + case INK_SUB: + R = maxVal((*frameBufferPtr & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0); + G = maxVal((*frameBufferPtr & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0); + B = maxVal((*frameBufferPtr & 0x1F) - subBlendTable[color & 0x1F], 0); + + *frameBufferPtr = R | G | B; + break; + } + } + + } + ++frameBufferPtr; + finalX += cosine; + finalY -= sine; + } + drawX -= sine; + drawY -= cosine; + frameBufferPtr += pitch; + } + } + else if (direction == FLIP_XY) { + int drawX = sprXPos - (cosine * startX - sine * startY) - (truescale >> 1); + int drawY = sprYPos - (cosine * startY + sine * startX); + while (maxY--) { + activePalette = fullPalette[*lineBuffer]; + activePalette32 = fullPalette32[*lineBuffer]; + lineBuffer++; + int finalX = drawX; + int finalY = drawY; + int w = maxX; + while (w--) { + if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) { + byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)]; + if (index > 0) { + + ushort color = activePalette[index]; + int R; + int G; + int B; + switch (ink) { + case INK_NONE: + *frameBufferPtr = activePalette[index]; + break; + case INK_BLEND: + *frameBufferPtr = ((activePalette[index] & 0xF7DE) >> 1) + ((*frameBufferPtr & 0xF7DE) >> 1); + break; + case INK_ALPHA: + R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11; + G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6; + B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[color & 0x1F]; + + *frameBufferPtr = R | G | B; + break; + case INK_ADD: + R = minVal((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBufferPtr & 0xF800), 0xF800); + G = minVal((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBufferPtr & 0x7E0), 0x7E0); + B = minVal(blendTablePtr[color & 0x1F] + (*frameBufferPtr & 0x1F), 0x1F); + + *frameBufferPtr = R | G | B; + break; + case INK_SUB: + R = maxVal((*frameBufferPtr & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0); + G = maxVal((*frameBufferPtr & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0); + B = maxVal((*frameBufferPtr & 0x1F) - subBlendTable[color & 0x1F], 0); + + *frameBufferPtr = R | G | B; + break; + } + } + + } + ++frameBufferPtr; + finalX -= cosine; + finalY -= sine; + } + drawX += sine; + drawY -= cosine; + frameBufferPtr += pitch; + } + } + else { + int drawX = sprXPos + cosine * startX - sine * startY; + int drawY = cosine * startY + sprYPos + sine * startX; + while (maxY--) { + activePalette = fullPalette[*lineBuffer]; + activePalette32 = fullPalette32[*lineBuffer]; + lineBuffer++; + int finalX = drawX; + int finalY = drawY; + int w = maxX; + while (w--) { + if (finalX > shiftPivot && finalX < fullwidth && finalY > shiftheight && finalY < fullheight) { + byte index = gfxData[(finalY >> 9 << lineSize) + (finalX >> 9)]; + if (index > 0) { + + ushort color = activePalette[index]; + int R; + int G; + int B; + switch (ink) { + case INK_NONE: + *frameBufferPtr = activePalette[index]; + break; + case INK_BLEND: + *frameBufferPtr = ((activePalette[index] & 0xF7DE) >> 1) + ((*frameBufferPtr & 0xF7DE) >> 1); + break; + case INK_ALPHA: + R = (fbufferBlend[(*frameBufferPtr & 0xF800) >> 11] + pixelBlend[(color & 0xF800) >> 11]) << 11; + G = (fbufferBlend[(*frameBufferPtr & 0x7E0) >> 6] + pixelBlend[(color & 0x7E0) >> 6]) << 6; + B = fbufferBlend[*frameBufferPtr & 0x1F] + pixelBlend[color & 0x1F]; + + *frameBufferPtr = R | G | B; + break; + case INK_ADD: + R = minVal((blendTablePtr[(color & 0xF800) >> 11] << 11) + (*frameBufferPtr & 0xF800), 0xF800); + G = minVal((blendTablePtr[(color & 0x7E0) >> 6] << 6) + (*frameBufferPtr & 0x7E0), 0x7E0); + B = minVal(blendTablePtr[color & 0x1F] + (*frameBufferPtr & 0x1F), 0x1F); + + *frameBufferPtr = R | G | B; + break; + case INK_SUB: + R = maxVal((*frameBufferPtr & 0xF800) - (subBlendTable[(color & 0xF800) >> 11] << 11), 0); + G = maxVal((*frameBufferPtr & 0x7E0) - (subBlendTable[(color & 0x7E0) >> 6] << 6), 0); + B = maxVal((*frameBufferPtr & 0x1F) - subBlendTable[color & 0x1F], 0); + + *frameBufferPtr = R | G | B; + break; + } + } + } + ++frameBufferPtr; + finalX += cosine; + finalY += sine; + } + drawX -= sine; + drawY += cosine; + frameBufferPtr += pitch; + } + } +#endif +} + void DrawBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int sheetID) { #if RETRO_SOFTWARE_RENDER @@ -4678,7 +5066,7 @@ void DrawTexturedFaceBlended(void *v, byte sheetID) } ushort *fbPtr = &frameBufferPtr[startX]; frameBufferPtr += GFX_LINESIZE; - int counter = posDifference + 1; + int counter = posDifference; while (counter--) { if (UPos < 0) UPos = 0; diff --git a/RSDKv4/Drawing.hpp b/RSDKv4/Drawing.hpp index ff370cc68..f53039ad1 100644 --- a/RSDKv4/Drawing.hpp +++ b/RSDKv4/Drawing.hpp @@ -6,9 +6,16 @@ #define DRAWLAYER_COUNT (7) +//changing DrawFXFlags so they can be merged with binary +#define FX_FLIP (1) +#define FX_ROTATE (2) +#define FX_SCALE (4) +#define FX_ROTOZOOM (6) +#define FX_INK (8) +#define FX_TINT (16) enum FlipFlags { FLIP_NONE, FLIP_X, FLIP_Y, FLIP_XY }; enum InkFlags { INK_NONE, INK_BLEND, INK_ALPHA, INK_ADD, INK_SUB }; -enum DrawFXFlags { FX_SCALE, FX_ROTATE, FX_ROTOZOOM, FX_INK, FX_TINT, FX_FLIP }; +//enum DrawFXFlags { FX_SCALE, FX_ROTATE, FX_ROTOZOOM, FX_INK, FX_TINT, FX_FLIP }; struct DrawListEntry { int entityRefs[ENTITY_COUNT]; @@ -128,6 +135,8 @@ void DrawSpriteRotated(int direction, int XPos, int YPos, int pivotX, int pivotY int sheetID); void DrawSpriteRotozoom(int direction, int XPos, int YPos, int pivotX, int pivotY, int sprX, int sprY, int width, int height, int rotation, int scale, int sheetID); +void DrawSpriteAllEffect(int direction, int XPos, int YPos, int pivotX, int pivotY, int sprX, int sprY, int width, int height, int rotation, int scale, + int sheetID, int alpha, int ink, int flags); void DrawBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int sheetID); void DrawAlphaBlendedSprite(int XPos, int YPos, int width, int height, int sprX, int sprY, int alpha, int sheetID); diff --git a/RSDKv4/Script.cpp b/RSDKv4/Script.cpp index 627cd2a9a..ded7c87b4 100644 --- a/RSDKv4/Script.cpp +++ b/RSDKv4/Script.cpp @@ -540,10 +540,11 @@ const FunctionInfo functions[] = { AliasInfo publicAliases[ALIAS_COUNT] = { AliasInfo("true", "1"), AliasInfo("false", "0"), - AliasInfo("FX_SCALE", "0"), - AliasInfo("FX_ROTATE", "1"), - AliasInfo("FX_ROTOZOOM", "2"), - AliasInfo("FX_INK", "3"), + AliasInfo("FX_FLIP", "1"), + AliasInfo("FX_ROTATE", "2"), + AliasInfo("FX_SCALE", "4"), + AliasInfo("FX_ROTOZOOM", "6"), + AliasInfo("FX_INK", "8"), AliasInfo("PRESENTATION_STAGE", "0"), AliasInfo("REGULAR_STAGE", "1"), AliasInfo("BONUS_STAGE", "2"), @@ -557,7 +558,6 @@ AliasInfo publicAliases[ALIAS_COUNT] = { AliasInfo("MAT_WORLD", "0"), AliasInfo("MAT_VIEW", "1"), AliasInfo("MAT_TEMP", "2"), - AliasInfo("FX_FLIP", "5"), AliasInfo("FACING_LEFT", "1"), AliasInfo("FACING_RIGHT", "0"), AliasInfo("FLIP_NONE", "0"), @@ -4530,6 +4530,12 @@ void ProcessScript(int scriptCodePtr, int jumpTablePtr, byte scriptEvent) case FUNC_DRAWSPRITEFX: opcodeSize = 0; spriteFrame = &scriptFrames[scriptInfo->frameListOffset + scriptEng.operands[0]]; + DrawSpriteAllEffect(entity->direction, (scriptEng.operands[2] >> 16) - xScrollOffset, + (scriptEng.operands[3] >> 16) - yScrollOffset, -spriteFrame->pivotX, -spriteFrame->pivotY, + spriteFrame->sprX, spriteFrame->sprY, spriteFrame->width, spriteFrame->height, entity->rotation, + entity->scale, scriptInfo->spriteSheetID, entity->alpha, entity->inkEffect, scriptEng.operands[1]); + break; + /* switch (scriptEng.operands[1]) { default: break; case FX_SCALE: @@ -4625,9 +4631,15 @@ void ProcessScript(int scriptCodePtr, int jumpTablePtr, byte scriptEvent) break; } break; + */ case FUNC_DRAWSPRITESCREENFX: opcodeSize = 0; spriteFrame = &scriptFrames[scriptInfo->frameListOffset + scriptEng.operands[0]]; + DrawSpriteAllEffect(entity->direction, scriptEng.operands[2], scriptEng.operands[3], -spriteFrame->pivotX, + -spriteFrame->pivotY, spriteFrame->sprX, spriteFrame->sprY, spriteFrame->width, spriteFrame->height, + entity->rotation, entity->scale, scriptInfo->spriteSheetID, entity->alpha, entity->inkEffect, scriptEng.operands[1]); + break; + /* switch (scriptEng.operands[1]) { default: break; case FX_SCALE: @@ -4712,6 +4724,7 @@ void ProcessScript(int scriptCodePtr, int jumpTablePtr, byte scriptEvent) break; } break; + */ case FUNC_LOADANIMATION: opcodeSize = 0; scriptInfo->animFile = AddAnimationFile(scriptText);