diff options
Diffstat (limited to 'engines/sci/gfx')
24 files changed, 654 insertions, 548 deletions
diff --git a/engines/sci/gfx/font.cpp b/engines/sci/gfx/font.cpp index 02412a2f43..b70714fa34 100644 --- a/engines/sci/gfx/font.cpp +++ b/engines/sci/gfx/font.cpp @@ -192,8 +192,7 @@ static inline void render_char(byte *dest, byte *src, int width, int line_width, } } -gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int characters, - gfx_pixmap_color_t *fg0, gfx_pixmap_color_t *fg1, gfx_pixmap_color_t *bg) { +gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int characters, PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg) { unsigned char *text = (unsigned char *)stext; int height = font->height; int width = 0; @@ -201,7 +200,7 @@ gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int cha int fore_0, fore_1, back; int i; int hack = 0; - gfx_pixmap_color_t dummy = {0, 0, 0, 0}; + PaletteEntry dummy(0,0,0); // black byte *offset; for (i = 0; i < characters; i++) { @@ -217,35 +216,32 @@ gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *stext, int cha pxm = gfx_pixmap_alloc_index_data(gfx_new_pixmap(width, height, GFX_RESID_NONE, 0, 0)); - pxm->colors_nr = !!fg0 + !!fg1 + !!bg; - if (pxm->colors_nr == 0) { + int colors_nr = !!fg0 + !!fg1 + !!bg; + if (colors_nr == 0) { GFXWARN("Pixmap would have zero colors, resetting!\n"); - pxm->colors_nr = 3; + colors_nr = 3; hack = 1; fg0 = fg1 = bg = &dummy; } - pxm->colors = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * pxm->colors_nr); -#ifdef SATISFY_PURIFY - memset(pxm->colors, 0, sizeof(gfx_pixmap_color_t) * pxm->colors_nr); -#endif - pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_ALLOCATED | GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE; + pxm->palette = new Palette(colors_nr); + pxm->palette->name = "font"; i = 0; if (fg0 || hack) { - memcpy(pxm->colors + i, fg0, sizeof(gfx_pixmap_color_t)); + pxm->palette->setColor(i, fg0->r, fg0->g, fg0->b); fore_0 = i++; } else fore_0 = pxm->color_key; if (fg1 || hack) { - memcpy(pxm->colors + i, fg1, sizeof(gfx_pixmap_color_t)); + pxm->palette->setColor(i, fg1->r, fg1->g, fg1->b); fore_1 = i++; } else fore_1 = pxm->color_key; if (bg || hack) { - memcpy(pxm->colors + i, bg, sizeof(gfx_pixmap_color_t)); + pxm->palette->setColor(i, bg->r, bg->g, bg->b); back = i++; } else back = pxm->color_key; diff --git a/engines/sci/gfx/font.h b/engines/sci/gfx/font.h index 81d5b4274f..5e97e5bfa3 100644 --- a/engines/sci/gfx/font.h +++ b/engines/sci/gfx/font.h @@ -109,7 +109,7 @@ text_fragment_t *gfxr_font_calculate_size(gfx_bitmap_font_t *font, int max_width */ gfx_pixmap_t *gfxr_draw_font(gfx_bitmap_font_t *font, const char *text, int characters, - gfx_pixmap_color_t *fg0, gfx_pixmap_color_t *fg1, gfx_pixmap_color_t *bg); + PaletteEntry *fg0, PaletteEntry *fg1, PaletteEntry *bg); /* Draws text in a specific font to a pixmap ** Parameters: (gfx_bitmap_font_t *) font: The font to use for drawing ** (char *) text: The start of the text to draw diff --git a/engines/sci/gfx/gfx_driver.cpp b/engines/sci/gfx/gfx_driver.cpp index 51067b8604..dd92fda9f5 100644 --- a/engines/sci/gfx/gfx_driver.cpp +++ b/engines/sci/gfx/gfx_driver.cpp @@ -38,6 +38,7 @@ struct _scummvm_driver_state { byte *visual[2]; uint8 *pointer_data; int xsize, ysize; + uint8 *palette_data; }; #define S ((struct _scummvm_driver_state *)(drv->state)) @@ -75,7 +76,12 @@ static int scummvm_init_specific(gfx_driver_t *drv, int xfact, int yfact, int by } Graphics::PixelFormat format = { bytespp, 0, 0, 0, 0, 0, 0, 0, 0 }; - drv->mode = gfx_new_mode(xfact, yfact, format, 256, 0); + drv->mode = gfx_new_mode(xfact, yfact, format, new Palette(256), 0); + drv->mode->palette->name = "global"; + + S->palette_data = new uint8[4*256]; + for (i = 0; i < 4*256; ++i) + S->palette_data[i] = 0; return GFX_OK; } @@ -100,6 +106,9 @@ static void scummvm_exit(gfx_driver_t *drv) { delete[] S->pointer_data; S->pointer_data = NULL; + delete[] S->palette_data; + S->palette_data = NULL; + delete S; } } @@ -115,7 +124,7 @@ static void drawProc(int x, int y, int c, void *data) { static int scummvm_draw_line(gfx_driver_t *drv, Common::Point start, Common::Point end, gfx_color_t color, gfx_line_mode_t line_mode, gfx_line_style_t line_style) { - uint32 scolor = color.visual.global_index; + uint32 scolor = color.visual.parent_index; int xfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->xfact; int yfact = (line_mode == GFX_LINE_MODE_FINE)? 1: drv->mode->yfact; int xsize = S->xsize; @@ -148,7 +157,7 @@ static int scummvm_draw_filled_rect(gfx_driver_t *drv, rect_t rect, gfx_color_t gfx_rectangle_fill_t shade_mode) { if (color1.mask & GFX_MASK_VISUAL) { for (int i = rect.y; i < rect.y + rect.yl; i++) { - memset(S->visual[0] + i * S->xsize + rect.x, color1.visual.global_index, rect.xl); + memset(S->visual[0] + i * S->xsize + rect.x, color1.visual.parent_index, rect.xl); } } @@ -267,7 +276,7 @@ static uint8 *create_cursor(gfx_driver_t *drv, gfx_pixmap_t *pointer, int mode) for (int xc = 0; xc < pointer->index_xl; xc++) { uint8 color = *src; if (color != 255) - color = pointer->colors[color].global_index; + color = pointer->palette->getColor(color).parent_index; for (int scalectr = 0; scalectr < drv->mode->xfact; scalectr++) { *pos++ = color; } @@ -302,9 +311,16 @@ static int scummvm_set_palette(gfx_driver_t *drv, int index, byte red, byte gree return GFX_ERROR; } - byte color[] = {red, green, blue, 255}; - g_system->setPalette(color, index, 1); + S->palette_data[4*index+0] = red; + S->palette_data[4*index+1] = green; + S->palette_data[4*index+2] = blue; + S->palette_data[4*index+3] = 255; + + return GFX_OK; +} +static int scummvm_install_palette(gfx_driver_t *drv, Palette* palette) { + g_system->setPalette(S->palette_data, 0, palette->size()); return GFX_OK; } @@ -326,6 +342,7 @@ gfx_driver_t gfx_driver_scummvm = { scummvm_set_static_buffer, scummvm_set_pointer, scummvm_set_palette, + scummvm_install_palette, NULL }; diff --git a/engines/sci/gfx/gfx_driver.h b/engines/sci/gfx/gfx_driver.h index 4221e4b689..e61f305e66 100644 --- a/engines/sci/gfx/gfx_driver.h +++ b/engines/sci/gfx/gfx_driver.h @@ -281,7 +281,9 @@ struct gfx_driver_t { /* Graphics driver */ int (*set_palette)(gfx_driver_t *drv, int index, byte red, byte green, byte blue); - /* Manipulates a palette index in the hardware palette + /* Manipulates a palette index in the hardware palette. + ** The actual update is not performed until install_palette() is called. + ** This way updates can be batched. ** Parameters: (gfx_driver_t *) drv: The driver affected ** (int) index: The index of the palette entry to modify ** (int x int x int) red, green, blue: The RGB intensities to @@ -293,6 +295,8 @@ struct gfx_driver_t { /* Graphics driver */ ** set_palette() is only required for targets supporting color index mode. */ + int (*install_palette)(gfx_driver_t *drv, Palette* pal); + /* As set_palette, but for the full palette. */ void *state; /* Reserved for internal use */ diff --git a/engines/sci/gfx/gfx_pixmap_scale.cpp b/engines/sci/gfx/gfx_pixmap_scale.cpp index eacc78e47c..999a42315d 100644 --- a/engines/sci/gfx/gfx_pixmap_scale.cpp +++ b/engines/sci/gfx/gfx_pixmap_scale.cpp @@ -66,15 +66,16 @@ void FUNCNAME(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale) { alpha_dest = pxm->alpha_map = (byte *)sci_malloc(pxm->index_xl * xfact * pxm->index_yl * yfact); // Calculate all colors - for (i = 0; i < pxm->colors_nr; i++) { + for (i = 0; i < pxm->colors_nr(); i++) { int col; + const PaletteEntry& color = pxm->palette->getColor(i); if (PALETTE_MODE) - col = pxm->colors[i].global_index; + col = color.parent_index; else { - col = mode->red_mask & ((EXTEND_COLOR(pxm->colors[i].r)) >> mode->red_shift); - col |= mode->green_mask & ((EXTEND_COLOR(pxm->colors[i].g)) >> mode->green_shift); - col |= mode->blue_mask & ((EXTEND_COLOR(pxm->colors[i].b)) >> mode->blue_shift); + col = mode->red_mask & ((EXTEND_COLOR(color.r)) >> mode->red_shift); + col |= mode->green_mask & ((EXTEND_COLOR(color.g)) >> mode->green_shift); + col |= mode->blue_mask & ((EXTEND_COLOR(color.b)) >> mode->blue_shift); col |= alpha_ormask; } result_colors[i] = col; @@ -247,9 +248,10 @@ void FUNCNAME_LINEAR(gfx_mode_t *mode, gfx_pixmap_t *pxm, int scale) { rec[2] = other[2] - ctexel[2]; \ rec[3] = 0xffff - ctexel[3]; \ } else { \ - rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 16) - ctexel[0]; \ - rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 16) - ctexel[1]; \ - rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 16) - ctexel[2]; \ + const PaletteEntry& e = (*pxm->palette)[nr]; \ + rec[0] = (EXTEND_COLOR(e.r) >> 16) - ctexel[0]; \ + rec[1] = (EXTEND_COLOR(e.g) >> 16) - ctexel[1]; \ + rec[2] = (EXTEND_COLOR(e.b) >> 16) - ctexel[2]; \ rec[3] = 0 - ctexel[3]; \ } @@ -326,9 +328,10 @@ static inline void gfx_apply_delta(unsigned int *color, int *delta, int factor) rec[2] = 0; \ rec[3] = 0xffffff; \ } else { \ - rec[0] = (EXTEND_COLOR(pxm->colors[nr].r) >> 8); \ - rec[1] = (EXTEND_COLOR(pxm->colors[nr].g) >> 8); \ - rec[2] = (EXTEND_COLOR(pxm->colors[nr].b) >> 8); \ + const PaletteEntry& e = (*pxm->palette)[nr]; \ + rec[0] = (EXTEND_COLOR(e.r) >> 8); \ + rec[1] = (EXTEND_COLOR(e.g) >> 8); \ + rec[2] = (EXTEND_COLOR(e.b) >> 8); \ rec[3] = 0; \ } diff --git a/engines/sci/gfx/gfx_res_options.cpp b/engines/sci/gfx/gfx_res_options.cpp index c07ba96421..370140584b 100644 --- a/engines/sci/gfx/gfx_res_options.cpp +++ b/engines/sci/gfx/gfx_res_options.cpp @@ -115,29 +115,22 @@ static inline gfx_res_conf_t *find_match(gfx_res_conf_t *conflist, int type, int } 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; - } + if (pxm->palette) + pxm->palette->free(); - pxm->colors_nr = conf->assign.palette.colors_nr; - pxm->colors = conf->assign.palette.colors; + pxm->palette = new Palette(conf->assign.palette.colors, conf->assign.palette.colors_nr); + pxm->palette->name = "res"; } 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; + Palette *pal = pxm->palette; + int i, pal_size = pal ? pal->size() : 0; // 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 + if (pal && pal->isShared()) { + pal = pxm->palette->copy(); + pxm->palette->free(); + pxm->palette = pal; } switch (mod->type) { @@ -147,14 +140,17 @@ void apply_mod(gfx_res_mod_t *mod, gfx_pixmap_t *pxm) { int v; #define UPDATE_COL(nm, idx) \ - v = pal[i].nm; \ + v = 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); + nm = (v > 255)? 255 : v; + + PaletteEntry c = pal->getColor(i); + UPDATE_COL(c.r, 0); + UPDATE_COL(c.g, 1); + UPDATE_COL(c.b, 2); + pal->setColor(i, c.r, c.g, c.b); + #undef UPDATE_COL } break; diff --git a/engines/sci/gfx/gfx_resmgr.h b/engines/sci/gfx/gfx_resmgr.h index 005025670c..1f1c2454d4 100644 --- a/engines/sci/gfx/gfx_resmgr.h +++ b/engines/sci/gfx/gfx_resmgr.h @@ -83,8 +83,7 @@ struct gfx_resstate_t { int version; /* Interpreter version */ gfx_options_t *options; gfx_driver_t *driver; - gfx_pixmap_color_t *static_palette; - int static_palette_entries; + Palette *static_palette; int lock_counter; /* Global lock counter; increased for each new resource allocated. ** The newly allocated resource will then be assigned the new value ** of the lock_counter, as will any resources referenced afterwards. @@ -309,7 +308,7 @@ gfx_pixmap_t *gfxr_interpreter_get_cursor(gfx_resstate_t *state, int nr, void *i ** Returns : (gfx_pixmap_t *) The cursor pixmap, or NULL on error */ -gfx_pixmap_color_t *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal); +Palette *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal); /* Retreives the static palette from the interpreter-specific code ** Parameters: (int) version: Interpreter version to use ** (int *) colors_nr: Number of colors to use @@ -318,7 +317,7 @@ gfx_pixmap_color_t *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, i ** if a static palette must be used, NULL otherwise */ -gfx_pixmap_color_t *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr); +Palette *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr); /* Retreives the static palette from the interpreter-specific code ** Parameters: (int) version: Interpreter version to use ** (int *) colors_nr: Number of colors to use diff --git a/engines/sci/gfx/gfx_resource.cpp b/engines/sci/gfx/gfx_resource.cpp index 463c3e378e..70976fa685 100644 --- a/engines/sci/gfx/gfx_resource.cpp +++ b/engines/sci/gfx/gfx_resource.cpp @@ -55,8 +55,8 @@ static void gfxr_free_loop(gfx_driver_t *driver, gfxr_loop_t *loop) { void gfxr_free_view(gfx_driver_t *driver, gfxr_view_t *view) { int i; - if (view->colors && !(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) - free(view->colors); + if (view->palette) + view->palette->free(); if (view->loops) { for (i = 0; i < view->loops_nr; i++) @@ -352,21 +352,9 @@ static inline void _gfx_xlate_pixmap_trilinear(gfx_mode_t *mode, gfx_pixmap_t *p void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t filter) { int was_allocated = 0; - if (mode->palette && !(pxm->flags & GFX_PIXMAP_FLAG_PALETTE_ALLOCATED)) { - int i; - - for (i = 0; i < pxm->colors_nr; i++) { - if (gfx_alloc_color(mode->palette, pxm->colors + i) < 0) { - GFXWARN("Failed to allocate color %d/%d in pixmap (color %02x/%02x/%02x)!\n", - i, pxm->colors_nr, pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b); - pxm->colors[i].global_index = 0; - } - /* - GFXDEBUG("alloc(%02x/%02x/%02x) -> %d\n", pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b, pxm->colors[i].global_index); - */ - } - - pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_ALLOCATED; + if (mode->palette) { + if (pxm->palette && pxm->palette != mode->palette) + pxm->palette->mergeInto(mode->palette); } @@ -376,7 +364,7 @@ void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t fi // Assume that memory, if allocated already, will be sufficient // Allocate alpha map - if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS) + if (!mode->alpha_mask && pxm->colors_nr() < GFX_PIC_COLORS) pxm->alpha_map = (byte*)sci_malloc(mode->xfact * mode->yfact * pxm->index_xl * pxm->index_yl + 1); } else was_allocated = 1; @@ -398,7 +386,7 @@ void gfx_xlate_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode, gfx_xlate_filter_t fi GFXERROR("Attempt to filter pixmap %04x in invalid mode #%d\n", pxm->ID, filter); if (!was_allocated) { - if (!mode->alpha_mask && pxm->colors_nr < GFX_PIC_COLORS) + if (!mode->alpha_mask && pxm->colors_nr() < GFX_PIC_COLORS) free(pxm->alpha_map); free(pxm->data); } diff --git a/engines/sci/gfx/gfx_resource.h b/engines/sci/gfx/gfx_resource.h index 584a2a7e64..90911ef12d 100644 --- a/engines/sci/gfx/gfx_resource.h +++ b/engines/sci/gfx/gfx_resource.h @@ -62,12 +62,13 @@ namespace Sci { extern int sci0_palette; /* (gfx_pic_0.c) The 16 EGA base colors */ +extern Palette* gfx_sci0_image_pal[]; extern gfx_pixmap_color_t gfx_sci0_image_colors[][16]; /* (gfx_pic_0.c) The 256 interpolated colors (initialized when ** gfxr_init_pic() is called for the first time, or when gfxr_init_static_palette() is called) */ -extern gfx_pixmap_color_t gfx_sci0_pic_colors[]; +extern Palette* gfx_sci0_pic_colors; struct gfxr_pic0_params_t { @@ -113,8 +114,7 @@ struct gfxr_view_t { int ID; int flags; - int colors_nr; - gfx_pixmap_color_t *colors; + Palette *palette; int loops_nr; gfxr_loop_t *loops; @@ -176,7 +176,7 @@ void gfxr_clear_pic0(gfxr_pic_t *pic, int sci_titlebar_size); void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, int default_palette, int size, byte *resource, gfxr_pic0_params_t *style, int resid, int sci1, - gfx_pixmap_color_t *static_pal, int static_pal_nr); + Palette *static_pal); /* Draws a pic resource (all formats prior to SCI1.1) ** Parameters: (gfxr_pic_t *) pic: The pic to draw to ** (int) fill_normally: If 1, the pic is drawn normally; if 0, all @@ -197,7 +197,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int fill_normally, int default_palette, void gfxr_draw_pic11(gfxr_pic_t *pic, int fill_normally, int default_palette, int size, byte *resource, gfxr_pic0_params_t *style, int resid, - gfx_pixmap_color_t *static_pal, int static_pal_nr); + Palette *static_pal); /* Draws a pic resource (SCI1.1) ** Parameters: (gfxr_pic_t *) pic: The pic to draw to ** (int) fill_normally: If 1, the pic is drawn normally; if 0, all @@ -246,7 +246,7 @@ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette); /* SCI1 operations */ /*********************/ -gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int size); +Palette *gfxr_read_pal1(int id, byte *resource, int size); /* Reads an SCI1 palette ** Parameters: (int) id: Resource ID for the palette (or the view it was found in) ** (int *) colors_nr: Pointer to the variable the number of colors @@ -256,7 +256,7 @@ gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int s ** Returns : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors */ -gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file); +Palette *gfxr_read_pal1_amiga(Common::File &file); /* Reads an SCI1 palette ** Parameters: (int *) colors_nr: Pointer to the variable the number of colors ** will be stored in @@ -264,7 +264,7 @@ gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file); ** Returns : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors */ -gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int size); +Palette *gfxr_read_pal11(int id, byte *resource, int size); /* Reads an SCI1.1 palette ** Parameters: (int) id: Resource ID for the palette (or the view it was found in) ** (int *) colors_nr: Pointer to the variable the number of colors @@ -274,8 +274,7 @@ gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int ** Returns : (gfx_pixmap_color_t *) *colors_nr color_t entries with the colors */ -gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_t *static_pal, - int static_pal_nr); +gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal); /* Calculates an SCI1 view ** Parameters: (int) id: Resource ID of the view ** (byte *) resource: Pointer to the resource to read diff --git a/engines/sci/gfx/gfx_system.h b/engines/sci/gfx/gfx_system.h index a6fb285315..1bb098eaa3 100644 --- a/engines/sci/gfx/gfx_system.h +++ b/engines/sci/gfx/gfx_system.h @@ -30,6 +30,7 @@ #include "common/rect.h" #include "sci/sci_memory.h" #include "sci/tools.h" +#include "sci/gfx/palette.h" namespace Sci { @@ -50,26 +51,6 @@ namespace Sci { #define GFX_COLOR_SYSTEM -1 - -/** Palette color description */ -struct gfx_palette_color_t { - - int lockers; /* Number of pixmaps holding a lock on that color. - ** 0 means that the color is unused, -1 means that it is - ** "system allocated" and may not be freed. */ - byte r, g, b; /* Red, green, blue; intensity varies from 0 (min) to 255 (max) */ - -}; - -/** Palette description for color index modes */ -struct gfx_palette_t{ - - int max_colors_nr; /* Maximum number of allocated colors */ - gfx_palette_color_t *colors; /* Actual colors, malloc()d as a block */ -}; - - - #define GFX_MODE_IS_UNSCALED(mode) (((mode)->xfact == 1) && ((mode)->yfact == 1)) /* Reverse-endian: Target display has non-native endianness @@ -88,9 +69,8 @@ struct gfx_mode_t { uint32 flags; /* GFX_MODE_FLAG_* Flags- see above */ - gfx_palette_t *palette; /* Palette or NULL to indicate non-palette mode. - ** Palette (color-index) mode is only supported - ** for bytespp=1. */ + Palette *palette; // Palette or NULL to indicate non-palette mode. + // Palette mode is only supported for bytespp = 1 /* Color masks */ uint32 red_mask, green_mask, blue_mask, alpha_mask; @@ -119,7 +99,7 @@ struct gfx_pixmap_color_t{ /** Full color */ struct gfx_color_t { - gfx_pixmap_color_t visual; + PaletteEntry visual; uint8 alpha; /* transparency = (1-opacity) */ int8 priority, control; byte mask; /* see mask values below */ @@ -232,11 +212,7 @@ static inline rect_t gfx_rect_translate(rect_t rect, Common::Point offset) { #define GFX_PIC_COLORS 256 #define GFX_PIXMAP_FLAG_SCALED_INDEX (1<<0) /* Index data is scaled already */ -#define GFX_PIXMAP_FLAG_EXTERNAL_PALETTE (1<<1) /* The colors pointer points to an external palette */ #define GFX_PIXMAP_FLAG_INSTALLED (1<<2) /* Pixmap has been registered */ -#define GFX_PIXMAP_FLAG_PALETTE_ALLOCATED (1<<3) /* Palette has been allocated */ -#define GFX_PIXMAP_FLAG_PALETTE_SET (1<<4) /* Palette has been propagated to the driver */ -#define GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE (1<<5) /* Used by text, which uses preallocated colors */ #define GFX_PIXMAP_FLAG_PALETTIZED (1<<6) /* Indicates a palettized view */ #define GFX_PIXMAP_COLOR_KEY_NONE -1 /* No transpacency colour key */ @@ -249,8 +225,9 @@ struct gfx_pixmap_t { /* gfx_pixmap_t: Pixel map */ /*** Color map ***/ - int colors_nr; - gfx_pixmap_color_t *colors; /* colors_nr color entries, or NULL if the + Palette *palette; + int colors_nr() const { return palette ? palette->size() : 0; } + /* color entries, or NULL if the ** default palette is to be used. ** A maximum of 255 colors is allowed; color ** index 0xff is reserved for transparency. @@ -294,10 +271,6 @@ struct gfx_pixmap_t { /* gfx_pixmap_t: Pixel map */ /*** Constant values ***/ /***********************/ -/* Default palettes */ -extern gfx_pixmap_color_t gfx_sci0_image_colors[][16]; -extern gfx_pixmap_color_t gfx_sci0_pic_colors[256]; - /* Return values */ enum gfx_return_value_t { GFX_OK = 0, /* Indicates "operation successful" */ diff --git a/engines/sci/gfx/gfx_tools.cpp b/engines/sci/gfx/gfx_tools.cpp index d500edacb0..13bff4f0ec 100644 --- a/engines/sci/gfx/gfx_tools.cpp +++ b/engines/sci/gfx/gfx_tools.cpp @@ -44,7 +44,7 @@ void gfx_clip_box_basic(rect_t *box, int maxx, int maxy) { box->yl = maxy - box->y + 1; } -gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, int palette, int flags) { +gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags) { gfx_mode_t *mode = (gfx_mode_t *)sci_malloc(sizeof(gfx_mode_t)); mode->xfact = xfact; @@ -72,22 +72,14 @@ gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &form mode->alpha_shift = 0; } mode->flags = flags; - - if (palette) { - mode->palette = (gfx_palette_t *)sci_malloc(sizeof(gfx_palette_t)); - mode->palette->max_colors_nr = palette; - mode->palette->colors = (gfx_palette_color_t *)sci_calloc(sizeof(gfx_palette_color_t), palette); // Initialize with empty entries - } else - mode->palette = NULL; + mode->palette = palette; return mode; } void gfx_free_mode(gfx_mode_t *mode) { - if (mode->palette) { - free(mode->palette->colors); - free(mode->palette); - } + if (mode->palette) + mode->palette->free(); free(mode); } @@ -118,7 +110,7 @@ gfx_pixmap_t *gfx_clone_pixmap(gfx_pixmap_t *pxm, gfx_mode_t *mode) { gfx_pixmap_t *clone = (gfx_pixmap_t *)sci_malloc(sizeof(gfx_pixmap_t)); *clone = *pxm; clone->index_data = NULL; - clone->colors = NULL; + clone->palette = NULL; clone->data = NULL; gfx_pixmap_alloc_data(clone, mode); @@ -137,7 +129,7 @@ gfx_pixmap_t *gfx_new_pixmap(int xl, int yl, int resid, int loop, int cel) { pxm->alpha_map = NULL; pxm->data = NULL; pxm->internal.info = NULL; - pxm->colors = NULL; + pxm->palette = NULL; pxm->internal.handle = 0; pxm->index_xl = xl; @@ -158,35 +150,15 @@ gfx_pixmap_t *gfx_new_pixmap(int xl, int yl, int resid, int loop, int cel) { void gfx_free_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) { if (driver) { - if (driver->mode->palette && pxm->flags & GFX_PIXMAP_FLAG_PALETTE_ALLOCATED - && !(pxm->flags & GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE) && !(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) { - int i; - int error = 0; - - GFXDEBUG("UNALLOCATING %d\n", pxm->colors_nr); - for (i = 0; i < pxm->colors_nr; i++) - if (gfx_free_color(driver->mode->palette, pxm->colors + i)) - error++; - - if (error) { - GFXWARN("%d errors occured while freeing %d colors of pixmap with ID %06x/%d/%d\n", - error, pxm->colors_nr, pxm->ID, pxm->loop, pxm->cel); - } + if (driver->mode->palette) { + if (pxm->palette) + pxm->palette->free(); } } - if (pxm->index_data) - free(pxm->index_data); - - if (pxm->alpha_map) - free(pxm->alpha_map); - - if (pxm->data) - free(pxm->data); - - if (pxm->colors && !(pxm->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE)) - free(pxm->colors); - + free(pxm->index_data); + free(pxm->alpha_map); + free(pxm->data); free(pxm); } @@ -256,105 +228,6 @@ gfx_pixmap_t *gfx_pixmap_free_data(gfx_pixmap_t *pixmap) { return pixmap; } -int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color) { - int i; - int dr, dg, db; - int bestdelta = 1 + ((0x100 * 0x100) * 3); - int bestcolor = -1; - int firstfree = -1; - - if (pal == NULL) - return GFX_OK; - - if (pal->max_colors_nr <= 0) { - GFXERROR("Palette has zero or less color entries!\n"); - return GFX_ERROR; - } - - - if (color->global_index != GFX_COLOR_INDEX_UNMAPPED) { -#if 0 - GFXDEBUG("Attempt to allocate color twice: index 0x%d (%02x/%02x/%02x)!\n", - color->global_index, color->r, color->g, color->b); -#endif - return GFX_OK; - } - - for (i = 0; i < pal->max_colors_nr; i++) { - gfx_palette_color_t *pal_color = pal->colors + i; - - if (pal_color->lockers) { - int delta; - - dr = abs(pal_color->r - color->r); - dg = abs(pal_color->g - color->g); - db = abs(pal_color->b - color->b); - - if (dr == 0 && dg == 0 && db == 0) { - color->global_index = i; - if (pal->colors[i].lockers != GFX_COLOR_SYSTEM) - pal->colors[i].lockers++; - return GFX_OK; - } - - delta = (dr * dr) + (dg * dg) + (db * db); - if (delta < bestdelta) { - bestdelta = delta; - bestcolor = i; - } - } else - if (firstfree == -1) - firstfree = i; - } - - if (firstfree != -1) { - pal->colors[firstfree].r = color->r; - pal->colors[firstfree].g = color->g; - pal->colors[firstfree].b = color->b; - pal->colors[firstfree].lockers = 1; - color->global_index = firstfree; - - return 42; // positive value to indicate that this color still needs to be set - } - - color->global_index = bestcolor; - if (pal->colors[bestcolor].lockers != GFX_COLOR_SYSTEM) - pal->colors[bestcolor].lockers++; - - //GFXWARN("Out of palette colors- doing approximated mapping"); - return GFX_OK; -} - -int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color) { - gfx_palette_color_t *palette_color = pal->colors + color->global_index; - - if (!pal) - return GFX_OK; - - if (color->global_index == GFX_COLOR_INDEX_UNMAPPED) { - GFXWARN("Attempt to free unmapped color %02x/%02x/%02x!\n", color->r, color->g, color->b); - BREAKPOINT(); - return GFX_ERROR; - } - - if (color->global_index >= pal->max_colors_nr) { - GFXERROR("Attempt to free invalid color index %d (%02x/%02x/%02x)\n", color->global_index, color->r, color->g, color->b); - return GFX_ERROR; - } - - if (!palette_color->lockers) { - GFXERROR("Attempt to free unused color index %d (%02x/%02x/%02x)\n", color->global_index, color->r, color->g, color->b); - return GFX_ERROR; - } - - if (palette_color->lockers != GFX_COLOR_SYSTEM) - --(palette_color->lockers); - - color->global_index = GFX_COLOR_INDEX_UNMAPPED; - - return GFX_OK; -} - gfx_pixmap_t *gfx_pixmap_scale_index_data(gfx_pixmap_t *pixmap, gfx_mode_t *mode) { byte *old_data, *new_data, *initial_new_data; byte *linestart; diff --git a/engines/sci/gfx/gfx_tools.h b/engines/sci/gfx/gfx_tools.h index 63f4d441f4..451dfefc98 100644 --- a/engines/sci/gfx/gfx_tools.h +++ b/engines/sci/gfx/gfx_tools.h @@ -47,7 +47,7 @@ extern int gfx_crossblit_alpha_threshold; /* Crossblitting functions use this va ** for distinguishing between transparent and opaque ** wrt alpha values */ -gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, int palette, int flags); +gfx_mode_t *gfx_new_mode(int xfact, int yfact, const Graphics::PixelFormat &format, Palette *palette, int flags); /* Allocates a new gfx_mode_t structure with the specified parameters ** Parameters: (int x int) xfact x yfact: Horizontal and vertical scaling factors ** (Graphics::PixelFormat) format: pixel format description @@ -191,7 +191,7 @@ int gfx_crossblit_pixmap(gfx_mode_t *mode, gfx_pixmap_t *pxm, int priority, ** linear access. */ -int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color); +//int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color); /* Allocates a color entry for the specified pixmap color ** Parameters: (gfx_palette_t *) pal: The palette structure the color should be allocated in ** (gfx_pixmap_color_t *) color: The color to allocate @@ -200,7 +200,7 @@ int gfx_alloc_color(gfx_palette_t *pal, gfx_pixmap_color_t *color); ** palette. */ -int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color); +//int gfx_free_color(gfx_palette_t *pal, gfx_pixmap_color_t *color); /* Frees the color entry allocated for the specified pixmap color ** Parameters: (gfx_palette_t *) pal: The palette structure the color was previously allocated in ** (gfx_pixmap_color_t *) color: The color to free diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp index ad1eec7674..81c5c8a08e 100644 --- a/engines/sci/gfx/gfx_widgets.cpp +++ b/engines/sci/gfx/gfx_widgets.cpp @@ -867,10 +867,7 @@ gfxw_dyn_view_t *gfxw_new_dyn_view(gfx_state_t *state, Common::Point pos, int z, widget->color.priority = priority; widget->color.control = control; widget->color.alpha = 0; - widget->color.visual.global_index = 0; - widget->color.visual.r = 0; - widget->color.visual.g = 0; - widget->color.visual.b = 0; + widget->color.visual = PaletteEntry(0,0,0); // FIXME: black! widget->view = view; widget->loop = loop; widget->cel = cel; @@ -2042,7 +2039,7 @@ gfxw_dyn_view_t *gfxw_picviewize_dynview(gfxw_dyn_view_t *dynview) { gfxw_port_t *gfxw_get_chrono_port(gfxw_visual_t *visual, gfxw_list_t **temp_widgets_list, int flags) { gfxw_port_t *result = NULL; - gfx_color_t transparent = {{-1, 0, 0, 01}, 0, -1, -1, 0}; + gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0}; int id = 0; if (!(flags & GFXW_CHRONO_NON_TOPMOST)) { diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index d6274648cd..5911abff5d 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -96,29 +96,6 @@ static void _gfxop_scale_point(Common::Point *point, gfx_mode_t *mode) { point->y *= yfact; } -static void _gfxop_alloc_colors(gfx_state_t *state, gfx_pixmap_color_t *colors, int colors_nr) { - int i; - - if (!PALETTE_MODE) - return; - - for (i = 0; i < colors_nr; i++) - gfx_alloc_color(state->driver->mode->palette, colors + i); -} - -#if 0 -// Unreferenced - removed -static void _gfxop_free_colors(gfx_state_t *state, gfx_pixmap_color_t *colors, int colors_nr) { - int i; - - if (!PALETTE_MODE) - return; - - for (i = 0; i < colors_nr; i++) - gfx_free_color(state->driver->mode->palette, colors + i); -} -#endif - int _gfxop_clip(rect_t *rect, rect_t clipzone) { // Returns 1 if nothing is left */ #if 0 @@ -225,25 +202,22 @@ DRAW_LOOP(map->index_data[offset] < color) // Draw only lower priority #undef DRAW_LOOP static int _gfxop_install_pixmap(gfx_driver_t *driver, gfx_pixmap_t *pxm) { - int error; - - if (driver->mode->palette && (!(pxm->flags & GFX_PIXMAP_FLAG_PALETTE_SET))) { - int i; - - for (i = 0; i < pxm->colors_nr; i++) { - if ((error = driver->set_palette(driver, pxm->colors[i].global_index, pxm->colors[i].r, - pxm->colors[i].g, pxm->colors[i].b))) { + if (!driver->mode->palette) return GFX_OK; + if (!pxm->palette) return GFX_OK; + + assert(pxm->palette->getParent() == driver->mode->palette); - GFXWARN("driver->set_palette(%d, %02x/%02x/%02x) failed!\n", - pxm->colors[i].global_index, pxm->colors[i].r, pxm->colors[i].g, pxm->colors[i].b); + if (!driver->mode->palette->isDirty()) return GFX_OK; - if (error == GFX_FATAL) - return GFX_FATAL; - } - } - - pxm->flags |= GFX_PIXMAP_FLAG_PALETTE_SET; + // TODO: We probably want to only update the colours used by this pixmap + // here. This will require updating the 'dirty' system. + for (unsigned int i = 0; i < driver->mode->palette->size(); ++i) { + const PaletteEntry& c = (*driver->mode->palette)[i]; + driver->set_palette(driver, i, c.r, c.g, c.b); } + + driver->install_palette(driver, driver->mode->palette); + driver->mode->palette->markClean(); return GFX_OK; } @@ -438,12 +412,13 @@ static int _gfxop_clear_dirty_rec(gfx_state_t *state, gfx_dirty_rect_t *rect) { static void init_aux_pixmap(gfx_pixmap_t **pixmap) { *pixmap = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320, 200, GFX_RESID_NONE, 0, 0)); - (*pixmap)->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; - (*pixmap)->colors_nr = DEFAULT_COLORS_NR; - (*pixmap)->colors = default_colors; + // FIXME: don't duplicate this palette for every aux_pixmap + (*pixmap)->palette = new Palette(default_colors, DEFAULT_COLORS_NR); } static int _gfxop_init_common(gfx_state_t *state, gfx_options_t *options, void *misc_payload) { + gfxr_init_static_palette(); + state->options = options; if (!((state->resstate = gfxr_new_resource_manager(state->version, state->options, state->driver, misc_payload)))) { @@ -451,9 +426,8 @@ static int _gfxop_init_common(gfx_state_t *state, gfx_options_t *options, void * return GFX_FATAL; } - if ((state->static_palette = gfxr_interpreter_get_static_palette(state->resstate, state->version, - &(state->static_palette_entries), misc_payload))) - _gfxop_alloc_colors(state, state->static_palette, state->static_palette_entries); + int size; + state->static_palette = gfxr_interpreter_get_static_palette(state->resstate, state->version, &size, misc_payload); state->visible_map = GFX_MASK_VISUAL; state->fullscreen_override = NULL; // No magical override @@ -622,8 +596,6 @@ int gfxop_set_clip_zone(gfx_state_t *state, rect_t zone) { } int gfxop_set_color(gfx_state_t *state, gfx_color_t *color, int r, int g, int b, int a, int priority, int control) { - gfx_pixmap_color_t pixmap_color = {0, 0, 0, 0}; - int error_code; int mask = ((r >= 0 && g >= 0 && b >= 0) ? GFX_MASK_VISUAL : 0) | ((priority >= 0) ? GFX_MASK_PRIORITY : 0) | ((control >= 0) ? GFX_MASK_CONTROL : 0); @@ -644,20 +616,7 @@ int gfxop_set_color(gfx_state_t *state, gfx_color_t *color, int r, int g, int b, color->alpha = a; if (PALETTE_MODE) { - pixmap_color.r = r; - pixmap_color.g = g; - pixmap_color.b = b; - pixmap_color.global_index = GFX_COLOR_INDEX_UNMAPPED; - if ((error_code = gfx_alloc_color(state->driver->mode->palette, &pixmap_color))) { - if (error_code < 0) { - GFXWARN("Could not get color entry for %02x/%02x/%02x\n", r, g, b); - return error_code; - } else if ((error_code = state->driver->set_palette(state->driver, pixmap_color.global_index, (byte) r, (byte) g, (byte) b))) { - GFXWARN("Graphics driver failed to set color index %d to (%02x/%02x/%02x)\n", pixmap_color.global_index, r, g, b); - return error_code; - } - } - color->visual.global_index = pixmap_color.global_index; + color->visual.parent_index = state->driver->mode->palette->findNearbyColor(r,g,b,true); } } @@ -674,52 +633,27 @@ int gfxop_set_color(gfx_state_t *state, gfx_color_t *colorOut, gfx_color_t &colo colorIn.priority, colorIn.control); } -int gfxop_set_system_color(gfx_state_t *state, gfx_color_t *color) { - gfx_palette_color_t *palette_colors; +int gfxop_set_system_color(gfx_state_t *state, unsigned int index, gfx_color_t *color) { BASIC_CHECKS(GFX_FATAL); if (!PALETTE_MODE) return GFX_OK; - if (color->visual.global_index < 0 || color->visual.global_index >= state->driver->mode->palette->max_colors_nr) { - GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.global_index); + if (index >= state->driver->mode->palette->size()) { + GFXERROR("Attempt to set invalid color index %02x as system color\n", color->visual.parent_index); return GFX_ERROR; } - palette_colors = state->driver->mode->palette->colors; - palette_colors[color->visual.global_index].lockers = GFX_COLOR_SYSTEM; + state->driver->mode->palette->makeSystemColor(index, color->visual); return GFX_OK; } int gfxop_free_color(gfx_state_t *state, gfx_color_t *color) { - gfx_palette_color_t *palette_color = 0; - gfx_pixmap_color_t pixmap_color = {0, 0, 0, 0}; - int error_code; - BASIC_CHECKS(GFX_FATAL); - - if (!PALETTE_MODE) - return GFX_OK; - - if (color->visual.global_index < 0 || color->visual.global_index >= state->driver->mode->palette->max_colors_nr) { - GFXERROR("Attempt to free invalid color index %02x\n", color->visual.global_index); - return GFX_ERROR; - } - - pixmap_color.global_index = color->visual.global_index; - palette_color = state->driver->mode->palette->colors + pixmap_color.global_index; - pixmap_color.r = palette_color->r; - pixmap_color.g = palette_color->g; - pixmap_color.b = palette_color->b; - - if ((error_code = gfx_free_color(state->driver->mode->palette, &pixmap_color))) { - GFXWARN("Failed to free color with color index %02x\n", color->visual.global_index); - return error_code; - } - - return GFX_OK; + // FIXME: implement. (And call in the appropriate places!) } + // Generic drawing operations static int line_check_bar(int *start, int *length, int clipstart, int cliplength) { @@ -950,7 +884,7 @@ int gfxop_draw_line(gfx_state_t *state, Common::Point start, Common::Point end, end.y += yfact >> 1; } - if (color.visual.global_index == GFX_COLOR_INDEX_UNMAPPED) + if (color.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED) gfxop_set_color(state, &color, color); return _gfxop_draw_line_clipped(state, start, end, color, line_mode, line_style); } @@ -1089,7 +1023,7 @@ int gfxop_draw_box(gfx_state_t *state, rect_t box, gfx_color_t color1, gfx_color if (shade_type == GFX_BOX_SHADE_FLAT) { color1.priority = 0; color1.control = 0; - if (color1.visual.global_index == GFX_COLOR_INDEX_UNMAPPED) + if (color1.visual.parent_index == GFX_COLOR_INDEX_UNMAPPED) gfxop_set_color(state, &color1, color1); return drv->draw_filled_rect(drv, new_box, color1, color1, GFX_SHADE_FLAT); } else { @@ -1098,8 +1032,10 @@ int gfxop_draw_box(gfx_state_t *state, rect_t box, gfx_color_t color1, gfx_color return GFX_ERROR; } - gfx_color_t draw_color1 = {{0, 0, 0, 0}, 0, 0, 0, 0}; - gfx_color_t draw_color2 = {{0, 0, 0, 0}, 0, 0, 0, 0}; + gfx_color_t draw_color1; // CHECKME + gfx_color_t draw_color2; + gfxop_set_color(state, &draw_color1, 0, 0, 0, 0, 0, 0); + gfxop_set_color(state, &draw_color2, 0, 0, 0, 0, 0, 0); draw_color1.mask = draw_color2.mask = color1.mask; draw_color1.priority = draw_color2.priority = color1.priority; @@ -1253,7 +1189,6 @@ int gfxop_disable_dirty_frames(gfx_state_t *state) { // Pointer and IO ops - int gfxop_sleep(gfx_state_t *state, uint32 msecs) { BASIC_CHECKS(GFX_FATAL); @@ -2175,8 +2110,6 @@ gfx_pixmap_t *gfxop_grab_pixmap(gfx_state_t *state, rect_t area) { if (_gfxop_grab_pixmap(state, &pixmap, area.x, area.y, area.xl, area.yl, 0, &resultzone)) return NULL; // area CUT the visual screen had a null or negative size - pixmap->flags |= GFX_PIXMAP_FLAG_PALETTE_SET | GFX_PIXMAP_FLAG_DONT_UNALLOCATE_PALETTE; - return pixmap; } diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index b2edb9a022..efcf1f2dc0 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -102,8 +102,7 @@ struct gfx_state_t { rect_t clip_zone; /* The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */ gfx_driver_t *driver; - gfx_pixmap_color_t *static_palette; /* Null for dynamic palettes */ - int static_palette_entries; + Palette *static_palette; /* Null for dynamic palettes */ int visible_map; @@ -335,9 +334,10 @@ int gfxop_set_color(gfx_state_t *state, gfx_color_t *color, int r, int g, int b, ** free that color. */ -int gfxop_set_system_color(gfx_state_t *state, gfx_color_t *color); +int gfxop_set_system_color(gfx_state_t *state, unsigned int index, gfx_color_t *color); /* Designates a color as a 'system color' ** Parameters: (gfx_state_t *) state: The affected state +** (unsigned int) index: The index for the new system color ** (gfx_color_t *) color: The color to designate as a system color ** Returns : (int) GFX_OK or GFX_ERROR if state is invalid ** System colors are permanent colors that cannot be deallocated. As such, they must be used diff --git a/engines/sci/gfx/palette.cpp b/engines/sci/gfx/palette.cpp new file mode 100644 index 0000000000..f7beb3f474 --- /dev/null +++ b/engines/sci/gfx/palette.cpp @@ -0,0 +1,265 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "sci/gfx/palette.h" +#include "sci/gfx/gfx_system.h" + +// #define DEBUG_MERGE + +namespace Sci { + +Palette::Palette(unsigned int s) { + _size = s; + _colors = new PaletteEntry[s]; + _parent = 0; + _dirty = true; + _refcount = 1; +} + +Palette::Palette(gfx_pixmap_color_t* colors, unsigned int s) +{ + _size = s; + _colors = new PaletteEntry[s]; + _parent = 0; + _dirty = true; + _refcount = 1; + + for (unsigned int i = 0; i < _size; ++i) + setColor(i, colors[i].r, colors[i].g, colors[i].b); +} + +Palette::~Palette() { + if (_parent) + unmerge(); + + delete[] _colors; + _colors = 0; +} + +Palette* Palette::getref() { + _refcount++; + return this; +} + +void Palette::free() { + assert(_refcount > 0); + _refcount--; + + if (_refcount == 0) + delete this; +} + +void Palette::resize(unsigned int s) { + if (s == _size) return; + assert(!_parent); + assert(_refcount == 1); + assert(s >= _size); + + PaletteEntry *n = new PaletteEntry[s]; + for (unsigned int i = 0; i < _size; ++i) + n[i] = _colors[i]; + + delete[] _colors; + _colors = n; + _size = s; +} + +void Palette::unmerge() { + assert(_parent); +#ifdef DEBUG_MERGE + fprintf(stderr, "Unmerge %s from %s (%d colors)\n", name.c_str(), _parent->name.c_str(), _size); +#endif + + int count = 0; + for (unsigned int i = 0; i < _size; ++i) { + if (_colors[i].refcount == PALENTRY_FREE) continue; + int pi = _colors[i].parent_index; + assert(pi >= 0); + assert(pi < (int)_parent->_size); + assert(_parent->_colors[pi].refcount != 0); + assert(_parent->_colors[pi].refcount != PALENTRY_FREE); + int old = _parent->_colors[pi].refcount; + if (_parent->_colors[pi].refcount != PALENTRY_LOCKED) + _parent->_colors[pi].refcount--; + if (_parent->_colors[pi].refcount == 0) { + _parent->_colors[pi].refcount = PALENTRY_FREE; + count++; + } +#ifdef DEBUG_MERGE + fprintf(stderr, "%d: %d -> %d\n", pi, old, _parent->_colors[pi].refcount); +#endif + _colors[i].parent_index = -1; + } +#ifdef DEBUG_MERGE + fprintf(stderr, "Unmerge free %d colors\n", count); +#endif + + _parent = 0; +} + +void Palette::setColor(unsigned int index, byte r, byte g, byte b) { + assert(index < _size); + assert(!_parent); + +// FIXME: We may want to have this assert. This will require changing the +// way loops sharing a single view's palette works. +// assert(_refcount == 1); + + PaletteEntry& entry = _colors[index]; + + assert(entry.refcount == PALENTRY_FREE || entry.refcount == 0); + entry.refcount = 0; + entry.r = r; + entry.g = g; + entry.b = b; + entry.parent_index = -1; + + _dirty = true; +} + +void Palette::makeSystemColor(unsigned int index, const PaletteEntry& color) { + assert(index < _size); + PaletteEntry& entry = _colors[index]; + entry.r = color.r; + entry.g = color.g; + entry.b = color.b; + entry.refcount = PALENTRY_LOCKED; +} + +unsigned int Palette::findNearbyColor(byte r, byte g, byte b, bool lock) { + int bestdelta = 1 + ((0x100 * 0x100) * 3); + int bestcolor = -1; + int firstfree = -1; + + assert(_size != 0); + + for (unsigned int i = 0; i < _size; ++i) { + PaletteEntry& entry = _colors[i]; + + if (entry.refcount != PALENTRY_FREE) { + int dr = abs(entry.r - r); + int dg = abs(entry.g - g); + int db = abs(entry.b - b); + + if (dr == 0 && dg == 0 && db == 0) { + // Exact match + //exact = true; + if (lock && entry.refcount != PALENTRY_LOCKED) + entry.refcount++; + return i; + } + + int delta = (dr * dr) + (dg * dg) + (db * db); + if (delta < bestdelta) { + bestdelta = delta; + bestcolor = i; + } + } else { + if (firstfree == -1) + firstfree = i; + } + } + + if (firstfree != -1) { + // TODO: mark palette as dirty + setColor(firstfree, r, g, b); + //exact = true; + if (lock) + _colors[firstfree].refcount++; + return firstfree; + } + + //exact = false; + if (lock && _colors[bestcolor].refcount != PALENTRY_LOCKED) { +#if 0 + _colors[bestcolor].r = r; + _colors[bestcolor].g = g; + _colors[bestcolor].b = b; + _dirty = true; +#endif + _colors[bestcolor].refcount++; + } + return bestcolor; +} + +void Palette::mergeInto(Palette *parent) { + assert(!_parent || _parent == parent); + assert(parent != this); +#ifdef DEBUG_MERGE + fprintf(stderr, "Merge: %s into %s (%d colors)\n", name.c_str(), parent->name.c_str(), _size); +#endif + + if (_parent == parent) { +#ifdef DEBUG_MERGE + fprintf(stderr, "NOP\n"); +#endif + return; + } + _parent = parent; + +#ifdef DEBUG_MERGE + bool *used = new bool[_parent->size()]; + for (unsigned int i = 0; i < _parent->size(); ++i) + used[i] = false; + int count = 0; + int used_min = 1000; + int used_max = 0; +#endif + + for (unsigned int i = 0; i < _size; ++i) { + PaletteEntry& entry = _colors[i]; + if (entry.refcount == PALENTRY_FREE) continue; + + unsigned int pi = _parent->findNearbyColor(entry.r, entry.g, entry.b); +#ifdef DEBUG_MERGE + if (!used[pi]) count++; + used[pi] = true; + if (pi > used_max) used_max = pi; + if (pi < used_min) used_min = pi; +#endif + entry.parent_index = pi; + if (_parent->_colors[pi].refcount != PALENTRY_LOCKED) + _parent->_colors[pi].refcount++; + } +#ifdef DEBUG_MERGE + fprintf(stderr, "Merge used %d colours in [%d..%d]\n", count, used_min, used_max); + delete[] used; +#endif +} + +Palette* Palette::copy() { + assert(!_parent); + Palette* p = new Palette(_size); + p->name = "copy of " + name; + + for (unsigned int i = 0; i < _size; ++i) { + p->_colors[i] = _colors[i]; + p->_colors[i].refcount = 0; + } + return p; +} + + +} // End of namespace Sci diff --git a/engines/sci/gfx/palette.h b/engines/sci/gfx/palette.h new file mode 100644 index 0000000000..19b21fed89 --- /dev/null +++ b/engines/sci/gfx/palette.h @@ -0,0 +1,107 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_GFX_PALETTE_H +#define SCI_GFX_PALETTE_H + +#include "common/scummsys.h" +#include "common/str.h" + +namespace Sci { + +const int PALENTRY_LOCKED = -42; +const int PALENTRY_FREE = -41; + +struct PaletteEntry { + PaletteEntry() + : r(0), g(0), b(0), parent_index(-1), refcount(PALENTRY_FREE) + { } + PaletteEntry(byte R, byte G, byte B) + : r(R), g(G), b(B), parent_index(-1), refcount(PALENTRY_FREE) + { } + + // Color data + byte r, g, b; + + // Index in parent palette, or -1 + int parent_index; + + // Number of references from child palettes. (This includes palettes + // of pixmaps.) + // Special values: PALENTRY_LOCKED, PALENTRY_FREE + int refcount; +}; + +struct gfx_pixmap_color_t; + +class Palette { +public: + explicit Palette(unsigned int size); + Palette(gfx_pixmap_color_t* colors, unsigned int size); + ~Palette(); + + Palette* getref(); + void free(); + Palette* copy(); + + void resize(unsigned int size); + void setColor(unsigned int index, byte r, byte g, byte b); + void makeSystemColor(unsigned int index, const PaletteEntry& color); + const PaletteEntry& getColor(unsigned int index) const { + assert(index < _size); + return _colors[index]; + } + const PaletteEntry& operator[](unsigned int index) const { + return getColor(index); + } + unsigned int size() const { return _size; } + bool isDirty() const { return _dirty; } + bool isShared() const { return _refcount > 1; } + Palette* getParent() { return _parent; } + + void markClean() { _dirty = false; } + + unsigned int findNearbyColor(byte r, byte g, byte b, bool lock=false); + + void mergeInto(Palette *parent); + void unmerge(); + + Common::String name; // strictly for debugging purposes +private: + PaletteEntry *_colors; + unsigned int _size; + + Palette *_parent; + + bool _dirty; // Palette has changed + int _refcount; // Number of pixmaps (or other objects) using this palette +}; + + + + +} // End of namespace Sci + +#endif // SCI_GFX_PALETTE_H diff --git a/engines/sci/gfx/resmgr.cpp b/engines/sci/gfx/resmgr.cpp index 1737c2e6fa..45ec5adfbb 100644 --- a/engines/sci/gfx/resmgr.cpp +++ b/engines/sci/gfx/resmgr.cpp @@ -58,6 +58,7 @@ gfx_resstate_t *gfxr_new_resource_manager(int version, gfx_options_t *options, g state->options = options; state->driver = driver; state->misc_payload = misc_payload; + state->static_palette = 0; state->tag_lock_counter = state->lock_counter = 0; for (ii = 0; ii < GFX_RESOURCE_TYPES_NR; ii++) { diff --git a/engines/sci/gfx/resource/sci_pal_1.cpp b/engines/sci/gfx/resource/sci_pal_1.cpp index c448550655..74fb8629b7 100644 --- a/engines/sci/gfx/resource/sci_pal_1.cpp +++ b/engines/sci/gfx/resource/sci_pal_1.cpp @@ -39,13 +39,13 @@ namespace Sci { #define SCI_PAL_FORMAT_VARIABLE_FLAGS 0 #define SCI_PAL_FORMAT_CONSTANT_FLAGS 1 -gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int size) { +Palette *gfxr_read_pal11(int id, byte *resource, int size) { int start_color = resource[25]; int format = resource[32]; int entry_size = 0; - gfx_pixmap_color_t *retval; + Palette *retval; byte *pal_data = resource + 37; - int _colors_nr = *colors_nr = READ_LE_UINT16(resource + 29); + int _colors_nr = READ_LE_UINT16(resource + 29); int i; switch (format) { @@ -57,28 +57,21 @@ gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int break; } - retval = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color)); - memset(retval, 0, sizeof(gfx_pixmap_color_t) * (_colors_nr + start_color)); + retval = new Palette(_colors_nr + start_color); + char buf[100]; + sprintf(buf, "read_pal11 (id %d)", id); + retval->name = buf; for (i = 0; i < start_color; i ++) { - retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED; - retval[i].r = 0; - retval[i].g = 0; - retval[i].b = 0; + retval->setColor(i, 0, 0, 0); } for (i = start_color; i < start_color + _colors_nr; i ++) { switch (format) { case SCI_PAL_FORMAT_CONSTANT_FLAGS: - retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED; - retval[i].r = pal_data[0]; - retval[i].g = pal_data[1]; - retval[i].b = pal_data[2]; + retval->setColor(i, pal_data[0], pal_data[1], pal_data[2]); break; case SCI_PAL_FORMAT_VARIABLE_FLAGS: - retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED; - retval[i].r = pal_data[1]; - retval[i].g = pal_data[2]; - retval[i].b = pal_data[3]; + retval->setColor(i, pal_data[1], pal_data[2], pal_data[3]); break; } pal_data += entry_size; @@ -87,11 +80,10 @@ gfx_pixmap_color_t *gfxr_read_pal11(int id, int *colors_nr, byte *resource, int return retval; } -gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int size) { +Palette *gfxr_read_pal1(int id, byte *resource, int size) { int counter = 0; int pos; unsigned int colors[MAX_COLORS] = {0}; - gfx_pixmap_color_t *retval; if (size < PALETTE_START + 4) { GFXERROR("Palette resource too small in %04x\n", id); @@ -118,26 +110,22 @@ gfx_pixmap_color_t *gfxr_read_pal1(int id, int *colors_nr, byte *resource, int s return NULL; } - retval = (gfx_pixmap_color_t*)sci_malloc(sizeof(gfx_pixmap_color_t) * counter); + Palette *retval = new Palette(counter); + char buf[100]; + sprintf(buf, "read_pal1 (id %d)", id); + retval->name = buf; - *colors_nr = counter; for (pos = 0; pos < counter; pos++) { unsigned int color = colors[pos]; - - retval[pos].global_index = GFX_COLOR_INDEX_UNMAPPED; - retval[pos].r = (color >> 8) & 0xff; - retval[pos].g = (color >> 16) & 0xff; - retval[pos].b = (color >> 24) & 0xff; + retval->setColor(pos, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); } return retval; } -gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file) { +Palette *gfxr_read_pal1_amiga(Common::File &file) { int i; - gfx_pixmap_color_t *retval; - - retval = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * 32); + Palette *retval = new Palette(32); for (i = 0; i < 32; i++) { int b1, b2; @@ -150,14 +138,9 @@ gfx_pixmap_color_t *gfxr_read_pal1_amiga(int *colors_nr, Common::File &file) { return NULL; } - retval[i].global_index = GFX_COLOR_INDEX_UNMAPPED; - retval[i].r = (b1 & 0xf) * 0x11; - retval[i].g = ((b2 & 0xf0) >> 4) * 0x11; - retval[i].b = (b2 & 0xf) * 0x11; + retval->setColor(i, (b1 & 0xf) * 0x11, ((b2 & 0xf0) >> 4) * 0x11, (b2 & 0xf) * 0x11); } - *colors_nr = 32; - return retval; } diff --git a/engines/sci/gfx/resource/sci_pic_0.cpp b/engines/sci/gfx/resource/sci_pic_0.cpp index f4f0027b3d..b91ad8ff05 100644 --- a/engines/sci/gfx/resource/sci_pic_0.cpp +++ b/engines/sci/gfx/resource/sci_pic_0.cpp @@ -99,9 +99,9 @@ gfx_pixmap_color_t gfx_sci0_image_colors[SCI0_MAX_PALETTE+1][GFX_SCI0_IMAGE_COLO #undef C3 #undef C4 -gfx_pixmap_color_t gfx_sci0_pic_colors[GFX_SCI0_PIC_COLORS_NR]; // Initialized during initialization - -static int _gfxr_pic0_colors_initialized = 0; +Palette* gfx_sci0_pic_colors = 0; // Initialized during initialization +Palette* gfx_sci0_image_pal[SCI0_MAX_PALETTE+1]; +Palette* embedded_view_pal = 0; #define SCI1_PALETTE_SIZE 1284 @@ -121,18 +121,28 @@ gfx_pixmap_color_t embedded_view_colors[16] = { }; void gfxr_init_static_palette() { - if (!_gfxr_pic0_colors_initialized) { + if (!gfx_sci0_pic_colors) { + gfx_sci0_pic_colors = new Palette(256); + gfx_sci0_pic_colors->name = "gfx_sci0_pic_colors"; for (int i = 0; i < 256; i++) { - gfx_sci0_pic_colors[i].global_index = GFX_COLOR_INDEX_UNMAPPED; - gfx_sci0_pic_colors[i].r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r, - gfx_sci0_image_colors[sci0_palette][i >> 4].r); - gfx_sci0_pic_colors[i].g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g, - gfx_sci0_image_colors[sci0_palette][i >> 4].g); - gfx_sci0_pic_colors[i].b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b, - gfx_sci0_image_colors[sci0_palette][i >> 4].b); + byte r = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].r, + gfx_sci0_image_colors[sci0_palette][i >> 4].r); + byte g = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].g, + gfx_sci0_image_colors[sci0_palette][i >> 4].g); + byte b = INTERCOL(gfx_sci0_image_colors[sci0_palette][i & 0xf].b, + gfx_sci0_image_colors[sci0_palette][i >> 4].b); + gfx_sci0_pic_colors->setColor(i,r,g,b); } //warning("Uncomment me after fixing sci0_palette changes to reset me"); //_gfxr_pic0_colors_initialized = 1; + + for (int i = 0; i <= SCI0_MAX_PALETTE; ++i) { + gfx_sci0_image_pal[i] = new Palette(gfx_sci0_image_colors[i], GFX_SCI0_IMAGE_COLORS_NR); + gfx_sci0_image_pal[i]->name = "gfx_sci0_image_pal[i]"; + } + + embedded_view_pal = new Palette(embedded_view_colors, 16); + embedded_view_pal->name = "embedded_view_pal"; } } @@ -150,28 +160,26 @@ gfxr_pic_t *gfxr_init_pic(gfx_mode_t *mode, int ID, int sci1) { pic->visual_map = gfx_pixmap_alloc_index_data(gfx_new_pixmap(320 * mode->xfact, 200 * mode->yfact, ID, 0, 0)); - pic->visual_map->colors = gfx_sci0_pic_colors; - pic->visual_map->colors_nr = GFX_SCI0_PIC_COLORS_NR; + + // Initialize colors + if (!sci1) { + pic->ID = ID; + gfxr_init_static_palette(); + } + + pic->visual_map->palette = gfx_sci0_pic_colors->getref(); pic->visual_map->color_key = GFX_PIXMAP_COLOR_KEY_NONE; - pic->visual_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; - pic->priority_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; - pic->control_map->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + pic->visual_map->flags = 0; + pic->priority_map->flags = 0; + pic->control_map->flags = 0; if (mode->xfact > 1 || mode->yfact > 1) { pic->visual_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX; pic->priority_map->flags |= GFX_PIXMAP_FLAG_SCALED_INDEX; } - pic->priority_map->colors = gfx_sci0_image_colors[sci0_palette]; - pic->priority_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR; - pic->control_map->colors = gfx_sci0_image_colors[sci0_palette]; - pic->control_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR; - - // Initialize colors - if (!sci1) { - pic->ID = ID; - gfxr_init_static_palette(); - } + pic->priority_map->palette = gfx_sci0_image_pal[sci0_palette]->getref(); + pic->control_map->palette = gfx_sci0_image_pal[sci0_palette]->getref(); pic->undithered_buffer_size = pic->visual_map->index_xl * pic->visual_map->index_yl; pic->undithered_buffer = NULL; @@ -1257,14 +1265,18 @@ void gfxr_remove_artifacts_pic0(gfxr_pic_t *dest, gfxr_pic_t *src) { } -static void view_transparentize(gfx_pixmap_t *view, byte *pic_index_data, int posx, int posy, int width, int height) { +static void view_transparentize(gfx_pixmap_t *view, gfx_pixmap_t *background, int posx, int posy, int width, int height) { int i, j; + byte *pic_index_data = background->index_data; + + // FIXME: this assumes view and background have the same palette... + // We may want to do a reverse mapping or similar to make it general, + // but this (hopefully...) suffices for the current uses of this function. for (i = 0;i < width;i++) for (j = 0;j < height;j++) { if (view->index_data[j*width+i] == view->color_key) { - view->index_data[j*width+i] = - pic_index_data[(j+posy)*width+i+posx]; + view->index_data[j*width+i] = pic_index_data[(j+posy)*width+i+posx]; } } } @@ -1274,7 +1286,7 @@ extern gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byt extern void _gfx_crossblit_simple(byte *dest, byte *src, int dest_line_width, int src_line_width, int xl, int yl, int bpp); void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource, - gfxr_pic0_params_t *style, int resid, int sci1, gfx_pixmap_color_t *static_pal, int static_pal_nr) { + gfxr_pic0_params_t *style, int resid, int sci1, Palette *static_pal) { const int default_palette_table[GFXR_PIC0_PALETTE_SIZE] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x88, @@ -1610,8 +1622,9 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, case PIC_SCI1_OPX_SET_PALETTE: p0printf("Set palette @%d\n", pos); - pic->visual_map->flags &= ~GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; - pic->visual_map->colors = gfxr_read_pal1(resid, &pic->visual_map->colors_nr, + if (pic->visual_map->palette) + pic->visual_map->palette->free(); + pic->visual_map->palette = gfxr_read_pal1(resid, resource + pos, SCI1_PALETTE_SIZE); pos += SCI1_PALETTE_SIZE; goto end_op_loop; @@ -1640,17 +1653,9 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, int nodraw = 0; gfx_pixmap_t *view; - //gfx_mode_t *mode; p0printf("Embedded view @%d\n", pos); -#if 0 - // Set up mode structure for resizing the view - Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1bpp, which handles masks and the rest for us - mode = gfx_new_mode(pic->visual_map->index_xl / 320, - pic->visual_map->index_yl / 200, format, 16, 0); -#endif - GET_ABS_COORDS(posx, posy); bytesize = (*(resource + pos)) + (*(resource + pos + 1) << 8); p0printf("(%d, %d)\n", posx, posy); @@ -1658,7 +1663,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, if (!sci1 && !nodraw) view = gfxr_draw_cel0(-1, -1, -1, resource + pos, bytesize, NULL, 0); else - view = gfxr_draw_cel1(-1, -1, -1, 0, resource + pos, bytesize, NULL, static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR); + view = gfxr_draw_cel1(-1, -1, -1, 0, resource + pos, bytesize, NULL, (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR)); pos += bytesize; if (nodraw) continue; @@ -1667,7 +1672,7 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, // we can only safely replace the palette if it's static // *if it's not for some reason, we should die - if (!(view->flags & GFX_PIXMAP_FLAG_EXTERNAL_PALETTE) && !sci1) { + if (view->palette && view->palette->isShared() && !sci1) { sciprintf("gfx_draw_pic0(): can't set a non-static palette for an embedded view!\n"); } @@ -1675,40 +1680,36 @@ void gfxr_draw_pic01(gfxr_pic_t *pic, int flags, int default_palette, int size, // nibble of the color index to the high nibble. if (sci1) { - if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) { + if (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR) { // Assume Amiga game - pic->visual_map->colors = static_pal; - pic->visual_map->colors_nr = static_pal_nr; - pic->visual_map->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + pic->visual_map->palette = static_pal->getref(); } - view->colors = pic->visual_map->colors; - view->colors_nr = pic->visual_map->colors_nr; + if (view->palette) view->palette->free(); + view->palette = pic->visual_map->palette->copy(); } else - view->colors = embedded_view_colors; + view->palette = embedded_view_pal->getref(); // Hack to prevent overflowing the visual map buffer. // Yes, this does happen otherwise. if (view->index_yl + sci_titlebar_size > 200) sci_titlebar_size = 0; -#if 0 - // FIXME: This doesn't just scale the image, but also - // tries to fit the colours into the palette in 'mode', - // breaking colours in e.g., KQ5 floppy. + // Set up mode structure for resizing the view + Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1byte/p, which handles masks and the rest for us + gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_xl / 320, + pic->visual_map->index_yl / 200, format, view->palette, 0); + gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE); -#endif + gfx_free_mode(mode); if (flags & DRAWPIC01_FLAG_OVERLAID_PIC) - view_transparentize(view, pic->visual_map->index_data, posx, sci_titlebar_size + posy, + view_transparentize(view, pic->visual_map, posx, sci_titlebar_size + posy, view->index_xl, view->index_yl); _gfx_crossblit_simple(pic->visual_map->index_data + (sci_titlebar_size * 320) + posy * 320 + posx, view->index_data, pic->visual_map->index_xl, view->index_xl, view->index_xl, view->index_yl, 1); -#if 0 - gfx_free_mode(mode); -#endif gfx_free_pixmap(NULL, view); } goto end_op_loop; @@ -1777,36 +1778,32 @@ end_op_loop: {} } void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size, byte *resource, - gfxr_pic0_params_t *style, int resid, gfx_pixmap_color_t *static_pal, int static_pal_nr) { + gfxr_pic0_params_t *style, int resid, Palette *static_pal) { int has_bitmap = READ_LE_UINT16(resource + 4); int vector_data_ptr = READ_LE_UINT16(resource + 16); int palette_data_ptr = READ_LE_UINT16(resource + 28); int bitmap_data_ptr = READ_LE_UINT16(resource + 32); int sci_titlebar_size = style->pic_port_bounds.y; - //gfx_mode_t *mode; gfx_pixmap_t *view = NULL; -#if 0 - // Set up mode structure for resizing the view - Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1bpp, which handles masks and the rest for us - mode = gfx_new_mode(pic->visual_map->index_xl / 320, pic->visual_map->index_yl / 200, - format, 16, 0); -#endif - pic->visual_map->colors = gfxr_read_pal11(-1, &(pic->visual_map->colors_nr), resource + palette_data_ptr, 1284); + if (pic->visual_map->palette) pic->visual_map->palette->free(); + pic->visual_map->palette = gfxr_read_pal11(-1, resource + palette_data_ptr, 1284); if (has_bitmap) view = gfxr_draw_cel11(-1, 0, 0, 0, resource, resource + bitmap_data_ptr, size - bitmap_data_ptr, NULL); if (view) { - view->colors = pic->visual_map->colors; - view->colors_nr = pic->visual_map->colors_nr; + view->palette = pic->visual_map->palette->getref(); + + // Set up mode structure for resizing the view + Graphics::PixelFormat format = { 1, 0, 0, 0, 0, 0, 0, 0, 0 }; // 1 byte/p, which handles masks and the rest for us + gfx_mode_t *mode = gfx_new_mode(pic->visual_map->index_xl / 320, pic->visual_map->index_yl / 200, format, view->palette, 0); -#if 0 gfx_xlate_pixmap(view, mode, GFX_XLATE_FILTER_NONE); -#endif + gfx_free_mode(mode); if (flags & DRAWPIC01_FLAG_OVERLAID_PIC) - view_transparentize(view, pic->visual_map->index_data, 0, 0, view->index_xl, view->index_yl); + view_transparentize(view, pic->visual_map, 0, 0, view->index_xl, view->index_yl); // Hack to prevent overflowing the visual map buffer. // Yes, this does happen otherwise. @@ -1823,8 +1820,7 @@ void gfxr_draw_pic11(gfxr_pic_t *pic, int flags, int default_palette, int size, GFXWARN("No view was contained in SCI1.1 pic resource"); } - gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr, resource + vector_data_ptr, style, resid, 1, - static_pal, static_pal_nr); + gfxr_draw_pic01(pic, flags, default_palette, size - vector_data_ptr, resource + vector_data_ptr, style, resid, 1, static_pal); } void gfxr_dither_pic0(gfxr_pic_t *pic, int dmode, int pattern) { @@ -1841,8 +1837,7 @@ void gfxr_dither_pic0(gfxr_pic_t *pic, int dmode, int pattern) { return; // Nothing to do if (dmode == GFXR_DITHER_MODE_D16) { // Limit to 16 colors - pic->visual_map->colors = gfx_sci0_image_colors[sci0_palette]; - pic->visual_map->colors_nr = GFX_SCI0_IMAGE_COLORS_NR; + pic->visual_map->palette = gfx_sci0_image_pal[sci0_palette]->getref(); } for (y = 0; y < yl; y++) { diff --git a/engines/sci/gfx/resource/sci_resmgr.cpp b/engines/sci/gfx/resource/sci_resmgr.cpp index 97ecfb3d1d..c3646eb6b4 100644 --- a/engines/sci/gfx/resource/sci_resmgr.cpp +++ b/engines/sci/gfx/resource/sci_resmgr.cpp @@ -101,31 +101,25 @@ int gfxr_interpreter_calculate_pic(gfx_resstate_t *state, gfxr_pic_t *scaled_pic if (state->version >= SCI_VERSION_01_VGA) { if (need_unscaled) { if (state->version == SCI_VERSION_1_1) - gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic11(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, state->static_palette); else - gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 1, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 1, state->static_palette); } if (scaled_pic && scaled_pic->undithered_buffer) memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size); if (state->version == SCI_VERSION_1_1) - gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic11(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->static_palette); else - gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->version, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, state->version, state->static_palette); } else { if (need_unscaled) - gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 0, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic01(unscaled_pic, flags, default_palette, res->size, res->data, &basic_style, res->id, 0, state->static_palette); if (scaled_pic && scaled_pic->undithered_buffer) memcpy(scaled_pic->visual_map->index_data, scaled_pic->undithered_buffer, scaled_pic->undithered_buffer_size); - gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, 0, - state->static_palette, state->static_palette_entries); + gfxr_draw_pic01(scaled_pic, flags, default_palette, res->size, res->data, &style, res->id, 0, state->static_palette); if (need_unscaled) gfxr_remove_artifacts_pic0(scaled_pic, unscaled_pic); @@ -147,12 +141,12 @@ int gfxr_interpreter_calculate_pic(gfx_resstate_t *state, gfxr_pic_t *scaled_pic return GFX_OK; } -void gfxr_palettize_view(gfxr_view_t *view, gfx_pixmap_color_t *source, int source_entries) { - int i; - - for (i = 0;i < MIN(view->colors_nr, source_entries);i++) { - if ((view->colors[i].r == 0) && (view->colors[i].g == 0) && (view->colors[i].b == 0)) { - view->colors[i] = source[i]; +void gfxr_palettize_view(gfxr_view_t *view, Palette *source) { + for (unsigned i = 0; i < MIN(view->palette->size(), source->size()); i++) { + const PaletteEntry& vc = view->palette->getColor(i); + if (vc.r == 0 && vc.g == 0 && vc.b == 0) { + const PaletteEntry& sc = source->getColor(i); + view->palette->setColor(i, sc.r, sc.g, sc.b); } } } @@ -179,7 +173,7 @@ gfxr_view_t *gfxr_interpreter_get_view(gfx_resstate_t *state, int nr, void *inte case SCI_VERSION_01_VGA_ODD: case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: - result = gfxr_draw_view1(resid, res->data, res->size, state->static_palette, state->static_palette_entries); + result = gfxr_draw_view1(resid, res->data, res->size, state->static_palette); break; case SCI_VERSION_1_1: case SCI_VERSION_32: @@ -188,12 +182,11 @@ gfxr_view_t *gfxr_interpreter_get_view(gfx_resstate_t *state, int nr, void *inte } if (state->version >= SCI_VERSION_01_VGA) { - if (!result->colors) { - result->colors = (gfx_pixmap_color_t *)sci_malloc(sizeof(gfx_pixmap_color_t) * state->static_palette_entries); - memset(result->colors, 0, sizeof(gfx_pixmap_color_t) * state->static_palette_entries); - result->colors_nr = state->static_palette_entries; + if (!result->palette) { + result->palette = new Palette(state->static_palette->size()); + result->palette->name = "interpreter_get_view"; } - gfxr_palettize_view(result, state->static_palette, state->static_palette_entries); + gfxr_palettize_view(result, state->static_palette); } return result; } @@ -235,9 +228,9 @@ gfx_pixmap_t *gfxr_interpreter_get_cursor(gfx_resstate_t *state, int nr, void *i byte *resource = res->data; retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(CURSOR_SIZE, CURSOR_SIZE, resid, 0, 0)); - retval->colors = gfx_sci01_cursor_colors; - retval->colors_nr = (state->version != SCI_VERSION_0) ? 3 : 2; - retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + // FIXME: don't copy palette + retval->palette = new Palette(gfx_sci01_cursor_colors, (state->version != SCI_VERSION_0) ? 3 : 2); + retval->palette->name = "cursor"; retval->color_key = GFX_CURSOR_TRANSPARENT; if (state->version != SCI_VERSION_0) { @@ -305,15 +298,15 @@ int *gfxr_interpreter_get_resources(gfx_resstate_t *state, gfx_resource_type_t t return resources; } -gfx_pixmap_color_t *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal) { +Palette *gfxr_interpreter_get_static_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal) { if (version >= SCI_VERSION_01_VGA) return gfxr_interpreter_get_palette(state, version, colors_nr, internal, 999); *colors_nr = GFX_SCI0_PIC_COLORS_NR; - return gfx_sci0_pic_colors; + return gfx_sci0_pic_colors->getref(); } -gfx_pixmap_color_t *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr) { +Palette *gfxr_interpreter_get_palette(gfx_resstate_t *state, int version, int *colors_nr, void *internal, int nr) { ResourceManager *resmgr = (ResourceManager *)state->misc_payload; Resource *res; @@ -329,7 +322,7 @@ gfx_pixmap_color_t *gfxr_interpreter_get_palette(gfx_resstate_t *state, int vers case SCI_VERSION_01_VGA_ODD : case SCI_VERSION_1_EARLY : case SCI_VERSION_1_LATE : - return gfxr_read_pal1(res->id, colors_nr, res->data, res->size); + return gfxr_read_pal1(res->id, res->data, res->size); case SCI_VERSION_1_1 : case SCI_VERSION_32 : GFXDEBUG("Palettes are not yet supported in this SCI version\n"); diff --git a/engines/sci/gfx/resource/sci_view_0.cpp b/engines/sci/gfx/resource/sci_view_0.cpp index 8a9c4c024a..6a0ca140c4 100644 --- a/engines/sci/gfx/resource/sci_view_0.cpp +++ b/engines/sci/gfx/resource/sci_view_0.cpp @@ -49,14 +49,11 @@ gfx_pixmap_t *gfxr_draw_cel0(int id, int loop, int cel, byte *resource, int size retval->xoffset = mirrored ? xhot : -xhot; retval->yoffset = -yhot; - retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; if (view) { - retval->colors = view->colors; - retval->colors_nr = view->colors_nr; + retval->palette = view->palette->getref(); } else { - retval->colors = gfx_sci0_image_colors[sci0_palette]; - retval->colors_nr = GFX_SCI0_IMAGE_COLORS_NR; + retval->palette = gfx_sci0_image_pal[sci0_palette]->getref(); } if (xl <= 0 || yl <= 0) { @@ -183,9 +180,8 @@ gfxr_view_t *gfxr_draw_view0(int id, byte *resource, int size, int palette) { view->loops_nr = resource[V0_LOOPS_NR_OFFSET]; // Set palette - view->colors_nr = GFX_SCI0_IMAGE_COLORS_NR; - view->flags = GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; - view->colors = gfx_sci0_image_colors[sci0_palette]; + view->flags = 0; + view->palette = gfx_sci0_image_pal[sci0_palette]->getref(); if ((palette_ofs) && (palette >= 0)) { byte *paldata = resource + palette_ofs + (palette * GFX_SCI0_IMAGE_COLORS_NR); diff --git a/engines/sci/gfx/resource/sci_view_1.cpp b/engines/sci/gfx/resource/sci_view_1.cpp index b9f5477bd1..937264d84c 100644 --- a/engines/sci/gfx/resource/sci_view_1.cpp +++ b/engines/sci/gfx/resource/sci_view_1.cpp @@ -244,12 +244,8 @@ gfx_pixmap_t *gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *reso retval->xoffset = (mirrored) ? xhot : -xhot; retval->yoffset = -yhot; - if (view) { - retval->colors = view->colors; - retval->colors_nr = view->colors_nr; - } - - retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + if (view) + retval->palette = view->palette->getref(); if (xl <= 0 || yl <= 0) { gfx_free_pixmap(NULL, retval); @@ -316,8 +312,7 @@ static int gfxr_draw_loop1(gfxr_loop_t *dest, int id, int loop, int mirrored, by #define V1_MAGICS_NR 5 //static byte view_magics[V1_MAGICS_NR] = {0x80, 0x00, 0x00, 0x00, 0x00}; -gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_t *static_pal, - int static_pal_nr) { +gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, Palette *static_pal) { int i; int palette_offset; gfxr_view_t *view; @@ -358,22 +353,18 @@ gfxr_view_t *gfxr_draw_view1(int id, byte *resource, int size, gfx_pixmap_color_ free(view); return NULL; } - if (!(view->colors = gfxr_read_pal1(id, &(view->colors_nr), - resource + palette_offset, size - palette_offset))) { + if (!(view->palette = gfxr_read_pal1(id, resource + palette_offset, size - palette_offset))) { GFXERROR("view %04x: Palette reading failed. Aborting...\n", id); free(view); return NULL; } - } else if (static_pal_nr == GFX_SCI1_AMIGA_COLORS_NR) { + } else if (static_pal && static_pal->size() == GFX_SCI1_AMIGA_COLORS_NR) { // Assume we're running an amiga game. amiga_game = 1; - view->colors = static_pal; - view->colors_nr = static_pal_nr; - view->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + view->palette = static_pal->getref(); } else { GFXWARN("view %04x: Doesn't have a palette. Can FreeSCI handle this?\n", view->ID); - view->colors = NULL; - view->colors_nr = 0; + view->palette = NULL; } view->loops = (gfxr_loop_t*)sci_malloc(sizeof(gfxr_loop_t) * view->loops_nr); @@ -434,12 +425,8 @@ gfx_pixmap_t *gfxr_draw_cel11(int id, int loop, int cel, int mirrored, byte *res retval->xoffset = (mirrored) ? xdisplace : -xdisplace; retval->yoffset = -ydisplace; - if (view) { - retval->colors = view->colors; - retval->colors_nr = view->colors_nr; - } - - retval->flags |= GFX_PIXMAP_FLAG_EXTERNAL_PALETTE; + if (view) + retval->palette = view->palette->getref(); if (xl <= 0 || yl <= 0) { gfx_free_pixmap(NULL, retval); @@ -494,7 +481,7 @@ gfxr_view_t *gfxr_draw_view11(int id, byte *resource, int size) { view->loops = (gfxr_loop_t *)calloc(view->loops_nr, sizeof(gfxr_loop_t)); // There is no indication of size here, but this is certainly large enough - view->colors = gfxr_read_pal11(id, &view->colors_nr, resource + palette_offset, 1284); + view->palette = gfxr_read_pal11(id, resource + palette_offset, 1284); seeker = resource + header_size; for (i = 0; i < view->loops_nr; i++) { diff --git a/engines/sci/gfx/sci_widgets.cpp b/engines/sci/gfx/sci_widgets.cpp index 3e6329d426..2509383b89 100644 --- a/engines/sci/gfx/sci_widgets.cpp +++ b/engines/sci/gfx/sci_widgets.cpp @@ -135,7 +135,8 @@ gfxw_port_t *sciw_new_window(EngineState *s, rect_t area, int font, gfx_color_t gfx_state_t *state = s->gfx_state; int shadow_offset = 2; rect_t frame; - gfx_color_t black = {{0, 0, 0, 0}, 0, 0, 0, 0}; + gfx_color_t black; + gfxop_set_color(state, &black, 0, 0, 0, 0, 0, 0); gfxw_port_t *win; gfxw_list_t *decorations; // int xextra = !(flags & WINDOW_FLAG_NOFRAME) ? 1 : 0; @@ -596,7 +597,7 @@ gfxw_widget_t *_make_menu_entry(menu_item_t *item, int offset, int width, gfxw_p rect_t area = gfx_rect(MENU_BOX_LEFT_PADDING, 0, width - MENU_BOX_LEFT_PADDING, 10); rect_t list_area = gfx_rect(port->zone.x, area.y + offset + port->zone.y, width, area.yl); gfxw_list_t *list = (gfxw_list_t *) gfxw_set_id(GFXW(gfxw_new_list(list_area, 0)), ID, GFXW_NO_ID); - gfx_color_t xcolor = {{0, 0, 0, 0}, 0, 0, 0, 0}; + gfx_color_t xcolor = { PaletteEntry(), 0, 0, 0, 0}; color = un_prioritize(color); bgcolor = un_prioritize(bgcolor); |