start rewriting rollo so it's a little more parameterized.
diff --git a/res/raw/rollo.c b/res/raw/rollo.c
index 5ed562a..428ff78 100644
--- a/res/raw/rollo.c
+++ b/res/raw/rollo.c
@@ -3,10 +3,22 @@
 #pragma stateFragment(PF)
 #pragma stateFragmentStore(PFS)
 
-// Scratch buffer layout
-#define SCRATCH_FADE 0
-#define SCRATCH_ZOOM 1
-#define SCRATCH_ROT 2
+#define PI 3.14159f
+
+// Allocations ======
+#define ALLOC_PARAMS    0
+#define ALLOC_STATE     1
+#define ALLOC_SCRATCH   2
+#define ALLOC_ICON_IDS  3
+#define ALLOC_LABEL_IDS 4
+
+// Variables from java ======
+
+// Parameters ======
+#define PARAM_BUBBLE_WIDTH              0
+#define PARAM_BUBBLE_HEIGHT             1
+#define PARAM_BUBBLE_BITMAP_WIDTH       2
+#define PARAM_BUBBLE_BITMAP_HEIGHT      3
 
 //#define STATE_POS_X             0
 #define STATE_DONE              1
@@ -19,166 +31,124 @@
 #define STATE_COUNT             8
 #define STATE_TOUCH             9
 
+// Scratch variables ======
+#define SCRATCH_FADE 0
+#define SCRATCH_ZOOM 1
+#define SCRATCH_ROT 2
 
-float filter(float val, float target, float str)
+// Drawing constants, should be parameters ======
+#define SCREEN_WIDTH 480
+#define SCREEN_HEIGHT 854
+#define COLUMNS_PER_PAGE 4
+#define ROWS_PER_PAGE 4
+#define DIAMETER 8.0f
+
+#define PAGE_PADDING_TOP_PX 80
+#define CELL_PADDING_TOP_PX 5
+#define ICON_HEIGHT_PX 64
+#define ICON_LABEL_GUTTER_PX 5
+#define CELL_PADDING_BOTTOM_PX 5
+#define ROW_GUTTER_PX 10
+
+#define PAGE_PADDING_LEFT_PX 22
+#define CELL_WIDTH_PX 105
+#define ICON_WIDTH_PX 64
+#define COLUMN_GUTTER_PX 5
+#define LABEL_WIDTH_PX 105
+
+int
+count_pages(int iconCount)
 {
-    float delta = (target - val);
-    return val + delta * str;
+    int iconsPerPage = COLUMNS_PER_PAGE * ROWS_PER_PAGE;
+    int pages = iconCount / iconsPerPage;
+    if (pages*iconsPerPage != iconCount) {
+        iconCount++;
+    }
+    return iconCount;
 }
 
