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 uint32 *dst = (uint32 *)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 uint32 *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 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[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_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 = 0;
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 = 0;
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 = GB(*src_n, 0, 8);
00167
00168 *anim++ = *src_n;
00169 *dst++ = (m >= PALETTE_ANIM_START) ? this->AdjustBrightness(this->LookupColourInPalette(m), GB(*src_n, 8, 8)) : src_px->data;
00170 src_px++;
00171 src_n++;
00172 } while (--n != 0);
00173 } else {
00174 do {
00175 uint m = GB(*src_n, 0, 8);
00176 *anim++ = 0;
00177 if (m >= PALETTE_ANIM_START) {
00178 *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(m), GB(*src_n, 8, 8)), src_px->a, *dst);
00179 } else {
00180 *dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
00181 }
00182 dst++;
00183 src_px++;
00184 src_n++;
00185 } while (--n != 0);
00186 }
00187 break;
00188 }
00189 }
00190
00191 anim = anim_ln;
00192 dst = dst_ln;
00193 src_px = src_px_ln;
00194 src_n = src_n_ln;
00195 }
00196 }
00197
00198 void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
00199 {
00200 if (_screen_disable_anim) {
00201
00202 Blitter_32bppOptimized::Draw(bp, mode, zoom);
00203 return;
00204 }
00205
00206 switch (mode) {
00207 default: NOT_REACHED();
00208 case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
00209 case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
00210 case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
00211 }
00212 }
00213
00214 void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)
00215 {
00216 if (_screen_disable_anim) {
00217
00218 Blitter_32bppOptimized::DrawColourMappingRect(dst, width, height, pal);
00219 return;
00220 }
00221
00222 uint32 *udst = (uint32 *)dst;
00223 uint16 *anim;
00224
00225 anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);
00226
00227 if (pal == PALETTE_TO_TRANSPARENT) {
00228 do {
00229 for (int i = 0; i != width; i++) {
00230 *udst = MakeTransparent(*udst, 154);
00231 *anim = 0;
00232 udst++;
00233 anim++;
00234 }
00235 udst = udst - width + _screen.pitch;
00236 anim = anim - width + this->anim_buf_width;
00237 } while (--height);
00238 return;
00239 }
00240 if (pal == PALETTE_NEWSPAPER) {
00241 do {
00242 for (int i = 0; i != width; i++) {
00243 *udst = MakeGrey(*udst);
00244 *anim = 0;
00245 udst++;
00246 anim++;
00247 }
00248 udst = udst - width + _screen.pitch;
00249 anim = anim - width + this->anim_buf_width;
00250 } while (--height);
00251 return;
00252 }
00253
00254 DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('%d')", pal);
00255 }
00256
00257 void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
00258 {
00259 *((uint32 *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);
00260
00261
00262 if (_screen_disable_anim) return;
00263 this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour | (DEFAULT_BRIGHTNESS << 8);
00264 }
00265
00266 void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
00267 {
00268 if (_screen_disable_anim) {
00269
00270 Blitter_32bppOptimized::DrawRect(video, width, height, colour);
00271 return;
00272 }
00273
00274 uint32 colour32 = LookupColourInPalette(colour);
00275 uint16 *anim_line;
00276
00277 anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00278
00279 do {
00280 uint32 *dst = (uint32 *)video;
00281 uint16 *anim = anim_line;
00282
00283 for (int i = width; i > 0; i--) {
00284 *dst = colour32;
00285
00286 *anim = colour | (DEFAULT_BRIGHTNESS << 8);
00287 dst++;
00288 anim++;
00289 }
00290 video = (uint32 *)video + _screen.pitch;
00291 anim_line += this->anim_buf_width;
00292 } while (--height);
00293 }
00294
00295 void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
00296 {
00297 assert(!_screen_disable_anim);
00298 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00299 uint32 *dst = (uint32 *)video;
00300 const uint32 *usrc = (const uint32 *)src;
00301 uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00302
00303 for (; height > 0; height--) {
00304
00305 uint32 *dst_pal = dst;
00306 uint16 *anim_pal = anim_line;
00307
00308 memcpy(dst, usrc, width * sizeof(uint32));
00309 usrc += width;
00310 dst += _screen.pitch;
00311
00312 memcpy(anim_line, usrc, width * sizeof(uint16));
00313 usrc = (const uint32 *)((const uint16 *)usrc + width);
00314 anim_line += this->anim_buf_width;
00315
00316
00317
00318
00319
00320
00321
00322
00323 for (int i = 0; i < width; i++) {
00324 uint colour = GB(*anim_pal, 0, 8);
00325 if (colour >= PALETTE_ANIM_START) {
00326
00327 *dst_pal = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim_pal, 8, 8));
00328 }
00329 dst_pal++;
00330 anim_pal++;
00331 }
00332 }
00333 }
00334
00335 void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
00336 {
00337 assert(!_screen_disable_anim);
00338 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00339 uint32 *udst = (uint32 *)dst;
00340 const uint32 *src = (const uint32 *)video;
00341 const uint16 *anim_line;
00342
00343 if (this->anim_buf == NULL) return;
00344
00345 anim_line = ((const uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
00346
00347 for (; height > 0; height--) {
00348 memcpy(udst, src, width * sizeof(uint32));
00349 src += _screen.pitch;
00350 udst += width;
00351
00352 memcpy(udst, anim_line, width * sizeof(uint16));
00353 udst = (uint32 *)((uint16 *)udst + width);
00354 anim_line += this->anim_buf_width;
00355 }
00356 }
00357
00358 void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
00359 {
00360 assert(!_screen_disable_anim);
00361 assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
00362 uint16 *dst, *src;
00363
00364
00365 if (scroll_y > 0) {
00366 dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
00367 src = dst - scroll_y * this->anim_buf_width;
00368
00369
00370 if (scroll_x >= 0) {
00371 dst += scroll_x;
00372 } else {
00373 src -= scroll_x;
00374 }
00375
00376 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00377 uint th = height - scroll_y;
00378 for (; th > 0; th--) {
00379 memcpy(dst, src, tw * sizeof(uint16));
00380 src -= this->anim_buf_width;
00381 dst -= this->anim_buf_width;
00382 }
00383 } else {
00384
00385 dst = this->anim_buf + left + top * this->anim_buf_width;
00386 src = dst - scroll_y * this->anim_buf_width;
00387
00388
00389 if (scroll_x >= 0) {
00390 dst += scroll_x;
00391 } else {
00392 src -= scroll_x;
00393 }
00394
00395
00396
00397 uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
00398 uint th = height + scroll_y;
00399 for (; th > 0; th--) {
00400 memmove(dst, src, tw * sizeof(uint16));
00401 src += this->anim_buf_width;
00402 dst += this->anim_buf_width;
00403 }
00404 }
00405
00406 Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
00407 }
00408
00409 int Blitter_32bppAnim::BufferSize(int width, int height)
00410 {
00411 return width * height * (sizeof(uint32) + sizeof(uint16));
00412 }
00413
00414 void Blitter_32bppAnim::PaletteAnimate(const Palette &palette)
00415 {
00416 assert(!_screen_disable_anim);
00417
00418 this->palette = palette;
00419
00420
00421
00422 if (this->palette.first_dirty == 0) return;
00423 assert(this->palette.first_dirty == PALETTE_ANIM_START);
00424
00425 const uint16 *anim = this->anim_buf;
00426 uint32 *dst = (uint32 *)_screen.dst_ptr;
00427
00428
00429 for (int y = this->anim_buf_height; y != 0 ; y--) {
00430 for (int x = this->anim_buf_width; x != 0 ; x--) {
00431 uint colour = GB(*anim, 0, 8);
00432 if (colour >= PALETTE_ANIM_START) {
00433
00434 *dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8));
00435 }
00436 dst++;
00437 anim++;
00438 }
00439 dst += _screen.pitch - this->anim_buf_width;
00440 }
00441
00442
00443 _video_driver->MakeDirty(0, 0, _screen.width, _screen.height);
00444 }
00445
00446 Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
00447 {
00448 return Blitter::PALETTE_ANIMATION_BLITTER;
00449 }
00450
00451 void Blitter_32bppAnim::PostResize()
00452 {
00453 if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
00454
00455 free(this->anim_buf);
00456 this->anim_buf = CallocT<uint16>(_screen.width * _screen.height);
00457 this->anim_buf_width = _screen.width;
00458 this->anim_buf_height = _screen.height;
00459 }
00460 }