aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorWillem Jan Palenstijn2009-03-08 20:17:01 +0000
committerWillem Jan Palenstijn2009-03-08 20:17:01 +0000
commitced40b2266976d0129294a1c5925b7d88024b2de (patch)
tree61b4339e05c997d91a3491aaeac2a978e86e9997 /engines
parent85f6f204195c0859ecf4119e63d5f53b91fb5684 (diff)
downloadscummvm-rg350-ced40b2266976d0129294a1c5925b7d88024b2de.tar.gz
scummvm-rg350-ced40b2266976d0129294a1c5925b7d88024b2de.tar.bz2
scummvm-rg350-ced40b2266976d0129294a1c5925b7d88024b2de.zip
Use new Palette class to manager pixmap palettes.
There are some remaining regressions with text colour in SCI1 games, but overall it should fix more than it breaks. svn-id: r39242
Diffstat (limited to 'engines')
-rw-r--r--engines/sci/engine/game.cpp36
-rw-r--r--engines/sci/engine/kgraphics.cpp49
-rw-r--r--engines/sci/engine/kmenu.cpp4
-rw-r--r--engines/sci/engine/kpathing.cpp10
-rw-r--r--engines/sci/engine/state.h2
-rw-r--r--engines/sci/gfx/font.cpp24
-rw-r--r--engines/sci/gfx/font.h2
-rw-r--r--engines/sci/gfx/gfx_driver.cpp29
-rw-r--r--engines/sci/gfx/gfx_driver.h6
-rw-r--r--engines/sci/gfx/gfx_pixmap_scale.cpp25
-rw-r--r--engines/sci/gfx/gfx_res_options.cpp42
-rw-r--r--engines/sci/gfx/gfx_resmgr.h7
-rw-r--r--engines/sci/gfx/gfx_resource.cpp26
-rw-r--r--engines/sci/gfx/gfx_resource.h19
-rw-r--r--engines/sci/gfx/gfx_system.h41
-rw-r--r--engines/sci/gfx/gfx_tools.cpp151
-rw-r--r--engines/sci/gfx/gfx_tools.h6
-rw-r--r--engines/sci/gfx/gfx_widgets.cpp7
-rw-r--r--engines/sci/gfx/operations.cpp131
-rw-r--r--engines/sci/gfx/operations.h6
-rw-r--r--engines/sci/gfx/palette.cpp265
-rw-r--r--engines/sci/gfx/palette.h107
-rw-r--r--engines/sci/gfx/resmgr.cpp1
-rw-r--r--engines/sci/gfx/resource/sci_pal_1.cpp55
-rw-r--r--engines/sci/gfx/resource/sci_pic_0.cpp147
-rw-r--r--engines/sci/gfx/resource/sci_resmgr.cpp55
-rw-r--r--engines/sci/gfx/resource/sci_view_0.cpp12
-rw-r--r--engines/sci/gfx/resource/sci_view_1.cpp33
-rw-r--r--engines/sci/gfx/sci_widgets.cpp5
-rw-r--r--engines/sci/module.mk1
30 files changed, 699 insertions, 605 deletions
diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp
index 572fe9dc90..c84637b2bc 100644
--- a/engines/sci/engine/game.cpp
+++ b/engines/sci/engine/game.cpp
@@ -101,28 +101,14 @@ static int _init_graphics_input(EngineState *s) {
}
static void _sci1_alloc_system_colors(EngineState *s) {
- gfx_color_t white;
- gfx_color_t black;
-
- white.visual.global_index = 255;
- white.visual.r = white.visual.g = white.visual.b = 255;
- white.alpha = 0;
- white.priority = white.control = 0;
- white.mask = GFX_MASK_VISUAL;
- gfxop_set_system_color(s->gfx_state, &white);
-
- black.visual.global_index = 0;
- black.visual.r = black.visual.g = black.visual.b = 0;
- black.alpha = 0;
- black.priority = black.control = 0;
- black.mask = GFX_MASK_VISUAL;
- gfxop_set_system_color(s->gfx_state, &black);
+ gfx_color_t black = { PaletteEntry(0, 0, 0), 0, 0, 0, GFX_MASK_VISUAL };
+ gfxop_set_system_color(s->gfx_state, 0, &black);
}
int _reset_graphics_input(EngineState *s) {
Resource *resource;
int font_nr;
- gfx_color_t transparent = { { -1, 0, 0, 0 }, 0, -1, -1, 0 };
+ gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
sciprintf("Initializing graphics\n");
if (s->resmgr->_sciVersion <= SCI_VERSION_01) {
@@ -133,24 +119,28 @@ int _reset_graphics_input(EngineState *s) {
gfx_sci0_image_colors[sci0_palette][i].g, gfx_sci0_image_colors[sci0_palette][i].b, 0, -1, -1)) {
return 1;
}
- gfxop_set_system_color(s->gfx_state, &(s->ega_colors[i]));
+ gfxop_set_system_color(s->gfx_state, i, &(s->ega_colors[i]));
}
} else {
// Check for Amiga palette file.
Common::File file;
if (file.open("spal")) {
- s->gfx_state->resstate->static_palette = gfxr_read_pal1_amiga(&s->gfx_state->resstate->static_palette_entries, file);
+ if (s->gfx_state->resstate->static_palette)
+ s->gfx_state->resstate->static_palette->free();
+ s->gfx_state->resstate->static_palette = gfxr_read_pal1_amiga(file);
+ s->gfx_state->resstate->static_palette->name = "static palette";
file.close();
_sci1_alloc_system_colors(s);
} else {
resource = s->resmgr->findResource(kResourceTypePalette, 999, 1);
if (resource) {
+ if (s->gfx_state->resstate->static_palette)
+ s->gfx_state->resstate->static_palette->free();
if (s->version < SCI_VERSION(1, 001, 000))
- s->gfx_state->resstate->static_palette = gfxr_read_pal1(999, &s->gfx_state->resstate->static_palette_entries,
- resource->data, resource->size);
+ s->gfx_state->resstate->static_palette = gfxr_read_pal1(999, resource->data, resource->size);
else
- s->gfx_state->resstate->static_palette = gfxr_read_pal11(999, &s->gfx_state->resstate->static_palette_entries,
- resource->data, resource->size);
+ s->gfx_state->resstate->static_palette = gfxr_read_pal11(999, resource->data, resource->size);
+ s->gfx_state->resstate->static_palette->name = "static palette";
_sci1_alloc_system_colors(s);
s->resmgr->unlockResource(resource, 999, kResourceTypePalette);
} else {
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index ff615e688e..b9a7d0036c 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -264,24 +264,26 @@ void graph_restore_box(EngineState *s, reg_t handle) {
#define KERNEL_COLOR_PALETTE s->gfx_state->pic->visual_map->colors
#define KERNEL_COLORS_NR s->gfx_state->pic->visual_map->colors_nr
#else
-#define KERNEL_COLOR_PALETTE s->gfx_state->resstate->static_palette
-#define KERNEL_COLORS_NR s->gfx_state->resstate->static_palette_entries
+#define KERNEL_COLOR_PALETTE (s->gfx_state->resstate->static_palette)
+#define KERNEL_COLORS_NR (s->gfx_state->resstate->static_palette ? s->gfx_state->resstate->static_palette->size() : 0)
#endif
-static gfx_pixmap_color_t white = {GFX_COLOR_INDEX_UNMAPPED, 255, 255, 255};
+//static gfx_pixmap_color_t white = {GFX_COLOR_INDEX_UNMAPPED, 255, 255, 255};
-gfx_pixmap_color_t *get_pic_color(EngineState *s, int color) {
+//PaletteEntry white(255, 255, 255);
+
+PaletteEntry get_pic_color(EngineState *s, int color) {
if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA)
- return &(s->ega_colors[color].visual);
+ return s->ega_colors[color].visual;
if (color == 255)
- return &white;
- else if (color < KERNEL_COLORS_NR)
- return &(KERNEL_COLOR_PALETTE[color]);
+ return PaletteEntry(255,255,255);
+ else if (color < (int)KERNEL_COLORS_NR)
+ return KERNEL_COLOR_PALETTE->getColor(color);
else {
SCIkwarn(SCIkERROR, "Color index %d out of bounds for pic %d (%d max)", color, s->gfx_state->pic_nr, KERNEL_COLORS_NR);
BREAKPOINT();
- return NULL;
+ return PaletteEntry(0,0,0);
}
}
@@ -293,7 +295,7 @@ static gfx_color_t graph_map_color(EngineState *s, int color, int priority, int
gfxop_set_color(s->gfx_state, &retval, (color < 0) ? -1 : retval.visual.r, retval.visual.g, retval.visual.b,
(color == -1) ? 255 : 0, priority, control);
} else {
- retval.visual = *(get_pic_color(s, color));
+ retval.visual = get_pic_color(s, color);
retval.alpha = 0;
retval.priority = priority;
retval.control = control;
@@ -1276,10 +1278,10 @@ reg_t kPalette(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int i, delta, bestindex = -1, bestdelta = 200000;
- for (i = 0; i < KERNEL_COLORS_NR; i++) {
- int dr = abs(KERNEL_COLOR_PALETTE[i].r - r);
- int dg = abs(KERNEL_COLOR_PALETTE[i].g - g);
- int db = abs(KERNEL_COLOR_PALETTE[i].b - b);
+ for (i = 0; i < (int)KERNEL_COLORS_NR; i++) {
+ int dr = abs(KERNEL_COLOR_PALETTE->getColor(i).r - r);
+ int dg = abs(KERNEL_COLOR_PALETTE->getColor(i).g - g);
+ int db = abs(KERNEL_COLOR_PALETTE->getColor(i).b - b);
delta = dr * dr + dg * dg + db * db;
@@ -2464,9 +2466,9 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) {
if (SKPV_OR_ALT(8 + argextra, 255) >= 0) {
if (s->resmgr->_sciVersion < SCI_VERSION_01_VGA)
- bgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(8 + argextra, 15)));
+ bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 15));
else
- bgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(8 + argextra, 255)));
+ bgcolor.visual = get_pic_color(s, SKPV_OR_ALT(8 + argextra, 255));
bgcolor.mask = GFX_MASK_VISUAL;
}
@@ -2475,13 +2477,14 @@ reg_t kNewWindow(EngineState *s, int funct_nr, int argc, reg_t *argv) {
bgcolor.alpha = 0;
SCIkdebug(SCIkGRAPHICS, "New window with params %d, %d, %d, %d\n", SKPV(0), SKPV(1), SKPV(2), SKPV(3));
- fgcolor.visual = *(get_pic_color(s, SKPV_OR_ALT(7 + argextra, 0)));
+ fgcolor.visual = get_pic_color(s, SKPV_OR_ALT(7 + argextra, 0));
fgcolor.mask = GFX_MASK_VISUAL;
fgcolor.alpha = 0;
- black.visual = *(get_pic_color(s, 0));
+ black.visual = get_pic_color(s, 0);
black.mask = GFX_MASK_VISUAL;
black.alpha = 0;
- lWhite.visual = *(get_pic_color(s, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 15 : 255)), lWhite.mask = GFX_MASK_VISUAL;
+ lWhite.visual = get_pic_color(s, s->resmgr->_sciVersion < SCI_VERSION_01_VGA ? 15 : 255);
+ lWhite.mask = GFX_MASK_VISUAL;
lWhite.alpha = 0;
window = sciw_new_window(s, gfx_rect(x, y, xl, yl), s->titlebar_port->font_nr, fgcolor, bgcolor,
@@ -3083,7 +3086,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int index = UKPV_OR_ALT(1, 0);
int temp;
bool save_under = false;
- gfx_color_t transparent = { { -1, 0, 0, 0 }, 0, -1, -1, 0 };
+ gfx_color_t transparent = { PaletteEntry(), 0, -1, -1, 0 };
char *text;
gfxw_port_t *port = (s->port) ? s->port : s->picture_port;
bool update_immediately = true;
@@ -3100,7 +3103,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
// TODO: in SCI1VGA the default colors for text and background are #0 (black)
// SCI0 case should be checked
if (s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) {
- color0.visual = bg_color.visual = *get_pic_color(s, 0);
+ color0.visual = bg_color.visual = get_pic_color(s, 0);
}
if (textp.segment) {
@@ -3140,7 +3143,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
color0 = (s->ega_colors[temp]);
else
if ((s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) && temp >= 0 && temp < 256) {
- color0.visual = *(get_pic_color(s, temp));
+ color0.visual = get_pic_color(s, temp);
color0.mask = GFX_MASK_VISUAL;
} else
if (temp == -1)
@@ -3157,7 +3160,7 @@ reg_t kDisplay(EngineState *s, int funct_nr, int argc, reg_t *argv) {
bg_color = s->ega_colors[temp];
else
if ((s->resmgr->_sciVersion >= SCI_VERSION_01_VGA) && temp >= 0 && temp <= 256) {
- bg_color.visual = *get_pic_color(s, temp);
+ bg_color.visual = get_pic_color(s, temp);
bg_color.mask = GFX_MASK_VISUAL;
} else
if (temp == -1)
diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp
index d58582c97e..f08e0d3180 100644
--- a/engines/sci/engine/kmenu.cpp
+++ b/engines/sci/engine/kmenu.cpp
@@ -68,9 +68,9 @@ reg_t kDrawStatus(EngineState *s, int funct_nr, int argc, reg_t *argv) {
int fgcolor = SKPV_OR_ALT(1, s->status_bar_foreground);
int bgcolor = SKPV_OR_ALT(2, s->status_bar_background);
- s->titlebar_port->color.visual = *(get_pic_color(s, fgcolor));
+ s->titlebar_port->color.visual = get_pic_color(s, fgcolor);
s->titlebar_port->color.mask = GFX_MASK_VISUAL;
- s->titlebar_port->bgcolor.visual = *(get_pic_color(s, bgcolor));
+ s->titlebar_port->bgcolor.visual = get_pic_color(s, bgcolor);
s->titlebar_port->bgcolor.mask = GFX_MASK_VISUAL;
s->status_bar_foreground = fgcolor;
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index c7c5b00858..b5f34d3f07 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -293,10 +293,7 @@ static void draw_line(EngineState *s, Common::Point p1, Common::Point p2, int ty
gfxw_list_t *decorations = s->picture_port->decorations;
gfxw_primitive_t *line;
- col.visual.global_index = GFX_COLOR_INDEX_UNMAPPED;
- col.visual.r = poly_colors[type][0];
- col.visual.g = poly_colors[type][1];
- col.visual.b = poly_colors[type][2];
+ col.visual = PaletteEntry(poly_colors[type][0], poly_colors[type][1], poly_colors[type][2]);
col.alpha = 0;
col.priority = -1;
col.control = 0;
@@ -318,10 +315,7 @@ static void draw_point(EngineState *s, Common::Point p, int start) {
gfxw_list_t *decorations = s->picture_port->decorations;
gfxw_box_t *box;
- col.visual.global_index = GFX_COLOR_INDEX_UNMAPPED;
- col.visual.r = point_colors[start][0];
- col.visual.g = point_colors[start][1];
- col.visual.b = point_colors[start][2];
+ col.visual = PaletteEntry(point_colors[start][0], point_colors[start][1], point_colors[start][2]);
col.alpha = 0;
col.priority = -1;
col.control = 0;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index bc33f6de92..a8c1e08d24 100644
--- a/engines/sci/engine/state.h
+++ b/engines/sci/engine/state.h
@@ -310,7 +310,7 @@ bool get_savegame_metadata(Common::SeekableReadStream* stream, SavegameMetadata*
/* Read the header from a savegame
*/
-gfx_pixmap_color_t *get_pic_color(EngineState *s, int color);
+PaletteEntry get_pic_color(EngineState *s, int color);
/* Retrieves the gfx_pixmap_color_t associated with a game color index
** Parameters: (EngineState *) s: The game state
** (int) color: The color to look up
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);
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index 287759f52b..df2d9a0697 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -43,6 +43,7 @@ MODULE_OBJS = \
gfx/gfx_widgets.o \
gfx/menubar.o \
gfx/operations.o \
+ gfx/palette.o \
gfx/resmgr.o \
gfx/sbtree.o \
gfx/sci_widgets.o \