Files @ r14217:40beee5d2e82
Branch filter:

Location: cpp/openttd-patchpack/source/src/blitter/32bpp_anim.cpp - annotation

michi_cc
(svn r18778) -Fix [FS#3483]: [YAPP] Remove a special check for two-sided signals when reserving a path as this causes trains to get stuck in front of them.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
r8091:d63ba361d6b8
r8091:d63ba361d6b8
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r12768:980ae0491352
r9111:983de9c5a848
r9111:983de9c5a848
r6971:b3bdb012053e
r9548:44248dc324db
r8123:dde0a9a84019
r7170:38b143754b40
r6971:b3bdb012053e
r6971:b3bdb012053e
r8264:d493cb51fe8a
r8264:d493cb51fe8a
r6971:b3bdb012053e
r6971:b3bdb012053e
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r12204:a49bd04a557a
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r11085:c87a330fb4c2
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r11085:c87a330fb4c2
r9597:95581b9351bb
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9598:e6a0e60714ce
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9870:dd3f7f4ab6d7
r9597:95581b9351bb
r12204:a49bd04a557a
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9870:dd3f7f4ab6d7
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7557:1821f4ba38b6
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r9597:95581b9351bb
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r11085:c87a330fb4c2
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r11085:c87a330fb4c2
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r7552:47c4bace5157
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r11085:c87a330fb4c2
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r11085:c87a330fb4c2
r6971:b3bdb012053e
r11085:c87a330fb4c2
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r6971:b3bdb012053e
r6971:b3bdb012053e
r11085:c87a330fb4c2
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r11085:c87a330fb4c2
r11085:c87a330fb4c2
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r11085:c87a330fb4c2
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r11085:c87a330fb4c2
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r11085:c87a330fb4c2
r11085:c87a330fb4c2
r11085:c87a330fb4c2
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r9989:3df1ea4f0982
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6986:f09d57f6b2d7
r6986:f09d57f6b2d7
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r12752:0ee2ec59ee1c
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6979:c72bc9ef55cf
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r6979:c72bc9ef55cf
r6971:b3bdb012053e
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r6971:b3bdb012053e
r9548:44248dc324db
r6971:b3bdb012053e
r9548:44248dc324db
r6971:b3bdb012053e
r6971:b3bdb012053e
r9550:6041b660ac25
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7170:38b143754b40
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
r14151:b74c66bf771d
/* $Id$ */

/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/** @file 32bpp_anim.cpp Implementation of the optimized 32 bpp blitter with animation support. */

#include "../stdafx.h"
#include "../core/math_func.hpp"
#include "../gfx_func.h"
#include "../video/video_driver.hpp"
#include "32bpp_anim.hpp"

#include "../table/sprites.h"

static FBlitter_32bppAnim iFBlitter_32bppAnim;

template <BlitterMode mode>
inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
{
	const SpriteData *src = (const SpriteData *)bp->sprite;

	const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
	const uint8  *src_n  = (const uint8  *)(src->data + src->offset[zoom][1]);

	for (uint i = bp->skip_top; i != 0; i--) {
		src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
		src_n += *(const uint32 *)src_n;
	}

	uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
	uint8 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;

	const byte *remap = bp->remap; // store so we don't have to access it via bp everytime

	for (int y = 0; y < bp->height; y++) {
		uint32 *dst_ln = dst + bp->pitch;
		uint8 *anim_ln = anim + this->anim_buf_width;

		const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
		src_px++;

		const uint8 *src_n_ln = src_n + *(uint32 *)src_n;
		src_n += 4;

		uint32 *dst_end = dst + bp->skip_left;

		uint n;

		while (dst < dst_end) {
			n = *src_n++;

			if (src_px->a == 0) {
				dst += n;
				src_px ++;
				src_n++;

				if (dst > dst_end) anim += dst - dst_end;
			} else {
				if (dst + n > dst_end) {
					uint d = dst_end - dst;
					src_px += d;
					src_n += d;

					dst = dst_end - bp->skip_left;
					dst_end = dst + bp->width;

					n = min<uint>(n - d, (uint)bp->width);
					goto draw;
				}
				dst += n;
				src_px += n;
				src_n += n;
			}
		}

		dst -= bp->skip_left;
		dst_end -= bp->skip_left;

		dst_end += bp->width;

		while (dst < dst_end) {
			n = min<uint>(*src_n++, (uint)(dst_end - dst));

			if (src_px->a == 0) {
				anim += n;
				dst += n;
				src_px++;
				src_n++;
				continue;
			}

			draw:;

			switch (mode) {
				case BM_COLOUR_REMAP:
					if (src_px->a == 255) {
						do {
							uint m = *src_n;
							/* In case the m-channel is zero, do not remap this pixel in any way */
							if (m == 0) {
								*dst = src_px->data;
								*anim = 0;
							} else {
								uint r = remap[m];
								*anim = r;
								if (r != 0) *dst = this->LookupColourInPalette(r);
							}
							anim++;
							dst++;
							src_px++;
							src_n++;
						} while (--n != 0);
					} else {
						do {
							uint m = *src_n;
							if (m == 0) {
								*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
								*anim = 0;
							} else {
								uint r = remap[m];
								*anim = r;
								if (r != 0) *dst = ComposeColourPANoCheck(this->LookupColourInPalette(r), src_px->a, *dst);
							}
							anim++;
							dst++;
							src_px++;
							src_n++;
						} while (--n != 0);
					}
					break;

				case BM_TRANSPARENT:
					/* TODO -- We make an assumption here that the remap in fact is transparency, not some colour.
					 *  This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
					 *  we produce a result the newgrf maker didn't expect ;) */

					/* Make the current colour a bit more black, so it looks like this image is transparent */
					src_n += n;
					if (src_px->a == 255) {
						src_px += n;
						do {
							*dst = MakeTransparent(*dst, 3, 4);
							*anim = remap[*anim];
							anim++;
							dst++;
						} while (--n != 0);
					} else {
						do {
							*dst = MakeTransparent(*dst, (256 * 4 - src_px->a), 256 * 4);
							*anim = remap[*anim];
							anim++;
							dst++;
							src_px++;
						} while (--n != 0);
					}
					break;

				default:
					if (src_px->a == 255) {
						do {
							/* Compiler assumes pointer aliasing, can't optimise this on its own */
							uint m = *src_n++;
							/* Above 217 (PALETTE_ANIM_SIZE_START) is palette animation */
							*anim++ = m;
							*dst++ = (m >= PALETTE_ANIM_SIZE_START) ? this->LookupColourInPalette(m) : src_px->data;
							src_px++;
						} while (--n != 0);
					} else {
						do {
							uint m = *src_n++;
							*anim++ = m;
							if (m >= PALETTE_ANIM_SIZE_START) {
								*dst = ComposeColourPANoCheck(this->LookupColourInPalette(m), src_px->a, *dst);
							} else {
								*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
							}
							dst++;
							src_px++;
						} while (--n != 0);
					}
					break;
			}
		}

		anim = anim_ln;
		dst = dst_ln;
		src_px = src_px_ln;
		src_n  = src_n_ln;
	}
}

void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
	if (_screen_disable_anim) {
		/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
		Blitter_32bppOptimized::Draw(bp, mode, zoom);
		return;
	}

	switch (mode) {
		default: NOT_REACHED();
		case BM_NORMAL:       Draw<BM_NORMAL>      (bp, zoom); return;
		case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
		case BM_TRANSPARENT:  Draw<BM_TRANSPARENT> (bp, zoom); return;
	}
}

