diff options
author | Eugene Sandulenko | 2004-04-12 21:40:49 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2004-04-12 21:40:49 +0000 |
commit | f3d340fb0ce72b9db59b8c701153bc82b595f75e (patch) | |
tree | bf250cf3a1e6aee35c7f40d766994b0c2c188e5c /saga/image.cpp | |
parent | 0a0a0c7b0609d8774cef849e7511e7b21d12c5db (diff) | |
download | scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.gz scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.tar.bz2 scummvm-rg350-f3d340fb0ce72b9db59b8c701153bc82b595f75e.zip |
WIP for SAGA engine.
o text formatting is not consistent with rules, just indent utility is too
dumb for that
o it does not use OSystem, i.e. it runs on direct SDL calls
o it may not even compile on your box
o if you enable it, expect zillions of warnings
o no sound
Now it runs ITE intro as reinherit did
svn-id: r13564
Diffstat (limited to 'saga/image.cpp')
-rw-r--r-- | saga/image.cpp | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/saga/image.cpp b/saga/image.cpp new file mode 100644 index 0000000000..d63e6c1088 --- /dev/null +++ b/saga/image.cpp @@ -0,0 +1,510 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2004 The ScummVM project + * + * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header$ + * + */ +/* + Description: + + SAGA Image resource management routines + + Notes: +*/ + +#include "reinherit.h" + +#include "yslib.h" + +/* + * Uses the following modules: +\*--------------------------------------------------------------------------*/ +#include "game_mod.h" + +/* + * Begin module +\*--------------------------------------------------------------------------*/ +#include "image_mod.h" +#include "image.h" + +namespace Saga { + +int +IMG_DecodeBGImage(const uchar * image_data, + size_t image_size, + uchar ** output_buf, size_t * output_buf_len, int *w, int *h) +{ + + R_IMAGE_HEADER hdr; + int modex_height; + + const uchar *RLE_data_ptr; + size_t RLE_data_len; + + uchar *decode_buf; + size_t decode_buf_len; + + uchar *out_buf; + size_t out_buf_len; + + const uchar *read_p = image_data; + + if (image_size <= SAGA_IMAGE_DATA_OFFSET) { + /* Image size is way too small */ + return R_FAILURE; + } + + hdr.width = ys_read_u16_le(read_p, &read_p); + hdr.height = ys_read_u16_le(read_p, &read_p); + hdr.unknown4 = ys_read_u16_le(read_p, &read_p); + hdr.unknown6 = ys_read_u16_le(read_p, &read_p); + + RLE_data_ptr = image_data + SAGA_IMAGE_DATA_OFFSET; + RLE_data_len = image_size - SAGA_IMAGE_DATA_OFFSET; + + modex_height = Granulate(hdr.height, 4); + + decode_buf_len = hdr.width * modex_height; + decode_buf = (uchar *)malloc(decode_buf_len); + + out_buf_len = hdr.width * hdr.height; + out_buf = (uchar *)malloc(out_buf_len); + + if (DecodeBGImageRLE(RLE_data_ptr, + RLE_data_len, decode_buf, decode_buf_len) != R_SUCCESS) { + + free(decode_buf); + free(out_buf); + + return R_FAILURE; + } + + UnbankBGImage(out_buf, decode_buf, hdr.width, hdr.height); + + /* For some reason bg images in IHNM are upside down + * \*------------------------------------------------------------- */ + if (GAME_GetGameType() == R_GAMETYPE_IHNM) { + + FlipImage(out_buf, hdr.width, hdr.height); + } + + free(decode_buf); + + *output_buf_len = out_buf_len; + *output_buf = out_buf; + + *w = hdr.width; + *h = hdr.height; + + return R_SUCCESS; +} + +int +DecodeBGImageRLE(const uchar * inbuf, + size_t inbuf_len, uchar * outbuf, size_t outbuf_len) +{ + + const uchar *inbuf_ptr; + uchar *outbuf_ptr; + size_t inbuf_remain; + + const uchar *inbuf_end; + uchar *outbuf_end; + size_t outbuf_remain; + + uchar mark_byte; + int test_byte; + + uint runcount; + + uchar bitfield; + uchar bitfield_byte1; + uchar bitfield_byte2; + + uchar *backtrack_ptr; + int backtrack_amount; + + uint c, b; + + int decode_err = 0; + + inbuf_ptr = inbuf; + inbuf_remain = inbuf_len; + + outbuf_ptr = outbuf; + outbuf_remain = outbuf_len; + + inbuf_end = (inbuf + inbuf_len) - 1; + outbuf_end = (outbuf + outbuf_len) - 1; + + memset(outbuf, 0, outbuf_len); + + while ((inbuf_remain > 1) && (outbuf_remain > 0) && !decode_err) { + + if ((inbuf_ptr > inbuf_end) || (outbuf_ptr > outbuf_end)) { + return R_FAILURE; + } + + mark_byte = *inbuf_ptr++; + inbuf_remain--; + + test_byte = mark_byte & 0xC0; /* Mask all but two high order bits */ + + switch (test_byte) { + + case 0xC0: /* 1100 0000 */ + + /* Uncompressed run follows: Max runlength 63 */ + runcount = mark_byte & 0x3f; + + if ((inbuf_remain < runcount) || + (outbuf_remain < runcount)) { + return R_FAILURE; + } + + for (c = 0; c < runcount; c++) { + *outbuf_ptr++ = *inbuf_ptr++; + } + + inbuf_remain -= runcount; + outbuf_remain -= runcount; + continue; + + break; + + case 0x80: /* 1000 0000 */ + + /* Compressed run follows: Max runlength 63 */ + runcount = (mark_byte & 0x3f) + 3; + + if (!inbuf_remain || (outbuf_remain < runcount)) { + return R_FAILURE; + } + + for (c = 0; c < runcount; c++) { + *outbuf_ptr++ = *inbuf_ptr; + } + + inbuf_ptr++; + inbuf_remain--; + outbuf_remain -= runcount; + continue; + + break; + + case 0x40: /* 0100 0000 */ + + /* Repeat decoded sequence from output stream: + * Max runlength 10 */ + + runcount = ((mark_byte >> 3) & 0x07U) + 3; + + backtrack_amount = *inbuf_ptr; + + if (!inbuf_remain || + (backtrack_amount > (outbuf_ptr - outbuf)) || + (runcount > outbuf_remain)) { + return R_FAILURE; + } + + inbuf_ptr++; + inbuf_remain--; + + backtrack_ptr = outbuf_ptr - backtrack_amount; + + for (c = 0; c < runcount; c++) { + *outbuf_ptr++ = *backtrack_ptr++; + } + + outbuf_remain -= runcount; + continue; + + break; + + default: /* 0000 0000 */ + break; + } + + /* Mask all but the third and fourth highest order bits */ + test_byte = mark_byte & 0x30; + + switch (test_byte) { + + case 0x30: /* 0011 0000 */ + /* Bitfield compression */ + + runcount = (mark_byte & 0x0F) + 1; + + if ((inbuf_remain < (runcount + 2)) || + (outbuf_remain < (runcount * 8))) { + return R_FAILURE; + } + + bitfield_byte1 = *inbuf_ptr++; + bitfield_byte2 = *inbuf_ptr++; + + for (c = 0; c < runcount; c++) { + + bitfield = *inbuf_ptr; + + for (b = 0; b < 8; b++) { + + if (bitfield & 0x80) { + *outbuf_ptr = bitfield_byte2; + } else { + *outbuf_ptr = bitfield_byte1; + } + + bitfield <<= 1; + + outbuf_ptr++; + } + inbuf_ptr++; + } + + inbuf_remain -= (runcount + 2); + outbuf_remain -= (runcount * 8); + continue; + + break; + + case 0x20: /* 0010 0000 */ + /* Uncompressed run follows */ + + runcount = ((mark_byte & 0x0F) << 8) + *inbuf_ptr; + + if ((inbuf_remain < (runcount + 1)) || + (outbuf_remain < runcount)) { + return R_FAILURE; + } + + inbuf_ptr++; + + for (c = 0; c < runcount; c++) { + *outbuf_ptr++ = *inbuf_ptr++; + } + + inbuf_remain -= (runcount + 1); + outbuf_remain -= runcount; + continue; + + break; + + case 0x10: /* 0001 0000 */ + /* Repeat decoded sequence from output stream */ + + backtrack_amount = + ((mark_byte & 0x0F) << 8) + *inbuf_ptr; + + if (inbuf_remain < 2) { + return R_FAILURE; + } + + inbuf_ptr++; + runcount = *inbuf_ptr++; + + if ((backtrack_amount > (outbuf_ptr - outbuf)) || + (outbuf_remain < runcount)) { + return R_FAILURE; + } + + backtrack_ptr = outbuf_ptr - backtrack_amount; + + for (c = 0; c < runcount; c++) { + *outbuf_ptr++ = *backtrack_ptr++; + } + + inbuf_remain -= 2; + outbuf_remain -= runcount; + continue; + + break; + + default: + return R_FAILURE; + break; + + } + + } /* end while */ + + return R_SUCCESS; +} + +int FlipImage(uchar * img_buf, int columns, int scanlines) +{ + + int line; + uchar *tmp_scan; + + uchar *flip_p1; + uchar *flip_p2; + + int flipcount = scanlines / 2; + + tmp_scan = (uchar *)malloc(columns); + if (tmp_scan == NULL) { + return R_FAILURE; + } + + flip_p1 = img_buf; + flip_p2 = img_buf + (columns * (scanlines - 1)); + + for (line = 0; line < flipcount; line++) { + + memcpy(tmp_scan, flip_p1, columns); + memcpy(flip_p1, flip_p2, columns); + memcpy(flip_p2, tmp_scan, columns); + + flip_p1 += columns; + flip_p2 -= columns; + } + + free(tmp_scan); + + return R_SUCCESS; +} + +int +UnbankBGImage(uchar * dst_buf, + const uchar * src_buf, int columns, int scanlines) +{ + + int x, y; + int temp; + + int quadruple_rows; + int remain_rows; + + int rowjump_src; + int rowjump_dest; + + const uchar *src_p; + uchar *dst_p; + + const uchar *srcptr1, *srcptr2, *srcptr3, *srcptr4; + uchar *dstptr1, *dstptr2, *dstptr3, *dstptr4; + + quadruple_rows = scanlines - (scanlines % 4); + remain_rows = scanlines - quadruple_rows; + + assert(scanlines > 0); + + src_p = src_buf; + dst_p = dst_buf + columns; + + srcptr1 = src_p; + srcptr2 = src_p + 1; + srcptr3 = src_p + 2; + srcptr4 = src_p + 3; + + dstptr1 = dst_buf; + dstptr2 = dst_buf + columns; + dstptr3 = dst_buf + columns * 2; + dstptr4 = dst_buf + columns * 3; + + rowjump_src = columns * 4; + rowjump_dest = columns * 4; + + /* Unbank groups of 4 first */ + for (y = 0; y < quadruple_rows; y += 4) { + + for (x = 0; x < columns; x++) { + temp = x * 4; + dstptr1[x] = srcptr1[temp]; + dstptr2[x] = srcptr2[temp]; + dstptr3[x] = srcptr3[temp]; + dstptr4[x] = srcptr4[temp]; + } + + /* This is to avoid generating invalid pointers - + * usually innocuous, but undefined */ + if (y < quadruple_rows - 4) { + + dstptr1 += rowjump_dest; + dstptr2 += rowjump_dest; + dstptr3 += rowjump_dest; + dstptr4 += rowjump_dest; + srcptr1 += rowjump_src; + srcptr2 += rowjump_src; + srcptr3 += rowjump_src; + srcptr4 += rowjump_src; + } + + } + + /* Unbank rows remaining */ + switch (remain_rows) { + + case 1: + dstptr1 += rowjump_dest; + srcptr1 += rowjump_src; + + for (x = 0; x < columns; x++) { + temp = x * 4; + dstptr1[x] = srcptr1[temp]; + } + break; + + case 2: + dstptr1 += rowjump_dest; + dstptr2 += rowjump_dest; + srcptr1 += rowjump_src; + srcptr2 += rowjump_src; + + for (x = 0; x < columns; x++) { + temp = x * 4; + dstptr1[x] = srcptr1[temp]; + dstptr2[x] = srcptr2[temp]; + } + break; + + case 3: + dstptr1 += rowjump_dest; + dstptr2 += rowjump_dest; + dstptr3 += rowjump_dest; + srcptr1 += rowjump_src; + srcptr2 += rowjump_src; + srcptr3 += rowjump_src; + + for (x = 0; x < columns; x++) { + temp = x * 4; + dstptr1[x] = srcptr1[temp]; + dstptr2[x] = srcptr2[temp]; + dstptr3[x] = srcptr3[temp]; + } + break; + + default: + break; + } + + return R_SUCCESS; +} + +const uchar *IMG_GetImagePal(const uchar * image_data, size_t image_size) +{ + if (image_size <= SAGA_IMAGE_HEADER_LEN) { + return NULL; + } + + return image_data + SAGA_IMAGE_HEADER_LEN; +} + +} // End of namespace Saga |