changeset 496:966617f0f6cd

Add a simple utility for generating different sinus, etc. value tables in c64 assembler format.
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 17 Nov 2012 01:52:59 +0200
parents 30145d17aebd
children b02f1bfce53b
files Makefile.gen gentab.c
diffstat 2 files changed, 269 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Fri Nov 16 19:18:03 2012 +0200
+++ b/Makefile.gen	Sat Nov 17 01:52:59 2012 +0200
@@ -192,7 +192,7 @@
 ifeq ($(DM_BUILD_TOOLS),yes)
 DMLIB_OBJS += libgfx.o lib64gfx.o
 ifeq ($(DM_USE_STDIO),yes)
-BINARIES+= objlink data2inc gfxconv
+BINARIES+= objlink data2inc gfxconv gentab
 ifeq ($(SUP_MODLOAD),yes)
 BINARIES+= viewmod mod2wav testpl
 ifeq ($(DM_GFX_BLITS),yes)
@@ -391,6 +391,10 @@
 	@echo " LINK $+"
 	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS)
 
+$(BINPATH)gentab$(EXEEXT): $(OBJPATH)gentab.o $(DMLIB_A)
+	@echo " LINK $+"
+	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) -lm
+
 
 ###
 ### Editor targets
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gentab.c	Sat Nov 17 01:52:59 2012 +0200
@@ -0,0 +1,264 @@
+#include "dmlib.h"
+#include "dmargs.h"
+#include <math.h>
+
+enum
+{
+    MT_SIN,
+    MT_COS,
+    MT_SMOOTH1,
+    MT_SCURVE,
+    MT_SMOOTH1_CLAMP,
+    MT_SCURVE_CLAMP,
+    MT_SIN_SCURVE,
+
+    MT_LAST
+};
+
+
+typedef struct
+{
+    char *name;
+    char *desc;
+} DMTransType;
+
+static DMTransType dmTransTypes[MT_LAST] =
+{
+    { "sin", "Sine" },
+    { "cos", "Cosine" },
+    { "smooth1", "Smoothstep1 LERP" },
+    { "scurve", "S-curve LERP" },
+    { "smooth1-clamp", "Clamped smoothstep1 LERP" },
+    { "scurve-clamp", "Clamped S-curve LERP" },
+    { "sin-scurve", "Sine S-curve" },
+};
+
+
+DMFloat
+    optSOffset     = 0.0f,
+    optSAmplitude  = 1.0f,
+    optSOmega      = 1.0f,
+    optStartValue  = 0.0f,
+    optEndValue    = 1.0f;
+
+int optNSteps      = 64,
+    optPerLine     = 16,
+    optTransType   = -1;
+
+char
+    *optObjectName = NULL,
+    *optOutFilename = NULL;
+
+
+static DMOptArg optList[] =
+{
+    {  0, '?', "help",        "Show this help", OPT_NONE },
+    {  1, 'v', "verbose",     "Increase verbosity", OPT_NONE },
+    {  2, 'o', "output",      "Set output file (default stdout)", OPT_ARGREQ },
+    {  3, 'n', "name",        "Set output object name", OPT_ARGREQ },
+
+    {  4, 's', "steps",       "Number of steps/values in output table", OPT_ARGREQ },
+    {  5, 't', "type",        "Curve/interpolation type (see list)", OPT_ARGREQ },
+
+    {  6, 'O', "offset",      "Output data offset", OPT_ARGREQ },
+    {  7, 'A', "amplitude",   "Output amplitude scale", OPT_ARGREQ },
+    {  8, 'W', "omega",       "Omega (w) multiplier", OPT_ARGREQ },
+
+    {  9, 'S', "start",       "Start value (only smooth/scurve)", OPT_ARGREQ },
+    { 10, 'E', "end",         "End value (only smooth/scurve)", OPT_ARGREQ },
+};
+
+static const int optListN = sizeof(optList) / sizeof(optList[0]);
+
+
+void argShowHelp()
+{
+    int index;
+    dmPrintBanner(stdout, dmProgName, "[options]");
+    dmArgsPrintHelp(stdout, optList, optListN);
+
+    printf("\nAvailable types:\n");
+    for (index = 0; index < MT_LAST; index++)
+    {
+        DMTransType *tm = &dmTransTypes[index];
+        printf("%-15s | %s\n", tm->name, tm->desc);
+    }
+    printf("\n");
+}
+
+
+BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
+{
+    switch (optN)
+    {
+        case 0:
+            argShowHelp();
+            exit(0);
+            break;
+
+        case 1:
+            dmVerbosity++;
+            break;
+        
+        case 2:
+            optOutFilename = optArg;
+            break;
+        
+        case 3:
+            optObjectName = optArg;
+            break;
+        
+        case 4:
+            {
+                int tmp;
+                if (sscanf(optArg, "%d", &tmp) != 1)
+                {
+                    dmError("Invalid number of steps argument '%s'.\n", optArg);
+                    return FALSE;
+                }
+                optNSteps = tmp;
+            }
+            break;
+
+        case 5:
+            {
+                int index;
+                for (index = 0; index < MT_LAST; index++)
+                {
+                    DMTransType *tm = &dmTransTypes[index];
+                    if (strcasecmp(tm->name, optArg) == 0)
+                    {
+                        optTransType = index;
+                        return TRUE;
+                    }
+                }
+                dmError("Invalid transformation type option '%s'.\n",
+                    optArg);
+                return FALSE;
+            }
+            break;
+
+        case 6:
+        case 7:
+        case 8:
+        case 9:
+        case 10:
+            {
+                DMFloat tmp;
+                if (sscanf(optArg, "%f", &tmp) != 1)
+                {
+                    dmError("Invalid %s option argument '%s', expected a floating point value.\n",
+                        currArg, optArg);
+                    return FALSE;
+                }
+                switch (optN)
+                {
+                    case  6: optSOffset = tmp; break;
+                    case  7: optSAmplitude = tmp; break;
+                    case  8: optSOmega = tmp; break;
+                    case  9: optStartValue = tmp; break;
+                    case 10: optEndValue = tmp; break;
+                }
+            }
+            break;
+
+        default:
+            dmError("Unknown argument '%s'.\n", currArg);
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+int main(int argc, char *argv[])
+{
+    FILE *outFile;
+    DMLerpContext ctx;
+    int step, n;
+
+    dmInitProg("gentab", "Sine, etc. table generator", "0.1", NULL, NULL);
+    dmVerbosity = 1;
+
+    // Parse arguments
+    if (!dmArgsProcess(argc, argv, optList, optListN,
+        argHandleOpt, NULL, TRUE))
+        exit(1);
+
+    // Check settings
+    if (optTransType < 0)
+    {
+        dmError("No transformation type set, perhaps try --help\n");
+        return -1;
+    }
+    
+    if (optObjectName == NULL)
+    {
+        dmError("Object name not specified, try --help\n");
+        return -2;
+    }
+
+    if (optOutFilename == NULL)
+        outFile = stdout;
+    else
+    if ((outFile = fopen(optOutFilename, "w")) == NULL)
+    {
+        int err = dmGetErrno();
+        dmError("Could not open output file '%s', %d: %s\n",
+            optOutFilename, err, dmErrorStr(err));
+        return -2;
+    }
+    
+
+    // Generate table
+    dmLerpInit(&ctx, optStartValue, optEndValue, optNSteps);
+
+    fprintf(outFile,
+        "cnt_%s = %d\n"
+        "vtab_%s: ",
+        optObjectName,
+        optNSteps,
+        optObjectName
+        );
+
+    for (n = 0, step = 0; step < optNSteps; step++)
+    {
+        DMFloat t = ((DMFloat) step * optSOmega) / (DMFloat) optNSteps, delta, value;
+        
+        switch (optTransType)
+        {
+            case MT_SIN:           delta = sin(t * 2 * DM_PI); break;
+            case MT_COS:           delta = cos(t * 2 * DM_PI); break;
+
+            case MT_SMOOTH1:       delta = dmLerp1(&ctx, step); break;
+            case MT_SCURVE:        delta = dmLerpSCurve(&ctx, step); break;
+            case MT_SMOOTH1_CLAMP: delta = dmLerp1Clamp(&ctx, step); break;
+            case MT_SCURVE_CLAMP:  delta = dmLerpSCurveClamp(&ctx, step); break;
+            case MT_SIN_SCURVE:    delta = dmLerpSCurveClamp(&ctx, step); break;
+            
+            default: delta = 0;
+        }
+        
+        value = optSOffset + delta * optSAmplitude;
+        
+        // Print the value
+        if (n == 0)
+            fprintf(outFile, "\t.byte ");
+
+        fprintf(outFile, "%ld%s",
+            lrint(value),
+            (n < optPerLine - 1) ? "," : "");
+
+        if (++n >= optPerLine)
+        {
+            fprintf(outFile, "\n");
+            n = 0;
+        }
+    }
+    if (n > 0)
+        fprintf(outFile, "\n");
+    
+    fprintf(outFile, "\n");
+
+    return 0;
+}