00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029 #ifndef ALPHA_LINUX_CXX
00030 # include <cstring>
00031 #endif
00032 #include <iostream>
00033 #include "databuf.h"
00034 #include "playfli.h"
00035 #include "utils.h"
00036 #include "gamewin.h"
00037 #include "palette.h"
00038
00039 #include "SDL_timer.h"
00040
00041 #ifndef UNDER_CE
00042 using std::ifstream;
00043 using std::memset;
00044 using std::size_t;
00045 using std::cout;
00046 using std::endl;
00047 #endif
00048
00049 playfli::playfli(const char *fli_name)
00050 {
00051 ifstream fli_stream;
00052 U7open(fli_stream, fli_name);
00053 fli_data = new StreamDataSource(&fli_stream);
00054
00055 initfli();
00056 }
00057
00058 playfli::playfli(char *buffer, size_t len): fli_data(new BufferDataSource(buffer, len))
00059 {
00060 initfli();
00061 }
00062
00063 void playfli::initfli()
00064 {
00065 fli_size = fli_data->read4();
00066 fli_magic = fli_data->read2();
00067 fli_frames = fli_data->read2();
00068 fli_width = fli_data->read2();
00069 fli_height = fli_data->read2();
00070 fli_depth = fli_data->read2();
00071 fli_flags = fli_data->read2();
00072 fli_speed = fli_data->read2();
00073 fli_buf = NULL;
00074 fli_data->skip(110);
00075 streampos = streamstart = fli_data->getPos();
00076 frame = 0;
00077 palette = new Palette;
00078 thispal = -1;
00079 nextpal = 0;
00080 changepal = false;
00081 }
00082
00083
00084 void playfli::info(fliinfo *fi)
00085 {
00086 #ifdef DEBUG
00087 cout << "Frame count : " << fli_frames << endl;
00088 cout << "Width : " << fli_width << endl;
00089 cout << "Height : " << fli_height << endl;
00090 cout << "Depth : " << fli_depth << endl;
00091 cout << "Speed : " << fli_speed << endl;
00092 #endif
00093 if (fi)
00094 {
00095 fi->frames = fli_frames;
00096 fi->width = fli_width;
00097 fi->height = fli_height;
00098 fi->depth = fli_depth;
00099 fi->speed = fli_speed;
00100 }
00101 }
00102
00103 int playfli::play(Image_window *win, int first_frame, int last_frame, unsigned long ticks, int brightness)
00104 {
00105 int frame_size;
00106 int frame_magic;
00107 int frame_chunks;
00108 int chunk_size;
00109 int chunk_type;
00110 unsigned char *pixbuf;
00111 int xoffset=(win->get_width()-fli_width)/2;
00112 int yoffset=(win->get_height()-fli_height)/2;
00113 bool dont_show = false;
00114
00115 if (!fli_buf && win) fli_buf = win->create_buffer (fli_width, fli_height);
00116
00117
00118 if (first_frame == last_frame) dont_show = true;
00119 if (first_frame < 0) first_frame += fli_frames;
00120 if (last_frame < 0) last_frame += 1 + fli_frames;
00121 if (first_frame == last_frame) last_frame++;
00122 if (last_frame < 0 || last_frame > fli_frames) last_frame = fli_frames;
00123
00124 if (!ticks) ticks = SDL_GetTicks();
00125
00126 if (first_frame < frame)
00127 {
00128 nextpal = 0;
00129 frame = 0;
00130 streampos = streamstart;
00131 }
00132 pixbuf = new unsigned char[fli_width];
00133
00134 if (brightness != palette->get_brightness())
00135 {
00136 palette->set_brightness(brightness);
00137 changepal = true;
00138 }
00139
00140
00141 for ( ; frame < last_frame; frame++)
00142 {
00143 fli_data->seek(streampos);
00144 frame_size = fli_data->read4();
00145 frame_magic = fli_data->read2();
00146 frame_chunks = fli_data->read2();
00147 fli_data->skip(8);
00148 for (int chunk = 0; chunk < frame_chunks; chunk++)
00149 {
00150 chunk_size = fli_data->read4();
00151 chunk_type = fli_data->read2();
00152
00153 switch (chunk_type)
00154 {
00155 case 11: {
00156 int packets = fli_data->read2();
00157 unsigned char colors[3 * 256];
00158
00159 memset(colors, 0, 3 * 256);
00160 int current = 0;
00161
00162 for (int p_count = 0; p_count < packets;
00163 p_count++)
00164 {
00165 int skip = fli_data->read1();
00166
00167 current += skip;
00168 int change = fli_data->read1();
00169
00170 if (change == 0)
00171 change = 256;
00172 fli_data->read((char*)&colors[current*3], change*3);
00173 }
00174
00175 palette->set_palette (colors);
00176 if (thispal != nextpal)
00177 {
00178 thispal = nextpal;
00179 changepal = true;
00180 }
00181 nextpal++;
00182
00183 } break;
00184
00185 case 12: {
00186
00187 int skip_lines = fli_data->read2();
00188 int change_lines = fli_data->read2();
00189 for (int line = 0; line < change_lines; line++)
00190 {
00191 int packets = fli_data->read1();
00192 int pixpos = 0;
00193 for (int p_count = 0; p_count < packets;
00194 p_count++)
00195 {
00196 int skip_count = fli_data->read1();
00197 pixpos += skip_count;
00198 uint8 size_count = fli_data->read1();
00199 if (size_count > 127)
00200 {
00201 size_count = 256 - size_count;
00202 unsigned char data = fli_data->read1();
00203 memset(pixbuf, data, size_count);
00204 if (fli_buf) fli_buf->copy8(pixbuf,size_count,1,pixpos,skip_lines+line);
00205 pixpos += size_count;
00206
00207 }
00208 else
00209 {
00210 fli_data->read((char*)pixbuf, size_count);
00211 if (fli_buf) fli_buf->copy8(pixbuf,size_count,1,pixpos, skip_lines+line);
00212 pixpos += size_count;
00213 }
00214 }
00215 }
00216
00217 } break;
00218
00219 case 13:
00220 break;
00221
00222 case 15: {
00223 for (int line = 0; line < fli_height; line++)
00224 {
00225 int packets = fli_data->read1();
00226 int pixpos = 0;
00227 for (int p_count = 0; p_count < packets;
00228 p_count++)
00229 {
00230 char size_count = fli_data->read1();
00231 if (size_count > 0)
00232 {
00233 unsigned char data = fli_data->read1();
00234 memset(&pixbuf[pixpos], data, size_count);
00235 pixpos += size_count;
00236 } else {
00237 fli_data->read((char*)&pixbuf[pixpos],
00238 -size_count);
00239 pixpos -= size_count;
00240 }
00241 }
00242 if (fli_buf) fli_buf->copy8(pixbuf,fli_width,1,0,line);
00243 }
00244 } break;
00245
00246 case 16:
00247 fli_data->skip(fli_width * fli_height);
00248 break;
00249
00250 default:
00251 cout << "UNKNOWN FLIC FRAME" << endl;
00252 break;
00253 }
00254 }
00255
00256 streampos += frame_size;
00257
00258 if (changepal) palette->apply(false);
00259 changepal = false;
00260
00261 if (frame < first_frame)
00262 continue;
00263
00264
00265 int skip_frame = Game_window::get_instance()->get_frame_skipping() && SDL_GetTicks() >= ticks;
00266
00267 if(win && fli_buf) win->put (fli_buf, xoffset, yoffset);
00268
00269 while (SDL_GetTicks() < ticks) SDL_Delay(0);
00270
00271 ticks += fli_speed*10;
00272
00273 if(win && !dont_show && !skip_frame)
00274 win->show();
00275 }
00276
00277 delete[] pixbuf;
00278
00279 return ticks;
00280 }
00281
00282 void playfli::put_buffer(Image_window *win)
00283 {
00284 int xoffset=(win->get_width()-fli_width)/2;
00285 int yoffset=(win->get_height()-fli_height)/2;
00286
00287 if(win && fli_buf) win->put (fli_buf, xoffset, yoffset);
00288 }
00289
00290 playfli::~playfli()
00291 {
00292 if (fli_buf) delete fli_buf;
00293 delete fli_data;
00294 delete palette;
00295 }