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
|
||||
|
130
kyra/kyra.cpp
130
kyra/kyra.cpp
|
@ -1,5 +1,5 @@
|
|||
/* ScummVM - Scumm Interpreter
|
||||
* Copyright (C) 2003 The ScummVM project
|
||||
/* 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
|
||||
|
@ -28,33 +28,56 @@
|
|||
#include "sound/mixer.h"
|
||||
#include "common/file.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "kyra.h"
|
||||
|
||||
static const GameSettings kyra_setting =
|
||||
{ "kyra", "Legend of Kyrandia", 0 };
|
||||
#include "kyra.h"
|
||||
#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 games;
|
||||
const KyraGameSettings *g = kyra_settings;
|
||||
|
||||
while (g->name) {
|
||||
games.push_back(g->toGameSettings());
|
||||
g++;
|
||||
}
|
||||
|
||||
games.push_back(kyra_setting);
|
||||
return games;
|
||||
}
|
||||
|
||||
// TODO: Improve this :)
|
||||
DetectedGameList Engine_KYRA_detectGames(const FSList &fslist) {
|
||||
const KyraGameSettings *game;
|
||||
DetectedGameList detectedGames;
|
||||
File test_file;
|
||||
|
||||
// Iterate over all files in the given directory
|
||||
for (game = kyra_settings; game->name; ++game) {
|
||||
if (game->detectName == NULL)
|
||||
continue;
|
||||
|
||||
for (FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) {
|
||||
const char *name = file->displayName().c_str();
|
||||
if ((0 == scumm_stricmp("chapter1.vrm", name)) ||
|
||||
(0 == scumm_stricmp("chapter5.vrm", name))) {
|
||||
detectedGames.push_back(kyra_setting);
|
||||
printf("Detecting Kyra...\n");
|
||||
if ((!scumm_stricmp(game->detectName, name))) {
|
||||
detectedGames.push_back(game->toGameSettings());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return detectedGames;
|
||||
}
|
||||
|
@ -78,11 +101,37 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *syst)
|
|||
|
||||
//getGameDataPath();
|
||||
|
||||
// Initialize backend
|
||||
syst->initSize(320, 240);
|
||||
// Initialize backen
|
||||
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() {
|
||||
delete _resMgr;
|
||||
delete _mouse;
|
||||
delete _items;
|
||||
delete _npcScript;
|
||||
delete _currentScript;
|
||||
delete _font;
|
||||
}
|
||||
|
||||
void KyraEngine::errorString(const char *buf1, char *buf2) {
|
||||
|
@ -91,10 +140,61 @@ void KyraEngine::errorString(const char *buf1, char *buf2) {
|
|||
|
||||
void KyraEngine::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() {
|
||||
_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
|
||||
|
||||
|
|
35
kyra/kyra.h
35
kyra/kyra.h
|
@ -22,26 +22,49 @@
|
|||
#ifndef KYRA_H
|
||||
#define KYRA_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
//#include "common/scummsys.h"
|
||||
#include "base/engine.h"
|
||||
#include "base/gameDetector.h"
|
||||
#include "common/util.h"
|
||||
|
||||
enum {
|
||||
GF_FLOPPY = 1 << 0,
|
||||
GF_TALKIE = 1 << 1,
|
||||
GF_KYRA1 = 1 << 2,
|
||||
GF_KYRA2 = 1 << 3
|
||||
};
|
||||
|
||||
namespace Kyra {
|
||||
class Resourcemanager;
|
||||
class CPSImage;
|
||||
class Font;
|
||||
class Palette;
|
||||
class VMContext;
|
||||
|
||||
class KyraEngine : public Engine {
|
||||
|
||||
public:
|
||||
KyraEngine(GameDetector *detector, OSystem *syst);
|
||||
~KyraEngine();
|
||||
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:
|
||||
void go();
|
||||
void shutdown();
|
||||
Resourcemanager* _resMgr;
|
||||
uint8 *_screen;
|
||||
|
||||
public:
|
||||
|
||||
KyraEngine(GameDetector *detector, OSystem *syst);
|
||||
virtual ~KyraEngine();
|
||||
Font* _font;
|
||||
CPSImage* _mouse;
|
||||
CPSImage* _items;
|
||||
|
||||
VMContext* _currentScript; // our current script
|
||||
VMContext* _npcScript; // script from NPCs
|
||||
};
|
||||
|
||||
} // End of namespace Kyra
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
MODULE := kyra
|
||||
|
||||
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 += \
|
||||
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