1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1994-1998 Revolution Software Ltd.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23  */
24 
25 // ---------------------------------------------------------------------------
26 // A more intelligent version of the old ANIMS.C
27 // All this stuff by James
28 // DON'T TOUCH!
29 // ---------------------------------------------------------------------------
30 
31 
32 #include "common/file.h"
33 
34 #include "sword2/sword2.h"
35 #include "sword2/defs.h"
36 #include "sword2/header.h"
37 #include "sword2/screen.h"
38 #include "sword2/interpreter.h"
39 #include "sword2/logic.h"
40 #include "sword2/maketext.h"
41 #include "sword2/resman.h"
42 #include "sword2/router.h"
43 #include "sword2/sound.h"
44 #include "sword2/animation.h"
45 
46 namespace Sword2 {
47 
doAnimate(byte * ob_logic,byte * ob_graph,int32 animRes,bool reverse)48 int Router::doAnimate(byte *ob_logic, byte *ob_graph, int32 animRes, bool reverse) {
49 	AnimHeader anim_head;
50 	byte *anim_file;
51 
52 	ObjectLogic obLogic(ob_logic);
53 	ObjectGraphic obGraph(ob_graph);
54 
55 	if (obLogic.getLooping() == 0) {
56 		// This is the start of the anim - set up the first frame
57 
58 		// For testing all anims!
59 		// A script loop can send every resource number to the anim
60 		// function & it will only run the valid ones. See
61 		// 'testing_routines' object in George's Player Character
62 		// section of linc
63 
64 		if (_vm->_logic->readVar(SYSTEM_TESTING_ANIMS)) {
65 			if (!_vm->_resman->checkValid(animRes)) {
66 				// Not a valid resource number. Switch off
67 				// the sprite. Don't animate - just continue
68 				// script next cycle.
69 				setSpriteStatus(ob_graph, NO_SPRITE);
70 				return IR_STOP;
71 			}
72 
73 			// if it's not an animation file
74 			if (_vm->_resman->fetchType(animRes) != ANIMATION_FILE) {
75 				// switch off the sprite
76 				// don't animate - just continue
77 				// script next cycle
78 				setSpriteStatus(ob_graph, NO_SPRITE);
79 				return IR_STOP;
80 			}
81 
82 			// switch on the sprite
83 			setSpriteStatus(ob_graph, SORT_SPRITE);
84 		}
85 
86 		assert(animRes);
87 
88 		// open anim file
89 		anim_file = _vm->_resman->openResource(animRes);
90 
91 		assert(_vm->_resman->fetchType(animRes) == ANIMATION_FILE);
92 
93 		// point to anim header
94 		anim_head.read(_vm->fetchAnimHeader(anim_file));
95 
96 		// now running an anim, looping back to this call again
97 		obLogic.setLooping(1);
98 		obGraph.setAnimResource(animRes);
99 
100 		if (reverse)
101 			obGraph.setAnimPc(anim_head.noAnimFrames - 1);
102 		else
103 			obGraph.setAnimPc(0);
104 	} else if (_vm->_logic->getSync() != -1) {
105 		// We've received a sync - return to script immediately
106 		debug(5, "**sync stopped %d**", _vm->_logic->readVar(ID));
107 
108 		// If sync received, anim finishes right now (remaining on
109 		// last frame). Quit animation, but continue script.
110 		obLogic.setLooping(0);
111 		return IR_CONT;
112 	} else {
113 		// Not first frame, and no sync received - set up the next
114 		// frame of the anim.
115 
116 		// open anim file and point to anim header
117 		anim_file = _vm->_resman->openResource(obGraph.getAnimResource());
118 		anim_head.read(_vm->fetchAnimHeader(anim_file));
119 
120 		if (reverse)
121 			obGraph.setAnimPc(obGraph.getAnimPc() - 1);
122 		else
123 			obGraph.setAnimPc(obGraph.getAnimPc() + 1);
124 	}
125 
126 	// check for end of anim
127 
128 	if (reverse) {
129 		if (obGraph.getAnimPc() == 0)
130 			obLogic.setLooping(0);
131 	} else {
132 		if (obGraph.getAnimPc() == anim_head.noAnimFrames - 1)
133 			obLogic.setLooping(0);
134 	}
135 
136 	// close the anim file
137 	_vm->_resman->closeResource(obGraph.getAnimResource());
138 
139 	// check if we want the script to loop back & call this function again
140 	return obLogic.getLooping() ? IR_REPEAT : IR_STOP;
141 }
142 
megaTableAnimate(byte * ob_logic,byte * ob_graph,byte * ob_mega,byte * animTable,bool reverse)143 int Router::megaTableAnimate(byte *ob_logic, byte *ob_graph, byte *ob_mega, byte *animTable, bool reverse) {
144 	int32 animRes = 0;
145 
146 	// If this is the start of the anim, read the anim table to get the
147 	// appropriate anim resource
148 
149 	ObjectLogic obLogic(ob_logic);
150 
151 	if (obLogic.getLooping() == 0) {
152 		ObjectMega obMega(ob_mega);
153 
154 		// Appropriate anim resource is in 'table[direction]'
155 		animRes = READ_LE_UINT32(animTable + 4 * obMega.getCurDir());
156 	}
157 
158 	return doAnimate(ob_logic, ob_graph, animRes, reverse);
159 }
160 
setSpriteStatus(byte * ob_graph,uint32 type)161 void Router::setSpriteStatus(byte *ob_graph, uint32 type) {
162 	ObjectGraphic obGraph(ob_graph);
163 
164 	// Remove the previous status, but don't affect the shading upper-word
165 	obGraph.setType((obGraph.getType() & 0xffff0000) | type);
166 }
167 
setSpriteShading(byte * ob_graph,uint32 type)168 void Router::setSpriteShading(byte *ob_graph, uint32 type) {
169 	ObjectGraphic obGraph(ob_graph);
170 
171 	// Remove the previous shading, but don't affect the status lower-word.
172 	// Note that mega frames may still be shaded automatically, even when
173 	// not sent 'RDSPR_SHADOW'.
174 	obGraph.setType((obGraph.getType() & 0x0000ffff) | type);
175 }
176 
177 } // End of namespace Sword2
178