1 // _________ __ __
2 // / _____// |_____________ _/ |______ ____ __ __ ______
3 // \_____ \\ __\_ __ \__ \\ __\__ \ / ___\| | \/ ___/
4 // / \| | | | \// __ \| | / __ \_/ /_/ > | /\___ |
5 // /_______ /|__| |__| (____ /__| (____ /\___ /|____//____ >
6 // \/ \/ \//_____/ \/
7 // ______________________ ______________________
8 // T H E W A R B E G I N S
9 // Stratagus - A free fantasy real time strategy game engine
10 //
11 /**@name mng.cpp - The mng graphic file loader. */
12 //
13 // (c) Copyright 2004-2005 by Jimmy Salmon
14 //
15 // This program is free software; you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation; only version 2 of the License.
18 //
19 // This program is distributed in the hope that it will be useful,
20 // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 // GNU General Public License for more details.
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program; if not, write to the Free Software
26 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 // 02111-1307, USA.
28 //
29
30 //@{
31
32 /*----------------------------------------------------------------------------
33 -- Includes
34 ----------------------------------------------------------------------------*/
35
36 #include "stratagus.h"
37
38 #ifdef USE_MNG
39
40 #include "video.h"
41 #include "iolib.h"
42 #include "iocompat.h"
43
44 /*----------------------------------------------------------------------------
45 -- Functions
46 ----------------------------------------------------------------------------*/
47
my_alloc(mng_size_t len)48 static mng_ptr MNG_DECL my_alloc(mng_size_t len)
49 {
50 char *ptr = new char[len];
51 memset(ptr, 0, len);
52 return (mng_ptr)ptr;
53 }
54
my_free(mng_ptr ptr,mng_size_t)55 static void MNG_DECL my_free(mng_ptr ptr, mng_size_t)
56 {
57 delete[] static_cast<char *>(ptr);
58 }
59
my_openstream(mng_handle handle)60 static mng_bool MNG_DECL my_openstream(mng_handle handle)
61 {
62 Mng *mng;
63
64 mng = (Mng *)mng_get_userdata(handle);
65 mng->fd = fopen(mng->name.c_str(), "rb");
66 if (!mng->fd) {
67 return MNG_FALSE;
68 }
69 return MNG_TRUE;
70 }
71
my_closestream(mng_handle handle)72 static mng_bool MNG_DECL my_closestream(mng_handle handle)
73 {
74 Mng *mng;
75
76 mng = (Mng *)mng_get_userdata(handle);
77 if (mng->fd) {
78 fclose(mng->fd);
79 }
80 return MNG_TRUE;
81 }
82
my_readdata(mng_handle handle,mng_ptr buf,mng_uint32 buflen,mng_uint32p read)83 static mng_bool MNG_DECL my_readdata(mng_handle handle, mng_ptr buf, mng_uint32 buflen,
84 mng_uint32p read)
85 {
86 Mng *mng;
87
88 mng = (Mng *)mng_get_userdata(handle);
89 *read = fread(buf, 1, buflen, mng->fd);
90 return MNG_TRUE;
91 }
92
my_processheader(mng_handle handle,mng_uint32 width,mng_uint32 height)93 static mng_bool MNG_DECL my_processheader(mng_handle handle, mng_uint32 width,
94 mng_uint32 height)
95 {
96 mng_imgtype type = mng_get_sigtype(handle);
97 if (type != mng_it_mng) {
98 return TRUE;
99 }
100
101 Mng *mng = (Mng *)mng_get_userdata(handle);
102
103 // Allocate the SDL surface to hold the image
104 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
105 const Uint32 Rmask = 0x000000FF;
106 const Uint32 Gmask = 0x0000FF00;
107 const Uint32 Bmask = 0x00FF0000;
108 #else
109 const Uint32 Rmask = 0xFF000000 >> 8;
110 const Uint32 Gmask = 0x00FF0000 >> 8;
111 const Uint32 Bmask = 0x0000FF00 >> 8;
112 #endif
113
114 mng->buffer = new unsigned char[width * height * 3];
115 memset(mng->buffer, width * height * 3, sizeof(unsigned char));
116
117 mng->surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
118 8 * 3, Rmask, Gmask, Bmask, 0);
119 if (mng->surface == NULL) {
120 fprintf(stderr, "Out of memory");
121 exit(1);
122 }
123
124 return MNG_TRUE;
125 }
126
my_getcanvasline(mng_handle handle,mng_uint32 linenr)127 static mng_ptr MNG_DECL my_getcanvasline(mng_handle handle, mng_uint32 linenr)
128 {
129 Mng *mng;
130
131 mng = (Mng *)mng_get_userdata(handle);
132 return mng->buffer + linenr * mng->surface->w * 3;
133 }
134
my_refresh(mng_handle handle,mng_uint32,mng_uint32,mng_uint32,mng_uint32)135 static mng_bool MNG_DECL my_refresh(mng_handle handle, mng_uint32, mng_uint32,
136 mng_uint32, mng_uint32)
137 {
138 Mng *mng = (Mng *)mng_get_userdata(handle);
139 SDL_LockSurface(mng->surface);
140 for (int i = 0; i < mng->surface->h; ++i) {
141 memcpy((char *)mng->surface->pixels + i * mng->surface->pitch,
142 mng->buffer + i * mng->surface->w * 3, mng->surface->w * 3);
143 }
144 SDL_UnlockSurface(mng->surface);
145
146 return MNG_TRUE;
147 }
148
my_gettickcount(mng_handle)149 static mng_uint32 MNG_DECL my_gettickcount(mng_handle)
150 {
151 return GetTicks();
152 }
153
my_settimer(mng_handle handle,mng_uint32 msecs)154 static mng_bool MNG_DECL my_settimer(mng_handle handle, mng_uint32 msecs)
155 {
156 Mng *mng = (Mng *)mng_get_userdata(handle);
157 mng->ticks = GetTicks() + msecs;
158
159 return MNG_TRUE;
160 }
161
my_processmend(mng_handle handle,mng_uint32 iterationsdone,mng_uint32)162 static mng_bool MNG_DECL my_processmend(mng_handle handle, mng_uint32 iterationsdone,
163 mng_uint32)
164 {
165 Mng *mng = (Mng *)mng_get_userdata(handle);
166 mng->iteration = iterationsdone;
167
168 return MNG_TRUE;
169 }
170
my_errorproc(mng_handle handle,mng_int32,mng_int8,mng_chunkid,mng_uint32,mng_int32,mng_int32,mng_pchar errortext)171 static mng_bool MNG_DECL my_errorproc(mng_handle handle, mng_int32,
172 mng_int8, mng_chunkid, mng_uint32, mng_int32, mng_int32, mng_pchar errortext)
173 {
174 Mng *mng = (Mng *)mng_get_userdata(handle);
175 mng->iteration = 0x7fffffff;
176 if (errortext) {
177 DebugPrint("MNG error: %s\n" _C_ errortext);
178 }
179 return TRUE;
180 }
181
182
Mng()183 Mng::Mng() :
184 name(NULL), fd(NULL), handle(NULL), surface(NULL), buffer(NULL),
185 ticks(0), iteration(0), is_dirty(false)
186 {
187 }
188
189
~Mng()190 Mng::~Mng()
191 {
192 // delete[] name;
193 if (handle) {
194 mng_cleanup(&handle);
195 }
196 if (surface) {
197 SDL_FreeSurface(surface);
198 }
199 delete[] buffer;
200 }
201
202
203 /**
204 ** Display a MNG
205 **
206 ** @param x X coordinate
207 ** @param y Y coordinate
208 */
Draw(int x,int y)209 void Mng::Draw(int x, int y)
210 {
211 if (ticks <= GetTicks()) {
212 mng_display_resume(handle);
213 }
214
215 SDL_Rect rect = {(short int)x, (short int)y, (short unsigned int)(surface->w), (short unsigned int)(surface->h)};
216 SDL_BlitSurface(surface, NULL, TheScreen, &rect);
217 }
218
219 /**
220 ** Load a MNG
221 **
222 ** @param name Name of the MNG file
223 */
Load(const std::string & name)224 bool Mng::Load(const std::string &name)
225 {
226 this->name = LibraryFileName(name.c_str());
227 handle = mng_initialize(this, my_alloc, my_free, MNG_NULL);
228 if (handle == MNG_NULL) {
229 return false;
230 }
231 mng_setcb_openstream(handle, my_openstream);
232 mng_setcb_closestream(handle, my_closestream);
233 mng_setcb_readdata(handle, my_readdata);
234 mng_setcb_processheader(handle, my_processheader);
235 mng_setcb_processmend(handle, my_processmend);
236 mng_setcb_getcanvasline(handle, my_getcanvasline);
237 mng_setcb_refresh(handle, my_refresh);
238 mng_setcb_gettickcount(handle, my_gettickcount);
239 mng_setcb_settimer(handle, my_settimer);
240 mng_setcb_errorproc(handle, my_errorproc);
241
242 mng_read(handle);
243 if (surface && iteration != 0x7fffffff) {
244 mng_display(handle);
245 }
246
247 if (!surface || iteration == 0x7fffffff) {
248 return false;
249 }
250 return true;
251 }
252
253 /**
254 ** Reset a MNG
255 */
Reset()256 void Mng::Reset()
257 {
258 mng_display_reset(handle);
259 iteration = 0;
260 mng_display(handle);
261 }
262
_getData() const263 void* Mng::_getData() const
264 {
265 if (ticks <= GetTicks()) {
266 is_dirty = true;
267 mng_display_resume(handle);
268 } else {
269 is_dirty = false;
270 }
271 return surface;
272 }
273
274 #endif // USE_MNG
275
276 //@}
277