view tools/gentab.c @ 2208:90ec1ec89c56

Revamp the palette handling in lib64gfx somewhat, add helper functions to lib64util for handling external palette file options and add support for specifying one of the "internal" palettes or external (.act) palette file to gfxconv and 64vw.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 14 Jun 2019 05:01:12 +0300
parents e3f0eaf23f4f
children 2e656da1b10b
line wrap: on
line source

#include "dmtool.h"
#include "dmlib.h"
#include "dmargs.h"
#include "dmcurves.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 const 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, 0);

    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)
                {
                    dmErrorMsg("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;
                    }
                }
                dmErrorMsg("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)
                {
                    dmErrorMsg("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:
            dmErrorMsg("Unimplemented option argument '%s'.\n", currArg);
            return FALSE;
    }

    return TRUE;
}


int main(int argc, char *argv[])
{
    FILE *outFile;
    DMLerpContext ctx;
    int step, n;

    dmInitProg("gentab", "Table generator", "0.2", NULL, NULL);
    dmVerbosity = 1;

    // Parse arguments
    if (!dmArgsProcess(argc, argv, optList, optListN,
        argHandleOpt, NULL, OPTH_BAILOUT))
        exit(1);

    // Check settings
    if (optTransType < 0)
    {
        dmErrorMsg("No transformation type set, perhaps try --help\n");
        return -1;
    }

    if (optObjectName == NULL)
    {
        dmErrorMsg("Object name not specified, try --help\n");
        return -2;
    }

    if (optOutFilename == NULL)
        outFile = stdout;
    else
    if ((outFile = fopen(optOutFilename, "w")) == NULL)
    {
        int err = dmGetErrno();
        dmErrorMsg("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;
}