ref: f9a6d630fb4df6a523df9e08d18c6cb71f103d85
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_tables.h" #include "ft2_structs.h" // ported from original FT2 code #define NUM_STARS 1000 #define ABOUT_SCREEN_W 626 #define ABOUT_SCREEN_H 167 #define ABOUT_LOGO_W 449 #define ABOUT_LOGO_H 111 #define ABOUT_TEXT_W 349 #define ABOUT_TEXT_H 29 typedef struct { int16_t x, y, z; } vector_t; typedef struct { uint16_t x, y, z; } rotate_t; typedef struct { vector_t x, y, z; } matrix_t; static const uint8_t starColConv[24] = { 2,2,2,2,2,2,2,2, 2,2,2,1,1,1,3,3, 3,3,3,3,3,3,3,3 }; static int16_t hastighet; static int32_t lastStarScreenPos[NUM_STARS]; static uint32_t randSeed; static vector_t starcrd[NUM_STARS]; static rotate_t star_a; static matrix_t starmat; void seedAboutScreenRandom(uint32_t newseed) { randSeed = newseed; } static inline int32_t random32(int32_t l) // Turbo Pascal Random() implementation { int32_t r; randSeed *= 134775813; randSeed += 1; r = ((int64_t)randSeed * l) >> 32; return r; } static void fixaMatris(rotate_t a, matrix_t *mat) { int32_t sa, sb, sc, ca, cb, cc; // original code used a cos/sin table, but this only runs once per frame, no need... sa = (int32_t)round(32767.0 * sin(a.x * (2.0 * M_PI / 65536.0))); ca = (int32_t)round(32767.0 * cos(a.x * (2.0 * M_PI / 65536.0))); sb = (int32_t)round(32767.0 * sin(a.y * (2.0 * M_PI / 65536.0))); cb = (int32_t)round(32767.0 * cos(a.y * (2.0 * M_PI / 65536.0))); sc = (int32_t)round(32767.0 * sin(a.z * (2.0 * M_PI / 65536.0))); cc = (int32_t)round(32767.0 * cos(a.z * (2.0 * M_PI / 65536.0))); mat->x.x = (int16_t)(((ca * cc) >> 16) + ((sc * ((sa * sb) >> 16)) >> (16-1))); mat->y.x = (int16_t)((sa * cb) >> 16); mat->z.x = (int16_t)(((cc * ((sa * sb) >> 16)) >> (16-1)) - ((ca * sc) >> 16)); mat->x.y = (int16_t)(((sc * ((ca * sb) >> 16)) >> (16-1)) - ((sa * cc) >> 16)); mat->y.y = (int16_t)((ca * cb) >> 16); mat->z.y = (int16_t)(((sa * sc) >> 16) + ((cc * ((ca * sb) >> 16)) >> (16-1))); mat->x.z = (int16_t)((cb * sc) >> 16); mat->y.z = (int16_t)(0 - (sb >> 1)); mat->z.z = (int16_t)((cb * cc) >> 16); } static inline int32_t sqr(int32_t x) { return x * x; } static void aboutInit(void) { uint8_t type; int16_t i; int32_t r, n, w, h; double ww; type = (uint8_t)random32(4); switch (type) { case 0: { hastighet = 309; for (i = 0; i < NUM_STARS; i++) { starcrd[i].z = (int16_t)random32(0xFFFF) - 0x8000; starcrd[i].y = (int16_t)random32(0xFFFF) - 0x8000; starcrd[i].x = (int16_t)random32(0xFFFF) - 0x8000; } } break; case 1: { hastighet = 0; for (i = 0; i < NUM_STARS; i++) { if (i < NUM_STARS/4) { starcrd[i].z = (int16_t)random32(0xFFFF) - 0x8000; starcrd[i].y = (int16_t)random32(0xFFFF) - 0x8000; starcrd[i].x = (int16_t)random32(0xFFFF) - 0x8000; } else { r = random32(30000); n = random32(5); w = ((2 * random32(2)) - 1) * sqr(random32(1000)); ww = (((M_PI * 2.0) / 5.0) * n) + (r / 12000.0) + (w / 3000000.0); h = ((sqr(r) / 30000) * (random32(10000) - 5000)) / 12000; starcrd[i].x = (int16_t)(r * cos(ww)); starcrd[i].y = (int16_t)(r * sin(ww)); starcrd[i].z = (int16_t)h; } } } break; case 2: case 3: { hastighet = 0; for (i = 0; i < NUM_STARS; i++) { r = (int32_t)round(sqrt(random32(500) * 500)); w = random32(3000); ww = ((w * 8) + r) / 16.0; const int32_t z = (int32_t)round(32767.0 * cos(w * (2.0 * M_PI / 1024.0))); const int32_t y = (int32_t)round(32767.0 * sin(w * (2.0 * M_PI / 1024.0))); const int32_t x = (int32_t)round(32767.0 * cos(ww * (2.0 * M_PI / 1024.0))) / 4; starcrd[i].z = (int16_t)((z * (w + r)) / 3500); starcrd[i].y = (int16_t)((y * (w + r)) / 3500); starcrd[i].x = (int16_t)((x * r) / 500); } } break; default: break; } star_a.x = 0; star_a.y = 748; star_a.z = 200; for (i = 0; i < NUM_STARS; i++) lastStarScreenPos[i] = -1; } static void realStars(void) { uint8_t col; int16_t z, xx, xy, xz, yx, yy, yz, zx, zy, zz; int32_t x, y, screenBufferPos; vector_t *star; xx = starmat.x.x; xy = starmat.x.y; xz = starmat.x.z; yx = starmat.y.x; yy = starmat.y.y; yz = starmat.y.z; zx = starmat.z.x; zy = starmat.z.y; zz = starmat.z.z; for (int16_t i = 0; i < NUM_STARS; i++) { // erase last star pixel screenBufferPos = lastStarScreenPos[i]; if (screenBufferPos >= 0) { if (!(video.frameBuffer[screenBufferPos] & 0xFF000000)) video.frameBuffer[screenBufferPos] = video.palette[PAL_BCKGRND]; lastStarScreenPos[i] = -1; } star = &starcrd[i]; star->z += hastighet; // this intentionally overflows int16_t z = ((xz * star->x) + (yz * star->y) + (zz * star->z)) >> 16; z += 9000; if (z <= 100) continue; y = ((xy * star->x) + (yy * star->y) + (zy * star->z)) >> (16-7); y /= z; y += (2+ABOUT_SCREEN_H)/2; if ((uint32_t)y > 2+ABOUT_SCREEN_H) continue; x = ((xx * star->x) + (yx * star->y) + (zx * star->z)) >> (16-7); x += x >> 2; // x *= 1.25 x /= z; x += (2+ABOUT_SCREEN_W)/2; if ((uint32_t)x > 2+ABOUT_SCREEN_W) continue; // render star pixel if the pixel under it is the background screenBufferPos = ((uint32_t)y * SCREEN_W) + (uint32_t)x; if ((video.frameBuffer[screenBufferPos] >> 24) == PAL_BCKGRND) { col = ((uint8_t)~(z >> 8) >> 3) - 14; if (col < 24) { video.frameBuffer[screenBufferPos] = video.palette[starColConv[col]] & 0x00FFFFFF; lastStarScreenPos[i] = screenBufferPos; } } } } void aboutFrame(void) { star_a.x += 3*64; star_a.y += 2*64; star_a.z -= 1*64; fixaMatris(star_a, &starmat); realStars(); } extern uint32_t *unpackedData; void showAboutScreen(void) // called once when About screen is opened { #define TEXT_BORDER_COL 0x202020 char verText[32]; uint16_t x, y; if (ui.extended) exitPatternEditorExtended(); hideTopScreen(); drawFramework(0, 0, 632, 173, FRAMEWORK_TYPE1); drawFramework(2, 2, 628, 169, FRAMEWORK_TYPE2); showPushButton(PB_EXIT_ABOUT); blit32(91, 31, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H); setCustomPalColor(TEXT_BORDER_COL); // sets PAL_CUSTOM const char *infoString = "Clone by Olav \"8bitbubsy\" S\025rensen"; x = (SCREEN_W - textWidth(infoString)) >> 1; y = 147; textOutBorder(x, y, PAL_FORGRND, PAL_CUSTOM, infoString); sprintf(verText, "v%s (compiled on %s)", PROG_VER_STR, __DATE__); x = (SCREEN_W - textWidth(verText)) >> 1; y = 159; textOutBorder(x, y, PAL_FORGRND, PAL_CUSTOM, verText); aboutInit(); ui.aboutScreenShown = true; } void hideAboutScreen(void) { hidePushButton(PB_EXIT_ABOUT); ui.aboutScreenShown = false; } void exitAboutScreen(void) { hideAboutScreen(); showTopScreen(true); }