00001
00002
00005 #include "../stdafx.h"
00006 #include "../core/alloc_func.hpp"
00007 #include "../core/math_func.hpp"
00008 #include "../gfx_func.h"
00009 #include "../video/video_driver.hpp"
00010 #include "32bpp_anim.hpp"
00011
00012 #include "../table/sprites.h"
00013
00014 static FBlitter_32bppAnim iFBlitter_32bppAnim;
00015
00016 template <BlitterMode mode>
00017 inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
00018 {
00019 const SpriteData *src = (const SpriteData *)bp->sprite;
00020
00021 const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
00022 const uint8 *src_n = (const uint8 *)(src->data + src->offset[zoom][1]);
00023
00024 for (uint i = bp->skip_top; i != 0; i--) {
00025 src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00026 src_n += *(const uint32 *)src_n;
00027 }
00028
00029 uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
00030 uint8 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
00031
00032 const byte *remap = bp->remap;
00033
00034 for (int y = 0; y < bp->height; y++) {
00035 uint32 *dst_ln = dst + bp->pitch;
00036 uint8 *anim_ln = anim + this->anim_buf_width;
00037
00038 const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
00039 src_px++;
00040
00041 const uint8 *src_n_ln = src_n + *(uint32 *)src_n;
00042 src_n += 4;
00043
00044 uint32 *dst_end = dst + bp->skip_left;
00045
00046 uint n;
00047
00048 while (dst < dst_end) {
00049 n = *src_n++;
00050
00051 if (src_px->a == 0) {
00052 dst += n;
00053 src_px ++;
00054 src_n++;
00055
00056 if (dst > dst_end) anim += dst - dst_end;
00057 } else {
00058 if (dst + n > dst_end) {
00059 uint d = dst_end - dst;
00060 src_px += d;
00061 src_n += d;
00062
00063 dst = dst_end - bp->skip_left;
00064 dst_end = dst + bp->width;
00065
00066 n = min<uint>(n - d, (uint)bp->width);
00067 goto draw;
00068 }
00069 dst += n;
00070 src_px += n;
00071 src_n += n;
00072 }
00073 }
00074
00075 dst -= bp->skip_left;
00076 dst_end -= bp->skip_left;
00077
00078 dst_end += bp->width;
00079
00080 while (dst < dst_end) {
00081 n = min<uint>(*src_n++, (uint)(dst_end - dst));
00082
00083 if (src_px->a == 0) {
00084 anim += n;
00085 dst += n;
00086 src_px++;
00087 src_n++;
00088 continue;
00089 }
00090
00091 draw:;
00092
00093 switch (mode) {
00094 case BM_COLOUR_REMAP:
00095 if (src_px->a == 255) {
00096 do {
00097 uint m = *src_n;
00098
00099 if (m == 0) {
00100 *dst = *src_px;
00101 *anim = 0;
00102 } else {
00103 uint r = remap[m];
00104 *anim = r;
00105 if (r != 0) *dst = this->LookupColourInPalette(r);
00106 }
00107 anim++;
00108 dst++;
00109 src_px++;
00110 src_n++;
00111 } while (--n != 0);
00112 } else {
00113 do {
00114 uint m = *src_n;
00115 if (m == 0) {
00116 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00117 *anim = 0;
00118 } else {
00119 uint r = remap[m];
00120 *anim = r;
00121 if (r != 0) *dst = ComposeColourPANoCheck(this->LookupColourInPalette(r), src_px->a, *dst);
00122 }
00123 anim++;
00124 dst++;
00125 src_px++;
00126 src_n++;
00127 } while (--n != 0);
00128 }
00129 break;
00130
00131 case BM_TRANSPARENT:
00132
00133
00134
00135
00136
00137 src_n += n;
00138 if (src_px->a == 255) {
00139 src_px += n;
00140 do {
00141 *dst = MakeTransparent(*dst, 3, 4);
00142 *anim = remap[*anim];
00143 anim++;
00144 dst++;
00145 } while (--n != 0);
00146 } else {
00147 do {
00148 *dst = MakeTransparent(*dst, (256 * 4 - src_px->a), 256 * 4);
00149 *anim = remap[*anim];
00150 anim++;
00151 dst++;
00152 src_px++;
00153 } while (--n != 0);
00154 }
00155 break;
00156
00157 default:
00158 if (src_px->a == 255) {
00159 do {
00160
00161 uint m = *src_n++;
00162
00163 *anim++ = m;
00164 *dst++ = (m >= PALETTE_ANIM_SIZE_START) ? this->LookupColourInPalette(m) : *src_px;
00165 src_px++;
00166 } while (--n != 0);
00167 } else {
00168 do {
00169 uint m = *src_n++;
00170 *anim++ = m;
00171 if (m >= PALETTE_ANIM_SIZE_START) {
00172 *dst = ComposeColourPANoCheck(this->LookupColourInPalette(m), src_px->a, *dst);
00173 } else {
00174 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00175 }
00176 dst++;
00177 src_px++;
00178 } while (--n != 0);
00179 }
00180 break;
00181 }
00182 }
00183
00184 anim = anim_ln;
00185 dst = dst_ln;
00186 src_px = src_px_ln;
00187 src_n = src_n_ln;
00188 }
00189 }
00190
00191 void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
00192 {
00193 if (_screen_disable_anim) {
00194
00195 Blitter_32bppOptimized::Draw(bp, mode, zoom);
00196 return;
00197 }
00198
00199 if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
00200
00201 free(this->anim_buf);
00202 this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
00203 this->anim_buf_width = _screen.width;
00204 this->anim_buf_height = _screen.height;
00205 }
00206
00207 switch (mode) {
00208 default: NOT_REACHED();
00209 case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
00210 case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
00211 case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
00212 }
00213 }
00214
00215 void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height, int pal)
00216 {
00217 if (_screen_disable_anim) {
00218
00219 Blitter_32bppOptimized::DrawColourMappingRect(dst, width, height, pal);
00220 return;
00221 }
00222
00223 uint32 *udst = (uint32 *)dst;
00224 uint8 *anim;
00225
00226 anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);
00227
00228 if (pal == PALETTE_TO_TRANSPARENT) {
00229 do {
00230 for (int i = 0; i != width; i++) {
00231 *udst = MakeTransparent(*udst, 154);
00232 *anim = 0;
00233 udst++;
00234 anim++;
00235 }
00236 udst = udst - width + _screen.pitch;
00237 anim = anim - width + this->anim_buf_width;
00238 } while (--height);
00239 return;
00240 }
00241 if (pal == PALETTE_TO_STRUCT_GREY) {
00242 do {
00243 for (int i = 0; i != width; i++) {
00244 *udst = MakeGrey(*udst);
00245 *anim = 0;
00246 udst++;
00247 anim++;
00248 }
00249 udst = udst - width + _screen.pitch;
00250 anim = anim - width + this->anim_buf_width;
00251 } while (--height);
00252 return;
00253 }
00254
00255 DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('%d')", pal);
00256 }
00257
00258 void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
00259 {
00260 *((uint32 *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
00261
00262
00263 if (_screen_disable_anim) return;
00264 this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour;
00265 }
00266
00267 void Blitter_32bppAnim::SetPixelIfEmpty(void *video, int x, int y, uint8 colour)
00268 {
00269 uint32 *dst = (uint32 *)video + x + y * _screen.pitch;
00270 if (*dst == 0) {
00271 *dst = LookupColourInPalette(colour);
00272
00273 if (_screen_disable_anim) return;
00274 this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour;
00275 }
00276 }
00277
00278 void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
00279 {
00280 if (_screen_disable_anim) {
00281
00282 Blitter_32bppOptimized::DrawRect(video, width, height, colour);
00283 return;
00284 }
00285
00286 uint32 colour32 = LookupColourInPalette(colour);
00287 uint8 *anim_line;
00288
00289 anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00290
00291 do {
00292 uint32 *dst = (uint32 *)video;
00293 uint8 *anim = anim_line;
00294
00295 for (int i = width; i > 0; i--) {
00296 *dst = colour32;
00297
00298 *anim = colour;
00299 dst++;
00300 anim++;
00301 }
00302 video = (uint32 *)video + _screen.pitch;
00303 anim_line += this->anim_buf_width;
00304 } while (--height);
00305 }
00306
00307 void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
00308 {
00309 assert(!_screen_disable_anim);
00310 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00311 uint32 *dst = (uint32 *)video;
00312 uint32 *usrc = (uint32 *)src;
00313 uint8 *anim_line;
00314
00315 anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00316
00317 for (; height > 0; height--) {
00318 memcpy(dst, usrc, width * sizeof(uint32));
00319 usrc += width;
00320 dst += _screen.pitch;
00321
00322 memcpy(anim_line, usrc, width * sizeof(uint8));
00323 usrc = (uint32 *)((uint8 *)usrc + width);
00324 anim_line += this->anim_buf_width;
00325 }
00326
00327
00328 this->PaletteAnimate(PALETTE_ANIM_SIZE_START, (_use_palette == PAL_DOS) ? PALETTE_ANIM_SIZE_DOS : PALETTE_ANIM_SIZE_WIN);
00329 }
00330
00331 void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
00332 {
00333 assert(!_screen_disable_anim);
00334 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00335 uint32 *udst = (uint32 *)dst;
00336 uint32 *src = (uint32 *)video;
00337 uint8 *anim_line;
00338
00339 if (this->anim_buf == NULL) return;
00340
00341 anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00342
00343 for (; height > 0; height--) {
00344 memcpy(udst, src, width * sizeof(uint32));
00345 src += _screen.pitch;
00346 udst += width;
00347
00348 memcpy(udst, anim_line, width * sizeof(uint8));
00349 udst = (uint32 *)((uint8 *)udst + width);
00350 anim_line += this->anim_buf_width;
00351 }
00352 }
00353
00354 void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
00355 {
00356 assert(!_screen_disable_anim);
00357 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00358 uint8 *dst, *src;
00359
00360
00361 if (scroll_y > 0) {
00362 dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
00363 src = dst - scroll_y * this->anim_buf_width;
00364
00365
00366 if (scroll_x >= 0) dst += scroll_x;
00367 else src -= scroll_x;
00368
00369 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00370 uint th = height - scroll_y;
00371 for (; th > 0; th--) {
00372 memcpy(dst, src, tw * sizeof(uint8));
00373 src -= this->anim_buf_width;
00374 dst -= this->anim_buf_width;
00375 }
00376 } else {
00377
00378 dst = this->anim_buf + left + top * this->anim_buf_width;
00379 src = dst - scroll_y * this->anim_buf_width;
00380
00381
00382 if (scroll_x >= 0) dst += scroll_x;
00383 else src -= scroll_x;
00384
00385
00386
00387 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00388 uint th = height + scroll_y;
00389 for (; th > 0; th--) {
00390 memmove(dst, src, tw * sizeof(uint8));
00391 src += this->anim_buf_width;
00392 dst += this->anim_buf_width;
00393 }
00394 }
00395
00396 Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
00397 }
00398
00399 int Blitter_32bppAnim::BufferSize(int width, int height)
00400 {
00401 return width * height * (sizeof(uint32) + sizeof(uint8));
00402 }
00403
00404 void Blitter_32bppAnim::PaletteAnimate(uint start, uint count)
00405 {
00406 assert(!_screen_disable_anim);
00407
00408
00409 if (start == 0) {
00410 start++;
00411 count--;
00412 }
00413
00414 const uint8 *anim = this->anim_buf;
00415 uint32 *dst = (uint32 *)_screen.dst_ptr;
00416
00417
00418 for (int y = this->anim_buf_height; y != 0 ; y--) {
00419 for (int x = this->anim_buf_width; x != 0 ; x--) {
00420 uint colour = *anim;
00421 if (IsInsideBS(colour, start, count)) {
00422
00423 *dst = LookupColourInPalette(colour);
00424 }
00425 dst++;
00426 anim++;
00427 }
00428 dst += _screen.pitch - this->anim_buf_width;
00429 }
00430
00431
00432 _video_driver->MakeDirty(0, 0, _screen.width, _screen.height);
00433 }
00434
00435 Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
00436 {
00437 return Blitter::PALETTE_ANIMATION_BLITTER;
00438 }