2 #include <proto/exec.h>
3 #include <proto/graphics.h>
6 #include <exec/libraries.h>
7 #include <hardware/custom.h>
8 #include <hardware/intbits.h>
9 #include <hardware/cia.h>
10 #include <hidd/graphics.h>
11 #include <graphics/modeid.h>
13 #include "amigavideogfx.h"
14 #include "amigavideobitmap.h"
18 #include <aros/debug.h>
20 static const UBYTE fetchunits
[] = { 3,3,3,0, 4,3,3,0, 5,4,3,0 };
21 static const UBYTE fm_maxplanes
[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
23 /* reset to OCS defaults */
24 void resetcustom(struct amigavideo_staticdata
*data
)
26 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
27 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
29 custom
->fmode
= 0x0000;
30 custom
->bplcon0
= 0x0200;
31 custom
->bplcon1
= 0x0000;
32 custom
->bplcon2
= 0x0000;
33 custom
->bplcon3
= 0x0c00;
34 custom
->bplcon4
= 0x0011;
35 custom
->vposw
= 0x8000;
36 custom
->color
[0] = 0x0444;
38 // Use AGA modes and create AGA copperlists only if AGA is "enabled"
39 data
->aga_enabled
= data
->aga
&& GfxBase
->ChipRevBits0
== SETCHIPREV_AA
;
42 static void waitvblank(struct amigavideo_staticdata
*data
)
44 // ugly busy loop for now..
45 UWORD fc
= data
->framecounter
;
46 while (fc
== data
->framecounter
);
49 static void setnullsprite(struct amigavideo_staticdata
*data
)
51 if (data
->copper1_spritept
) {
52 UWORD
*p
= data
->sprite_null
;
53 data
->copper1_spritept
[0] = (UWORD
)(((ULONG
)p
) >> 16);
54 data
->copper1_spritept
[2] = (UWORD
)(((ULONG
)p
) >> 0);
58 void resetsprite(struct amigavideo_staticdata
*data
)
60 UWORD
*sprite
= data
->sprite
;
63 FreeMem(sprite
, data
->spritedatasize
);
64 data
->sprite_width
= data
->sprite_height
= 0;
67 static void setfmode(struct amigavideo_staticdata
*data
)
70 fmode
= data
->fmode_bpl
== 2 ? 3 : data
->fmode_bpl
;
71 fmode
|= (data
->fmode_spr
== 2 ? 3 : data
->fmode_spr
) << 2;
72 if (data
->copper2
.copper2_fmode
) {
73 *data
->copper2
.copper2_fmode
= fmode
;
75 *data
->copper2i
.copper2_fmode
= fmode
;
79 static void setcoppercolors(struct amigavideo_staticdata
*data
)
83 if (!data
->copper2
.copper2_palette
)
85 if (data
->aga
&& data
->aga_enabled
) {
87 for (i
= 0; i
< data
->use_colors
; i
++) {
89 UBYTE r
= data
->palette
[i
* 3 + 0];
90 UBYTE g
= data
->palette
[i
* 3 + 1];
91 UBYTE b
= data
->palette
[i
* 3 + 2];
94 valhi
= ((r
& 0xf0) << 4) | ((g
& 0xf0)) | ((b
& 0xf0) >> 4);
95 vallo
= ((r
& 0x0f) << 8) | ((g
& 0x0f) << 4) | ((b
& 0x0f));
96 data
->copper2
.copper2_palette
[i
* 2 + off
] = valhi
;
97 data
->copper2
.copper2_palette_aga_lo
[i
* 2 + off
] = vallo
;
98 if (data
->interlace
) {
99 data
->copper2i
.copper2_palette
[i
* 2 + off
] = valhi
;
100 data
->copper2i
.copper2_palette_aga_lo
[i
* 2 + off
] = vallo
;
103 } else if (data
->res
== 2 && !data
->aga
) {
104 /* ECS "scrambled" superhires */
105 for (i
= 0; i
< data
->use_colors
; i
++) {
106 UBYTE offset
= i
< 16 ? 0 : 16;
107 UBYTE c1
= (i
& 3) + offset
;
108 UBYTE c2
= ((i
>> 2) & 3) + offset
;
109 UWORD val1
= ((data
->palette
[c1
* 3 + 0] >> 4) << 8) | ((data
->palette
[c1
* 3 + 1] >> 4) << 4) | ((data
->palette
[c1
* 3 + 2] >> 4) << 0);
110 UWORD val2
= ((data
->palette
[c2
* 3 + 0] >> 4) << 8) | ((data
->palette
[c2
* 3 + 1] >> 4) << 4) | ((data
->palette
[c2
* 3 + 2] >> 4) << 0);
111 UWORD val
= (val1
& 0xccc) | ((val2
& 0xccc) >> 2);
112 data
->copper2
.copper2_palette
[i
* 2 + 1] = val
;
114 data
->copper2i
.copper2_palette
[i
* 2 + 1] = val
;
118 for (i
= 0; i
< data
->use_colors
; i
++) {
119 UWORD val
= ((data
->palette
[i
* 3 + 0] >> 4) << 8) | ((data
->palette
[i
* 3 + 1] >> 4) << 4) | ((data
->palette
[i
* 3 + 2] >> 4) << 0);
120 data
->copper2
.copper2_palette
[i
* 2 + 1] = val
;
122 data
->copper2i
.copper2_palette
[i
* 2 + 1] = val
;
127 static void setpalntsc(struct amigavideo_staticdata
*data
, ULONG modeid
)
129 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
130 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
132 data
->palmode
= (GfxBase
->DisplayFlags
& NTSC
) == 0;
133 if (!data
->ecs_agnus
)
135 if ((modeid
& MONITOR_ID_MASK
) == PAL_MONITOR_ID
) {
136 custom
->beamcon0
= 0x0020;
137 data
->palmode
= TRUE
;
138 } else if ((modeid
& MONITOR_ID_MASK
) == NTSC_MONITOR_ID
) {
139 custom
->beamcon0
= 0x0000;
140 data
->palmode
= FALSE
;
142 custom
->beamcon0
= (GfxBase
->DisplayFlags
& NTSC
) ? 0x0000 : 0x0020;
146 void resetmode(struct amigavideo_staticdata
*data
)
148 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
149 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
151 D(bug("resetmode\n"));
155 custom
->dmacon
= 0x0100;
158 custom
->cop2lc
= (ULONG
)data
->copper2_backup
;
163 FreeVec(data
->copper2
.copper2
);
164 data
->copper2
.copper2
= NULL
;
165 FreeVec(data
->copper2i
.copper2
);
166 data
->copper2i
.copper2
= NULL
;
168 GfxBase
->LOFlist
= GfxBase
->SHFlist
= data
->copper2_backup
;
175 /* Use nominal screen height. Overscan is not supported yet. */
176 static WORD
limitheight(struct amigavideo_staticdata
*data
, WORD y
, BOOL lace
, BOOL maxlimit
)
181 if (maxlimit
&& y
> 311)
183 else if (!maxlimit
&& y
> 256)
186 if (maxlimit
&& y
> 261)
188 else if (!maxlimit
&& y
> 200)
196 static void setcopperscroll2(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
, struct copper2data
*c2d
, BOOL odd
)
198 UWORD
*copptr
= c2d
->copper2_scroll
, *copbpl
;
199 WORD xscroll
, yscroll
;
201 WORD ystart
, yend
, i
, xdelay
;
202 WORD xmaxscroll
, modulo
, ddfstrt
, fmodewidth
, minearly
;
205 fmodewidth
= 16 << data
->fmode_bpl
;
207 y
= data
->starty
+ (bm
->topedge
>> data
->interlace
);
215 xmaxscroll
= 1 << (1 + data
->fmode_bpl
);
216 xdelay
= x
& (fmodewidth
- 1);
219 yend
= y
+ (bm
->displayheight
>> data
->interlace
);
220 yend
= limitheight(data
, yend
, FALSE
, TRUE
);
221 ystart
= y
- data
->extralines
;
223 modulo
= (data
->interlace
? bm
->bytesperrow
: 0) + data
->modulo
;
224 ddfstrt
= data
->ddfstrt
;
226 offset
= ((xscroll
+ (xmaxscroll
<< 3) - 1) >> 3) & ~(xmaxscroll
- 1);
227 offset
-= (yscroll
* bm
->bytesperrow
) << (data
->interlace
? 1 : 0);
229 minearly
= 1 << fetchunits
[data
->fmode_bpl
* 4 + data
->res
];
232 modulo
-= (minearly
<< data
->res
) / 4;
233 offset
-= (minearly
<< data
->res
) / 4;
236 copptr
[1] = (y
<< 8) | (data
->startx
); //(y << 8) + (x + 1);
237 copptr
[3] = (yend
<< 8) | ((data
->startx
+ 0x140) & 0xff); //((y + (bm->rows >> data->interlace)) << 8) + ((x + 1 + (bm->width >> data->res)) & 0x00ff);
238 copptr
[5] = ((y
>> 8) & 7) | (((yend
>> 8) & 7) << 8) | 0x2000;
240 copbpl
= c2d
->copper2_bpl
;
241 for (i
= 0; i
< bm
->depth
; i
++) {
242 ULONG pptr
= (ULONG
)(bm
->pbm
->Planes
[data
->bploffsets
[i
]]);
243 if (data
->interlace
&& odd
)
244 pptr
+= bm
->bytesperrow
;
246 copbpl
[1] = (UWORD
)(pptr
>> 16);
247 copbpl
[3] = (UWORD
)(pptr
>> 0);
251 xdelay
<<= 2 - data
->res
;
253 (((xdelay
>> 2) & 0x0f) << 0) | (((xdelay
>> 2) & 0x0f) << 4)
254 | ((xdelay
>> 6) << 10) | ((xdelay
>> 6) << 14)
255 | ((xdelay
& 3) << 8) | ((xdelay
& 3) << 12);
258 copptr
[9] = data
->ddfstop
;
262 yend
= y
+ bm
->displayheight
+ yscroll
;
263 yend
= limitheight(data
, yend
, FALSE
, TRUE
);
264 copptr
= c2d
->copper2_bplcon0
;
265 copptr
[4] = (yend
<< 8) | 0x05;
266 if (yend
< 256 || ystart
>= 256) {
274 copptr
= c2d
->copper2
;
279 copptr
[2] = (ystart
<< 8) | 0x05;
280 copptr
= c2d
->copper2_bplcon0
;
281 copptr
[-2] = (y
<< 8) | 0x05;
284 static void setcopperscroll(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
)
286 setcopperscroll2(data
, bm
, &data
->copper2
, FALSE
);
288 setcopperscroll2(data
, bm
, &data
->copper2i
, TRUE
);
291 static UWORD
get_copper_list_length(struct amigavideo_staticdata
*data
, UBYTE depth
)
295 if (data
->aga
&& data
->aga_enabled
) {
296 v
= 1000 + ((1 << depth
) + 1 + (1 << depth
) / 32 + 1) * 2;
303 static void createcopperlist(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
, struct copper2data
*c2d
, BOOL lace
)
307 UWORD bplcon0
, bplcon0_res
;
311 D(bug("Copperlist%d %p\n", lace
? 2 : 1, c
));
314 bplcon0_res
= 0x8000;
315 else if (data
->res
== 2)
316 bplcon0_res
= 0x0040;
320 data
->bplcon0_null
= 0x0201 | (data
->interlace
? 4 : 0) | bplcon0_res
;
321 data
->bplcon3
= ((data
->sprite_res
+ 1) << 6) | 2; // spriteres + bordersprite
329 *c
++ = data
->bplcon0_null
;
331 c2d
->copper2_bpl
= c
;
332 for (i
= 0; i
< bm
->depth
; i
++) {
333 pptr
= (ULONG
)(bm
->pbm
->Planes
[data
->bploffsets
[i
]]);
335 pptr
+= bm
->bytesperrow
;
337 *c
++ = (UWORD
)(pptr
>> 16);
339 *c
++ = (UWORD
)(pptr
>> 0);
342 data
->use_colors
= 1 << bm
->depth
;
343 // need to update sprite colors
344 if (data
->use_colors
< 16 + 4)
345 data
->use_colors
= 16 + 4;
346 if (data
->res
== 2 && !data
->aga
)
347 data
->use_colors
= 32; /* ECS "scrambled" superhires */
349 if (data
->use_colors
> 32 && (data
->modeid
& EXTRAHALFBRITE_KEY
))
350 data
->use_colors
= 32;
351 if (data
->modeid
& HAM_KEY
) {
353 data
->use_colors
= 16 + 4;
355 data
->use_colors
= 64;
358 c2d
->copper2_scroll
= c
;
376 *c
++ = 0x0024 | ((data
->aga
&& !(data
->modeid
& EXTRAHALFBRITE_KEY
)) ? 0x0200 : 0);
378 c2d
->copper2_fmode
= NULL
;
379 if (data
->aga
&& data
->aga_enabled
) {
383 c2d
->copper2_fmode
= c
;
387 bplcon0
= data
->bplcon0_null
;
391 bplcon0
|= bm
->depth
<< 12;
392 if (data
->modeid
& HAM_KEY
)
395 c2d
->copper2_palette
= c
;
396 if (data
->aga
&& data
->aga_enabled
) {
398 for (i
= 0; i
< data
->use_colors
; i
++) {
402 *c
++ = data
->bplcon3
| ((i
/ 32) << 13);
404 *c
++ = 0x180 + agac
* 2;
407 c2d
->copper2_palette_aga_lo
= c
;
409 for (i
= 0; i
< data
->use_colors
; i
++) {
413 *c
++ = data
->bplcon3
| ((i
/ 32) << 13) | 0x0200;
415 *c
++ = 0x180 + agac
* 2;
419 *c
++ = data
->bplcon3
;
422 for (i
= 0; i
< data
->use_colors
; i
++) {
423 *c
++ = 0x180 + i
* 2;
428 data
->extralines
= (c
- c2d
->copper2
) / 112 + 1;
432 c2d
->copper2_bplcon0
= c
;
442 *c
++ = data
->bplcon0_null
;
444 if (data
->interlace
) {
445 ULONG nextptr
= (ULONG
)(lace
? data
->copper2
.copper2
: data
->copper2i
.copper2
);
447 *c
++ = (UWORD
)(nextptr
>> 16);
449 *c
++ = (UWORD
)(nextptr
>> 0);
456 BOOL
setbitmap(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
)
458 data
->width
= bm
->width
;
459 data
->height
= data
->interlace
? (bm
->height
+ 1) / 2 : bm
->height
;
460 data
->modulo
= bm
->bytesperrow
- data
->modulopre
/ (4 >> data
->res
);
461 data
->modulo
&= ~((2 << data
->fmode_bpl
) - 1);
462 data
->updatescroll
= bm
;
463 data
->depth
= bm
->depth
;
464 setcopperscroll(data
, bm
);
466 D(bug("setbitmap bm=%x mode=%08x w=%d h=%d d=%d bpr=%d\n",
467 bm
, data
->modeid
, bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
));
471 BOOL
setmode(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
)
473 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
474 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
475 UWORD ddfstrt
, ddfstop
;
476 UBYTE fetchunit
, maxplanes
;
477 UWORD bplwidth
, viewwidth
;
480 if (data
->disp
== bm
)
486 if ((data
->modeid
& SUPER_KEY
) == SUPER_KEY
)
488 else if ((data
->modeid
& SUPER_KEY
) == HIRES_KEY
)
490 data
->interlace
= (data
->modeid
& LORESLACE_KEY
) ? 1 : 0;
491 data
->fmode_bpl
= data
->aga
&& data
->aga_enabled
? 2 : 0;
493 fetchunit
= fetchunits
[data
->fmode_bpl
* 4 + data
->res
];
494 maxplanes
= fm_maxplanes
[data
->fmode_bpl
* 4 + data
->res
];
496 D(bug("res %d fmode %d depth %d maxplanes %d aga %d agae %d\n",
497 data
->res
, data
->fmode_bpl
, bm
->depth
, maxplanes
, data
->aga
, data
->aga_enabled
));
499 if (bm
->depth
> (1 << maxplanes
)) {
500 if (data
->aga
&& !data
->aga_enabled
) {
501 // Enable AGA if requesting AGA only mode.
502 // This is a compatibility hack because our display
503 // database currently contains all AGA modes even if AGA
505 GfxBase
->ChipRevBits0
= SETCHIPREV_AA
;
506 data
->aga_enabled
= TRUE
;
507 data
->fmode_bpl
= data
->aga
&& data
->aga_enabled
? 2 : 0;
508 fetchunit
= fetchunits
[data
->fmode_bpl
* 4 + data
->res
];
509 maxplanes
= fm_maxplanes
[data
->fmode_bpl
* 4 + data
->res
];
511 if (bm
->depth
> (1 << maxplanes
))
515 viewwidth
= bm
->width
;
516 // use nominal width for now
517 if ((viewwidth
<< data
->res
) > 320)
518 viewwidth
= 320 << data
->res
;
520 D(bug("setmode bm=%x mode=%08x w=%d h=%d d=%d bpr=%d fu=%d\n",
521 bm
, data
->modeid
, bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
, fetchunit
));
523 bplwidth
= viewwidth
>> (data
->res
+ 1);
524 ddfstrt
= (data
->startx
/ 2) & ~((1 << fetchunit
) - 1);
525 ddfstop
= ddfstrt
+ ((bplwidth
+ ((1 << fetchunit
) - 1) - 2 * (1 << fetchunit
)) & ~((1 << fetchunit
) - 1));
526 data
->modulopre
= ddfstop
+ 2 * (1 << fetchunit
) - ddfstrt
;
527 ddfstrt
-= 1 << maxplanes
;
528 data
->ddfstrt
= ddfstrt
;
529 data
->ddfstop
= ddfstop
;
531 for (i
= 0; i
< 8; i
++)
532 data
->bploffsets
[i
] = i
;
533 if ((data
->modeid
& HAM_KEY
) && bm
->depth
> 6) {
534 data
->bploffsets
[0] = 6;
535 data
->bploffsets
[1] = 7;
536 for (i
= 0; i
< 6; i
++)
537 data
->bploffsets
[i
+ 2] = i
;
540 data
->copper2
.copper2
= AllocVec(get_copper_list_length(data
, bm
->depth
), MEMF_CLEAR
| MEMF_CHIP
);
542 data
->copper2i
.copper2
= AllocVec(get_copper_list_length(data
, bm
->depth
), MEMF_CLEAR
| MEMF_CHIP
);
543 createcopperlist(data
, bm
, &data
->copper2
, FALSE
);
544 if (data
->interlace
) {
545 createcopperlist(data
, bm
, &data
->copper2i
, TRUE
);
549 setpalntsc(data
, data
->modeid
);
550 custom
->bplcon0
= data
->bplcon0_null
;
552 bm
->displaywidth
= viewwidth
;
553 bm
->displayheight
= limitheight(data
, bm
->height
, data
->interlace
, FALSE
);
557 GfxBase
->LOFlist
= data
->copper2
.copper2
;
558 GfxBase
->SHFlist
= data
->interlace
? data
->copper2i
.copper2
: data
->copper2
.copper2
;
559 custom
->dmacon
= 0x8100;
561 setcoppercolors(data
);
562 setspritepos(data
, data
->spritex
, data
->spritey
);
568 BOOL
setsprite(struct amigavideo_staticdata
*data
, WORD width
, WORD height
, struct pHidd_Gfx_SetCursorShape
*shape
)
570 OOP_MethodID HiddBitMapBase
= data
->cs_HiddBitMapBase
;
572 UWORD bitmapwidth
= width
;
575 if (data
->aga
&& data
->aga_enabled
&& width
> 16)
579 fetchsize
= 2 << data
->fmode_spr
;
580 width
= 16 << data
->fmode_spr
;
582 if (width
!= data
->sprite_width
|| height
!= data
->sprite_height
) {
584 data
->spritedatasize
= fetchsize
* 2 + fetchsize
* height
* 2 + fetchsize
* 2;
585 data
->sprite
= AllocMem(data
->spritedatasize
, MEMF_CHIP
| MEMF_CLEAR
);
588 data
->sprite_width
= width
;
589 data
->sprite_height
= height
;
590 data
->sprite_offset_x
= shape
->xoffset
;
591 data
->sprite_offset_y
= shape
->yoffset
;
595 for(y
= 0; y
< height
; y
++) {
597 for (xx
= 0, xxx
= 0; xx
< width
; xx
+= 16, xxx
++) {
598 UWORD pix1
= 0, pix2
= 0;
599 for(x
= 0; x
< 16; x
++) {
601 if (xx
+ x
< bitmapwidth
)
602 c
= HIDD_BM_GetPixel(shape
->shape
, xx
+ x
, y
);
604 /* Sprite alignment grid */
605 if (xx
+ x
== 0 || xx
+ x
== width
- 1 || y
== 0 || y
== height
- 1) {
613 pix1
|= (c
& 1) ? 1 : 0;
614 pix2
|= (c
& 2) ? 1 : 0;
617 p
[xxx
+ fetchsize
/ 2] = pix2
;
621 setspritepos(data
, data
->spritex
, data
->spritey
);
622 setspritevisible(data
, data
->cursorvisible
);
626 void setspritepos(struct amigavideo_staticdata
*data
, WORD x
, WORD y
)
632 if (!data
->sprite
|| data
->sprite_height
== 0)
635 x
+= data
->sprite_offset_x
<< data
->res
;
636 x
<<= (2 - data
->res
); // convert x to shres coordinates
637 x
+= (data
->startx
- 1) << 2; // display left edge offset
640 y
/= 2; // y is always in nonlaced
642 y
+= data
->sprite_offset_y
;
644 pos
= (y
<< 8) | (x
>> 3);
645 ctl
= ((y
+ data
->sprite_height
) << 8);
646 ctl
|= ((y
>> 8) << 2) | (((y
+ data
->sprite_height
) >> 8) << 1) | ((x
>> 2) & 1) | ((x
& 3) << 3);
647 data
->spritepos
= pos
;
648 data
->spritectl
= ctl
;
651 void setspritevisible(struct amigavideo_staticdata
*data
, BOOL visible
)
653 data
->cursorvisible
= visible
;
655 if (data
->copper1_spritept
) {
656 UWORD
*p
= data
->sprite
;
658 data
->copper1_spritept
[0] = (UWORD
)(((ULONG
)p
) >> 16);
659 data
->copper1_spritept
[2] = (UWORD
)(((ULONG
)p
) >> 0);
666 BOOL
setcolors(struct amigavideo_staticdata
*data
, struct pHidd_BitMap_SetColors
*msg
, BOOL visible
)
669 if (msg
->firstColor
+ msg
->numColors
> data
->max_colors
)
672 for (i
= msg
->firstColor
; j
< msg
->numColors
; i
++, j
++) {
673 UBYTE red
, green
, blue
;
674 red
= msg
->colors
[j
].red
>> 8;
675 green
= msg
->colors
[j
].green
>> 8;
676 blue
= msg
->colors
[j
].blue
>> 8;
677 data
->palette
[i
* 3 + 0] = red
;
678 data
->palette
[i
* 3 + 1] = green
;
679 data
->palette
[i
* 3 + 2] = blue
;
680 //bug("%d: %02x %02x %02x\n", i, red, green, blue);
683 setcoppercolors(data
);
686 void setscroll(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
)
688 data
->updatescroll
= bm
;
691 /* Convert Z flag to normal C-style return variable. Fun. */
692 UBYTE
bltnode_wrapper(void)
697 " move.l 4(%%a1),-(%%sp)\n"
706 #define BEAMSYNC_ALARM 0x0f00
707 /* AOS must use some GfxBase flags field for these. Later.. */
708 #define bqvar GfxBase->pad3
710 #define BQ_BEAMSYNC 2
711 #define BQ_BEAMSYNCWAITING 4
714 static AROS_INTH1(gfx_blit
, struct GfxBase
*, GfxBase
)
718 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
719 struct bltnode
*bn
= NULL
;
723 dmaconr
= custom
->dmaconr
;
724 dmaconr
= custom
->dmaconr
;
725 if (dmaconr
& 0x4000) {
726 /* Blitter still active? Wait for next interrupt. */
730 if (GfxBase
->blthd
== NULL
&& GfxBase
->bsblthd
== NULL
) {
731 custom
->intena
= INTF_BLIT
;
735 /* Was last blit in this node? */
736 if (bqvar
& BQ_NEXT
) {
737 bqvar
&= ~(BQ_NEXT
| BQ_MISSED
);
738 if (bqvar
& BQ_BEAMSYNC
)
739 bn
= GfxBase
->bsblthd
;
742 if (bn
->stat
== CLEANUP
)
743 AROS_UFC2(UBYTE
, bn
->cleanup
,
744 AROS_UFCA(struct Custom
*, custom
, A0
),
745 AROS_UFCA(struct bltnode
*, bn
, A1
));
748 if (bqvar
& BQ_BEAMSYNC
)
749 GfxBase
->bsblthd
= bn
;
754 if (GfxBase
->bsblthd
) {
755 bn
= GfxBase
->bsblthd
;
756 bqvar
|= BQ_BEAMSYNC
;
757 } else if (GfxBase
->blthd
) {
759 bqvar
&= ~BQ_BEAMSYNC
;
763 /* Last blit finished */
765 custom
->intena
= INTF_BLIT
;
766 GfxBase
->blthd
= GfxBase
->bsblthd
= NULL
;
771 if (bqvar
& BQ_BEAMSYNC
) {
772 UWORD vpos
= VBeamPos();
773 bqvar
&= ~BQ_BEAMSYNCWAITING
;
774 if (!(bqvar
& BQ_MISSED
) && bn
->beamsync
> vpos
) {
775 volatile struct CIA
*ciab
= (struct CIA
*)0xbfd000;
776 UWORD w
= BEAMSYNC_ALARM
- (bn
->beamsync
- vpos
);
777 bqvar
|= BQ_BEAMSYNCWAITING
;
778 ciab
->ciacrb
&= ~0x80;
780 ciab
->ciatodmid
= w
>> 8;
786 v
= AROS_UFC2(UBYTE
, bltnode_wrapper
,
787 AROS_UFCA(struct Custom
*, custom
, A0
),
788 AROS_UFCA(struct bltnode
*, bn
, A1
));
790 dmaconr
= custom
->dmaconr
;
791 dmaconr
= custom
->dmaconr
;
792 if (!(dmaconr
& 0x4000)) {
793 /* Eh? Blitter not active?, better fake the interrupt. */
794 custom
->intreq
= INTF_SETCLR
| INTF_BLIT
;
798 /* Handle same node again next time */
809 static AROS_INTH1(gfx_beamsync
, struct amigavideo_staticdata
*, data
)
813 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
815 if (bqvar
& BQ_BEAMSYNCWAITING
) {
816 /* We only need to trigger blitter interrupt */
817 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
818 custom
->intreq
= INTF_SETCLR
| INTF_BLIT
;
826 static AROS_INTH1(gfx_vblank
, struct amigavideo_staticdata
*, data
)
830 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
831 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
832 BOOL lof
= (custom
->vposr
& 0x8000) != 0;
834 if (data
->interlace
) {
835 custom
->cop2lc
= (ULONG
)(lof
? GfxBase
->LOFlist
: GfxBase
->SHFlist
);
837 custom
->cop2lc
= (ULONG
)GfxBase
->LOFlist
;
838 /* We may be in SHF mode after switching interlace off. Fix it here. */
840 custom
->vposw
= custom
->vposr
| 0x8000;
843 data
->framecounter
++;
845 UWORD
*p
= data
->sprite
;
846 p
[0] = data
->spritepos
;
847 p
[1 << data
->fmode_spr
] = data
->spritectl
;
850 if (data
->updatescroll
) {
851 setcopperscroll(data
, data
->updatescroll
);
852 data
->updatescroll
= NULL
;
855 if (bqvar
& BQ_BEAMSYNC
)
863 void initcustom(struct amigavideo_staticdata
*data
)
868 struct GfxBase
*GfxBase
;
869 struct Library
*OOPBase
;
870 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
871 volatile struct CIA
*ciab
= (struct CIA
*)0xbfd000;
873 /* Reset audio registers to values that help emulation
874 * if some program enables audio DMA without setting period
875 * or length. Very high period emulation is very CPU intensive.
877 for (i
= 0; i
< 4; i
++) {
878 custom
->aud
[i
].ac_vol
= 0;
879 custom
->aud
[i
].ac_per
= 100;
880 custom
->aud
[i
].ac_len
= 1000;
886 /* data->cs_OOPBase was already set up.
887 * See amigavideo.conf's 'oopbase_field' config
889 OOPBase
= data
->cs_OOPBase
;
890 data
->cs_HiddBitMapBase
= OOP_GetMethodID(IID_Hidd_BitMap
, 0);
891 data
->cs_HiddGfxBase
= OOP_GetMethodID(IID_Hidd_Gfx
, 0);
893 data
->cs_UtilityBase
= TaggedOpenLibrary(TAGGEDOPEN_UTILITY
);
894 if (!data
->cs_UtilityBase
)
895 Alert(AT_DeadEnd
| AN_Hidd
| AG_OpenLib
| AO_UtilityLib
);
896 data
->cs_GfxBase
= TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
897 if (!data
->cs_GfxBase
)
898 Alert(AT_DeadEnd
| AN_Hidd
| AG_OpenLib
| AO_GraphicsLib
);
899 GfxBase
= ((struct GfxBase
*)data
->cs_GfxBase
);
900 GfxBase
->cia
= OpenResource("ciab.resource");
902 data
->inter
.is_Code
= (APTR
)gfx_vblank
;
903 data
->inter
.is_Data
= data
;
904 data
->inter
.is_Node
.ln_Name
= "GFX VBlank server";
905 data
->inter
.is_Node
.ln_Pri
= 25;
906 data
->inter
.is_Node
.ln_Type
= NT_INTERRUPT
;
907 AddIntServer(INTB_VERTB
, &data
->inter
);
909 /* There are programs that take over the system and
910 * assume SysBase->IntVects[BLITTER].iv_Data = GfxBase!
912 GfxBase
->bltsrv
.is_Code
= (APTR
)gfx_blit
;
913 GfxBase
->bltsrv
.is_Data
= GfxBase
;
914 GfxBase
->bltsrv
.is_Node
.ln_Name
= "Blitter";
915 GfxBase
->bltsrv
.is_Node
.ln_Type
= NT_INTERRUPT
;
916 SetIntVector(INTB_BLIT
, &GfxBase
->bltsrv
);
917 custom
->intena
= INTF_BLIT
;
919 // CIA-B TOD counts scanlines */
920 GfxBase
->timsrv
.is_Code
= (APTR
)gfx_beamsync
;
921 GfxBase
->timsrv
.is_Data
= data
;
922 GfxBase
->timsrv
.is_Node
.ln_Name
= "Beamsync";
923 GfxBase
->timsrv
.is_Node
.ln_Type
= NT_INTERRUPT
;
925 AddICRVector(GfxBase
->cia
, 2, &GfxBase
->timsrv
);
926 AbleICR(GfxBase
->cia
, 1 << 2);
927 ciab
->ciacrb
|= 0x80;
929 /* TOD/ALARM CIA bug: http://eab.abime.net/showpost.php?p=277315&postcount=10 */
930 ciab
->ciatodmid
= BEAMSYNC_ALARM
>> 8;
931 ciab
->ciatodlow
= BEAMSYNC_ALARM
& 0xff;
932 ciab
->ciacrb
&= ~0x80;
936 AbleICR(GfxBase
->cia
, 0x80 | (1 << 2));
939 GfxBase
->NormalDisplayColumns
= 640;
940 GfxBase
->NormalDisplayRows
= (GfxBase
->DisplayFlags
& NTSC
) ? 200 : 256;
941 GfxBase
->MaxDisplayColumn
= 640;
942 GfxBase
->MaxDisplayRow
= (GfxBase
->DisplayFlags
& NTSC
) ? 200 : 256;
947 vposr
= custom
->vposr
& 0x7f00;
948 data
->aga
= vposr
>= 0x2200;
949 data
->ecs_agnus
= vposr
>= 0x2000;
950 val
= custom
->deniseid
;
951 custom
->deniseid
= custom
->dmaconr
;;
952 if (val
== custom
->deniseid
) {
953 custom
->deniseid
= custom
->dmaconr
^ 0x8000;
954 if (val
== custom
->deniseid
) {
955 if ((val
& (2 + 8)) == 8)
956 data
->ecs_denise
= TRUE
;
959 data
->max_colors
= data
->aga
? 256 : 32;
960 data
->palette
= AllocVec(data
->max_colors
* 3, MEMF_CLEAR
);
961 data
->copper1
= AllocVec(22 * 2 * sizeof(WORD
), MEMF_CLEAR
| MEMF_CHIP
);
962 data
->sprite_null
= AllocMem(2 * 8, MEMF_CLEAR
| MEMF_CHIP
);
963 data
->sprite_res
= 0; /* lores */
965 for (i
= 0; i
< 8; i
++) {
966 *c
++ = 0x0120 + i
* 4;
968 data
->copper1_spritept
= c
;
969 *c
++ = (UWORD
)(((ULONG
)data
->sprite_null
) >> 16);
970 *c
++ = 0x0122 + i
* 4;
971 *c
++ = (UWORD
)(((ULONG
)data
->sprite_null
) >> 0);
977 data
->copper2_backup
= c
;
980 custom
->cop1lc
= (ULONG
)data
->copper1
;
981 custom
->cop2lc
= (ULONG
)data
->copper2_backup
;
982 custom
->dmacon
= 0x8000 | 0x0080 | 0x0040 | 0x0020;
984 GfxBase
->copinit
= (struct copinit
*)data
->copper1
;
986 D(bug("Copperlist0 %p\n", data
->copper1
));