Welcome, Guest. Please login or register.

Author Topic: Big restriction in AmigaOS for UserCopper lists ?  (Read 3619 times)

Description:

0 Members and 1 Guest are viewing this topic.

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Big restriction in AmigaOS for UserCopper lists ?
« on: November 15, 2004, 06:54:06 PM »
Hi. I tried to compile the example in the RKM libraries to see if it looked how I expected it. After one or two error corrections (VBCC seems to be more types resctrict than SAS) it worked et voila... Then  decided to change it a bit to push the Copper resolution to the maximum (4HirRes pixels if I remember correctly, and eventhough that was for ECS, AGA's the same I think...). I made it change various successive pixels to see the result. You know what ? It was visisble on the screen that for color change it took more than eight lowres pixels (probably 16 HiRes ones or more :-o  :-o  :-x ) .

My question is, is this an AmigaOS restriction on Copper lists?
Is there any way of achieving the maximum resolution without banging directly the hardware?  :-(

Bellow is on of the the example versions (just modified the WAIT instruction values, and the colors used to make them more different from one another, so that I can see how many pixels it takes to change between them):

Code: [Select]
/*  The example program below shows the use of user Copper lists
    under Intuition.

    UserCopperExample.c
    User Copper List Example
    For SAS/C 5.10a,
    compile with:  LC -b1 -cfist -L -v -y UserCopperExample.c
    link with lc.lib and amiga.lib
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <graphics/gfxmacros.h>
#include <graphics/copper.h>
#include <graphics/videocontrol.h>
#include <intuition/intuition.h>
#include <intuition/preferences.h>
#include <hardware/custom.h>
#include <libraries/dos.h>

#include <clib/exec_protos.h>           /*  Prototypes.  */
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>

#include <stdlib.h>

/*  Use this structure to gain access to the custom registers.  */
extern struct Custom far, custom;

/*  Global variables.  */
struct GfxBase        *GfxBase = NULL;
struct IntuitionBase  *IntuitionBase = NULL;
struct Screen         *screen = NULL;
struct Window         *window = NULL;

int main( VOID ), cleanExit( WORD );
WORD openAll( VOID ), loadCopper( VOID );


/*
 *   The main() routine -- just calls subroutines
 */
int main( VOID )
{
WORD ret_val;
struct IntuiMessage     *intuiMessage;

        /*  Open the libraries, a screen and a window.  */
        ret_val = openAll();
        if (RETURN_OK == ret_val)
        {
                /*  Create and attach the user Copper list.  */
                ret_val = loadCopper();
                if (RETURN_OK == ret_val)
                {
                        /*  Wait until the user clicks in the close gadget.  */
                        (VOID) Wait(1<<window->UserPort->mp_SigBit);

                        while (intuiMessage = (struct IntuiMessage *)GetMsg(window->UserPort))
                                ReplyMsg((struct Message *)intuiMessage);
                }
        }
        cleanExit(ret_val);
}


/*
 * openAll() -- opens the libraries, screen and window
 */
WORD openAll( VOID )
{
#define MY_WA_WIDTH 270 /*  Width of window.  */

        WORD ret_val = RETURN_OK;

        /*  Prepare to explicitly request Topaz 60 as the screen font.  */
        struct TextAttr topaz60 =
        {
                (STRPTR)&quot;topaz.font&quot;,
                (UWORD)TOPAZ_SIXTY, (UBYTE)0, (UBYTE)0
        };

        GfxBase = (struct GfxBase *)OpenLibrary(&quot;graphics.library&quot;, 37L);
        if (GfxBase == NULL)
                ret_val = ERROR_INVALID_RESIDENT_LIBRARY;
        else
        {
                IntuitionBase = (struct IntuitionBase *)
                        OpenLibrary(&quot;intuition.library&quot;, 37L);

                if (IntuitionBase == NULL)
                        ret_val = ERROR_INVALID_RESIDENT_LIBRARY;
                else
                {
                        screen = OpenScreenTags( NULL,
                                 SA_Overscan, OSCAN_STANDARD,
                                 SA_Title,    &quot;User Copper List Example&quot;,
                                 SA_Font,     (ULONG)&topaz60,
                                 TAG_DONE);

                        if (NULL == screen)
                                ret_val = ERROR_NO_FREE_STORE;
                        else
                        {
                                window = OpenWindowTags( NULL,
                                         WA_CustomScreen, screen,
                                         WA_Title,        &quot;<- Click here to quit.&quot;,
                                         WA_IDCMP,        CLOSEWINDOW,
                                         WA_Flags,        WINDOWDRAG|WINDOWCLOSE|INACTIVEWINDOW,
                                         WA_Left,         (screen->Width-MY_WA_WIDTH)/2,
                                         WA_Top,          screen->Height/2,
                                         WA_Height,       screen->Font->ta_YSize + 3,
                                         WA_Width,        MY_WA_WIDTH,
                                         TAG_DONE);

                                if (NULL == window)
                                        ret_val = ERROR_NO_FREE_STORE;
                        }
                }
        }

        return(ret_val);
}


/*
 * loadCopper() -- creates a Copper list program and adds it to the system
 */
WORD loadCopper( VOID )
{
register USHORT   i, scanlines_per_color;
         WORD     ret_val    = RETURN_OK;
struct   ViewPort *viewPort;
struct   UCopList *uCopList  = NULL;
struct   TagItem  uCopTags[] =
          {
               (LONG)VTAG_USERCLIP_SET, (LONG)NULL,
               (LONG)VTAG_END_CM,(LONG) NULL
          };

UWORD    spectrum[] =
          {
                0x0000, 0x0705, 0x1006, 0x1006, 0x1006, 0x1006, 0x1006,
                0x0000, 0x0612, 0x0613, 0x0614, 0x0615, 0x0616, 0x0617,
                0x0000, 0x0619, 0x0620, 0x0621, 0x0622, 0x0623, 0x0624,
                0x0000, 0x0626, 0x0627, 0x0628, 0x0629, 0x0630, 0x0631,
                0x0000, 0x0633, 0x0734, 0x0835
          };

#define NUMCOLORS 4

        /*  Allocate memory for the Copper list.  */
        /*  Make certain that the initial memory is cleared.  */
        uCopList = (struct UCopList *)
                AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR);

        if (NULL == uCopList)
                ret_val = ERROR_NO_FREE_STORE;
        else
        {
                /*  Initialize the Copper list buffer.  */
                CINIT(uCopList, NUMCOLORS);

                scanlines_per_color = screen->Height/NUMCOLORS;

                /*  Load in each color.  */
                for (i=1; i<NUMCOLORS; i++)
                        {
                        CWAIT(uCopList, 100,(((BYTE)(100+i))));
                        CMOVE(uCopList, custom.color[0], spectrum[i]);
                        }

                CEND(uCopList); /*  End the Copper list  */

                viewPort = ViewPortAddress(window);     /*  Get a pointer to the ViewPort.  */
                Forbid();       /*  Forbid task switching while changing the Copper list.  */
                viewPort->UCopIns=uCopList;
                Permit();       /*  Permit task switching again.  */

                /*  Enable user copper list clipping for this ViewPort.  */
                (VOID) VideoControl( viewPort->ColorMap, uCopTags );

                RethinkDisplay();       /*  Display the new Copper list.  */

                return(ret_val);
        }
}


/*
 *  cleanExit() -- returns all resources that were used.
 */
VOID cleanExit( WORD retval )
{
struct ViewPort *viewPort;

if (NULL != IntuitionBase)
{
        if (NULL != screen)
        {
                if (NULL != window)
                {
                        viewPort = ViewPortAddress(window);
                        if (NULL != viewPort->UCopIns)
                        {
                                /*  Free the memory allocated for the Copper.  */
                                FreeVPortCopLists(viewPort);
                                RemakeDisplay();
                        }
                        CloseWindow(window);
                }
                CloseScreen(screen);
        }
        CloseLibrary((struct Library *)IntuitionBase);
}

if (NULL != GfxBase)
        CloseLibrary((struct Library *)GfxBase);

exit((int)retval);
}

\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Re: Big restriction in AmigaOS for UserCopper lists ?
« Reply #1 on: November 19, 2004, 06:11:31 PM »
Hey all :-)