void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height, int pal)
{
	if (_screen_disable_anim) {
		/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawColourMappingRect() */
		Blitter_32bppOptimized::DrawColourMappingRect(dst, width, height, pal);
		return;
	}

	uint32 *udst = (uint32 *)dst;
	uint8 *anim;

	anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);

	if (pal == PALETTE_TO_TRANSPARENT) {
		do {
			for (int i = 0; i != width; i++) {
				*udst = MakeTransparent(*udst, 154);
				*anim = 0;
				udst++;
				anim++;
			}
			udst = udst - width + _screen.pitch;
			anim = anim - width + this->anim_buf_width;
		} while (--height);
		return;
	}
	if (pal == PALETTE_TO_STRUCT_GREY) {
		do {
			for (int i = 0; i != width; i++) {
				*udst = MakeGrey(*udst);
				*anim = 0;
				udst++;
				anim++;
			}
			udst = udst - width + _screen.pitch;
			anim = anim - width + this->anim_buf_width;
		} while (--height);
		return;
	}

	DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('%d')", pal);
}

void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
{
	*((uint32 *)video + x + y * _screen.pitch) = LookupColourInPalette(colour);

	/* Set the colour in the anim-buffer too, if we are rendering to the screen */
	if (_screen_disable_anim) return;
	this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour;
}

void Blitter_32bppAnim::SetPixelIfEmpty(void *video, int x, int y, uint8 colour)
{
	uint32 *dst = (uint32 *)video + x + y * _screen.pitch;
	if (*dst == 0) {
		*dst = LookupColourInPalette(colour);
		/* Set the colour in the anim-buffer too, if we are rendering to the screen */
		if (_screen_disable_anim) return;
		this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour;
	}
}

