/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * Additional copyright for this file:
 * Copyright (C) 1994-1998 Revolution Software Ltd.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-0/engines/sword2/protocol.cpp $
 * $Id: protocol.cpp 30459 2008-01-12 23:07:51Z sev $
 */



#include "sword2/sword2.h"
#include "sword2/header.h"
#include "sword2/resman.h"

namespace Sword2 {

/**
 * Returns a pointer to the first palette entry, given the pointer to the start
 * of the screen file.
 */

byte *Sword2Engine::fetchPalette(byte *screenFile) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());

	byte *palette = screenFile + ResHeader::size() + mscreenHeader.palette;

	// Always set colour 0 to black, because while most background screen
	// palettes have a bright colour 0 it should come out as black in the
	// game.

	palette[0] = 0;
	palette[1] = 0;
	palette[2] = 0;
	palette[3] = 0;

	return palette;
}

/**
 * Returns a pointer to the start of the palette match table, given the pointer
 * to the start of the screen file.
 */

byte *Sword2Engine::fetchPaletteMatchTable(byte *screenFile) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());

	return screenFile + ResHeader::size() + mscreenHeader.paletteTable;
}

/**
 * Returns a pointer to the screen header, given the pointer to the start of
 * the screen file.
 */

byte *Sword2Engine::fetchScreenHeader(byte *screenFile) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());

	return screenFile + ResHeader::size() + mscreenHeader.screen;
}

/**
 * Returns a pointer to the requested layer header, given the pointer to the
 * start of the screen file. Drops out if the requested layer number exceeds
 * the number of layers on this screen.
 */

byte *Sword2Engine::fetchLayerHeader(byte *screenFile, uint16 layerNo) {
#ifdef SWORD2_DEBUG
	ScreenHeader screenHead;

	screenHead.read(fetchScreenHeader(screenFile));
	assert(layerNo < screenHead.noLayers);
#endif

	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());

	return screenFile + ResHeader::size() + mscreenHeader.layers + layerNo * LayerHeader::size();
}

/**
 * Returns a pointer to the start of the shading mask, given the pointer to the
 * start of the screen file.
 */

byte *Sword2Engine::fetchShadingMask(byte *screenFile) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());

	return screenFile + ResHeader::size() + mscreenHeader.maskOffset;
}

/**
 * Returns a pointer to the anim header, given the pointer to the start of the
 * anim file.
 */

byte *Sword2Engine::fetchAnimHeader(byte *animFile) {
	return animFile + ResHeader::size();
}

/**
 * Returns a pointer to the requested frame number's cdtEntry, given the
 * pointer to the start of the anim file. Drops out if the requested frame
 * number exceeds the number of frames in this anim.
 */

byte *Sword2Engine::fetchCdtEntry(byte *animFile, uint16 frameNo) {
#ifdef SWORD2_DEBUG
	AnimHeader animHead;

	animHead.read(fetchAnimHeader(animFile));

	if (frameNo > animHead->noAnimFrames - 1)
		error("fetchCdtEntry(animFile,%d) - anim only %d frames", frameNo, animHead.noAnimFrames);
#endif

	return fetchAnimHeader(animFile) + AnimHeader::size() + frameNo * CdtEntry::size();
}

/**
 * Returns a pointer to the requested frame number's header, given the pointer
 * to the start of the anim file. Drops out if the requested frame number
 * exceeds the number of frames in this anim
 */

byte *Sword2Engine::fetchFrameHeader(byte *animFile, uint16 frameNo) {
	// required address = (address of the start of the anim header) + frameOffset
	CdtEntry cdt;

	cdt.read(fetchCdtEntry(animFile, frameNo));

	return animFile + ResHeader::size() + cdt.frameOffset;
}

/**
 * Returns a pointer to the requested parallax layer data.
 */

byte *Sword2Engine::fetchBackgroundParallaxLayer(byte *screenFile, int layer) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());
	assert(mscreenHeader.bg_parallax[layer]);

	return screenFile + ResHeader::size() + mscreenHeader.bg_parallax[layer];
}

byte *Sword2Engine::fetchBackgroundLayer(byte *screenFile) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());
	assert(mscreenHeader.screen);

	return screenFile + ResHeader::size() + mscreenHeader.screen + ScreenHeader::size();
}

byte *Sword2Engine::fetchForegroundParallaxLayer(byte *screenFile, int layer) {
	MultiScreenHeader mscreenHeader;

	mscreenHeader.read(screenFile + ResHeader::size());
	assert(mscreenHeader.fg_parallax[layer]);

	return screenFile + ResHeader::size() + mscreenHeader.fg_parallax[layer];
}

byte *Sword2Engine::fetchTextLine(byte *file, uint32 text_line) {
	TextHeader text_header;
	static byte errorLine[128];

	text_header.read(file + ResHeader::size());

	if (text_line >= text_header.noOfLines) {
		sprintf((char *)errorLine, "xxMissing line %d of %s (only 0..%d)", text_line, _resman->fetchName(file), text_header.noOfLines - 1);

		// first 2 chars are NULL so that actor-number comes out as '0'
		errorLine[0] = 0;
		errorLine[1] = 0;
		return errorLine;
	}

	// The "number of lines" field is followed by a lookup table

	return file + READ_LE_UINT32(file + ResHeader::size() + 4 + 4 * text_line);
}

// Used for testing text & speech (see fnISpeak in speech.cpp)

bool Sword2Engine::checkTextLine(byte *file, uint32 text_line) {
	TextHeader text_header;

	text_header.read(file + ResHeader::size());

	return text_line < text_header.noOfLines;
}

} // End of namespace Sword2
