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