aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/gfx/resource/sci_view_1.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2009-02-15 11:39:07 +0000
committerEugene Sandulenko2009-02-15 11:39:07 +0000
commite241843bec22600ab4ef98e7a085e82aac73fc93 (patch)
tree61a793884d3462e1feb80e80f202d8816d0c8ec4 /engines/sci/gfx/resource/sci_view_1.cpp
parente9f742806362a84ffdb176a7414318dd2ab4df89 (diff)
downloadscummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.gz
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.bz2
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.zip
- Remove some unneeded files
- Mass rename .c to .cpp svn-id: r38227
Diffstat (limited to 'engines/sci/gfx/resource/sci_view_1.cpp')
-rw-r--r--engines/sci/gfx/resource/sci_view_1.cpp554
1 files changed, 554 insertions, 0 deletions
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) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* 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<<i),
+ resource, loop_offset, size, view, amiga_game)) {
+ /* An error occured */
+ view->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;
+}