+
+static void renderLight(struct point *p, int width, int height, unsigned short *light)
+{
+ int x, y, dx;
+ unsigned short *src, *dst;
+
+ int x0 = p->x;
+ int y0 = p->y;
+ int x1 = p->x + width;
+ int y1 = p->y + height;
+
+ int xl = 0;
+ int yl = 0;
+
+ if (x0 < 0)
+ {
+ xl = -x0;
+ x0 = 0;
+ }
+
+ if (y0 < 0)
+ {
+ yl = -y0;
+ y0 = 0;
+ }
+
+ if (x1 > fb_width) x1 = fb_width;
+ if (y1 > fb_height) y1 = fb_height;
+
+ dx = x1 - x0;
+
+ dst = lightmap + y0 * fb_width + x0;
+ src = light + yl * width + xl;
+
+ for (y = y0; y < y1; y++)
+ {
+ for (x = x0; x < x1; x++)
+ {
+ *dst++ |= *src++;
+ }
+ dst += fb_width - dx;
+ src += width - dx;
+ }
+}
+
+static void eraseLights()
+{
+ int i;
+ for (i = 0; i < NUM_BIG_LIGHTS; i++)
+ eraseArea(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT);
+}
+
+static void renderLights()
+{
+ int i;
+ for (i = 0; i < NUM_BIG_LIGHTS; i++)
+ renderLight(&bigLightPoint[i], BIG_LIGHT_WIDTH, BIG_LIGHT_HEIGHT, bigLight[i]);
+}
+
+static void renderParticles()
+{
+ int i;
+ for (i = 0; i < NUM_PARTICLES; i++)
+ renderLight(&particlePoint[i], PARTICLE_LIGHT_WIDTH, PARTICLE_LIGHT_HEIGHT, particleLight);
+}
+
+static void animateLights()
+{
+ struct point center;
+ float dt = (float)(time_msec - startingTime) / 1000.0f;
+ float tt = 1.0f - sin(dt);
+ float disperse = tt * 64.0f;
+
+ center.x = (fb_width >> 1) - (BIG_LIGHT_WIDTH / 2);
+ center.y = (fb_height >> 1) - (BIG_LIGHT_HEIGHT / 2);
+
+ bigLightPoint[0].x = center.x + sin(1.2f * dt) * (144.0f + disperse);
+ bigLightPoint[0].y = center.y + sin(0.8f * dt) * (148.0f + disperse);
+
+ bigLightPoint[1].x = center.x + sin(1.5f * dt) * (156.0f + disperse);
+ bigLightPoint[1].y = center.y + sin(1.1f * dt) * (92.0f + disperse);
+
+ bigLightPoint[2].x = center.x + sin(2.0f * dt) * (112.0f + disperse);
+ bigLightPoint[2].y = center.y + sin(1.3f * dt) * (136.0f + disperse);
+}
+
+static void renderBump(unsigned short *vram)