-int main(void* con, int ft, int launchID)
+int
+main(void* con, int ft, int launchID)
 {
-    int rowCount;
-    int row;
-    int col;
-    int imageID;
-    int done = loadI32(0, STATE_DONE);
-    int selectedID = loadI32(0, STATE_SELECTION);
-
-    float f = loadF(2, 0);
-
+    // Clear to transparent
     pfClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-    if (done) {
-        if (f > 0.02f) {
-            //f = f - 0.02f;
-            //storeF(2, 0, f);
-        }
-    } else {
-        if (f < 0.8f) {
-            f = f + 0.02f;
-            storeF(2, 0, f);
-        }
-    }
 
-    float touchCut = 1.f;
-    if (loadI32(0, STATE_TOUCH)) {
-        touchCut = 4.f;
-    }
+    // icons & labels
+    int iconCount = loadI32(ALLOC_STATE, STATE_COUNT);
+    int pageCount = count_pages(iconCount);
+
+    float densityScale = 2.0f / SCREEN_WIDTH;
+    float screenTop = SCREEN_HEIGHT/(float)SCREEN_WIDTH; // == (SCREEN_HEIGHT/2)*densityScale;
+
+    float pagePaddingTop = screenTop - (PAGE_PADDING_TOP_PX * densityScale);
+    float pageGutterY = ROW_GUTTER_PX * densityScale;
+    float cellHeight = (CELL_PADDING_TOP_PX + ICON_HEIGHT_PX + ICON_LABEL_GUTTER_PX
+            + loadI32(ALLOC_PARAMS, PARAM_BUBBLE_HEIGHT)
+            + CELL_PADDING_BOTTOM_PX + ROW_GUTTER_PX) * densityScale;
+    float cellPaddingTop = CELL_PADDING_TOP_PX * densityScale;
+    float iconHeight = ICON_HEIGHT_PX * densityScale;
+    float iconLabelGutter = ICON_LABEL_GUTTER_PX * densityScale;
+
+    float pagePaddingLeft = PAGE_PADDING_LEFT_PX * densityScale;
+    float cellWidth = CELL_WIDTH_PX * densityScale;
+    float iconWidth = ICON_WIDTH_PX * densityScale;
+    float columnGutter = COLUMN_GUTTER_PX * densityScale;
+
+    float pageLeft = -1;
+    int icon = 0;
+    int page;
+
+    float labelWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_WIDTH) * densityScale;
+    float labelTextureWidth = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_WIDTH) * densityScale;
+    float labelTextureHeight = loadI32(ALLOC_PARAMS, PARAM_BUBBLE_BITMAP_HEIGHT) * densityScale;
+
+    int scrollXPx = 100;
+    pageLeft -= scrollXPx * densityScale;
 
 
-    float targetZoom = ((float)loadI32(0, STATE_ZOOM)) / 1000.f;
-    float zoom = filter(loadF(2, SCRATCH_ZOOM), targetZoom, 0.15 * touchCut);
-    storeF(2, SCRATCH_ZOOM, zoom);
+    for (page=0; page<pageCount; page++) {
+        // Bug makes 1.0f alpha fail.
+        color(1.0f, 1.0f, 1.0f, 0.99f);
+        
+        float cellTop = pagePaddingTop;
+        int row;
+        for (row=0; row<ROWS_PER_PAGE && icon<iconCount; row++) {
+            float s = pageLeft; // distance along the linear strip of icons in normalized coords
+            s += pagePaddingLeft;
+            int col;
+            for (col=0; col<COLUMNS_PER_PAGE && icon<iconCount; col++) {
+                // icon
+                float iconLeft = s + ((cellWidth-iconWidth)/2.0f);
+                float iconRight = iconLeft + iconWidth;
+                float iconTop = cellTop - cellPaddingTop;
+                float iconBottom = iconTop - iconHeight;
 
-    float targetRot = loadI32(0, STATE_FIRST_VISIBLE) / 180.0f * 3.14f;
-    targetRot = targetRot * 0.80f - .12f;
-    float drawRot = filter(loadF(2, SCRATCH_ROT), targetRot, 0.1f * touchCut);
-    storeF(2, SCRATCH_ROT, drawRot);
+                bindProgramFragment(NAMED_PF);
+                bindProgramFragmentStore(NAMED_PFS);
 
-    float diam = 8.f;
-    float scale = 1.0f / zoom;
+                bindTexture(NAMED_PF, 0, loadI32(ALLOC_ICON_IDS, icon));
+                drawRect(iconLeft, iconTop, iconRight, iconBottom, 0.0f);
 
-    // Bug makes 1.0f alpha fail.
-    color(1.0f, 1.0f, 1.0f, 0.99f);
+                // label
+                float labelLeft = s + ((cellWidth-labelWidth)/2.0f);
+                float labelTop = iconBottom - iconLabelGutter;
 
-    float rot = drawRot * scale;
-    float rotStep = 16.0f / 180.0f * 3.14f * scale;
-    rowCount = 4;
-    int index = 0;
-    int iconCount = loadI32(0, STATE_COUNT);
-    while (iconCount) {
-        float tmpSin = sinf(rot);
-        float tmpCos = cosf(rot);
-            //debugF("rot", rot);
+                bindProgramFragment(NAMED_PFText);
+                bindProgramFragmentStore(NAMED_PFSText);
 
-        float tx1 = tmpSin * diam - (tmpCos * scale * 0.9f);
-        float tx2 = tx1 + (tmpCos * scale * 1.8f);
-        float tz1 = tmpCos * diam + (tmpSin * scale * 0.9f);
-        float tz2 = tz1 - (tmpSin * scale * 1.8f);
+                bindTexture(NAMED_PFText, 0, loadI32(ALLOC_LABEL_IDS, icon));
+                drawRect(labelLeft, labelTop, labelLeft+labelTextureWidth,
+                        labelTop-labelTextureHeight, 0.0f);
 
-        int y;
-        for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-            float ty1 = ((y * 3.1f) - 5.f) * scale;
-            float ty2 = ty1 + scale * 1.8f;
-            bindTexture(NAMED_PF, 0, loadI32(1, index));
-            drawQuad(tx1, ty1, tz1,
-                     tx2, ty1, tz2,
-                     tx2, ty2, tz2,
-                     tx1, ty2, tz1);
-
-            iconCount--;
-            index++;
-        }
-        rot = rot + rotStep;
-    }
-
-    if ((zoom < 1.1f) && (zoom > 0.9f)) {
-        bindProgramVertex(NAMED_PVOrtho);
-        bindProgramFragment(NAMED_PFText);
-        bindProgramFragmentStore(NAMED_PFSText);
-
-        rot = drawRot * scale;
-        index = 0;
-        iconCount = loadI32(0, STATE_COUNT);
-        while (iconCount) {
-            int y;
-
-            float tx = 240.f + floorf(sinf(rot) * 430.f) - 64.f + 16.f;
-
-            float alpha = 2.4f - (fabsf(tx - 240.f + 48.f) / 76.f);
-            if (alpha > 0.99f) {
-                alpha = 0.99f;
+                s += cellWidth + columnGutter;
+                icon++;
             }
-            alpha = alpha * (1.f - (fabsf(zoom - 1.f) * 10.f));
-
-            tx = tx + 0.25f;
-
-            for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-
-                if (alpha > 0) {
-                    color(1.0f, 1.0f, 1.0f, alpha);
-
-                    float ty = 654.f - y * 150.f;
-
-                    ty = ty + 0.25f;
-
-                    bindTexture(NAMED_PFText, 0, loadI32(3, index));
-                    drawRect(tx, ty, tx + 128.f, ty + 64.f, 0.5f);
-                }
-                iconCount--;
-                index++;
-            }
-            rot = rot + rotStep;
+            cellTop -= cellHeight;
         }
-
-
-        bindProgramVertex(NAMED_PV);
-        bindProgramFragment(NAMED_PF);
-        bindProgramFragmentStore(NAMED_PFS);
+        pageLeft += 2.0f;
     }
 
-    // Draw the selected icon
-    color(1.0f, 1.0f, 1.0f, 0.9f);
-    rot = drawRot * scale;
-    index = 0;
-    iconCount = loadI32(0, STATE_COUNT);
-    while (iconCount) {
-        int y;
-        for (y = rowCount -1; (y >= 0) && iconCount; y--) {
-            if (index == selectedID) {
-
-                float tmpSin = sinf(rot) * scale;
-                float tmpCos = cosf(rot) * scale;
-                float tx1 = tmpSin * diam * 0.9f - tmpCos * 2.f;
-                float tx2 = tx1 + (tmpCos * 4.f);
-                float tz1 = tmpCos * diam * 0.9f + tmpSin * 2.f;
-                float tz2 = tz1 - (tmpSin * 4.f);
-
-                float ty1 = ((y * 3.1f) - 4.5f) * scale;
-                float ty2 = ty1 + scale * 4.f;
-                bindTexture(NAMED_PF, 0, loadI32(1, index));
-                drawQuad(tx1, ty1, tz1,
-                         tx2, ty1, tz2,
-                         tx2, ty2, tz2,
-                         tx1, ty2, tz1);
-            }
-            iconCount--;
-            index++;
-        }
-        rot = rot + rotStep;
-    }
-
-    return 1;
+    return 0;
 }