summaryrefslogtreecommitdiff
path: root/ipl/packs/loadfunc/cspgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipl/packs/loadfunc/cspgen.c')
-rw-r--r--ipl/packs/loadfunc/cspgen.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/ipl/packs/loadfunc/cspgen.c b/ipl/packs/loadfunc/cspgen.c
new file mode 100644
index 0000000..3a88ee0
--- /dev/null
+++ b/ipl/packs/loadfunc/cspgen.c
@@ -0,0 +1,113 @@
+/*
+ * cspgen(image, cycle) - calculate next "cyclic space" generation
+ *
+ * The image is considered a torus, with top and bottom connected directly
+ * and with sides connected using a shift of one row.
+ */
+
+/*
+ * internal buffer layout:
+ *
+ * image header
+ * copy of last row
+ * original array
+ * copy of first row
+ *
+ * new array is stored atop old array, but directly after the header.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include "icall.h"
+
+
+int cspgen(int argc, descriptor *argv)
+{
+ int ulength, period, i;
+ char *ustring, *udata, *cycle;
+ char *old, *new;
+ char o, x;
+
+ int w, h, n; /* width, height, total pixels */
+
+ char hbuf[20]; /* image header buffer */
+ int hlen; /* header length */
+
+ static char *ibuf; /* image buffer */
+ static int ilen; /* buffer length */
+ int ineed; /* buffer length needed */
+
+ static char map[256]; /* mapping from one char to next */
+
+ /*
+ * Get the parameters.
+ */
+ ArgString(1); /* validate types */
+ ArgString(2);
+ ustring = StringAddr(argv[1]); /* universe string and length */
+ ulength = StringLen(argv[1]);
+ cycle = StringAddr(argv[2]); /* cycle and length */
+ period = StringLen(argv[2]);
+ sscanf(ustring, "%d", &w); /* row width */
+
+ /*
+ * Build the generation mapping table.
+ */
+ map[cycle[period-1] & 0xFF] = cycle[0]; /* last maps to first */
+ for (i = 1; i < period; i++)
+ map[cycle[i-1] & 0xFF] = cycle[i];
+
+ /*
+ * Copy the image header (through the second comma) to hbuf.
+ */
+ old = ustring;
+ new = hbuf;
+ while ((*new++ = *old++) != ',')
+ ;
+ while ((*new++ = *old++) != ',')
+ ;
+ udata = old;
+ hlen = udata - ustring; /* header length */
+
+ /*
+ * Allocate the image buffer.
+ */
+ n = ulength - hlen; /* number of pixels */
+ if (n % w != 0)
+ Error(205);
+ h = n / w; /* image height */
+
+ ineed = hlen + n + 2 * w; /* buffer size needed */
+ if (ilen < ineed)
+ if (!(ibuf = realloc(ibuf, ilen = ineed)))
+ Error(305);
+
+ /*
+ * Copy the image into the buffer. Allow for the possibility that
+ * the image already be *in* the buffer.
+ */
+ new = ibuf + hlen;
+ old = new + w;
+ memmove(old, udata, n); /* main image, leaving room */
+ memcpy(old - w, old + n - w, w); /* dup last row first first */
+ memcpy(old + n, old, w); /* dup first row beyond last */
+
+ /*
+ * Create the new image.
+ */
+ memcpy(ibuf, hbuf, hlen);
+ for (i = 0; i < n; i++) {
+ o = *old;
+ x = map[o & 0xFF];
+ if (old[-1] == x || old[1] == x || old[-w] == x || old[w] == x)
+ o = x;
+ *new++ = o;
+ old++;
+ }
+
+ /*
+ * Return the result.
+ */
+ RetConstStringN(ibuf, ulength);
+}