00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../video/video_driver.hpp"
00014 #include "32bpp_anim.hpp"
00015
00016 #include "../table/sprites.h"
00017
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 uint16 *src_n = (const uint16 *)(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 uint16 *)((const byte *)src_n + *(const uint32 *)src_n);
00032 }
00033
00034 Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
00035 uint16 *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 Colour *dst_ln = dst + bp->pitch;
00041 uint16 *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 uint16 *src_n_ln = (const uint16 *)((const byte *)src_n + *(const uint32 *)src_n);
00047 src_n += 2;
00048
00049 Colour *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[GB(m, 0, 8)];
00109 *anim = r | (m & 0xFF00);
00110 if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8));
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[GB(m, 0, 8)];
00125 *anim = 0;
00126 if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), 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_CRASH_REMAP:
00137 if (src_px->a == 255) {
00138 do {
00139 uint m = *src_n;
00140 if (m == 0) {
00141 uint8 g = MakeDark(src_px->r, src_px->g, src_px->b);
00142 *dst = ComposeColourRGBA(g, g, g, src_px->a, *dst);
00143 *anim = 0;
00144 } else {
00145 uint r = remap[GB(m, 0, 8)];
00146 *anim = r | (m & 0xFF00);
00147 if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8));
00148 }
00149 anim++;
00150 dst++;
00151 src_px++;
00152 src_n++;
00153 } while (--n != 0);
00154 } else {
00155 do {
00156 uint m = *src_n;
00157 if (m == 0) {
00158 if (src_px->a != 0) {
00159 uint8 g = MakeDark(src_px->r, src_px->g, src_px->b);
00160 *dst = ComposeColourRGBA(g, g, g, src_px->a, *dst);
00161 *anim = 0;
00162 }
00163 } else {
00164 uint r = remap[GB(m, 0, 8)];
00165 *anim = 0;
00166 if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst);
00167 }
00168 anim++;
00169 dst++;
00170 src_px++;
00171 src_n++;
00172 } while (--n != 0);
00173 }
00174 break;
00175
00176 case BM_TRANSPARENT:
00177
00178
00179
00180
00181
00182 src_n += n;
00183 if (src_px->a == 255) {
00184 src_px += n;
00185 do {
00186 *dst = MakeTransparent(*dst, 3, 4);
00187 *anim = 0;
00188 anim++;
00189 dst++;
00190 } while (--n != 0);
00191 } else {
00192 do {
00193 *dst = MakeTransparent(*dst, (256 * 4 - src_px->a), 256 * 4);
00194 *anim = 0;
00195 anim++;
00196 dst++;
00197 src_px++;
00198 } while (--n != 0);
00199 }
00200 break;
00201
00202 default:
00203 if (src_px->a == 255) {
00204 do {
00205
00206 uint m = GB(*src_n, 0, 8);
00207
00208 *anim++ = *src_n;
00209 *dst++ = (m >= PALETTE_ANIM_START) ? this->AdjustBrightness(this->LookupColourInPalette(m), GB(*src_n, 8, 8)) : src_px->data;
00210 src_px++;
00211 src_n++;
00212 } while (--n != 0);
00213 } else {
00214 do {
00215 uint m = GB(*src_n, 0, 8);
00216 *anim++ = 0;
00217 if (m >= PALETTE_ANIM_START) {
00218 *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(m), GB(*src_n, 8, 8)), src_px->a, *dst);
00219 } else {
00220 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00221 }
00222 dst++;
00223 src_px++;
00224 src_n++;
00225 } while (--n != 0);
00226 }
00227 break;
00228 }
00229 }
00230
00231 anim = anim_ln;
00232 dst = dst_ln;
00233 src_px = src_px_ln;
00234 src_n = src_n_ln;
00235 }
00236 }
00237
00238 void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
00239 {
00240 if (_screen_disable_anim) {
00241
00242 Blitter_32bppOptimized::Draw(bp, mode, zoom);
00243 return;
00244 }
00245
00246 switch (mode) {
00247 default: NOT_REACHED();
00248 case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
00249 case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
00250 case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
00251 case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP> (bp, zoom); return;
00252 }
00253 }
00254
00255 void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)
00256 {
00257 if (_screen_disable_anim) {
00258
00259 Blitter_32bppOptimized::DrawColourMappingRect(dst, width, height, pal);
00260 return;
00261 }
00262
00263 Colour *udst = (Colour *)dst;
00264 uint16 *anim;
00265
00266 anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);
00267
00268 if (pal == PALETTE_TO_TRANSPARENT) {
00269 do {
00270 for (int i = 0; i != width; i++) {
00271 *udst = MakeTransparent(*udst, 154);
00272 *anim = 0;
00273 udst++;
00274 anim++;
00275 }
00276 udst = udst - width + _screen.pitch;
00277 anim = anim - width + this->anim_buf_width;
00278 } while (--height);
00279 return;
00280 }
00281 if (pal == PALETTE_NEWSPAPER) {
00282 do {
00283 for (int i = 0; i != width; i++) {
00284 *udst = MakeGrey(*udst);
00285 *anim = 0;
00286 udst++;
00287 anim++;
00288 }
00289 udst = udst - width + _screen.pitch;
00290 anim = anim - width + this->anim_buf_width;
00291 } while (--height);
00292 return;
00293 }
00294
00295 DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('%d')", pal);
00296 }
00297
00298 void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
00299 {
00300 *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
00301
00302
00303 if (_screen_disable_anim) return;
00304 this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour | (DEFAULT_BRIGHTNESS << 8);
00305 }
00306
00307 void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
00308 {
00309 if (_screen_disable_anim) {
00310
00311 Blitter_32bppOptimized::DrawRect(video, width, height, colour);
00312 return;
00313 }
00314
00315 Colour colour32 = LookupColourInPalette(colour);
00316 uint16 *anim_line;
00317
00318 anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00319
00320 do {
00321 Colour *dst = (Colour *)video;
00322 uint16 *anim = anim_line;
00323
00324 for (int i = width; i > 0; i--) {
00325 *dst = colour32;
00326
00327 *anim = colour | (DEFAULT_BRIGHTNESS << 8);
00328 dst++;
00329 anim++;
00330 }
00331 video = (uint32 *)video + _screen.pitch;
00332 anim_line += this->anim_buf_width;
00333 } while (--height);
00334 }
00335
00336 void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
00337 {
00338 assert(!_screen_disable_anim);
00339 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00340 Colour *dst = (Colour *)video;
00341 const uint32 *usrc = (const uint32 *)src;
00342 uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00343
00344 for (; height > 0; height--) {
00345
00346 Colour *dst_pal = dst;
00347 uint16 *anim_pal = anim_line;
00348
00349 memcpy(dst, usrc, width * sizeof(uint32));
00350 usrc += width;
00351 dst += _screen.pitch;
00352
00353 memcpy(anim_line, usrc, width * sizeof(uint16));
00354 usrc = (const uint32 *)((const uint16 *)usrc + width);
00355 anim_line += this->anim_buf_width;
00356
00357
00358
00359
00360
00361
00362
00363
00364 for (int i = 0; i < width; i++) {
00365 uint colour = GB(*anim_pal, 0, 8);
00366 if (colour >= PALETTE_ANIM_START) {
00367
00368 *dst_pal = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim_pal, 8, 8));
00369 }
00370 dst_pal++;
00371 anim_pal++;
00372 }
00373 }
00374 }
00375
00376 void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
00377 {
00378 assert(!_screen_disable_anim);
00379 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00380 uint32 *udst = (uint32 *)dst;
00381 const uint32 *src = (const uint32 *)video;
00382 const uint16 *anim_line;
00383
00384 if (this->anim_buf == NULL) return;
00385
00386 anim_line = ((const uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00387
00388 for (; height > 0; height--) {
00389 memcpy(udst, src, width * sizeof(uint32));
00390 src += _screen.pitch;
00391 udst += width;
00392
00393 memcpy(udst, anim_line, width * sizeof(uint16));
00394 udst = (uint32 *)((uint16 *)udst + width);
00395 anim_line += this->anim_buf_width;
00396 }
00397 }
00398
00399 void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
00400 {
00401 assert(!_screen_disable_anim);
00402 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00403 uint16 *dst, *src;
00404
00405
00406 if (scroll_y > 0) {
00407 dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
00408 src = dst - scroll_y * this->anim_buf_width;
00409
00410
00411 if (scroll_x >= 0) {
00412 dst += scroll_x;
00413 } else {
00414 src -= scroll_x;
00415 }
00416
00417 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00418 uint th = height - scroll_y;
00419 for (; th > 0; th--) {
00420 memcpy(dst, src, tw * sizeof(uint16));
00421 src -= this->anim_buf_width;
00422 dst -= this->anim_buf_width;
00423 }
00424 } else {
00425
00426 dst = this->anim_buf + left + top * this->anim_buf_width;
00427 src = dst - scroll_y * this->anim_buf_width;
00428
00429
00430 if (scroll_x >= 0) {
00431 dst += scroll_x;
00432 } else {
00433 src -= scroll_x;
00434 }
00435
00436
00437
00438 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00439 uint th = height + scroll_y;
00440 for (; th > 0; th--) {
00441 memmove(dst, src, tw * sizeof(uint16));
00442 src += this->anim_buf_width;
00443 dst += this->anim_buf_width;
00444 }
00445 }
00446
00447 Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
00448 }
00449
00450 int Blitter_32bppAnim::BufferSize(int width, int height)
00451 {
00452 return width * height * (sizeof(uint32) + sizeof(uint16));
00453 }
00454
00455 void Blitter_32bppAnim::PaletteAnimate(const Palette &palette)
00456 {
00457 assert(!_screen_disable_anim);
00458
00459 this->palette = palette;
00460
00461
00462
00463 assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0);
00464
00465 const uint16 *anim = this->anim_buf;
00466 Colour *dst = (Colour *)_screen.dst_ptr;
00467
00468
00469 for (int y = this->anim_buf_height; y != 0 ; y--) {
00470 for (int x = this->anim_buf_width; x != 0 ; x--) {
00471 uint colour = GB(*anim, 0, 8);
00472 if (colour >= PALETTE_ANIM_START) {
00473
00474 *dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8));
00475 }
00476 dst++;
00477 anim++;
00478 }
00479 dst += _screen.pitch - this->anim_buf_width;
00480 }
00481
00482
00483 VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height);
00484 }
00485
00486 Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
00487 {
00488 return Blitter::PALETTE_ANIMATION_BLITTER;
00489 }
00490
00491 void Blitter_32bppAnim::PostResize()
00492 {
00493 if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
00494
00495 free(this->anim_buf);
00496 this->anim_buf = CallocT<uint16>(_screen.width * _screen.height);
00497 this->anim_buf_width = _screen.width;
00498 this->anim_buf_height = _screen.height;
00499 }
00500 }