Merge in some of LordHotos kyra code, with some changes.
It's still non-functional, but once I merge in some more of my local changes things should actually be moving a long a bit. svn-id: r15554
This commit is contained in:
parent
9e40ef7d29
commit
8f65711a28
15 changed files with 2645 additions and 27 deletions
322
kyra/codecs.cpp
Normal file
322
kyra/codecs.cpp
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "codecs.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* decode.c - Decoding routines for format80, format40, format20
|
||||||
|
* and format3 type graphics
|
||||||
|
* Author: Olaf van der spek
|
||||||
|
* Modified for FreeCNC by Kareem Dana
|
||||||
|
* Modified for Kyra by Jack Burton
|
||||||
|
* Format3 decoding added by Jack Burton
|
||||||
|
* Modified for ScummVM by Johannes Schickel
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/** decompress format 80 compressed data.
|
||||||
|
* @param compressed data.
|
||||||
|
* @param pointer to output uncompressed data.
|
||||||
|
* @returns size of uncompressed data.
|
||||||
|
*/
|
||||||
|
namespace Kyra {
|
||||||
|
int Compression::decode80(const uint8* image_in, uint8* image_out) {
|
||||||
|
/*
|
||||||
|
0 copy 0cccpppp p
|
||||||
|
1 copy 10cccccc
|
||||||
|
2 copy 11cccccc p p
|
||||||
|
3 fill 11111110 c c v
|
||||||
|
4 copy 11111111 c c p p
|
||||||
|
*/
|
||||||
|
|
||||||
|
const uint8* copyp;
|
||||||
|
const uint8* readp = image_in;
|
||||||
|
uint8* writep = image_out;
|
||||||
|
uint16 code;
|
||||||
|
uint16 count;
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
uint16 bigend; /* temporary big endian var */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
code = *readp++;
|
||||||
|
if (~code & 0x80)
|
||||||
|
{
|
||||||
|
//bit 7 = 0
|
||||||
|
//command 0 (0cccpppp p): copy
|
||||||
|
count = (code >> 4) + 3;
|
||||||
|
copyp = writep - (((code & 0xf) << 8) + *readp++);
|
||||||
|
while (count--)
|
||||||
|
*writep++ = *copyp++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bit 7 = 1
|
||||||
|
count = code & 0x3f;
|
||||||
|
if (~code & 0x40)
|
||||||
|
{
|
||||||
|
//bit 6 = 0
|
||||||
|
if (!count)
|
||||||
|
//end of image
|
||||||
|
break;
|
||||||
|
//command 1 (10cccccc): copy
|
||||||
|
while (count--)
|
||||||
|
*writep++ = *readp++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bit 6 = 1
|
||||||
|
if (count < 0x3e)
|
||||||
|
{
|
||||||
|
//command 2 (11cccccc p p): copy
|
||||||
|
count += 3;
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
memcpy(&bigend, readp, 2);
|
||||||
|
copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)SWAP_BYTES_16(bigend))];
|
||||||
|
#else
|
||||||
|
copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)readp))];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
readp += 2;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = *copyp++;
|
||||||
|
}
|
||||||
|
else if (count == 0x3e)
|
||||||
|
{
|
||||||
|
//command 3 (11111110 c c v): fill
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
memset(&count, 0, sizeof(uint32));
|
||||||
|
memcpy(&count, readp, 2);
|
||||||
|
count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count));
|
||||||
|
#else
|
||||||
|
count = *(const_cast<uint16*>((const uint16*)readp));
|
||||||
|
#endif
|
||||||
|
readp += 2;
|
||||||
|
code = *readp++;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//command 4 (copy 11111111 c c p p): copy
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
memset(&count, 0, sizeof(uint32));
|
||||||
|
memcpy(&count, readp, 2);
|
||||||
|
count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count));
|
||||||
|
#else
|
||||||
|
count = *(const_cast<uint16*>((const uint16*)readp));
|
||||||
|
#endif
|
||||||
|
readp += 2;
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
memcpy(&bigend, readp, 2);
|
||||||
|
copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)SWAP_BYTES_16(bigend))];
|
||||||
|
#else
|
||||||
|
copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)readp))];
|
||||||
|
#endif
|
||||||
|
readp += 2;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = *copyp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (writep - image_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** decompress format 40 compressed data.
|
||||||
|
* @param compressed data.
|
||||||
|
* @param pointer to put uncompressed data in.
|
||||||
|
* @returns size of uncompressed data.
|
||||||
|
*/
|
||||||
|
int Compression::decode40(const uint8* image_in, uint8* image_out) {
|
||||||
|
/*
|
||||||
|
0 fill 00000000 c v
|
||||||
|
1 copy 0ccccccc
|
||||||
|
2 skip 10000000 c 0ccccccc
|
||||||
|
3 copy 10000000 c 10cccccc
|
||||||
|
4 fill 10000000 c 11cccccc v
|
||||||
|
5 skip 1ccccccc
|
||||||
|
*/
|
||||||
|
|
||||||
|
const uint8* readp = image_in;
|
||||||
|
uint8* writep = image_out;
|
||||||
|
uint16 code;
|
||||||
|
uint16 count;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
code = *readp++;
|
||||||
|
if (~code & 0x80)
|
||||||
|
{
|
||||||
|
//bit 7 = 0
|
||||||
|
if (!code)
|
||||||
|
{
|
||||||
|
//command 0 (00000000 c v): fill
|
||||||
|
count = *readp++;
|
||||||
|
code = *readp++;
|
||||||
|
while (count--)
|
||||||
|
*writep++ ^= code;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//command 1 (0ccccccc): copy
|
||||||
|
count = code;
|
||||||
|
while (count--)
|
||||||
|
*writep++ ^= *readp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bit 7 = 1
|
||||||
|
if (!(count = code & 0x7f))
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef SCUMM_BIG_ENDIAN
|
||||||
|
memset(&count, 0, sizeof(uint32));
|
||||||
|
memcpy(&count, readp, 2);
|
||||||
|
count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count));
|
||||||
|
#else
|
||||||
|
count = *(const_cast<uint16*>((const uint16*)readp));
|
||||||
|
#endif
|
||||||
|
readp += 2;
|
||||||
|
code = count >> 8;
|
||||||
|
if (~code & 0x80)
|
||||||
|
{
|
||||||
|
//bit 7 = 0
|
||||||
|
//command 2 (10000000 c 0ccccccc): skip
|
||||||
|
if (!count)
|
||||||
|
// end of image
|
||||||
|
break;
|
||||||
|
writep += count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bit 7 = 1
|
||||||
|
count &= 0x3fff;
|
||||||
|
if (~code & 0x40)
|
||||||
|
{
|
||||||
|
//bit 6 = 0
|
||||||
|
//command 3 (10000000 c 10cccccc): copy
|
||||||
|
while (count--)
|
||||||
|
*writep++ ^= *readp++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//bit 6 = 1
|
||||||
|
//command 4 (10000000 c 11cccccc v): fill
|
||||||
|
code = *readp++;
|
||||||
|
while (count--)
|
||||||
|
*writep++ ^= code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //command 5 (1ccccccc): skip
|
||||||
|
writep += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (writep - image_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** decompress format 3 compressed data.
|
||||||
|
* @param compressed data.
|
||||||
|
* @param pointer to put uncompressed data in.
|
||||||
|
* @param size of uncompressed image.
|
||||||
|
*/
|
||||||
|
int Compression::decode3(const uint8* image_in, uint8* image_out, int size)
|
||||||
|
{ /* Untested on BIG-Endian machines */
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 copy
|
||||||
|
1 fill
|
||||||
|
2 fill
|
||||||
|
*/
|
||||||
|
const uint8* readp = image_in;
|
||||||
|
uint8* writep = image_out;
|
||||||
|
int16 code;
|
||||||
|
int16 count;
|
||||||
|
|
||||||
|
do {
|
||||||
|
code = *const_cast<int8*>((const int8*)readp++);
|
||||||
|
if (code > 0) // Copy
|
||||||
|
{
|
||||||
|
count = code ;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = *readp++;
|
||||||
|
}
|
||||||
|
else if (code == 0) // Fill(1)
|
||||||
|
{
|
||||||
|
count = *(const_cast<uint16*>((const uint16*)readp));
|
||||||
|
|
||||||
|
#ifdef SCUMM_LITTLE_ENDIAN
|
||||||
|
count = SWAP_BYTES_16(count);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
readp += 2;
|
||||||
|
code = *readp++;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = (uint8)code;
|
||||||
|
}
|
||||||
|
else if (code < 0) // Fill (2)
|
||||||
|
{
|
||||||
|
count = -code;
|
||||||
|
code = *readp++;
|
||||||
|
while (count--)
|
||||||
|
*writep++ = (uint8)code;
|
||||||
|
}
|
||||||
|
} while ((writep - image_out) < size);
|
||||||
|
|
||||||
|
//and, to be uniform to other decomp. functions...
|
||||||
|
return (writep - image_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** decompress format 20 compressed data.
|
||||||
|
* @param compressed data.
|
||||||
|
* @param pointer to pu uncompressed data in.
|
||||||
|
* @param size of compressed data?
|
||||||
|
* @returns size of uncompressed data?
|
||||||
|
*/
|
||||||
|
int Compression::decode2(const uint8* s, uint8* d, int cb_s) {
|
||||||
|
const uint8* r = s;
|
||||||
|
const uint8* r_end = s + cb_s;
|
||||||
|
uint8* w = d;
|
||||||
|
while (r < r_end) {
|
||||||
|
int v = *r++;
|
||||||
|
if (v)
|
||||||
|
*w++ = v;
|
||||||
|
else {
|
||||||
|
v = *r++;
|
||||||
|
memset(w, 0, v);
|
||||||
|
w += v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w - d;
|
||||||
|
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
43
kyra/codecs.h
Normal file
43
kyra/codecs.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Various decompression routines */
|
||||||
|
#ifndef __COMPRESSION_H
|
||||||
|
#define __COMPRESSION_H
|
||||||
|
|
||||||
|
// THIS CODE WAS TAKEN FROM FreeKyra Tools Module
|
||||||
|
|
||||||
|
#include "common/stdafx.h"
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
class Compression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int decode80(const uint8* image_in, uint8* image_out);
|
||||||
|
static int decode40(const uint8* image_in, uint8* image_out);
|
||||||
|
static int decode3(const uint8* image_in, uint8* image_out, int s);
|
||||||
|
static int decode2(const uint8* s, uint8* d, int cb_s);
|
||||||
|
};
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
183
kyra/cpsimage.cpp
Normal file
183
kyra/cpsimage.cpp
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "codecs.h"
|
||||||
|
|
||||||
|
#include "common/stream.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
|
||||||
|
struct CPSResource {
|
||||||
|
uint32 size;
|
||||||
|
uint16 width;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const CPSResource CPSResourceTable[] = {
|
||||||
|
{ 64000, 320 }, { 7740, 180 }, { 46080, 320 }, { 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int16 getWidthFromCPSRes(uint32 size) {
|
||||||
|
int16 c = 0;
|
||||||
|
|
||||||
|
for (; CPSResourceTable[c].size; ++c) {
|
||||||
|
if (CPSResourceTable[c].size == size)
|
||||||
|
return CPSResourceTable[c].width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPSImage::CPSImage(uint8* buffer, uint32 size) {
|
||||||
|
if (!buffer) {
|
||||||
|
error("resource created without data");
|
||||||
|
}
|
||||||
|
Common::MemoryReadStream bufferstream(buffer, size);
|
||||||
|
|
||||||
|
// reads in the Header
|
||||||
|
_cpsHeader._filesize = bufferstream.readUint16LE() + 2;
|
||||||
|
_cpsHeader._format = bufferstream.readUint16LE();
|
||||||
|
_cpsHeader._imagesize = bufferstream.readUint16LE();
|
||||||
|
_cpsHeader._pal = bufferstream.readUint32LE();
|
||||||
|
|
||||||
|
// lets check a bit
|
||||||
|
if(_cpsHeader._pal == 0x3000000) {
|
||||||
|
warning("CPS images with a palette aren't supported");
|
||||||
|
|
||||||
|
// skip 768 bytes
|
||||||
|
// if this was a compressed palette you should have strange graphics
|
||||||
|
bufferstream.seek(bufferstream.pos() + 768);
|
||||||
|
}
|
||||||
|
|
||||||
|
_image = new uint8[_cpsHeader._imagesize];
|
||||||
|
assert(_image);
|
||||||
|
|
||||||
|
uint8* imagebuffer = &buffer[bufferstream.pos()];
|
||||||
|
assert(imagebuffer);
|
||||||
|
|
||||||
|
if(_cpsHeader._format == 4) {
|
||||||
|
Compression::decode80(imagebuffer, _image);
|
||||||
|
} else if(_cpsHeader._format == 3) {
|
||||||
|
Compression::decode3(imagebuffer, _image, _cpsHeader._imagesize);
|
||||||
|
} else {
|
||||||
|
error("unknown CPS format %d", _cpsHeader._format);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 width = getWidthFromCPSRes(_cpsHeader._imagesize);
|
||||||
|
|
||||||
|
if(width == -1) {
|
||||||
|
warning("unknown CPS width(imagesize: %d)", _cpsHeader._imagesize);
|
||||||
|
delete [] buffer;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_width = (uint16)width;
|
||||||
|
_height = _cpsHeader._imagesize / _width;
|
||||||
|
|
||||||
|
_transparency = -1;
|
||||||
|
|
||||||
|
delete [] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPSImage::~CPSImage() {
|
||||||
|
delete [] _image;
|
||||||
|
delete _ownPalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPSImage::drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y) {
|
||||||
|
if (_transparency == -1) {
|
||||||
|
// 'fast' blitting
|
||||||
|
|
||||||
|
uint8* src = _image;
|
||||||
|
uint8* dst = &plane[y * planepitch + x];
|
||||||
|
uint32 copysize = planepitch - x;
|
||||||
|
|
||||||
|
if (copysize > _width)
|
||||||
|
copysize = _width;
|
||||||
|
|
||||||
|
for (uint16 y_ = 0; y_ < _height && y + y_ < planeheight; ++y_) {
|
||||||
|
memcpy(dst, src, copysize * sizeof(uint8));
|
||||||
|
dst += planepitch;
|
||||||
|
src += _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// oh no! we have transparency so we have a very slow copy :/
|
||||||
|
uint8* src = _image;
|
||||||
|
uint8* dst = &plane[y * planepitch + x];
|
||||||
|
|
||||||
|
for (uint16 yadd = 0; yadd < _height; ++yadd) {
|
||||||
|
for (uint16 xadd = 0; xadd < _width; ++xadd) {
|
||||||
|
if (*src == _transparency) {
|
||||||
|
++dst;
|
||||||
|
++src;
|
||||||
|
} else {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst += planepitch - _width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPSImage::drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y,
|
||||||
|
uint16 srcx, uint16 srcy, uint16 srcwidth, uint16 srcheight) {
|
||||||
|
if (_transparency == -1) {
|
||||||
|
// 'fast' blitting
|
||||||
|
|
||||||
|
uint8* src = &_image[srcy * _width + srcx];
|
||||||
|
uint8* dst = &plane[y * planepitch + x];
|
||||||
|
uint32 copysize = planepitch - x;
|
||||||
|
|
||||||
|
if (copysize > srcwidth)
|
||||||
|
copysize = srcwidth;
|
||||||
|
|
||||||
|
for (uint16 y_ = 0; y_ < srcheight && y + y_ < planeheight; ++y_) {
|
||||||
|
memcpy(dst, src, copysize * sizeof(uint8));
|
||||||
|
dst += planepitch;
|
||||||
|
src += _width;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// oh no! we have transparency so we have a very slow copy :/
|
||||||
|
// blit it without transparency
|
||||||
|
uint8* src = &_image[srcy * _width + srcx];
|
||||||
|
uint8* dst = &plane[y * planepitch + x];
|
||||||
|
|
||||||
|
for (uint16 yadd = 0; yadd < _height; ++yadd) {
|
||||||
|
for (uint16 xadd = 0; xadd < _width; ++xadd) {
|
||||||
|
if (*src == _transparency) {
|
||||||
|
++dst;
|
||||||
|
++src;
|
||||||
|
} else {
|
||||||
|
*dst++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst += planepitch - _width;
|
||||||
|
src += _width - srcwidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
329
kyra/font.cpp
Normal file
329
kyra/font.cpp
Normal file
|
@ -0,0 +1,329 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "common/stream.h"
|
||||||
|
#include "common/array.h"
|
||||||
|
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
#include <cstdio>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
const uint16 FontHeader_Magic1 = 0x0500;
|
||||||
|
const uint16 FontHeader_Magic2 = 0x000e;
|
||||||
|
const uint16 FontHeader_Magic3 = 0x0014;
|
||||||
|
|
||||||
|
Font::Font(uint8* buffer, uint32 size) {
|
||||||
|
if (!buffer) {
|
||||||
|
error("resource created without data");
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer = buffer;
|
||||||
|
|
||||||
|
Common::MemoryReadStream bufferstream(buffer, size);
|
||||||
|
|
||||||
|
bufferstream.read(&_fontHeader, sizeof(_fontHeader));
|
||||||
|
|
||||||
|
// tests for the magic values
|
||||||
|
if(_fontHeader._magic1 != FontHeader_Magic1 || _fontHeader._magic2 != FontHeader_Magic2 ||
|
||||||
|
_fontHeader._magic3 != FontHeader_Magic3) {
|
||||||
|
error("magic vars in the fontheader are corrupt\n"
|
||||||
|
"_magic1 = 0x%x, _magic2 = 0x%x, _magic3 = 0x%x",
|
||||||
|
_fontHeader._magic1, _fontHeader._magic2, _fontHeader._magic3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init all the pointers
|
||||||
|
_offsetTable = (uint16*)&buffer[bufferstream.pos()];
|
||||||
|
_charWidth = &buffer[_fontHeader._charWidthOffset];
|
||||||
|
_charHeight = (uint16*)&buffer[_fontHeader._charHeightOffset];
|
||||||
|
_charBits = &buffer[_fontHeader._charBitsOffset];
|
||||||
|
|
||||||
|
// now prerender =)
|
||||||
|
preRenderAllChars(bufferstream.pos());
|
||||||
|
|
||||||
|
// This value seems to be a version or language variable
|
||||||
|
// Known Values
|
||||||
|
// ------------
|
||||||
|
// Russian Floppy: 0x1010
|
||||||
|
// German Floppy and English CD: 0x1011
|
||||||
|
// Kyrandia 2 should be 0x1012
|
||||||
|
debug("_version = 0x%x", _fontHeader._version);
|
||||||
|
|
||||||
|
delete [] _buffer;
|
||||||
|
_buffer = 0;
|
||||||
|
_offsetTable = 0;
|
||||||
|
_charHeight = 0;
|
||||||
|
_charWidth = 0;
|
||||||
|
_charBits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Font::~Font() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 Font::getStringWidth(const char* string, char terminator) {
|
||||||
|
uint32 strsize;
|
||||||
|
|
||||||
|
for (strsize = 0; string[strsize] != terminator; ++strsize)
|
||||||
|
;
|
||||||
|
|
||||||
|
uint32 stringwidth = 0;
|
||||||
|
|
||||||
|
for (uint32 pos = 0; pos < strsize; ++pos) {
|
||||||
|
stringwidth += _preRenderedChars[string[pos]].width;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8* Font::getChar(char c, uint8* width, uint8* height, uint8* heightadd) {
|
||||||
|
PreRenderedChar& c_ = _preRenderedChars[c];
|
||||||
|
|
||||||
|
*width = c_.width;
|
||||||
|
*height = c_.height;
|
||||||
|
*heightadd = c_.heightadd;
|
||||||
|
|
||||||
|
return c_.c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// splits up the String in a word
|
||||||
|
const char* Font::getNextWord(const char* string, uint32* size) {
|
||||||
|
uint32 startpos = 0;
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
// gets start of the word
|
||||||
|
for (; string[startpos] == ' '; ++startpos)
|
||||||
|
;
|
||||||
|
|
||||||
|
// not counting size
|
||||||
|
for (*size = 0; string[startpos + *size] != ' ' && string[startpos + *size] != '\0'; ++(*size))
|
||||||
|
;
|
||||||
|
|
||||||
|
++(*size);
|
||||||
|
|
||||||
|
return &string[startpos];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move this to Font declaration?
|
||||||
|
struct WordChunk {
|
||||||
|
const char* _string;
|
||||||
|
uint32 _size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Font::drawStringToPlane(const char* string,
|
||||||
|
uint8* plane, uint16 planewidth, uint16 planeheight,
|
||||||
|
uint16 x, uint16 y, uint8 color) {
|
||||||
|
|
||||||
|
// lets do it word after word
|
||||||
|
Common::Array<WordChunk> words;
|
||||||
|
|
||||||
|
uint32 lastPos = 0;
|
||||||
|
uint32 lastSize = 0;
|
||||||
|
uint32 strlgt = strlen(string);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
WordChunk newchunk;
|
||||||
|
newchunk._string = getNextWord(&string[lastPos], &lastSize);
|
||||||
|
newchunk._size = lastSize;
|
||||||
|
|
||||||
|
lastPos += lastSize;
|
||||||
|
|
||||||
|
words.push_back(newchunk);
|
||||||
|
|
||||||
|
if (lastPos >= strlgt)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 current_x = x, current_y = y;
|
||||||
|
uint8 heighest = 0;
|
||||||
|
|
||||||
|
const uint8* src = 0;
|
||||||
|
uint8 width = 0, height = 0, heightadd = 0;
|
||||||
|
|
||||||
|
// now the have alle of these words
|
||||||
|
for (uint32 tmp = 0; tmp < words.size(); ++tmp) {
|
||||||
|
lastSize = getStringWidth(words[tmp]._string, ' ');
|
||||||
|
|
||||||
|
// adjust x position
|
||||||
|
if (current_x + lastSize >= planewidth) {
|
||||||
|
// hmm lets move it a bit to the left
|
||||||
|
if (current_x == x && (int16)planewidth - (int16)lastSize >= 0) {
|
||||||
|
current_x = planewidth - lastSize;
|
||||||
|
} else {
|
||||||
|
current_x = x;
|
||||||
|
if (heighest)
|
||||||
|
current_y += heighest + 2;
|
||||||
|
else // now we are using just the fist char :)
|
||||||
|
current_y += _preRenderedChars[words[tmp]._string[0]].height;
|
||||||
|
heighest = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: maybe test if current_y >= planeheight ?
|
||||||
|
|
||||||
|
// output word :)
|
||||||
|
for (lastPos = 0; lastPos < words[tmp]._size; ++lastPos) {
|
||||||
|
if (words[tmp]._string[lastPos] == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
// gets our char :)
|
||||||
|
src = getChar(words[tmp]._string[lastPos], &width, &height, &heightadd);
|
||||||
|
|
||||||
|
// lets draw our char
|
||||||
|
drawCharToPlane(src, color, width, height, plane, planewidth, planeheight, current_x, current_y + heightadd);
|
||||||
|
|
||||||
|
current_x += width;
|
||||||
|
heighest = MAX(heighest, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::drawCharToPlane(const uint8* c, uint8 color, uint8 width, uint8 height,
|
||||||
|
uint8* plane, uint16 planewidth, uint16 planeheight, uint16 x, uint16 y) {
|
||||||
|
const uint8* src = c;
|
||||||
|
|
||||||
|
// blit them to the screen
|
||||||
|
for (uint8 yadd = 0; yadd < height; ++yadd) {
|
||||||
|
for (uint8 xadd = 0; xadd < width; ++xadd) {
|
||||||
|
switch(*src) {
|
||||||
|
case 1:
|
||||||
|
plane[(y + yadd) * planewidth + x + xadd] = color;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
plane[(y + yadd) * planewidth + x + xadd] = 14;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
plane[(y + yadd) * planewidth + x + xadd] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// nothing to do now
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
++src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::preRenderAllChars(uint16 offsetTableOffset) {
|
||||||
|
uint16 startOffset = _offsetTable[0];
|
||||||
|
uint16 currentOffset = offsetTableOffset;
|
||||||
|
uint8 currentChar = 0;
|
||||||
|
|
||||||
|
for (; currentOffset < startOffset; ++currentChar, currentOffset += sizeof(uint16)) {
|
||||||
|
// lets prerender the char :)
|
||||||
|
|
||||||
|
PreRenderedChar newChar;
|
||||||
|
|
||||||
|
newChar.c = new uint8[(_charHeight[currentChar] >> 8) * _charWidth[currentChar]];
|
||||||
|
assert(newChar.c);
|
||||||
|
memset(newChar.c, 0, sizeof(uint8) * (_charHeight[currentChar] >> 8) * _charWidth[currentChar]);
|
||||||
|
newChar.height = (_charHeight[currentChar] >> 8);
|
||||||
|
newChar.width = _charWidth[currentChar];
|
||||||
|
newChar.heightadd = _charHeight[currentChar] & 0xFF;
|
||||||
|
|
||||||
|
uint8* src = _buffer + _offsetTable[currentChar];
|
||||||
|
uint8* dst = &newChar.c[0];
|
||||||
|
uint8 index = 0;
|
||||||
|
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
static char filename[32] = { 0 };
|
||||||
|
sprintf(filename, "dumps/char%d.dmp", currentChar);
|
||||||
|
FILE* dump = fopen(filename, "w+");
|
||||||
|
assert(dump);
|
||||||
|
|
||||||
|
fprintf(dump, "This should be a '%c'\n", currentChar);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// prerender the char
|
||||||
|
for (uint8 yadd = 0; yadd < newChar.height; ++yadd) {
|
||||||
|
for (uint8 xadd = 0; xadd < newChar.width; ++xadd) {
|
||||||
|
if (xadd % 2) {
|
||||||
|
index = ((*src) & 0xF0) >> 4;
|
||||||
|
++src;
|
||||||
|
} else {
|
||||||
|
index = (*src) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(index) {
|
||||||
|
case 1:
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "#");
|
||||||
|
#endif
|
||||||
|
dst[yadd * newChar.width + xadd] = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "$");
|
||||||
|
#endif
|
||||||
|
dst[yadd * newChar.width + xadd] = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "§");
|
||||||
|
#endif
|
||||||
|
dst[yadd * newChar.width + xadd] = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "%d", index);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newChar.width % 2) {
|
||||||
|
++src;
|
||||||
|
}
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DUMP_FILES
|
||||||
|
fprintf(dump, "\nThis is the created map:\n");
|
||||||
|
// now print the whole thing again
|
||||||
|
for (uint8 yadd = 0; yadd < newChar.height; ++yadd) {
|
||||||
|
for (uint8 xadd = 0; xadd < newChar.width; ++xadd) {
|
||||||
|
fprintf(dump, "%d", dst[yadd * newChar.width + xadd]);
|
||||||
|
}
|
||||||
|
fprintf(dump, "\n");
|
||||||
|
}
|
||||||
|
fclose(dump);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_preRenderedChars[currentChar] = newChar;
|
||||||
|
|
||||||
|
if (currentChar == 255) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
140
kyra/kyra.cpp
140
kyra/kyra.cpp
|
@ -1,5 +1,5 @@
|
||||||
/* ScummVM - Scumm Interpreter
|
/* ScummVM - Kyrandia Interpreter
|
||||||
* Copyright (C) 2003 The ScummVM project
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
|
@ -28,35 +28,58 @@
|
||||||
#include "sound/mixer.h"
|
#include "sound/mixer.h"
|
||||||
#include "common/file.h"
|
#include "common/file.h"
|
||||||
#include "common/config-manager.h"
|
#include "common/config-manager.h"
|
||||||
#include "kyra.h"
|
|
||||||
|
|
||||||
static const GameSettings kyra_setting =
|
#include "kyra.h"
|
||||||
{ "kyra", "Legend of Kyrandia", 0 };
|
#include "resource.h"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
struct KyraGameSettings {
|
||||||
|
const char *name;
|
||||||
|
const char *description;
|
||||||
|
uint32 features;
|
||||||
|
const char *detectName;
|
||||||
|
GameSettings toGameSettings() const {
|
||||||
|
GameSettings dummy = { name, description, features };
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const KyraGameSettings kyra_settings[] = {
|
||||||
|
{"kyra1cd", "Legend of Kyrandia (CD)", GF_TALKIE & GF_KYRA1, "CHAPTER1.VRM"},
|
||||||
|
{"kyra1", "Legend of Kyrandia (Floppy)", GF_FLOPPY & GF_KYRA1, "INTRO.SND"},
|
||||||
|
{ 0, 0, 0, 0}
|
||||||
|
};
|
||||||
|
|
||||||
GameList Engine_KYRA_gameList() {
|
GameList Engine_KYRA_gameList() {
|
||||||
GameList games;
|
GameList games;
|
||||||
|
const KyraGameSettings *g = kyra_settings;
|
||||||
|
|
||||||
|
while (g->name) {
|
||||||
|
games.push_back(g->toGameSettings());
|
||||||
|
g++;
|
||||||
|
}
|
||||||
|
|
||||||
games.push_back(kyra_setting);
|
|
||||||
return games;
|
return games;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Improve this :)
|
|
||||||
DetectedGameList Engine_KYRA_detectGames(const FSList &fslist) {
|
DetectedGameList Engine_KYRA_detectGames(const FSList &fslist) {
|
||||||
|
const KyraGameSettings *game;
|
||||||
DetectedGameList detectedGames;
|
DetectedGameList detectedGames;
|
||||||
File test_file;
|
|
||||||
|
|
||||||
// Iterate over all files in the given directory
|
for (game = kyra_settings; game->name; ++game) {
|
||||||
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
|
if (game->detectName == NULL)
|
||||||
const char *name = file->displayName().c_str();
|
continue;
|
||||||
if ((0 == scumm_stricmp("chapter1.vrm", name)) ||
|
|
||||||
(0 == scumm_stricmp("chapter5.vrm", name))) {
|
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||||
detectedGames.push_back(kyra_setting);
|
const char *name = file->displayName().c_str();
|
||||||
printf("Detecting Kyra...\n");
|
if ((!scumm_stricmp(game->detectName, name))) {
|
||||||
break;
|
detectedGames.push_back(game->toGameSettings());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return detectedGames;
|
return detectedGames;
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine *Engine_KYRA_create(GameDetector *detector, OSystem *syst) {
|
Engine *Engine_KYRA_create(GameDetector *detector, OSystem *syst) {
|
||||||
|
@ -78,11 +101,37 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *syst)
|
||||||
|
|
||||||
//getGameDataPath();
|
//getGameDataPath();
|
||||||
|
|
||||||
// Initialize backend
|
// Initialize backen
|
||||||
syst->initSize(320, 240);
|
syst->initSize(320, 200);
|
||||||
|
_screen = new uint8[320*200];
|
||||||
|
memset((void*)_screen, 0, sizeof(_screen));
|
||||||
|
|
||||||
|
_resMgr = new Resourcemanager(this, getGameDataPath());
|
||||||
|
assert(_resMgr);
|
||||||
|
|
||||||
|
setCurrentPalette(_resMgr->loadPalette("PALETTE.COL"));
|
||||||
|
|
||||||
|
// loads the 2 cursors
|
||||||
|
_mouse = _resMgr->loadImage("MOUSE.CPS"); //startup.pak
|
||||||
|
_items = _resMgr->loadImage("ITEMS.CPS");
|
||||||
|
|
||||||
|
// loads the Font
|
||||||
|
_font = _resMgr->loadFont("8FAT.FNT");
|
||||||
|
printf("loading scripts\n");
|
||||||
|
// loads out scripts
|
||||||
|
_npcScript = _resMgr->loadScript("_NPC.EMC");
|
||||||
|
_currentScript = _resMgr->loadScript("_STARTUP.EMC");
|
||||||
|
printf("done\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KyraEngine::~KyraEngine() {
|
KyraEngine::~KyraEngine() {
|
||||||
|
delete _resMgr;
|
||||||
|
delete _mouse;
|
||||||
|
delete _items;
|
||||||
|
delete _npcScript;
|
||||||
|
delete _currentScript;
|
||||||
|
delete _font;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KyraEngine::errorString(const char *buf1, char *buf2) {
|
void KyraEngine::errorString(const char *buf1, char *buf2) {
|
||||||
|
@ -91,10 +140,61 @@ void KyraEngine::errorString(const char *buf1, char *buf2) {
|
||||||
|
|
||||||
void KyraEngine::go() {
|
void KyraEngine::go() {
|
||||||
warning("Kyrandia Engine ::go()");
|
warning("Kyrandia Engine ::go()");
|
||||||
|
// starts the init script
|
||||||
|
if (!_currentScript->startScript(kSetupScene)) {
|
||||||
|
error("couldn't init '_STARTUP.EMC' script");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_currentScript->contScript() != kScriptStopped) {
|
||||||
|
if (_currentScript->state() == kScriptError) {
|
||||||
|
error("couldn't run script");
|
||||||
|
} else {
|
||||||
|
warning("init script returned: %d", _currentScript->state());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
OSystem::Event event;
|
||||||
|
//if (_debugger->isAttached())
|
||||||
|
// _debugger->onFrame();
|
||||||
|
|
||||||
|
updateScreen();
|
||||||
|
while (g_system->pollEvent(event)) {
|
||||||
|
switch (event.event_code) {
|
||||||
|
case OSystem::EVENT_QUIT:
|
||||||
|
g_system->quit();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_system->delayMillis(10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KyraEngine::shutdown() {
|
void KyraEngine::shutdown() {
|
||||||
_system->quit();
|
_system->quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KyraEngine::updateScreen(void) {
|
||||||
|
_system->copyRectToScreen(_screen, 320, 0, 0, 320, 240);
|
||||||
|
_system->updateScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KyraEngine::setCurrentPalette(Palette* pal, bool delNextTime) {
|
||||||
|
// if (_delPalNextTime)
|
||||||
|
// delete _currentPal;
|
||||||
|
|
||||||
|
// _delPalNextTime = delNextTime;
|
||||||
|
|
||||||
|
// _currentPal = pal;
|
||||||
|
|
||||||
|
if (pal->getData()) {
|
||||||
|
_system->setPalette(pal->getData(), 0, 256);
|
||||||
|
} else {
|
||||||
|
warning("palette contains no data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace KYRA
|
} // End of namespace KYRA
|
||||||
|
|
||||||
|
|
35
kyra/kyra.h
35
kyra/kyra.h
|
@ -22,26 +22,49 @@
|
||||||
#ifndef KYRA_H
|
#ifndef KYRA_H
|
||||||
#define KYRA_H
|
#define KYRA_H
|
||||||
|
|
||||||
#include "common/scummsys.h"
|
//#include "common/scummsys.h"
|
||||||
#include "base/engine.h"
|
#include "base/engine.h"
|
||||||
#include "base/gameDetector.h"
|
#include "base/gameDetector.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GF_FLOPPY = 1 << 0,
|
||||||
|
GF_TALKIE = 1 << 1,
|
||||||
|
GF_KYRA1 = 1 << 2,
|
||||||
|
GF_KYRA2 = 1 << 3
|
||||||
|
};
|
||||||
|
|
||||||
namespace Kyra {
|
namespace Kyra {
|
||||||
|
class Resourcemanager;
|
||||||
|
class CPSImage;
|
||||||
|
class Font;
|
||||||
|
class Palette;
|
||||||
|
class VMContext;
|
||||||
|
|
||||||
class KyraEngine : public Engine {
|
class KyraEngine : public Engine {
|
||||||
|
public:
|
||||||
|
KyraEngine(GameDetector *detector, OSystem *syst);
|
||||||
|
~KyraEngine();
|
||||||
void errorString( const char *buf_input, char *buf_output);
|
void errorString( const char *buf_input, char *buf_output);
|
||||||
|
|
||||||
|
void updateScreen(void);
|
||||||
|
void setCurrentPalette(Palette* pal, bool delNextTime = true);
|
||||||
|
|
||||||
|
Resourcemanager* resManager(void) { return _resMgr; }
|
||||||
|
// MidiDriver* midiDriver(void) { return _midiDriver; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void go();
|
void go();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
Resourcemanager* _resMgr;
|
||||||
|
uint8 *_screen;
|
||||||
|
|
||||||
public:
|
Font* _font;
|
||||||
|
CPSImage* _mouse;
|
||||||
KyraEngine(GameDetector *detector, OSystem *syst);
|
CPSImage* _items;
|
||||||
virtual ~KyraEngine();
|
|
||||||
|
|
||||||
|
VMContext* _currentScript; // our current script
|
||||||
|
VMContext* _npcScript; // script from NPCs
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of namespace Kyra
|
} // End of namespace Kyra
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
MODULE := kyra
|
MODULE := kyra
|
||||||
|
|
||||||
MODULE_OBJS = \
|
MODULE_OBJS = \
|
||||||
kyra/kyra.o
|
kyra/kyra.o kyra/codecs.o kyra/script.o kyra/script_v1.o kyra/resource.o \
|
||||||
|
kyra/wsamovie.o kyra/palette.o kyra/cpsimage.o kyra/font.o
|
||||||
|
|
||||||
MODULE_DIRS += \
|
MODULE_DIRS += \
|
||||||
kyra
|
kyra
|
||||||
|
|
80
kyra/palette.cpp
Normal file
80
kyra/palette.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#include "common/stream.h"
|
||||||
|
#include "codecs.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
|
||||||
|
Palette::Palette(uint8* data, uint32 size) {
|
||||||
|
if (!data) {
|
||||||
|
error("resource created without data");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size != 768) {
|
||||||
|
Common::MemoryReadStream datastream(data, size);
|
||||||
|
|
||||||
|
datastream.readSint32LE();
|
||||||
|
int imageSize = datastream.readSint16LE();
|
||||||
|
|
||||||
|
if (imageSize != 768) {
|
||||||
|
error("decompresed palette is not 768 byte long!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// lets uncompress this palette :)
|
||||||
|
_palette = new uint8[imageSize];
|
||||||
|
assert(_palette);
|
||||||
|
|
||||||
|
// made decompression
|
||||||
|
if (Compression::decode80(data + 10, _palette) != 768) {
|
||||||
|
error("decode80 decompressesize != 768 bytes");
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
data = _palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
// hmm.. common/system.h Docu is wrong or SDL Backend has a bug :)
|
||||||
|
// a palette should have this order:
|
||||||
|
// R1-G1-B1-A1-R2-G2-B2-A2-...
|
||||||
|
// so we need 4 bytes per color
|
||||||
|
_palette = new uint8[256 * 4];
|
||||||
|
|
||||||
|
uint8* currentpossrc = &data[0];
|
||||||
|
uint8* currentposdst = &_palette[0];
|
||||||
|
|
||||||
|
// creates the original pallette (only first 6 bits are used)
|
||||||
|
for (uint32 i = 0; i < 256; i++) {
|
||||||
|
currentposdst[0] = currentpossrc[0] << 2;
|
||||||
|
currentposdst[1] = currentpossrc[1] << 2;
|
||||||
|
currentposdst[2] = currentpossrc[2] << 2;
|
||||||
|
currentpossrc += 3;
|
||||||
|
currentposdst += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
254
kyra/resource.cpp
Normal file
254
kyra/resource.cpp
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "wsamovie.h"
|
||||||
|
|
||||||
|
#include "common/file.h"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
Resourcemanager::Resourcemanager(KyraEngine* engine, const char* gamedir) {
|
||||||
|
_gameDir = gamedir;
|
||||||
|
|
||||||
|
// prefetches all PAK Files
|
||||||
|
|
||||||
|
// ugly a hardcoded list
|
||||||
|
// TODO: use the FS Backend to get all .PAK Files and load them
|
||||||
|
static const char* kyraFilelist[] = {
|
||||||
|
"A_E.PAK", "DAT.PAK", "F_L.PAK", "MAP_5.PAK", "MSC.PAK", "M_S.PAK",
|
||||||
|
"S_Z.PAK", "WSA1.PAK", "WSA2.PAK", "WSA3.PAK", "WSA4.PAK", "WSA5.PAK",
|
||||||
|
"WSA6.PAK", "startup.pak", "intro1.pak", 0
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32 tmp = 0; kyraFilelist[tmp]; ++tmp) {
|
||||||
|
|
||||||
|
// prefetch file
|
||||||
|
PAKFile* file = new PAKFile(getPath() + kyraFilelist[tmp]);
|
||||||
|
assert(file);
|
||||||
|
|
||||||
|
if (file->isValid())
|
||||||
|
_pakfiles.push_back(file);
|
||||||
|
else
|
||||||
|
warning("couldn't load file '%s' correctly", kyraFilelist[tmp]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Resourcemanager::~Resourcemanager() {
|
||||||
|
Common::List<PAKFile*>::iterator start = _pakfiles.begin();
|
||||||
|
|
||||||
|
for (;start != _pakfiles.end(); ++start) {
|
||||||
|
delete *start;
|
||||||
|
*start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* Resourcemanager::fileData(const char* file, uint32* size) {
|
||||||
|
uint8* buffer = 0;
|
||||||
|
|
||||||
|
debug("looking for file '%s'", file);
|
||||||
|
|
||||||
|
File file_;
|
||||||
|
|
||||||
|
// test to open it in the main dir
|
||||||
|
if (file_.open((getPath() + file).c_str())) {
|
||||||
|
|
||||||
|
*size = file_.size();
|
||||||
|
|
||||||
|
buffer = new uint8[*size];
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
file_.read(buffer, *size);
|
||||||
|
|
||||||
|
file_.close();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// opens the file in a PAK File
|
||||||
|
Common::List<PAKFile*>::iterator start = _pakfiles.begin();
|
||||||
|
|
||||||
|
for (;start != _pakfiles.end(); ++start) {
|
||||||
|
*size = (*start)->getFileSize(file);
|
||||||
|
|
||||||
|
if (!*size)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer = new uint8[*size];
|
||||||
|
assert(buffer);
|
||||||
|
|
||||||
|
// creates a copy of the file
|
||||||
|
memcpy(buffer, (*start)->getFile(file), *size);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buffer || !(*size)) {
|
||||||
|
warning("couldn't find file '%s'", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Palette* Resourcemanager::loadPalette(const char* file) {
|
||||||
|
uint32 size = 0;
|
||||||
|
uint8* buffer = 0;
|
||||||
|
buffer = fileData(file, &size);
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
return new Palette(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
CPSImage* Resourcemanager::loadImage(const char* file) {
|
||||||
|
uint32 size = 0;
|
||||||
|
uint8* buffer = 0;
|
||||||
|
buffer = fileData(file, &size);
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
return new CPSImage(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Font* Resourcemanager::loadFont(const char* file) {
|
||||||
|
uint32 size = 0;
|
||||||
|
uint8* buffer = 0;
|
||||||
|
buffer = fileData(file, &size);
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
return new Font(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Movie* Resourcemanager::loadMovie(const char* file) {
|
||||||
|
// TODO: we have to check the Extenion to create the right movie
|
||||||
|
uint32 size = 0;
|
||||||
|
uint8* buffer = 0;
|
||||||
|
buffer = fileData(file, &size);
|
||||||
|
if (!buffer)
|
||||||
|
return 0;
|
||||||
|
return new WSAMovieV1(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMContext* Resourcemanager::loadScript(const char* file) {
|
||||||
|
VMContext* context = new VMContext(_engine);
|
||||||
|
context->loadScript(file);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::String Resourcemanager::getPath(void) {
|
||||||
|
assert(_gameDir);
|
||||||
|
int32 len = strlen(_gameDir);
|
||||||
|
|
||||||
|
if(len < 1)
|
||||||
|
error("no valid gamedir");
|
||||||
|
|
||||||
|
// tests for an path seperator at the end
|
||||||
|
if (_gameDir[len - 1] == '\\') {
|
||||||
|
return string(_gameDir);
|
||||||
|
} else if (_gameDir[len - 1 ] == '/') {
|
||||||
|
return string(_gameDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// creates a path seperator at the end
|
||||||
|
// we are always using the path seperator from the system
|
||||||
|
// even if Windows shoudl accept '/'
|
||||||
|
#ifdef WIN32
|
||||||
|
return string(_gameDir) + "\\";
|
||||||
|
#else
|
||||||
|
return string(_gameDir) + "/";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////
|
||||||
|
// Pak file manager
|
||||||
|
#define PAKFile_Iterate Common::List<PakChunk*>::iterator start=_files.begin();start != _files.end(); ++start
|
||||||
|
|
||||||
|
PAKFile::PAKFile(const Common::String& file) {
|
||||||
|
File pakfile;
|
||||||
|
|
||||||
|
if (!pakfile.open(file.c_str())) {
|
||||||
|
warning("PAKFile couldn't open: '%s'", file.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 filesize = pakfile.size();
|
||||||
|
_buffer = new uint8[filesize];
|
||||||
|
assert(_buffer);
|
||||||
|
|
||||||
|
pakfile.read(_buffer, filesize);
|
||||||
|
pakfile.close();
|
||||||
|
|
||||||
|
// works with the file
|
||||||
|
uint32 pos = 0, startoffset = 0, endoffset = 0;
|
||||||
|
|
||||||
|
startoffset = *(reinterpret_cast<uint32*>((_buffer + pos)));
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
while (pos < filesize) {
|
||||||
|
PakChunk* chunk = new PakChunk;
|
||||||
|
assert(chunk);
|
||||||
|
|
||||||
|
// saves the name
|
||||||
|
chunk->_name = reinterpret_cast<const char*>(_buffer + pos);
|
||||||
|
pos += strlen(chunk->_name) + 1;
|
||||||
|
if(!chunk->_name)
|
||||||
|
break;
|
||||||
|
|
||||||
|
endoffset = *(reinterpret_cast<uint32*>((_buffer + pos)));
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
chunk->_data = _buffer + startoffset;
|
||||||
|
chunk->_size = endoffset - startoffset;
|
||||||
|
|
||||||
|
startoffset = endoffset;
|
||||||
|
|
||||||
|
_files.push_back(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PAKFile::~PAKFile() {
|
||||||
|
delete [] _buffer;
|
||||||
|
_buffer = 0;
|
||||||
|
|
||||||
|
for (PAKFile_Iterate) {
|
||||||
|
delete *start;
|
||||||
|
*start = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8* PAKFile::getFile(const char* file) {
|
||||||
|
for (PAKFile_Iterate) {
|
||||||
|
if (!scumm_stricmp((*start)->_name, file))
|
||||||
|
return (*start)->_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 PAKFile::getFileSize(const char* file) {
|
||||||
|
for (PAKFile_Iterate) {
|
||||||
|
if (!scumm_stricmp((*start)->_name, file))
|
||||||
|
return (*start)->_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
201
kyra/resource.h
Normal file
201
kyra/resource.h
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RESOURCE_H
|
||||||
|
#define RESOURCE_H
|
||||||
|
|
||||||
|
#include "common/stdafx.h"
|
||||||
|
#include "common/scummsys.h"
|
||||||
|
#include "common/str.h"
|
||||||
|
#include "common/list.h"
|
||||||
|
#include "common/map.h"
|
||||||
|
|
||||||
|
#include "kyra.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
|
||||||
|
// standard Package format for Kyrandia games
|
||||||
|
class PAKFile {
|
||||||
|
|
||||||
|
struct PakChunk {
|
||||||
|
const char* _name;
|
||||||
|
const uint8* _data;
|
||||||
|
uint32 _size;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PAKFile(const Common::String& file);
|
||||||
|
~PAKFile();
|
||||||
|
|
||||||
|
const uint8* getFile(const char* file);
|
||||||
|
uint32 getFileSize(const char* file);
|
||||||
|
|
||||||
|
bool isValid(void) { return (_buffer != 0); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8* _buffer; // the whole file
|
||||||
|
Common::List<PakChunk*> _files; // the entries
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// some resource types
|
||||||
|
class Palette;
|
||||||
|
class CPSImage;
|
||||||
|
class Font;
|
||||||
|
class Movie;
|
||||||
|
class VMContext;
|
||||||
|
|
||||||
|
// out resource manager
|
||||||
|
class Resourcemanager {
|
||||||
|
typedef Common::String string;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Resourcemanager(KyraEngine* engine, const char* gamedir);
|
||||||
|
virtual ~Resourcemanager();
|
||||||
|
|
||||||
|
uint8* fileData(const char* file, uint32* size);
|
||||||
|
|
||||||
|
Palette* loadPalette(const char* file);
|
||||||
|
CPSImage* loadImage(const char* file);
|
||||||
|
Font* loadFont(const char* file);
|
||||||
|
Movie* loadMovie(const char* file);
|
||||||
|
VMContext* loadScript(const char* file);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
KyraEngine* _engine;
|
||||||
|
|
||||||
|
string getPath(void);
|
||||||
|
const char* _gameDir;
|
||||||
|
Common::List<PAKFile*> _pakfiles;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class Palette {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Palette(uint8* data, uint32 size);
|
||||||
|
~Palette() { delete [] _palette; }
|
||||||
|
|
||||||
|
uint8* getData(void) { return _palette; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint8* _palette;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class CPSImage {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CPSImage(uint8* buffer, uint32 size);
|
||||||
|
~CPSImage();
|
||||||
|
|
||||||
|
Palette* palette(void) { return _ownPalette; }
|
||||||
|
bool hasPalette(void) { return (_ownPalette != 0); }
|
||||||
|
|
||||||
|
// if col == -1 then no transparany
|
||||||
|
void setTransparencyColor(int16 col) { _transparency = col; }
|
||||||
|
|
||||||
|
void drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y);
|
||||||
|
void drawToPlane(uint8* plane, uint16 planepitch, uint16 planeheight, uint16 x, uint16 y,
|
||||||
|
uint16 srcx, uint16 srcy, uint16 srcwidth, uint16 srcheight);
|
||||||
|
|
||||||
|
// only for testing :)
|
||||||
|
uint8 getColor(uint16 x, uint16 y) { return _image[y * _width + x]; }
|
||||||
|
|
||||||
|
uint8& operator[](uint16 index) { if(index > _width * _height) return _image[0]; return _image[index]; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
struct CPSHeader {
|
||||||
|
uint16 _filesize;
|
||||||
|
uint16 _format;
|
||||||
|
uint16 _imagesize;
|
||||||
|
uint32 _pal;
|
||||||
|
} _cpsHeader;
|
||||||
|
|
||||||
|
Palette* _ownPalette;
|
||||||
|
uint8* _image;
|
||||||
|
|
||||||
|
uint16 _width, _height;
|
||||||
|
int16 _transparency;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Font {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Font(uint8* buffer, uint32 size);
|
||||||
|
~Font();
|
||||||
|
|
||||||
|
uint32 getStringWidth(const char* string, char terminator = '\0');
|
||||||
|
void drawStringToPlane(const char* string,
|
||||||
|
uint8* plane, uint16 planewidth, uint16 planeheight,
|
||||||
|
uint16 x, uint16 y, uint8 color);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void drawCharToPlane(const uint8* c, uint8 color, uint8 width, uint8 height,
|
||||||
|
uint8* plane, uint16 planewidth, uint16 planeheight, uint16 x, uint16 y);
|
||||||
|
const uint8* getChar(char c, uint8* width, uint8* height, uint8* heightadd);
|
||||||
|
const char* getNextWord(const char* string, uint32* size);
|
||||||
|
|
||||||
|
void preRenderAllChars(uint16 offsetTableOffset);
|
||||||
|
|
||||||
|
uint8* _buffer;
|
||||||
|
|
||||||
|
uint16* _offsetTable;
|
||||||
|
uint8* _charWidth;
|
||||||
|
uint16* _charHeight;
|
||||||
|
uint8* _charBits;
|
||||||
|
|
||||||
|
// the chars I call 'prerendered' aren't really prerendered
|
||||||
|
// they are only 'decoded'
|
||||||
|
struct PreRenderedChar {
|
||||||
|
uint8* c;
|
||||||
|
uint8 width, height, heightadd;
|
||||||
|
};
|
||||||
|
|
||||||
|
Common::Map<uint8, PreRenderedChar> _preRenderedChars; // our prerendered chars :)
|
||||||
|
|
||||||
|
// INFO:
|
||||||
|
// _magic1 = 0x0500
|
||||||
|
// _magic2 = 0x000e
|
||||||
|
// _magic3 = 0x0014
|
||||||
|
#pragma START_PACK_STRUCTS
|
||||||
|
struct FontHeader {
|
||||||
|
uint16 _size;
|
||||||
|
uint16 _magic1, _magic2, _magic3;
|
||||||
|
uint16 _charWidthOffset, _charBitsOffset, _charHeightOffset;
|
||||||
|
uint16 _version;
|
||||||
|
uint16 _countChars;
|
||||||
|
uint8 _width, _height;
|
||||||
|
} GCC_PACK _fontHeader;
|
||||||
|
#pragma END_PACK_STRUCTS
|
||||||
|
};
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
||||||
|
#endif
|
506
kyra/script.cpp
Normal file
506
kyra/script.cpp
Normal file
|
@ -0,0 +1,506 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "kyra.h"
|
||||||
|
#include "script.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#include "common/stream.h"
|
||||||
|
|
||||||
|
#define COMMAND(x) { &VMContext::x, #x }
|
||||||
|
#define OPCODE(x) { &VMContext::x, #x }
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
VMContext::VMContext(KyraEngine* engine) {
|
||||||
|
_engine = engine;
|
||||||
|
|
||||||
|
// now we create a list of all Command/Opcode procs and so
|
||||||
|
static CommandEntry commandProcs[] = {
|
||||||
|
// 0
|
||||||
|
COMMAND(c1_goToLine),
|
||||||
|
COMMAND(c1_setReturn),
|
||||||
|
COMMAND(c1_pushRetRec),
|
||||||
|
COMMAND(c1_push),
|
||||||
|
COMMAND(c1_push),
|
||||||
|
COMMAND(c1_pushVar),
|
||||||
|
COMMAND(c1_pushFrameNeg),
|
||||||
|
COMMAND(c1_pushFramePos),
|
||||||
|
COMMAND(c1_popRetRec),
|
||||||
|
COMMAND(c1_popVar),
|
||||||
|
|
||||||
|
// 10
|
||||||
|
COMMAND(c1_popFrameNeg),
|
||||||
|
COMMAND(c1_popFramePos),
|
||||||
|
COMMAND(c1_addToSP),
|
||||||
|
COMMAND(c1_subFromSP),
|
||||||
|
COMMAND(c1_execOpcode),
|
||||||
|
COMMAND(c1_ifNotGoTo),
|
||||||
|
COMMAND(c1_negate),
|
||||||
|
COMMAND(c1_evaluate),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 20
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 30
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 40
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 50
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 60
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 70
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 80
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 90
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 100
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 110
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 120
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 130
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 140
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 150
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 160
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 170
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 180
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 190
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 200
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 210
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 220
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 230
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 240
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
|
||||||
|
// 250
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
COMMAND(c1_unknownCommand),
|
||||||
|
{ 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
_scriptFile = NULL;
|
||||||
|
_scriptFileSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::loadScript(const char* file) {
|
||||||
|
printf("a\n");
|
||||||
|
if (_scriptFile) {
|
||||||
|
delete [] _scriptFile;
|
||||||
|
_scriptFileSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug("--------------");
|
||||||
|
|
||||||
|
// loads the new file
|
||||||
|
_scriptFile = _engine->resManager()->fileData(file, &_scriptFileSize);
|
||||||
|
printf("c\n");
|
||||||
|
|
||||||
|
if (!_scriptFileSize || !_scriptFile) {
|
||||||
|
error("couldn't load script file '%s'", file);
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::MemoryReadStream script(_scriptFile, _scriptFileSize);
|
||||||
|
memset(_chunks, 0, sizeof(ScriptChunk) * kCountChunkTypes);
|
||||||
|
uint8 chunkName[sizeof("EMC2ORDR") + 1];
|
||||||
|
|
||||||
|
// so lets look for our chunks :)
|
||||||
|
while(true) {
|
||||||
|
if (script.eof()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// lets read only the first 4 chars
|
||||||
|
script.read(chunkName, sizeof(uint8) * 4);
|
||||||
|
chunkName[4] = '\0';
|
||||||
|
debug("chunk name(4 chars): '%s'", chunkName);
|
||||||
|
|
||||||
|
// check name of chunk
|
||||||
|
if (!scumm_stricmp((char*)chunkName, "FORM")) {
|
||||||
|
// FreeKyra swaps the size I only read it in BigEndian :)
|
||||||
|
_chunks[kForm]._size = script.readUint32BE();
|
||||||
|
debug("_chunks[kForm]._size = %d", _chunks[kForm]._size);
|
||||||
|
} else if (!scumm_stricmp((char*)chunkName, "TEXT")) {
|
||||||
|
uint32 text_size = script.readUint32BE();
|
||||||
|
text_size += text_size % 2 != 0 ? 1 : 0;
|
||||||
|
|
||||||
|
_chunks[kText]._data = _scriptFile + script.pos();
|
||||||
|
_chunks[kText]._size = READ_BE_UINT16(_chunks[kText]._data) >> 1;
|
||||||
|
_chunks[kText]._additional = _chunks[kText]._data + (_chunks[kText]._size << 1);
|
||||||
|
debug("_chunks[kText]._size = %d, real chunk size = %d", _chunks[kText]._size, text_size);
|
||||||
|
|
||||||
|
script.seek(script.pos() + text_size);
|
||||||
|
} else if (!scumm_stricmp((char*)chunkName, "DATA")) {
|
||||||
|
_chunks[kData]._size = script.readUint32BE();
|
||||||
|
_chunks[kData]._data = _scriptFile + script.pos();
|
||||||
|
debug("_chunks[kData]._size = %d", _chunks[kData]._size);
|
||||||
|
|
||||||
|
// mostly it will be the end of the file because all files should end with a 'DATA' chunk
|
||||||
|
script.seek(script.pos() + _chunks[kData]._size);
|
||||||
|
} else {
|
||||||
|
// read next 4 chars
|
||||||
|
script.read(&chunkName[4], sizeof(uint8) * 4);
|
||||||
|
chunkName[8] = '\0';
|
||||||
|
debug("chunk name(8 chars): '%s'", chunkName);
|
||||||
|
|
||||||
|
if (!scumm_stricmp((char*)chunkName, "EMC2ORDR")) {
|
||||||
|
_chunks[kEmc2Ordr]._size = script.readUint32BE() >> 1;
|
||||||
|
_chunks[kEmc2Ordr]._data = _scriptFile + script.pos();
|
||||||
|
debug("_chunks[kEmc2Ordr]._size = %d, real chunk size = %d", _chunks[kEmc2Ordr]._size, _chunks[kEmc2Ordr]._size * 2);
|
||||||
|
|
||||||
|
script.seek(script.pos() + _chunks[kEmc2Ordr]._size * 2);
|
||||||
|
} else {
|
||||||
|
// any unkown chunk or problems with seeking through the file
|
||||||
|
error("unknown chunk");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// so file loaded
|
||||||
|
debug("--------------");
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 VMContext::param(int32 index) {
|
||||||
|
if (_stackPos - index + 1 >= 16 || _stackPos - index + 1 < 0)
|
||||||
|
return -0xFFFF;
|
||||||
|
return _stack[_stackPos - index + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* VMContext::stringAtIndex(int32 index) {
|
||||||
|
if (index < 0 || (uint32)index >= _chunks[kText]._size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (char*)(_chunks[kText]._additional + _chunks[kText]._data[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VMContext::startScript(int32 func) {
|
||||||
|
if ((uint32)func >= _chunks[kEmc2Ordr]._size || func < 0) {
|
||||||
|
debug("script doesn't support function %d", func);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_instructionPos = (READ_BE_UINT16(&_chunks[kEmc2Ordr]._data[func]) << 1) + 2;
|
||||||
|
_stackPos = 0;
|
||||||
|
_tempPos = 0;
|
||||||
|
_delay = 0;
|
||||||
|
_scriptState = kScriptRunning;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 VMContext::contScript(void) {
|
||||||
|
uint8* script_start = _chunks[kData]._data;
|
||||||
|
assert(script_start);
|
||||||
|
|
||||||
|
uint32 scriptStateAtStart = _scriptState;
|
||||||
|
|
||||||
|
// runs the script
|
||||||
|
while(true) {
|
||||||
|
if ((uint32)_instructionPos > _chunks[kData]._size) {
|
||||||
|
debug("_instructionPos( = %d) > _chunks[kData]._size( = %d)", _instructionPos, _chunks[kData]._size);
|
||||||
|
_error = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentCommand = *(script_start + _instructionPos++);
|
||||||
|
|
||||||
|
// gets out
|
||||||
|
if (_currentCommand & 0x80) {
|
||||||
|
_argument = ((_currentCommand & 0x0F) << 8) | *(script_start + _instructionPos++);
|
||||||
|
_currentCommand &= 0xF0;
|
||||||
|
} else if (_currentCommand & 0x40) {
|
||||||
|
_argument = *(script_start + _instructionPos++);
|
||||||
|
} else if (_currentCommand & 0x20) {
|
||||||
|
_instructionPos++;
|
||||||
|
|
||||||
|
uint16 tmp = *(uint16*)(script_start + _instructionPos);
|
||||||
|
tmp &= 0xFF7F;
|
||||||
|
|
||||||
|
_argument = READ_BE_UINT16(&tmp);
|
||||||
|
_instructionPos += 2;
|
||||||
|
} else {
|
||||||
|
debug("unknown way of getting the command");
|
||||||
|
}
|
||||||
|
|
||||||
|
_currentCommand &= 0x1f;
|
||||||
|
|
||||||
|
CommandProc currentProc = _commands[_currentCommand].proc;
|
||||||
|
(this->*currentProc)();
|
||||||
|
|
||||||
|
if (_error) {
|
||||||
|
_scriptState = kScriptError;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scriptStateAtStart != _scriptState) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _scriptState;
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
155
kyra/script.h
Normal file
155
kyra/script.h
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef VM_H
|
||||||
|
#define VM_H
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
// TODO:
|
||||||
|
// find out more script functions
|
||||||
|
enum ScriptFunc {
|
||||||
|
kSetupScene = 0,
|
||||||
|
kClickEvent = 1, // _registers[1] and _registers[2] are mouse x, y _registers[4] is action
|
||||||
|
kActorEvent = 2,
|
||||||
|
kEnterEvent = 4,
|
||||||
|
kExitEvent = 5,
|
||||||
|
kLoadResources = 7
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ScriptState {
|
||||||
|
kScriptStopped = 0,
|
||||||
|
kScriptRunning = 1,
|
||||||
|
kScriptWaiting = 2,
|
||||||
|
kScriptError = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
class VMContext {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
VMContext(KyraEngine* engine);
|
||||||
|
~VMContext() { delete [] _scriptFile; }
|
||||||
|
|
||||||
|
void loadScript(const char* file);
|
||||||
|
|
||||||
|
const char* stringAtIndex(int32 index);
|
||||||
|
|
||||||
|
// TODO: check for 'over'flow
|
||||||
|
void pushStack(int32 value) { _stack[_stackPos++] = value; }
|
||||||
|
void registerValue(int32 reg, int32 value) { _registers[reg] = value; }
|
||||||
|
int32 checkReg(int32 reg) { return _registers[reg]; }
|
||||||
|
|
||||||
|
uint32 state(void) { return _scriptState; }
|
||||||
|
|
||||||
|
bool startScript(int32 func);
|
||||||
|
uint32 contScript(void);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
KyraEngine* _engine;
|
||||||
|
uint8* _scriptFile;
|
||||||
|
uint32 _scriptFileSize;
|
||||||
|
|
||||||
|
uint32 _scriptState;
|
||||||
|
uint32 _delay;
|
||||||
|
|
||||||
|
int32 _registers[32]; // registers of the interpreter
|
||||||
|
int32 _stack[32]; // our stack
|
||||||
|
|
||||||
|
// TODO: check for 'under'flow
|
||||||
|
int32 popStack(void) { return _stack[_stackPos--]; }
|
||||||
|
int32& topStack(void) { return _stack[_stackPos]; }
|
||||||
|
|
||||||
|
uint32 _returnValue;
|
||||||
|
|
||||||
|
int32 _instructionPos;
|
||||||
|
int32 _stackPos;
|
||||||
|
int32 _tempPos;
|
||||||
|
|
||||||
|
// used by command & opcode procs
|
||||||
|
uint16 _argument;
|
||||||
|
uint8 _currentCommand;
|
||||||
|
uint32 _currentOpcode;
|
||||||
|
|
||||||
|
int32 param(int32 index);
|
||||||
|
const char* paramString(int32 index) { return stringAtIndex(param(index)); }
|
||||||
|
|
||||||
|
bool _error; // used by all command- and opcodefuncs
|
||||||
|
|
||||||
|
enum ScriptChunkTypes {
|
||||||
|
kForm = 0,
|
||||||
|
kEmc2Ordr = 1,
|
||||||
|
kText = 2,
|
||||||
|
kData = 3,
|
||||||
|
kCountChunkTypes
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ScriptChunk {
|
||||||
|
uint32 _size;
|
||||||
|
uint8* _data; // by TEXT used for count of texts, by EMC2ODRD it is used for a count of somewhat
|
||||||
|
uint8* _additional; // currently only used for TEXT
|
||||||
|
};
|
||||||
|
|
||||||
|
ScriptChunk _chunks[kCountChunkTypes];
|
||||||
|
|
||||||
|
typedef void (VMContext::*CommandProc)();
|
||||||
|
struct CommandEntry {
|
||||||
|
CommandProc proc;
|
||||||
|
const char* desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (VMContext::*OpcodeProc)();
|
||||||
|
struct OpcodeEntry {
|
||||||
|
OpcodeProc proc;
|
||||||
|
const char* desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
const CommandEntry* _commands;
|
||||||
|
const OpcodeEntry* _opcodes;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// the command procs
|
||||||
|
void c1_goToLine(void); // 0x00
|
||||||
|
void c1_setReturn(void); // 0x01
|
||||||
|
void c1_pushRetRec(void); // 0x02
|
||||||
|
void c1_push(void); // 0x03 & 0x04
|
||||||
|
void c1_pushVar(void); // 0x05
|
||||||
|
void c1_pushFrameNeg(void); // 0x06
|
||||||
|
void c1_pushFramePos(void); // 0x07
|
||||||
|
void c1_popRetRec(void); // 0x08
|
||||||
|
void c1_popVar(void); // 0x09
|
||||||
|
void c1_popFrameNeg(void); // 0x0A
|
||||||
|
void c1_popFramePos(void); // 0x0B
|
||||||
|
void c1_addToSP(void); // 0x0C
|
||||||
|
void c1_subFromSP(void); // 0x0D
|
||||||
|
void c1_execOpcode(void); // 0x0E
|
||||||
|
void c1_ifNotGoTo(void); // 0x0F
|
||||||
|
void c1_negate(void); // 0x10
|
||||||
|
void c1_evaluate(void); // 0x11
|
||||||
|
void c1_unknownCommand(void);
|
||||||
|
|
||||||
|
// the opcode procs
|
||||||
|
void o1_0x68(void); // 0x68
|
||||||
|
void o1_unknownOpcode(void);
|
||||||
|
};
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
220
kyra/script_v1.cpp
Normal file
220
kyra/script_v1.cpp
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
|
||||||
|
#include "kyra.h"
|
||||||
|
#include "script.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
// Command procs
|
||||||
|
|
||||||
|
void VMContext::c1_unknownCommand(void) {
|
||||||
|
debug("unknown command '0x%x'.", _currentCommand);
|
||||||
|
debug("\targument: '0x%x'", _argument);
|
||||||
|
|
||||||
|
_error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_goToLine(void) {
|
||||||
|
_instructionPos = _argument << 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_setReturn(void) {
|
||||||
|
_returnValue = _argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_pushRetRec(void) {
|
||||||
|
if (!_argument) {
|
||||||
|
pushStack(_returnValue);
|
||||||
|
} else {
|
||||||
|
int32 rec = ((int16)_tempPos << 16) | ((_instructionPos >> 1) + 1);
|
||||||
|
pushStack(rec);
|
||||||
|
_tempPos = _instructionPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_push(void) {
|
||||||
|
pushStack(_argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_pushVar(void) {
|
||||||
|
pushStack(_registers[_argument]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_pushFrameNeg(void) {
|
||||||
|
pushStack(_stack[_tempPos + _argument]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_pushFramePos(void) {
|
||||||
|
pushStack(_stack[_tempPos - _argument]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_popRetRec(void) {
|
||||||
|
if (!_argument) {
|
||||||
|
_returnValue = popStack();
|
||||||
|
} else {
|
||||||
|
if (_stackPos <= 0) {
|
||||||
|
_scriptState = kScriptStopped;
|
||||||
|
}
|
||||||
|
int32 rec = popStack();
|
||||||
|
|
||||||
|
_tempPos = (int16)((rec & 0xFFFF0000) >> 16);
|
||||||
|
_instructionPos = (rec & 0x0000FFFF) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_popVar(void) {
|
||||||
|
_registers[_argument] = popStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_popFrameNeg(void) {
|
||||||
|
_stack[_tempPos + _argument] = popStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_popFramePos(void) {
|
||||||
|
_stack[_tempPos - _argument] = popStack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_addToSP(void) {
|
||||||
|
_stackPos -= _argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_subFromSP(void) {
|
||||||
|
_stackPos += _argument;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_execOpcode(void) {
|
||||||
|
OpcodeProc proc = _opcodes[_argument].proc;
|
||||||
|
(this->*proc)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_ifNotGoTo(void) {
|
||||||
|
if (!popStack()) {
|
||||||
|
_instructionPos = _argument << 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_negate(void) {
|
||||||
|
switch(_argument) {
|
||||||
|
case 0:
|
||||||
|
topStack() = !topStack();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
topStack() = -topStack();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
topStack() = ~topStack();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
debug("unkown negate instruction %d", _argument);
|
||||||
|
_error = true;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void VMContext::c1_evaluate(void) {
|
||||||
|
int32 x, y;
|
||||||
|
int32 res = false;
|
||||||
|
|
||||||
|
x = popStack();
|
||||||
|
y = popStack();
|
||||||
|
|
||||||
|
switch(_argument) {
|
||||||
|
case 0:
|
||||||
|
res = x && y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
res = x || y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
res = x != y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
res = x < y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
res = x <= y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
res = x > y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
res = x >= y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
res = x + y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 9:
|
||||||
|
res = x - y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
res = x * y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
res = x / y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
res = x >> y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
res = x << y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
res = x & y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 15:
|
||||||
|
res = x | y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 16:
|
||||||
|
res = x % y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 17:
|
||||||
|
res = x ^ y;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
debug("unknown evaluate command");
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
pushStack(res);
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
119
kyra/wsamovie.cpp
Normal file
119
kyra/wsamovie.cpp
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "wsamovie.h"
|
||||||
|
#include "codecs.h"
|
||||||
|
|
||||||
|
#include "common/stream.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
WSAMovieV1::WSAMovieV1(uint8* data, uint32 size) {
|
||||||
|
if (!data) {
|
||||||
|
error("resource created without data");
|
||||||
|
}
|
||||||
|
|
||||||
|
_buffer = data;
|
||||||
|
|
||||||
|
// I like these Streams .... =)
|
||||||
|
Common::MemoryReadStream datastream(data, size);
|
||||||
|
|
||||||
|
datastream.read(&_wsaHeader, sizeof(_wsaHeader));
|
||||||
|
|
||||||
|
// check for version
|
||||||
|
if (_wsaHeader._type) {
|
||||||
|
error("loading a WSA version 2 with the WSA version 1 loader");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 offsetAdd = 0;
|
||||||
|
|
||||||
|
// checks now for own palette
|
||||||
|
if (_wsaHeader._type % 2) {
|
||||||
|
// don't now if this will work right, because a few lines before we use
|
||||||
|
// _wsaHeader._type for detect the version of the WSA movie,
|
||||||
|
// but this code was from FreeKyra Tools so I think it will work
|
||||||
|
|
||||||
|
// if this is a packed palette we have a problem :)
|
||||||
|
offsetAdd = 768 /* 0x300 */;
|
||||||
|
}
|
||||||
|
|
||||||
|
_frameCount = _wsaHeader._numFrames;
|
||||||
|
_offsetTable = new uint32[_wsaHeader._numFrames + 2];
|
||||||
|
assert(!_offsetTable);
|
||||||
|
|
||||||
|
// loads the offset table
|
||||||
|
for (uint32 tmp = 0; tmp < _wsaHeader._numFrames; ++tmp) {
|
||||||
|
_offsetTable[tmp] = datastream.readUint32LE() + offsetAdd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offsetAdd) {
|
||||||
|
uint8* palbuffer = new uint8[offsetAdd];
|
||||||
|
assert(!palbuffer);
|
||||||
|
|
||||||
|
_ownPalette = new Palette(palbuffer, offsetAdd);
|
||||||
|
assert(!_ownPalette);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WSAMovieV1::~WSAMovieV1() {
|
||||||
|
delete [] _buffer;
|
||||||
|
delete [] _offsetTable;
|
||||||
|
delete _ownPalette;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8* WSAMovieV1::loadFrame(uint16 frame, uint16* width, uint16* height) {
|
||||||
|
if (width) *width = _wsaHeader._width;
|
||||||
|
if (height) *height = _wsaHeader._height;
|
||||||
|
|
||||||
|
if (frame == _prefetchedFrame) {
|
||||||
|
return _currentFrame;
|
||||||
|
} else {
|
||||||
|
if (!_currentFrame) {
|
||||||
|
_currentFrame = new uint8[_wsaHeader._width * _wsaHeader._height];
|
||||||
|
assert(_currentFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* frameData = 0;
|
||||||
|
uint8 image40[64000]; // I think this crash on Plam OS :)
|
||||||
|
|
||||||
|
if (frame = _prefetchedFrame + 1) {
|
||||||
|
frameData = _buffer + _offsetTable[frame] + (hasPalette() ? 768 : 0);
|
||||||
|
Compression::decode80(frameData, image40);
|
||||||
|
Compression::decode40(image40, _currentFrame);
|
||||||
|
} else {
|
||||||
|
memset(_currentFrame, 0, _wsaHeader._width * _wsaHeader._height);
|
||||||
|
|
||||||
|
for (uint32 i = 0; i <= frame; i++)
|
||||||
|
{
|
||||||
|
frameData = _buffer + _offsetTable[i] + (hasPalette() ? 768 : 0);
|
||||||
|
Compression::decode80(frameData, image40);
|
||||||
|
Compression::decode40(image40, _currentFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_prefetchedFrame = frame;
|
||||||
|
return _currentFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
82
kyra/wsamovie.h
Normal file
82
kyra/wsamovie.h
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/* ScummVM - Kyrandia Interpreter
|
||||||
|
* Copyright (C) 2003-2004 The ScummVM project
|
||||||
|
*
|
||||||
|
* 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$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOVIES_H
|
||||||
|
#define MOVIES_H
|
||||||
|
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
namespace Kyra {
|
||||||
|
|
||||||
|
// a generic movie
|
||||||
|
class Movie {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~Movie() {}
|
||||||
|
|
||||||
|
virtual const uint8* loadFrame(uint16 frame, uint16* width = 0, uint16* height = 0) = 0;
|
||||||
|
virtual uint16 countFrames(void) { return _frameCount; }
|
||||||
|
|
||||||
|
virtual bool hasPalette(void) { return (_ownPalette != 0); }
|
||||||
|
virtual Palette* palette(void) { return _ownPalette; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint16 _frameCount;
|
||||||
|
Palette* _ownPalette;
|
||||||
|
};
|
||||||
|
|
||||||
|
// movie format for Kyrandia 1
|
||||||
|
// there is also a new WSA Format for Kyrandia 2
|
||||||
|
// which i will implement in future
|
||||||
|
class WSAMovieV1 : public Movie {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WSAMovieV1(uint8* data, uint32 size);
|
||||||
|
~WSAMovieV1();
|
||||||
|
|
||||||
|
const uint8* loadFrame(uint16 frame, uint16* width, uint16* height);
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint8* _buffer;
|
||||||
|
|
||||||
|
#pragma START_PACK_STRUCTS
|
||||||
|
struct WSAHeader {
|
||||||
|
uint16 _numFrames; // All right
|
||||||
|
uint16 _width; // should be right
|
||||||
|
uint16 _height; // should be right
|
||||||
|
uint8 _xPos; // could be wrong
|
||||||
|
uint8 _yPos; // could be wrong
|
||||||
|
uint16 _delta; // could be wrong
|
||||||
|
uint16 _type; // should be right
|
||||||
|
} GCC_PACK _wsaHeader;
|
||||||
|
#pragma END_PACK_STRUCTS
|
||||||
|
|
||||||
|
uint32* _offsetTable;
|
||||||
|
|
||||||
|
uint8* _currentFrame;
|
||||||
|
uint16 _prefetchedFrame;
|
||||||
|
};
|
||||||
|
} // end of namespace Kyra
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue