foo
[dosdemo] / src / grise.c
index f354181..94e3850 100644 (file)
@@ -16,7 +16,7 @@ typedef struct {
 
 static RLEBitmap *rleCreate(unsigned int w, unsigned int h);
 static void rleDestroy(RLEBitmap *b);
-static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride, 
+static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
        RLEBitmap *bitmap, int blitX, int blitY);
 static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride,
        RLEBitmap *bitmap, int blitX, int blitY, float scaleX, float scaleY);
@@ -62,8 +62,8 @@ static void updateScrollTables(float dt);
 
 
 static unsigned short *background = 0;
-static unsigned int backgroundW = 0;
-static unsigned int backgroundH = 0;
+static int backgroundW = 0;
+static int backgroundH = 0;
 
 static unsigned int lastFrameTime = 0;
 static float lastFrameDuration = 0.0f;
@@ -78,16 +78,17 @@ static int scrollTableRounded[REFLECTION_HEIGHT];
 static int scrollModTable[REFLECTION_HEIGHT];
 static float nearScrollAmount = 0.0f;
 
-static char miniFXBuffer[1024];
+static unsigned char miniFXBuffer[1024];
 
 static RLEBitmap *grobj = 0;
+static RLEBitmap *rlePropeller = 0;
 
 static struct screen scr = {
        "galaxyrise",
        init,
        destroy,
        start,
-       stop,
+       0,
        draw
 };
 
@@ -96,7 +97,6 @@ struct screen *grise_screen(void)
        return &scr;
 }
 
-
 static int init(void)
 {
        unsigned char *tmpBitmap;
@@ -128,11 +128,7 @@ static int init(void)
 
        processNormal();
 
-#ifdef MIKE_PC
-       return 0xCAFE;
-#else
        return 0;
-#endif
 }
 
 static void destroy(void)
@@ -150,15 +146,9 @@ static void start(long trans_time)
        lastFrameTime = time_msec;
 }
 
-static void stop(long trans_time)
-{
-}
-
-
-
 
 static void draw(void)
-{      
+{
        int scroll = MIN_SCROLL + (MAX_SCROLL - MIN_SCROLL) * mouse_x / fb_width;
        unsigned short *dst = backBuffer + PIXEL_PADDING;
        unsigned short *src = background + scroll;
@@ -166,12 +156,15 @@ static void draw(void)
        int i = 0;
        short *dispScanline;
        int d;
+       int accum = 0;
+       int md, sc;
+       int scrolledIndex;
 
        lastFrameDuration = (time_msec - lastFrameTime) / 1000.0f;
        lastFrameTime = time_msec;
 
        /* Update mini-effects here */
-       updatePropeller(time_msec / 1000.0f);
+       updatePropeller(4.0f * time_msec / 1000.0f);
 
        /* First, render the horizon */
        for (scanline = 0; scanline < HORIZON_HEIGHT; scanline++) {
@@ -179,11 +172,11 @@ static void draw(void)
                src += backgroundW;
                dst += BB_SIZE;
        }
-       
+
        /* Create scroll offsets for all scanlines of the normalmap */
        updateScrollTables(lastFrameDuration);
 
-       /* Render the baked reflection one scanline below its place, so that 
+       /* Render the baked reflection one scanline below its place, so that
         * the displacement that follows will be done in a cache-friendly way
         */
        src -= PIXEL_PADDING; /* We want to also fill the PADDING pixels here */
@@ -195,15 +188,26 @@ static void draw(void)
        }
 
        /* Blit reflections first, to be  displaced */
-       for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, grobj, 134 + (i-3) * 60, 235, 1.0f, 1.8f);
+       for (i = 0; i < 5; i++) rleBlitScaleInv(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 200, 1.0f, 1.8f);
 
        /* Perform displacement */
        dst = backBuffer + HORIZON_HEIGHT * BB_SIZE + PIXEL_PADDING;
        src = dst + BB_SIZE; /* The pixels to be displaced are 1 scanline below */
        dispScanline = displacementMap;
        for (scanline = 0; scanline < REFLECTION_HEIGHT; scanline++) {
+
+               md = scrollModTable[scanline];
+               sc = scrollTableRounded[scanline];
+               accum = 0;
+
                for (i = 0; i < fb_width; i++) {
-                       d = dispScanline[(i + scrollTableRounded[scanline]) % scrollModTable[scanline]];
+                       /* Try to immitate modulo without the division */
+                       if (i == md) accum += md;
+                       scrolledIndex = i - accum + sc;
+                       if (scrolledIndex >= md) scrolledIndex -= md;
+
+                       /* Displace */
+                       d = dispScanline[scrolledIndex];
                        *dst++ = src[i + d];
                }
                src += backgroundW;
@@ -212,20 +216,14 @@ static void draw(void)
        }
 
        /* Then after displacement, blit the objects */
-       for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, grobj, 134 + (i-3) * 60, 100);
-
-       for (scanline = 0; scanline < 32; scanline++) {
-               for (i = 0; i < 32; i++) {
-                       backBuffer[PIXEL_PADDING + scanline * BB_SIZE + i] = miniFXBuffer[i + 32 * scanline] ? 0xFFFF : 0x0000;
-               }
-       }
+       for (i = 0; i < 5; i++) rleBlit(backBuffer + PIXEL_PADDING, fb_width, fb_height, BB_SIZE, rlePropeller, 134 + (i-3) * 60, 100);
 
        /* Blit effect to framebuffer */
        src = backBuffer + PIXEL_PADDING;
-       dst = vmem_back;
+       dst = fb_pixels;
        for (scanline = 0; scanline < fb_height; scanline++) {
                memcpy(dst, src, fb_width * 2);
-               src += BB_SIZE; 
+               src += BB_SIZE;
                dst += fb_width;
        }
 
