2 Copyright © 1995-2019, The AROS Development Team. All rights reserved.
6 #include <proto/exec.h>
7 #include <proto/graphics.h>
10 #include <exec/libraries.h>
11 #include <hardware/custom.h>
12 #include <hardware/intbits.h>
13 #include <hardware/cia.h>
15 #include <graphics/modeid.h>
17 #include "amigavideo_hidd.h"
18 #include "amigavideo_bitmap.h"
21 #include <aros/debug.h>
23 #define BPLCONMASK 0x8a55
25 static const UBYTE fetchunits
[] = { 3,3,3,0, 4,3,3,0, 5,4,3,0 };
26 static const UBYTE fm_maxplanes
[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
28 /* reset to OCS defaults */
29 void resetcustom(struct amigavideo_staticdata
*csd
)
31 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
32 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
35 bug("[AmigaVideo] %s()\n", __func__
);
36 bug("[AmigaVideo] %s: GfxBase @ 0x%p\n", __func__
, GfxBase
);
39 GfxBase
->system_bplcon0
&= ~BPLCONMASK
;
40 GfxBase
->system_bplcon0
|= 0x0200;
41 D(bug("[AmigaVideo] %s: bplcon0 = %04x\n", __func__
, GfxBase
->system_bplcon0
));
43 custom
->fmode
= 0x0000;
44 custom
->bplcon0
= GfxBase
->system_bplcon0
;
45 custom
->bplcon1
= 0x0000;
46 custom
->bplcon2
= 0x0024;
47 custom
->bplcon3
= 0x0c00;
48 custom
->bplcon4
= 0x0011;
49 custom
->vposw
= 0x8000;
50 custom
->color
[0] = 0x0444;
52 // Use AGA modes and create AGA copperlists only if AGA is "enabled"
53 csd
->aga_enabled
= csd
->aga
&& GfxBase
->ChipRevBits0
== SETCHIPREV_AA
;
56 static void waitvblank(struct amigavideo_staticdata
*csd
)
58 // ugly busy loop for now..
59 UWORD fc
= csd
->framecounter
;
60 while (fc
== csd
->framecounter
);
63 static void setnullsprite(struct amigavideo_staticdata
*csd
)
65 if (csd
->copper1_spritept
) {
66 UWORD
*p
= csd
->sprite_null
;
67 csd
->copper1_spritept
[0] = (UWORD
)(((ULONG
)p
) >> 16);
68 csd
->copper1_spritept
[2] = (UWORD
)(((ULONG
)p
) >> 0);
72 void resetsprite(struct amigavideo_staticdata
*csd
)
74 UWORD
*sprite
= csd
->sprite
;
77 FreeMem(sprite
, csd
->spritedatasize
);
78 csd
->sprite_width
= csd
->sprite_height
= 0;
81 static void setfmode(struct amigavideo_staticdata
*csd
)
84 fmode
= csd
->fmode_bpl
== 2 ? 3 : csd
->fmode_bpl
;
85 fmode
|= (csd
->fmode_spr
== 2 ? 3 : csd
->fmode_spr
) << 2;
86 if (csd
->copper2
.copper2_fmode
) {
87 *csd
->copper2
.copper2_fmode
= fmode
;
89 *csd
->copper2i
.copper2_fmode
= fmode
;
93 static void setcoppercolors(struct amigavideo_staticdata
*csd
)
97 if (!csd
->copper2
.copper2_palette
)
99 if (csd
->aga
&& csd
->aga_enabled
) {
101 for (i
= 0; i
< csd
->use_colors
; i
++) {
103 UBYTE r
= csd
->palette
[i
* 3 + 0];
104 UBYTE g
= csd
->palette
[i
* 3 + 1];
105 UBYTE b
= csd
->palette
[i
* 3 + 2];
108 valhi
= ((r
& 0xf0) << 4) | ((g
& 0xf0)) | ((b
& 0xf0) >> 4);
109 vallo
= ((r
& 0x0f) << 8) | ((g
& 0x0f) << 4) | ((b
& 0x0f));
110 csd
->copper2
.copper2_palette
[i
* 2 + off
] = valhi
;
111 csd
->copper2
.copper2_palette_aga_lo
[i
* 2 + off
] = vallo
;
112 if (csd
->interlace
) {
113 csd
->copper2i
.copper2_palette
[i
* 2 + off
] = valhi
;
114 csd
->copper2i
.copper2_palette_aga_lo
[i
* 2 + off
] = vallo
;
117 } else if (csd
->res
== 2 && !csd
->aga
) {
118 /* ECS "scrambled" superhires */
119 for (i
= 0; i
< csd
->use_colors
; i
++) {
120 UBYTE offset
= i
< 16 ? 0 : 16;
121 UBYTE c1
= (i
& 3) + offset
;
122 UBYTE c2
= ((i
>> 2) & 3) + offset
;
123 UWORD val1
= ((csd
->palette
[c1
* 3 + 0] >> 4) << 8) | ((csd
->palette
[c1
* 3 + 1] >> 4) << 4) | ((csd
->palette
[c1
* 3 + 2] >> 4) << 0);
124 UWORD val2
= ((csd
->palette
[c2
* 3 + 0] >> 4) << 8) | ((csd
->palette
[c2
* 3 + 1] >> 4) << 4) | ((csd
->palette
[c2
* 3 + 2] >> 4) << 0);
125 UWORD val
= (val1
& 0xccc) | ((val2
& 0xccc) >> 2);
126 csd
->copper2
.copper2_palette
[i
* 2 + 1] = val
;
128 csd
->copper2i
.copper2_palette
[i
* 2 + 1] = val
;
132 for (i
= 0; i
< csd
->use_colors
; i
++) {
133 UWORD val
= ((csd
->palette
[i
* 3 + 0] >> 4) << 8) | ((csd
->palette
[i
* 3 + 1] >> 4) << 4) | ((csd
->palette
[i
* 3 + 2] >> 4) << 0);
134 csd
->copper2
.copper2_palette
[i
* 2 + 1] = val
;
136 csd
->copper2i
.copper2_palette
[i
* 2 + 1] = val
;
141 static void setpalntsc(struct amigavideo_staticdata
*csd
, ULONG modeid
)
143 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
144 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
146 csd
->palmode
= (GfxBase
->DisplayFlags
& NTSC
) == 0;
149 if ((modeid
& MONITOR_ID_MASK
) == PAL_MONITOR_ID
) {
150 custom
->beamcon0
= 0x0020;
152 } else if ((modeid
& MONITOR_ID_MASK
) == NTSC_MONITOR_ID
) {
153 custom
->beamcon0
= 0x0000;
154 csd
->palmode
= FALSE
;
156 custom
->beamcon0
= (GfxBase
->DisplayFlags
& NTSC
) ? 0x0000 : 0x0020;
160 void resetmode(struct amigavideo_staticdata
*csd
)
162 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
163 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
165 D(bug("[AmigaVideo] %s()\n", __func__
));
169 custom
->dmacon
= 0x0100;
172 custom
->cop2lc
= (ULONG
)csd
->copper2_backup
;
177 FreeVec(csd
->copper2
.copper2
);
178 csd
->copper2
.copper2
= NULL
;
179 FreeVec(csd
->copper2i
.copper2
);
180 csd
->copper2i
.copper2
= NULL
;
182 GfxBase
->LOFlist
= GfxBase
->SHFlist
= csd
->copper2_backup
;
189 /* Use nominal screen height. Overscan is not supported yet. */
190 static WORD
limitheight(struct amigavideo_staticdata
*csd
, WORD y
, BOOL lace
, BOOL maxlimit
)
195 if (maxlimit
&& y
> 311)
197 else if (!maxlimit
&& y
> 256)
200 if (maxlimit
&& y
> 261)
202 else if (!maxlimit
&& y
> 200)
210 static void setcopperscroll2(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
, struct copper2data
*c2d
, BOOL odd
)
212 UWORD
*copptr
= c2d
->copper2_scroll
, *copbpl
;
213 WORD xscroll
, yscroll
;
215 WORD ystart
, yend
, i
, xdelay
;
216 WORD xmaxscroll
, modulo
, ddfstrt
, fmodewidth
, minearly
;
219 fmodewidth
= 16 << csd
->fmode_bpl
;
221 y
= csd
->starty
+ (bm
->topedge
>> csd
->interlace
);
229 xmaxscroll
= 1 << (1 + csd
->fmode_bpl
);
230 xdelay
= x
& (fmodewidth
- 1);
233 yend
= y
+ (bm
->displayheight
>> csd
->interlace
);
234 yend
= limitheight(csd
, yend
, FALSE
, TRUE
);
235 ystart
= y
- csd
->extralines
;
237 modulo
= (csd
->interlace
? bm
->bytesperrow
: 0) + csd
->modulo
;
238 ddfstrt
= csd
->ddfstrt
;
240 offset
= ((xscroll
+ (xmaxscroll
<< 3) - 1) >> 3) & ~(xmaxscroll
- 1);
241 offset
-= (yscroll
* bm
->bytesperrow
) << (csd
->interlace
? 1 : 0);
243 minearly
= 1 << fetchunits
[csd
->fmode_bpl
* 4 + csd
->res
];
246 modulo
-= (minearly
<< csd
->res
) / 4;
247 offset
-= (minearly
<< csd
->res
) / 4;
250 copptr
[1] = (y
<< 8) | (csd
->startx
); //(y << 8) + (x + 1);
251 copptr
[3] = (yend
<< 8) | ((csd
->startx
+ 0x140) & 0xff); //((y + (bm->rows >> csd->interlace)) << 8) + ((x + 1 + (bm->width >> csd->res)) & 0x00ff);
252 copptr
[5] = ((y
>> 8) & 7) | (((yend
>> 8) & 7) << 8) | 0x2000;
254 copbpl
= c2d
->copper2_bpl
;
255 for (i
= 0; i
< bm
->depth
; i
++) {
256 ULONG pptr
= (ULONG
)(bm
->pbm
->Planes
[csd
->bploffsets
[i
]]);
257 if (csd
->interlace
&& odd
)
258 pptr
+= bm
->bytesperrow
;
260 copbpl
[1] = (UWORD
)(pptr
>> 16);
261 copbpl
[3] = (UWORD
)(pptr
>> 0);
265 xdelay
<<= 2 - csd
->res
;
267 (((xdelay
>> 2) & 0x0f) << 0) | (((xdelay
>> 2) & 0x0f) << 4)
268 | ((xdelay
>> 6) << 10) | ((xdelay
>> 6) << 14)
269 | ((xdelay
& 3) << 8) | ((xdelay
& 3) << 12);
272 copptr
[9] = csd
->ddfstop
;
276 yend
= y
+ bm
->displayheight
+ yscroll
;
277 yend
= limitheight(csd
, yend
, FALSE
, TRUE
);
278 copptr
= c2d
->copper2_bplcon0
;
279 copptr
[4] = (yend
<< 8) | 0x05;
280 if (yend
< 256 || ystart
>= 256) {
288 copptr
= c2d
->copper2
;
293 copptr
[2] = (ystart
<< 8) | 0x05;
294 copptr
= c2d
->copper2_bplcon0
;
295 copptr
[-2] = (y
<< 8) | 0x05;
298 static void setcopperscroll(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
)
300 setcopperscroll2(csd
, bm
, &csd
->copper2
, FALSE
);
302 setcopperscroll2(csd
, bm
, &csd
->copper2i
, TRUE
);
305 static UWORD
get_copper_list_length(struct amigavideo_staticdata
*csd
, UBYTE depth
)
309 if (csd
->aga
&& csd
->aga_enabled
) {
310 v
= 1000 + ((1 << depth
) + 1 + (1 << depth
) / 32 + 1) * 2;
317 static void createcopperlist(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
, struct copper2data
*c2d
, BOOL lace
)
319 struct GfxBase
*GfxBase
= (struct GfxBase
*)csd
->cs_GfxBase
;
320 volatile WORD
*system_bplcon0
= (volatile WORD
*)&GfxBase
->system_bplcon0
;
323 UWORD bplcon0
, bplcon0_res
;
326 D(bug("[AmigaVideo] %s()\n", __func__
));
327 D(bug("[AmigaVideo] %s: GfxBase @ 0x%p\n", __func__
, GfxBase
));
328 D(bug("[AmigaVideo] %s: system_bplcon0 @ 0x%p\n", __func__
, system_bplcon0
));
331 D(bug("[AmigaVideo] %s: Copperlist%d %p\n", __func__
, lace
? 2 : 1, c
));
333 bplcon0_res
= *system_bplcon0
& ~BPLCONMASK
;
334 D(bug("[AmigaVideo] %s: bplcon0_res = %04x\n", __func__
, bplcon0_res
));
337 bplcon0_res
|= 0x8000;
338 else if (csd
->res
== 2)
339 bplcon0_res
|= 0x0040;
343 csd
->bplcon0_null
= 0x0201 | (csd
->interlace
? 4 : 0) | bplcon0_res
;
344 csd
->bplcon3
= ((csd
->sprite_res
+ 1) << 6) | 2; // spriteres + bordersprite
352 *c
++ = csd
->bplcon0_null
;
354 c2d
->copper2_bpl
= c
;
355 for (i
= 0; i
< bm
->depth
; i
++) {
356 pptr
= (ULONG
)(bm
->pbm
->Planes
[csd
->bploffsets
[i
]]);
358 pptr
+= bm
->bytesperrow
;
360 *c
++ = (UWORD
)(pptr
>> 16);
362 *c
++ = (UWORD
)(pptr
>> 0);
365 csd
->use_colors
= 1 << bm
->depth
;
366 // need to update sprite colors
367 if (csd
->use_colors
< 16 + 4)
368 csd
->use_colors
= 16 + 4;
369 if (csd
->res
== 2 && !csd
->aga
)
370 csd
->use_colors
= 32; /* ECS "scrambled" superhires */
372 if (csd
->use_colors
> 32 && (csd
->modeid
& EXTRAHALFBRITE_KEY
))
373 csd
->use_colors
= 32;
374 if (csd
->modeid
& HAM_KEY
) {
376 csd
->use_colors
= 16 + 4;
378 csd
->use_colors
= 64;
381 c2d
->copper2_scroll
= c
;
399 *c
++ = 0x0024 | ((csd
->aga
&& !(csd
->modeid
& EXTRAHALFBRITE_KEY
)) ? 0x0200 : 0);
401 c2d
->copper2_fmode
= NULL
;
402 if (csd
->aga
&& csd
->aga_enabled
) {
406 c2d
->copper2_fmode
= c
;
410 bplcon0
= csd
->bplcon0_null
;
414 bplcon0
|= bm
->depth
<< 12;
415 if (csd
->modeid
& HAM_KEY
)
418 *system_bplcon0
= (*system_bplcon0
& ~BPLCONMASK
) | bplcon0
;
419 D(bug("[AmigaVideo] %s: system_bplcon0 = %04x\n", __func__
, *system_bplcon0
));
421 c2d
->copper2_palette
= c
;
422 if (csd
->aga
&& csd
->aga_enabled
) {
424 for (i
= 0; i
< csd
->use_colors
; i
++) {
428 *c
++ = csd
->bplcon3
| ((i
/ 32) << 13);
430 *c
++ = 0x180 + agac
* 2;
433 c2d
->copper2_palette_aga_lo
= c
;
435 for (i
= 0; i
< csd
->use_colors
; i
++) {
439 *c
++ = csd
->bplcon3
| ((i
/ 32) << 13) | 0x0200;
441 *c
++ = 0x180 + agac
* 2;
448 for (i
= 0; i
< csd
->use_colors
; i
++) {
449 *c
++ = 0x180 + i
* 2;
454 csd
->extralines
= (c
- c2d
->copper2
) / 112 + 1;
458 c2d
->copper2_bplcon0
= c
;
468 *c
++ = csd
->bplcon0_null
;
470 if (csd
->interlace
) {
471 ULONG nextptr
= (ULONG
)(lace
? csd
->copper2
.copper2
: csd
->copper2i
.copper2
);
473 *c
++ = (UWORD
)(nextptr
>> 16);
475 *c
++ = (UWORD
)(nextptr
>> 0);
482 BOOL
setbitmap(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
)
484 csd
->width
= bm
->width
;
485 csd
->height
= csd
->interlace
? (bm
->height
+ 1) / 2 : bm
->height
;
486 csd
->modulo
= bm
->bytesperrow
- csd
->modulopre
/ (4 >> csd
->res
);
487 csd
->modulo
&= ~((2 << csd
->fmode_bpl
) - 1);
488 csd
->updatescroll
= bm
;
489 csd
->depth
= bm
->depth
;
490 setcopperscroll(csd
, bm
);
492 D(bug("setbitmap bm=%x mode=%08x w=%d h=%d d=%d bpr=%d\n",
493 bm
, csd
->modeid
, bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
));
497 BOOL
setmode(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
)
499 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
500 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
501 UWORD ddfstrt
, ddfstop
;
502 UBYTE fetchunit
, maxplanes
;
503 UWORD bplwidth
, viewwidth
;
512 if ((csd
->modeid
& SUPER_KEY
) == SUPER_KEY
)
514 else if ((csd
->modeid
& SUPER_KEY
) == HIRES_KEY
)
516 csd
->interlace
= (csd
->modeid
& LORESLACE_KEY
) ? 1 : 0;
517 csd
->fmode_bpl
= csd
->aga
&& csd
->aga_enabled
? 2 : 0;
519 fetchunit
= fetchunits
[csd
->fmode_bpl
* 4 + csd
->res
];
520 maxplanes
= fm_maxplanes
[csd
->fmode_bpl
* 4 + csd
->res
];
522 D(bug("res %d fmode %d depth %d maxplanes %d aga %d agae %d\n",
523 csd
->res
, csd
->fmode_bpl
, bm
->depth
, maxplanes
, csd
->aga
, csd
->aga_enabled
));
525 if (bm
->depth
> (1 << maxplanes
)) {
526 if (csd
->aga
&& !csd
->aga_enabled
) {
527 // Enable AGA if requesting AGA only mode.
528 // This is a compatibility hack because our display
529 // database currently contains all AGA modes even if AGA
531 GfxBase
->ChipRevBits0
= SETCHIPREV_AA
;
532 csd
->aga_enabled
= TRUE
;
533 csd
->fmode_bpl
= csd
->aga
&& csd
->aga_enabled
? 2 : 0;
534 fetchunit
= fetchunits
[csd
->fmode_bpl
* 4 + csd
->res
];
535 maxplanes
= fm_maxplanes
[csd
->fmode_bpl
* 4 + csd
->res
];
537 if (bm
->depth
> (1 << maxplanes
))
541 viewwidth
= bm
->width
;
542 // use nominal width for now
543 if ((viewwidth
<< csd
->res
) > 320)
544 viewwidth
= 320 << csd
->res
;
546 D(bug("setmode bm=%x mode=%08x w=%d h=%d d=%d bpr=%d fu=%d\n",
547 bm
, csd
->modeid
, bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
, fetchunit
));
549 bplwidth
= viewwidth
>> (csd
->res
+ 1);
550 ddfstrt
= (csd
->startx
/ 2) & ~((1 << fetchunit
) - 1);
551 ddfstop
= ddfstrt
+ ((bplwidth
+ ((1 << fetchunit
) - 1) - 2 * (1 << fetchunit
)) & ~((1 << fetchunit
) - 1));
552 csd
->modulopre
= ddfstop
+ 2 * (1 << fetchunit
) - ddfstrt
;
553 ddfstrt
-= 1 << maxplanes
;
554 csd
->ddfstrt
= ddfstrt
;
555 csd
->ddfstop
= ddfstop
;
557 for (i
= 0; i
< 8; i
++)
558 csd
->bploffsets
[i
] = i
;
559 if ((csd
->modeid
& HAM_KEY
) && bm
->depth
> 6) {
560 csd
->bploffsets
[0] = 6;
561 csd
->bploffsets
[1] = 7;
562 for (i
= 0; i
< 6; i
++)
563 csd
->bploffsets
[i
+ 2] = i
;
566 csd
->copper2
.copper2
= AllocVec(get_copper_list_length(csd
, bm
->depth
), MEMF_CLEAR
| MEMF_CHIP
);
568 csd
->copper2i
.copper2
= AllocVec(get_copper_list_length(csd
, bm
->depth
), MEMF_CLEAR
| MEMF_CHIP
);
569 createcopperlist(csd
, bm
, &csd
->copper2
, FALSE
);
570 if (csd
->interlace
) {
571 createcopperlist(csd
, bm
, &csd
->copper2i
, TRUE
);
575 setpalntsc(csd
, csd
->modeid
);
576 custom
->bplcon0
= csd
->bplcon0_null
;
578 bm
->displaywidth
= viewwidth
;
579 bm
->displayheight
= limitheight(csd
, bm
->height
, csd
->interlace
, FALSE
);
583 GfxBase
->LOFlist
= csd
->copper2
.copper2
;
584 GfxBase
->SHFlist
= csd
->interlace
? csd
->copper2i
.copper2
: csd
->copper2
.copper2
;
585 custom
->dmacon
= 0x8100;
587 setcoppercolors(csd
);
588 setspritepos(csd
, csd
->spritex
, csd
->spritey
);
594 UBYTE
av__PickPen(struct amigavideo_staticdata
*csd
, ULONG pixel
)
600 BOOL
setsprite(OOP_Class
*cl
, OOP_Object
*o
, WORD width
, WORD height
, struct pHidd_Gfx_SetCursorShape
*msg
)
602 struct amigavideo_staticdata
*csd
= CSD(cl
);
603 struct Library
*OOPBase
= csd
->cs_OOPBase
;
604 OOP_MethodID HiddGfxBase
= csd
->cs_HiddGfxBase
;
605 OOP_MethodID HiddBitMapBase
= csd
->cs_HiddBitMapBase
;
606 OOP_Object
*bmPFObj
= NULL
;
607 HIDDT_PixelFormat
*bmPF
;
610 UWORD bitmapwidth
= width
;
613 OOP_GetAttr(msg
->shape
, aHidd_BitMap_PixFmt
, (IPTR
*)&bmPFObj
);
614 OOP_GetAttr(bmPFObj
, aHidd_PixFmt_ColorModel
, &bmcmod
);
615 if (bmcmod
== vHidd_ColorModel_TrueColor
)
617 OOP_GetAttr(bmPFObj
, aHidd_PixFmt_StdPixFmt
, (IPTR
*)&pf
);
618 bmPF
= (HIDDT_PixelFormat
*)HIDD_Gfx_GetPixFmt(o
, pf
);
621 if (csd
->aga
&& csd
->aga_enabled
&& width
> 16)
625 fetchsize
= 2 << csd
->fmode_spr
;
626 width
= 16 << csd
->fmode_spr
;
628 if (width
!= csd
->sprite_width
|| height
!= csd
->sprite_height
) {
630 csd
->spritedatasize
= fetchsize
* 2 + fetchsize
* height
* 2 + fetchsize
* 2;
631 csd
->sprite
= AllocMem(csd
->spritedatasize
, MEMF_CHIP
| MEMF_CLEAR
);
634 csd
->sprite_width
= width
;
635 csd
->sprite_height
= height
;
636 csd
->sprite_offset_x
= msg
->xoffset
;
637 csd
->sprite_offset_y
= msg
->yoffset
;
641 for(y
= 0; y
< height
; y
++) {
643 for (xx
= 0, xxx
= 0; xx
< width
; xx
+= 16, xxx
++) {
644 UWORD pix1
= 0, pix2
= 0;
645 for(x
= 0; x
< 16; x
++) {
647 if (xx
+ x
< bitmapwidth
)
649 if (bmcmod
!= vHidd_ColorModel_TrueColor
)
650 c
= HIDD_BM_GetPixel(msg
->shape
, x
, y
);
653 HIDDT_Pixel pix
= HIDD_BM_GetPixel(msg
->shape
, x
, y
);
655 if ((ALPHA_COMP(pix
, bmPF
) & 0xFF00) == 0xFF00)
656 c
= av__PickPen(csd
, ((RED_COMP(pix
, bmPF
) & 0xFF00) << 8) | (GREEN_COMP(pix
, bmPF
) & 0xFF00) | ((BLUE_COMP(pix
, bmPF
) >> 8) & 0xFF));
662 pix1
|= (c
& 1) ? 1 : 0;
663 pix2
|= (c
& 2) ? 1 : 0;
666 p
[xxx
+ fetchsize
/ 2] = pix2
;
670 setspritepos(csd
, csd
->spritex
, csd
->spritey
);
671 setspritevisible(csd
, csd
->cursorvisible
);
675 void setspritepos(struct amigavideo_staticdata
*csd
, WORD x
, WORD y
)
681 if (!csd
->sprite
|| csd
->sprite_height
== 0)
684 x
+= csd
->sprite_offset_x
<< csd
->res
;
685 x
<<= (2 - csd
->res
); // convert x to shres coordinates
686 x
+= (csd
->startx
- 1) << 2; // display left edge offset
689 y
/= 2; // y is always in nonlaced
691 y
+= csd
->sprite_offset_y
;
693 pos
= (y
<< 8) | (x
>> 3);
694 ctl
= ((y
+ csd
->sprite_height
) << 8);
695 ctl
|= ((y
>> 8) << 2) | (((y
+ csd
->sprite_height
) >> 8) << 1) | ((x
>> 2) & 1) | ((x
& 3) << 3);
696 csd
->spritepos
= pos
;
697 csd
->spritectl
= ctl
;
700 void setspritevisible(struct amigavideo_staticdata
*csd
, BOOL visible
)
702 csd
->cursorvisible
= visible
;
704 if (csd
->copper1_spritept
) {
705 UWORD
*p
= csd
->sprite
;
707 csd
->copper1_spritept
[0] = (UWORD
)(((ULONG
)p
) >> 16);
708 csd
->copper1_spritept
[2] = (UWORD
)(((ULONG
)p
) >> 0);
715 BOOL
setcolors(struct amigavideo_staticdata
*csd
, struct pHidd_BitMap_SetColors
*msg
, BOOL visible
)
718 if (msg
->firstColor
+ msg
->numColors
> csd
->max_colors
)
721 for (i
= msg
->firstColor
; j
< msg
->numColors
; i
++, j
++) {
722 UBYTE red
, green
, blue
;
723 red
= msg
->colors
[j
].red
>> 8;
724 green
= msg
->colors
[j
].green
>> 8;
725 blue
= msg
->colors
[j
].blue
>> 8;
726 csd
->palette
[i
* 3 + 0] = red
;
727 csd
->palette
[i
* 3 + 1] = green
;
728 csd
->palette
[i
* 3 + 2] = blue
;
729 //bug("%d: %02x %02x %02x\n", i, red, green, blue);
732 setcoppercolors(csd
);
735 void setscroll(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
)
737 csd
->updatescroll
= bm
;
740 /* Convert Z flag to normal C-style return variable. Fun. */
741 UBYTE
bltnode_wrapper(void)
746 " move.l 4(%%a1),-(%%sp)\n"
755 #define BEAMSYNC_ALARM 0x0f00
756 /* AOS must use some GfxBase flags field for these. Later.. */
757 #define bqvar GfxBase->pad3
759 #define BQ_BEAMSYNC 2
760 #define BQ_BEAMSYNCWAITING 4
763 static AROS_INTH1(gfx_blit
, struct GfxBase
*, GfxBase
)
767 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
768 struct bltnode
*bn
= NULL
;
772 dmaconr
= custom
->dmaconr
;
773 dmaconr
= custom
->dmaconr
;
774 if (dmaconr
& 0x4000) {
775 /* Blitter still active? Wait for next interrupt. */
779 if (GfxBase
->blthd
== NULL
&& GfxBase
->bsblthd
== NULL
) {
780 custom
->intena
= INTF_BLIT
;
784 /* Was last blit in this node? */
785 if (bqvar
& BQ_NEXT
) {
786 bqvar
&= ~(BQ_NEXT
| BQ_MISSED
);
787 if (bqvar
& BQ_BEAMSYNC
)
788 bn
= GfxBase
->bsblthd
;
791 if (bn
->stat
== CLEANUP
)
792 AROS_UFC2(UBYTE
, bn
->cleanup
,
793 AROS_UFCA(struct Custom
*, custom
, A0
),
794 AROS_UFCA(struct bltnode
*, bn
, A1
));
797 if (bqvar
& BQ_BEAMSYNC
)
798 GfxBase
->bsblthd
= bn
;
803 if (GfxBase
->bsblthd
) {
804 bn
= GfxBase
->bsblthd
;
805 bqvar
|= BQ_BEAMSYNC
;
806 } else if (GfxBase
->blthd
) {
808 bqvar
&= ~BQ_BEAMSYNC
;
812 /* Last blit finished */
814 custom
->intena
= INTF_BLIT
;
815 GfxBase
->blthd
= GfxBase
->bsblthd
= NULL
;
820 if (bqvar
& BQ_BEAMSYNC
) {
821 UWORD vpos
= VBeamPos();
822 bqvar
&= ~BQ_BEAMSYNCWAITING
;
823 if (!(bqvar
& BQ_MISSED
) && bn
->beamsync
> vpos
) {
824 volatile struct CIA
*ciab
= (struct CIA
*)0xbfd000;
825 UWORD w
= BEAMSYNC_ALARM
- (bn
->beamsync
- vpos
);
826 bqvar
|= BQ_BEAMSYNCWAITING
;
827 ciab
->ciacrb
&= ~0x80;
829 ciab
->ciatodmid
= w
>> 8;
835 v
= AROS_UFC2(UBYTE
, bltnode_wrapper
,
836 AROS_UFCA(struct Custom
*, custom
, A0
),
837 AROS_UFCA(struct bltnode
*, bn
, A1
));
839 dmaconr
= custom
->dmaconr
;
840 dmaconr
= custom
->dmaconr
;
841 if (!(dmaconr
& 0x4000)) {
842 /* Eh? Blitter not active?, better fake the interrupt. */
843 custom
->intreq
= INTF_SETCLR
| INTF_BLIT
;
847 /* Handle same node again next time */
858 static AROS_INTH1(gfx_beamsync
, struct amigavideo_staticdata
*, csd
)
862 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
864 if (bqvar
& BQ_BEAMSYNCWAITING
) {
865 /* We only need to trigger blitter interrupt */
866 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
867 custom
->intreq
= INTF_SETCLR
| INTF_BLIT
;
875 static AROS_INTH1(gfx_vblank
, struct amigavideo_staticdata
*, csd
)
879 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
880 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
881 BOOL lof
= (custom
->vposr
& 0x8000) != 0;
883 if (csd
->interlace
) {
884 custom
->cop2lc
= (ULONG
)(lof
? GfxBase
->LOFlist
: GfxBase
->SHFlist
);
886 custom
->cop2lc
= (ULONG
)GfxBase
->LOFlist
;
887 /* We may be in SHF mode after switching interlace off. Fix it here. */
889 custom
->vposw
= custom
->vposr
| 0x8000;
894 UWORD
*p
= csd
->sprite
;
895 p
[0] = csd
->spritepos
;
896 p
[1 << csd
->fmode_spr
] = csd
->spritectl
;
899 if (csd
->updatescroll
) {
900 setcopperscroll(csd
, csd
->updatescroll
);
901 csd
->updatescroll
= NULL
;
904 if (bqvar
& BQ_BEAMSYNC
)
912 void initcustom(struct amigavideo_staticdata
*csd
)
917 struct GfxBase
*GfxBase
;
918 struct Library
*OOPBase
;
919 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
920 volatile struct CIA
*ciab
= (struct CIA
*)0xbfd000;
922 D(bug("[AmigaVideo] %s()\n", __func__
));
924 /* Reset audio registers to values that help emulation
925 * if some program enables audio DMA without setting period
926 * or length. Very high period emulation is very CPU intensive.
928 for (i
= 0; i
< 4; i
++) {
929 custom
->aud
[i
].ac_vol
= 0;
930 custom
->aud
[i
].ac_per
= 100;
931 custom
->aud
[i
].ac_len
= 1000;
934 /* csd->cs_OOPBase was already set up.
935 * See amigavideo.conf's 'oopbase_field' config
937 OOPBase
= csd
->cs_OOPBase
;
938 csd
->cs_HiddBitMapBase
= OOP_GetMethodID(IID_Hidd_BitMap
, 0);
939 csd
->cs_HiddGfxBase
= OOP_GetMethodID(IID_Hidd_Gfx
, 0);
941 csd
->cs_UtilityBase
= TaggedOpenLibrary(TAGGEDOPEN_UTILITY
);
942 if (!csd
->cs_UtilityBase
)
943 Alert(AT_DeadEnd
| AN_Hidd
| AG_OpenLib
| AO_UtilityLib
);
944 csd
->cs_GfxBase
= TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
945 if (!csd
->cs_GfxBase
)
946 Alert(AT_DeadEnd
| AN_Hidd
| AG_OpenLib
| AO_GraphicsLib
);
947 GfxBase
= ((struct GfxBase
*)csd
->cs_GfxBase
);
948 GfxBase
->cia
= OpenResource("ciab.resource");
950 /* Reset now we have the bases */
954 csd
->inter
.is_Code
= (APTR
)gfx_vblank
;
955 csd
->inter
.is_Data
= csd
;
956 csd
->inter
.is_Node
.ln_Name
= "GFX VBlank server";
957 csd
->inter
.is_Node
.ln_Pri
= 25;
958 csd
->inter
.is_Node
.ln_Type
= NT_INTERRUPT
;
959 AddIntServer(INTB_VERTB
, &csd
->inter
);
961 /* There are programs that take over the system and
962 * assume SysBase->IntVects[BLITTER].iv_Data = GfxBase!
964 GfxBase
->bltsrv
.is_Code
= (APTR
)gfx_blit
;
965 GfxBase
->bltsrv
.is_Data
= GfxBase
;
966 GfxBase
->bltsrv
.is_Node
.ln_Name
= "Blitter";
967 GfxBase
->bltsrv
.is_Node
.ln_Type
= NT_INTERRUPT
;
968 SetIntVector(INTB_BLIT
, &GfxBase
->bltsrv
);
969 custom
->intena
= INTF_BLIT
;
971 // CIA-B TOD counts scanlines */
972 GfxBase
->timsrv
.is_Code
= (APTR
)gfx_beamsync
;
973 GfxBase
->timsrv
.is_Data
= csd
;
974 GfxBase
->timsrv
.is_Node
.ln_Name
= "Beamsync";
975 GfxBase
->timsrv
.is_Node
.ln_Type
= NT_INTERRUPT
;
977 AddICRVector(GfxBase
->cia
, 2, &GfxBase
->timsrv
);
978 AbleICR(GfxBase
->cia
, 1 << 2);
979 ciab
->ciacrb
|= 0x80;
981 /* TOD/ALARM CIA bug: http://eab.abime.net/showpost.php?p=277315&postcount=10 */
982 ciab
->ciatodmid
= BEAMSYNC_ALARM
>> 8;
983 ciab
->ciatodlow
= BEAMSYNC_ALARM
& 0xff;
984 ciab
->ciacrb
&= ~0x80;
988 AbleICR(GfxBase
->cia
, 0x80 | (1 << 2));
991 GfxBase
->NormalDisplayColumns
= 640;
992 GfxBase
->NormalDisplayRows
= (GfxBase
->DisplayFlags
& NTSC
) ? 200 : 256;
993 GfxBase
->MaxDisplayColumn
= 640;
994 GfxBase
->MaxDisplayRow
= (GfxBase
->DisplayFlags
& NTSC
) ? 200 : 256;
999 vposr
= custom
->vposr
& 0x7f00;
1000 csd
->aga
= vposr
>= 0x2200;
1001 csd
->ecs_agnus
= vposr
>= 0x2000;
1002 val
= custom
->deniseid
;
1003 custom
->deniseid
= custom
->dmaconr
;;
1004 if (val
== custom
->deniseid
) {
1005 custom
->deniseid
= custom
->dmaconr
^ 0x8000;
1006 if (val
== custom
->deniseid
) {
1007 if ((val
& (2 + 8)) == 8)
1008 csd
->ecs_denise
= TRUE
;
1011 csd
->max_colors
= csd
->aga
? 256 : 32;
1012 csd
->palette
= AllocVec(csd
->max_colors
* 3, MEMF_CLEAR
);
1013 csd
->copper1
= AllocVec(22 * 2 * sizeof(WORD
), MEMF_CLEAR
| MEMF_CHIP
);
1014 csd
->sprite_null
= AllocMem(2 * 8, MEMF_CLEAR
| MEMF_CHIP
);
1015 csd
->sprite_res
= 0; /* lores */
1017 for (i
= 0; i
< 8; i
++) {
1018 *c
++ = 0x0120 + i
* 4;
1020 csd
->copper1_spritept
= c
;
1021 *c
++ = (UWORD
)(((ULONG
)csd
->sprite_null
) >> 16);
1022 *c
++ = 0x0122 + i
* 4;
1023 *c
++ = (UWORD
)(((ULONG
)csd
->sprite_null
) >> 0);
1029 csd
->copper2_backup
= c
;
1032 custom
->cop1lc
= (ULONG
)csd
->copper1
;
1033 custom
->cop2lc
= (ULONG
)csd
->copper2_backup
;
1034 custom
->dmacon
= 0x8000 | 0x0080 | 0x0040 | 0x0020;
1036 GfxBase
->copinit
= (struct copinit
*)csd
->copper1
;
1038 D(bug("Copperlist0 %p\n", csd
->copper1
));