2 Copyright © 1995-2017, The AROS Development Team. All rights reserved.
6 #include <proto/exec.h>
7 #include <proto/graphics.h>
9 #include <exec/libraries.h>
10 #include <hardware/custom.h>
11 #include <hardware/intbits.h>
14 #include "amigavideo_hidd.h"
15 #include "amigavideo_bitmap.h"
19 #include <aros/debug.h>
30 // Safety check for fast ram bitmaps
31 static BOOL
canblit(struct BitMap
*bm
)
34 for (i
= 0; i
< bm
->Depth
; i
++) {
35 UBYTE
*p
= bm
->Planes
[i
];
36 if (p
== (UBYTE
*)0x00000000 || p
== (UBYTE
*)0xffffffff)
38 // Lower 2M is guaranteed to be Chip RAM
39 if (p
< (UBYTE
)0x00200000)
41 // Re-implementations and UAE may have more Chip RAM.
42 if (TypeOfMem(p
) & MEMF_CHIP
)
46 return USE_BLITTER
!= 0;
49 static void startblitter(struct amigavideo_staticdata
*data
, UWORD w
, UWORD h
)
51 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
53 if (data
->ecs_agnus
) {
57 if (h
> 1024 || w
> 64)
59 custom
->bltsize
= (h
<< 6) | (w
& 63);
62 static const UWORD leftmask
[] = {
63 0xffff, 0x7fff, 0x3fff, 0x1fff,
64 0x0fff, 0x07ff, 0x03ff, 0x01ff,
65 0x00ff, 0x007f, 0x003f, 0x001f,
66 0x000f, 0x0007, 0x0003, 0x0001
68 static const UWORD rightmask
[] = {
69 0x8000, 0xc000, 0xe000, 0xf000,
70 0xf800, 0xfc00, 0xfe00, 0xff00,
71 0xff80, 0xffc0, 0xffe0, 0xfff0,
72 0xfff8, 0xfffc, 0xfffe, 0xffff
75 static const UBYTE copy_minterm
[] = { 0xff, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff };
76 // A-DAT = edge masking
80 // 0: zero (->fillrect)
81 // 1: src AND dst /AC + ABC
82 // 2: src AND NOT dst /AC + AB/C
84 // 4: NOT src AND dst /AC + A/B/C
86 // 6: src XOR dst /AC + A
87 // 7: copy source and blit thru mask
90 // 10: NOT dst (->fillrect)
95 // 15: one (->fillrect)
97 BOOL
blit_copybox(struct amigavideo_staticdata
*data
, struct BitMap
*srcbm
, struct BitMap
*dstbm
,
98 WORD srcx
, WORD srcy
, WORD w
, WORD h
, WORD dstx
, WORD dsty
, HIDDT_DrawMode mode
)
100 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
101 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
102 ULONG srcoffset
, dstoffset
;
104 WORD srcwidth
, dstwidth
, width
;
106 UWORD shifta
, shiftb
;
109 BOOL reverse
= FALSE
;
110 BOOL intersect
= FALSE
;
112 if (!canblit(srcbm
) || !canblit(dstbm
))
115 srcx2
= srcx
+ w
- 1;
116 dstx2
= dstx
+ w
- 1;
117 if (copy_minterm
[mode
] == 0xff)
118 return blit_fillrect(data
, dstbm
, dstx
, dsty
, dstx2
, dsty
+ h
- 1, 0, mode
);
120 if (copy_minterm
[mode
] == 0)
123 D(bug("copybox(%x %x %dx%d %dx%d %dx%d %d)\n", srcbm
, dstbm
, srcx
, srcy
, dstx
, dsty
, w
, h
, mode
));
125 if (srcbm
== dstbm
) {
126 intersect
= !(srcx
> dstx2
|| srcx2
< dstx
|| srcy
> dsty
+ h
- 1 || srcy
+ h
- 1 < dsty
);
129 srcoffset
= srcbm
->BytesPerRow
* srcy
+ (srcx
/ 16) * 2;
130 dstoffset
= dstbm
->BytesPerRow
* dsty
+ (dstx
/ 16) * 2;
131 shift
= (dstx
& 15) - (srcx
& 15);
134 // do we need >16 bit edge mask? (not handled yet)
135 if (dstoffset
< srcoffset
&& shift
< 0) // asc + desc
137 if (dstoffset
> srcoffset
&& shift
> 0) // desc + asc
144 } else if (intersect
&& dstoffset
> srcoffset
) {
148 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
149 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
157 if (dstwidth
>= srcwidth
) {
160 shiftb
= shift
<< 12;
161 alwm
= leftmask
[dstx
];
162 afwm
= rightmask
[dstx2
];
165 shifta
= shift
<< 12;
166 shiftb
= shift
<< 12;
167 alwm
= leftmask
[srcx
];
168 afwm
= rightmask
[srcx2
];
170 srcoffset
+= srcbm
->BytesPerRow
* (h
- 1) + (width
- 1) * 2;
171 dstoffset
+= dstbm
->BytesPerRow
* (h
- 1) + (width
- 1) * 2;
173 if (dstwidth
>= srcwidth
) {
176 shiftb
= shift
<< 12;
177 afwm
= leftmask
[dstx
];
178 alwm
= rightmask
[dstx2
];
181 shifta
= shift
<< 12;
182 shiftb
= shift
<< 12;
183 afwm
= leftmask
[srcx
];
184 alwm
= rightmask
[srcx2
];
188 D(bug("shift=%d rev=%d sw=%d dw=%d %04x %04x\n", shift
, reverse
, srcwidth
, dstwidth
, afwm
, alwm
));
193 custom
->bltafwm
= afwm
;
194 custom
->bltalwm
= alwm
;
195 custom
->bltbmod
= srcbm
->BytesPerRow
- width
* 2;
196 custom
->bltcmod
= dstbm
->BytesPerRow
- width
* 2;
197 custom
->bltdmod
= dstbm
->BytesPerRow
- width
* 2;
198 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | shiftb
;
199 bltcon0
= 0x0700 | copy_minterm
[mode
] | shifta
;
200 custom
->bltadat
= 0xffff;
202 for (i
= 0; i
< dstbm
->Depth
; i
++) {
203 UWORD bltcon0b
= bltcon0
;
204 if (dstbm
->Planes
[i
] == (UBYTE
*)0x00000000 || dstbm
->Planes
[i
] == (UBYTE
*)0xffffffff)
207 if (i
>= srcbm
->Depth
|| srcbm
->Planes
[i
] == (UBYTE
*)0x00000000) {
209 custom
->bltbdat
= 0x0000;
210 } else if (srcbm
->Planes
[i
] == (UBYTE
*)0xffffffff) {
212 custom
->bltbdat
= 0xffff;
214 custom
->bltbpt
= (APTR
)(srcbm
->Planes
[i
] + srcoffset
);
216 custom
->bltcon0
= bltcon0b
;
217 custom
->bltcpt
= (APTR
)(dstbm
->Planes
[i
] + dstoffset
);
218 custom
->bltdpt
= (APTR
)(dstbm
->Planes
[i
] + dstoffset
);
219 startblitter(data
, width
, h
);
228 BOOL
blit_copybox_mask(struct amigavideo_staticdata
*data
, struct BitMap
*srcbm
, struct BitMap
*dstbm
,
229 WORD srcx
, WORD srcy
, WORD w
, WORD h
, WORD dstx
, WORD dsty
, HIDDT_DrawMode mode
, APTR maskplane
)
231 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
232 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
233 ULONG srcoffset
, dstoffset
;
235 WORD srcwidth
, dstwidth
, width
;
239 UWORD bltcon0
, maskmod
;
240 BOOL reverse
= FALSE
;
241 BOOL intersect
= FALSE
;
242 UWORD
*tempmask
= NULL
;
243 BOOL needtempmask
= FALSE
;
245 if (!canblit(srcbm
) || !canblit(dstbm
))
248 srcx2
= srcx
+ w
- 1;
249 dstx2
= dstx
+ w
- 1;
251 D(bug("CopyBoxMasked(%x %x %dx%d %dx%d %dx%d %d %x)\n", srcbm
, dstbm
, srcx
, srcy
, dstx
, dsty
, w
, h
, mode
, maskplane
));
253 if (srcbm
== dstbm
) {
254 intersect
= !(srcx
> dstx2
|| srcx2
< dstx
|| srcy
> dsty
+ h
- 1 || srcy
+ h
- 1 < dsty
);
257 srcoffset
= srcbm
->BytesPerRow
* srcy
+ (srcx
/ 16) * 2;
258 dstoffset
= dstbm
->BytesPerRow
* dsty
+ (dstx
/ 16) * 2;
259 shift
= (dstx
& 15) - (srcx
& 15);
262 // do we need >16 bit edge mask? (not handled yet)
263 if (dstoffset
< srcoffset
&& shift
< 0) // asc + desc
265 if (dstoffset
> srcoffset
&& shift
> 0) // desc + asc
272 } else if (intersect
&& dstoffset
> srcoffset
) {
276 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
277 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
284 if (dstwidth
> srcwidth
&& ((srcx
+ w
- 1) & ~15) != ((dstx
+ w
- 1) & ~15)) {
285 // >16 bit edge mask needed?
286 D(bug("unsupported %d,%d %d,%d %d %d,%d\n", srcwidth
, dstwidth
, srcx
, dstx
, w
, srcx
+ w
, dstx
+ w
));
290 bltshift
= shift
<< 12;
292 if (dstwidth
> srcwidth
) {
294 alwm
= leftmask
[srcx
];
295 if (srcwidth
== 1 && srcx2
> srcx
) {
296 // source is single word
297 alwm
&= rightmask
[srcx2
];
300 afwm
= rightmask
[srcx2
];
304 alwm
= leftmask
[srcx
];
305 afwm
= rightmask
[srcx2
];
307 srcoffset
+= srcbm
->BytesPerRow
* (h
- 1) + (width
- 1) * 2;
308 dstoffset
+= dstbm
->BytesPerRow
* (h
- 1) + (width
- 1) * 2;
310 if (dstwidth
> srcwidth
) {
312 afwm
= leftmask
[srcx
];
313 if (srcwidth
== 1 && srcx2
> srcx
) {
314 // source is single word
315 afwm
&= rightmask
[srcx2
];
318 alwm
= rightmask
[srcx2
];
322 afwm
= leftmask
[srcx
];
323 alwm
= rightmask
[srcx2
];
328 UWORD
*oldmask
= maskplane
+ srcoffset
, *newmask
, *mask2
;
330 tempmask
= AllocVec((srcwidth
+ 1) * 2 * (h
+ 1), MEMF_CHIP
);
334 newmask
= tempmask
+ (srcwidth
+ 1);
336 // create temp mask generation mask
337 for (ww
= 0; ww
< srcwidth
- 1; ww
++)
339 // we need to mask out part of second to last word which
340 // is not directly supported by the blitter.
341 mask2
[srcwidth
- 1] = reverse
? afwm
: alwm
;
342 mask2
[srcwidth
] = 0x0000;
347 custom
->bltapt
= mask2
;
348 custom
->bltbdat
= 0x0000;
349 custom
->bltcpt
= oldmask
;
350 custom
->bltdpt
= newmask
;
351 custom
->bltamod
= -(srcwidth
+ 1) * 2;
352 custom
->bltcmod
= srcbm
->BytesPerRow
- (srcwidth
+ 1) * 2;
354 custom
->bltafwm
= 0xffff;
355 custom
->bltalwm
= 0xffff;
357 custom
->bltcon0
= 0x0bac;
358 custom
->bltcon1
= 0x0000;
359 startblitter(data
, srcwidth
+ 1, h
);
365 maskplane
+= srcoffset
;
366 maskmod
= srcbm
->BytesPerRow
- width
* 2;
369 D(bug("shift=%d rev=%d sw=%d dw=%d sbpr=%d srcx=%d/%d %04x %04x %p\n", shift
, reverse
, srcwidth
, dstwidth
, srcbm
->BytesPerRow
, srcx
, srcx2
, afwm
, alwm
, maskplane
));
374 custom
->bltafwm
= afwm
;
375 custom
->bltalwm
= alwm
;
376 custom
->bltamod
= maskmod
;
377 custom
->bltbmod
= srcbm
->BytesPerRow
- width
* 2;
378 custom
->bltcmod
= dstbm
->BytesPerRow
- width
* 2;
379 custom
->bltdmod
= dstbm
->BytesPerRow
- width
* 2;
380 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | bltshift
;
381 bltcon0
= 0x0f00 | 0x00ca | bltshift
;
383 for (i
= 0; i
< dstbm
->Depth
; i
++) {
384 UWORD bltcon0b
= bltcon0
;
385 if (dstbm
->Planes
[i
] == (UBYTE
*)0x00000000 || dstbm
->Planes
[i
] == (UBYTE
*)0xffffffff)
388 if (i
>= srcbm
->Depth
|| srcbm
->Planes
[i
] == (UBYTE
*)0x00000000) {
390 custom
->bltbdat
= 0x0000;
391 } else if (srcbm
->Planes
[i
] == (UBYTE
*)0xffffffff) {
393 custom
->bltbdat
= 0xffff;
395 custom
->bltbpt
= (APTR
)(srcbm
->Planes
[i
] + srcoffset
);
397 custom
->bltcon0
= bltcon0b
;
398 custom
->bltapt
= (APTR
)maskplane
;
399 custom
->bltcpt
= (APTR
)(dstbm
->Planes
[i
] + dstoffset
);
400 custom
->bltdpt
= (APTR
)(dstbm
->Planes
[i
] + dstoffset
);
401 startblitter(data
, width
, h
);
413 static const UBYTE fill_minterm
[] = { 0xca, 0x00, 0x00, 0xca, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xca };
415 // copy: /AC + AB = (NABC | NANBC) | (ABNC | ABC) = 0xCA
416 // invert: /AC + A/C = (NABC | NANBC) | (ABNC | ANBNC) = 0x5A
418 // A-DAT = edge masking
419 // B-DAT = pixel value (ones or zeros, not used when invert mode)
423 BOOL
blit_fillrect(struct amigavideo_staticdata
*data
, struct BitMap
*bm
, WORD x1
,WORD y1
,WORD x2
,WORD y2
, HIDDT_Pixel pixel
, HIDDT_DrawMode mode
)
425 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
426 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
434 D(bug("fillrect(%dx%d,%dx%d,%d,%d)\n", x1
, y1
, x2
, y2
, pixel
, mode
));
435 D(bug("bm = %dx%dx%d bpr=%d\n", bm
->BytesPerRow
* 8, bm
->Rows
, bm
->Depth
, bm
->BytesPerRow
));
437 if (fill_minterm
[mode
] == 0)
440 offset
= bm
->BytesPerRow
* y1
+ (x1
/ 16) * 2;
441 width
= x2
/ 16 - x1
/ 16 + 1;
442 height
= y2
- y1
+ 1;
447 custom
->bltafwm
= leftmask
[x1
& 15];
448 custom
->bltalwm
= rightmask
[x2
& 15];
449 custom
->bltcmod
= bm
->BytesPerRow
- width
* 2;
450 custom
->bltdmod
= bm
->BytesPerRow
- width
* 2;
451 custom
->bltcon1
= 0x0000;
452 custom
->bltcon0
= 0x0300 | fill_minterm
[mode
];
453 custom
->bltadat
= 0xffff;
455 if (mode
== vHidd_GC_DrawMode_Clear
)
457 else if (mode
== vHidd_GC_DrawMode_Set
|| mode
== vHidd_GC_DrawMode_Invert
)
460 for (i
= 0; i
< bm
->Depth
; i
++) {
461 if (bm
->Planes
[i
] != (UBYTE
*)0x00000000 && bm
->Planes
[i
] != (UBYTE
*)0xffffffff) {
463 custom
->bltbdat
= (pixel
& 1) ? 0xffff : 0x0000;
464 custom
->bltcpt
= (APTR
)(bm
->Planes
[i
] + offset
);
465 custom
->bltdpt
= (APTR
)(bm
->Planes
[i
] + offset
);
466 startblitter(data
, width
, height
);
478 struct pHidd_BitMap_PutTemplate
491 // A-DAT = edge masking
496 BOOL
blit_puttemplate(struct amigavideo_staticdata
*data
, struct BitMap
*bm
, struct pHidd_BitMap_PutTemplate
*tmpl
)
498 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
499 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
500 OOP_Object
*gc
= tmpl
->gc
;
501 HIDDT_Pixel fgpen
= GC_FG(tmpl
->gc
);
502 HIDDT_Pixel bgpen
= GC_BG(tmpl
->gc
);
506 UWORD shifta
, shiftb
;
508 ULONG srcoffset
, dstoffset
;
509 WORD width
, srcwidth
, dstwidth
;
511 WORD height
= tmpl
->height
;
514 WORD dstx2
= tmpl
->x
+ tmpl
->width
- 1;
515 WORD srcx
= tmpl
->srcx
;
516 WORD srcx2
= srcx
+ tmpl
->width
- 1;
521 if (GC_COLEXP(gc
) == vHidd_GC_ColExp_Transparent
)
523 else if (GC_DRMD(gc
) == vHidd_GC_DrawMode_Invert
)
527 if (tmpl
->inverttemplate
)
530 D(bug("puttemplate: %x srcx=%d x=%d y=%d w=%d h=%d type=%d fg=%d bg=%d\n",
531 tmpl
->masktemplate
, tmpl
->srcx
, tmpl
->x
, tmpl
->y
, tmpl
->width
, tmpl
->height
, type
, fgpen
, bgpen
));
533 srcoffset
= (srcx
/ 16) * 2;
534 dstoffset
= bm
->BytesPerRow
* dsty
+ (dstx
/ 16) * 2;
536 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
537 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
546 D(bug("shift=%d srcwidth=%d dstwidth=%d\n", shift
, srcwidth
, dstwidth
));
551 if (dstwidth
>= srcwidth
) {
554 shiftb
= shift
<< 12;
555 alwm
= leftmask
[dstx
];
556 afwm
= rightmask
[dstx2
];
559 shifta
= shift
<< 12;
560 shiftb
= shift
<< 12;
561 alwm
= leftmask
[srcx
];
562 afwm
= rightmask
[srcx2
];
564 srcoffset
+= tmpl
->modulo
* (height
- 1) + (width
- 1) * 2;
565 dstoffset
+= bm
->BytesPerRow
* (height
- 1) + (width
- 1) * 2;
568 if (dstwidth
>= srcwidth
) {
571 shiftb
= shift
<< 12;
572 afwm
= leftmask
[dstx
];
573 alwm
= rightmask
[dstx2
];
576 shifta
= shift
<< 12;
577 shiftb
= shift
<< 12;
578 afwm
= leftmask
[srcx
];
579 alwm
= rightmask
[srcx2
];
586 custom
->bltafwm
= afwm
;
587 custom
->bltalwm
= alwm
;
588 custom
->bltbmod
= tmpl
->modulo
- width
* 2;
589 custom
->bltcmod
= bm
->BytesPerRow
- width
* 2;
590 custom
->bltdmod
= bm
->BytesPerRow
- width
* 2;
591 custom
->bltadat
= 0xffff;
593 for (i
= 0; i
< bm
->Depth
; i
++) {
595 UWORD chmask
, shiftbv
;
603 if (bm
->Planes
[i
] == (UBYTE
*)0x00000000 || bm
->Planes
[i
] == (UBYTE
*)0xffffffff)
609 /* not guaranteed to be correct, last time I played with minterms
610 * was something like 20 years ago..
615 minterm
= (NABC
| NANBC
) | (fg
? ABC
| ABNC
| ANBC
: ANBC
);
617 case 1: // JAM1 | INVERSVID
618 minterm
= (NABC
| NANBC
) | (fg
? ANBC
| ANBNC
| ABC
: ABC
);
620 case 2: // COMPLEMENT:
621 minterm
= (NABC
| NANBC
) | (ANBC
| ABNC
);
623 case 3: // COMPLEMENT | INVERSVID:
624 minterm
= (NABC
| NANBC
) | (ABC
| ANBNC
);
626 case 5: // JAM2 | INVERSVID
632 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
635 } else if (!fg
&& !bg
) {
636 minterm
= (NABC
| NANBC
);
640 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
642 minterm
= (NABC
| NANBC
) | (ANBC
| ANBNC
);
648 custom
->bltcon0
= shifta
| chmask
| minterm
;
649 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | shiftbv
;
650 custom
->bltbdat
= 0xffff;
651 custom
->bltbpt
= (APTR
)(tmpl
->masktemplate
+ srcoffset
);
652 custom
->bltcpt
= (APTR
)(bm
->Planes
[i
] + dstoffset
);
653 custom
->bltdpt
= (APTR
)(bm
->Planes
[i
] + dstoffset
);
654 startblitter(data
, width
, height
);
663 static UBYTE
getminterm(UBYTE type
, UBYTE fg
, UBYTE bg
)
665 UBYTE minterm
= 0, tg
;
669 minterm
= (NABC
| NANBC
) | (fg
? ABC
| ABNC
| ANBC
: ANBC
);
671 case 1: // JAM1 | INVERSVID
672 minterm
= (NABC
| NANBC
) | (fg
? ANBC
| ANBNC
| ABC
: ABC
);
674 case 2: // COMPLEMENT:
675 minterm
= (NABC
| NANBC
) | (ANBC
| ABNC
);
677 case 3: // COMPLEMENT | INVERSVID:
678 minterm
= (NABC
| NANBC
) | (ABC
| ANBNC
);
680 case 5: // JAM2 | INVERSVID
686 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
687 } else if (!fg
&& !bg
) {
688 minterm
= (NABC
| NANBC
);
690 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
692 minterm
= (NABC
| NANBC
) | (ANBC
| ANBNC
);
699 BOOL
blit_putpattern(struct amigavideo_staticdata
*csd
, struct BitMap
*bm
, struct pHidd_BitMap_PutPattern
*pat
)
701 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
702 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
705 UBYTE fgpen
= GC_FG(pat
->gc
);
706 UBYTE bgpen
= GC_BG(pat
->gc
);
709 UWORD shifta
, shiftb
;
715 WORD height
= pat
->height
;
718 WORD dstx2
= pat
->x
+ pat
->width
- 1;
720 WORD patternymask
= pat
->patternheight
- 1;
727 if (pat
->patterndepth
!= 1)
730 if (GC_COLEXP(pat
->gc
) == vHidd_GC_ColExp_Transparent
)
732 else if (GC_DRMD(pat
->gc
) == vHidd_GC_DrawMode_Invert
)
736 if (pat
->invertpattern
)
739 D(bug("PutPattern(%dx%d,%dx%d,mask=%x,mod=%d,masksrcx=%d,P=%x,%dx%d,h=%d,T=%d)\n",
740 pat
->x
, pat
->y
, pat
->width
, pat
->height
,
741 pat
->mask
, pat
->maskmodulo
, pat
->masksrcx
,
742 pat
->pattern
, pat
->patternsrcx
, pat
->patternsrcy
, pat
->patternheight
, type
));
744 dstoffset
= bm
->BytesPerRow
* dsty
+ (dstx
/ 16) * 2;
745 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
752 afwm
= leftmask
[dstx
];
753 alwm
= rightmask
[dstx2
];
758 custom
->bltafwm
= afwm
;
759 custom
->bltalwm
= alwm
;
760 custom
->bltcmod
= (bm
->BytesPerRow
- dstwidth
* 2) + bm
->BytesPerRow
* (pat
->patternheight
- 1);
761 custom
->bltdmod
= (bm
->BytesPerRow
- dstwidth
* 2) + bm
->BytesPerRow
* (pat
->patternheight
- 1);
762 custom
->bltadat
= 0xffff;
764 for (i
= 0; i
< bm
->Depth
; i
++, fgpen
>>= 1, bgpen
>>= 1) {
770 if (bm
->Planes
[i
] == (UBYTE
*)0x00000000 || bm
->Planes
[i
] == (UBYTE
*)0xffffffff)
778 minterm
= getminterm(type
, fg
, bg
);
781 custom
->bltcon0
= shifta
| chmask
| minterm
;
782 custom
->bltcon1
= shiftb
;
784 for(patcnt
= 0, dstoffset2
= 0; patcnt
< pat
->patternheight
; patcnt
++, dstoffset2
+= bm
->BytesPerRow
) {
785 UWORD blitheight
= (height
- patcnt
+ 1) / pat
->patternheight
;
786 UWORD pattern
= ((UWORD
*)pat
->pattern
)[(pat
->patternsrcy
+ patcnt
) & patternymask
];
787 if (blitheight
&& pattern
) {
789 custom
->bltbdat
= pattern
;
790 custom
->bltcpt
= (APTR
)(bm
->Planes
[i
] + dstoffset
+ dstoffset2
);
791 custom
->bltdpt
= (APTR
)(bm
->Planes
[i
] + dstoffset
+ dstoffset2
);
792 startblitter(csd
, dstwidth
, blitheight
);