void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
{
	if (_screen_disable_anim) {
		/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent DrawRect() */
		Blitter_32bppOptimized::DrawRect(video, width, height, colour);
		return;
	}

	uint32 colour32 = LookupColourInPalette(colour);
	uint8 *anim_line;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	do {
		uint32 *dst = (uint32 *)video;
		uint8 *anim = anim_line;

		for (int i = width; i > 0; i--) {
			*dst = colour32;
			/* Set the colour in the anim-buffer too */
			*anim = colour;
			dst++;
			anim++;
		}
		video = (uint32 *)video + _screen.pitch;
		anim_line += this->anim_buf_width;
	} while (--height);
}

void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint32 *dst = (uint32 *)video;
	uint32 *usrc = (uint32 *)src;
	uint8 *anim_line;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	for (; height > 0; height--) {
		memcpy(dst, usrc, width * sizeof(uint32));
		usrc += width;
		dst += _screen.pitch;
		/* Copy back the anim-buffer */
		memcpy(anim_line, usrc, width * sizeof(uint8));
		usrc = (uint32 *)((uint8 *)usrc + width);
		anim_line += this->anim_buf_width;
	}

	/* We update the palette (or the pixels that do animation) immediatly, to avoid graphical glitches */
	this->PaletteAnimate(PALETTE_ANIM_SIZE_START, (_use_palette == PAL_DOS) ? PALETTE_ANIM_SIZE_DOS : PALETTE_ANIM_SIZE_WIN);
}

void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint32 *udst = (uint32 *)dst;
	uint32 *src = (uint32 *)video;
	uint8 *anim_line;

	if (this->anim_buf == NULL) return;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	for (; height > 0; height--) {
		memcpy(udst, src, width * sizeof(uint32));
		src += _screen.pitch;
		udst += width;
		/* Copy the anim-buffer */
		memcpy(udst, anim_line, width * sizeof(uint8));
		udst = (uint32 *)((uint8 *)udst + width);
		anim_line += this->anim_buf_width;
	}
}

void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint8 *dst, *src;

	/* We need to scroll the anim-buffer too */
	if (scroll_y > 0) {
		dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
		src = dst - scroll_y * this->anim_buf_width;

		/* Adjust left & width */
		if (scroll_x >= 0) {
			dst += scroll_x;
		} else {
			src -= scroll_x;
		}

		uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
		uint th = height - scroll_y;
		for (; th > 0; th--) {
			memcpy(dst, src, tw * sizeof(uint8));
			src -= this->anim_buf_width;
			dst -= this->anim_buf_width;
		}
	} else {
		/* Calculate pointers */
		dst = this->anim_buf + left + top * this->anim_buf_width;
		src = dst - scroll_y * this->anim_buf_width;

		/* Adjust left & width */
		if (scroll_x >= 0) {
			dst += scroll_x;
		} else {
			src -= scroll_x;
		}

		/* the y-displacement may be 0 therefore we have to use memmove,
		 * because source and destination may overlap */
		uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
		uint th = height + scroll_y;
		for (; th > 0; th--) {
			memmove(dst, src, tw * sizeof(uint8));
			src += this->anim_buf_width;
			dst += this->anim_buf_width;
		}
	}

	Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
}

int Blitter_32bppAnim::BufferSize(int width, int height)
{
	return width * height * (sizeof(uint32) + sizeof(uint8));
}

void Blitter_32bppAnim::PaletteAnimate(uint start, uint count)
{
	assert(!_screen_disable_anim);

	/* Never repaint the transparency pixel */
	if (start == 0) {
		start++;
		count--;
	}

	const uint8 *anim = this->anim_buf;
	uint32 *dst = (uint32 *)_screen.dst_ptr;

	/* Let's walk the anim buffer and try to find the pixels */
	for (int y = this->anim_buf_height; y != 0 ; y--) {
		for (int x = this->anim_buf_width; x != 0 ; x--) {
			uint colour = *anim;
			if (IsInsideBS(colour, start, count)) {
				/* Update this pixel */
				*dst = LookupColourInPalette(colour);
			}
			dst++;
			anim++;
		}
		dst += _screen.pitch - this->anim_buf_width;
	}

	/* Make sure the backend redraws the whole screen */
	_video_driver->MakeDirty(0, 0, _screen.width, _screen.height);
}

Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
{
	return Blitter::PALETTE_ANIMATION_BLITTER;
}

void Blitter_32bppAnim::PostResize()
{
	if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
		/* The size of the screen changed; we can assume we can wipe all data from our buffer */
		free(this->anim_buf);
		this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
		this->anim_buf_width = _screen.width;
		this->anim_buf_height = _screen.height;
	}
}