diff options
author | Eugene Sandulenko | 2009-02-15 11:39:07 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2009-02-15 11:39:07 +0000 |
commit | e241843bec22600ab4ef98e7a085e82aac73fc93 (patch) | |
tree | 61a793884d3462e1feb80e80f202d8816d0c8ec4 /engines/sci/gfx/gfx_res_options.cpp | |
parent | e9f742806362a84ffdb176a7414318dd2ab4df89 (diff) | |
download | scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.gz scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.bz2 scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.zip |
- Remove some unneeded files
- Mass rename .c to .cpp
svn-id: r38227
Diffstat (limited to 'engines/sci/gfx/gfx_res_options.cpp')
-rw-r--r-- | engines/sci/gfx/gfx_res_options.cpp | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/engines/sci/gfx/gfx_res_options.cpp b/engines/sci/gfx/gfx_res_options.cpp new file mode 100644 index 0000000000..0692fece0f --- /dev/null +++ b/engines/sci/gfx/gfx_res_options.cpp @@ -0,0 +1,652 @@ +/*************************************************************************** + gfx_res_options.c Copyright (C) 2002 Christoph Reichenbach + + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public Licence as + published by the Free Software Foundaton; either version 2 of the + Licence, or (at your option) any later version. + + It is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + merchantibility or fitness for a particular purpose. See the + GNU General Public Licence for more details. + + You should have received a copy of the GNU General Public Licence + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + + Please contact the maintainer for any program-related bug reports or + inquiries. + + Current Maintainer: + + Christoph Reichenbach (CR) <jameson@linuxgames.com> + +***************************************************************************/ + +#include "sci/include/gfx_system.h" +#include "sci/include/gfx_options.h" +#include "sci/include/gfx_resmgr.h" + +#include <ctype.h> + +/*#define DEBUG*/ + +static gfx_res_pattern_list_t* +pattern_list_insert(gfx_res_pattern_list_t *list, int min, int max) +{ + gfx_res_pattern_list_t *retval = (gfx_res_pattern_list_t*)sci_malloc(sizeof(gfx_res_pattern_list_t)); + retval->pattern.min = min; + retval->pattern.max = max; + retval->next = list; + + return retval; +} + +static int +pattern_list_len(gfx_res_pattern_list_t *list) +{ + int v = 0; + while (list) { + ++v; + list = list->next; + } + + return v; +} + +static void +pattern_list_flatten(gfx_res_pattern_t *dest, gfx_res_pattern_list_t *list) +{ + while (list) { + *dest++ = list->pattern; + list = list->next; + } +} + +static inline void +pattern_list_free(gfx_res_pattern_list_t *list) +{ + if (list) + pattern_list_free(list->next); + + free(list); +} + + +static inline int +extract_pattern(gfx_res_pattern_list_t **destp, + char *src, int offset) +{ + char *src_orig = src - offset; + int final = 0; + int wildcard = 0; + + while (!final) { + char *end = strchr(src, ','); + if (end) + *end = 0; + else + final = 1; + + while (*src && isblank(*src)) + ++src; + + if (*src == '*' + || *src == '_') { + wildcard = 1; + ++src; + } else if (*src == '.' || isdigit(*src)) { + char *endp; + int start = strtol(src, &endp, 0); + + if (*src == '.' + && src[1] == '.') { + start = GFX_RES_PATTERN_MIN; + endp = src; + } + + src = endp; + + while (*src && isblank(*src)) + ++src; + + if (*src) { + int stop; + if (*src == '.' + && src[1] == '.') { + + src += 2; + while (*src && isblank(*src)) + ++src; + + if (!*src) + stop = GFX_RES_PATTERN_MAX; + else if (!isdigit(*src)) { + if (end) + *end = ','; + goto lexical_error_label; + } + + stop = strtol(src, &endp, 0); + src = endp; + + *destp = pattern_list_insert(*destp, + start, stop); + + } else { /* No ellipsis */ + if (end) + *end = ','; + goto lexical_error_label; + } + } else /* End of sub-pattern */ + *destp = pattern_list_insert(*destp, + start, start); + + while (*src && isblank(*src)) + ++src; + + if (*src) { + if (end) + *end = ','; + goto lexical_error_label; + } + + } else { + if (end) + *end = ','; + sciprintf("[gfx-conf] Unexpected character '%c'\n", + *src); + goto lexical_error_label; + } + + if (!final) { + *end = ','; + src = end + 1; + } + } + + if (wildcard) { + pattern_list_free(*destp); + *destp = NULL; + } + + return 0; + + lexical_error_label: + sciprintf("[gfx-conf] Lexical error in pattern at offset %d\n", + src - src_orig); + return 1; +} + +static int +extract_mod_rule(char *src, gfx_res_mod_t *rule) +{ + char *orig_src = src; + char *endp; + float f[3]; + int i; + + rule->type = GFX_RES_MULTIPLY_FIXED; + + if (isdigit(*src) || *src == '.') { + f[0] = f[1] = f[2] = strtod(src, &endp); + + if (*endp) + goto mod_error_label; + } else if (*src == '(') { + i = 0; + ++src; + + do { + while (*src && isblank(*src)) + ++src; + if (!*src || !(isdigit(*src) || *src == '.')) { + sciprintf("[gfx-conf] Unexpected character '%c'\n", + *src); + goto mod_error_label; + } + f[i++] = strtod(src, &endp); + + src = endp; + + while (*src && isblank(*src)) + ++src; + + if ((i == 3) && *src != ')') { + sciprintf("[gfx-conf] Error: Expected ')' at end of modification rule\n"); + goto mod_error_label; + } else if (i<3 && !isdigit(*src) && *src != '.' && *src != ',') { + sciprintf("[gfx-conf] Error: Expected ',' as separator in modification rule, not '%c'\n", + *src); + goto mod_error_label; + } + ++src; + } while (i < 3); + + if (*src) { + sciprintf("[gfx-conf] Error: Trailing garbage after modification rule\n"); + goto mod_error_label; + } + + } else + goto mod_error_label; + + for (i = 0; i < 3; i++) { + int v = (int)(f[i] * 16.0); + rule->mod.factor[i] = (v > 255) ? 255 : v; + } + + return 0; + mod_error_label: + sciprintf("[gfx-conf] Ill-formed modification rule '%s'\n", + orig_src); + return 1; +} + + +extern gfx_pixmap_color_t gfx_sci0_image_colors[][GFX_SCI0_IMAGE_COLORS_NR]; + +#define PREDEFINED_PALETTES_NR 4 +static int +extract_assign_rule(char *src, gfx_res_assign_t *rule) +{ + /*char *orig_src = src;*/ + struct { + const char *name; + int colors_nr; + gfx_pixmap_color_t *colors; + } predefined_palettes[PREDEFINED_PALETTES_NR] = { + {"default", 16, (gfx_pixmap_color_t *) &(gfx_sci0_image_colors[0])}, + {"amiga", 16, (gfx_pixmap_color_t *) &(gfx_sci0_image_colors[1])}, + {"gray", 16, (gfx_pixmap_color_t *) &(gfx_sci0_image_colors[2])}, + {"grey", 16, (gfx_pixmap_color_t *) &(gfx_sci0_image_colors[2])}, + }; + int i; + + rule->type = GFX_RES_ASSIGN_TYPE_PALETTE; + + for (i = 0; i < PREDEFINED_PALETTES_NR; i++) + if (!strcmp(src, predefined_palettes[i].name)) { + rule->assign.palette.colors_nr = + predefined_palettes[i].colors_nr; + rule->assign.palette.colors = + predefined_palettes[i].colors; + return 0; + } + + sciprintf("[gfx-conf] Unknown palette '%s'\n", src); + return 1; + /* + assign_error_label: + sciprintf("[gfx-conf] Ill-formed assignment rule '%s'\n", + orig_src); + return 1; + */ +} + +#define CLASSES_NR 3 +int +gfx_update_conf(gfx_options_t *options, char *str) +{ + int total_patterns; + int mod = 0; /* Modifier or assignment rule? */ + char *orig_str = str; + char *sem_end; + + int fields_nr; /* Number of fields a restriction is possible by. + ** cursors:1, pics:2, views:3. */ + struct { + const char *class_name; + int class_id; + int fields_nr; + } classes[CLASSES_NR] = { + {"view", GFX_RESOURCE_TYPE_VIEW, 3}, + {"pic", GFX_RESOURCE_TYPE_PIC, 2}, + {"cursor", GFX_RESOURCE_TYPE_CURSOR, 1}, + }; + gfx_res_conf_t *conf = (gfx_res_conf_t*)sci_malloc(sizeof(gfx_res_conf_t)); + gfx_res_pattern_list_t *patterns = NULL; + gfx_res_pattern_list_t *loops = NULL; + gfx_res_pattern_list_t *cels = NULL; + gfx_res_pattern_list_t **fields[3] = { + &patterns, &loops, &cels + }; + int i; + int fieldcnt; + const char *pat_name_str; + + /* Extract pattern(s) */ + while (*str && isblank(*str)) + ++str; + + fields_nr = -1; + for (i = 0; i < CLASSES_NR; i++) { + int len = strlen(classes[i].class_name); + + if (!strncmp(str, classes[i].class_name, len)) { + pat_name_str = classes[i].class_name; + conf->type = classes[i].class_id; + fields_nr = classes[i].fields_nr; + str += len; + break; + } + } + + if (fields_nr == -1) { + sciprintf("[gfx-conf] Unexpected pattern class: Expected one of 'view', 'pic', 'cursor'\n"); + goto failure_label; + } + + fieldcnt = 0; + do { + while (*str && isblank(*str)) + ++str; + + if (!*str) + goto unexpected_end; + + if (*str == '=' + || *str == '*') + break; + + if (*str == '(') { + char *end = strchr(str, ')'); + + if (fieldcnt >= fields_nr) { + sciprintf("[gfx-conf] Error: Patterns of class '%s' may only be" + " constrained by %d arguments\n", + pat_name_str, fields_nr); + goto failure_label; + } + + if (!end) { + sciprintf("[gfx-conf] Unmatched parentheses at offset %d\n", + str - orig_str); + goto failure_label; + } + *end = 0; + + if (extract_pattern(fields[fieldcnt++], + str + 1, + str + 1 - orig_str)) + goto failure_label; + + *end = ')'; + str = end + 1; + + continue; + } + + sciprintf("[gfx-conf] Lexical error in pattern at offset %d: Unexpected '%c'\n", + str - orig_str, *str); + goto failure_label; + } while (1); + + + /* Flatten patterns */ + conf->patterns = NULL; + total_patterns = conf->patterns_nr = pattern_list_len(patterns); + total_patterns += (conf->loops_nr = pattern_list_len(loops)); + total_patterns += (conf->cels_nr = pattern_list_len(cels)); + + conf->patterns = (gfx_res_pattern_t*)sci_malloc(1 + (sizeof(gfx_res_pattern_t) * total_patterns)); + pattern_list_flatten(conf->patterns, patterns); + pattern_list_flatten(conf->patterns + conf->patterns_nr, loops); + pattern_list_flatten(conf->patterns + conf->patterns_nr + conf->loops_nr, cels); + + pattern_list_free(patterns); + patterns = NULL; + pattern_list_free(loops); + loops = NULL; + pattern_list_free(cels); + cels = NULL; + + /* Parse remainder */ + if (*str == '*') { + mod = 1; + ++str; + } + + if (*str != '=') { + sciprintf("[gfx-conf] Expected '='\n"); + goto failure_label; + } + + do { ++str; } + while (*str && isblank(*str)); + + sem_end = strchr(str, ';'); + if (!sem_end) { + sciprintf("[gfx-conf] Expected ';' at end of rule\n"); + goto failure_label; + } + do { *sem_end-- = 0; } + while (sem_end >= str + && isblank(*sem_end)); + + if (mod) { + if (extract_mod_rule(str, &conf->conf.mod)) + goto failure_label; + } else { + if (extract_assign_rule(str, &conf->conf.assign)) + goto failure_label; + } + + /* Write back into options */ + if (mod) { + conf->next = options->res_conf.mod[conf->type]; + options->res_conf.mod[conf->type] = conf; + } else { + conf->next = options->res_conf.assign[conf->type]; + options->res_conf.assign[conf->type] = conf; + } + + return 0; + + /* Error handling */ +unexpected_end: + sciprintf("[gfx-conf] Unexpected end of pattern encountered\n"); + failure_label: + sciprintf("[gfx-conf] Error occured in: '%s'\n", orig_str); + pattern_list_free(patterns); + pattern_list_free(loops); + pattern_list_free(cels); + if (conf->patterns) + free(conf->patterns); + free(conf); + return 1; +} + +static inline int +matches_patternlist(gfx_res_pattern_t *patterns, int nr, int val) +{ + int i; + for (i = 0; i < nr; i++) + if (patterns[i].min <= val + && patterns[i].max >= val) + return 1; + + return 0; +} + +#ifdef DEBUG +static void +print_pattern(gfx_res_pattern_t *pat) +{ + fprintf(stderr, "[%d..%d]", + pat->min, pat->max); +} +#endif + +static inline int +resource_matches_patternlists(gfx_res_conf_t *conf, + int type, int nr, int loop, int cel) +{ + int loc; +#ifdef DEBUG + int i; + fprintf(stderr, "[DEBUG:gfx-res] Trying to match against %d/%d/%d choices\n", + conf->patterns_nr, conf->loops_nr, conf->cels_nr); + for (i = 0; i < conf->patterns_nr; i++) { + fprintf(stderr, "[DEBUG:gfx-res] Pat #%d: ", i); + print_pattern(conf->patterns + i); + fprintf(stderr, "\n"); + } + loc = conf->patterns_nr; + for (i = 0; i < conf->loops_nr; i++) { + fprintf(stderr, "[DEBUG:gfx-res] Loop #%d: ", i); + print_pattern(conf->patterns + i + loc); + fprintf(stderr, "\n"); + } + loc += conf->loops_nr; + for (i = 0; i < conf->cels_nr; i++) { + fprintf(stderr, "[DEBUG:gfx-res] Cel #%d: ", i); + print_pattern(conf->patterns + i + loc); + fprintf(stderr, "\n"); + } +#endif + if (conf->patterns_nr && + !matches_patternlist(conf->patterns, + conf->patterns_nr, + nr)) + return 0; + + if (type == GFX_RESOURCE_TYPE_CURSOR) + return 1; + + /* Otherwise, we must match at least the loop (pic) + ** and, for views, the cel as well */ + loc = conf->patterns_nr; + if (conf->loops_nr && + !matches_patternlist(conf->patterns + loc, + conf->loops_nr, + loop)) + return 0; + + if (type != GFX_RESOURCE_TYPE_VIEW) + return 1; + + loc += conf->loops_nr; + + if (!conf->cels_nr) + return 1; + + return matches_patternlist(conf->patterns + loc, + conf->cels_nr, + cel); +} + +static inline gfx_res_conf_t * +find_match(gfx_res_conf_t *conflist, + int type, int nr, int loop, int cel) +{ + while (conflist) { + if (resource_matches_patternlists(conflist, + type, nr, loop, cel)) { +#ifdef DEBUG + fprintf(stderr, "[DEBUG:gfx-res] Found match!\n"); +#endif + return conflist; + } + + conflist = conflist->next; + } + return NULL; +} + +void +apply_assign(gfx_res_assign_t *conf, gfx_pixmap_t *pxm) +{ + /* Has a dynamically allocated palette? Must clean up */ + if (!(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) { + if (pxm->colors) + free(pxm->colors); + pxm->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + } + + pxm->colors_nr = conf->assign.palette.colors_nr; + pxm->colors = conf->assign.palette.colors; +} + +void +apply_mod(gfx_res_mod_t *mod, gfx_pixmap_t *pxm) +{ + gfx_pixmap_color_t *pal = pxm->colors; + int i, pal_size = pxm->colors_nr; + + /* Does not have a dynamically allocated palette? Must dup current one */ + if (pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE) { + int size = sizeof(gfx_pixmap_color_t) * pal_size; + pxm->colors = (gfx_pixmap_color_t*)sci_malloc(size); + memcpy(pxm->colors, pal, size); + pal = pxm->colors; + pxm->flags &= ~GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + /* Flag for later deallocation */ + } + + switch (mod->type) { + + case GFX_RES_MULTIPLY_FIXED: { + for (i = 0; i < pal_size; i++) { + int v; + +#define UPDATE_COL(nm, idx) \ + v = pal[i].nm; \ + v *= mod->mod.factor[idx]; \ + v >>= 4; \ + pal[i].nm = (v > 255)? 255 : v; + + UPDATE_COL(r, 0); + UPDATE_COL(g, 1); + UPDATE_COL(b, 2); +#undef UPDATE_COL + } + break; + } + + default: + GFXERROR("Using unexpected visual resource modifier %d\n", mod->type); + } +} + +int +gfx_get_res_config(gfx_options_t *options, gfx_pixmap_t *pxm) +{ + int restype = GFXR_RES_TYPE(pxm->ID); + int nr = GFXR_RES_NR(pxm->ID); + int loop = pxm->loop; + int cel = pxm->cel; + + gfx_res_conf_t *conf; + +#ifdef DEBUG + fprintf(stderr, "[DEBUG:gfx-res] Trying to conf %d/%d/%d/%d (ID=%d)\n", + restype, nr, loop, cel, pxm->ID); +#endif + + if (pxm->ID < 0 || restype < 0 || restype >= GFX_RESOURCE_TYPES_NR) + return 1; /* Not appropriate */ + + conf = find_match(options->res_conf.assign[restype], + restype, nr, loop, cel); + + if (conf) + apply_assign(&(conf->conf.assign), pxm); + + conf = options->res_conf.mod[restype]; + while (conf) { + conf = find_match(conf, + restype, nr, loop, cel); + if (conf) { + apply_mod(&(conf->conf.mod), pxm); + conf = conf->next; + } + } + fflush(NULL); + + return 0; +} |