ref: f9216942946e320476d75cb77809de1b0792630f
dir: /src/ft2_about.c/
#include <stdio.h> // sprintf() #include <math.h> #include "ft2_header.h" #include "ft2_gui.h" #include "ft2_pattern_ed.h" #include "ft2_bmp.h" #include "ft2_video.h" #include "ft2_structs.h" #define NUM_STARS 2048 #define ABOUT_SCREEN_W 626 #define ABOUT_SCREEN_H 167 #define ABOUT_LOGO_W 449 #define ABOUT_LOGO_H 110 #define ABOUT_TEXT_W 349 #define ABOUT_TEXT_H 29 typedef struct { float x, y, z; } vector_t; typedef struct { vector_t x, y, z; } matrix_t; 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 vector_t starPoints[NUM_STARS], rotation; static matrix_t matrix; void seedAboutScreenRandom(uint32_t newseed) { randSeed = newseed; } static int32_t random32(void) { randSeed *= 134775813; randSeed += 1; return randSeed; } static void rotateMatrix(void) { const float xx = rotation.x * f2pi; const float sa = sinf(xx); const float ca = cosf(xx); const float yy = rotation.y * f2pi; const float sb = sinf(yy); const float cb = cosf(yy); const float zz = rotation.z * f2pi; const float sc = sinf(zz); const float cc = cosf(zz); // x matrix.x.x = (ca * cc) + (sc * sa * sb); matrix.y.x = sa * cb; matrix.z.x = (cc * sa * sb) - (ca * sc); // y matrix.x.y = (sc * ca * sb) - (sa * cc); matrix.y.y = ca * cb; matrix.z.y = (sa * sc) + (cc * ca * sb); // z matrix.x.z = cb * sc; matrix.y.z = 0.0f - 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++) { s->x = (float)(random32() * (1.0 / (UINT32_MAX+1.0))); s->y = (float)(random32() * (1.0 / (UINT32_MAX+1.0))); s->z = (float)(random32() * (1.0 / (UINT32_MAX+1.0))); } rotation.x = rotation.y = rotation.z = 0.0f; for (int32_t i = 0; i < NUM_STARS; i++) lastStarScreenPos[i] = -1; } 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; 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) 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); const int32_t outX = (int32_t)(x + 0.5f); // rounded if ((uint32_t)outX > 2+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; d ^= 255; int32_t r = d - 75; if (r < 0) r = 0; int32_t g = d - 38; if (g < 0) g = 0; int32_t b = d + 64; if (b > 255) b = 255; video.frameBuffer[screenBufferPos] = RGB32(r, g, b); lastStarScreenPos[i] = screenBufferPos; } } } void aboutFrame(void) { 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; } } void showAboutScreen(void) // called once when About screen is opened { if (ui.extended) exitPatternEditorExtended(); hideTopScreen(); drawFramework(0, 0, 632, 173, FRAMEWORK_TYPE1); drawFramework(2, 2, 628, 169, FRAMEWORK_TYPE2); showPushButton(PB_EXIT_ABOUT); sprintf(customText3, "v%s (%s)", PROG_VER_STR, __DATE__); customText1X = (SCREEN_W - textWidth(customText1)) >> 1; customText2X = (SCREEN_W-8) - textWidth(customText2); customText3X = (SCREEN_W-8) - textWidth(customText3); customText1Y = 157; customText2Y = 157-12; customText3Y = 157; aboutInit(); frameCounter = 0; fadeValue = 0; ui.aboutScreenShown = true; } void hideAboutScreen(void) { hidePushButton(PB_EXIT_ABOUT); ui.aboutScreenShown = false; } void exitAboutScreen(void) { hideAboutScreen(); showTopScreen(true); }