Skip to content

Commit 1e7f5bc

Browse files
committed
'About screen' optimizations
1 parent 8bef5c2 commit 1e7f5bc

1 file changed

Lines changed: 113 additions & 53 deletions

File tree

src/ft2_about.c

Lines changed: 113 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,26 @@
1111
#include "ft2_random.h"
1212

1313
#define NUM_STARS 1500
14-
#define STARSHINE_ALPHA_PERCENTAGE 33
14+
#define STARSHINE_ALPHA_PERCENTAGE 31
1515
#define ABOUT_SCREEN_X 3
1616
#define ABOUT_SCREEN_Y 3
1717
#define ABOUT_SCREEN_W 626
1818
#define ABOUT_SCREEN_H 167
1919
#define ABOUT_LOGO_W 541
2020
#define ABOUT_LOGO_H 78
21+
#define BG_COLORKEY 0xFF000000
22+
#define STAR_PIXEL_ID 0xFE000000
2123

2224
typedef struct
2325
{
24-
float x, y, z;
26+
int16_t x, y, z;
2527
} vector_t;
2628

29+
typedef struct
30+
{
31+
float x, y, z;
32+
} rotate_t;
33+
2734
typedef struct
2835
{
2936
vector_t x, y, z;
@@ -35,10 +42,32 @@ static char *customText2 = "https://16-bits.org";
3542
static char customText3[128];
3643
static int16_t customText0X, customText0Y, customText1X, customText1Y;
3744
static int16_t customText2X, customText2Y, customText3X, customText3Y;
45+
static int32_t lastStarPos[NUM_STARS];
3846
static const uint16_t starShineAlpha16 = (65535 * STARSHINE_ALPHA_PERCENTAGE) / 100;
39-
static vector_t starPoints[NUM_STARS], starRotation;
47+
static vector_t starPoints[NUM_STARS];
48+
static rotate_t starRotation;
4049
static matrix_t starMatrix;
4150

51+
static void clearPixel(uint32_t x, uint32_t y)
52+
{
53+
if (x >= ABOUT_SCREEN_X+ABOUT_SCREEN_W || y >= ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
54+
return;
55+
56+
const uint32_t pos = (y * SCREEN_W) + x;
57+
if ((video.frameBuffer[pos] & 0xFF000000) == STAR_PIXEL_ID)
58+
video.frameBuffer[pos] = BG_COLORKEY;
59+
}
60+
61+
static void putPixel(uint32_t x, uint32_t y, uint32_t color)
62+
{
63+
if (x >= ABOUT_SCREEN_X+ABOUT_SCREEN_W || y >= ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
64+
return;
65+
66+
const uint32_t pos = (y * SCREEN_W) + x;
67+
if (video.frameBuffer[pos] == BG_COLORKEY)
68+
video.frameBuffer[pos] = color | STAR_PIXEL_ID;
69+
}
70+
4271
static void blendPixelsXY(uint32_t x, uint32_t y, uint32_t pixelB_r, uint32_t pixelB_g, uint32_t pixelB_b, uint16_t alpha)
4372
{
4473
uint32_t *p = &video.frameBuffer[(y * SCREEN_W) + x];
@@ -49,33 +78,57 @@ static void blendPixelsXY(uint32_t x, uint32_t y, uint32_t pixelB_r, uint32_t pi
4978
const int32_t g = ((RGB32_G(pixelA) * invAlpha) + (pixelB_g * alpha)) >> 16;
5079
const int32_t b = ((RGB32_B(pixelA) * invAlpha) + (pixelB_b * alpha)) >> 16;
5180

52-
*p = RGB32(r, g, b);
81+
if (*p == BG_COLORKEY)
82+
*p = RGB32(r, g, b) | STAR_PIXEL_ID;
5383
}
5484

5585
static void starfield(void)
5686
{
5787
vector_t *star = starPoints;
5888
for (int16_t i = 0; i < NUM_STARS; i++, star++)
5989
{
60-
star->z += 0.0001f;
61-
if (star->z >= 0.5f)
62-
star->z -= 1.0f;
63-
64-
const float z = (starMatrix.x.z * star->x) + (starMatrix.y.z * star->y) + (starMatrix.z.z * star->z) + 0.5f;
65-
if (z <= 0.0f)
90+
// erase previous star
91+
if (lastStarPos[i] != -1)
92+
{
93+
const int32_t x = lastStarPos[i] >> 16, y = lastStarPos[i] & 0xFFFF;
94+
lastStarPos[i] = -1;
95+
96+
// center
97+
clearPixel(x, y);
98+
99+
// sides
100+
clearPixel(x-1, y);
101+
clearPixel(x+1, y);
102+
clearPixel(x, y-1);
103+
clearPixel(x, y+1);
104+
}
105+
106+
star->z += 3;
107+
if (star->z > 16384)
108+
star->z -= 32768;
109+
110+
int32_t z = (((starMatrix.x.z * star->x) + (starMatrix.y.z * star->y) + (starMatrix.z.z * star->z)) >> 15) + 16384;
111+
if (z <= 0)
112+
continue;
113+
114+
int32_t y = ((((starMatrix.x.y * star->x) + (starMatrix.y.y * star->y) + (starMatrix.z.y * star->z)) >> 15) * 400) / z;
115+
y += ABOUT_SCREEN_H / 2;
116+
if ((uint32_t)y >= ABOUT_SCREEN_H)
66117
continue;
67118

68-
float y = (((starMatrix.x.y * star->x) + (starMatrix.y.y * star->y) + (starMatrix.z.y * star->z)) / z) * 400.0f;
69-
const int32_t outY = (ABOUT_SCREEN_Y+(ABOUT_SCREEN_H/2)) + (int32_t)y;
70-
if (outY < ABOUT_SCREEN_Y || outY >= ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
119+
int32_t x = ((((starMatrix.x.x * star->x) + (starMatrix.y.x * star->y) + (starMatrix.z.x * star->z)) >> 15) * 400) / z;
120+
x += ABOUT_SCREEN_W / 2;
121+
if ((uint32_t)x >= ABOUT_SCREEN_W)
71122
continue;
72123

73-
float x = (((starMatrix.x.x * star->x) + (starMatrix.y.x * star->y) + (starMatrix.z.x * star->z)) / z) * 400.0f;
74-
const int32_t outX = (ABOUT_SCREEN_X+(ABOUT_SCREEN_W/2)) + (int32_t)x;
75-
if (outX < ABOUT_SCREEN_X || outX >= ABOUT_SCREEN_X+ABOUT_SCREEN_W)
124+
const int32_t outX = ABOUT_SCREEN_X + x;
125+
const int32_t outY = ABOUT_SCREEN_Y + y;
126+
127+
// only draw star if it's not over logo and text
128+
if (video.frameBuffer[(outY * SCREEN_W) + outX] != BG_COLORKEY)
76129
continue;
77130

78-
int32_t intensity255 = (int32_t)(z * 256.0f);
131+
int32_t intensity255 = z >> 7;
79132
if (intensity255 > 255)
80133
intensity255 = 255;
81134
intensity255 ^= 255;
@@ -94,6 +147,9 @@ static void starfield(void)
94147
if (b > 255)
95148
b = 255;
96149

150+
// plot center pixel
151+
putPixel(outX, outY, RGB32(r, g, b));
152+
97153
// plot and blend sides of star (basic shine effect)
98154

99155
if (outX-1 >= ABOUT_SCREEN_X)
@@ -108,69 +164,58 @@ static void starfield(void)
108164
if (outY+1 < ABOUT_SCREEN_Y+ABOUT_SCREEN_H)
109165
blendPixelsXY(outX, outY+1, r, g, b, starShineAlpha16);
110166

111-
// plot center pixel
112-
video.frameBuffer[(outY * SCREEN_W) + outX] = RGB32(r, g, b);
167+
lastStarPos[i] = (outX << 16) | outY;
113168
}
114169
}
115170

116171
static void rotateStarfieldMatrix(void)
117172
{
118173
#define F_2PI (float)(2.0 * PI)
174+
#define SCALE 32767.0f
119175

120-
const float xrad = starRotation.x * F_2PI;
121-
const float xsin = sinf(xrad);
122-
const float xcos = cosf(xrad);
176+
const float rx2p = starRotation.x * F_2PI;
177+
const float xsin = sinf(rx2p);
178+
const float xcos = cosf(rx2p);
123179

124-
const float yrad = starRotation.y * F_2PI;
125-
const float ysin = sinf(yrad);
126-
const float ycos = cosf(yrad);
180+
const float ry2p = starRotation.y * F_2PI;
181+
const float ysin = sinf(ry2p);
182+
const float ycos = cosf(ry2p);
127183

128-
const float zrad = starRotation.z * F_2PI;
129-
const float zsin = sinf(zrad);
130-
const float zcos = cosf(zrad);
184+
const float rz2p = starRotation.z * F_2PI;
185+
const float zsin = sinf(rz2p);
186+
const float zcos = cosf(rz2p);
131187

132188
// x
133-
starMatrix.x.x = (xcos * zcos) + (zsin * xsin * ysin);
134-
starMatrix.y.x = xsin * ycos;
135-
starMatrix.z.x = (zcos * xsin * ysin) - (xcos * zsin);
189+
starMatrix.x.x = (int16_t)(SCALE * ((xcos * zcos) + (zsin * xsin * ysin)));
190+
starMatrix.y.x = (int16_t)(SCALE * (xsin * ycos));
191+
starMatrix.z.x = (int16_t)(SCALE * ((zcos * xsin * ysin) - (xcos * zsin)));
136192

137193
// y
138-
starMatrix.x.y = (zsin * xcos * ysin) - (xsin * zcos);
139-
starMatrix.y.y = xcos * ycos;
140-
starMatrix.z.y = (xsin * zsin) + (zcos * xcos * ysin);
194+
starMatrix.x.y = (int16_t)(SCALE * ((zsin * xcos * ysin) - (xsin * zcos)));
195+
starMatrix.y.y = (int16_t)(SCALE * (xcos * ycos));
196+
starMatrix.z.y = (int16_t)(SCALE * ((xsin * zsin) + (zcos * xcos * ysin)));
141197

142198
// z
143-
starMatrix.x.z = ycos * zsin;
144-
starMatrix.y.z = 0.0f - ysin;
145-
starMatrix.z.z = ycos * zcos;
199+
starMatrix.x.z = (int16_t)(SCALE * (ycos * zsin));
200+
starMatrix.y.z = (int16_t)(SCALE * (0.0f - ysin));
201+
starMatrix.z.z = (int16_t)(SCALE * (ycos * zcos));
146202
}
147203

148204
void renderAboutScreenFrame(void)
149205
{
150-
clearRect(ABOUT_SCREEN_X, ABOUT_SCREEN_Y, ABOUT_SCREEN_W, ABOUT_SCREEN_H);
151-
152-
// 3D starfield
153-
154206
starfield();
155207
starRotation.x -= 0.0003f;
156208
starRotation.y -= 0.0002f;
157209
starRotation.z += 0.0001f;
158210
rotateStarfieldMatrix();
159211

160-
// FT2 logo
161-
blit32((SCREEN_W - ABOUT_LOGO_W) / 2, 30, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H);
162-
163-
// render static texts
164-
textOut(customText0X, customText0Y, PAL_FORGRND, customText0);
165-
textOut(customText1X, customText1Y, PAL_FORGRND, customText1);
166-
textOut(customText2X, customText2Y, PAL_FORGRND, customText2);
167-
textOut(customText3X, customText3Y, PAL_FORGRND, customText3);
168-
169212
showPushButton(PB_EXIT_ABOUT); // yes, we also have to redraw the exit button per frame :)
170213
}
171214

172215
void showAboutScreen(void) // called once when about screen is opened
173216
{
217+
memset(lastStarPos, -1, NUM_STARS * sizeof (int32_t));
218+
174219
if (ui.extendedPatternEditor)
175220
exitPatternEditorExtended();
176221

@@ -179,6 +224,21 @@ void showAboutScreen(void) // called once when about screen is opened
179224
drawFramework(0, 0, 632, 173, FRAMEWORK_TYPE1);
180225
drawFramework(2, 2, 628, 169, FRAMEWORK_TYPE2);
181226

227+
for (int32_t y = ABOUT_SCREEN_Y; y < ABOUT_SCREEN_Y+ABOUT_SCREEN_H; y++)
228+
{
229+
for (int32_t x = ABOUT_SCREEN_X; x < ABOUT_SCREEN_X+ABOUT_SCREEN_W; x++)
230+
video.frameBuffer[(y * SCREEN_W) + x] = BG_COLORKEY;
231+
}
232+
233+
// FT2 logo
234+
blit32((SCREEN_W - ABOUT_LOGO_W) / 2, 30, bmp.ft2AboutLogo, ABOUT_LOGO_W, ABOUT_LOGO_H);
235+
236+
// render static texts
237+
textOut(customText0X, customText0Y, PAL_FORGRND, customText0);
238+
textOut(customText1X, customText1Y, PAL_FORGRND, customText1);
239+
textOut(customText2X, customText2Y, PAL_FORGRND, customText2);
240+
textOut(customText3X, customText3Y, PAL_FORGRND, customText3);
241+
182242
showPushButton(PB_EXIT_ABOUT);
183243
ui.aboutScreenShown = true;
184244
}
@@ -188,9 +248,9 @@ void initAboutScreen(void)
188248
vector_t *s = starPoints;
189249
for (int32_t i = 0; i < NUM_STARS; i++, s++)
190250
{
191-
s->x = (float)((randoml(INT32_MAX) - (INT32_MAX/2)) * (1.0 / INT32_MAX));
192-
s->y = (float)((randoml(INT32_MAX) - (INT32_MAX/2)) * (1.0 / INT32_MAX));
193-
s->z = (float)((randoml(INT32_MAX) - (INT32_MAX/2)) * (1.0 / INT32_MAX));
251+
s->x = (int16_t)(randoml(32768) - 16384);
252+
s->y = (int16_t)(randoml(32768) - 16384);
253+
s->z = (int16_t)(randoml(32768) - 16384);
194254
}
195255

196256
sprintf(customText3, "v%s (%s)", PROG_VER_STR, __DATE__);

0 commit comments

Comments
 (0)