"Also, this merging might explain why there are additional limitations to what you can do in the user copper list.
"
Don't system copper lists only make changes between viewports to change resolution and color registers etc. ? If so, at least i the middle of a Viewport there shouldn't be any restrictions.

One thing I remembered is that the example above uses macros. Maybe there are limitations on those macros  :-?


@Samurai

Ok, taking off those WAIT instructions will improved it but since copper DMA Chip ram access is conditioned by DMA priorities and competes with other stuff how's one supposed to know where the changes end up occurig?

By the way, there are some programs that claim to manage more than 100 chages per line with just ECS

Hmm AGA can make 320 changes at 12 bit? That would be just great but the results I got with the above example were on a AGA machine  :-(


By the way, I was planning to use this on a little proggies I had planned...
I'm gonna check this out more a bit, I was hopping someone would spare me that hard work   8-)
\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Re: Big restriction in AmigaOS for UserCopper lists ?
« Reply #2 on: November 21, 2004, 12:28:37 PM »
@lordv

Was that on AGA ? How many bitplanes?

I guess it's not worth to try to bang the hardware myself then if the results are the same

Question, why do some programs claim to make more than 100 changes per line then?

By the way, like Thomas said, the hardware manual mentions 4 horizontal pixels, or 8, for lo and hires screens respectively.

I've read the Hardware manual's part on the copper but it was more than 1 year ago and these macros and gfx library stuff is easy to use that's the reason I prefer it this way. I think using the macros and gfx.library functions it's quicker to do it, but if I have to bang the hardware so be it :-D

\\"We made Amiga, they {bleep}ed it up\\"
 

Offline JoseTopic starter

  • Hero Member
  • *****
  • Join Date: Feb 2002
  • Posts: 2871
    • Show all replies
Re: Big restriction in AmigaOS for UserCopper lists ?
« Reply #3 on: November 21, 2004, 01:16:58 PM »
Just to make it clear here's the stuff I think is relevant from the hardware manual:

"...The horizontal beam position has a value of $0 to $E2. The least signifieant bit is not used in the comparison, so there are 113 positions available for Copper operations. This corresponds to 4 pixels in low resolution and 8 pixels in high resolution. ..."

"... All Copper instructions consist of two 16-bit words in sequential memory locations. Each time the Copper fetches an instruction, it fetches both words. The MOVE and SKIP instructions require two memory cycles and two instruction words. Because only the odd memory cycles are requested by
the Copper, four memory cycle times are required per instruction. The WAIT instruction requires three memory cycles and six memory cycle times; it takes one extra memory cycle to wake up."

They don't specify if it's 4 cycles to fetch the data or for the instruction to execute, reading it it seems one memory cycle to fetch (because it fetches both WORDS) and one to execute, but probably it's 4 cycles to fetch, 4 to execute, wich results in 8 pixels between instructions.. :-(
\\"We made Amiga, they {bleep}ed it up\\"