Call CloseDevice() before DeleteIORequest(), and don't call
[AROS.git] / arch / m68k-amiga / hidd / gfx / blitter.c
blob0fa9a1c0b2c690645dc04b5a330e8eafb1233fc2
2 #include <proto/exec.h>
3 #include <proto/graphics.h>
5 #include <exec/libraries.h>
6 #include <hardware/custom.h>
7 #include <hardware/intbits.h>
8 #include <hidd/graphics.h>
10 #include "amigavideogfx.h"
11 #include "amigavideobitmap.h"
12 #include "blitter.h"
14 #define DEBUG 0
15 #include <aros/debug.h>
17 #define ABC 0x80
18 #define ABNC 0x40
19 #define ANBC 0x20
20 #define ANBNC 0x10
21 #define NABC 0x08
22 #define NABNC 0x04
23 #define NANBC 0x02
24 #define NANBNC 0x01
26 static void startblitter(struct amigavideo_staticdata *data, UWORD w, UWORD h)
28 volatile struct Custom *custom = (struct Custom*)0xdff000;
30 if (data->ecs_agnus) {
31 custom->bltsizv = h;
32 custom->bltsizh = w;
33 } else {
34 if (h > 1024 || w > 64)
35 return;
36 custom->bltsize = (h << 6) | (w & 63);
39 static const UWORD leftmask[] = {
40 0xffff, 0x7fff, 0x3fff, 0x1fff,
41 0x0fff, 0x07ff, 0x03ff, 0x01ff,
42 0x00ff, 0x007f, 0x003f, 0x001f,
43 0x000f, 0x0007, 0x0003, 0x0001
45 static const UWORD rightmask[] = {
46 0x8000, 0xc000, 0xe000, 0xf000,
47 0xf800, 0xfc00, 0xfe00, 0xff00,
48 0xff80, 0xffc0, 0xffe0, 0xfff0,
49 0xfff8, 0xfffc, 0xfffe, 0xffff
52 static const UBYTE copy_minterm[] = { 0xff, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff };
53 // A-DAT = edge masking
54 // B = source
55 // C = destination
56 // D = destination
57 // 0: zero (->fillrect)
58 // 1: src AND dst /AC + ABC
59 // 2: src AND NOT dst /AC + AB/C
60 // 3: src /AC + AB
61 // 4: NOT src AND dst /AC + A/B/C
62 // 5: dst (nop)
63 // 6: src XOR dst /AC + A
64 // 7: copy source and blit thru mask
65 // 8:
66 // 9:
67 // 10: NOT dst (->fillrect)
68 // 11:
69 // 12:
70 // 13:
71 // 14:
72 // 15: one (->fillrect)
74 BOOL blit_copybox(struct amigavideo_staticdata *data, struct amigabm_data *srcbm, struct amigabm_data *dstbm,
75 WORD srcx, WORD srcy, WORD w, WORD h, WORD dstx, WORD dsty, HIDDT_DrawMode mode)
77 volatile struct Custom *custom = (struct Custom*)0xdff000;
78 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
79 ULONG srcoffset, dstoffset;
80 BYTE shift, i;
81 WORD srcwidth, dstwidth, width;
82 WORD srcx2, dstx2;
83 UWORD shifta, shiftb;
84 UWORD afwm, alwm;
85 UWORD bltcon0;
86 BOOL reverse = FALSE;
87 BOOL intersect = FALSE;
89 if (USE_BLITTER == 0)
90 return FALSE;
92 srcx2 = srcx + w - 1;
93 dstx2 = dstx + w - 1;
94 if (copy_minterm[mode] == 0xff)
95 return blit_fillrect(data, dstbm, dstx, dsty, dstx2, dsty + h - 1, 0, mode);
97 if (copy_minterm[mode] == 0)
98 return FALSE;
100 D(bug("copybox(%x %x %dx%d %dx%d %dx%d %d)\n", srcbm, dstbm, srcx, srcy, dstx, dsty, w, h, mode));
102 if (srcbm == dstbm) {
103 intersect = !(srcx > dstx2 || srcx2 < dstx || srcy > dsty + h - 1 || srcy + h - 1 < dsty);
106 srcoffset = srcbm->bytesperrow * srcy + (srcx / 16) * 2;
107 dstoffset = dstbm->bytesperrow * dsty + (dstx / 16) * 2;
108 shift = (dstx & 15) - (srcx & 15);
110 if (intersect) {
111 // do we need >16 bit edge mask? (not handled yet)
112 if (dstoffset < srcoffset && shift < 0) // asc + desc
113 return FALSE;
114 if (dstoffset > srcoffset && shift > 0) // desc + asc
115 return FALSE;
118 if (shift < 0) {
119 reverse = TRUE;
120 shift = -shift;
121 } else if (intersect && dstoffset > srcoffset) {
122 reverse = TRUE;
125 srcwidth = srcx2 / 16 - srcx / 16 + 1;
126 dstwidth = dstx2 / 16 - dstx / 16 + 1;
127 srcx &= 15;
128 dstx &= 15;
129 dstx2 &= 15;
130 srcx2 &= 15;
132 if (reverse) {
133 if (dstwidth >= srcwidth) {
134 width = dstwidth;
135 shifta = 0;
136 shiftb = shift << 12;
137 alwm = leftmask[dstx];
138 afwm = rightmask[dstx2];
139 } else {
140 width = srcwidth;
141 shifta = shift << 12;
142 shiftb = shift << 12;
143 alwm = leftmask[srcx];
144 afwm = rightmask[srcx2];
146 srcoffset += srcbm->bytesperrow * (h - 1) + (width - 1) * 2;
147 dstoffset += dstbm->bytesperrow * (h - 1) + (width - 1) * 2;
148 } else {
149 if (dstwidth >= srcwidth) {
150 width = dstwidth;
151 shifta = 0;
152 shiftb = shift << 12;
153 afwm = leftmask[dstx];
154 alwm = rightmask[dstx2];
155 } else {
156 width = srcwidth;
157 shifta = shift << 12;
158 shiftb = shift << 12;
159 afwm = leftmask[srcx];
160 alwm = rightmask[srcx2];
164 //D(bug("shift=%d rev=%d sw=%d dw=%d %04x %04x\n", shift, reverse, srcwidth, dstwidth, afwm, alwm));
166 OwnBlitter();
167 WaitBlit();
169 custom->bltafwm = afwm;
170 custom->bltalwm = alwm;
171 custom->bltbmod = srcbm->bytesperrow - width * 2;
172 custom->bltcmod = dstbm->bytesperrow - width * 2;
173 custom->bltdmod = dstbm->bytesperrow - width * 2;
174 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | shiftb;
175 bltcon0 = 0x0700 | copy_minterm[mode] | shifta;
176 custom->bltadat = 0xffff;
178 for (i = 0; i < dstbm->depth; i++) {
179 UWORD bltcon0b = bltcon0;
180 if (dstbm->planes[i] == (UBYTE*)0x00000000 || dstbm->planes[i] == (UBYTE*)0xffffffff)
181 continue;
182 WaitBlit();
183 if (i >= srcbm->depth || srcbm->planes[i] == (UBYTE*)0x00000000) {
184 bltcon0b &= ~0x0400;
185 custom->bltbdat = 0x0000;
186 } else if (srcbm->planes[i] == (UBYTE*)0xffffffff) {
187 bltcon0b &= ~0x0400;
188 custom->bltbdat = 0xffff;
189 } else {
190 custom->bltbpt = (APTR)(srcbm->planes[i] + srcoffset);
192 custom->bltcon0 = bltcon0b;
193 custom->bltcpt = (APTR)(dstbm->planes[i] + dstoffset);
194 custom->bltdpt = (APTR)(dstbm->planes[i] + dstoffset);
195 startblitter(data, width, h);
198 WaitBlit();
199 DisownBlitter();
201 return TRUE;
204 BOOL blit_copybox_mask(struct amigavideo_staticdata *data, struct amigabm_data *srcbm, struct amigabm_data *dstbm,
205 WORD srcx, WORD srcy, WORD w, WORD h, WORD dstx, WORD dsty, HIDDT_DrawMode mode, APTR maskplane)
207 volatile struct Custom *custom = (struct Custom*)0xdff000;
208 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
209 ULONG srcoffset, dstoffset;
210 BYTE shift, i;
211 WORD srcwidth, dstwidth, width;
212 WORD srcx2, dstx2;
213 UWORD bltshift;
214 UWORD afwm, alwm;
215 UWORD bltcon0;
216 BOOL reverse = FALSE;
217 BOOL intersect = FALSE;
219 if (USE_BLITTER == 0)
220 return FALSE;
222 srcx2 = srcx + w - 1;
223 dstx2 = dstx + w - 1;
225 D(bug("CopyBoxMasked(%x %x %dx%d %dx%d %dx%d %d %x)\n", srcbm, dstbm, srcx, srcy, dstx, dsty, w, h, mode, maskplane));
227 if (srcbm == dstbm) {
228 intersect = !(srcx > dstx2 || srcx2 < dstx || srcy > dsty + h - 1 || srcy + h - 1 < dsty);
231 srcoffset = srcbm->bytesperrow * srcy + (srcx / 16) * 2;
232 dstoffset = dstbm->bytesperrow * dsty + (dstx / 16) * 2;
233 shift = (dstx & 15) - (srcx & 15);
235 if (intersect) {
236 // do we need >16 bit edge mask? (not handled yet)
237 if (dstoffset < srcoffset && shift < 0) // asc + desc
238 return FALSE;
239 if (dstoffset > srcoffset && shift > 0) // desc + asc
240 return FALSE;
243 if (shift < 0) {
244 reverse = TRUE;
245 shift = -shift;
246 } else if (intersect && dstoffset > srcoffset) {
247 reverse = TRUE;
250 srcwidth = srcx2 / 16 - srcx / 16 + 1;
251 dstwidth = dstx2 / 16 - dstx / 16 + 1;
252 srcx &= 15;
253 dstx &= 15;
254 dstx2 &= 15;
255 srcx2 &= 15;
257 bltshift = shift << 12;
258 if (reverse) {
259 if (dstwidth > srcwidth) {
260 width = dstwidth;
261 alwm = 0xffff;
262 afwm = 0x0000;
263 } else {
264 width = srcwidth;
265 alwm = 0xffff;
266 afwm = 0xffff;
268 srcoffset += srcbm->bytesperrow * (h - 1) + (width - 1) * 2;
269 dstoffset += dstbm->bytesperrow * (h - 1) + (width - 1) * 2;
270 } else {
271 if (dstwidth > srcwidth) {
272 width = dstwidth;
273 afwm = 0xffff;
274 alwm = 0x0000;
275 } else {
276 width = srcwidth;
277 afwm = 0xffff;
278 alwm = 0xffff;
282 D(bug("shift=%d rev=%d sw=%d dw=%d sbpr=%d %04x %04x\n", shift, reverse, srcwidth, dstwidth, srcbm->bytesperrow, afwm, alwm));
284 OwnBlitter();
285 WaitBlit();
287 custom->bltafwm = afwm;
288 custom->bltalwm = alwm;
289 custom->bltamod = srcbm->bytesperrow - width * 2;
290 custom->bltbmod = srcbm->bytesperrow - width * 2;
291 custom->bltcmod = dstbm->bytesperrow - width * 2;
292 custom->bltdmod = dstbm->bytesperrow - width * 2;
293 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | bltshift;
294 bltcon0 = 0x0f00 | 0x00ca | bltshift;
296 for (i = 0; i < dstbm->depth; i++) {
297 UWORD bltcon0b = bltcon0;
298 if (dstbm->planes[i] == (UBYTE*)0x00000000 || dstbm->planes[i] == (UBYTE*)0xffffffff)
299 continue;
300 WaitBlit();
301 if (i >= srcbm->depth || srcbm->planes[i] == (UBYTE*)0x00000000) {
302 bltcon0b &= ~0x0400;
303 custom->bltbdat = 0x0000;
304 } else if (srcbm->planes[i] == (UBYTE*)0xffffffff) {
305 bltcon0b &= ~0x0400;
306 custom->bltbdat = 0xffff;
307 } else {
308 custom->bltbpt = (APTR)(srcbm->planes[i] + srcoffset);
310 custom->bltcon0 = bltcon0b;
311 custom->bltapt = (APTR)(maskplane + srcoffset);
312 custom->bltcpt = (APTR)(dstbm->planes[i] + dstoffset);
313 custom->bltdpt = (APTR)(dstbm->planes[i] + dstoffset);
314 startblitter(data, width, h);
317 WaitBlit();
318 DisownBlitter();
320 return TRUE;
323 static const UBYTE fill_minterm[] = { 0xca, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xca };
325 // copy: /AC + AB = (NABC | NANBC) | (ABNC | ABC) = 0xCA
326 // invert: /AC + A/C = (NABC | NANBC) | (ABNC | ANBNC) = 0x5A
328 // A-DAT = edge masking
329 // B-DAT = pixel value (ones or zeros, not used when invert mode)
330 // C = source
331 // D = destination
333 BOOL blit_fillrect(struct amigavideo_staticdata *data, struct amigabm_data *bm, WORD x1,WORD y1,WORD x2,WORD y2, HIDDT_Pixel pixel, HIDDT_DrawMode mode)
335 volatile struct Custom *custom = (struct Custom*)0xdff000;
336 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
337 ULONG offset;
338 WORD width, height;
339 UBYTE i;
341 if (USE_BLITTER == 0)
342 return FALSE;
344 D(bug("fillrect(%dx%d,%dx%d,%d,%d)\n", x1, y1, x2, y2, pixel, mode));
345 D(bug("bm = %dx%dx%d bpr=%d\n", bm->width, bm->height, bm->depth, bm->bytesperrow));
347 if (fill_minterm[mode] == 0)
348 return FALSE;
350 offset = bm->bytesperrow * y1 + (x1 / 16) * 2;
351 width = x2 / 16 - x1 / 16 + 1;
352 height = y2 - y1 + 1;
354 OwnBlitter();
355 WaitBlit();
357 custom->bltafwm = leftmask[x1 & 15];
358 custom->bltalwm = rightmask[x2 & 15];
359 custom->bltcmod = bm->bytesperrow - width * 2;
360 custom->bltdmod = bm->bytesperrow - width * 2;
361 custom->bltcon1 = 0x0000;
362 custom->bltcon0 = 0x0300 | fill_minterm[mode];
363 custom->bltadat = 0xffff;
365 if (mode == vHidd_GC_DrawMode_Clear)
366 pixel = 0x00;
367 else if (mode == vHidd_GC_DrawMode_Set)
368 pixel = 0xff;
370 for (i = 0; i < bm->depth; i++) {
371 if (bm->planes[i] != (UBYTE*)0x00000000 && bm->planes[i] != (UBYTE*)0xffffffff) {
372 WaitBlit();
373 custom->bltbdat = (pixel & 1) ? 0xffff : 0x0000;
374 custom->bltcpt = (APTR)(bm->planes[i] + offset);
375 custom->bltdpt = (APTR)(bm->planes[i] + offset);
376 startblitter(data, width, height);
378 pixel >>= 1;
381 WaitBlit();
382 DisownBlitter();
384 return TRUE;
387 #if 0
388 struct pHidd_BitMap_PutTemplate
390 OOP_MethodID mID;
391 OOP_Object *gc;
392 UBYTE *Template;
393 ULONG modulo;
394 WORD srcx;
395 WORD x, y;
396 WORD width, height;
397 BOOL inverttemplate;
399 #endif
401 // A-DAT = edge masking
402 // B = template
403 // C = destination
404 // D = destination
406 BOOL blit_puttemplate(struct amigavideo_staticdata *data, struct amigabm_data *bm, struct pHidd_BitMap_PutTemplate *tmpl)
408 volatile struct Custom *custom = (struct Custom*)0xdff000;
409 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
410 OOP_Object *gc = tmpl->gc;
411 HIDDT_Pixel fgpen = GC_FG(tmpl->gc);
412 HIDDT_Pixel bgpen = GC_BG(tmpl->gc);
414 UBYTE type, i;
415 BYTE shift;
416 UWORD shifta, shiftb;
417 UWORD afwm, alwm;
418 ULONG srcoffset, dstoffset;
419 WORD width, srcwidth, dstwidth;
420 BOOL reverse;
421 WORD height = tmpl->height;
422 WORD dstx = tmpl->x;
423 WORD dsty = tmpl->y;
424 WORD dstx2 = tmpl->x + tmpl->width - 1;
425 WORD srcx = tmpl->srcx;
426 WORD srcx2 = srcx + tmpl->width - 1;
428 if (USE_BLITTER == 0)
429 return FALSE;
431 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
432 type = 0;
433 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
434 type = 2;
435 else
436 type = 4;
437 if (tmpl->inverttemplate)
438 type++;
440 D(bug("puttemplate: %x srcx=%d x=%d y=%d w=%d h=%d type=%d fg=%d bg=%d\n",
441 tmpl->Template, tmpl->srcx, tmpl->x, tmpl->y, tmpl->width, tmpl->height, type, fgpen, bgpen));
443 srcoffset = (srcx / 16) * 2;
444 dstoffset = bm->bytesperrow * dsty + (dstx / 16) * 2;
446 srcwidth = srcx2 / 16 - srcx / 16 + 1;
447 dstwidth = dstx2 / 16 - dstx / 16 + 1;
449 dstx &= 15;
450 dstx2 &= 15;
451 srcx &= 15;
452 srcx2 &= 15;
454 shift = dstx - srcx;
456 D(bug("shift=%d srcwidth=%d dstwidth=%d\n", shift, srcwidth, dstwidth));
458 if (shift < 0) {
459 reverse = TRUE;
460 shift = -shift;
461 if (dstwidth >= srcwidth) {
462 width = dstwidth;
463 shifta = 0;
464 shiftb = shift << 12;
465 alwm = leftmask[dstx];
466 afwm = rightmask[dstx2];
467 } else {
468 width = srcwidth;
469 shifta = shift << 12;
470 shiftb = shift << 12;
471 alwm = leftmask[srcx];
472 afwm = rightmask[srcx2];
474 srcoffset += tmpl->modulo * (height - 1) + (width - 1) * 2;
475 dstoffset += bm->bytesperrow * (height - 1) + (width - 1) * 2;
476 } else {
477 reverse = FALSE;
478 if (dstwidth >= srcwidth) {
479 width = dstwidth;
480 shifta = 0;
481 shiftb = shift << 12;
482 afwm = leftmask[dstx];
483 alwm = rightmask[dstx2];
484 } else {
485 width = srcwidth;
486 shifta = shift << 12;
487 shiftb = shift << 12;
488 afwm = leftmask[srcx];
489 alwm = rightmask[srcx2];
493 OwnBlitter();
494 WaitBlit();
496 custom->bltafwm = afwm;
497 custom->bltalwm = alwm;
498 custom->bltbmod = tmpl->modulo - width * 2;
499 custom->bltcmod = bm->bytesperrow - width * 2;
500 custom->bltdmod = bm->bytesperrow - width * 2;
501 custom->bltadat = 0xffff;
503 for (i = 0; i < bm->depth; i++) {
504 UBYTE minterm;
505 UWORD chmask, shiftbv;
506 UBYTE fg, bg, tg;
508 fg = fgpen & 1;
509 bg = bgpen & 1;
510 fgpen >>= 1;
511 bgpen >>= 1;
513 if (bm->planes[i] == (UBYTE*)0x00000000 || bm->planes[i] == (UBYTE*)0xffffffff)
514 continue;
516 chmask = 0x0700;
517 shiftbv = shiftb;
519 /* not guaranteed to be correct, last time I played with minterms
520 * was something like 20 years ago..
522 switch (type)
524 case 0: // JAM1:
525 minterm = (NABC | NANBC) | (fg ? ABC | ABNC | ANBC : ANBC);
526 break;
527 case 1: // JAM1 | INVERSVID
528 minterm = (NABC | NANBC) | (fg ? ANBC | ANBNC | ABC : ABC);
529 break;
530 case 2: // COMPLEMENT:
531 minterm = (NABC | NANBC) | (ANBC | ABNC);
532 break;
533 case 3: // COMPLEMENT | INVERSVID:
534 minterm = (NABC | NANBC) | (ABC | ANBNC);
535 break;
536 case 5: // JAM2 | INVERSVID
537 tg = fg;
538 fg = bg;
539 bg = tg;
540 case 4: // JAM2
541 if (fg && bg) {
542 minterm = (NABC | NANBC) | (ABC | ABNC);
543 chmask = 0x0300;
544 shiftbv = 0;
545 } else if (!fg && !bg) {
546 minterm = (NABC | NANBC);
547 chmask = 0x0300;
548 shiftbv = 0;
549 } else if (fg) {
550 minterm = (NABC | NANBC) | (ABC | ABNC);
551 } else {
552 minterm = (NABC | NANBC) | (ANBC | ANBNC);
554 break;
557 WaitBlit();
558 custom->bltcon0 = shifta | chmask | minterm;
559 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | shiftbv;
560 custom->bltbdat = 0xffff;
561 custom->bltbpt = (APTR)(tmpl->Template + srcoffset);
562 custom->bltcpt = (APTR)(bm->planes[i] + dstoffset);
563 custom->bltdpt = (APTR)(bm->planes[i] + dstoffset);
564 startblitter(data, width, height);
567 WaitBlit();
568 DisownBlitter();
570 return TRUE;
573 static UBYTE getminterm(UBYTE type, UBYTE fg, UBYTE bg)
575 UBYTE minterm = 0, tg;
576 switch (type)
578 case 0: // JAM1:
579 minterm = (NABC | NANBC) | (fg ? ABC | ABNC | ANBC : ANBC);
580 break;
581 case 1: // JAM1 | INVERSVID
582 minterm = (NABC | NANBC) | (fg ? ANBC | ANBNC | ABC : ABC);
583 break;
584 case 2: // COMPLEMENT:
585 minterm = (NABC | NANBC) | (ANBC | ABNC);
586 break;
587 case 3: // COMPLEMENT | INVERSVID:
588 minterm = (NABC | NANBC) | (ABC | ANBNC);
589 break;
590 case 5: // JAM2 | INVERSVID
591 tg = fg;
592 fg = bg;
593 bg = tg;
594 case 4: // JAM2
595 if (fg && bg) {
596 minterm = (NABC | NANBC) | (ABC | ABNC);
597 } else if (!fg && !bg) {
598 minterm = (NABC | NANBC);
599 } else if (fg) {
600 minterm = (NABC | NANBC) | (ABC | ABNC);
601 } else {
602 minterm = (NABC | NANBC) | (ANBC | ANBNC);
604 break;
606 return minterm;
609 BOOL blit_putpattern(struct amigavideo_staticdata *csd, struct amigabm_data *bm, struct pHidd_BitMap_PutPattern *pat)
611 volatile struct Custom *custom = (struct Custom*)0xdff000;
612 struct GfxBase *GfxBase = (APTR)csd->cs_GfxBase;
614 UBYTE type;
615 UBYTE fgpen = GC_FG(pat->gc);
616 UBYTE bgpen = GC_BG(pat->gc);
618 UBYTE i;
619 UWORD shifta, shiftb;
620 UWORD afwm, alwm;
621 ULONG dstoffset;
622 WORD dstwidth;
623 WORD patcnt;
625 WORD height = pat->height;
626 WORD dstx = pat->x;
627 WORD dsty = pat->y;
628 WORD dstx2 = pat->x + pat->width - 1;
630 WORD patternymask = pat->patternheight - 1;
632 if (USE_BLITTER == 0)
633 return FALSE;
635 if (pat->mask)
636 return FALSE;
637 if (pat->patterndepth != 1)
638 return FALSE;
640 if (GC_COLEXP(pat->gc) == vHidd_GC_ColExp_Transparent)
641 type = 0;
642 else if (GC_DRMD(pat->gc) == vHidd_GC_DrawMode_Invert)
643 type = 2;
644 else
645 type = 4;
646 if (pat->invertpattern)
647 type++;
649 D(bug("PutPattern(%dx%d,%dx%d,mask=%x,mod=%d,masksrcx=%d,P=%x,%dx%d,h=%d,T=%d)\n",
650 pat->x, pat->y, pat->width, pat->height,
651 pat->mask, pat->maskmodulo, pat->masksrcx,
652 pat->pattern, pat->patternsrcx, pat->patternsrcy, pat->patternheight, type));
654 dstoffset = bm->bytesperrow * dsty + (dstx / 16) * 2;
655 dstwidth = dstx2 / 16 - dstx / 16 + 1;
657 dstx &= 15;
658 dstx2 &= 15;
660 shifta = 0;
661 shiftb = 0;
662 afwm = leftmask[dstx];
663 alwm = rightmask[dstx2];
665 OwnBlitter();
666 WaitBlit();
668 custom->bltafwm = afwm;
669 custom->bltalwm = alwm;
670 custom->bltcmod = (bm->bytesperrow - dstwidth * 2) + bm->bytesperrow * (pat->patternheight - 1);
671 custom->bltdmod = (bm->bytesperrow - dstwidth * 2) + bm->bytesperrow * (pat->patternheight - 1);
672 custom->bltadat = 0xffff;
674 for (i = 0; i < bm->depth; i++, fgpen >>= 1, bgpen >>= 1) {
675 ULONG dstoffset2;
676 UBYTE minterm;
677 UWORD chmask;
678 UBYTE fg, bg;
680 if (bm->planes[i] == (UBYTE*)0x00000000 || bm->planes[i] == (UBYTE*)0xffffffff)
681 continue;
683 fg = fgpen & 1;
684 bg = bgpen & 1;
686 chmask = 0x0300;
688 minterm = getminterm(type, fg, bg);
690 WaitBlit();
691 custom->bltcon0 = shifta | chmask | minterm;
692 custom->bltcon1 = shiftb;
694 for(patcnt = 0, dstoffset2 = 0; patcnt < pat->patternheight; patcnt++, dstoffset2 += bm->bytesperrow) {
695 UWORD blitheight = (height - patcnt + 1) / pat->patternheight;
696 UWORD pattern = ((UWORD*)pat->pattern)[(pat->patternsrcy + patcnt) & patternymask];
697 if (blitheight && pattern) {
698 WaitBlit();
699 custom->bltbdat = pattern;
700 custom->bltcpt = (APTR)(bm->planes[i] + dstoffset + dstoffset2);
701 custom->bltdpt = (APTR)(bm->planes[i] + dstoffset + dstoffset2);
702 startblitter(csd, dstwidth, blitheight);
707 WaitBlit();
708 DisownBlitter();
710 return TRUE;