ft2-clone

Fasttracker 2 clone
Log | Files | Refs | README | LICENSE

commit 2dc801a4650666d198feb5970d63b20955fa19c4
parent 21bf3f4f5c1efed4024872ba6c59e606125733ed
Author: Olav Sørensen <olav.sorensen@live.no>
Date:   Tue, 25 Apr 2023 16:56:12 +0200

Alpha-based fade in for the about screen

Diffstat:
Msrc/ft2_about.c | 126+++++++++++++++++++++++++++++++++----------------------------------------------
Msrc/ft2_gui.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/ft2_gui.h | 9++++-----
Msrc/ft2_header.h | 2+-
4 files changed, 118 insertions(+), 105 deletions(-)

diff --git a/src/ft2_about.c b/src/ft2_about.c @@ -8,6 +8,7 @@ #include "ft2_structs.h" #define NUM_STARS 2048 +#define ALPHA_FADE_MILLISECS 2100 /* amount of milliseconds until content is fully faded in */ #define ABOUT_SCREEN_W 626 #define ABOUT_SCREEN_H 167 #define ABOUT_LOGO_W 449 @@ -27,13 +28,9 @@ typedef struct static char *customText1 = "Clone by Olav \"8bitbubsy\" S\025rensen"; static char *customText2 = "https://16-bits.org"; -static char customText3[64]; - -static int16_t customText1Y, customText2Y, customText3Y; -static int16_t customText1X, customText2X, customText3X; -static int32_t lastStarScreenPos[NUM_STARS], fadeValue; -static uint32_t randSeed, frameCounter; -static float f2pi; +static char customText3[256]; +static int16_t customText1Y, customText2Y, customText3Y, customText1X, customText2X, customText3X; +static uint32_t alphaValue, randSeed, frameCounter; static vector_t starPoints[NUM_STARS], rotation; static matrix_t matrix; @@ -51,15 +48,17 @@ static int32_t random32(void) static void rotateMatrix(void) { - const float xx = rotation.x * f2pi; +#define MY_PI_FLOAT 3.141592653589793f + + const float xx = rotation.x * MY_PI_FLOAT; const float sa = sinf(xx); const float ca = cosf(xx); - const float yy = rotation.y * f2pi; + const float yy = rotation.y * MY_PI_FLOAT; const float sb = sinf(yy); const float cb = cosf(yy); - const float zz = rotation.z * f2pi; + const float zz = rotation.z * MY_PI_FLOAT; const float sc = sinf(zz); const float cc = cosf(zz); @@ -75,14 +74,12 @@ static void rotateMatrix(void) // z matrix.x.z = cb * sc; - matrix.y.z = 0.0f - sb; + matrix.y.z = -sb; matrix.z.z = cb * cc; } static void aboutInit(void) { - f2pi = (float)(2.0 * 4.0 * atan(1.0)); // M_PI can not be trusted - vector_t *s = starPoints; for (int32_t i = 0; i < NUM_STARS; i++, s++) { @@ -92,8 +89,8 @@ static void aboutInit(void) } rotation.x = rotation.y = rotation.z = 0.0f; - for (int32_t i = 0; i < NUM_STARS; i++) - lastStarScreenPos[i] = -1; + alphaValue = 0; + frameCounter = 0; } static void starfield(void) @@ -101,88 +98,73 @@ static void starfield(void) vector_t *star = starPoints; for (int16_t i = 0; i < NUM_STARS; i++, star++) { - // erase last star pixel - int32_t screenBufferPos = lastStarScreenPos[i]; - if (screenBufferPos >= 0) - { - if (!(video.frameBuffer[screenBufferPos] & 0xFF000000)) - video.frameBuffer[screenBufferPos] = video.palette[PAL_BCKGRND]; - - lastStarScreenPos[i] = -1; - } - star->z += 0.00015f; - if (star->z >= 0.5f) star->z -= 1.0f; + if (star->z >= 0.5f) + star->z -= 1.0f; const float z = (matrix.x.z * star->x) + (matrix.y.z * star->y) + (matrix.z.z * star->z) + 0.5f; if (z <= 0.0f) continue; - float y = (((matrix.x.y * star->x) + (matrix.y.y * star->y) + (matrix.z.y * star->z)) / z) * 400.0f; - y += 2.0f + (ABOUT_SCREEN_H/2.0f); - - const int32_t outY = (int32_t)(y + 0.5f); // rounded - if ((uint32_t)outY > 2+ABOUT_SCREEN_H) + float y = (ABOUT_SCREEN_H/2.0f) + ((((matrix.x.y * star->x) + (matrix.y.y * star->y) + (matrix.z.y * star->z)) / z) * 400.0f); + const int32_t outY = (int32_t)y; + if (outY < 3 || outY >= 3+ABOUT_SCREEN_H) continue; - float x = (((matrix.x.x * star->x) + (matrix.y.x * star->y) + (matrix.z.x * star->z)) / z) * 400.0f; - x += 2.0f + (ABOUT_SCREEN_W/2.0f); + float x = (ABOUT_SCREEN_W/2.0f) + ((((matrix.x.x * star->x) + (matrix.y.x * star->y) + (matrix.z.x * star->z)) / z) * 400.0f); - const int32_t outX = (int32_t)(x + 0.5f); // rounded - if ((uint32_t)outX > 2+ABOUT_SCREEN_W) + const int32_t outX = (int32_t)x; + if (outX < 3 || outX >= 3+ABOUT_SCREEN_W) continue; - // render star pixel if the pixel under it is the background key - screenBufferPos = ((uint32_t)outY * SCREEN_W) + (uint32_t)outX; - if ((video.frameBuffer[screenBufferPos] >> 24) == PAL_BCKGRND) - { - int32_t d = (int32_t)(z * 255.0f); - if (d > 255) - d = 255; + int32_t d = (int32_t)(z * 255.0f); + if (d > 255) + d = 255; + d ^= 255; - d ^= 255; + // add a tint of blue to the star pixel - int32_t r = d - 75; - if (r < 0) - r = 0; + int32_t r = d - 79; + if (r < 0) + r = 0; - int32_t g = d - 38; - if (g < 0) - g = 0; + int32_t g = d - 38; + if (g < 0) + g = 0; - int32_t b = d + 64; - if (b > 255) - b = 255; + int32_t b = d + 64; + if (b > 255) + b = 255; - video.frameBuffer[screenBufferPos] = RGB32(r, g, b); - lastStarScreenPos[i] = screenBufferPos; - } + video.frameBuffer[(outY * SCREEN_W) + outX] = RGB32(r, g, b); } } -void aboutFrame(void) +void aboutFrame(void) // called every frame when the about screen is shown { + clearRect(3, 3, ABOUT_SCREEN_W, ABOUT_SCREEN_H); + + // 3D starfield rotateMatrix(); starfield(); - rotation.x -= 0.00011f; rotation.z += 0.00006f; - // fade in stuff after 1/3th of a second - if (fadeValue < 256 && ++frameCounter >= (int32_t)((VBLANK_HZ/3.0)+0.5)) - { - blit32Fade(91, 31, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H, fadeValue); - textOutFade(customText1X, customText1Y, PAL_FORGRND, customText1, fadeValue); - textOutFade(customText2X, customText2Y, PAL_FORGRND, customText2, fadeValue); - textOutFade(customText3X, customText3Y, PAL_FORGRND, customText3, fadeValue); - - fadeValue += 3; - if (fadeValue > 256) - fadeValue = 256; - } + // logo + text + blit32Alpha(91, 31, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H, alphaValue); + textOutAlpha(customText1X, customText1Y, PAL_FORGRND, customText1, alphaValue); + textOutAlpha(customText2X, customText2Y, PAL_FORGRND, customText2, alphaValue); + textOutAlpha(customText3X, customText3Y, PAL_FORGRND, customText3, alphaValue); + + alphaValue += (uint32_t)((65536.0 / (ALPHA_FADE_MILLISECS / (1000.0 / VBLANK_HZ))) + 0.5); + if (alphaValue > 65536) + alphaValue = 65536; + + // the exit button has to be redrawn since it gets overwritten :) + showPushButton(PB_EXIT_ABOUT); } -void showAboutScreen(void) // called once when About screen is opened +void showAboutScreen(void) // called once when about screen is opened { if (ui.extended) exitPatternEditorExtended(); @@ -195,7 +177,7 @@ void showAboutScreen(void) // called once when About screen is opened showPushButton(PB_EXIT_ABOUT); sprintf(customText3, "v%s (%s)", PROG_VER_STR, __DATE__); - customText1X = (SCREEN_W - textWidth(customText1)) >> 1; + customText1X = (SCREEN_W - textWidth(customText1)) / 2; customText2X = (SCREEN_W-8) - textWidth(customText2); customText3X = (SCREEN_W-8) - textWidth(customText3); customText1Y = 157; @@ -203,8 +185,6 @@ void showAboutScreen(void) // called once when About screen is opened customText3Y = 157; aboutInit(); - frameCounter = 0; - fadeValue = 0; ui.aboutScreenShown = true; } diff --git a/src/ft2_gui.c b/src/ft2_gui.c @@ -385,7 +385,7 @@ void charOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr) } } -static void charOutFade(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, int32_t fade) // for about screen +void charOutAlpha(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint32_t alpha) { assert(xPos < SCREEN_W && yPos < SCREEN_H); @@ -393,7 +393,11 @@ static void charOutFade(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char if (chr == ' ') return; + if (alpha > 65536) + alpha = 65536; + const uint32_t pixVal = video.palette[paletteIndex]; + const uint32_t palNum = paletteIndex << 24; const uint8_t *srcPtr = &bmp.font1[chr * FONT1_CHAR_W]; uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos]; @@ -401,14 +405,25 @@ static void charOutFade(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char { for (int32_t x = 0; x < FONT1_CHAR_W; x++) { - if (srcPtr[x] != 0) - { - const int32_t r = (RGB32_R(pixVal) * fade) >> 8; - const int32_t g = (RGB32_G(pixVal) * fade) >> 8; - const int32_t b = (RGB32_B(pixVal) * fade) >> 8; + const uint32_t srcPixel = srcPtr[x]; + if (srcPixel == 0) + continue; - dstPtr[x] = RGB32(r, g, b) | 0xFF000000; - } + const uint32_t dstPixel = dstPtr[x]; + + const int32_t srcR = RGB32_R(pixVal); + const int32_t srcG = RGB32_G(pixVal); + const int32_t srcB = RGB32_B(pixVal); + + int32_t dstR = RGB32_R(dstPixel); + int32_t dstG = RGB32_G(dstPixel); + int32_t dstB = RGB32_B(dstPixel); + + dstR = ((dstR * (65536-alpha)) + (srcR * alpha)) >> 16; + dstG = ((dstG * (65536-alpha)) + (srcG * alpha)) >> 16; + dstB = ((dstB * (65536-alpha)) + (srcB * alpha)) >> 16; + + dstPtr[x] = RGB32(dstR, dstG, dstB) | palNum; } srcPtr += FONT1_WIDTH; @@ -621,13 +636,19 @@ void textOut(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr) } } -void textOutFade(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, int32_t fade) // for about screen +void textOutAlpha(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, uint32_t alpha) { char chr; uint16_t currX; assert(textPtr != NULL); + if (alpha >= 65536) + { + textOut(x, y, paletteIndex, textPtr); + return; + } + currX = x; while (true) { @@ -635,7 +656,7 @@ void textOutFade(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textP if (chr == '\0') break; - charOutFade(currX, y, paletteIndex, chr, fade); + charOutAlpha(currX, y, paletteIndex, chr, alpha); currX += charWidth(chr); } } @@ -808,14 +829,11 @@ void clearRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h) { assert(xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H); - const uint32_t width = w * sizeof (int32_t); + const uint32_t pitch = w * sizeof (int32_t); uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos]; - for (int32_t y = 0; y < h; y++) - { - memset(dstPtr, 0, width); - dstPtr += SCREEN_W; - } + for (int32_t y = 0; y < h; y++, dstPtr += SCREEN_W) + memset(dstPtr, 0, pitch); } void fillRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h, uint8_t paletteIndex) @@ -834,7 +852,7 @@ void fillRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h, uint8_t pale } } -void blit32(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h) +void blit32(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h) { assert(srcPtr != NULL && xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H); @@ -852,24 +870,40 @@ void blit32(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, ui } } -void blit32Fade(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h, int32_t fade) // for about screen +void blit32Alpha(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h, uint32_t alpha) { assert(srcPtr != NULL && xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H); + if (alpha >= 65536) + { + blit32(xPos, yPos, srcPtr, w, h); + return; + } + uint32_t *dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos]; for (int32_t y = 0; y < h; y++) { for (int32_t x = 0; x < w; x++) { - const uint32_t pixel = srcPtr[x]; - if (pixel != 0x00FF00) - { - const int32_t r = (RGB32_R(pixel) * fade) >> 8; - const int32_t g = (RGB32_G(pixel) * fade) >> 8; - const int32_t b = (RGB32_B(pixel) * fade) >> 8; + const uint32_t srcPixel = srcPtr[x]; + if (srcPixel == 0x00FF00) + continue; - dstPtr[x] = RGB32(r, g, b) | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette - } + const uint32_t dstPixel = dstPtr[x]; + + const int32_t srcR = RGB32_R(srcPixel); + const int32_t srcG = RGB32_G(srcPixel); + const int32_t srcB = RGB32_B(srcPixel); + + int32_t dstR = RGB32_R(dstPixel); + int32_t dstG = RGB32_G(dstPixel); + int32_t dstB = RGB32_B(dstPixel); + + dstR = ((dstR * (65536-alpha)) + (srcR * alpha)) >> 16; + dstG = ((dstG * (65536-alpha)) + (srcG * alpha)) >> 16; + dstB = ((dstB * (65536-alpha)) + (srcB * alpha)) >> 16; + + dstPtr[x] = RGB32(dstR, dstG, dstB) | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette } srcPtr += w; diff --git a/src/ft2_gui.h b/src/ft2_gui.h @@ -79,7 +79,8 @@ void line(int16_t x1, int16_t x2, int16_t y1, int16_t y2, uint8_t paletteIndex); void clearRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h); void fillRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h, uint8_t paletteIndex); void drawFramework(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t type); -void blit32(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h); +void blit32(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h); +void blit32Alpha(uint16_t xPos, uint16_t yPos, const uint32_t *srcPtr, uint16_t w, uint16_t h, uint32_t alpha); void blit(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h); void blitClipX(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h, uint16_t clipX); void blitFast(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h); // no transparency/colorkey @@ -90,6 +91,7 @@ void hexOutShadow(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, uint8_t sh void textOutTiny(int32_t xPos, int32_t yPos, char *str, uint32_t color); // A..Z/a..z and 0..9 void textOutTinyOutline(int32_t xPos, int32_t yPos, char *str); // A..Z/a..z and 0..9 void charOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr); +void charOutAlpha(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint32_t alpha); void charOutBg(uint16_t xPos, uint16_t yPos, uint8_t fgPalette, uint8_t bgPalette, char chr); void charOutShadow(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, uint8_t shadowPaletteIndex, char chr); void charOutClipX(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr, uint16_t clipX); @@ -97,6 +99,7 @@ void bigCharOut(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, char chr); void charOutShadow(uint16_t x, uint16_t y, uint8_t paletteIndex, uint8_t shadowPaletteIndex, char chr); void charOutOutlined(uint16_t x, uint16_t y, uint8_t paletteIndex, char chr); void textOut(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr); +void textOutAlpha(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, uint32_t alpha); void textOutBorder(uint16_t x, uint16_t y, uint8_t paletteIndex, uint8_t borderPaletteIndex, const char *textPtr); void textOutFixed(uint16_t x, uint16_t y, uint8_t fgPaltete, uint8_t bgPalette, const char *textPtr); void bigTextOut(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr); @@ -117,7 +120,3 @@ void hideTopLeftScreen(void); void hideTopScreen(void); void showTopScreen(bool restoreScreens); void showBottomScreen(void); - -// for about screen -void textOutFade(uint16_t x, uint16_t y, uint8_t paletteIndex, const char *textPtr, int32_t fade); -void blit32Fade(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h, int32_t fade); diff --git a/src/ft2_header.h b/src/ft2_header.h @@ -12,7 +12,7 @@ #endif #include "ft2_replayer.h" -#define PROG_VER_STR "1.66" +#define PROG_VER_STR "1.67" // do NOT change these! It will only mess things up...