Support compound translations

This commit is contained in:
Lactozilla 2024-01-19 19:35:29 -03:00
parent 6d1908c93e
commit 4b057f84ec

View file

@ -75,8 +75,7 @@ struct PaletteRemapParseResult
} tint;
};
boolean has_error;
char error[4096];
char *error;
};
void PaletteRemap_Init(void)
@ -156,14 +155,6 @@ boolean PaletteRemap_IsIdentity(remaptable_t *tr)
unsigned PaletteRemap_Add(remaptable_t *tr)
{
#if 0
for (unsigned i = 0; i < numpaletteremaps; i++)
{
if (PaletteRemap_Equal(tr, paletteremaps[i]))
return i;
}
#endif
numpaletteremaps++;
paletteremaps = Z_Realloc(paletteremaps, sizeof(remaptable_t *) * numpaletteremaps, PU_STATIC, NULL);
paletteremaps[numpaletteremaps - 1] = tr;
@ -453,15 +444,13 @@ struct ParsedTranslation
static struct ParsedTranslation *parsedTranslationListHead = NULL;
static struct ParsedTranslation *parsedTranslationListTail = NULL;
static void AddParsedTranslation(unsigned id, int base_translation, struct PaletteRemapParseResult *data)
static void AddParsedTranslation(remaptable_t *remap, remaptable_t *base_translation, struct PaletteRemapParseResult *data)
{
struct ParsedTranslation *node = Z_Calloc(sizeof(struct ParsedTranslation), PU_STATIC, NULL);
node->remap = paletteremaps[id];
node->remap = remap;
node->data = data;
if (base_translation != -1)
node->baseTranslation = paletteremaps[base_translation];
node->baseTranslation = base_translation;
if (parsedTranslationListHead == NULL)
parsedTranslationListHead = parsedTranslationListTail = node;
@ -511,12 +500,20 @@ void R_LoadParsedTranslations(void)
struct ParsedTranslation *next = node->next;
remaptable_t *tr = node->remap;
PaletteRemap_SetIdentity(tr);
if (tr)
{
if (tr->num_entries == 0)
{
tr->num_entries = NUM_PALETTE_ENTRIES;
if (node->baseTranslation)
memcpy(tr, node->baseTranslation, sizeof(remaptable_t));
PaletteRemap_SetIdentity(tr);
PaletteRemap_ApplyResult(tr, result);
if (node->baseTranslation)
memcpy(tr, node->baseTranslation, sizeof(remaptable_t));
}
PaletteRemap_ApplyResult(tr, result);
}
Z_Free(result);
Z_Free(node);
@ -553,15 +550,17 @@ static boolean ParseDecimal(tokenizer_t *sc, double *out)
static struct PaletteRemapParseResult *ThrowError(const char *format, ...)
{
const size_t err_size = 512 * sizeof(char);
struct PaletteRemapParseResult *err = Z_Calloc(sizeof(struct PaletteRemapParseResult), PU_STATIC, NULL);
err->error = Z_Calloc(err_size, PU_STATIC, NULL);
va_list argptr;
va_start(argptr, format);
vsnprintf(err->error, sizeof err->error, format, argptr);
vsnprintf(err->error, err_size, format, argptr);
va_end(argptr);
err->has_error = true;
return err;
}
@ -789,15 +788,119 @@ static struct PaletteRemapParseResult *PaletteRemap_ParseTranslation(const char
return result;
}
static void PrintError(const char *name, const char *format, ...)
{
char error[256];
va_list argptr;
va_start(argptr, format);
vsnprintf(error, sizeof error, format, argptr);
va_end(argptr);
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': %s\n", name, error);
}
#define CHECK_EOF() \
if (!tkn) \
{ \
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': Unexpected EOF\n", name); \
PrintError(name, "Unexpected EOF"); \
goto fail; \
}
struct NewTranslation
{
int id;
char *name;
char *base_translation_name;
struct PaletteRemapParseResult **results;
size_t num_results;
};
static void AddNewTranslation(struct NewTranslation **list_p, size_t *num, char *name, int id, char *base_translation_name, struct PaletteRemapParseResult *parse_result)
{
struct NewTranslation *list = *list_p;
size_t count = *num;
for (size_t i = 0; i < count; i++)
{
struct NewTranslation *entry = &list[i];
if (entry->id == id && strcmp(entry->name, name) == 0)
{
if (entry->base_translation_name && base_translation_name
&& strcmp(entry->base_translation_name, base_translation_name) != 0)
continue;
entry->num_results++;
entry->results = Z_Realloc(entry->results,
entry->num_results * sizeof(struct PaletteRemapParseResult **), PU_STATIC, NULL);
entry->results[entry->num_results - 1] = parse_result;
return;
}
}
size_t i = count;
count++;
list = Z_Realloc(list, count * sizeof(struct NewTranslation), PU_STATIC, NULL);
struct NewTranslation *entry = &list[i];
entry->name = name;
entry->id = id;
entry->base_translation_name = base_translation_name;
entry->num_results = 1;
entry->results = Z_Realloc(entry->results, 1 * sizeof(struct PaletteRemapParseResult **), PU_STATIC, NULL);
entry->results[0] = parse_result;
*list_p = list;
*num = count;
}
static void PrepareNewTranslations(struct NewTranslation *list, size_t count)
{
if (!list)
return;
for (size_t i = 0; i < count; i++)
{
struct NewTranslation *entry = &list[i];
remaptable_t *tr = R_GetTranslationByID(entry->id);
if (tr == NULL)
{
tr = PaletteRemap_New();
R_AddCustomTranslation(entry->name, PaletteRemap_Add(tr));
}
remaptable_t *base_translation = NULL;
char *base_translation_name = entry->base_translation_name;
if (base_translation_name)
{
int base_translation_id = R_FindCustomTranslation(base_translation_name);
if (base_translation_id == -1)
PrintError(entry->name, "No translation named '%s'", base_translation_name);
else
base_translation = R_GetTranslationByID(base_translation_id);
}
// The translation is not generated until later, because the palette may not have been loaded.
// We store the result for when it's needed.
for (size_t j = 0; j < entry->num_results; j++)
AddParsedTranslation(tr, base_translation, entry->results[j]);
tr->num_entries = 0;
Z_Free(base_translation_name);
Z_Free(entry->results);
Z_Free(entry->name);
}
Z_Free(list);
}
void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
{
tokenizer_t *sc = NULL;
const char *tkn = NULL;
char *lumpData = (char *)W_CacheLumpNumPwad(wadNum, lumpnum, PU_STATIC);
size_t lumpLength = W_LumpLengthPwad(wadNum, lumpnum);
char *text = (char *)Z_Malloc((lumpLength + 1), PU_STATIC, NULL);
@ -805,14 +908,18 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
text[lumpLength] = '\0';
Z_Free(lumpData);
tokenizer_t *sc = Tokenizer_Open(text, 1);
const char *tkn = sc->get(sc, 0);
sc = Tokenizer_Open(text, 1);
tkn = sc->get(sc, 0);
struct NewTranslation *list = NULL;
size_t list_count = 0;
while (tkn != NULL)
{
int base_translation = -1;
char *name = Z_StrDup(tkn);
char *base_translation_name = NULL;
tkn = sc->get(sc, 0);
CHECK_EOF();
if (strcmp(tkn, ":") == 0)
@ -820,19 +927,15 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
tkn = sc->get(sc, 0);
CHECK_EOF();
base_translation = R_FindCustomTranslation(tkn);
if (base_translation == -1)
{
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': No translation named '%s'\n", name, tkn);
goto fail;
}
base_translation_name = Z_StrDup(tkn);
tkn = sc->get(sc, 0);
CHECK_EOF();
}
if (strcmp(tkn, "=") != 0)
{
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': Expected '=', got '%s'\n", name, tkn);
PrintError(name, "Expected '=', got '%s'", tkn);
goto fail;
}
tkn = sc->get(sc, 0);
@ -840,52 +943,65 @@ void R_ParseTrnslate(INT32 wadNum, UINT16 lumpnum)
if (strcmp(tkn, "\"") != 0)
{
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': Expected '=', got '%s'\n", name, tkn);
PrintError(name, "Expected '\"', got '%s'", tkn);
goto fail;
}
tkn = sc->get(sc, 0);
CHECK_EOF();
struct PaletteRemapParseResult *result = NULL;
int existing_id = R_FindCustomTranslation(name);
// Parse all of the translations
do {
result = PaletteRemap_ParseTranslation(tkn);
if (result->has_error)
struct PaletteRemapParseResult *parse_result = PaletteRemap_ParseTranslation(tkn);
if (parse_result->error)
{
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': %s\n", name, result->error);
Z_Free(result);
PrintError(name, "%s", parse_result->error);
Z_Free(parse_result->error);
goto fail;
}
else
{
AddNewTranslation(&list, &list_count, name, existing_id, base_translation_name, parse_result);
}
tkn = sc->get(sc, 0);
if (!tkn)
break;
if (strcmp(tkn, "\"") != 0)
if (!tkn || strcmp(tkn, "\"") != 0)
{
CONS_Alert(CONS_ERROR, "Error parsing translation '%s': Expected '=', got '%s'\n", name, tkn);
if (tkn)
PrintError(name, "Expected '\"', got '%s'", tkn);
else
PrintError(name, "Expected '\"', got EOF");
goto fail;
}
// Get ',' or parse the next line
tkn = sc->get(sc, 0);
if (!tkn || strcmp(tkn, ",") != 0)
break;
// Get '"'
tkn = sc->get(sc, 0);
if (!tkn || strcmp(tkn, "\"") != 0)
{
if (!tkn)
PrintError(name, "Expected '\"', got EOF");
else
PrintError(name, "Expected '\"', got '%s'", tkn);
goto fail;
}
tkn = sc->get(sc, 0);
CHECK_EOF();
} while (true);
// Allocate it and register it
remaptable_t *tr = PaletteRemap_New();
unsigned id = PaletteRemap_Add(tr);
R_AddCustomTranslation(name, id);
// Free this, since it's no longer needed
Z_Free(name);
// The translation is not generated until later, because the palette may not have been loaded.
// We store the result for when it's needed.
AddParsedTranslation(id, base_translation, result);
}
fail:
// Now add all of the new translations
if (list)
PrepareNewTranslations(list, list_count);
Tokenizer_Close(sc);
Z_Free(text);
}