[Scummvm-cvs-logs] CVS: scummvm/kyra codecs.cpp,NONE,1.1 codecs.h,NONE,1.1 cpsimage.cpp,NONE,1.1 font.cpp,NONE,1.1 palette.cpp,NONE,1.1 resource.cpp,NONE,1.1 resource.h,NONE,1.1 script.cpp,NONE,1.1 script.h,NONE,1.1 script_v1.cpp,NONE,1.1 wsamovie.cpp,NONE,1.1 wsamovie.h,NONE,1.1 kyra.cpp,1.2,1.3 kyra.h,1.1,1.2 module.mk,1.1,1.2

James Brown ender at users.sourceforge.net
Thu Oct 14 23:08:28 CEST 2004


Update of /cvsroot/scummvm/scummvm/kyra
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20976

Modified Files:
	kyra.cpp kyra.h module.mk 
Added Files:
	codecs.cpp codecs.h cpsimage.cpp font.cpp palette.cpp 
	resource.cpp resource.h script.cpp script.h script_v1.cpp 
	wsamovie.cpp wsamovie.h 
Log Message:
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.


--- NEW FILE: codecs.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/codecs.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */


#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


--- NEW FILE: codecs.h ---
/* 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: /cvsroot/scummvm/scummvm/kyra/codecs.h,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

/** 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


--- NEW FILE: cpsimage.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/cpsimage.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: font.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/font.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: palette.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/palette.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: resource.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/resource.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: resource.h ---
/* 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: /cvsroot/scummvm/scummvm/kyra/resource.h,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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

--- NEW FILE: script.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/script.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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

--- NEW FILE: script.h ---
/* 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: /cvsroot/scummvm/scummvm/kyra/script.h,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: script_v1.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/script_v1.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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

--- NEW FILE: wsamovie.cpp ---
/* 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: /cvsroot/scummvm/scummvm/kyra/wsamovie.cpp,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


--- NEW FILE: wsamovie.h ---
/* 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: /cvsroot/scummvm/scummvm/kyra/wsamovie.h,v 1.1 2004/10/15 06:06:47 ender Exp $
 *
 */

#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


Index: kyra.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/kyra/kyra.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- kyra.cpp	31 Jul 2004 09:31:15 -0000	1.2
+++ kyra.cpp	15 Oct 2004 06:06:47 -0000	1.3
@@ -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
@@ -8,7 +8,7 @@
 
  * 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
+ * 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
@@ -28,35 +28,58 @@
 #include "sound/mixer.h"
 #include "common/file.h"
 #include "common/config-manager.h"
+
 #include "kyra.h"
+#include "resource.h"
+#include "script.h"
 
-static const GameSettings kyra_setting =
-        { "kyra", "Legend of Kyrandia", 0 };
+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 (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");
-			break;
+	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 ((!scumm_stricmp(game->detectName, name))) {
+				detectedGames.push_back(game->toGameSettings());
+				break;
+			}
 		}
 	}
 
-	return detectedGames;
+        return detectedGames;
 }
 
 Engine *Engine_KYRA_create(GameDetector *detector, OSystem *syst) {
@@ -78,11 +101,37 @@
 
 	//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::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
 

Index: kyra.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/kyra/kyra.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- kyra.h	9 Apr 2004 12:36:06 -0000	1.1
+++ kyra.h	15 Oct 2004 06:06:47 -0000	1.2
@@ -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

Index: module.mk
===================================================================
RCS file: /cvsroot/scummvm/scummvm/kyra/module.mk,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- module.mk	9 Apr 2004 12:36:06 -0000	1.1
+++ module.mk	15 Oct 2004 06:06:47 -0000	1.2
@@ -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





More information about the Scummvm-git-logs mailing list