1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * Additional copyright for this file:
8  * Copyright (C) 1999-2000 Revolution Software Ltd.
9  * This code is based on source code created by Revolution Software,
10  * used with permission.
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25  *
26  */
27 
28 #include "engines/icb/common/ptr_util.h"
29 #include "engines/icb/mission.h"
30 #include "engines/icb/global_objects.h"
31 #include "engines/icb/global_switches.h"
32 #include "engines/icb/options_manager_pc.h"
33 #include "engines/icb/cluster_manager_pc.h"
34 #include "engines/icb/res_man_pc.h"
35 #include "engines/icb/movie_pc.h"
36 
37 #include "common/util.h"
38 
39 namespace ICB {
40 
41 int32 Movie_name_to_ID(char *name);
42 void Init_play_movie(const char *param0, bool8 param1);
43 
fn_play_movie(int32 & result,int32 * params)44 mcodeFunctionReturnCodes fn_play_movie(int32 &result, int32 *params) { return (MS->fn_play_movie(result, params)); }
45 
fn_play_movie(int32 &,int32 * params)46 mcodeFunctionReturnCodes _game_session::fn_play_movie(int32 &, int32 *params) {
47 	const char *movie_name = NULL;
48 	if (params && params[0]) {
49 		movie_name = (const char *)MemoryUtil::resolvePtr(params[0]);
50 	}
51 
52 	// Are we free to begin movie playback
53 	if (!L->looping) {
54 		Init_play_movie(movie_name, (bool8)params[1]);
55 
56 		// Cycle calls to this function until playback has finished
57 		L->looping = 1;
58 
59 		return (IR_REPEAT);
60 	} else {
61 		// If we're already playing a movie then loop through this function until we're done
62 		if (g_theSequenceManager->busy())
63 			return (IR_REPEAT);
64 		else {
65 			// Movie finished so continue script
66 			L->looping = 0;
67 			return (IR_CONT);
68 		}
69 	}
70 }
71 
Init_play_movie(const char * param0,bool8 param1)72 void Init_play_movie(const char *param0, bool8 param1) {
73 	// Stop all sounds occuring
74 	PauseSounds();
75 
76 	const char *moviename = (const char *)param0;
77 
78 	// Filename checking to help catch Jake's PSX restrictions
79 	if (strlen(moviename) > 8)
80 		Fatal_error("Movie stream name must not exceed 8 characters in length!!!");
81 
82 	for (uint32 i = 0; i < strlen(moviename); i++) {
83 		if (!Common::isAlnum(moviename[i]))
84 			Fatal_error(pxVString("Can't register movie: %s as filename must consist of alpha-numerics ONLY.", moviename));
85 		if (!Common::isDigit(moviename[i]))
86 			if (!Common::isLower(moviename[i]))
87 				Fatal_error(pxVString("Can't register movie: %s as filename must consist of lowercase characters ONLY.", moviename));
88 	}
89 
90 	pxString fullname;
91 
92 #ifndef PC_DEMO
93 #if 1 // was #ifdef FROM_PC_CD
94 	// Non-global movies are streamed from the CD
95 	// char *_root = g_theClusterManager->GetCDRoot();
96 #endif
97 #endif
98 
99 	// All in one directory, which is nice
100 	fullname.Format("movies\\%s.bik", moviename);
101 	fullname.ConvertPath();
102 	// Ensure correct CD is in the drive (can't assume this because of movie library)
103 	switch (moviename[2]) {
104 	case '1':
105 		g_theClusterManager->CheckDiscInserted(MISSION1);
106 		break;
107 	case '2':
108 		g_theClusterManager->CheckDiscInserted(MISSION2);
109 		break;
110 	case '3':
111 		g_theClusterManager->CheckDiscInserted(MISSION3);
112 		break;
113 	case '4':
114 		g_theClusterManager->CheckDiscInserted(MISSION4);
115 		break;
116 	case '5':
117 		g_theClusterManager->CheckDiscInserted(MISSION5);
118 		break;
119 	case '7':
120 		g_theClusterManager->CheckDiscInserted(MISSION7);
121 		break;
122 	case '8':
123 		g_theClusterManager->CheckDiscInserted(MISSION8);
124 		break;
125 	case '9':
126 		g_theClusterManager->CheckDiscInserted(MISSION9);
127 		break;
128 	case '0':
129 		g_theClusterManager->CheckDiscInserted(MISSION10);
130 		break;
131 	}
132 
133 	// Did we find it in the mission directory (or possibly global directory already)
134 	if (!checkFileExists(fullname)) {
135 		// File is not present in the mission directory so check the global directory
136 
137 		fullname.Format("gmovies\\%s.bik", moviename);
138 		fullname.ConvertPath();
139 
140 		if (!checkFileExists(fullname))
141 			Fatal_error(pxVString("Movie %s.bik does not exist in mission or global movie directory", moviename));
142 	}
143 
144 	if (g_theSequenceManager->registerMovie(fullname, param1, FALSE8)) {
145 		// Is this movie part of the title screen library
146 		int32 mvid = Movie_name_to_ID(const_cast<char *>(moviename));
147 
148 		if (mvid != -1) {
149 			// We can now consider this movie viewable in the title screen library
150 			g_movieLibrary[mvid].visible = TRUE8;
151 		}
152 
153 		// Bink is now active and playing
154 
155 		// Successfully opened a bink sequence so set the engine to play and display it
156 		g_stub->Push_stub_mode(__sequence);
157 	} else {
158 		Fatal_error(pxVString("Couldn't register the movie: %s", (const char *)fullname));
159 	}
160 }
161 
162 } // End of namespace ICB
163