From e241843bec22600ab4ef98e7a085e82aac73fc93 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 15 Feb 2009 11:39:07 +0000 Subject: - Remove some unneeded files - Mass rename .c to .cpp svn-id: r38227 --- engines/sci/gfx/resource/sci_view_1.cpp | 554 ++++++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 engines/sci/gfx/resource/sci_view_1.cpp (limited to 'engines/sci/gfx/resource/sci_view_1.cpp') diff --git a/engines/sci/gfx/resource/sci_view_1.cpp b/engines/sci/gfx/resource/sci_view_1.cpp new file mode 100644 index 0000000000..d747545331 --- /dev/null +++ b/engines/sci/gfx/resource/sci_view_1.cpp @@ -0,0 +1,554 @@ +/*************************************************************************** + view_1.c Copyright (C) 2000 Christoph Reichenbach + + + This program may be modified and copied freely according to the terms of + the GNU general public license (GPL), as long as the above copyright + notice and the licensing information contained herein are preserved. + + Please refer to www.gnu.org for licensing details. + + This work is provided AS IS, without warranty of any kind, expressed or + implied, including but not limited to the warranties of merchantibility, + noninfringement, and fitness for a specific purpose. The author will not + be held liable for any damage caused by this work or derivatives of it. + + By using this source code, you agree to the licensing terms as stated + above. + + + Please contact the maintainer for bug reports or inquiries. + + Current Maintainer: + + Christoph Reichenbach (CR) + +***************************************************************************/ +/* SCI 1 view resource defrobnicator */ + +#include "sci/include/sci_memory.h" +#include "sci/include/gfx_system.h" +#include "sci/include/gfx_resource.h" +#include "sci/include/gfx_tools.h" + +#define V1_LOOPS_NR_OFFSET 0 +#define V1_MIRROR_MASK 2 +#define V1_PALETTE_OFFSET 6 +#define V1_FIRST_LOOP_OFFSET 8 + +#define V1_RLE 0x80 /* run-length encode? */ +#define V1_RLE_BG 0x40 /* background fill */ + +#define NEXT_RUNLENGTH_BYTE(n) \ + if (literal_pos == runlength_pos) \ + literal_pos += n; \ + runlength_pos += n; + +#define NEXT_LITERAL_BYTE(n) \ + if (literal_pos == runlength_pos) \ + runlength_pos += n; \ + literal_pos += n; + +static int +decompress_sci_view(int id, int loop, int cel, byte *resource, byte *dest, int mirrored, int pixmap_size, int size, + int runlength_pos, int literal_pos, int xl, int yl, int color_key) +{ + int writepos = mirrored? xl : 0; + + if (mirrored) { + int linebase = 0; + + while (linebase < pixmap_size && literal_pos < size && runlength_pos < size) { + int op = resource[runlength_pos]; + int bytes; + int readbytes = 0; + int color; + + NEXT_RUNLENGTH_BYTE(1); + + if (op & V1_RLE) { + bytes = op & 0x3f; + op &= (V1_RLE | V1_RLE_BG); + readbytes = (op & V1_RLE_BG)? 0 : 1; + } else { + readbytes = bytes = op & 0x3f; + op = 0; + } + + if (runlength_pos + readbytes > size) + { + GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n", + id, loop, cel, readbytes, size - runlength_pos, runlength_pos-1); + return 1; + } +/* + if (writepos - bytes < 0) { + GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n", + id, loop, cel, writepos - bytes, pixmap_size, pos - 1); + bytes = pixmap_size - writepos; + } +*/ + if (op==V1_RLE) + { + color = resource[literal_pos]; + NEXT_LITERAL_BYTE(1); + } + + if (!op && literal_pos + bytes > size) + { + GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n", + id, loop, cel, bytes, size - literal_pos, literal_pos-1); + return 1; + } + + while (bytes--) + { + if (op) { + if (op & V1_RLE_BG) { + writepos--; + *(dest + writepos) = color_key; + } else { + writepos--; + *(dest + writepos) = color; + } + } else { + writepos--; + *(dest + writepos) = *(resource + literal_pos); + NEXT_LITERAL_BYTE(1); + + } + if (writepos == linebase) + { + writepos+=2*xl; + linebase+=xl; + } + } + } + } + else { + while (writepos < pixmap_size && literal_pos < size && runlength_pos < size) { + int op = resource[runlength_pos]; + int bytes; + int readbytes = 0; + + NEXT_RUNLENGTH_BYTE(1); + + if (op & V1_RLE) { + bytes = op & 0x3f; + op &= (V1_RLE | V1_RLE_BG); + readbytes = (op & V1_RLE_BG)? 0 : 1; + } else { + readbytes = bytes = op & 0x3f; + op = 0; + } + + if (runlength_pos + readbytes > size) { + return 1; + } + + if (writepos + bytes > pixmap_size) { + GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n", + id, loop, cel, writepos-bytes, pixmap_size, runlength_pos - 1); + bytes = pixmap_size - writepos; + } + + if (!op && literal_pos + bytes > size) + { + GFXWARN("View %02x:(%d/%d) requires %d bytes to be read when %d are available at pos %d\n", + id, loop, cel, bytes, size - literal_pos, literal_pos-1); + return 1; + } + + if (writepos + bytes > pixmap_size) + { + GFXWARN("Writing out of bounds: %d bytes at %d > size %d\n", bytes, writepos, pixmap_size); + } + + if (op) { + if (op & V1_RLE_BG) + memset(dest + writepos, color_key, bytes); + else { + int color = resource[literal_pos]; + + NEXT_LITERAL_BYTE(1); + memset(dest + writepos, color, bytes); + } + } else { + memcpy(dest + writepos, resource + literal_pos, bytes); + NEXT_LITERAL_BYTE(bytes); + } + writepos += bytes; + + } + + }; + + return 0; +} + +static int +decompress_sci_view_amiga(int id, int loop, int cel, byte *resource, byte *dest, int mirrored, int pixmap_size, int size, + int pos, int xl, int yl, int color_key) +{ + int writepos = mirrored? xl - 1 : 0; + + while (writepos < pixmap_size && pos < size) { + int op = resource[pos++]; + int bytes; + int color; + + if (op & 0x07) { + bytes = op & 0x07; + color = op >> 3; + } else { + bytes = op >> 3; + color = color_key; + } + + if (mirrored) { + while (bytes--) { + dest[writepos--] = color; + /* If we've just written the first pixel of a line... */ + if (!((writepos + 1) % xl)) { + /* Then move to the end of next line */ + writepos += 2 * xl; + + if (writepos >= pixmap_size && bytes) + { + GFXWARN("View %02x:(%d/%d) writing out of bounds\n", id, loop, cel); + break; + } + } + } + } else { + if (writepos + bytes > pixmap_size) { + GFXWARN("View %02x:(%d/%d) describes more bytes than needed: %d/%d bytes at rel. offset 0x%04x\n", + id, loop, cel, writepos-bytes, pixmap_size, pos - 1); + bytes = pixmap_size - writepos; + } + memset(dest + writepos, color, bytes); + writepos += bytes; + } + } + + if (writepos < pixmap_size) { + GFXWARN("View %02x:(%d/%d) not enough pixel data in view\n", id, loop, cel); + return 1; + } + + return 0; +} + +gfx_pixmap_t * +gfxr_draw_cel1(int id, int loop, int cel, int mirrored, byte *resource, int size, gfxr_view_t *view, int amiga_game) +{ + int xl = get_int_16(resource); + int yl = get_int_16(resource + 2); + int xhot = (gint8) resource[4]; + int yhot = (guint8) resource[5]; + int pos = 8; + int pixmap_size = xl * yl; + gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel)); + byte *dest = retval->index_data; + int decompress_failed; + + retval->color_key = resource[6]; + 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 (xl <= 0 || yl <= 0) { + gfx_free_pixmap(NULL, retval); + GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl); + return NULL; + } + + if (amiga_game) + decompress_failed = decompress_sci_view_amiga(id, loop, cel, + resource, dest, mirrored, pixmap_size, size, pos, + xl, yl, retval->color_key); + else + decompress_failed = decompress_sci_view(id, loop, cel, + resource, dest, mirrored, pixmap_size, size, pos, + pos, xl, yl, retval->color_key); + + if (decompress_failed) { + gfx_free_pixmap(NULL, retval); + return NULL; + } + + return retval; +} + +static int +gfxr_draw_loop1(gfxr_loop_t *dest, int id, int loop, int mirrored, byte *resource, int offset, int size, gfxr_view_t *view, int amiga_game) +{ + int i; + int cels_nr = get_int_16(resource + offset); + + if (get_uint_16(resource + offset + 2)) { + GFXWARN("View %02x:(%d): Gray magic %04x in loop, expected white\n", id, loop, get_uint_16(resource + offset + 2)); + } + + if (cels_nr * 2 + 4 + offset > size) { + GFXERROR("View %02x:(%d): Offset array for %d cels extends beyond resource space\n", id, loop, cels_nr); + dest->cels_nr = 0; /* Mark as "delete no cels" */ + dest->cels = NULL; + return 1; + } + + dest->cels = (gfx_pixmap_t**)sci_malloc(sizeof(gfx_pixmap_t *) * cels_nr); + + for (i = 0; i < cels_nr; i++) { + int cel_offset = get_uint_16(resource + offset + 4 + (i << 1)); + gfx_pixmap_t *cel; + + if (cel_offset >= size) { + GFXERROR("View %02x:(%d/%d) supposed to be at illegal offset 0x%04x\n", id, loop, i, cel_offset); + cel = NULL; + } else + cel = gfxr_draw_cel1(id, loop, i, mirrored, resource + cel_offset, size - cel_offset, view, amiga_game); + + if (!cel) { + dest->cels_nr = i; + return 1; + } + + dest->cels[i] = cel; + } + + dest->cels_nr = cels_nr; + + return 0; +} + + +#define V1_FIRST_MAGIC 1 +#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) +{ + int i; + int palette_offset; + gfxr_view_t *view; + int mirror_mask; + int amiga_game = 0; + + if (size < V1_FIRST_LOOP_OFFSET + 8) { + GFXERROR("Attempt to draw empty view %04x\n", id); + return NULL; + } + + view = (gfxr_view_t*)sci_malloc(sizeof(gfxr_view_t)); + view->ID = id; + view->flags = 0; + + view->loops_nr = resource[V1_LOOPS_NR_OFFSET]; + palette_offset = get_uint_16(resource + V1_PALETTE_OFFSET); + mirror_mask = get_uint_16(resource + V1_MIRROR_MASK); + + if (view->loops_nr * 2 + V1_FIRST_LOOP_OFFSET > size) { + GFXERROR("View %04x: Not enough space in resource to accomodate for the claimed %d loops\n", id, view->loops_nr); + free(view); + return NULL; + } + +/* fprintf(stderr, "View flags are 0x%02x\n", resource[3]);*/ + +/* + for (i = 0; i < V1_MAGICS_NR; i++) + if (resource[V1_FIRST_MAGIC + i] != view_magics[i]) { + GFXWARN("View %04x: View magic #%d should be %02x but is %02x\n", + id, i, view_magics[i], resource[V1_FIRST_MAGIC + i]); + } +*/ + + if (palette_offset > 0) + { + if (palette_offset > size) { + GFXERROR("Palette is outside of view %04x\n", id); + free(view); + return NULL; + } + if (!(view->colors = gfxr_read_pal1(id, &(view->colors_nr), + 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) { + /* 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; + } else { + GFXWARN("view %04x: Doesn't have a palette. Can FreeSCI handle this?\n", view->ID); + view->colors = NULL; + view->colors_nr = 0; + } + + view->loops = (gfxr_loop_t*)sci_malloc(sizeof (gfxr_loop_t) * view->loops_nr); + + for (i = 0; i < view->loops_nr; i++) { + int error_token = 0; + int loop_offset = get_uint_16(resource + V1_FIRST_LOOP_OFFSET + (i << 1)); + + if (loop_offset >= size) { + GFXERROR("View %04x:(%d) supposed to be at illegal offset 0x%04x\n", id, i); + error_token = 1; + } + + if (error_token || gfxr_draw_loop1(view->loops + i, id, i, mirror_mask & (1<loops_nr = i; + gfxr_free_view(NULL, view); + return NULL; + } + } + + return view; +} + +#define V2_HEADER_SIZE 0 +#define V2_LOOPS_NUM 2 +#define V2_PALETTE_OFFSET 8 +#define V2_BYTES_PER_LOOP 12 +#define V2_BYTES_PER_CEL 13 + +#define V2_IS_MIRROR 1 +#define V2_COPY_OF_LOOP 2 +#define V2_CELS_NUM 4 +#define V2_LOOP_OFFSET 14 + +#define V2_CEL_WIDTH 0 +#define V2_CEL_HEIGHT 2 +#define V2_X_DISPLACEMENT 4 +#define V2_Y_DISPLACEMENT 6 +#define V2_COLOR_KEY 8 +#define V2_RUNLENGTH_OFFSET 24 +#define V2_LITERAL_OFFSET 28 + +gfx_pixmap_t * +gfxr_draw_cel11(int id, int loop, int cel, int mirrored, byte *resource_base, byte *cel_base, int size, gfxr_view_t *view) +{ + int xl = get_uint_16(cel_base + V2_CEL_WIDTH); + int yl = get_uint_16(cel_base + V2_CEL_HEIGHT); + int xdisplace = get_uint_16(cel_base + V2_X_DISPLACEMENT); + int ydisplace = get_uint_16(cel_base + V2_Y_DISPLACEMENT); + int runlength_offset = get_uint_16(cel_base + V2_RUNLENGTH_OFFSET); + int literal_offset = get_uint_16(cel_base + V2_LITERAL_OFFSET); + int pixmap_size = xl * yl; + + gfx_pixmap_t *retval = gfx_pixmap_alloc_index_data(gfx_new_pixmap(xl, yl, id, loop, cel)); + byte *dest = retval->index_data; + int decompress_failed; + + retval->color_key = cel_base[V2_COLOR_KEY]; + 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 (xl <= 0 || yl <= 0) { + gfx_free_pixmap(NULL, retval); + GFXERROR("View %02x:(%d/%d) has invalid xl=%d or yl=%d\n", id, loop, cel, xl, yl); + return NULL; + } + + decompress_failed = decompress_sci_view(id, loop, cel, resource_base, dest, mirrored, pixmap_size, size, + runlength_offset, literal_offset, xl, yl, retval->color_key); + + if (decompress_failed) { + gfx_free_pixmap(NULL, retval); + return NULL; + } + + return retval; +} + +gfxr_loop_t * +gfxr_draw_loop11(int id, int loop, int mirrored, byte *resource_base, byte *loop_base, int size, int cels_nr, + gfxr_loop_t *result, gfxr_view_t *view, int bytes_per_cel) +{ + byte *seeker = loop_base; + int i; + + result->cels_nr = cels_nr; + result->cels = (gfx_pixmap_t **) + sci_malloc(sizeof(gfx_pixmap_t *) * cels_nr); + + for (i = 0; i < cels_nr; i++) + { + result->cels[i] = gfxr_draw_cel11(id, loop, i, mirrored, resource_base, seeker, size, view); + seeker += bytes_per_cel; + } + + return result; +} + +gfxr_view_t * +gfxr_draw_view11(int id, byte *resource, int size) +{ + gfxr_view_t *view; + int header_size = get_uint_16(resource + V2_HEADER_SIZE); + int palette_offset = get_uint_16(resource + V2_PALETTE_OFFSET); + int bytes_per_loop = resource[V2_BYTES_PER_LOOP]; + int loops_num = resource[V2_LOOPS_NUM]; + int bytes_per_cel = resource[V2_BYTES_PER_CEL]; + int i; + byte *seeker; + + view = (gfxr_view_t*)sci_malloc(sizeof(gfxr_view_t)); + + memset(view, 0, sizeof(gfxr_view_t)); + view->ID = id; + view->flags = 0; + + view->loops_nr = loops_num; + 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); + + seeker = resource + header_size; + for (i = 0; i < view->loops_nr; i++) + { + static char *truth[2] = {"not ",""}; + int loop_offset = get_uint_16(seeker + V2_LOOP_OFFSET); + int cels = seeker[V2_CELS_NUM]; + int mirrored = seeker[V2_IS_MIRROR]; + int copy_entry = seeker[V2_COPY_OF_LOOP]; + + printf("%d\n", mirrored); + if (copy_entry == 255) + gfxr_draw_loop11(id, i, 0, resource, resource + loop_offset, size, cels, view->loops + i, + view, bytes_per_cel); else + { + byte *temp = resource + header_size + copy_entry * bytes_per_loop; + loop_offset = get_uint_16(temp + V2_LOOP_OFFSET); + cels = temp[V2_CELS_NUM]; + gfxr_draw_loop11(id, i, 1, resource, resource + loop_offset, size, cels, + view->loops + i, view, bytes_per_cel); + } + + seeker += bytes_per_loop; + } + + return view; +} -- cgit v1.2.3