@@ -311,7 +309,7 @@ static void initScrollTables() {
 
 static void updateScrollTables(float dt) {
        int i = 0;
-       
+
        nearScrollAmount += dt * NEAR_SCROLL_SPEED;
        nearScrollAmount = (float) fmod(nearScrollAmount, 512.0f);
 
@@ -322,7 +320,7 @@ static void updateScrollTables(float dt) {
 }
 
 /* -------------------------------------------------------------------------------------------------
- *                                   RLE STUFF                                                                           
+ *                                   RLE STUFF
  * -------------------------------------------------------------------------------------------------
  */
 /* Limit streak count per scanline so we can directly jump to specific scanline */
@@ -334,13 +332,17 @@ static void updateScrollTables(float dt) {
 
 #define RLE_FIXED_BITS 16
 
+static int rleByteCount(int w, int h) {
+       return h * RLE_BYTES_PER_SCANLINE + w;
+}
+
 static RLEBitmap *rleCreate(unsigned int w, unsigned int h) {
        RLEBitmap *ret = (RLEBitmap*)malloc(sizeof(RLEBitmap));
        ret->w = w;
        ret->h = h;
 
        /* Add some padding at the end of the buffer, with the worst case for a scanline (w/2 streaks) */
-       ret->scans = (unsigned char*) calloc(h * RLE_BYTES_PER_SCANLINE + w, 1);
+       ret->scans = (unsigned char*) calloc(rleByteCount(w, h), 1);
 
        return ret;
 }
@@ -361,6 +363,7 @@ static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w,
 
        /* https://www.youtube.com/watch?v=RKMR02o1I88&feature=youtu.be&t=55 */
        if (!b) b = rleCreate(w, h);
+       else memset(b->scans, 0, rleByteCount(b->w, b->h)); /* The following code assumes cleared array */
 
        for (scanline = 0; scanline < h; scanline++) {
                output = b->scans + scanline * RLE_BYTES_PER_SCANLINE;
@@ -404,8 +407,27 @@ static RLEBitmap *rleEncode(RLEBitmap *b, unsigned char *pixels, unsigned int w,
        return b;
 }
 
+static void rleDistributeStreaks(RLEBitmap *bitmap) {
+       int scanline, halfW = bitmap->w >> 1;
+       unsigned char *ptr, tmp;
+
+       ptr = bitmap->scans;
+       for (scanline = 0; scanline < bitmap->h; scanline++) {
+               if (ptr[0] >= halfW) {
+                       tmp = ptr[0];
+                       ptr[0] = ptr[6];
+                       ptr[6] = tmp;
+                       tmp = ptr[1];
+                       ptr[1] = ptr[7];
+                       ptr[7] = tmp;
+               }
+
+               ptr += 8;
+       }
+}
+
 static void rleBlit(unsigned short *dst, int dstW, int dstH, int dstStride,
-       RLEBitmap *bitmap, int blitX, int blitY) 
+       RLEBitmap *bitmap, int blitX, int blitY)
 {
        int scanline = 0;
        int streakPos = 0;
@@ -450,7 +472,7 @@ static void interpolateScan(unsigned char *output, unsigned char *a, unsigned ch
 
        t += 1.0f;
        ti = (*((unsigned int*)&t)) & 0x7FFFFF;
-       
+
        for (i = 0; i < RLE_BYTES_PER_SCANLINE; i++) {
                if (*a == 0) {
                        *output++ = *b++;
@@ -477,16 +499,17 @@ static void rleBlitScale(unsigned short *dst, int dstW, int dstH, int dstStride,
        unsigned int *output32;
        unsigned char *input;
        int scanlineCounter = 0;
+       int scaleXFixed;
        static unsigned char scan[512];
 
-       int blitW = (int)(bitmap->w * scaleX + 0.5f);
+       /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
        int blitH = (int)(bitmap->h * scaleY + 0.5f);
 
        /* From this point on, scaleY will be inverted */
        scaleY = 1.0f / scaleY;
 
-       int scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
-       
+       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
+
        dst += blitX + blitY * dstStride;
 
        for (scanline = blitY; scanline < blitY + blitH; scanline++) {
@@ -537,15 +560,16 @@ static void rleBlitScaleInv(unsigned short *dst, int dstW, int dstH, int dstStri
        unsigned int *output32;
        unsigned char *input;
        int scanlineCounter = 0;
+       int scaleXFixed;
        static unsigned char scan[512];
 
-       int blitW = (int)(bitmap->w * scaleX + 0.5f);
+       /*int blitW = (int)(bitmap->w * scaleX + 0.5f);*/
        int blitH = (int)(bitmap->h * scaleY + 0.5f);
 
        /* From this point on, scaleY will be inverted */
        scaleY = 1.0f / scaleY;
 
-       int scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
+       scaleXFixed = (int)(scaleX * (float)(1 << RLE_FIXED_BITS) + 0.5f);
 
        dst += blitX + blitY * dstStride;
 
@@ -600,7 +624,7 @@ static struct {
 static void updatePropeller(float t) {
        int i, j;
        int cx, cy, count = 0;
-       char *dst;
+       unsigned char *dst;
        float x = 0.0f;
        float y = 18.0f;
        float nx, ny;
@@ -658,4 +682,10 @@ static void updatePropeller(float t) {
                        *dst++ = count >= 2;
                }
        }
+
+       /* Then, encode to rle */
+       rlePropeller = rleEncode(rlePropeller, miniFXBuffer, 32, 32);
+
+       /* Distribute the produced streaks so that they don't produce garbage when interpolated */
+       rleDistributeStreaks(rlePropeller);
 }